MicroPython的午睡(107) ESP32版、RMT、どこの端子が使えるの?

Joseph Halfmoon

ESP32シリーズ用のMicroPythonに固有の機能の多くがesp32という名のモジュールに格納されています。その中に周辺の制御用にユニークな機能が一つ、RMTです。もともと赤外線リモコン用の送受信のために搭載されているハード機能を制御するためのクラスです。面白そうなのだけれども、だいたいどのピンが使えるの?

※「MicroPython的午睡」投稿順 Indexはこちら

RMT

RMTの概要は、いつもお世話になっております以下の日本語ページにも記述されております。

ESP32 用クイックリファレンス

ただ、上記では通り一遍すぎてイマイチなので、esp32モジュールの以下のページの方が詳しいデス。

esp32 — EDS32 に固有の機能

上記より1か所引用させていただきます。

ESP32 に固有の RMT (リモートコントロール)モジュールは、もともと赤外線リモートコントロール信号を送受信するために設計されました。ただし、柔軟な設計と非常に正確な(12.5ns程度の)パルス生成により、他の多くのタイプのデジタル信号の送受信にも使用できます

そうです「他の多くのタイプの」というところに可能性を感じてしまうのであります。なんていったって最小レゾリューション12.5ns単位で信号の「上げ」「下げ」が可能。これはハードウエアでないとなかなか成しえることではありません。さらに別に搬送波(赤外リモコン用の)を定義して上記信号で変調かけることもできます。ソフト制御の遅い信号とは一線を画する性能です。

ただしMicroPython上での実装には制限もありです。データシートを見るとRMTのハードは送受信、双方向の装置なのですが、現状のMicroPythonでは送信機能のみサポートとなっています。一方通行の赤外線リモコンを作ることは簡単にできそうですが、双方向(たとえばエアコンの赤外リモコンなどは双方向だと思います)のリモコンにするのはMicroPythonではできませぬ。とりあえず送信方向だけでも何かに使えそうではないかということで調べてみることにいたしました

ここでいくつか疑問が

    1. RMTには合計8チャネルの送受信チャネルが存在するが、チャネル間で同期した出力とかできるの?
    2. RMTの出力信号はどのGPIO端子にでも出力できるの?

1番目のようなことができると1チャネルでクロック信号を作りながら、別のチャネルでクロックに同期したデータを送出するといった技が使えます。また、さらっと(深くは読んでないっす)データシートを「見る」限り、プログラム次第でどのGPIOにも出力できそうな雰囲気があるのだけれど、本当にそうなのか?

例によって「実機に聞くのが早い」ということでやってしまいました。

今回実験のMicroPythonコード

以下の短いコードです。RMTチャネル0とチャネル1をテキトーなピンにアサインし、タイミング的には80MHzの元クロックの8分周、10MHz相当(100nsec)のレゾリューションでハイ/ロー非対称な長さのパルスを2発送り出すものです。これを外部で観察すれば、上記の疑問にアプローチできるんではないかと。

import esp32
import machine, time

def main():
    print("ESP32, RMT TX function test") 
    rmt0 = esp32.RMT(0, pin=machine.Pin(4), clock_div=8)
    rmt1 = esp32.RMT(1, pin=machine.Pin(22), clock_div=8)
    # 4, 21, 22, 32 .. OK
    # 15 .. NO ERROR, NO SIGNAL
    # 34, 35 .. OS ERROR, ESP_ERR_INVALID_ARG

    loopCounter = 0
    while True:
        rmt0.write_pulses((10, 20, 20, 10), 0)
        rmt1.write_pulses((12, 18, 15, 15), 0)   
        loopCounter += 1
        if (loopCounter % 25) == 0 :
            print("LOOPCOUNTER: ", loopCounter)
        time.sleep_ms(250)
            
if __name__ == "__main__":
    main()
使える端子の何本かは分かったけれど

ターゲットボードESP32 DevKitCから、テキトーに7端子(当方のブレッドボード上で当たりやすかった端子)選んでRMT信号を出力してみたところ、以下のようでした。

    1. 正常に出力可能な端子。4番、21番、22番、32番
    2. 出力しようとするとOS ERROR発生する端子。34番、35番
    3. ERRORは発生せず実行できるが、端子を観察しても信号が出てこない端子。15番

番号は、ESP32 DevKitCのボード表面にシルクで印刷してある番号です。

なぜ上記のような結果になるのか今のところ不明。とくに第3のケースは何?まあ、実験してOKな端子に出力しておけば使えることは使えそうですが、釈然としないデス。

タイミング

以下の波形、黄色がチャネル0、青色がチャネル1です。信号の幅などは観察していても揺るぎもしませぬ。設定したレゾリューションでキッチリ制御されているみたいです。ESP32_RMT_WaveForm

しかし、黄色と青色のパルス間の関係は微妙にズレることがありました。2つのwrite_pulseメソッドの間はMicroPython処理系のソフトウエアの実行速度依存のようです。2チャンネルを「同期」させて使うのは無理っぽい?

制御に使われている80MHzのクロックは同じものらしいので、何か工夫したらできんかのう。思いつきません。

MicroPython的午睡(106) ESP32版、DHT11を接続してみる へ戻る

MicroPython的午睡(108) ESP32版、「自前制作」タッチセンサをセンス へ進む