フェーズ2

E2-01 待ちで止まる問題を体験する:delayの限界を知る(なぜタイマが必要なのか)

シリーズ:実験シリーズ(フェーズ2)
対応ロードマップ:フェーズ2 / E2-01
今回の役割delay で待っている間、ほかの処理が止まることを体験し、タイマや周期処理が必要になる理由を理解する。

1. 目的

今回は、LED点滅をdelayで作ると、その待ち時間の間にボタン入力などの他の処理が行われないことを体験します。
これにより、次回以降の タイマで時刻を作る 理由を実感できることを目指します。

2. 前提・環境

  • 評価ボード:RTK7EKA8M2S00001BE
  • 開発環境:e² studio + FSP
  • 使用部品
    • タクトスイッチ 1個
    • LED 1個
    • LED用抵抗 1本
    • ジャンパ線
    • ブレッドボード
  • 前提
    • E1-05 ボタン入力でLED(ポーリング)が動いている
    • E1-08 デバウンスの考え方を軽く理解している
    • while(1)if が何となく読める

3. 今回の変更点

  • 配線:前回と同じ
  • FSP設定:前回と同じ
  • コード差分
    • ボタンを読んでLEDを変える処理は残す
    • その上で、長めの delay を入れた点滅処理 を追加する
  • ねらい
    • 「LED点滅はしている」
    • でも「ボタンの反応が鈍い/押してもすぐ反応しない」
    • という状態をわざと作る

4. 手順

4-1. まず今回やりたいこと

今回は、1つの while(1) の中で次の2つを同時に行います。

  • LEDを一定間隔で点滅させる
  • ボタンが押されたら、別のLED動作をさせる

一見できそうですが、点滅のために長く待ってしまうと、その待っている間はボタンの状態を見に行けません。
これを実際に確認します。

4-2. 配線

配線は、E1-05 で使った ボタン入力+LED出力 と同じでOKです。
新しい部品は増やしません。

4-3. コードを書く

最小構成の例です。

#include "hal_data.h"
#include <stdbool.h>

#define WAIT_MS   (700)

static bool led_state = false;

void hal_entry(void)
{
    R_BSP_PinAccessEnable();   // R_BSP_PinWrite / PinRead を使用可能にする
    
    while (1)
    {
        /* 1. LEDを点滅させる */
        led_state = !led_state;
        if (led_state)
        {
            R_BSP_PinWrite(BSP_IO_PORT_04_PIN_09, BSP_IO_LEVEL_HIGH);
        }
        else
        {
            R_BSP_PinWrite(BSP_IO_PORT_04_PIN_09, BSP_IO_LEVEL_LOW);
        }

        /* 2. ここで長く待つ */
        R_BSP_SoftwareDelay(WAIT_MS, BSP_DELAY_UNITS_MILLISECONDS);

        /* 3. 待ち終わってから、ボタンを1回だけ読む */
        bsp_io_level_t stable_sw_level;
        stable_sw_level = R_BSP_PinRead(BSP_IO_PORT_07_PIN_04);

		/* 4. 押されていたら、100msだけ点灯する  
			Active-Low前提 */
        if (BSP_IO_LEVEL_LOW == stable_sw_level)
        {
            R_BSP_PinWrite(BSP_IO_PORT_04_PIN_09, BSP_IO_LEVEL_HIGH);
            R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
            R_BSP_PinWrite(BSP_IO_PORT_04_PIN_09, BSP_IO_LEVEL_LOW);
        }
    }
}

4-4. 実行して観察する

次を順に見ます。

  1. LEDが 700ms ごとに点滅しているか
  2. 点滅の途中でボタンを押したとき、すぐ反応しないことがあるか
  3. ボタンを短く押したとき、反応しないことがある
  4. ボタンを長めに押すと、やっと反応しやすいか

4-5. 待ち時間を変えて比較する

WAIT_MS を変えて比べます。

  • 100
  • 300
  • 700
  • 1000

このとき、待ち時間が長いほど、ボタンの反応が悪くなりやすいことを確認します。

5. 結果

5-1. 期待する結果

たとえば WAIT_MS = 700 では、次のようなことが起きやすいです。

  • LEDの点滅は確認できる
  • ボタンを押した瞬間には反応しない
  • タイミングによっては、短く押した入力を取りこぼす
  • 長めに押したときだけ反応しやすい

5-2. 何が起きているのか

今回のポイントはここです。
delay は「少し待つ」ために便利ですが、
待っている間、CPUはその場から先へ進みません。
つまり、今回のコードでは

  • LEDを変える
  • 700ms待つ
  • そのあとで、ボタンの状態を確認する

という流れです。
そのため、700ms待っている間は、ボタン入力を確認できません。

5-3. 今回の実験で分かってほしいこと

delay は、LEDを点滅させるだけのような単純な動作を試すときには便利です。
しかし、ボタン入力などの他の処理も一緒に行いたい場合は、待っている間にそれらの処理を行えません。
そのため、長い delay を使うと、待ち時間の間は他の処理が行われないことが問題になります。
これはフェーズ2で「待ち時間でも処理を止めない土台」を作る理由そのものです。

6. ハマりポイント/原因と対策

6-1. ボタンを押してもまったく反応しない

原因

  • ボタンの配線が違っている
  • 入力ピンの設定が違っている
  • 押したときの判定が逆になっている

対策

  • まずは E1-05 の「押したらLEDが変わる」コードに戻す
  • その状態でボタンが反応することを確認してから、今回の delay の処理を追加する

6-2. 反応が悪いのか、配線ミスなのか分からない

原因

  • 今回は、わざとボタンの反応が遅れやすいコードにしているため、本当に間違っているのか迷いやすい

対策

  • WAIT_MS = 100WAIT_MS = 1000 を比べる
  • 待ち時間を長くしたときだけ反応しにくくなるなら、配線ミスではなく delay の影響と考えやすい

6-3. たまに反応するので、かえって分かりにくい

原因

  • ボタンを読むタイミングと、たまたま合ったときだけ反応している
  • 短く押すと読み逃しやすく、長めに押すと反応しやすいことがある

対策

  • これは今回の実験ではむしろ正常です
  • すぐ反応しないこと自体が、delay の影響を表している

6-4. for 文の空回しで待ちを作ったら挙動が安定しない

原因

  • 何もしないループで待つ方法は、環境によって時間が変わりやすい
  • 書き方によっては、思った通りの待ち時間にならないことがある

対策

  • 今回は R_BSP_SoftwareDelay() を使う
  • まずは時間の正確さよりも、「待っている間は他の処理を行えない」ことを見る

7. まとめ

今回の実験で確認したいのは、delay で待っている間は、他の処理は行われない ということです。

そのため、LED点滅だけなら簡単でも、

  • ボタン入力も見たい
  • ログも出したい
  • 将来はセンサやサーボも動かしたい

となると、delay だけでは限界があります。
このため、次回は、「今何msか」を自分で管理するための土台として、タイマで時刻を作る方向へ進みます。

8. 次回やること

タイマを使って 1msごとの基準時刻 を作り、待ち時間でも他の処理を止めない土台を作る。

9. 関連リンク

  • 基礎:delayの限界(なぜタイマが要る?)
  • 基礎:組み込み開発とは?
  • 基礎:C言語のはじめ(LED点滅で必要なところだけ)
  • 基礎:マイコンとは?RA8M2でLEDを点滅するための超入門
  • 実験:E1-05 ボタン入力でLED
  • 実験:E1-08 ボタン入力を安定させる(デバウンス)

-フェーズ2