ESP8266でAlexaデバイスを自作する

# はじめに
今回はArduino開発環境で扱えるESP8266を使い、Alexaデバイスとして振る舞えるようになるライブラリを試してみました。スマート電球みたいにLEDの色や明るさを変えることができます。筐体は百均の適当なケースです。音声操作ができるようになるだけではなく、LTE通信による遠隔操作もできるようになるので非常に便利だと思いました。
![PXL_20240125_074823429.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/f9092b1f-8d98-7926-0878-a5f202484e0e.jpeg)
# 開発環境
* Windows 11 Home 22H2
* Arduino IDE 2.2.1
* Adafruit NeoPixel 1.11.0
* Espalexa 2.7.0
# 部品表
今回は乾電池で駆動します。ESP8266の電源電圧範囲は2.7Vから3.6Vとなるため、公称電圧が1.2Vとなるニッケル水素電池を3本使いました。また、適当なブレッドボードやケースなども用意しました。
| 部品名 | 数量 |
|:--|:-:|
| AE-ESP-WROOM-02 | 1個 |
| PL9823-F5 | 4個 |
| スライドスイッチ | 2個 |
| タクトスイッチ | 1個 |
| 電池ボックス | 1個 |
# 配線
右側のスライドスイッチは書き込み用です。左側のスライドスイッチは電源用です。タクトスイッチを押すとリセットできます。また、EN、GPIO15、GPIO2は適切にプルアップ、プルダウンしておく必要があります[^1]。抵抗を介した方が無難だとは思います。
![PXL_20240125_144649021.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/311beb87-4f67-76a6-53fd-9b4fedb10ab0.jpeg)
# 書き込み
汎用的なUSBシリアル変換モジュールを使います。USBシリアル変換モジュールのTXD、RXDはESP8266のRXD、TXDに交差して結線します。GPIO0をGNDに落としてから電源を入れ直す、またはリセットスイッチを押すことで書き込み可能な状態となります。書き込みが完了したらGPIO0をGNDから切り離し、同じようにリセットするとプログラムが走り始めます。
![PXL_20240125_074008355.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/054fffd5-5792-bebc-bd88-3ddc7d5c783b.jpeg)
# スケッチ
[**こちら**](https://github.com/Aircoookie/Espalexa/blob/main/examples/EspalexaColor/EspalexaColor.ino)のサンプルコードを参考にしました。デバイス名は仮にESP8266と指定しています。ちなみに、ESP8266の起動直後におけるボーレートは74880bpsとなるため、シリアル通信のボーレートも揃えておくと起動直後に表示される文字列が文字化けしません。
```cpp:alexa.ino
#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <Espalexa.h>

#define LED_PIN 12
#define LED_COUNT 4

const char* ssid = ""; //put your Wi-Fi SSID
const char* password = ""; //put your Wi-Fi password

Espalexa espalexa;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_RGB + NEO_KHZ800);


void deviceCallback(uint8_t brightness, uint32_t color) {
  Serial.printf("#%06x, %d%%\n", color, brightness * 100 / 255);
  if (brightness) {
    pixels.setBrightness(brightness);
    pixels.fill(color, 0, LED_COUNT);
  } else {
    pixels.clear();
  }
  pixels.show();
}

//return true if successful or false if not
boolean connectToWiFi() {
  boolean state = true;
  int i = 0;
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  //wait for connection
  Serial.println("");
  Serial.print("Connecting...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");

    if (i > 20) {
      state = false;
      break;
    }
    i++;
  }
  Serial.println("");

  if (state) {
    Serial.println("Connected to Wi-Fi successfully");
  } else {
    Serial.println("Connection failed");
  }
  return state;
}

void setup() {
  Serial.begin(74880); //to avoid text garbling

  pixels.begin();
  pixels.show(); //turn off all LEDs

  if (connectToWiFi()) {
    espalexa.addDevice("ESP8266", deviceCallback); //device name
    espalexa.begin();
  }
}
 
void loop() {
  espalexa.loop();
  delay(1);
}
```
# 動作確認
まずはAlexaアプリから新しいデバイスとして追加します。デバイスの種類はその他を選択し、デバイスのロゴはWi-Fiを選択します。その後は自動で検出され、接続まで進めてくれます。暫く待つとデバイス名はESP8266として追加されました。しかし、このままだと非常に呼びにくかったため、Alexaアプリから編集し、電球に変更しました。Alexaに向かい、電球の色を青色にして、電球の明るさを暗くして、電球を点けて、というような感じで話しかけると正しく認識され、LEDの色や明るさが変わりました。カラーコードや明るさはシリアルモニタにも出力されます。
# おわりに
Alexaアプリの定型アクションにも追加できるようになるため、指定した時間帯に点けることなども可能です。スマートリモコンなどにも応用できそうです。
[^1]:https://www.kwbtblog.com/entry/2018/12/06/164413