ESP8266に手を出したワケ
今まで作ってきたボードはRaspberry Pi前提で、車両からCANデータを取得するものでした。ちょっと回路の間違いはあったけど一応動いている。でも、ボード単体でCANデータを送信できるようにしたり、ちょっとした解析ができれば、便利ではないかと思った。それには通信機能がついているマイコンが必要だ。
ここ1年くらいで急速に盛り上がってきたESP8266というWiFiチップがある。WiFiチップと言っても、Arduino IDEで開発できる単体マイコンでもあるから、他にマイコンは要らないわけだ。チップ単体だと500円を切っており、ヘタにArduinoボードを買うより安いというのも痺れる。
前回まで作っていたCANボードの搭載チップMCP2515はSPI接続だから、ESP8266のSPI APIを使おうとしたのです。
動かない・・・
ところが動かないんだなこれが。Arduino用のMCP2515ライブラリをESP8266で動くように移植していたのだが、テコでも動かない。レジスタも読めない。
ESP8266にはSPIとHSPIという2種類があるようなのだが・・・世間様の情報を見ても、なぜ2つあるのか全くわからなかったのだ。また、SPIにはArduino SDKでサポートされているArduino互換のSPI APIと、MetalPhreak: ESP8266_SPI_Driverの2種類あるのもなぞだった。
たまらず先人に質問したりしたのだが、接続等も間違っていないようだし。これはソフト的な問題なのか、それともチップ内部で使っているSPI接続(フラッシュメモリ)との競合なのか、などとと謎は増すばかり。
しかし、基板まで作っておいて手元にはテスター以外の計測器がなく・・・「わからないときはモノに聞け!」とばかりに宮仕え先のオシロをひっぱりだしてしまった。
ESP8266のSPI通信周りをオシロで確認した
まず、疑ったのはSPIのモード。SPI通信には4種類のモードがある。mbedのSPIマスターのWikiがまとまっている。Arduino ESP8266 SDKの標準SPIだとMODE0しかサポートしていないそうなので、MetalPhreak: ESP8266_SPI_Driverを使ってテストした。
ヘッダファイルのコメントには、
///////////////////////////////////////////////////////////////////
//
// Function Name: spi_mode
// Description: Configures SPI mode parameters for clock edge and
clock polarity.
// Parameters: spi_no - SPI (0) or HSPI (1)
// spi_cpha - (0) Data is valid on clock leading edge
// (1) Data is valid on clock trailing edge
// spi_cpol - (0) Clock is low when inactive
// (1) Clock is high when inactive
//
///////////////////////////////////////////////////////////////////
void spi_mode(uint8 spi_no, uint8 spi_cpha,uint8 spi_cpol)
こう書いてあるので自然と、
spi_mode(HSPI, 0, 0);
と書いてしまっていた。この状態でオシロでクロック出力を観察しようとすると・・・
信号!出てねえ!!
マジかよ。ちなみに緑がクロック、水色がスレーブ信号出力(MISO)です。SPI通信の場合、クロック供給はホスト側(マイコン)がやるのでクロックが出ていないのは明らかに異常・・・・だと思うのですがどうでしょう?
spi_mode(HSPI, 1, 0);
あ、これがArduino一般で言うところのMODE0じゃないのか?
spi_mode(HSPI, 0, 1);
んークロックが負論理になっててラッチ先行だからMODE2ですよね。
spi_mode(HSPI, 1, 1);
クロックが負論理で、シフト先行だから、MODE3ですよね。
おい!MODE1どこいった!!とにかくspi_mode(HSPI, 0, 0)だと動きそうにないことはわかった。ちなみにこの初期化をしない(デフォルト)で波形を観察すると、デフォルトはspi_mode(HSPI, 1, 0)のようです。なんかモヤモヤするけど、とりあえずの観察結果は以上です。MCP2515はMODE0とMODE3をサポートしているから、デフォルトでOKなのかしら(確認していない)
たぶん、何か勘違いしていると思いますが、現場からは以上です。
SPIとHSPIの違い
もうひとつの疑問。HSPIとSPIの違いは・・・実はよくわかりませんでした。速度差なのかな?と思って速度を調べてみました。
SPIのほうはArduino標準APIに沿っているので最大ホストクロックの2分周(DIV2)のようです。この場合の波形は以下のようになります。
1クロック(立ち上がり立下り)でだいたい150nsだから、周波数に直すと約6.6MHzですかね。まあ大半の用途では十分でしょう。
一方でMetalPhreak: ESP8266_SPI_Driverのspi_clock(HSPI, 1, 2);の場合は以下のような波形になりました。
60nsに2クロック入っているように見えます。だから周波数に直すと33MHzも出ているということになります。この設定では信号がかなり鈍ってしまってますので、実際に基板パターンをひきまわしてペリフェラルと33Mbpsで通信ができるとは限りませんが・・・確かに速いですね。
MCP2515の場合10MbpsまでサポートしていますからHSPIの方がよさそうです。デバイスにもよりますが画像取り込みもできる速度だと思います。意外とポテンシャル高いねESP8266。