以前は、Unit ASRをシリアル経由でTHINKLETに接続して、音声コマンドを実行するデモをやった。録画の開始と終了をstart/stopで指示できるやつなのだけど、モックなので実際に録画はしていないやつ。

今回は、ASRを直接THINKLETに接続するのではなく、制御用のマイコンを間にはさんで、ASRからの音声コマンドで、Unit FlashLightを制御しつつ、THINKLETにも動作したコマンド履歴を送りたい。
GroveはFlashLightを接続するので、ASRは底面ピン側に接続。縦4ピンなので簡単かな。
配線はこんな感じ。ASRはGroveに、ATOMS3 liteのピンから取ってGroveに変換してFlashLightに配線している。

とりあえず、ASRの動作確認用のスケッチを書く。
#include <Arduino.h>
#include <HardwareSerial.h>
HardwareSerial ASR(1);
// 受信のみ(ASR TX→ATOM RX)
constexpr int PIN_RX = 39; // ATOM側RX
constexpr int PIN_TX = 38; // 未使用でもbeginで指定
constexpr uint32_t BAUD = 115200;
// AA 55 <CMD> 55 AA
enum State : uint8_t { WAIT_AA, WAIT_55A, GOT_CMD, WAIT_55B, WAIT_AA2 };
static State st = WAIT_AA;
static uint8_t cmd = 0;
void setup() {
Serial.begin(115200);
ASR.begin(BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
}
void loop() {
while (ASR.available()) {
uint8_t b = ASR.read();
switch (st) {
case WAIT_AA:
st = (b == 0xAA) ? WAIT_55A : WAIT_AA; break;
case WAIT_55A:
if (b == 0x55) st = GOT_CMD;
else st = (b == 0xAA) ? WAIT_55A : WAIT_AA;
break;
case GOT_CMD:
cmd = b; st = WAIT_55B; break;
case WAIT_55B:
st = (b == 0x55) ? WAIT_AA2 : WAIT_AA; break;
case WAIT_AA2:
if (b == 0xAA) {
// 16進(0xNN)で出力
Serial.printf("0x%02X\n", cmd);
}
st = WAIT_AA; break;
}
}
}
うまく動いている。今回はHEXで出すようにした。

ASRのプリセット音声コマンドで、照明の操作に使えそうなのはこの4つ。
0x18 = turn on the lights(点灯)
0x19 = turn off the lights(消灯)
0x14 = turn on
0x15 = turn off
前に作ったFlashLightの制御スケッチとマージする。
FlashLight Unit買ってみた|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/10232381
FlashLight Unit買ってみた 2025年9月3日 08:00 ただのLEDではなく、フラッシュまたは照明アプリケーションとして使えるユニット。あんまり、こんなユニット使ってみている人はいなさそう。用途は、なんかあったとき用に高輝度でチカチカさせるとか? とりあえず、照明用に明るいのがほしかっただけ。パーツでいろいろ揃えたり、百均に行ってみたりしたけど、これ... 全体公開 kinneko
いずれかのコマンドが来たらオンオフする。USBシリアルにはTHINKLETで受信できるように、ASRのコマンドと、ライトのON/OFF/AUTOOFFを送信する。
#include <Arduino.h>
#include <HardwareSerial.h>
// ----- FlashLight配線/設定 -----
constexpr int PIN_SIG = 2; // HY2.0-4P 黄(G2) → Unit FlashLight SIG
constexpr int PIN_BTN = 41; // 反応しなければ 39 に変更
constexpr int PWM_FREQ = 5000; // 5 kHz
constexpr int PWM_RES = 10; // 10-bit (0..1023)
constexpr int BRIGHTNESS_PERCENT = 100; // 必要に応じて下げる
constexpr uint32_t TORCH_TIMEOUT_MS = 15000; // 自動消灯 15秒
// ----- ASR(UART) 配線/設定 -----
HardwareSerial ASR(1);
constexpr int PIN_ASR_RX = 39; // ATOM側RX (ASRのTXへ)
constexpr int PIN_ASR_TX = 38; // 未使用でもbeginで指定
constexpr uint32_t ASR_BAUD = 115200; // 115200 8N1
// ----- デバウンス -----
constexpr uint32_t DEBOUNCE_MS = 50;
bool stable = HIGH, lastRaw = HIGH;
uint32_t lastChange = 0;
// ----- 状態 -----
bool torch = false;
uint32_t torchOnSince = 0;
inline int dutyPct(int p) {
p = constrain(p, 0, 100);
const int maxDuty = (1 << PWM_RES) - 1;
return (p * maxDuty + 50) / 100; // 四捨五入
}
enum OffReason : uint8_t { OFF_MANUAL = 0, OFF_AUTO = 1 };
inline void setTorch(bool on, OffReason reason = OFF_MANUAL) {
if (torch == on) return; // 変化なし
analogWrite(PIN_SIG, on ? dutyPct(BRIGHTNESS_PERCENT) : 0);
torch = on;
if (on) {
torchOnSince = millis();
Serial.println("ON");
} else {
if (reason == OFF_AUTO) Serial.println("AUTOOFF");
else Serial.println("OFF");
}
}
// ----- ASRフレーム: AA 55 analogWriteFrequency(PIN_SIG, PWM_FREQ); // ピン指定あり analogWriteResolution(PIN_SIG, PWM_RES); // ピン+分解能 } // ----- ASR受信処理 ----- case WAIT_AA: case WAIT_55A: case GOT_CMD: case WAIT_55B: case WAIT_AA2: // 受信CMDをHEXで出力 // ライト制御 } } } } // ----- ボタン処理(立下りでトグル)----- bool raw = digitalRead(PIN_BTN); // 押下でLOW } } // ----- 自動消灯 ----- setTorch(false, OFF_AUTO); // ★自動消灯メッセージ } } まぁ、普通に動くよね。しかし、あいかわらず英語で反応が不安定なところは残るな。自分の発音が悪いのだろうけど。テンション高くしゃべらないとダメだな... THINKLETに仮付けするとこんな感じ。普通に使える。 100円投げ銭 https://kinneko.booth.pm/items/1963720 オリジナル投稿:enum State : uint8_t { WAIT_AA, WAIT_55A, GOT_CMD, WAIT_55B, WAIT_AA2 };
State st = WAIT_AA;
uint8_t cmd = 0;
void setup() {
Serial.begin(115200);
pinMode(PIN_BTN, INPUT_PULLUP);
analogWrite(PIN_SIG, 0);
stable = lastRaw = digitalRead(PIN_BTN);
ASR.begin(ASR_BAUD, SERIAL_8N1, PIN_ASR_RX, PIN_ASR_TX);
void loop() {
while (ASR.available()) {
uint8_t b = ASR.read();
switch (st) {
st = (b == 0xAA) ? WAIT_55A : WAIT_AA; break;
if (b == 0x55) st = GOT_CMD;
else st = (b == 0xAA) ? WAIT_55A : WAIT_AA;
break;
cmd = b; st = WAIT_55B; break;
st = (b == 0x55) ? WAIT_AA2 : WAIT_AA; break;
if (b == 0xAA) {
Serial.printf("0x%02X\n", cmd);
if (cmd == 0x18 || cmd == 0x14) { // lights on / turn on
setTorch(true, OFF_MANUAL);
} else if (cmd == 0x19 || cmd == 0x15) { // lights off / turn off
setTorch(false, OFF_MANUAL);
st = WAIT_AA; break;
if (raw != lastRaw) lastChange = millis();
if (millis() - lastChange > DEBOUNCE_MS) {
if (raw != stable) {
stable = raw;
if (stable == LOW) setTorch(!torch, OFF_MANUAL);
lastRaw = raw;
if (torch && (millis() - torchOnSince >= TORCH_TIMEOUT_MS)) {



ASRでATOMS3 LITE経由にしてFlashLightを点灯する|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/10466657



