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:シリアル受信バッファを増やす »
「失敗」カテゴリの記事
- カップ麺 だし汁漏出騒ぎ(2024.11.11)
- ステッピングモータ駆動回路を24Vだけで #2(2024.10.31)
- アマゾンで買ったユニバーサル基板:失敗だぁ(2024.09.13)
- 工具は使ってみなきゃ使い勝手が分からない(2023.09.08)
- 危険じゃないけど、ちょっと待てっ! ポカリ入りめんつゆ(2023.07.03)
「Arduino」カテゴリの記事
- 1/nカウント方式とDDS方式の2相パルス発生回路(2024.10.13)
- おっと。map関数の計算桁に注意(2024.10.06)
- DDS方式の2相パルス発生回路、周波数スキャン機能を付ける(2024.10.05)
- 1クロックでも速くしたい 割込を「ISR_NAKED」で(2024.09.30)
- 1クロックでも速くしたい DDS方式の2相パルス発生器(2024.09.27)
「重箱の隅」カテゴリの記事
- ステッピングモータ駆動回路を24Vだけで(2024.10.29)
- おっと。map関数の計算桁に注意(2024.10.06)
- リターンパスの無いオペアンプ入力回路(2024.05.31)
- サーミスタでの温度測定、「inf」の出現に耐えられるか?(2024.05.13)
- I2C液晶のアクセス、割り込みで処理しないようにすると(2024.04.12)
「ラズパイ・ピコ」カテゴリの記事
- トラ技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)
- ラズピコのピン:自由になりそうだけど定義で固定されている(2023.04.03)
コメント