M5StackをArduinoとして使う手順、2018年6月28日時点版
公式サイトの手順はarduino-esp32のインストールとm5stackライブラリのインストールでページが分かれていて、すこしややこしかったので現時点での手順を1ページにまとめてみました。
注:以下の手順は古いです。Arduino IDEのボードマネージャからESP32を選べるようになったそうです(2018/8/8 追記)
USBドライバのインストール
CP210xというUSBシリアルのドライバをダウンロードしてインストールする。
Windows10(Universal)
https://www.silabs.com/documents/public/software/CP210x_Universal_Windows_Driver.zip
Windows7/8/8.1
https://www.silabs.com/documents/public/software/CP210x_Windows_Drivers.zip
公式サイトをよく見るとUniversal版(v10.1.1)は使っちゃダメで、v6.7.1を使えと書いてあるけど、ドライバのサイトで公開されているUniversal版(v10.1.3)で問題なく使えている。バージョン少し上がっているのでたぶん使えるようになったのだと思う。Windows10の人はUniversal版で多分大丈夫です。7のひとは7用を使いましょう。
Arduino IDEのインストール
Arduino(Windows版)をダウンロードしてインストールする。
https://www.arduino.cc/download_handler.php?f=/arduino-1.8.5-windows.exe
Gitのインストール
ESP32(M5Stackに搭載されているマイコン)をArduino IDEで使うための環境入手にgitが必要(これが面倒でくじける人が多いと思う)。32bit版のWindowsを使っている人は32bit版を使いましょう。
64bit版
https://github.com/git-for-windows/git/releases/download/v2.18.0.windows.1/Git-2.18.0-64-bit.exe
32bit版
https://github.com/git-for-windows/git/releases/download/v2.18.0.windows.1/Git-2.18.0-32-bit.exe
ArduinoIDEをESP32に対応させるarduino-esp32をgit cloneする
手順の途中で「Arduinoスケッチブックの場所」というのが必要になるので、最初にその場所を確認する。
Arduinoというアプリがインストールされているはずなので、それを起動する。
ファイル – 環境設定 を開くと、「スケッチブックの保存場所」という項目があるのでそのパスを覚えるか、どこかにコピーしておく。
次に、Git GUIというアプリがインストールされているはずなので、それを起動する。
「Clone Existing Repository」を選ぶ。
Source Locationに次のURLを入力する。
https://github.com/espressif/arduino-esp32.git
Taget Directoryに先ほど記憶した「スケッチブックの保存場所/hardware/espressif/esp32」を指定する。(espressif以降のフォルダは存在してないので自分で新規作成した)
Cloneボタンを押すとリポジトリのクローンが始まる。
サブモジュールをアップデートする
クローンが終わったら、Git Bashというアプリを起動して、「スケッチブックの保存場所//hardware/espressif/esp32」に移動して次のコマンドを実行する。(CUI力が求められる)
このコマンド実行で2つのサブモジュールの内容がgit cloneされる。
git submodule update --init --recursive
get.exeを実行する
エクスプローラで「スケッチブックの保存場所//hardware/espressif/esp32/tools」を開いてgetという実行ファイルをダブルクリックしてなにかをゲットする。(10分以上かかります。外のネットワークに出るのにProxyを通さないといけない環境ではダウンロードがうまくできないこともあるようです。)
おつかれさまでした。これでArduinoでESP32のバイナリが生成できるようになりました。
M5Stackのライブラリをインストールする
ArduinoからM5Stackの液晶やボタンなどを簡単に扱えるように、M5Stackライブラリをインストールします。
Arduinoアプリを起動して、
メニューのスケッチ – ライブラリをインクルード – ライブラリを管理 を開きます。
右上の検索フィルタ欄にm5stackと入力すると、”M5Stack by M5Stack”という項目が見えるので、クリックして、インストールボタンを押します。
ボードの設定をする
ライブラリのインストールが終わったら、Arduinoのウインドウに戻ってボードの設定をします。
以降すべて メニュー – ツール の中の項目です。
- ボード:”ESP32 Dev Module”
- Flash Mode:”QIO”
- Flash Frequenry:”80MHz”
- Flash Size:”4MB(32Mb)”
- Partition Scheme:”初期値”
- Upload Speed:”921600″
- Core Debug Level:”なし”
- シリアルポート:”M5Stackをつなぐと1つだけCOMXXが見えていると思います”
- 書込装置:”AVRISP mkII”
なにかを書き込んでみる
メニューのファイル – スケッチ例 – (かなり下のほうに)M5Stack から Games – Tetris など、適当に選んで、メニューバーの(→)ボタンを押すと、コンパイル&書き込みが始まります。わりと時間がかかるのでじっくり待ちます。うまくコンパイルと書き込みが終わると、M5Stackが自動でリセットしてテトリスが起動します。
しゃべってもらう
ESP32用のAquestalkを導入する。
手順は次の2つのページを 参照。
ESP32で音声合成(AquesTalk pico for ESP32)
AquesTalkを使ってみたプログラム。LED点灯用のライブラリなども使っているのでWS2812FXとAdafruit NeoPixelというライブラリをインストールしておかないとビルドできないと思います。あと、マイクロSDカードから画像を読み込んでいるのでそれも準備が必要です。出だしで時刻取得のためにWifi接続してますが、時間をしゃべる機能を削ってしまったので意味なしですね・・・
#include <M5Stack.h> | |
#include <WiFi.h> | |
#include <time.h> | |
#include "AquesTalkTTS.h" | |
#include <WS2812FX.h> | |
#define LED_COUNT 24 | |
#define LED_PIN 5 | |
#define TIMER_MS 5000 | |
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_RGB + NEO_KHZ800); | |
unsigned long last_change = 0; | |
unsigned long now = 0; | |
//const char* licencekey = "XXX-XXX-XXX"; // AquesTalk-ESP licencekey | |
const char* licencekey = NULL; // AquesTalk-ESP licencekey | |
const char* ssid = "WIFI-SSID"; // WiFi SSID | |
const char* password = "PASSWORD"; // WiFi PW | |
const char* ntpServer = "ntp.jst.mfeed.ad.jp"; | |
const long gmtOffset_sec = 9 * 3600; | |
const int daylightOffset_sec = 0; | |
int modenum = 0; | |
int colorss[]={RED, GREEN, BLUE, WHITE, YELLOW, CYAN, MAGENTA, PURPLE, ORANGE, PINK}; | |
int colors_index = 2; | |
void setup() | |
{ | |
int iret; | |
Serial.begin(115200); | |
ws2812fx.init(); | |
ws2812fx.setBrightness(255); | |
ws2812fx.setSpeed(1000); | |
ws2812fx.setColor(colorss[colors_index]); | |
ws2812fx.setMode(FX_MODE_STATIC); | |
ws2812fx.start(); | |
M5.begin(); | |
M5.Lcd.setBrightness(200); | |
// M5.Lcd.drawJpgFile(SD, "/face.jpg"); | |
// Init Text-to-Speech (AquesTalk-ESP + I2S + Internal-DAC) | |
iret = TTS.create(licencekey); | |
if(iret){ | |
Serial.print("ERR: TTS_create():"); | |
Serial.println(iret); | |
} | |
} | |
void loop() | |
{ | |
int iret; | |
struct tm timeinfo; | |
char koe[200]; | |
if(M5.BtnA.wasPressed()){ | |
colors_index++; | |
if(colors_index > 9) { | |
colors_index = 0; | |
} | |
ws2812fx.setColor(colorss[colors_index]); | |
sprintf(koe,"konnnichiwa.yukkurimiteittekudasai"); | |
iret = TTS.play(koe, 100); | |
if(iret){ | |
Serial.println("ERR:TTS.play()"); | |
} | |
M5.Lcd.drawJpgFile(SD, "/tallonface.jpg"); | |
} | |
else if(M5.BtnB.wasPressed()){ | |
modenum = (ws2812fx.getMode() + 1) % ws2812fx.getModeCount(); | |
ws2812fx.setMode(modenum); | |
int xx =0; | |
if (modenum < 10) xx = M5.Lcd.drawChar('0', xx, 0, 6); | |
M5.Lcd.drawNumber(modenum, xx, 0, 6); | |
TTS.stop(); | |
} | |
else if(M5.BtnC.wasPressed()){ | |
modenum = (ws2812fx.getMode() - 1) % ws2812fx.getModeCount(); | |
if(modenum < 0){ | |
modenum = ws2812fx.getModeCount()-1; | |
} | |
ws2812fx.setMode(modenum); | |
int xx =0; | |
if (modenum < 10) xx = M5.Lcd.drawChar('0', xx, 0, 6); | |
M5.Lcd.drawNumber(modenum, xx, 0, 6); | |
TTS.stop(); | |
m5.Speaker.mute(); | |
} | |
M5.update(); | |
now = millis(); | |
ws2812fx.service(); | |
} | |
void taskClock(void *arg) | |
{ | |
// M5.Lcd.setRotation(1); | |
M5.Lcd.fillScreen(TFT_WHITE); | |
M5.Lcd.setTextSize(1); | |
M5.Lcd.setTextColor(TFT_PINK, TFT_WHITE); | |
//connect to WiFi | |
Serial.printf("Connecting to %s ", ssid); | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print("."); | |
} | |
Serial.println(" CONNECTED"); | |
//init and get the time | |
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); | |
struct tm timeinfo; | |
getLocalTime(&timeinfo); // すぐにWiFiのdisconnectするとNG | |
//printLocalTime(); | |
//disconnect WiFi as it's no longer needed | |
WiFi.disconnect(true); | |
WiFi.mode(WIFI_OFF); | |
for(;;){ | |
struct tm timeinfo; | |
if(!getLocalTime(&timeinfo)){ | |
Serial.println("Failed to obtain time"); | |
} | |
else { | |
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); | |
DrawTime(timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec); | |
} | |
delay(1000); | |
} | |
} | |
// from | |
// M5Stack-IDF/components/M5Stack/examples/Advanced/Display/TFT_Clock_Digital/TFT_Clock_Digital.ino | |
void DrawTime(int hh, int mm, int ss) | |
{ | |
static byte omm = 99, oss = 99; | |
static byte xcolon = 0, xsecs = 0; | |
static unsigned int colour = 0; | |
int xpos = 0; | |
int ypos = 85; // Top left corner ot clock text, about half way down | |
int ysecs = ypos + 24; | |
if (omm != mm) { // Redraw hours and minutes time every minute | |
omm = mm; | |
// Draw hours and minutes | |
if (hh < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add hours leading zero for 24 hr clock | |
xpos += M5.Lcd.drawNumber(hh, xpos, ypos, 8); // Draw hours | |
xcolon = xpos; // Save colon coord for later to flash on/off later | |
xpos += M5.Lcd.drawChar(':', xpos, ypos - 8, 8); | |
if (mm < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add minutes leading zero | |
xpos += M5.Lcd.drawNumber(mm, xpos, ypos, 8); // Draw minutes | |
xsecs = xpos; // Sae seconds 'x' position for later display updates | |
} | |
if (oss != ss) { // Redraw seconds time every second | |
oss = ss; | |
xpos = xsecs; | |
if (ss % 2) { // Flash the colons on/off | |
M5.Lcd.setTextColor(0xfddd, TFT_WHITE); // Set colour to grey to dim colon | |
M5.Lcd.drawChar(':', xcolon, ypos - 8, 8); // Hour:minute colon | |
xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon | |
M5.Lcd.setTextColor(TFT_PINK, TFT_WHITE); // Set colour back to yellow | |
} | |
else { | |
M5.Lcd.drawChar(':', xcolon, ypos - 8, 8); // Hour:minute colon | |
xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon | |
} | |
//Draw seconds | |
if (ss < 10) xpos += M5.Lcd.drawChar('0', xpos, ysecs, 6); // Add leading zero | |
M5.Lcd.drawNumber(ss, xpos, ysecs, 6); // Draw seconds | |
} | |
int xx =0; | |
if (modenum < 10) xx = M5.Lcd.drawChar('0', xx, 0, 6); | |
M5.Lcd.drawNumber(modenum, xx, 0, 6); | |
} |
(espressif以降のフォルダは存在してないので自分で新規作成した)
これを誤解して断念する人の方が多いでしょうね
コメントありがとうございます。
たしかにそうですね。つまづきポイントが多くてちょっと触ってみようと思う人がやる気なくしてしまうのがもったいないと感じます。
ボードマネージャからインストールできるようになったのはかなりありがたいです。