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 SSD1306Adafruit GFX LibraryAdafruit AHTX0Adafruit 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出力を確認できた。