LoginSignup
0
1

More than 1 year has passed since last update.

RaspberryPi pico TimerによるLチカ

Last updated at Posted at 2021-05-19

はじめに

前回はC言語の環境構築とサンプルのLチカを実施しました。
今回はTimerを使用してLEDを点滅させます。

仕様

LED点灯→LED消灯→LED点灯→LED消灯を繰り返す。
点灯と消灯している時間は500msとする。

ソース

#include <stdio.h>
#include "pico/stdlib.h"

#define LED_PIN         25

bool blink;

bool callback_timer(struct repeating_timer *t)
{
    if(blink){
        gpio_put(LED_PIN, 0);
        blink = !blink;
    } else {
        gpio_put(LED_PIN, 1);
        blink = !blink;
    }
}

void main(void)
{
    repeating_timer_t timer;

    stdio_init_all();
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);

    blink = false;
    add_repeating_timer_ms(500, callback_timer, NULL, &timer);

    while(1){
        sleep_ms(100);
    }
}

上記をbuildして、picoにdrag-and-dropしてください。

車やバイクのウインカーもどきの作成

上記を応用して左右用のスイッチを押して、LEDを点滅させるようにしました。

配線

GP14(19Pin)に左用のLEDのアノードを装着(カソードはGND)
GP15(20Pin)に左用の押しボタンスイッチを装着(GND→SW→Pin接続)
GP16(21Pin)に右用の押しボタンスイッチを装着(GND→SW→Pin接続)
GP17(22Pin)に右用のLEDのアノードを装着(カソードはGND)

仕様

ボタンを押して、LEDを点滅させる。
点灯、消灯の間隔は、上記と同じ500msとする。
1度押すと、6回点滅を繰り返し消灯する。
点滅中に再度押すと消灯する。
左のLEDが点滅中に右のスイッチを押すと、左は消灯する。
右のLEDが点滅中に左のスイッチを押すと、右は消灯する。
ボタンの検出はポーリングにする。

ソース

#include <stdio.h>
#include "pico/stdlib.h"

#define LED_BLINKER_L   14      // PinNo.19
#define LED_BLINKER_R   17      // PinNo.22
#define SW_BLINKER_L    15      // PinNo.20
#define SW_BLINKER_R    16      // PinNo.21

bool gBlinkerL;                 // Lウインカ
bool gBlinkerR;                 // Rウインカ
bool gFlashL;                   // Lウインカフラッシュ用
bool gFlashR;                   // Rウインカフラッシュ用
unsigned char gBlinkCountL;     // Lウインカ点滅カウンタ
unsigned char gBlinkCountR;     // Rウインカ点滅カウンタ

bool callback_timer(struct repeating_timer *t)
{
    // 左ウィンカの処理
    if(gBlinkerL){                                  // Lウインカ点滅有効
        if(gFlashL){                                // 点滅処理
            gpio_put(LED_BLINKER_L, 0);
            gFlashL = !gFlashL;
        } else {
            gpio_put(LED_BLINKER_L, 1);
            gBlinkCountL++;
            gFlashL = !gFlashL;
        }
        if(gBlinkCountL >= 6){                      // 点滅回数処理
            gBlinkerL = false;
            gBlinkCountL = 0;
        }
    } else {                                        // Lウインカ消灯
        gpio_put(LED_BLINKER_L, 0);
        gFlashL = false;
        gBlinkCountL = 0;
    }
    // 右ウィンカの処理
    if(gBlinkerR){                                  // Rウインカ点滅有効
        if(gFlashR){                                // 点滅処理
            gpio_put(LED_BLINKER_R, 0);
            gFlashR = !gFlashR;
        } else {
            gpio_put(LED_BLINKER_R, 1);
            gBlinkCountR++;
            gFlashR = !gFlashR;
        }
        if(gBlinkCountR >= 6){                      // 点滅回数処理
            gBlinkerR = false;
            gBlinkCountR = 0;
        }
    } else {                                        // Rウインカ消灯
        gpio_put(LED_BLINKER_R, 0);
        gFlashR = false;
        gBlinkCountR = 0;
    }
}

void main(void)
{
    bool blinkL, blinkR;
    repeating_timer_t timer;    // timer変数の定義

    gBlinkerL = gBlinkerR = false;
    gFlashL = gFlashR = false;
    gBlinkCountL = gBlinkCountR = 0;

    stdio_init_all();
    gpio_init(LED_BLINKER_L);
    gpio_init(LED_BLINKER_R);
    gpio_init(SW_BLINKER_L);
    gpio_init(SW_BLINKER_R);
    gpio_set_dir(LED_BLINKER_L, GPIO_OUT);
    gpio_set_dir(LED_BLINKER_R, GPIO_OUT);
    gpio_set_dir(SW_BLINKER_L, GPIO_IN);
    gpio_set_dir(SW_BLINKER_R, GPIO_IN);
    gpio_pull_up(SW_BLINKER_L);
    gpio_pull_up(SW_BLINKER_R);

    // Timerの起動(500ms毎にcallback_timer()がCallされる
    add_repeating_timer_ms(500, callback_timer, NULL, &timer);

    while(1){
        blinkL = gpio_get(SW_BLINKER_L);            // SW読み込み(Lウインカボタン)
        blinkR = gpio_get(SW_BLINKER_R);            // SW読み込み(Rウインカボタン)
        if(!blinkL){                                // Lウインカボタンが押された
            gBlinkerL = !gBlinkerL;                 // Lウインカ点滅開始/消灯
            if(gBlinkerL && gBlinkerR){             // Rウインカ点滅状態か?
                gBlinkerR = !gBlinkerR;             // Rウインカ消灯
            }
        }
        if(!blinkR){                                // Rウインカボタンが押された
            gBlinkerR = !gBlinkerR;                 // Rウインカ点滅開始/消灯
            if(gBlinkerR && gBlinkerL){             // Lウインカ点滅状態か?
                gBlinkerL = !gBlinkerL;             // Lウインカ消灯
            }
        }

        sleep_ms(250);
    }
}

補足

ポーリングでスイッチを取得しているので、sleepのタイミングでスイッチを押しても反応しないときがあります。
gpio_set_irq_enabled_with_callback()で割り込みを試したのですが、複数の割り込みが取れないようです。
複数の割り込み方法をご存じの方がおられましたら、是非ご教示をお願いします。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1