「Arduino Mega 2560 LESSON:12 DHT11 温度湿度センサー」の版間の差分
編集の要約なし |
|||
| (同じ利用者による、間の1版が非表示) | |||
| 360行目: | 360行目: | ||
ビット列は8ビットずつ、湿度、湿度補助、温度、温度補助、チェックサムになっています。チェックサムは47+0+28+3=78という計算です。 | ビット列は8ビットずつ、湿度、湿度補助、温度、温度補助、チェックサムになっています。チェックサムは47+0+28+3=78という計算です。 | ||
== '''ブロッキング処理と非ブロッキング処理の違い''' == | |||
'''1. ブロッキング処理(Blocking)''' | |||
処理が完了するまで、その場所で待ち続ける方式です。 | |||
例えば、次のプログラムです。 | |||
<freescript></script><div class="hljs-wrap"><pre data-label="Arduino Code" class="pre-wrap"> | |||
<code class="cpp">void loop() { | |||
digitalWrite(13, HIGH); | |||
delay(1000); | |||
digitalWrite(13, LOW); | |||
delay(1000); | |||
} | |||
</code></pre></div><script></freescript> | |||
delay(1000) が実行されると、Arduinoは1秒間、次の命令へ進みません。 | |||
[[ファイル:Mega2560 L12 05 ブロッキング処理図.png|380px||none|ブロッキング処理]] | |||
待っている間、通常のプログラムの流れでは、スイッチの確認やほかのセンサーの読み取りなどを実行できません。 | |||
ただし、CPUが完全に停止しているわけではなく、割り込み処理などは動作できます。 | |||
'''2. 非ブロッキング処理(Non-blocking)''' | |||
待ち時間があっても、その間にほかの仕事を進められる方式です。 | |||
例えば、millis() を使ってLEDを点滅させます。 | |||
<freescript></script><div class="hljs-wrap"><pre data-label="Arduino Code" class="pre-wrap"> | |||
<code class="cpp">unsigned long previousTime = 0; | |||
bool ledState = false; | |||
void setup() { | |||
pinMode(13, OUTPUT); | |||
} | |||
void loop() { | |||
if (millis() - previousTime >= 1000) { | |||
previousTime = millis(); | |||
ledState = !ledState; | |||
digitalWrite(13, ledState); | |||
} | |||
// ここで別の仕事ができる | |||
// スイッチの確認など | |||
} | |||
</code></pre></div><script></freescript> | |||
こちらは1秒経過するまで待ち続けるのではなく、loop() が回るたびに経過時間を確認しています。 | |||
[[ファイル:Mega2560 L12 06 非ブロッキング処理図.png|380px||none|非ブロッキング処理]] | |||
LEDの点滅を管理しながら、スイッチを確認したり、別の処理を実行したりできます。 | |||
2026年10月19日 (月) 17:06時点における最新版
概要
DHT11 温度湿度センサーを接続するレッスンです。
完成図は以下のようなモノです。
KiCADで追加した部品
- Conn_01x03:Generic connector, single row, 01x03, script generated (kicad-library-utils/schlib/autogen/connector)
- +5V
- GND
- PWR_FLAG
KiCADで追加したフットプリント
- Conn_01x03:Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical
- Conn_01x03:Connector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_Vertical
PCB図は以下のようなもの。
3DPreview図は以下のようなもの。
AIによるタイミングチャート作図です。
以下のようなコードです。
//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( "%" );
}
}
■dht_nonblocking.h
Arduino Mega 2560 LESSON:12 DHT11 温度湿度センサー dht_nonblocking.h
■dht_nonblocking.cpp
Arduino Mega 2560 LESSON:12 DHT11 温度湿度センサー dht_nonblocking.cpp
ライブラリを使わないで自分なりのコードにすると以下のようになりました。カウント部のデバッグ値も出力しています。
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という計算です。
ブロッキング処理と非ブロッキング処理の違い
1. ブロッキング処理(Blocking)
処理が完了するまで、その場所で待ち続ける方式です。
例えば、次のプログラムです。
void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}
delay(1000) が実行されると、Arduinoは1秒間、次の命令へ進みません。
待っている間、通常のプログラムの流れでは、スイッチの確認やほかのセンサーの読み取りなどを実行できません。
ただし、CPUが完全に停止しているわけではなく、割り込み処理などは動作できます。
2. 非ブロッキング処理(Non-blocking)
待ち時間があっても、その間にほかの仕事を進められる方式です。
例えば、millis() を使ってLEDを点滅させます。
unsigned long previousTime = 0;
bool ledState = false;
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
if (millis() - previousTime >= 1000) {
previousTime = millis();
ledState = !ledState;
digitalWrite(13, ledState);
}
// ここで別の仕事ができる
// スイッチの確認など
}
こちらは1秒経過するまで待ち続けるのではなく、loop() が回るたびに経過時間を確認しています。
LEDの点滅を管理しながら、スイッチを確認したり、別の処理を実行したりできます。