M5StackとM5CameraでWiFi, UDPによる動画転送を長時間連続安定動作させる実験

M5StackとM5CameraでWiFi,UDPで長時間安定して動画転送できた M5Stack

ESP32同士でDMAやWiFi UDP送受信を長時間安定動作させる個人的解決方法

前節のESP32がフリーズする問題の解決策をまとめると以下のようになりました。
あくまで素人解釈なので、間違えていたらコメント投稿で教えてください。

冷却ファンを使ってESP32のCPU温度を65℃未満に保つ

先ほど述べたように、長時間の大量のWiFi UDPデータ送受信は、ESP32のCPU温度が直ぐ上昇して、65℃を超えてフリーズしてしまいます。

M5StackもM5Cameraも両方に冷却ファンが必要だと思います。

残念ながら、M5Stackオプションで冷却ファンモジュールが無いので、私は以下のアイテムを使いました。

これのお勧めな点は、M5Stackのサイズに近い大きさだったことと、粘着テープではなく、吸着パッドがついているところです。
そして、USB電源で動作するという所も好都合でした。
パッケージはこんな感じでした。

これをネジ止めして組み立てると下図のようになります。

下図の様に吸着パッドの保護シートをはがせばM5Stackのボディーに吸着します。
これは、汚れたら洗い流せるそうです。

下図の様に、M5StackのBottom電池ケースを外して、冷却ファンを吸着させました。

次に、M5Cameraには、以下のような小型USB冷却ファンを使いました。

これは、買い合わせ対象商品で安かったので買ってみました。
今回はこれをM5Cameraに下図の様に乗っけただけです。

因みに、この写真にあるM5Cameraのスタンドは、デジカメ用の安い小型スタンドです。それにM5Cameraをインシュロックでくくりつけただけです。
今回は実験なので、冷却ファンを載せただけですので、ちゃんと動かしたい場合はしっかり固定させた方が良いと思います。
初めてUSB冷却ファンを使ってみましたが、汎用的に使えるので、何かと便利だと思いました。
これで、暖房の効いた部屋でもCPU温度を55℃近辺にキープできると思います。

個人的な希望としては、M5Stack社にオプションとして、M5Stack用ファンモジュールと、M5Camera用ファンモジュールを販売してくれるといいなぁと思っています。

ESP32のCPU温度を監視する関数を使って65℃を超えない様に監視する。

冷却ファンが使えない場合があると思いますので、その時はESP32のCPU温度を常に監視して、65℃近辺になったらWiFiを送信側、受信側両方をOFFにするなどのプログラミングが必要だと思います。

Arduino core for the ESP32では、CPU温度を返してくれる以下の関数が用意されています。


temperatureRead();

ウォッチドッグタイマを有効にし、WiFi関連処理をCPU core 0、シビアな連続処理はCPU core 1で動作させる

先ほど述べたように、ウォッチドッグタイマはおそらくWiFi関連プログラムの監視にも関わっている可能性が考えられるので、有効にすべきだと思われます。

あと、DMA等のシビアなタイミングが要求される連続処理は、基本的にCPU core 1で動作させた方が良いと思います。
連続処理によって、裏で動くWiFi関連のCPU core 0に影響を与えないようにするためです。

そして、WiFi関連処理については、裏で動いていると思われる低レイヤーのWiFiプログラムと同じCPU core 0で動かした方が良いと思われます。

Arduino coreのプログラミングの大まかな概要は以下のような感じです。

TaskHandle_t taskDMA_handl;

void setup() {
  xTaskCreatePinnedToCore(&taskUDP, "taskUDP", 8192, NULL, 24, &taskDMA_handl, 0);
  initTaskDMA();
}

void loop() {
  TaskDMA();
  //メインループにdelay(1)は不要
}

void initTaskDMA(){
  //DMA制御初期化
}

void TaskDMA(){
  //DMA制御
}

void taskUDP(void *pvParameters){
  setupWiFi(); //WiFiのセットアップをここで行う。
  while(true){
    //UDP送受信
    delay(1); //ウォッチドッグタイマ動作に必要
  }
}

連続動作のDMAはメインloopのCPU core 1で動かします。
WiFi およびUDP関連は core 0で動かします。
これはFreeRTOSのマルチタスクを使ったものです。
それについては過去の以下の記事も合わせて参照してみてください。

Arduino – ESP32 のマルチタスク ( Dual Core ) を試す

WiFi UDP関連のセットアップはCPU core 1のsetup関数で行わず、CPU core 0でセットアップを行うところが注意です。
taskUDPの優先度は最高の24にしました。
これはいろいろ変えて実験してみると良いと思います。

DMA等のシビアな連続動作はポーリングを避けて割り込みを使った方が良い

ポーリングという言葉は最近知ったのですが、メインloopやwhileループなどの無限ループ内で値を監視して、しきい値を超えたら動作させるようなプログラミングのことらしいです。

先ほど述べたように、それをDMAなどのシビアで高速な連続処理でやろうとすると、ウォッチドッグタイマ動作のためのdelay(1)を入れてしまうと処理が間に合いません。
よって、「割り込み」制御をした方が断然に高速処理ができて安定すると思います。
ただし、注意点として、割り込んだ先の関数内処理は、できるだけ短い時間の処理に留めることです。

GPIOの割り込みについてはArduino core ESP32のサンプルスケッチによる方法もありますが、私はESP32_Cameraライブラリを参考にして以下のように割り込みを使いました。
ESP32のGPIOのVSYNC端子で受けた電圧が、HIGHレベルからLOWレベルへ遷移した時に、割り込み処理が入る場合の概要です。

gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM);
gpio_isr_handler_add((gpio_num_t)cam_pin_VSYNC, &vsync_isr, NULL);
gpio_set_intr_type((gpio_num_t)cam_pin_VSYNC, GPIO_INTR_NEGEDGE);
static void IRAM_ATTR vsync_isr(void* arg){
  //vsyncレベルがLOWになった場合の処理
}

cam_pin_VSYNCが割り当てたGPIOピン番号です。
gpio_set_intr_type関数で割り込み制御がスタートします。
GPIO_INTR_NEGEDGEでHIGHからLOWレベルへ変化した場合としています。

その他、私はまだ勉強中で詳しくないので割愛します。

十分余裕のある容量の良質な電源を使う

今回の実験はM5CameraのイメージセンサOV2640のDMA制御と、大量の画像データをWiFi UDPで連続送信するため、M5Camera側の瞬間電流は460mA以上になる可能性があります。
平均的には160~200mAですが、瞬間的に大きな電流が流れて電圧降下が起きて、ESP32のCPU動作範囲電圧を下回ってしまう可能性があります。
そうするとフリーズする可能性が高くなります。
もしくはリセットしてしまうでしょう。

そうならないためにも、USB電源は良質で瞬時電圧降下でも耐えられる容量の充分大きい電源を使いましょう。
それと、USBケーブルも重要です。
安物で細くて長い粗悪なUSBケーブルを使うと、電圧降下で誤動作する可能性高いです。
先ほど紹介したような良質で太く短いケーブルを使うことをお勧めします。

コメント

  1. macsbug より:
    • mgo-tec mgo-tec より:

      macsbugさん

      コメントいただき、ありがとうございます。

      そのファンは以前Twitterで情報を頂いたんですが、その時は単体では売っていませんでした。
      今はもう単体で売っているんですね。
      私はAliexpressは使ったことが無いので、いつかAmazonかスイッチサイエンスさんで販売してほしいなぁ・・・と願って待っています。
      いつも有益な情報ありがとうございます。
      m(_ _)m

タイトルとURLをコピーしました