はじめに
前回は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()で割り込みを試したのですが、複数の割り込みが取れないようです。
複数の割り込み方法をご存じの方がおられましたら、是非ご教示をお願いします。