FreeRTOS実習その2
その1と記載せずだったが、こちらの続き。最初にお断りしておくが、ステキなプログラムではない(改善の余地あり)。
やること
ボタンを押したらタスクが切り替わるプログラムの実現。
使ったもの
スイッチサイエンスさん経由で購入したNucleo-F303RE。ユーザー用ボタンが最初から搭載されているので、、、という単純な理由。
コード
タスク関連宣言
ボタン押下を扱うタスクとLEDオンオフを扱うタスク2つ。
# include <STM32FreeRTOS.h>
const uint8_t Led = LED_BUILTIN;
const uint8_t Btn = USER_BTN;
TaskHandle_t TaskButton_Handler;
TaskHandle_t TaskBlink1_Handler;
TaskHandle_t TaskBlink0_Handler;
void TaskButton(void *pvParameters);
void TaskBlink1(void *pvParameters);
void TaskBlink0(void *pvParameters);
Arduino環境でおなじみ部分
タスク生成など。
void setup() {
Serial.begin(9600);
while (!Serial) {}
pinMode(Led, OUTPUT);
xTaskCreate(TaskButton, "Button", 128, NULL, 2, &TaskButton_Handler);
xTaskCreate(TaskBlink1, "Blink1", 128, NULL, 1, &TaskBlink1_Handler);
xTaskCreate(TaskBlink0, "Blink0", 128, NULL, 1, &TaskBlink0_Handler);
vTaskStartScheduler();
}
void loop() {
// Empty. Things are done in Tasks.
}
ボタン押下を扱うタスク
void TaskButton(void *pvParameters) {
(void) pvParameters;
int pressed = 0;
pinMode(Btn, INPUT);
vTaskSuspend(TaskBlink1_Handler);
vTaskSuspend(TaskBlink0_Handler);
for (;;) {
if (pressed == 0) {
if (digitalRead(Btn) == LOW){
Serial.println("Button Pushed for Blink1");
pressed = 1;
vTaskSuspend(TaskBlink0_Handler);
vTaskResume(TaskBlink1_Handler);
}
} else { // pressed == 1
if (digitalRead(Btn) == LOW){
Serial.println("Button Pushed for Blink0");
pressed = 0;
vTaskSuspend(TaskBlink1_Handler);
vTaskResume(TaskBlink0_Handler);
}
}
vTaskDelay(500/portTICK_PERIOD_MS); // wait for 500ms
}
}
最初にvTaskSuspend()で2つのLEDタスクを止めてしまう。ボタンが押されたら、2つのタスクを交互に眠らし(vTaskSuspend())、起こす(vTaskResume())。
LEDタスク
2つのタスクの違いは、LED点滅の間隔が異なるだけ。
void TaskBlink1(void *pvParameters) {
(void) pvParameters;
for (;;) {
digitalWrite(Led, HIGH);
delay(500);
digitalWrite(Led, LOW);
delay(500);
Serial.println("Blink1");
vTaskDelay(1);
}
}
void TaskBlink0(void *pvParameters) {
(void) pvParameters;
for (;;) {
digitalWrite(Led, HIGH);
delay(1000);
digitalWrite(Led, LOW);
delay(1000);
Serial.println("Blink0");
vTaskDelay(1);
}
}
ボタン押下タスクへの切換えの余地を残すため、vTaskDelay()を用いている。
実験
コンソール上では下記のような感じ。ボタンを押すと切り替わっている。
しかし、、
このプログラムではボタンのチャタリングを防ぐことはできず、ボタンスイッチを押しても(特にすぐに押して離す場合)タスクが切り替わらないことがある。これを解決するのは次回(その3)にて。