Introduction: Edisonプログラミング

About: 組み込み系システム、ガーデニング、ドローンに興味あり

ドローンでも作ってみようかとEdisonを購入していじってみた記録

(が、早々に方針を転換しました)

Step 1: Edison MCUプログラミング

mcuプログラムでdebug_print文で継続的に出力を行ったらCPU自体の処理が重くなり無線LANへの接続もままならなくなった。USBケーブルでシリアル接続するとなんとかコマンドは打てるが反応が鈍い。どうにかしてMCUにダウンロードしたプログラムを削除したいところ。

ディレクトリを探したところ、MCU関連では次のようなディレクトリを発見した。

/etc/intel_mcu

/sys/devices/platform/

/lib/firmware/

これらのうち、/lib/firmware/を見ると、

root@edison:/etc/intel_mcu# ls -la /lib/firmware/
drwxr-xr-x 2 root root 4096 May 5 05:16 .

drwxr-xr-x 8 root root 4096 Jun 19 2015 ..

-rw-r--r-- 1 root root 464927 Jun 19 2015 fw_sst_119a.bin

-rw------- 1 root root 13100 May 5 05:16 intel_mcu.bin

こんな感じ。intel_mcu.binがダウンロードしたバイナリっぽい。ダメ元でこれを削除して、ボードを再起動したところ復活した。

debug_printの大量の出力には注意が必要。

Step 2: Time_usの不具合

MCUをプログラミングしてみたものの、どうも怪しげな動作をする。

mcu_delayやtime_us関数が期待通り動作しない。どうやらメインCPUとデータをやり取りすると、経過時間のカウンタが大幅に増える(それも何秒分も)。ググってみると、インテルのディスカッションに類似のやり取りを見つけた。2016年2月の時点で未対処、5月6日にファームや開発環境(Mac)を最新化したものの、事象は変わらず。

これではmsecオーダでのリアルタイム処理を求めるような制御システムには使えない。

対処にこれだけ時間がかかっているところを見ると、ハードウェアレベルの問題なのか、もともとそのようなリアルタイム処理向けを重要視していないものなのだろう。

方針転換して、ArduinoやPICでの制御を考えることにした。

Step 3: SPI

Edisonにmraaを使って3軸センサMCU-9250の接続を試みた。

I2Cは容易に接続できたが、SPIでは接続できず。原因は不明のまま。

その過程でSPIの仕様を色々調べてみた結果、MCU-9250にはI2Cを使う方が良さそう。理由は次の通り。

[SPIの仕様]

・I2Cと違って、受信データは送信データとタイミングを取れない。例えば、MCU-9250に向かって読み取りレジスタアドレスを送信しても、次のバイトデータで情報を取得できるとは限らない。

・全二重なのでストリームデータを流すような送受で独立な通信に向いている。

[MCU-9250の仕様]

・SPIを使った通信方法の情報が少ない。

・マニュアルを見る限りではどのようにすればI2Cのようなバーストデータの取得ができるか不明。一つずつレジスタを指定していたのではスループットが落ちてI2Cと大差なくなる(SPI 1MHz,I2C 400kHz)

・SPIから磁気センサへのアクセスするはMCU-9250に内蔵されているI2Cマスター機能を使わなければならず煩雑。

<追記>

saleaeのロジックアナライザLogic4を購入したので動作を確認した。

mraaのwriteByteでは8クロックのみが出力され受信ができていない。

------------ writeByte --------------

mraa_spi_context spi_context = mraa_spi_init_raw(5,1) ;

mraa_spi* spi = new mraa::Spi( spi_context ) ;

spi->frequency(1000000) ;

spi->mode( mraa::SPI_MODE0 ) ;

spi->lsbmode(false) ;

uint8_t reg = 0x75 | 0x80 ;

uint8_t rx ;

spi->writeByte(reg) ;

int k ;

for( k = 0 ; k < 4 ; k++){

rx = spi->writeByte(reg) ;

}

transferを使ってもセンサーから返る値は安定しない。

------------ transfer --------------
mraa_spi_context spi_context = mraa_spi_init_raw(5,1) ;

mraa_spi* spi = new mraa::Spi( spi_context ) ;

