M5StickVを喋らせる

# はじめに

MaixCubeで喋らせることができたので、M5StickVでも喋らせてみましょう。日本語も試してみます。

# eSpeak NG

オープンソースの音声合成エンジンはいくつかありますが、マイコンで動作させることができそうな軽量の[eSpeak NG](https://github.com/espeak-ng/espeak-ng)を使ってみます。辞書は実行時にファイルから読み込むのではなく、メモリに展開するようにします。

Windows版のみバイナリーが配布されています。ただし、Windows版には日本語の辞書（ja_dict）が同梱されていません。日本語の辞書はソースからビルドする必要があります。mac OSではビルドがうまくできなかったのでLinuxでビルドしました。

追記：macOSでのビルドは次の手順でできました

1. [Homebrew](http://brew.sh) のインストール
1. Portaudio のインストール: `brew install portaudio`
1. MBROLA を無効にしてビルド: `./autogen.sh && ./configure --with-mbrola=no`
1. メイク: make



# サンプル

サンプルのコードは[こちら](https://github.com/fukuen/m5stickv-espeak-demo)

本文はこんな感じです

```c++

#include <Arduino.h>
#include <M5StickV_eSpeak.h>
#include <Wire.h>

M5StickVeSpeak speak;

#define AXP192_ADDR 0x34
#define PIN_SDA 29
#define PIN_SCL 28

bool axp192_init() {
    Serial.printf("AXP192 init.\n");
    sysctl_set_power_mode(SYSCTL_POWER_BANK3,SYSCTL_POWER_V33);

    Wire.begin((uint8_t) PIN_SDA, (uint8_t) PIN_SCL, 400000);
    Wire.beginTransmission(AXP192_ADDR);
    int err = Wire.endTransmission();
    if (err) {
        Serial.printf("Power management ic not found.\n");
        return false;
    }
    Serial.printf("AXP192 found.\n");

    // Clear the interrupts
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x46);
    Wire.write(0xFF);
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x23);
    Wire.write(0x08); //K210_VCore(DCDC2) set to 0.9V
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x33);
    Wire.write(0xC1); //190mA Charging Current
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x36);
    Wire.write(0x6C); //4s shutdown
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x91);
    Wire.write(0xF0); //LCD Backlight: GPIO0 3.3V
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x90);
    Wire.write(0x02); //GPIO LDO mode
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x28);
    Wire.write(0xF0); //VDD2.8V net: LDO2 3.3V,  VDD 1.5V net: LDO3 1.8V
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x27);
    Wire.write(0x2C); //VDD1.8V net:  DC-DC3 1.8V
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x12);
    Wire.write(0xFF); //open all power and EXTEN
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x23);
    Wire.write(0x08); //VDD 0.9v net: DC-DC2 0.9V
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x31);
    Wire.write(0x03); //Cutoff voltage 3.2V
    Wire.endTransmission();
    Wire.beginTransmission(AXP192_ADDR);
    Wire.write(0x39);
    Wire.write(0xFC); //Turnoff Temp Protect (Sensor not exist!)
    Wire.endTransmission();

    fpioa_set_function(23, (fpioa_function_t)(FUNC_GPIOHS0 + 26));
    gpiohs_set_drive_mode(26, GPIO_DM_OUTPUT);
    gpiohs_set_pin(26, GPIO_PV_HIGH); //Disable VBUS As Input, BAT->5V Boost->VBUS->Charing Cycle

    msleep(20);
    return true;
}

void setup() {
    Serial.begin(115200);
    axp192_init();

    speak.begin();
    Serial.printf("start.\n");

    espeak_ng_STATUS status = espeak_ng_SetVoiceByName("ja");
	speak.speak("コンニチワ");
    Serial.printf("konnichiwa.\n");

	sleep(1);
	speak.speak("ワレワレワ ウチュウジン ダ");
    Serial.printf("wareware wa uchujin da.\n");

}

void loop() {

}

```

# 最後に

片言ですが日本語も喋らせることができました。