Arduino IDEでRaspberry Pi Pico:32bitマイコンがバグを生む
Arduino UNOの「int」は16ビット。
それがRaspberry Pi Picoになると「int」は32ビットに。
Arduino UNOだとついついRAMをケチりたく
なって、255までの数値でOKなら「byte」でと
「スケッチ」を書いてしまいます。
8ビットで済むところをwordやintにするのは
もったいない・・・ はい。ケチです。
そんな考えで作ったプログラムをPicoに持って
くると思わぬ「バグ」が生じます。
・Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す
このスケッチ中で使っている時間待ちルーチン。
「bkdelay」という名で、1ms単位の時間待ちをしている途中、
シリアル入力があったら時間待ちを中断するという機能を
持たせています。
1秒待ちなんかしてる時に、「もぅエエからはよ終わろうぜ」
に対処します。
さて、この時間待ち。
割り込みを使わずに管理するとなると、millisを呼び出して
時間経過をチェックするという処理になります。
millisは32bit値で最大1193時間、50日ほどを計時できます。
「そんな長いこと待たへんのんで16bitでエエやん」と
ケチるわけです。 (16bitだと65秒)
その「ケチな考え」が32bit CPUでバグを生んでしまいます。
今回のルーチン。
/***** Break処理付のdelay *****/
// シリアル受信あればdelayを中断
void bkdelay(word dly)
{
word tn, t;
tn = (word)millis(); // now
while(1){
t = (word)millis(); // 経過
if((word)(t - tn) >= dly) break;
if(Serial.available()) break; // 受信データ
}
}
目標待ち時間dlyと経過時間(t - tn)を比較している
んですが、すべて16bit値で計算していました。
※Arduino UNOだから。
※UNOの時は(word)を付けてなかった。
※(t - tn)、符号無しwordだとtとtnの大小が逆に
なっても差の値は正しく出てきますんで。
ところが、Picoは32bitで内部処理。
16bitで減算して比較するつもりが、32bit値に型変換され
てから比較されるのです。
※「暗黙の型変換と符号拡張」というヤツです。
tとtnの大小が逆になったらマイナスになってしまいます。
tnの値によっては、いつまでたってもdlyを越えることが
できません。
ということで、減算式(t - tn)の前に付けた
キャスト演算子(word)。
これを忘れると動かないわけです。
※教訓:32bitマイコンはRAMをケチるな!
ちゃうちゃう。
「暗黙の型変換と符号拡張」に注意!ということで。
※millis時間判定の異常、検証用スケッチの紹介
・Arduino IDEでRaspberry Pi Pico:millisをwordで処理した時の異常
| 固定リンク
« Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す | トップページ | Arduino IDEでRaspberry Pi Pico:A/D入力が…あれっ? »
「失敗」カテゴリの記事
- カップ麺 だし汁漏出騒ぎ(2024.11.11)
- ステッピングモータ駆動回路を24Vだけで #2(2024.10.31)
- アマゾンで買ったユニバーサル基板:失敗だぁ(2024.09.13)
- 工具は使ってみなきゃ使い勝手が分からない(2023.09.08)
- 危険じゃないけど、ちょっと待てっ! ポカリ入りめんつゆ(2023.07.03)
「Arduino」カテゴリの記事
- Arduino UNO R3で周波数を計る(2025.05.16)
- Arduino UNO R3のクロック精度を1MHzパルスで確かめる(2025.04.28)
- Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMの例(2025.03.22)
- パルスジェネレータをI2C液晶で動かす(2025.01.28)
- EEPROMを使ったシリアル受信バッファ 512kバイトに増設(2024.12.26)
「重箱の隅」カテゴリの記事
- 1/1023監視団 活動中!(2025.03.10)
- DIPのLMC6482えらい高くなった(2025.03.07)
- 因縁のボリューム記号 トランジスタ技術2025年3月号(2025.02.17)
- ボリューム記号のボヤキ、トラ技2025年3月号の別冊付録に再掲載(2025.02.10)
- NECは3段タイプの発振回路をすすめてる(2025.01.31)
「ラズパイ・ピコ」カテゴリの記事
- Arduino UNO R3のクロック精度を1MHzパルスで確かめる(2025.04.28)
- トラ技2024年5月号に「3.3/65535」(2024.04.07)
- ラズピコだと1/65535が出現(2024.03.30)
- Help me! ラズピコ、Philhower版だとスケッチをアップロードできない(2023.04.12)
- Arduino IDEでのラズピコ開発環境 Philhower版が正解でしょう(2023.04.04)
コメント
while(1){
t = (word)millis();
if((word)(t - tn) >= dly) break;
if(Serial.available()) break;
}
とせずに、
t = (word)millis() - tn;
if(t >= dly) break;
if(Serial.available()) break;
こうすれば(word)のキャストがなくてもOK。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2022年4月14日 (木) 17時33分