環境: Windows 10 Iot Core, Arduino UNO, Visual Studio 2015
在Windows 10 IoT Core 的範例,可以讀取到 DHT11 的溫濕度資訊,但是它是 C++ 的範例。
本文依 Arduino I2C communication with Raspi 2 WIOT 這篇來修改實作的,
再透過 I2C 傳給 Raspberry 來接收資訊。如下圖,
本文依 Arduino I2C communication with Raspi 2 WIOT 這篇來修改實作的,
而 Arduino 的 DHT 程式庫可以從 Github Arduino/libraries/DHTlib/ Download,
請在 C:\Users\user\Documents\Arduino\libraries 目錄下建立 DHT 的目錄,
並將 dht.cpp 及 dht.h 放在該目錄中。
啟動 Arduino IDE 後,就可以使用 DHT 的程式庫了,如下,
加入 DHT 程式庫後,就可以呼叫它來取得 溫濕度資訊 。
因為要將資料透過 I2C 傳給 Raspberry 所以要引用 Wire 程式庫及定位 Address 為 0x40,
程式可以參考 Github 的 chrisfaig/Windows-IOT-i2C-Arduino
在 Arduino I2C communication with Raspi 2 WIOT 這篇只傳 溫度,
但我想要傳送溫濕度,所以我就模仿 Home Automation using Raspberry Pi 2 and Windows 10 IoT 這篇。
將這些資料分別放在傳送的 Byte Array之中,
Byte 0 表示溫度是否為負, Byte 1 表示溫度, Byte 2 表示濕度,(當然,這樣數值就只到整數位)
Arduino 程式如下,
#include <Wire.h>
#define SLAVE_ADDRESS 0x40 // Define the i2c address
#include <dht.h>
dht DHT;
#define DHT_PIN 4
byte sendInfo[3];
void setup(){
Serial.begin(9600);
Wire.begin(SLAVE_ADDRESS);
}
void loop(){
// read data
int chk = DHT.read22(DHT_PIN);
switch(chk){
case DHTLIB_OK:
Serial.print("OK,\t");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.print("Checksum error,\t");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.print("Time out error,\t");
break;
case DHTLIB_ERROR_CONNECT:
Serial.print("Connect error,\t");
break;
case DHTLIB_ERROR_ACK_L:
Serial.print("Ack Low error,\t");
break;
case DHTLIB_ERROR_ACK_H:
Serial.print("Ack High error,\t");
break;
default:
Serial.print("Unknown error,\t");
break;
}
Serial.print("temperature,:");
Serial.print(DHT.temperature);
Serial.print(",humidity:");
Serial.println(DHT.humidity);
Wire.onRequest(sendData);
delay(1000);
}
void sendData(){
sendInfo[0] = (byte)((DHT.temperature < 0) ? 1 : 0);
sendInfo[1] = (byte)((DHT.temperature < 0) ? (DHT.temperature*(-1)) : DHT.temperature);
sendInfo[2] = (byte)(DHT.humidity);
Wire.write(sendInfo, 3);
}
執行的畫面如下,
而在 Raspberry 上的 UWP 程式,我簡單在 MainPage 上拉了2個 TextBlock,分別來呈現 溫度及濕度,如下,
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="temperature" Text="temperature" Margin="0,20,0,0" />
<TextBlock x:Name="humidity" Text="humidity" Margin="0,40,0,0" />
</Grid>
而在程式中,要加入 Windows IoT Extensions for the UWP 參考,
然後在 MainPage.xaml.cs 就可以開始透過 I2C 跟 Arduino 要資料,如下,
private I2cDevice _device;
private Timer _periodTimer;
public MainPage()
{
this.InitializeComponent();
//初始設定
initCommuication();
}
private async void initCommuication()
{
// Arduino address SLAVE_ADDRESS
var settings = new I2cConnectionSettings(0x40);
settings.BusSpeed = I2cBusSpeed.StandardMode;
string aqs = I2cDevice.GetDeviceSelector("I2C1");
var dis = await DeviceInformation.FindAllAsync(aqs);
if(dis.Count > 0)
{
_device = await I2cDevice.FromIdAsync(dis[0].Id, settings);
_periodTimer = new Timer(this.TimerCallback, null, 0, 1000);
}
else
{
temperature.Text = humidity.Text = "找不到設備...";
}
}
private async void TimerCallback(object state)
{
byte[] readBuffer = new byte[3];
try
{
_device.Read(readBuffer);
byte flag = readBuffer[0];
byte t = readBuffer[1];
byte h = readBuffer[2];
string temperatureValue = (readBuffer[0] == 0)? t.ToString() : (t*(-1)).ToString();
string humidityValue = h.ToString(); //new string(humidityArray);
Debug.WriteLine($"{temperatureValue}:{humidityValue}");
//update screen
var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{ temperature.Text = string.Format($"Temperature:{temperatureValue} \u00B0C");
humidity.Text = string.Format($"Humidity:{humidityValue}% RH"); });
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
執行畫面如下,
一切都打通後,再來就可以將資料送到 Azure IoT Hub 上面了。
參考資料
DHT11 /DHT22 Temperature Sensor
Arduino I2C communication with Raspi 2 WIOT
chrisfaig/Windows-IOT-i2C-Arduino
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^