spi->frequency(1000000) ;

spi->mode( mraa::SPI_MODE0 ) ;

spi->lsbmode(false) ;

uint8_t reg = 0x75 | 0x80 ;

uint8_t data[4] = { 0xF5, 0x80, 0x80, 0x80 } ;

uint8_t rxBuf[4] ;

spi->writeByte(reg) ;

if (spi->transfer(data, rxBuf, 4) == mraa::SUCCESS) {
;

};

Step 4: PICとのI2Cレベル変換ICによる接続

EdisonのI2Cは1.8V、これに3.3VのPICのI2Cに接続するために、レベル変換IC(PCA9306)を利用した。購入したのは秋月のAE-PCA9306。秋月の説明書には記載がないが、VREF2側を高電圧側(このケースではPIC)に接続する必要があることに注意が必要。

Edison (breakout board)にはプルアップ抵抗が実装済みなので、AE-PCA9306のプルアップ抵抗を無効(パターンを切断)しなければならない。また、PIC側(VREF2側)のプルアップ抵抗(1kΩ)をそのまま使ったところ正しく動作しない。Edison側の信号を見てみるとSDAがLOWに落ちるものの続くシーケンスが進んでおらず、アナログ信号の変化も不十分である。PIC側の電圧が十分に下がらずPCA9306がPIC側がHレベルであると誤認しているようである(一つ目の写真)。このあたりについては、こちらのサイトに詳しい。

PIC側のプルアップ抵抗のパターンも削除して波形を観測すると正しく動作した。ただしPIC側はプルアップしないとHレベルは1.8V程度なのでこのままでは通信できない(二つ目の写真)。PIC側に4.7kのプルアップをSCLとSDAに接続したところレベル変換もできるようになった(三つ目の写真)。通信速度も400kHz程度でている。

Step 5: I2Cレベル変換トラブル

maraのI2C readByteでPICをslaveとしたデータを読み取ろうとしたら、0x80は読めても0x70が読めない。MSBがHIGHかLOWの違いでクロックが再開しない(一つ目の図)。SDAがなぜSCLに影響を与えているか(STOPビットとして誤認?)はわからないが、I2Cレベル変換IC(PCA9306)について詳細に解説したサイトがあった。これによると、コンデンサを挿入すると改善する可能性があるらしい。

この事象もタイミング問題のように思われるので、スレーブ側(PIC側3.3V)にコンデンサ100pFを、SCLとSDAに挿入したところ正しく動作するようになった。(二つ目の図)

三つ目の図はスレーブ側のコンデンサ挿入後の波形であるが、ピークの電圧が2.1V程度まで下がっており、最低基準の2.0Vギリギリである。一つ前の記事で記載したようにプルアップ抵抗4.7kΩでは100pFよりもやや小さい方が望ましい思われる。

計算上は、4.7kΩ x 100pFの時定数は0.47μsec(3.3Vx63%=2.1Vに到達する時間)、I2C 400kHzの周期は2.5μsec(Hレベルの保持期間は1/4の0.625μsec)となるが、これよりは実際の時定数は長いようである。

PCA9306は双方向であるがために挙動が難しく、プルアップ抵抗やコンデンサを注意深く調整する必要なようだ。

Step 6: PWM

サーボ(ESC)を制御するためにPWMを使う。mraaでは次のようなコードだけで制御できるので簡単。

mraa::Pwm* pwm = new mraa::Pwm(14); // pin14 is PWM1

pwm->period_ms(50) ;

pwm->enable(1) ;

pwm->write(0.1) ; // 10%

sleep(5) ;

pwm->write(0.5) ; // 50%

なお、コンストラクタで設定するpin番号は物理的なピン番号です。14番ピンはPWM1になります。

periodはPWMの周期です。が、こちらのサイトにも記載されているように、50msecを指定しても正確に50msecにはならず、54.613msecになります。実際ロジアナで見てみてもその値でした。サーボ制御くらいなら問題ないかもしれませんが、正確な組み込み制御にはEdisonは不向きかもしれません。

また、当然ながら、Edisonのロジックレベルは1.8Vなので、サーボ(ESC)との接続にはレベル変換(3.3V/5V)が必要です。