前回上手くいかなくて断念したが、原因が分かったので、まとめてみる。
上手くいったスケッチは、ここにあげておく。
動作した風景はこんな感じ。(著作権に配慮し波形だけです。)
上手くいかなかった原因は、ひとえにArduinoが遅いと言うことに尽きる。
入門用マイコンで遅い早いというのはナンセンスなのだが、
Arduinoでは、本来色々考慮しなくてはいけないところを上手く遮蔽して、
私のような初めてマイコンを触る人でも、何となくコードを書いて動くようにしてある。
本来、マイコンはブートローダを書き込むだの開始アドレスがぁとかLチカする前のお膳立てで挫折する人が多いと思う。自分もそうだし。
(ちなみにArduino UNOのマイコンであるAVRはわりと早い部類に入るので、マイコン自体が遅い訳ではない)
PCのソフトの感覚だと、最終的にコンパイルされるので、速度差は顕著に出ないと思ったが、
マイコンの世界ではPCの感覚は通用しない。1命令1クロック。(AVRの場合。http://ja.wikipedia.org/wiki/Atmel_AVR)少ないクロック数(=命令数)で如何に動かすかの世界なのだ。オマケにメモリも少ない。
例えば、デジタルポートをHIGHにするには、Arduinoでは
digitalWrite(BSYNC,HIGH);のようにするが、AVRのGCCに実はdigitalwriteなどという命令は無い。
実際のコードは以下のようになっている。(arduino-1.0.1\hardware\arduino\cores\arduino\wiring_digital.cより)
void digitalWrite(uint8_t pin, uint8_t val) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); volatile uint8_t *out; if (port == NOT_A_PIN) return; // If the pin that support PWM output, we need to turn it off // before doing a digital write. if (timer != NOT_ON_TIMER) turnOffPWM(timer); out = portOutputRegister(port); uint8_t oldSREG = SREG; cli(); if (val == LOW) { *out &= ~bit; } else { *out |= bit; } SREG = oldSREG; }では、本来はどうなのかというと、
*out_bsync |= bit_bsync;で済んでしまう。 (ピン定義とかは省略)
しかし、Arduinoのすばらしいのは、スケッチにAVR-GCCのコードが書ける(混在できる)という点。
つまり、Arduinoで一通りのことをやったら、次のステップとして、
スケッチの一部をAVR-GCCの関数に置き換えるとか出来るのである。
前回上手くいかなかったのは、
- 配列にmp3データを展開していたので、そもそもメモリが不足していた(可能性がある)
- shiftout命令が遅すぎて、転送が間に合っていなかった。
この2点のようだ。
いやぁ、マイコンは奥が深い。昔々メモリが少なかったDOSの時代とは違う面白さがある。
ディスプレイなど当然無いので、再起プログラム書いてもOut of Memoryなんて出ずに暴走するし。
ステップ実行なんてシミュレータでもないと無理だし。
0 件のコメント:
コメントを投稿