Arduino – ESP32 大幅更新( 2018/06/28以降 )と I2C 不具合解決、その他気付いたこと

ESP32 ( ESP-WROOM-32 )

こんばんは。

今回は M5Stack に BME280 データを表示させる予定だったのですが、最新の Arduino core for the ESP32 ( 以下Arduino – ESP32 )の更新があまりにも大規模だったので、それの対応に追われました。
そこで、予定を変更して、更新された Arduino – ESP32 について気付いた点を報告したいと思います。

2018/06/28頃から、GitHub の Arduino – ESP32 が今もまだ大幅更新され続けています。
それにより、過去のスケッチが動かなくなったりしている可能性があります。

そこで、私が個人的に知る限りの 2018/07/07 までの不具合ポイントやその対策、改善されたポイントを紹介してみたいと思います。
あまりにも多量の更新だったため、以下で述べたことはすぐに変わってしまうかも知れません。
予めご了承ください。

因みに、Twitter でもツイートしましたが、前回記事で紹介した I2Cインターフェースのオシロスコープ波形の謎の中間電位は、私のうっかりミスで、オシロスコープの設定が誤っておりました。
大変お騒がせしました。
ド素人で申し訳ございません。
m(_ _)m

オシロスコープはたまに使うと、裏画面の設定チェックをすっかり忘れることがあるもんなんですね。
これを忘れると、測定結果がエライことになってしって、月日が経ってもそれに気づかず、誤ったデータで電子工作してしまうことになります。
この危険性を肌で知ることになりました。
これ、知らないと、とても怖い結果になりますね。
今後気を付けたいと思いますが、忘れた頃にまた同じ過ちをしそうです。
この記事で戒めとしておこうと思います。

では、自分なりに気が付いた今回の大幅更新で変わったことや不具合ポイントを説明してみます。
誤っているかもしれませんので、何かありましたらコメント投稿等でご連絡いただけると助かります。

スポンサーリンク

Wire ライブラリ( I2C インターフェース ) の大幅更新について

Arduino – ESP32 の Wire ライブラリはかなり以前から不具合がありました。
特に、温湿度・気圧センサーの BOSCH製 BME280 をI2C で使った時の不具合が顕著でした。
それをまとめるとこんな感じです。

●長時間測定していると、3時間後には測定不能になり、ACKエラーが出る。

●マルチタスクで他の SPI デバイスと混同して使うと、測定値の誤差が大きくなり、数時間後には測定不能になる。
しかし、シングルタスクで BME280 だけで測定すると誤差が少なく安定している。

前回記事で述べた、BME280からの波形乱れは先に述べたように私のミスで、実際は波形には問題ありませんでしたので、今までの BME280 測定不良の原因はこの2点に絞った問題が未解決でした。

そこで、GitHub のArduino – ESP32 のIssue で、chuck todd さん(ハンドル名: stickbreaker)はかなり以前から Wire ライブラリの不具合を指摘していて、独自の修正案を提案されていたようです。
かなり前から Wire ライブラリは不具合があったらしいですね。
それが、今回の Arduino – ESP32 の大幅更新で、chuck todd さんのその提案が取り入れられたということのようです。
(英語は苦手なので、Google 翻訳に頼りながら読んだので、経緯を間違えていたらゴメンナサイ。)

そして、前回の記事で述べた「こばさん」やt-yoshさんが対策されていた Wire.reset() 関数は、今回の大幅更新で消去されてしまいました。
おそらく、それが無くても対策ができたよ、という事だと思います。

そこで、私は期待を込めてコンパイル書き込み実行させてみたのですが、なぜか数十分したら esp32-hal-i2cがエラーを多量に吐き出し、測定不能になりました。
以前はこんなことなかったのに・・・。

しばらくはこのエラーは Arduino – ESP32 の大幅更新が原因だろうと思っていました。

しかし、GitHub Arduino – ESP32 の Issue で、 chuck todd さんが、マルチタスクでは Wire ライブラリは動作しないと述べられていました。
以下のページです。

I2C Interrupt problem since uprade espressif32 core to v1.1.0 #107

この多量の esp32-hal-i2c エラーログは、今回の大幅更新から表示されるようになりました。
このエラーコードで I2C パルスのリセット等をコントロールしているようにも見受けられます。

これより、私のコードを見返してみると、setup関数内で Wire.begin を実行していて、void Task1 という関数でcore 0 で実行していました。
setup関数はメインloop関数と同じ core 1 タスクなので、別タスクで動かしていたということになります。

通常、Arduino スケッチでは、setup関数内で全て初期化するというのが通例だと思いますので、Wireライブラリをマルチタスクで動かす場合は、気付かずに別タスクにしてしまう可能性が大ですね。
これについては今回、「ハッ」っと気付かされました。

