はじめに
環境系のセンサーを複数持っているのに、使っていないからそれを活用するために有機ELを使った環境モニターを作ります。
使用部品
| 部品 | 用途 |
|---|---|
| Raspberry Pi Pico W | メイン制御 |
| SSD1306 OLED (128x64) | 表示 |
| DHT11 | 温湿度測定 |
| ADC入力 | アナログ電圧測定 |
| タクトスイッチ×3 | 操作 |
| ADC入力に付けたセンサー |
|---|
| ADC入力につないだセンサー |
| ガスセンサー |
| 明るさセンサー |
機能
- Wi-Fi接続
- NTPによる時刻同期
- デジタル時計表示
- DHT11温湿度表示
- アナログ入力3ch表示
- リアルタイムグラフ表示
- ボタン操作メニュー
- 自動スリープ・復帰
ライブラリ
import time
import machine
import ssd1306
import dht
import network
import ntptime
使用している主なライブラリです。
-
ssd1306- OLED制御
-
dht- DHT11センサー制御
-
network- Wi-Fi接続
-
ntptime- NTP時刻取得
Wi-Fi接続処理
接続リトライ
def wifi_connect():
Wi-Fi接続は起動時に行います。
ただし、組み込み機器では電波状況によって失敗することがあります。
そのため、
- 20回接続確認
- 失敗したら再試行
- 最大3回
という仕組みにしています。
OLEDにも状態表示します。
例:
TRY 1
BOOT 10/20
BOOT OK
起動中でも現在状態が分かります。
NTPによる時計合わせ
def ntp_sync():
ntptime.settime()
PicoにはRTCがありますが、電源OFFで時刻が消えます。
そこでネットワーク上のNTPサーバーから現在時刻を取得します。
日本時間へは、
JST = 9 * 3600
として9時間追加しています。
OLED初期化
i2c = machine.I2C(
0,
sda=Pin(0),
scl=Pin(1)
)
I2C接続でOLEDを制御しています。
解像度は、
SSD1306_I2C(128,64,i2c)
なので128×64ドットです。
センサー処理
DHT11
sensor = dht.DHT11(Pin(16))
GPIO16にDHT11を接続。
読み取りは、
sensor.measure()
t_now = sensor.temperature()
h_now = sensor.humidity()
で取得できます。
ADC入力
PicoのADCは16bit値で返ります。
raw = adc.read_u16()
そのため、
voltage = raw * 3.3 / 65535
で電圧へ変換しています。
今回は、
ADC26
ADC27
ADC28
の3チャンネルを使用しています。
ボタン処理
使用しているボタン:
| ボタン | 役割 |
|---|---|
| UP | 上移動 |
| DOWN | 下移動 |
| OK | 決定 |
プルアップ入力なので、
押していない
1
押す
0
になります。
長押し処理
OKボタンを1.5秒押すと、
sleep_request=True
になります。
画面に、
SLEEP
を表示してスリープします。
モード管理
画面状態は変数で管理しています。
MODE_CLOCK = 0
MODE_MENU = 1
MODE_TEMP = 2
MODE_HUM = 3
現在モード:
mode = MODE_CLOCK
例えば、
時計
↓ OK
メニュー
↓ OK
温度グラフ
という状態遷移になります。
メニュー表示
メニュー配列:
menu=[
"CLOCK",
"TEMP",
"HUM",
"analog1",
"analog2",
"analog3"
]
画面に表示できる行数は、
MENU_VISIBLE = 4
なのでスクロール表示しています。
カーソルは、
>
で表示します。
温湿度グラフ
取得した値を配列へ保存します。
temps.append(t_now)
hums.append(h_now)
最大110点まで保持。
MAX_POINTS = 110
古いデータは削除します。
グラフ変換
OLEDは座標なので、
値 → Y座標
へ変換します。
value_to_y()
例えば、
温度
20℃
|
|
30℃
を画面上の
0~63pixel
へ変換します。
自動スリープ
最後の操作時間を保存しています。
last_action
5分経過すると、
mode = MODE_SLEEP
になります。
消費電力削減のためです。
復帰処理
スリープ中にOKボタンを押すと、
wake()
を実行。
内容:
- OLED復帰
- Wi-Fi再接続
- NTP同期
を行います。
メインループ
中心部分です。
while True:
button()
sensor()
display()
実際にはタイマー管理して、
- センサー → 2秒周期
- 時計 → 1秒周期
- グラフ → 2秒周期
で更新しています。
工夫したポイント
1. delayを使いすぎない
組み込みでは、
time.sleep()
を大量に使うと操作不能になります。
そのため、
time.ticks_ms()
で時間管理しています。
2. OLEDを無駄に更新しない
毎回描画すると、
- 遅い
- 消費電力増加
になります。
必要な時だけ、
oled.show()
しています。
3. グラフの自動スケール
温度や湿度が変化すると、
T_MIN
T_MAX
を変更して表示範囲を調整します。
まとめ
次は外部から環境モニターの情報を習得できるようにしたい。