ESP32 DevKitで、HC-SR04の距離、AHT20の温度・湿度、BMP280の気圧を取得し、SSD1306 OLEDへ同時に表示した。後編では、この値をCODESYSへCSVで渡す。
完成した配線
| ESP32 | 接続先 |
|---|---|
| GPIO2 | 外付けLED |
| GPIO4 / GPIO5 | HC-SR04のTRIG / ECHO |
| GPIO21 / GPIO22 | I2CのSDA / SCL |
| 3V3 | SSD1306、AHT20+BMP280 |
| 5V | HC-SR04 |
SSD1306とAHT20+BMP280は同じI2Cバスに並列接続した。I2Cスキャナで確認できたアドレスは、AHT20が0x38、SSD1306が0x3C、BMP280が0x77だった。
LEDには通常、過電流を防ぐため220 Ωから1 kΩ程度の電流制限抵抗を直列に入れる。HC-SR04を5Vで使う場合は、ESP32の3.3V GPIOを保護するため、ECHO信号の分圧も検討する。
Arduino IDEの設定
ボードはESP32 Dev Module、シリアル速度は115200 baudを使用した。ライブラリはAdafruit SSD1306、Adafruit GFX Library、Adafruit AHTX0、Adafruit BMP280 Libraryを導入した。
シリアルモニタも同じ115200 baudへ合わせないと、確認文字列が文字化けする。
距離測定と表示の要点
距離は、ECHOがHIGHだった時間から次式で求める。
距離[cm] = ECHOのHIGH時間[µs] × 0.0343 ÷ 2
超音波は往復するため2で割る。測定にはタイムアウトを設定し、応答がない場合を値として扱わない。
unsigned long duration = pulseIn(ECHO_PIN, HIGH, 30000);
bool distanceValid = duration != 0;
float distance = distanceValid ? duration * 0.0343 / 2.0 : 0.0;
OLED表示では、バッファを消去し、文字色、文字サイズ、座標を設定してからdisplay.display()で実機へ転送する。文字色の指定がないため、OLEDに何も表示されない問題が起きたこともあった。
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Dist:");
display.print(distance, 1);
display.println("cm");
display.display();
CODESYSへ渡すCSV
人間向けの文字列ではなく、後段で解析しやすいCSVをUSBシリアルへ出力するようにした。
距離cm,温度℃,湿度%,気圧hPa
4.8,26.6,53.3,998.1
距離を検出できない場合は-1.0を出し、Serial.println()でLFを付ける。CODESYSがCOMポートを開いている間は、Arduino IDEのシリアルモニタを閉じる必要がある。同じポートを複数のアプリケーションで同時に開けないためだ。
この構成で、4項目の取得、OLED同時表示、距離によるLED制御、CSV出力を確認できた。