以前、こちらの記事やこちらの記事で、GPIO からパルス出力をする実験をしました。
その時、シングルタスクでは波形の乱れが無かったのですが、マルチタスクで動作させると波形が乱れるということがありました。
この原因はちゃんと追究できていなかったのです。
もしかしたら私のオシロ設定を間違えていたかも知れません。
(いつか再実験をしたいと思っています。)

考えてみれば、マイコンでレジスタを直叩きしてパルス出力する場合、マルチタスクで GPIO から綺麗な波形を出力することは困難だろうと容易に想像できます。
すると、ワンチップマイコンの GPIO からのパルス出力はシングルタスク内に収めた方が良いと想像できます。

そう言えば、最近、本家Espressif Systems社から、ESP32-SOLO-1なるものが出ましたが、今頃シングルコア版バージョンを投入してきました。
私の勝手な想像ですが、マルチタスクの場合は GPIO 出力等でいろいろな問題があるので、シンプルにトラブルの少ないシングルコア版を出してきたのだろうと思います。
(あくまで個人的見解です)

また、Twitter でセマフォを使えないですか? という意見がありましたが、私は素人なので、この時初めてセマフォという言葉を聞きました。
排他制御のことなのですが、そのやり方はまだ知りません。
要は、私自身勉強不足で、FreeRTOS の使い方を知らないだけです。
いつか試してみたいと思います。

ということで、話を戻して、マルチタスク原因を確かめる為、Wire.begin関数と同じタスクに全ての Wire関数を置いて実験してみました。

すると、見事、I2C周波数 400kHz でも8時間計測してもエラーが出ませんでした!!!
バンザーーイ!!!

これ、もしかして、GPIO パルス出力ということを考えると、SPIライブラリ関数も同じことが言えそうです。
いつか実験してみたいと思います。

また、別件ですが、つい先ほど、こちらの記事のコメント欄で、「さや」さんから貴重な情報を頂きました。
実際の現場では、I2Cインターフェースの read 前の write の後は、STOPコンディションではなく、repeated start condition にした方が良いとのことです。
BME280 データシートには STOPコンディション又は repeated start コンディションと書かれているので、どちらでも良いのですが、「さや」さんがおっしゃるには、設計仕様書に書いてないと、STOPでリードアドレスまでリセットかけてしまうハードウェア設計者もいるかも知れないとのこと。
特にマルチタスクで複数デバイスを駆動する場合、STOPコンディションにしてしまうと、いろいろトラブルが予想されそうですね。
これは、実際のプロの経験でしか得られないご意見ですね。
私の様な独学素人ではこんな考えに及びませんでした。
とても貴重な情報ありがとうございました。
m(_ _)m
今後のプログラミングに生かしたいと思います。

では、いろいろと話が逸れましたが、私が確認した今回の大幅更新のポイントをまとめると、以下の感じです。

マルチタスクで使う場合、beginを含めたWire関連関数を全て同じタスクに入れ込むべし

Arduino IDE スケッチの場合、setup 関数はメインloop関数と同じ core 1 タスクです。
よって、Wire.begin を setup 関数内に置いたら、他全ての Wire 関数をメインloop内に置くことです。

また、xTaskCreatePinnedToCore関数でcore 0 タスクで動作させたい場合、Wire.beginからその他全ての Wire関数を
void Task(void *pvParameters)関数内に入れることが原則です。
例えば、こんな感じです。

void setup(){
.....
  TaskHandle_t th;
  xTaskCreatePinnedToCore(Task1, "Task1", 8192, NULL, 5, &th, 0);
}

void loop(){
.....
}

void Task1(void *pvParameters) {
  Wire.begin();
  while(1){
    Wire....
    Wire….
  }
}

Arduino – ESP32 のマルチタスクについては以下の記事を参照してください。

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

reset()関数が無くなった

2018/06/24版 までの Arduino – ESP32 では、Wire.reset()関数があって、トラブルをねじ伏せていましたが、6/28以降、reset 関数は消去されました。
Wireライブラリを同じタスクで使う限りにおいては、自動で I2C パルスをリセットする制御が入っているようです。
先に述べた、chuck todd さん(ハンドル名: stickbreaker)のコードが使われています。

requestFrom 関数の引数が変更になり、size_t型が無くなった

2018/06/24版までは、Wire.requestFrom関数の引数や戻り値に size_t 型が使われていましたが、最新版ではuint8_t や int型に変更されました。
size_t型は将来的にいろいろ問題あるかも知れないので、結果的に良かったと思います。
その分、過去のスケッチで size_t型を使っていた場合、コンパイルエラーが出ます。
その場合、size_t型を変更してください。
uin8_t型で良いと思われます。

