「Arduino Mega 2560 LESSON:12 DHT11 温度湿度センサー」の版間の差分

提供:yonewiki
編集の要約なし
編集の要約なし
224行目: 224行目:
   interrupts();
   interrupts();
   for(byte i = 0; i < 40; i++){
   for(byte i = 0; i < 40; i++){
  Serial.print(" ");
    Serial.print(" ");
  Serial.print(countlow[i]);
    Serial.print(countlow[i]);
   }
   }
   Serial.println(" ");
   Serial.println(" ");
   for(byte i = 0; i < 40; i++){
   for(byte i = 0; i < 40; i++){
  Serial.print(" ");
    Serial.print(" ");
  Serial.print(counthigh[i]);
    Serial.print(counthigh[i]);
   }
   }
   Serial.println(" ");
   Serial.println(" ");
314行目: 314行目:
  Sample RAW Bits: 00101111 00000000 00011100 00000011 01001110
  Sample RAW Bits: 00101111 00000000 00011100 00000011 01001110
  Sample OK: 28.3 deg. C, 47 %
  Sample OK: 28.3 deg. C, 47 %
 ビット列は8ビットずつ、湿度、湿度補助、温度、温度補助、チェックサムになっています。チェックサムは47+0+28+3=78という計算です。





2026年10月17日 (土) 00:42時点における版

Arduino Mega 2560に戻る。

概要

 DHT11 温度湿度センサーを接続するレッスンです。


AIによるタイミングチャート作図です。

DHT11通信タイミングチャート


 以下のようなコードです。

//www.elegoo.com
//2018.10.25

#include <dht_nonblocking.h>
#define DHT_SENSOR_TYPE DHT_TYPE_11

static const int DHT_SENSOR_PIN = 2;
DHT_nonblocking dht_sensor( DHT_SENSOR_PIN, DHT_SENSOR_TYPE );

/*
 * Initialize the serial port.
 */
void setup( )
{
  Serial.begin( 9600);
}

/*
 * Poll for a measurement, keeping the state machine alive.  Returns
 * true if a measurement is available.
 */
static bool measure_environment( float *temperature, float *humidity )
{
  static unsigned long measurement_timestamp = millis( );

  /* Measure once every four seconds. */
  if( millis( ) - measurement_timestamp > 3000ul )
  {
    if( dht_sensor.measure( temperature, humidity ) == true )
    {
      dht_sensor.print_raw_data();
      measurement_timestamp = millis( );
      return( true );
    }
  }

  return( false );
}

/*
 * Main program loop.
 */
void loop( )
{
  float temperature;
  float humidity;

  /* Measure temperature and humidity.  If the functions returns
     true, then a measurement is available. */
  if( measure_environment( &temperature, &humidity ) == true )
  {
    Serial.print( "T = " );
    Serial.print( temperature, 1 );
    Serial.print( " deg. C, H = " );
    Serial.print( humidity, 1 );
    Serial.println( "%" );
    
  }
}


 ライブラリを使わないで自分なりのコードにすると以下のようになりました。カウント部のデバッグ値も出力しています。

const byte DHT_PIN = 2;

void setup() {
  Serial.begin(9600);

  // 待機状態(プルアップ)
  pinMode(DHT_PIN, INPUT_PULLUP);

  delay(1000);
}

