はじめに
秋月電子の謎SOC基板を使って、家の電力計の値を取得してHome Assistantで可視化しようの続きです。Home Assistantに電力量を蓄積できましたので、いつでも電力量を見られるように、常時表示する電力量専用の液晶画面を作りました。
ESPHomeを使おう
ESPHomeは、この記事を閲覧されている方にお馴染みの超お手軽SoCESP-WROOM-32 (以下ESP32)を使って、Home Assistantに接続する機器を自作できるアドオンです。
ESPHomeは、Home Assistantのアドオンとして組み込まれるため、設定からESP32への書き込みまですべてHome Assistant上で行えます。そして液晶に表示するためのコードは、Arduino的な専用スクリプトで処理部分のみ追記すればいいので、超簡単です。
表示デバイスを用意する
デバイスとして、ESP32-WROOM-32E 開発ボードと、ILI9341搭載TFT液晶ボード (以下ILI9341)を利用しました。(実際には、同型のタッチパネルなしモデルを使用しています。実際にどのような液晶が使えるかは、ESPHomeのサイトで確認できます)。以下図のように接続しています。(ESP32とILI9341の接続は、最後に載せたyamlスクリプトもご確認ください)
液晶ピン番号 | 液晶信号名 | ESP32開発ボードピン番号 | ESP32信号名 |
---|---|---|---|
1 | VCC(3.3V) | 2 | 3V3 |
2 | GND | 38 | GND |
3 | CS | 29 | GPIO5 |
4 | RESET | 28 | GPIO17 |
5 | DC/RS | 27 | GPIO16 |
6 | SDI(MOSI) | 37 | GPIO23 |
7 | SCK | 30 | GPIO18 |
8 | LED | 8 | GPIO32 |
9 | SDO(MISO) | 31 | GPIO19 |
あと細かいことですが、ESP32はWIFI4(2.4GHz帯)を使用しますので、接続可能なWIFI環境を用意しておきます。
ESPHomeアドオンをHome Assistantにインストールする
Home Assistantのweb画面から、「設定」⇒「アドオン」⇒「アドオンストア」で、「ESPHome」を選ぶだけです。インストール完了すると、画面左のメニューに「ESPHome」が追加されます。
ESP32をデバイスとして追加する
- まずはESP32-WROOM-32E 開発ボードを、Home Assistantが稼働しているサーバーに、USBケーブルで接続します。
- Home Assistantの画面左のメニュー「ESPHome」を開き、「NEW DEVICE」をクリックします。説明内容を確認し、「CONTINUE」をクリックします。
- デバイスの名前を入力します(例えばESP-echonetviewのように、既存の機器と重ならないような名前を付けます)。「Configuration created!」の画面が表示されるので、「INSTALL」をクリックします。
- 「How do you want to install ... on your device?」が表示されます。「Plug into this computer running ESPHome Dashboard」を選び、Pick Server Portで、USBケーブルでつないだESP32-WROOM-32E 開発ボードのデバイス名を選択します。(例えば「CP2102 USB to UART Briged Controller」(/dev/ttyUSB0)など、USB経由のシリアル(UART)接続デバイスを選びます)
- 後は、ESPHomeが自動で環境をビルドして、USBケーブル経由でESP32にファームウェアを書き込みます。環境によりますが、最初は5~10分程度かかります。
- 無事完了すれば、ESPHomeの画面に、デバイスが追加されます。
- 上記の作業を完了すれば、サーバとESP32間は無線LANで通信を行いますので、サーバーにUSBケーブルを接続しなくても単体で動作します。
デバイスの設定yamlファイルを作成する
- 文字表示のために、TTFフォントが必要です。Home Assistantサーバの homeassistant/esphome/ にTTFファイルをコピーしておきます。(今回はVeraMono.ttfを使用しています。ESP32はそれほど多くのメモリを積んでいないので、小さな(100KB未満くらい)のTTFファイルを探して入れましょう)
- 上記で作成したデバイスの「EDIT」をクリックして、以下を追記します(既存の記載をそのまま残して追記しましょう)。(細かい部分は環境に合わせてテキトウに修正してください)追記したら、「INSTALL」でESP32を更新します。
- グラフは「graph:」エントリ、画面の位置情報、グラフの凡例などの文字列は「display:」エントリで設定しています。自分の好みに合わせて変更してみてください。
- グラフやパーセンテージ表示は、上限30Aで決め打ちしています。変更したい場合は、「display:」「graph:」エントリあたりを変更してみてください。
esp32:
board: esp32dev
framework:
type: arduino
# SPI configuration
spi:
clk_pin: GPIO18
mosi_pin: GPIO23
miso_pin: GPIO19
interface: hardware
# Home Assistant Sensor
sensor:
- platform: homeassistant
id: ha_measured_power
name: "Echonet Measured Power"
entity_id: sensor.echonet_measured_power
- platform: homeassistant
id: ha_integrated_power
name: "Echonet Integrated Power"
entity_id: sensor.echonet_integrated_power
time:
- platform: homeassistant
id: esptime
# Define a PWM output on the ESP32
output:
- platform: ledc
pin: GPIO32
id: gpio_32_backlight_pwm
# Define a monochromatic, dimmable light for the backlight
light:
- platform: monochromatic
output: gpio_32_backlight_pwm
name: "Display Backlight"
id: back_light
restore_mode: ALWAYS_ON
font:
- file: 'VeraMono.ttf'
id: mono10
size: 10
- file: 'VeraMono.ttf'
id: mono16
size: 16
- file: 'VeraMono.ttf'
id: font_pwr
size: 56
- file: 'VeraMono.ttf'
id: font_per
size: 52
color:
- id: graph_line
red: 25%
green: 100%
blue: 50%
- id: title_blue
red: 25%
green: 50%
blue: 100%
graph:
# Show bare-minimum auto-ranged graph
- id: measured_power_graph
duration: 2h
width: 280
height: 120
max_value: 3000
min_value: 0
x_grid: 30min
y_grid: 500
traces:
- sensor: ha_measured_power
line_type: SOLID
line_thickness: 2
continuous: true
color: graph_line
display:
- platform: ili9xxx
model: ILI9341
cs_pin: GPIO5
dc_pin: GPIO16
reset_pin: GPIO17
auto_clear_enabled: True
rotation: 270
update_interval: 10s
lambda: |-
it.fill(COLOR_OFF);
auto back_blue = Color(16, 16, 96);
it.filled_rectangle (0, 0,320,20 ,back_blue);
it.filled_rectangle (0,224,320,240,back_blue);
it.strftime(319, 0, id(mono16), TextAlign::TOP_RIGHT, "%y-%m-%d %H:%M", id(esptime).now());
it.print ( 4, 0, id(mono16), id(title_blue), TextAlign::TOP_LEFT, "Measured POWER");
it.printf( 87, 76, id(font_pwr), TextAlign::BASELINE_CENTER, "%.0fW", id(ha_measured_power).state);
it.printf(259, 76, id(font_per), TextAlign::BASELINE_CENTER, "%.0f%%", id(ha_measured_power).state/30 );
it.printf(159, 240, id(mono16), TextAlign::BASELINE_CENTER, "TOTAL:%.1f KW", id(ha_integrated_power).state);
it.graph (30 , 94, id(measured_power_graph));
it.print (26 , 98, id(mono10), TextAlign::BASELINE_RIGHT , "3000");
it.print (26 ,138, id(mono10), TextAlign::BASELINE_RIGHT , "2000");
it.print (26 ,178, id(mono10), TextAlign::BASELINE_RIGHT , "1000");
it.print (26 ,218, id(mono10), TextAlign::BASELINE_RIGHT , "0");
it.print (92 ,224, id(mono10), TextAlign::BASELINE_CENTER, "-1:30");
it.print (162 ,224, id(mono10), TextAlign::BASELINE_CENTER, "-1:00");
it.print (232 ,224, id(mono10), TextAlign::BASELINE_CENTER, "-0:30");
it.print (302 ,224, id(mono10), TextAlign::BASELINE_CENTER, "-0:00");