温湿度センサー DHT11 (1-Wire接続)
ビギナーキットなどに同梱されているメジャーな温湿度センサープルアップ抵抗がセットされたユニット
センサー単体でも1個300円なので(プルアップ抵抗なし)なので妥当な価格
データの読み取りは単線バス(双方向)を通して行います。
アドレスのない1-Wire接続のようです。
※1-Wireは商標登録されているらしいてす、なので、1-Wire接続ではなく 単線バスだそうです。
データの通信手順(プロトコル)
以下の手順で通信を行います■通信の開始
ホスト側から:18m秒間LOW信号を出力
■通信開始の応答
デバイス側から:80μ秒LOW - 80μ秒HIGH
■データ:'0'
デバイス側から;50μ秒LOW-28μ秒HIGH
■データ'1'
デバイス側から:50μ秒LOW-70μ秒HIGH
■ デバイスから送信されるデータ
下記表の順番に40Bit(5Byte)が送信される
内容 | 範囲 | 長さ |
---|---|---|
湿度の整数部 | 20~95 | 8Bit(1Byte) |
湿度の小数部 | 常に0 | 8Bit(1Byte) |
温度の整数部 | 0~50 | 8Bit(1Byte) |
温度の小数部 | 0~9 | 8Bit(1Byte) |
Check SUM | 0x00~0xFF | 8Bit(1Byte) |
データの受信方法
■ 内蔵のPULL-UP抵抗を有効にするpinMode(DATAPIN, INPUT_PULLUP);
■ データ送信要求 を送信して 入力がLOWになるのを待つ
pinMode(DATAPIN, OUTPUT); //開始信号
delay(20); // ※18m秒以上なので、念のため(?)20m秒待つ
pinMode(DATAPIN, INPUT); // 入力に切り替え
while(digitalRead(DATAPIN) == LOW) { // 入力値がLOWになるまで待つ
delayMicroseconds(5) ;
}
■ 外部割込みを使用してデータを受信する方法
※ ArduinoUNO用 : DHT11の信号ピンはArduinoUNOの2番ピンに接続する
DHT11-INTERRUPT.zip
■ 入力値が変化するまでdigitalRead()を繰り返す:ポーリング処理
※DHT11の信号ピンは何処につないでも良い
DHT11-LOOP.zip
※ <>を全角<>に置き換えています。コピペの際は注意してください。
// 温湿度センサー DHT11 アクセステスト
// 全力でループするバージョン
#define BAUDRATE 9600
#define DATAPIN 2 // コレは何番ピンでも良い
char str[120] ;
// ----- Senser Data
struct dht11_s {
int8_t humidityN ; // 湿度の整数部
int8_t humidityD ; // 湿度の小数部 ※は常に0
int8_t temperatureN; // 温度の整数部
int8_t temperatureD; // 温度の小数部
} dht11 ;
bool readDTH11( ) {
uint8_t readData[5] ;
uint8_t checkSum = 0 ;
int setPos = 0 ;
int bitLen = 0 ;
int stat = HIGH ;
uint8_t bitData ;
unsigned long beginTime ;
unsigned long passTime ;
unsigned long zeroTime = 35 ; // 35μ秒以下なら0 以上なら1と判定 ※仕様では0は26~28μ秒
bool flagStart = false;
for (int i=0;i<5;i++) {
readData[i] = 0 ;
}
// ----- データ送信要求 -----
pinMode(DATAPIN, OUTPUT); //開始信号
delay(20);
pinMode(DATAPIN, INPUT);
while(digitalRead(DATAPIN) == LOW) {
delayMicroseconds(5) ;
}
// ----- ACSEPT -----
flagStart = false;
passTime = 0 ;
beginTime = micros();
while (passTime < 1000) {
passTime = micros() - beginTime ;
if (digitalRead(DATAPIN) != stat) {
if (stat == HIGH) {
stat = LOW ;
if (flagStart) {
break ;
}
} else {
beginTime = micros();
flagStart = true ;
stat = HIGH ;
}
}
}
// ----- データ受信 -----
bitData = 0x80 ;
flagStart = false;
passTime = 0 ;
beginTime = micros();
while (bitLen < 40 && passTime < 1000) {
passTime = micros() - beginTime ;
if (digitalRead(DATAPIN) != stat) {
if (stat == HIGH) {
stat = LOW ;
if (flagStart) {
// ----- 1Bit 受信 -----
if (passTime > zeroTime) {
readData[setPos] |= bitData ;
}
if (bitData != 0x01) {
bitData >>= 1 ;
} else {
bitData = 0x80 ;
setPos ++ ;
}
// ----- ステート変数リセット -----
beginTime = micros();
flagStart = false;
bitLen ++ ;
}
} else {
beginTime = micros();
flagStart = true ;
stat = HIGH ;
}
}
}
// ----- 取得データ格納 -----
dht11.humidityN = readData[0] ; // 湿度の整数部 Range:5~95
dht11.humidityD = readData[1] ; // 湿度の小数部 ※は常に0
dht11.temperatureN = readData[2]; // 温度の整数部 -20 ~
dht11.temperatureD = readData[3]; // 温度の小数部
checkSum = readData[0] + readData[1] + readData[2] + readData[3] ;
return (bitLen == 40 && checkSum == readData[4]) ;
}
void setup() {
Serial.begin(BAUDRATE);
Serial.println("\nDHT11 - Read") ;
pinMode(DATAPIN, INPUT_PULLUP);
}
void loop() {
if (readDTH11( )) {
sprintf(str,"気温:%2d.%d℃ 湿度:%2d%%", dht11.temperatureN ,dht11.temperatureD,dht11.humidityN ) ;
Serial.println(str) ;
}
delay(3000) ;
}
参考動画
参考動画で使用している温湿度計デモの配線図とスケッチDHT11のプルアップ抵抗は4.7KΩを使用。※PULL-UP抵抗付きのユニットを使用する場合には不要
ディスプレイはOLED SSD1306 または OLED SSD1315 を使用してください。(どちらでも動作します)
タグスイッチは7セグメントっぽい表示とグラフ表示の切り替え用、なくても構いません。
タグスイッチの抵抗は適当で、10KΩ位を推奨
※ Arduino用とRaspberriPi Pico用は別のスケッチ
※ メモリー容量の都合で、ArduinoではフォントをFLASHメモリーに配置しているだけで、ロジックは同じです。
DHT11-DEMO.zip :Arduino用
DHT11-DEMO-Pico.zip : RaspberryPi Pico用 ※mbedのボードライブラリを想定しています