連載一覧
- 第1回:プロジェクト概要
- 第2回:ESP32-S3 の環境構築
- 第3回:I/O の実装(ADC / PWM / DIO)
- 第4回:通信プロトコル(JSON コマンド)
- 第4.5回:デバイス化対応
- 第5回:Python アプリの API 実装
- 第6回:デバイスとしてまとめる(設計編)
- 第7回:実装編・応用編(GUI / アプリ化 / 拡張の可能性)
はじめに
前回(第4.5回)では、ESP32‑S3 側のファームウェアをデバイス化し、
USB でつなぐだけで I/O デバイスとして扱える基盤が整いました。
今回は、そのファームウェアを Python から扱うための
ESP32IO クラス(API) を実装します。
これで ESP32‑S3 を「USB でつなぐだけの I/O デバイス」として Python から扱えるようになります。
目的は以下の通りです。
- JSON コマンドを直接扱わず、Python から直感的に I/O を操作できるようにする
- エラー処理やタイムアウトを統一し、堅牢な API とする
- get_io_state や PWM 設定取得を活用して、テストツールや GUI の基盤を作れるようにする
※ 前回作成したファームウェアはこちら
ZIPファイル内の ESP32_S3_IO_DEVICE です。
ESP32_S3_IO_DEVICE_WiFi は不要です。
今回実装する API の要件
● 必須機能
- シリアル通信の初期化
- JSON コマンドの送信
- JSON レスポンスの受信
- タイムアウト処理
- エラーコードの例外化
- 各 I/O 操作のメソッド化
- read_di()
- set_do()
- read_adc()
- set_pwm()
- get_pwm_config()
- set_pwm_config()
- get_io_state()
● 目標
- ユーザーは JSON を意識しない
- 例外処理が統一されている
- get_io_state と PWM 設定取得によるデバッグ性の向上
API 設計方針
● 1. JSON の送受信を 1 箇所に集約する
内部メソッド _send_command() を用意し、
すべてのコマンドはこれを経由して送信します。
● 2. エラーコードは Python の例外に変換
例:
- INVALID_DIO_IN_PIN_ID → InvalidPinError
- JSON_PARSE_ERROR → ProtocolError
● 3. タイムアウトは読み取り側で管理
- シリアルが固まってもアプリが固まらないようにする
- デフォルト 1 秒程度
● 4. get_io_state を活用したデバッグ性の向上
- 全 I/O の状態を一括確認
- GUI やロガーの基盤にもなる
ESP32IO クラスの実装(コード)
以下は今回実装する ESP32IO クラスです。
-
ESP32IO クラス(API)実装コードはこちら:
https://github.com/noritama-lab/esp32io-api/releases/tag/a-v0.1.2
(/esp32io/ フォルダに Python API が入っています) -
ESP32IO クラスで提供される主なメソッド
read_di(pin_id)
set_do(pin_id, value)
read_adc(pin_id)
set_pwm(pin_id, duty)
get_pwm_config()
set_pwm_config(freq, res)
get_io_state()
- pip install で使う場合
esp32io は PyPI に公開されているため、次のコマンドでインストールできます。
pip install esp32io==0.1.2
※この記事の内容はV0.1.2より後のバージョンは動作確認していません。
インストール後は、通常どおり import できます。
from esp32io import ESP32IO
- ZIP 版を使う場合(任意)
pip install を使わずに GitHub のソースコードを直接利用したい場合は、
esp32io フォルダをプロジェクトと同じ階層に置くだけで使用できます。
your_project/
├─ esp32io/ ← GitHub から取得したフォルダ
└─ your_script.py
この構成にすることで、Python が import esp32io を正しく解決できます。
ESP32IOクラスの使用例
以下の回路を例に、ADC の値を PWM に反映してLEDの明るさを調整するサンプルを示します。ESP32-S3-devkitc-1には下記リンク先のファームウェアを書き込んでおいてください。
https://github.com/noritama-lab/esp32io-firmware
pin_id → GPIO 対応表
| 種類 | pin_id | GPIO |
|---|---|---|
| DIO_IN | 0–5 | 4, 5, 6, 7, 8, 9 |
| DIO_OUT | 0–5 | 10, 11, 12, 13, 14, 15 |
| ADC | 0–1 | 1, 2 |
| PWM | 0–1 | 38, 39 |
今回の回路では
- 可変抵抗 → ADC pin_id:0(GPIO 1)
- LED → PWM pin_id:0(GPIO 38)
に接続されています。
テストツールの実行
プロジェクトの直下(zipの場合、esp32ioフォルダと同じ階層)に test.pyなどのpythonファイルを作成して以下のコードをコピペします。実行すると、可変抵抗の電圧を ADC で読み取り、その値を PWM のデューティ比に変換して LED の明るさを制御します。
このサンプルでは read_adc() と set_pwm() を使って ADC 値を PWM デューティに反映します。必要に応じて get_pwm_config() / set_pwm_config() を使うことで、PWM 周波数と分解能も Python 側から管理できます。
まずはこのテストツールを動かすことで、ESP32IO が正しく動作しているかを一括で確認できます。
from esp32io import ESP32IO
import time
import serial
def main():
try:
# ESP32IO に接続
esp = ESP32IO("COM3", debug=False)
print("ESP32 に接続しました。")
# 現在の PWM 設定を確認し、必要なら変更
print("現在のPWM設定:", esp.get_pwm_config())
esp.set_pwm_config(5000, 8)
while True:
# ADC0 を読み取る
adc_value = esp.read_adc(0)
# PWM0 に反映(0〜4095 → 0〜255 にスケール)
duty = int(adc_value / 4095 * 255)
esp.set_pwm(0, duty)
print(f"ADC={adc_value}, PWM duty={duty}")
time.sleep(0.05)
except serial.SerialException as e:
print("ERROR: ESP32 に接続できませんでした。")
print("理由:", e)
print("COM ポートが正しいか確認してください。")
except Exception as e:
print("予期しないエラーが発生しました:", e)
finally:
# 安全のため PWM を停止
try:
esp.set_pwm(0, 0)
except:
pass
print("終了しました。PWM を停止しました。")
if __name__ == "__main__":
main()
ESP32IO の全コマンドを試せるテストツール
下記リンク先のテストツールに全コマンドの使用方法を示します。
- テストツールはこちら:
https://github.com/noritama-lab/esp32io-api
(リンク先の「example」フォルダ内にある esp32io-sample.py がテストツールです。)
esp32io-sample.py は、ESP32IO の全コマンドをまとめてテストできる初回動作確認ツールです。
できること - DIO 出力(set_do)
- DIO 入力(read_di)
- ADC 読み取り(read_adc)
- PWM 出力(set_pwm)
- PWM 設定の取得・更新(get_pwm_config / set_pwm_config)
- 全 I/O 状態の取得(get_io_state)
このサンプル 1 つで、ESP32IO API の基本動作をすべて確認できます。
サンプルの実行方法
- pip install でインストールした場合
通常どおり、次のコマンドで実行できます。
python examples/esp32io_sample.py
pip install 版では esp32io が site-packages に配置されるため、
直接実行でも import エラーは発生しません。
- ZIP 版を使う場合
ZIP 版では、esp32io フォルダをプロジェクトと同じ階層に置く必要があります。
この場合、サンプルは次のように -m を使って実行してください。
python -m examples.esp32io_sample
-m を使うことで、examples/esp32io_sample.py を
パッケージとして正しく実行できます。
※ python examples/esp32io_sample.py のような直接実行では、
esp32io パッケージが見つからず import エラーになります。
まとめ
- Python から ESP32‑S3 を安全に扱うための API を実装した
- JSON コマンドを意識せず I/O 操作が可能になった
- PWM 周波数と分解能も Python から設定できるようになった
- エラー処理とタイムアウトで堅牢性が向上
- get_io_state によりデバッグ性が大幅に向上
- 次回は GUI / ロギング / Wi‑Fi など応用編へつながる
次回予告
次回は、この API を使って
- デバイスとしてまとめる
- ケース化、配線、固定
- 電源周りの設計
- 実際の用途に合わせた応用例
を紹介します。
