Arduinoスケッチで必須の「 loop() 」って、目的によっては使いづらいと感じたことないですか? VisualBasicでプログラミングを始めた私は、最初結構戸惑いました。マイコンでもイベントドリブン的な作りをずっと考えてましたが、今回それらしくなってきたので投稿します。(すでにWEBからの操作ではそれが実質上出来てました。)
(余計なものを一杯くっつけたままの写真で醜くて申し訳ありません。外すの面倒で...)
カギは以前の投稿でも載せていることで、loop()内に
while (Serial.available() == 0) { ; }
// 見かけ上、シリアルからの入力があるまで停止
// 入力があったら、文字列を「line」で受け取る
String line = Serial.readString();
を挿入することです。そして、受け取った「line」を分割しコマンドを取り出します。あとはそれに応じた動作を定義しておけば良いわけです。文字列分割には次のサイト記事を参考にさせていただきました。有難うございます。
例1.ある周波数の音を2秒間鳴らす -> "tone 440 4"
例2.LEDを指定した明るさで1秒間光らせる -> "led 50 5"
回路としては、使用するPin4
からの出力を、圧電ブザーやLEDと、必要な抵抗を接続してGND
に落とします。
ArduinoIDE2.3.6
でのスケッチです。普通のESP32
で動作するはずです。
const int PWM_PIN = 4;
void setup() {
Serial.begin(115200);
Serial.println("\n\rSerial Console start...");
ledcAttach(PWM_PIN, 24000, 8);
}
void loop() {
Serial.println(">");
while (Serial.available() == 0) { ; }
String line = Serial.readString();
line.trim();
if (line.length() > 5 && line.substring(0, 4) == "tone") {
int n = 2; // "tone freq duration"
String zs[n];
int zi[n];
bool flag = true;
if (split(line.substring(5), ' ', zs, n) != n) flag = false;
for (int i = 0; i < n; i++) {
if (!(zi[i] = zs[i].toInt())) {
flag = false;
break;
}
}
if (flag) {
ledcWriteTone(PWM_PIN, zi[0]); // freq
delay(zi[1] * 500); // duration
ledcWriteTone(PWM_PIN, 0);
}
} else if (line.length() > 4 && line.substring(0, 3) == "led") {
int n = 2; // "led brightness duration"
String zs[n];
int zi[n];
bool flag = true;
if (split(line.substring(4), ' ', zs, n) != n) flag = false;
for (int i = 0; i < n; i++) {
if (!(zi[i] = zs[i].toInt())) {
flag = false;
break;
}
}
if (flag) {
analogWrite(PWM_PIN, zi[0]);
delay(zi[1] * 200);
analogWrite(PWM_PIN, 0);
}
} else {
Serial.println("?");
}
}
int split(String data, char delimiter, String* dst, int num) {
int index = 0;
int len = data.length();
for (int i = 0; i < len; i++) {
char tmp = data.charAt(i);
if (tmp == delimiter) {
index++;
if (index > num - 1) return -1;
} else {
dst[index] += tmp;
}
}
return index + 1;
}
最後までご覧いただきありがとうございました。