RMTを利用したリモコンライブラリESP32IRPulseKit

概要

ESP32はRMTという赤外線通信などで便利な機能があるのですが、有名な赤外線送受信ライブラリはタイマーで実装しているものばかりです。そこでRMTを利用してタイミング的に精度が高い赤外線リモコンの送受信ライブラリを作成してみました。

作成物

GitHub – tanakamasayuki/ESP32IRPulseKit
Contribute to tanakamasayuki/ESP32IRPulseKit development by creating an account on GitHub.

上記のライブラリとなります。特徴としてはRMTを利用してタイミング的な精度が高いライブラリとなっています。

有名なライブラリだとIRremoteESP8266がありますが、内部的にはタイマーを利用しています。そしてArduinoコアが3系にあがったときにタイマー系のAPIが変更され更新されなくて利用できない期間が無かったです。

そこでちゃんとしたライブラリを作ろうとしてできたのがESP32IRPulseKitになります。しかしながらリリース直前にIRremoteESP8266が更新され、最新版のESP32用Arduinoコアでも利用可能になりました!

といはいえ、RMTを利用してタイミング精度が高いのでESP32IRPulseKitの利点はあります。

RMTとは?

ESP32の機能でして、送信するときにLOWやHIGHの長さを指定した配列を渡すことで、その通りの出力をしてくれます。たとえばRGB LEDなどの信号などでよく利用されています。RMTを利用しない場合にはGPIOをdigitalWrite()などで制御して、delayMicroseconds(us)などを利用しつつタイミングをあわせる必要があります。

RMTを利用すると事前に信号の長さを配列で指定しておくことで、自動的に指定した信号を出力することが可能です。

受信する場合には反対に受信した信号をLOWとHIGHの長さが入った配列で受け取ることができます。受け取った配列を分析することで、受信漏れがなく時間精度も高く処理をが可能になっています。

赤外線リモコン信号とRMTの関係

ただし、RMTは万能ではありませんでした。

赤外線通信の場合には出したい信号があったときに、そのまま出力するのではなく、38KHzのキャリア波を使って送信します。出したい信号がHIGHのときには指定したキャリア周期でHIGHとLOWを繰り返すことでノイズの影響を減らすのと、送信電流も下げることが可能です。

RMTはキャリア波を送信する機能があります。しかしながらキャリア波の位相はコントロールできず、信号のどこからキャリア波は始まるかはわからないです。すると上記みたい出したい信号とキャリア波がずれ、受信側の信号が短くなることがあります。

基本はずれても大丈夫なようなプロトコルになっているのですが、一部の赤外線信号フォーマットではこのしきい値が非常に厳しいものがあります。このキャリア波の位相以外にも送信側の遅延や、受信側の遅延などが重なり30%ぐらいズレて、プロトコルエラーになるケースが発生しました。

最終的に採用したのは、キャリア波を含めてRMTで指定することでした。RMTのキャリア波生成は便利なのですが、誤差が出やすいのでメモリ的には無駄になりますがキャリアはのLOW/HIGHも含めてデータ作成をして送信しています。

pytestでのPeerテストが便利だった

pytest + arduino-cliで自動テスト
概要pytestにはマイコン向けのpytest-embeddedプラグインがあるのですが、ビルドを事前に行う必要があったり、ESP32向けなところがあります。そこでarduio-cliを利用して汎用的に利用できるArduino環境向けのテス…

このライブラリを作成するにあたって上記のpytest-embedded-arduino-cliを使って自動テストしています。その中の機能でピアテストがあります。これはESP32を2台準備して、送信側と受信側を同時にテストすることが可能です。

今回はESP32IRPulseKit同士の送受信テストだけではなく、IRremoteESP8266などの他の赤外線リモコンライブラリをクロスで相互接続を試す試験も自動試験できるようにしてあります。

ESP32IRPulseKitは当初RMTを利用しても、他のライブラリより時間精度が悪かったのですが確認したところ、タイマー実装の場合にはキャリア波自体もタイマーで生成しているために、位相のズレが発生しないためでした。そのためRMTでのキャリア波をやめて、自前キャリア波生成をデフォルトでは有効に変更しました。

また、他ライブラリ同士で送受信をしても送信エラーになるパターンがありました。どうも一部のライブラリではプロトコルの既定値で判定しているようでして、多少信号がなまると範囲外でエラーになってしまうパターンが多かったです。

プロトコル判定にスコアリング形式を採用

一般的なライブラリでは信号の範囲によって複雑な条件文を利用してプロトコル判定を行っております。特によく似たタイミングのプロトコル同士の判定があまくならないように、タイミングは厳密にチェックするパターンが多かったです。

ESP32IRPulseKitでは一括判定をするのではなく、プロトコルごとにスコアリングをして最後に最もスコアが高いフォーマットを採用する方式になっています。標準値からズレていても信号のLOWとHIGHが判定できる場合にはがんばってデコードします。そしてスコアには標準タイミングからのズレの累計も加味して反映されているので、似ているフォーマットで信号が鈍っていても、デコードが成功するように調整してあります。

とくにタイマー系のライブラリだと受信してもデコード失敗することが多い場合や、誤判定されているパターンなどはESP32IRPulseKitの方がデコード精度が高いははずです。そして送信もタイマーを利用せず、RMTのハードウエア側のタイミングで送信しているのでベンチマークでは他のライブラリより成績が良かったです。

まとめ

通常の実機だとプロトコルの規定よりもゆるく判定してくれることが多いのですが、複数のプロトコルを識別するライブラリはきつめの判定となります。

そのためRMTのキャリア波を利用しても実機には送信可能あと思いますが、かなり調整をして送信タイミングもかなり高いものが実現できました。

一応エアコン系も対応していますので、大抵の用途にはこのライブラリで問題ないものができていると思います。

コメント