また、別件ですが、I2Cデバイスアドレスを入力する引数が、なぜか uint16_t 型に変更されていたりしています。

APが見つからない場合のWIFI_OFF時の消費電流の大幅改善

以前のこちらの記事で紹介したように、Wi-Fiアクセスポイント(ルーター)に一度接続が成功して、その後、Wi-Fi のアクセスポイントが見つからない場合とか、ルーター電源をOFFにしていた場合、スケッチ内で WIFI_OFF を設定していても、なぜか消費電流が跳ね上がるという現象がありました。
アクセスポイントに接続できてさえいれば問題ありませんでした。

要するに、せっかくユーザー側でWIFI_OFF を設定しても、勝手にWi-Fiスキャンしに行っている感じです。
これは、ユーザーが操作できない領域でメーカー側のプログラムが勝手に動いていると思っていました。

でも、今回の大幅アップデートで、
WiFi.mode(WIFI_OFF);
を設定すると、アクセスポイントが見つからなくてもちゃんと OFF になったようです。
電流を測ってみると、ちゃんと抑えられていました。

この修正は有り難いですね。
省電力化にはとても有効だと思います。

WiFiClientSecureを使って SSLサイトから記事を取得し、その間、WiFi.mode( WIFI_OFF )と WiFi.begin の使用を繰り返すと、heap memory が減り続け、接続できなくなる現象が出ています。
以下の記事も合わせて参照してください。
ESP32 および M5Stack で数時間後に Web 記事取得失敗する問題について
(2018/09/25時点)

 

WiFiClientSecure およびDNSの新たな不具合

2018/07/10以降の最新版 Arduino – ESP32 で、WIFI_OFF時のアクセスポイントの再接続、および WiFiClientSecure による Web への再接続が 6/24以前と同様に正常に戻りました。

 

2018/06/24までの Arduino – ESP32 では問題無かったのですが、今回の大幅更新では、WiFiClientSecureライブラリを使った場合、以下の問題が新たに出てきました。

一度、WiFiアクセスポイントに接続成功し、SSLサイトからの記事取得に成功した後、ルーターの電源をOFF にし、アクセスポイントが見つからない状態にして、接続失敗させる。
その後、ルーターの電源をON にして、Wi-Fi接続成功して、NTPサーバーとの接続も成功するが、SSLサーバーに接続できない。
hostByName () で DNS Failed と表示される。

 

一度、Wi-Fi接続に失敗するとこういう状態になり、アクセスポイント接続できても、SSLサイトに延々と接続できません。

これは意外と近いうちに修正されると思いますので、気長に待とうと思います。

その他気になるところ

2018/06/24までは問題無かったのですが、しばらく M5Stack を起動し続けていると、謎の再起動してしまうことがあります。
これは調査中で何が原因かサッパリ分からないところがあります。

Arduino IDE の「ツール」メニューの「Core Debug Level」を「Verbose」にしていると、ログをシリアルモニターに吐き出している途中で再起動することがあります。
その場合は、「Core Debug Level」を「なし」にすると解消される場合があることが分かりました。
(2018/07/10)

 

編集後記

とりあえず、今のところ自分的に気付いた最新版( 2018/06/28~07/07まで)の Arduino – ESP32 の不具合や改善されたポイントを列挙してみました。

今回は、Twitter等でいろいろな方からご意見いただきました。
ホントにありがとうございます。
こういう方々がいて、今の自分がいるようなものです。
感謝感謝・・・。
m(_ _)m

あまりにも大規模アップデートだったため、未だに細かい修正アップデートされて続けています。
安定するまで今後もしばらく更新が続きますので、安定してから使用する方が良いかもしれません。

いずれにしても、これだけ頻繁に互換性が危うい更新を繰り返されると、ユーザーはなかなか大変ですよね。
自分もライブラリを作っている立場なので、気を付けて行こうと改めて思いました。

でも、互換性ばかり重視してしまうと、自由な発展ができなくなるので、その兼ね合いが難しいですね。
電子工作用途ならば、互換性を無視してドンドン発展してもらいたいですけどね。

ということで、今回はここまでです。

ようやく Arduino – ESP32 も安定しそうな気配なので、次回こそは M5Stack に BME280 のグラフを表示させてみたいと思います。

ではまた・・・。

Amazon.co.jp 当ブログのおすすめ

スイッチサイエンス ESPr Developer 32 Type-C SSCI-063647
スイッチサイエンス
¥2,420(2024/11/22 16:43時点)
ZEROPLUS ロジックアナライザ LAP-C(16032)
ZEROPLUS
¥19,358(2024/11/22 22:35時点)
Excelでわかるディープラーニング超入門
技術評論社
¥2,068(2024/11/23 14:03時点)

コメント

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