void loop() {
    byte data[5] = {0};

    bool success = true;
    int errorBit = -1;
    int errorStep = 0;

    byte countlow[40] = {0};
    byte counthigh[40] = {0};

    // ここから通信開始処理
  // ① Arduinoから通信開始信号を送信
  pinMode(DHT_PIN, OUTPUT);
  digitalWrite(DHT_PIN, LOW);
  delay(20);  // 20ms LOW

  // 開始信号のLOWを終了
  pinMode(DHT_PIN, INPUT_PULLUP);

  // センサーが応答を始めるまでの待ち時間
  delayMicroseconds(30);

  // 応答開始:LOWになるのを待つ
  if (!waitForLevel(LOW, 200)) {
    Serial.println("Error: No response");
    delay(3000);
    return;
  }

  // 応答LOW(約80us)の終了を待つ
  if (!waitForLevel(HIGH, 200)) {
    Serial.println("Error: Response LOW");
    delay(3000);
    return;
  }

  // 応答HIGH(約80us)の終了を待つ
  if (!waitForLevel(LOW, 200)) {
    Serial.println("Error: Response HIGH");
    delay(3000);
    return;
  }

  // ③ 40ビットを読み取る
  noInterrupts();

  for (int i = 0; i < 40; i++) {
    // LOWが続いた回数を数える
    unsigned int lowCount = countPulse(LOW);
    countlow[i] = lowCount;
    // HIGHが続いた回数を数える
    unsigned int highCount = countPulse(HIGH);
    counthigh[i] = highCount;
    if (lowCount == 0 || highCount == 0) {
      success = false;
      errorBit = i;
      errorStep = (lowCount == 0) ? 1 : 2;
      break;
    }

    // 受信データを左へ1ビットずらす
    data[i / 8] <<= 1;

    // HIGHの方が長ければ1
    if (highCount > lowCount) {
      data[i / 8] |= 1;
    }
  }
  
  interrupts();
  for(byte i = 0; i < 40; i++){
    Serial.print(" ");
    Serial.print(countlow[i]);
  }
  Serial.println(" ");
  for(byte i = 0; i < 40; i++){
    Serial.print(" ");
    Serial.print(counthigh[i]);
  }
  Serial.println(" ");

  if (!success) {
    Serial.print("Error: Reading failed, Bit=");
    Serial.print(errorBit);
    Serial.print(", Step=");
    Serial.println(errorStep);

    delay(3000);
    return;
  }

  // ④ 受信した40ビットを表示
  Serial.print("Sample RAW Bits: ");

  for (int i = 0; i < 5; i++) {
    for (int bit = 7; bit >= 0; bit--) {
      Serial.print((data[i] >> bit) & 1);
    }

    if (i < 4) {
      Serial.print(" ");
    }
  }

  Serial.println();

  // ⑤ チェックサムを検証
  byte checksum = data[0] + data[1] + data[2] + data[3];

  if (checksum == data[4]) {
    Serial.print("Sample OK: ");
    Serial.print(data[2]);
    Serial.print(".");
    Serial.print(data[3]);
    Serial.print(" deg. C, ");
    Serial.print(data[0]);
    Serial.println(" %");
  } else {
    Serial.println("Checksum Error");
  }

  delay(3000);
}


// 指定した電圧状態になるまで待つ
// timeout はマイクロ秒単位
bool waitForLevel(byte level, unsigned long timeout) {
  unsigned long start = micros();

  while (digitalRead(DHT_PIN) != level) {
    if (micros() - start >= timeout) {
      return false;
    }
  }

  return true;
}

unsigned int countPulse(byte level) {
  unsigned int count = 0;

  while (digitalRead(DHT_PIN) == level) {
    count++;

    if (count >= 1000) {
      return 0;
    }
  }

  return count;
}


              47/              0/             28/              3/             78 
 0 0 1 0 1 1 1 1/0 0 0 0 0 0 0 0/0 0 0 1 1 1 0 0/0 0 0 0 0 0 1 1/0 1 0 0 1 1 1 0
 7 7 7 6 6 7 6 7 6 6 6 7 7 6 6 6 6 6 7 7 6 7 6 6 6 7 7 6 6 6 6 7 6 6 7 6 6 7 6 7 
 2 2 9 3 9 9 9 9 3 3 2 2 2 3 3 3 3 2 2 9 9 9 3 3 2 2 2 3 3 3 9 9 3 9 2 3 9 9 9 2 
Sample RAW Bits: 00101111 00000000 00011100 00000011 01001110
Sample OK: 28.3 deg. C, 47 %


 ビット列は8ビットずつ、湿度、湿度補助、温度、温度補助、チェックサムになっています。チェックサムは47+0+28+3=78という計算です。


 

Arduino Mega 2560に戻る。