ESP32でシリアル通信で受信したデータでタイマー割り込みの周期を設定
2022/05/21 categories:ESP32| tags:ESP32|Arduino|Timer|Interrupt|
シリアル通信で受信したデータをもとにタイマ割り込みの周期を設定するプログラムを作成してみました。プログラムはArduino言語です。
設定
setup()内で以下の設定を行います。
- シリアル通信の設定
- LED用のIOの設定
- タイマーの設定
void setup() {
Serial.begin(115200);
delay(100);
pinMode(LED_PIN, OUTPUT);
timerSemaphore = xSemaphoreCreateBinary();
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
}
serialEvent()でデータを受信
シリアル通信のデータを受信するためにserialEventを使用しました。serialEventはデータを受信したときに実行されるようで、割り込みみたいな感じかと思いましたが、実際はメインループ内でデータの有無を確認しているだけで割り込みではないようです。今回は割り込みである必要がないのでserialEventを使うことにしました。
Serial.readBytesUntilで’\n’までのデータを受信して、そのデータをrecieve_dataに格納しています。
String recieve_data;
void serialEvent() {
char buffer [100];
Serial.readBytesUntil('\n', buffer, 100);
serial_recieved = true;
recieve_data = buffer;
}
タイマ割り込み
タイマ割り込みのハンドラ内ではセマフォをGiveするだけで、タイマ割り込み時に行う処理はメインループ内で処理しています。
void IRAM_ATTR onTimer(){
xSemaphoreGiveFromISR(timerSemaphore, NULL);
}
メインループ内の処理
xSemaphoreTakeでセマフォをTakeしてタイマ割り込み時にLEDのIOの出力を反転する処理を行います。また、シリアルデータ受信した場合はタイマの周期を変える処理を行います。これらの処理でLEDを一定間隔で点滅させて、シリアルデータを受信した場合にその周期を変えられるようになりました。
void loop() {
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE)
{
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
if (serial_recieved)
{
serial_recieved = false;
timerAlarmWrite(timer, recieve_data.toInt()*1000, true);
Serial.println(recieve_data);
}
}
動作の様子
数字の文字列をESP32にシリアル通信で送るとLEDの点滅周期が変わることを確認できました。
ESP32のコード
#include <Arduino.h>
#define LED_PIN 2
String recieve_data;
bool serial_recieved = false;
hw_timer_t * timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;
void IRAM_ATTR onTimer(){
xSemaphoreGiveFromISR(timerSemaphore, NULL);
}
void serialEvent() {
char buffer [100];
Serial.readBytesUntil('\n', buffer, 100);
serial_recieved = true;
recieve_data = buffer;
}
void setup() {
Serial.begin(115200);
delay(100);
pinMode(LED_PIN, OUTPUT);
timerSemaphore = xSemaphoreCreateBinary();
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
}
void loop() {
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE)
{
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
if (serial_recieved)
{
serial_recieved = false;
timerAlarmWrite(timer, recieve_data.toInt()*1000, true);
Serial.println(recieve_data);
}
}