ElixirのコードでESP32S3(LCD)を動かすことを目標にするコラムです
今回はExAtomVMを使います
開発環境
- Ubuntu 24.04
- elixir 1.17.1-otp-27
- erlang 27.2.1
実行イメージ
焼き方の前提知識&プロジェクト作成方法
LCD 参考資料
- AIを使って下調べ
AIをそのまま信じるのは危険です
場合によってはハードを壊します
AIが書いたソース
defmodule GroveLCD do
# I2Cアドレス定義
@lcd_addr 0x3E
@rgb_addr 0x62
# コマンド定義
@lcd_cmd_mode 0x80
@lcd_data_mode 0x40
# バックライト用レジスタ
@reg_red 0x04
@reg_green 0x03
@reg_blue 0x02
@reg_mode1 0x00
@reg_output 0x08
@doc """
初期化と「Hello ExAtom!」の表示
"""
def start do
# 1. I2Cバスの初期化 (ピン番号は使用するボードに合わせて変更してください)
# ESP32のデフォルト: sda=21, scl=22
{:ok, i2c} = I2C.open(sda: 21, scl: 22, speed_hz: 100_000)
# 2. LCDとRGBのセットアップ
init_lcd(i2c)
init_rgb(i2c)
# 3. テスト表示
set_rgb(i2c, 0, 255, 0) # 緑色にする
print(i2c, "Hello ExAtomVM!")
# 2行目に移動して表示する場合の例
# set_cursor(i2c, 0, 1)
# print(i2c, "Elixir works!")
end
# --- 内部関数: LCD制御 ---
def init_lcd(i2c) do
# I2C経由での初期化シーケンス (データシートに基づく)
Process.sleep(50)
send_cmd(i2c, 0x38) # Function set: 2 lines
Process.sleep(5)
send_cmd(i2c, 0x38)
Process.sleep(1)
send_cmd(i2c, 0x0C) # Display ON, Cursor OFF
send_cmd(i2c, 0x01) # Clear Display
Process.sleep(5)
send_cmd(i2c, 0x06) # Entry Mode
end
def print(i2c, str) do
String.to_charlist(str)
|> Enum.each(fn char -> send_data(i2c, char) end)
end
defp send_cmd(i2c, cmd) do
I2C.write(i2c, @lcd_addr, <<@lcd_cmd_mode, cmd>>)
end
defp send_data(i2c, data) do
I2C.write(i2c, @lcd_addr, <<@lcd_data_mode, data>>)
end
# --- 内部関数: RGBバックライト制御 ---
def init_rgb(i2c) do
# バックライトICのリセットと有効化
I2C.write(i2c, @rgb_addr, <<@reg_mode1, 0x00>>)
I2C.write(i2c, @rgb_addr, <<@reg_output, 0xAA>>)
end
def set_rgb(i2c, r, g, b) do
I2C.write(i2c, @rgb_addr, <<@reg_red, r>>)
I2C.write(i2c, @rgb_addr, <<@reg_green, g>>)
I2C.write(i2c, @rgb_addr, <<@reg_blue, b>>)
end
end
修正して動いたソース
I2C.writeは存在してません
I2C.write_bytesが正解です
defmodule AvmLcd do
@moduledoc """
Documentation for `AvmLcd`.
"""
# I2Cアドレス定義
@lcd_addr 0x3E
@rgb_addr 0x62
# コマンド定義
@lcd_cmd_mode 0x80
@lcd_data_mode 0x40
# バックライト用レジスタ
@reg_red 0x04
@reg_green 0x03
@reg_blue 0x02
@reg_mode1 0x00
@reg_output 0x08
def start do
Process.sleep(1000)
IO.inspect("YMN test")
# # --- 修正箇所: XIAO ESP32S3 のピン番号 (SDA=5, SCL=6) ---
i2c = I2C.open([{:scl, 6}, {:sda, 5}, {:clock_speed_hz, 1_000_000}])
IO.inspect("OK")
# # 初期化
init_lcd(i2c)
init_rgb(i2c)
IO.inspect("OK2-1")
set_rgb(i2c, 100, 100, 200)
# 文字を表示
print(i2c, "YMN Test")
end
# --- 以下は変更なし ---
def init_lcd(i2c) do
# 1. Function Set (0x38: DL=1: 8bit, N=1: 2R, F=0: 5x7)
# - AIP31068Lの Function Set コマンドは 0b0011NFXX, N=1, F=0 の場合 0b001110XX = 0x38
send_cmd(i2c, 0x38)
# Wait for more than 40us (1msで十分)
Process.sleep(1)
# 2. Display ON/OFF Control (0x0C: D=1, C=0, B=0)
send_cmd(i2c, 0x0C)
# Wait for more than 39us (1msで十分)
Process.sleep(1)
# 3. Display Clear (0x01)
#send_cmd(i2c, 0x01)
# Wait for more than 1.53ms (2msで十分)
#Process.sleep(2)
# 4. Entry Mode Set (0x06: I/D=1, S=0)
#send_cmd(i2c, 0x06)
# 念のため
#Process.sleep(1)
end
# 代替案: パターンマッチングで1バイトずつ取り出す
def print(i2c, <<char, rest::binary>>) do
send_data(i2c, char)
print(i2c, rest)
end
def print(_i2c, "") do
:ok
end
@compile {:no_warn_undefined, [I2C]}
defp send_cmd(i2c, cmd) do
I2C.write_bytes(i2c, @lcd_addr, <<@lcd_cmd_mode, cmd>>)
end
@compile {:no_warn_undefined, [I2C]}
defp send_data(i2c, data) do
I2C.write_bytes(i2c, @lcd_addr, <<@lcd_data_mode, data>>)
end
@compile {:no_warn_undefined, [I2C]}
def init_rgb(i2c) do
I2C.write_bytes(i2c, @rgb_addr, <<@reg_mode1, 0x00>>)
I2C.write_bytes(i2c, @rgb_addr, <<@reg_output, 0xAA>>)
end
@compile {:no_warn_undefined, [I2C]}
def set_rgb(i2c, r, g, b) do
I2C.write_bytes(i2c, @rgb_addr, <<@reg_red, r>>)
I2C.write_bytes(i2c, @rgb_addr, <<@reg_green, g>>)
I2C.write_bytes(i2c, @rgb_addr, <<@reg_blue, b>>)
end
end
これで動きました
俺は破壊王になる 〜 アンチパターン 〜
いじりすぎてLCDを破壊しました
AIに文字が薄いから対策したいと伝えました
いろいろ試して解決しなかったので、Vccを3.3Vから5Vの提案がありました
ここでI2Cの制御が一部使えなくなってバックライトがつかなくなりました
LCD本体のバージョンがいくつかあって最新版のLCDは5Vに対応していた
僕の使ったものは1つ前のバージョンでした、非対応で破壊した恐れあり
AIをそのまま信じるのは危険です
ハードを壊します
AIをそのまま信じるのは危険です
ハードを壊します
AIをそのまま信じるのは危険です
ハードを壊します
大事なので三回書きました
- AIを使って調査の反対はしません
- 自分の知識を超える範囲は慎重に扱いましょう
- 今回はLCDの使い方です
- AIのご利用は計画的に
- 大事な部分は人間が最終判断をすること
- AIに責任転嫁はやめましょう
- AIを使うのは自己責任です
AIコーディングはやっていますが…
本人以上の成果は厳しいです
僕はElixirの部分はなんとかなりますが、さすがに今時点ではハードは厳しいです
なので「AIを使えば簡単にコーディングできるでしょ?」は疑問をもっています
場合によって取り返しのつかないことが起きても不思議でないです
このコラムで一番伝えたい事です
〜 そして伝説へ 〜
まだLCDが元気だったころの姿です
