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:シリアル受信バッファを増やす »
「失敗」カテゴリの記事
- 工具は使ってみなきゃ使い勝手が分からない(2023.09.08)
- 危険じゃないけど、ちょっと待てっ! ポカリ入りめんつゆ(2023.07.03)
- 出窓:鯉のぼりを振れたらというリクエスト(2023.04.26)
- 回路設計はデータシートの熟読から。 スペックをちゃんと調べろ!(2022.09.28)
- Arduino IDEでRaspberry Pi Pico:millisをwordで処理した時の異常(2022.04.19)
「Arduino」カテゴリの記事
- Arduinoで「ボコスカハンマー」 あれれれれっ?!(2023.12.07)
- Arduino UNO R3で±19.9V表示電圧計(2023.10.14)
- 「御詠歌プレーヤー」の製作 (MP3-TF-16Pモジュールの使用例)(2023.08.10)
- Arduino UNO R3のソケット・・思えば違和感がぁ(2023.07.07)
- 初めて買ったArduino UNO・・・今は(2023.05.25)
「重箱の隅」カテゴリの記事
- C-MOS ICの入力ピンをオープンにすると(2023.11.01)
- トラ技の作図能力が落ちている・・・かもの続き(2023.10.31)
- トラ技の作図能力が落ちている・・・かも(2023.10.27)
- 不安な接続記号「●」(2023.06.07)
- トラ技Jr. 2023年春号(2023.04.12)
「ラズパイ・ピコ」カテゴリの記事
- Help me! ラズピコ、Philhower版だとスケッチをアップロードできない(2023.04.12)
- Arduino IDEでのラズピコ開発環境 Philhower版が正解でしょう(2023.04.04)
- ラズピコのピン:自由になりそうだけど定義で固定されている(2023.04.03)
- ラズピコで2chシリアル入出力のテスト(2023.03.30)
- Arduino IDEでのラズピコ開発環境(2023.03.29)
コメント