t-yosh’s blog

元ソフトウェアエンジニアが、モノづくりについて学んでいるブログです。モノづくりに必要なハードウェア・ソフトウェア・デザインのことを書いています。

I2C通信 デバッグ - M5Stack - 20180411解決

M5StackにADS1015(https://www.switch-science.com/catalog/1136/)をつなげて交流電流を測定しているのですが、どうも一定の確率でI2C通信が途絶えてデータが取れなくなる状態に陥ります。

使用しているライブラリはここのものです。

https://github.com/adafruit/Adafruit_ADS1X15)

 

プログラムからの再起動で復旧できたり、できなかったりと、不安定な動作をしていましたので、I2C通信ラインのデバッグをしていました。

結果的には読み込み命令の頻度が高すぎたことで問題が起きているようで、読み込み命令の後にdelayを入れることで様子を見ています。

 

以下、確認作業の履歴です。

 

I2Cを使う上での基本的な確認事項は以下です。

 (1) プルアップ抵抗の確認

 (2) 波形がなまっていないかの確認

 (3) I2C 制御の理解

 

(1)プルアップ抵抗の確認

 

f:id:t-yosh:20180304111200p:plain

ADS1015の回路図を見ると10Kが入っています。

 

(2)波形がなまっていないかの確認

f:id:t-yosh:20180304115630p:plain

波形自体は概ね良いかと思います。

 

(3)I2C 制御の理解

基本的なi2cの動作は以下がわかりやすかったです。

I2Cの低速通信について

基本の動作は上図の流れです。

 

ポイントは、スタートビット、ストップビットの判定がSCLがHの時に行われ、データはSCLがLの時に判定されるというところでしょうか。

 

最初の状態

SCLがH、SDAがH

 

スタートコンディション・ストップコンディション

通信の開始と停止のための信号

SCLがHの時に判断する。

 SCLがHの時、SDAが H →  L  : スタートコンディション

 SCLがHの時、SDAが L →  H  : ストップコンディション

 

データ 

スタートコンディションを認識すると、そのあとはSCLのLのタイミングでSDAをデータとして受信する。

 <データビットのW/R> LがWrite、HがRead

 <ACKビット>                 LがACK、HがNOACK

 

波形で見てみるとこんか感じです。

f:id:t-yosh:20180304122142p:plain

ACKの後に、一瞬Highが出ているのが気になりますが、エラーにはなっていないようです。

 

今回のデータ読み込み時の動作を確認します。

オシロプロトコル解析でI2Cデコードを行います。

f:id:t-yosh:20180304114928p:plain

f:id:t-yosh:20180304114752p:plain

 

 ー エラー時の状態 -

エラー時の状態を観察します。エラーが起こった時は、SCLのクロックが出たまま、SDAがHighになっています。

f:id:t-yosh:20180304111429p:plain

 

エラー発生前の状況

以下は、オシロでSDAがHの時間が10ms持続条件でトリガーをとりました。

f:id:t-yosh:20180304130943p:plain

 

状況としては、STOPコンディションを取りそびれて、データ送信モードが続いている状態に見えます。

 

ソフトリセットで再起動したあとの、エラー状態から復旧する時の波形が取れました。

f:id:t-yosh:20180304145217p:plain

f:id:t-yosh:20180304145405p:plain

ストップビットで復旧しているようです。

 

ソフトウェアでエラー検知時に再起動するのではなく、以下のコマンドを送ってみました。

<STOPビットを送ってみる>

Wire.endTransmission();

<W00を書き込んでみる>

delay(100);
Wire.beginTransmission(0x00);
#if ARDUINO >= 100
Wire.write((uint8_t)0x00);
#else
Wire.send(x);
#endif
Wire.endTransmission();
delay(100);

 

SDAにデータ信号は出力されませんでした。......................... orz

  

ここまで見たところで、動いている時の波形を見ていると、ずっと読み込みしていることに気づきました。そこで、連続読み込みせずに、delay(10)をいれたところ、エラー状態にならなくなりました。

 

あまりすっきりする感じではありませんが、ひとまずは安定して動いていそうなので、しばらく連続運転させて様子を見ることにします。

 

<20180411追記> 

問題解決しました。原因はESP32のソフトウェアにあったようです。Espressifのコミュニティサイトで検索していたところ、解決情報が上がっていました。

github.com

この人も色々波形を見たりしていたのですが、最後に「俺の試してよ」というコメント。

f:id:t-yosh:20180411201010p:plain

で、どうなったかというと

f:id:t-yosh:20180411201209p:plain

魔法みたいにうごいたよ!! It works like a charm!!

 

彼のソースコードは以下においてありました。必要なファイルだけ入れ替えれて、再ビルドするだけでよいです。

github.com

 

実際に私の環境でもI2Cの問題起こらなくなりました。30分に一回エラー出ていたのですが、1日中動かしていても問題なくなりました。

まさに魔法!!

☆パッチの内容まで確認できていませんので、参考になさる方は自己責任で確認してご利用ください。

 

参考

esp32 ハードウィア仕様書

https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf