Arduino IDEでRaspberry Pi Pico:millisをwordで処理した時の異常
2022年4月14日:Arduino IDEでRaspberry Pi Pico:32bitマイコンがバグを生む
この検証用スケッチを書いてみました。
/***** millisを使った時間待ち *****/
// uint32_tではなくwordで
word ms_0;
word ms_1;
void delay2(word dly)
{
ms_0 = (word)millis(); // 開始値
while(1){
digitalWrite(2, HIGH); // テスト用パルス出力
ms_1 = (word)millis(); // 現在値
if((ms_1 - ms_0) >= dly) break; // ★1 時間経過
// if((word)(ms_1 - ms_0) >= dly) break; // ★2
digitalWrite(2, LOW);
}
}
/***** SETUP *****/
void setup() {
Serial.begin(9600); // TX
pinMode(2, OUTPUT); // PD2
pinMode(3, OUTPUT); // PD3
pinMode(LED_BUILTIN, OUTPUT); // LED
}
/***** LOOP *****/
void loop() {
byte f_xLED = 0; // LED点滅用
word cnt = 0; // loopカウンタ
char tx_bff[64]; // 送信文字列
while(1){
f_xLED ^= 1; // LED トグル
digitalWrite(LED_BUILTIN, f_xLED);
delay2(1000); // 1000ms wait
sprintf(tx_bff, "#%4d %5u %5u",
cnt, ms_1, ms_0);
Serial.println(tx_bff); // 改行
cnt++;
if(cnt > 9999) cnt = 0;
}
}
★1 と ★2の違いが重要。
★2は引き算結果を(word)でキャストしています。
Arduino UNOで動いていた<★1>の処理、
これをRaspberry Pi Picoに持ってくると、
cnt ms_1 ms_0
# 61 62002 61002
# 62 63002 62002
# 63 64002 63002
# 64 65002 64002 ←ここまで動いて停止
数値の比較ができず(32bitのマイナス値になる)、
時間待ち関数から抜け出せません。
これを<★2>のようにすると、Pi PicoでもArduino UNO
でもオーバーフロー発生部分を無事に通過できます。
こんな具合。
cnt ms_1 ms_0
# 63 64002 63002
# 64 65002 64002 ←ここで止まっていたのが、
# 65 466 65002 (65536+466=66002) 通過
# 66 1466 466
# 67 2466 1466
# 68 3466 2466
符号なし16bit値同士の減算、オーバーフローが起こっても
16bitならうまく「差」が算出されます。
「466 - 65002」は16進だと「01D2 - FDEA」。
「01D2 - FDEA = FFFF・03E8」となり、不要な上位の
「FFFF」は捨てられて下位の16bit値、「03E8」が出てきます。
16進の03E8は10進で1000。
ちゃんと1000ms待ちが動きます。
それが32bitマイコンだと「暗黙の型変換と符号拡張」 が悪さをして、
「01D2 - FDEA = FFFF・03E8 = -64536」とマイナスの値になって
しまいます。
※符号なし16bit = word = uint16_t で比較されるつもりが
符号付の long = int32_t (32bitマイコンでは int だ) で
比較が行われるのです。
結果、1000msの経過がチェックできません。
今回の例では、減算値ms_0は65002と固定されています。
ms_1が0~65535の間を変化しても、1000を越える値は出てきません。
いつまでたってもこのdelayルーチンから抜け出せないのです。
このスカタンの場合、65秒ほど経てば「あれ? なんかおかしい」
と気が付くわけですが、もっと複雑な処理で、異常の出現まで
時間がかかるような場合や、条件が重なった時だけ発生する
ものだと、むちゃ怖いバグになってしまいます。
8bitマイコンで正しく動いていたルーチンを32bitマイコンに
持ってくると、転けてしまって動かない。
よく考えておかないと、こんなことが現実に起こります。
「暗黙の型変換と符号拡張」 、昔のルーチンを借用する時は
どうぞ気をつけてください。
| 固定リンク
« Arduino IDEでRaspberry Pi Pico:BSch3V部品ライブラリ | トップページ | Arduino IDEでRaspberry Pi Pico:シリアル受信バッファを増やす »
「失敗」カテゴリの記事
- 今日の失敗:ABS樹脂ケースに穴を開けたらホルソーが詰まったゾ(2026.01.15)
- 買ってはダメ! コーナンLIFELEXリピート型結束バンド(2025.08.17)
- カップ麺 だし汁漏出騒ぎ(2024.11.11)
- ステッピングモータ駆動回路を24Vだけで #2(2024.10.31)
- アマゾンで買ったユニバーサル基板:失敗だぁ(2024.09.13)
「Arduino」カテゴリの記事
- ATtiny1614:タイマレジスタの初期設定を見る(2026.01.06)
- ラジオペンチさんの「ダイソーのゆらゆらLEDキャンドルライト」#2(2025.09.15)
- ラジオペンチさんの「ダイソーのゆらゆらLEDキャンドルライト」(2025.09.11)
- ATtiny402サンプル:"Wire.h"を使わずI2Cで液晶表示 AQM1602だと(2025.09.09)
- ATtiny402サンプル:I2Cで液晶表示 SCL周波数を設定できるようにしたら(2025.09.09)
「重箱の隅」カテゴリの記事
- 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)


コメント