9月 12, 2020

ArduinoのSPIが上手く動かなかった話(解決?済)

結論:SPIの信号線を完全に分離しろ。

以前、Arduinoで二酸化炭素計を作ったのですが、最近どうも動きが怪しい。 PCに繋いだ状態で、シリアルモニタを有効にしていないと動かず、スタンドアロンでは動作しない状態でした。 シリアルモニタで状況を見ると動いて、状況を見ないと動かない・・・。まるで開発環境では動くのに、本番環境では動かないという良くあるアレです。
しかし、本当にこれでは困るので、なんとかしてスタンドアロンの状態で動作状況を確認したい。ということで、以前から購入していたものの使っていなかったLCDを追加して、状況表示をすることにしました。
使用するLCDは、PCD8544。Nokiaの携帯電話5110で使われていたディスプレイのため、5110という型番で呼ばれることも多いようです。
同じ液晶を使用している方のブログを参照してみると、液晶はだいたい同じなのですが、液晶が実装されている基板が異なるようで、ピンの番号や順番に違いがあるようです。このあたりは、手元にある部品のシルク印刷と照らし合わせながら合わせていきます。

そして実装。

これが、なぜか動いたり動かなかったりする。
正確には、最初は動くんだけど、すぐに動かなくなってしまう。
この症状には見覚えがあります。Arduinoのメモリが不足して処理が途中で転けているパターンです。
イーサネット&SDカードシールド、温度湿度気圧計、二酸化炭素計を搭載して既にライブラリでメモリがカツカツのところに、LCDのライブラリまで入ってきて、メモリが70%以上を消費しています。
LCDだけで動かすと問題が無いので、これはメモリ不足で間違いないと予測して、DHCP処理を外したり、ローカル変数で必要なメモリ量が動的になり後から必要になるメモリ量が読めない部分をグローバル変数にしてみたり、色々やってみたのですが、一向に解決しませんでした。

違う原因ではないかと、色々検索していたところ、別の機材とイーサネット&SDカードシールドの組み合わせで上手く動かないという現象と解決方法でした。
Arduinoのイーサネット&SDカードシールドと、PCD8544はSPI(Serial Peripheral Interface)という仕組みでArduino本体と通信をしています。
これは信号線とタイミング用のクロック線を共有し、相手先選択の線を利用して、通信相手を決定するというものです。

シリアル・ペリフェラル・インタフェース - Wikipediaより SPI three slavesen:User:Cburnett / CC BY-SA
  • MOSI(Master Out Slave In)
  • MISO(Master In Slave Out)
  • SCK(Serial Clock)
  • SS(SlaveSelect)
MOSI、MISO、SCKの3本を共有し、SSを機器別に1本ずつ用意してやれば、機械が一台増えるごとにSSを1本追加するだけでピンの数が節約できるというものです。
実際、イーサネット&SDカードシールドは、3本を共有し、残り2本のSSでSDカードとイーサネットの通信を切り替えているそうです。
ここで、PCD8544も同様に3本を共有し、PCD8544用のSSを1本追加して実装していたのですが、上手く動かないと書いていたブログでは、完全に信号線を分離したことで解決したと書かれていたので、こちらも分離してみることにしました。

あっさり稼働。
どうも、イーサネット&SDカードシールドのSPIに癖があるようです。
ということで、使用ピン数もだいぶギリギリの中、なんとか一台のArduinoの中に組み込むことができました。

ただ、シリアルモニタを開けないと動作しない点については、まだ何も解決していないのですが・・・。

0 件のコメント:

コメントを投稿