ESP8266/ESP32用のSoftwareSerialライブラリを作ってみた。

ESP8266には、SoftwareSerialが同梱されているのでそれを使えば良い話ではあるのだが、なんでこんなに複雑になるんだろうと思うくらいのコードになっていて性能的にも悪そうだし気分的にあまり使いたくないと思ってしまったので自分で作ってみることに...

SoftwareSerialは115200bpsだと処理が間に合わなくてスタートビットで割り込み処理に入った後、受信完了まで割り込み処理内でループする苦肉の策をとっているようだが、その方法だと他の割り込みを約100us遅延させてしまう。

このライブラリは、PinChange割り込みのみで実装しているが可能な限り単純化した結果、230400bps(ESP8266:80MHz)まで対応可能だ。対応フレームは8N1形式のみ。

但し、なんらかの割り込み処理時間或いは割り込み禁止時間が長いコードが存在する場合、そのコードの実行タイミングによってはボーレートに関わずデータ化けが発生してしまうことがある。ライブラリ側では解決不可能な問題であり、解決策としてはアプリ側のプロトコル処理でエラーリカバリーしてもらう以外に方法はない。

ちなみにESP32(240MHz)よりもESP8266(80MHz)のほうが性能が良いようだ。というかESP32が遅すぎる。ArduinoOTAの更新進捗速度を見ててもわかるくらい遅い。Pingのレスに至っては10倍以上も遅い。もしかして失敗作というか性能でなかったからクロックだけ上げてゴマかしちゃったとかではないよね?...(-_-;)

それはともかく、このライブラリのどこにも受信ピンをリードするコードがない...って、それで受信できるのか?(笑)

【ESP32-C3では使えない】
2023-03-19
正確に言うと無線接続前なら受信できるが無線接続後に受信できなくなる。詳しくは調べてないが無線処理の割込み処理時間が長い、割込み禁止時間が長い、或いは、FreeRTOSのタスク切り替えのオーバーヘッドが大きい(というかCPUが遅い?)のどれかだろうと思っている。原因はなんにせよこのCPUでは処理能力的に無理っぽそうなので、もう一つのシリアル(Serial1)を使うこと。ちなみにSerial1の規定のピンはUSB用に割り当てられているため他のピンに変更したほうが良いだろう。

例: Serial1.begin(115200, SERIAL_8N1, RXPIN, TXPIN);

【概要】

初期処理を行う。rxpin/txpinを省略する場合は、SWUART_NOPINを指定する。

終了処理を行う。

受信済みのデータバイト数を取得する。

1バイト受信する。データがないときは-1が返される。

複数バイト受信する。bufに格納したデータバイト数を返す。

1バイト送信する。送信は割り込み禁止で行われることに注意。

複数バイト送信する。

※通信は半二重方式。同時に送受信することは出来ないので注意!

【サンプル・スケッチ】

【ライブラリ】