■M5Stack
2020年1月時点で M5Stack を使用したときのメモ
■購入
M5Stack Gray(9軸IMU搭載)
https://www.amazon.co.jp/gp/product/B07BW4KVWM
みんなのM5Stack入門
https://www.amazon.co.jp/gp/product/4865942092
以下も購入したが、無くてもM5Stackは起動できる
M5Stack内に画面を保存して表示する場合などに必要となるみたい
Team microSDHCカード 16GB 高速転送UHS-1 日本国内10年保証 SD変換アダプター付属 正規品
https://www.amazon.co.jp/gp/product/B07DJ17CKQ
■開発環境構築
■Arduino統合開発環境のインストール
Arduino - Software
https://www.arduino.cc/en/Main/Software
「Windows Installer, for Windows XP and up」をクリック
「Contribute to the Arduino Software」というページへ遷移するので、「JUST DOWNLOAD」をクリック
(「CONTRIBUTE & DOWNLOAD」から寄付もできる)
arduino-1.8.10-windows.exe
をダウンロードできた(バージョンはそのときによって変更されている可能性がある)
ダウンロードしたファイルをダブルクリックで起動
規約が表示されるので「I Agree」をクリック
インストールオプションが表示されるので、そのまま「Next >」をクリック
インストール先が表示されるので、そのまま「Install」をクリック
(インストールは数分かかった。また、途中で何度かセキュリティの確認が表示されたので許可)
デスクトップに「Arduino」アイコンが作成されているので、ダブルクリックで起動
(起動時にセキュリティの確認が表示されたので許可)
■USBシリアルドライバのインストール
M5Stack - Modular Rapid ESP32 IoT Development Board - ESP32 dev kits - m5stack-store
https://m5stack.com/
Download - m5stack-store
https://m5stack.com/pages/download
「SOFTWARE → CP210X Driver → Download → Windows」をクリック
CP210x_VCP_Windows.zip
をダウンロードできたので解答する
64bit用のインストーラである CP210xVCPInstaller_x64_v6.7.0.0.exe をダブルクリックしてドライバをインストールする
ようこそ画面が表示されるので「次へ」をクリック
規約が表示されるので、「同意します」にチェックを入れて「次へ」をクリック
インストールされたら「完了」をクリック
M5Stackを付属のUSBケーブルでWindowsに接続する
接続するとM5Stackが起動し、画面にテキストなどが表示される
Windowsで左下のアイコンを右クリックし、デバイスマネージャーをクリック
「ポート(COM と LPT)」内に「Silicon Labos CP210x USB to UART Bridge (COM3)」のような表示があることを確認する
表示は環境によって差があるが、最後の「COM3」がポート番号なので控えておく
■ESP32ボードマネージャのインストール
Arduinoを起動し、メニューから「ファイル → 環境設定」を選択する
設定画面が表示されるので、「行番号の表示」にチェックを入れる
さらに「追加のボードマネージャのURL」の右側のアイコンをクリックし、
https://dl.espressif.com/dl/package_esp32_index.json を入力して「OK」をクリックする
「OK」をクリックして環境設定を完了する
メニューから「ツール → ボード:"Arduino/Genuino Uno" → Arduino/Genuino Uno」を選択し、
さらに「ツール → ボード:"Arduino/Genuino Uno" → ボードマネージャ」からボードマネージャを表示する
画面上部の入力欄に「esp32」と入力すると、「esp32 by Espressif Systems」というパッケージが表示される
マウスカーソルを合わせるとバージョン番号の選択ボックスが表示されるので、最新のバージョンを選択して「インストール」をクリックする
(今回は 1.0.4 をインストールした。「-beta」や「-rc」の付いたものは、マイナーリリースで不安定な場合があるので避ける方が無難)
完了したら「閉じる」をクリックする
「ツール → ボード:"Arduino/Genuino Uno"」の下の方に「M5Stack-Core-ESP32」が追加されているので選択する
また、「ツール → Upload Speed」の値が「921600」になっていることを確認する(なっていなければ変更する)
「ツール → シリアルポート」を先に確認した値にする(今回は「COM3」にする)
■M5Stackライブラリのインストール
メニューから「スケッチ → ライブラリをインクルード → ライブラリを管理...」を選択する
画面上部の入力欄に「m5stack」と入力すると、「M5Stack by M5Stack」というライブラリが表示されるので、最新バージョンをインストールする
完了したら「閉じる」をクリックする
■M5Stackの液晶画面に文字を表示する
メニューから「ファイル → スケッチ例 → M5Stack → Basics → HelloWorld」を選択する
以下のコードが表示される
#include <M5Stack.h>
// the setup routine runs once when M5Stack starts up
void setup(){
// Initialize the M5Stack object
M5.begin();
/*
Power chip connected to gpio21, gpio22, I2C device
Set battery charging voltage and current
If used battery, please call this function in your project
*/
M5.Power.begin();
// LCD display
M5.Lcd.print("Hello World");
}
// the loop routine runs over and over again forever
void loop() {
}
M5StackをUSBケーブルでパソコンに繋ぐ
メニューの「ツール → シリアルポート」がM5Stackを接続したポートになっていることを確認する
メニューの「→」ボタンをクリックしてマイコンボードに書き込む
1〜2分程度待つと、画面に「Hello World」と表示される
コード中の「LCD display」部分を以下のように変更する
これで再度書き込むと、画面の内容が「Hello! M5Stack」に変わる
// LCD display
M5.Lcd.print("Hello! M5Stack");
画面の表示を確認できたら、Arduinoのウインドウを閉じる
今回は変更内容は保存しない
■リセットと電源オフ
M5Stackの側面にある赤いボタンが、リセット兼電源ボタンとなっている
このボタンを1回押すとM5Stackがリセットされ、スケッチの最初から再実行される
電源をオフにするときは、USBケーブルを外してからこのボタンを2回続けて押す
電源がオフのときにこのボタンを1回押すと、電源がオンになる
USBケーブルから給電しているときは、赤いボタンを2回続けて押しても電源はオフにならず、1回押したときと同じようにM5Stackがリセットされる
■プログラム例
■Hello World
#include <M5Stack.h>
void setup(){
M5.begin();
M5.Lcd.print("Hello World");
}
void loop() {
}
■文字の位置とサイズを指定
#include <M5Stack.h>
void setup(){
M5.begin();
M5.Lcd.setCursor(40, 60);
M5.Lcd.setTextSize(3);
M5.Lcd.print("Hello World");
}
void loop() {
}
■四角形や円を描く
#include <M5Stack.h>
void setup(){
M5.begin();
M5.Lcd.fillRect(120, 140, 80, 30, WHITE);
M5.Lcd.fillCircle(90, 80, 10, WHITE);
M5.Lcd.fillCircle(230, 80, 10, WHITE);
}
void loop() {
}
■ボタンを使用する
#include <M5Stack.h>
void setup(){
M5.begin();
M5.Lcd.print("Started.");
}
void loop() {
M5.update();
if (M5.BtnA.wasPressed()) {
M5.Lcd.print("Button A was Pressed.");
} else if (M5.BtnA.pressedFor(1000)) {
M5.Lcd.print("Button A was Pressed for 1000.");
}
if (M5.BtnB.wasPressed()) {
M5.Lcd.print("Button B was Pressed.");
} else if (M5.BtnB.pressedFor(1000)) {
M5.Lcd.print("Button B was Pressed for 1000.");
}
if (M5.BtnC.wasPressed()) {
M5.Lcd.print("Button C was Pressed.");
} else if (M5.BtnC.pressedFor(1000)) {
M5.Lcd.print("Button C was Pressed for 1000.");
}
}
■スピーカーを鳴らす
#include <M5Stack.h>
void setup(){
M5.begin();
M5.Lcd.print("Started.");
}
void loop() {
M5.update();
if (M5.BtnA.wasPressed()) {
M5.Speaker.tone(262, 200); // ドの音を鳴らす
} else if (M5.BtnB.wasPressed()) {
M5.Speaker.tone(330, 200); // ミの音を鳴らす
} else if (M5.BtnC.wasPressed()) {
M5.Speaker.tone(392, 200); // ソの音を鳴らす
}
}
■ヘルツ・秒数・音量を指定して音を鳴らす
#include <M5Stack.h>
void setup(){
M5.begin();
M5.Lcd.print("Started.");
}
void loop() {
M5.update();
if (M5.BtnA.wasPressed()) {
beep(440, 1000, 2); // 440Hzの音を1秒鳴らす
} else if (M5.BtnB.wasPressed()) {
beep(460, 1000, 2); // 460Hzの音を1秒鳴らす
} else if (M5.BtnC.wasPressed()) {
beep(480, 1000, 2); // 480Hzの音を1秒鳴らす
}
}
// ヘルツ・秒数・音量を指定して音を鳴らす
void beep(int freq, int duration, uint8_t volume) {
int t = 1000000 / freq / 2;
unsigned long start = millis();
while ((millis() - start) < duration) {
dacWrite(SPEAKER_PIN, 0);
delayMicroseconds(t);
dacWrite(SPEAKER_PIN, volume);
delayMicroseconds(t);
}
dacWrite(SPEAKER_PIN, 0);
}
■Wi-Fiに接続する
※M5Stackに使われているESP32は、2.4GHz帯にのみ対応している
接続先を5Ghzにすると、エラーにはならないもののいつまで待っても接続されなかった
#include <M5Stack.h>
#include <WiFi.h>
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
void setup(){
M5.begin();
M5.Lcd.setTextSize(2);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print('.');
}
M5.Lcd.print("\r\nWiFi connected\r\nIP address: ");
M5.Lcd.println(WiFi.localIP());
}
void loop() {
}
■インターネットから時刻を取得する
#include <M5Stack.h>
#include <WiFi.h>
#define JST (3600L * 9)
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
void setup(){
M5.begin();
M5.Lcd.setTextSize(2);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print('.');
}
M5.Lcd.print("\r\nWiFi connected\r\nIP address: ");
M5.Lcd.println(WiFi.localIP());
delay(500);
M5.Lcd.setTextSize(3);
configTime(JST, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
}
void loop() {
struct tm tm;
if (getLocalTime(&tm)) {
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(60, 80);
M5.Lcd.printf("%d/%2d/%2d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
M5.Lcd.setCursor(80, 140);
M5.Lcd.printf("%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
}
delay(1000);
}
■インターネットからテキストを取得する
#include <M5Stack.h>
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
const char* url = "http://example.com/example.php";
void setup(){
M5.begin();
M5.Lcd.setTextSize(2);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print('.');
}
M5.Lcd.print("\r\nWiFi connected\r\nIP address: ");
M5.Lcd.println(WiFi.localIP());
delay(500);
M5.Lcd.setTextSize(2);
}
void loop() {
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0);
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
String response = http.getString();
M5.Lcd.print("Response=" + response);
} else {
M5.Lcd.print("Error on HTTP request.");
}
http.end();
delay(10 * 1000);
}
■インターネットから画像を取得する
#include <M5Stack.h>
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
const char* url = "http://example.com/example.jpg";
uint8_t buff[64 * 1024] = { 0 };
void setup(){
M5.begin();
M5.Lcd.setTextSize(2);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print('.');
}
M5.Lcd.print("\r\nWiFi connected\r\nIP address: ");
M5.Lcd.println(WiFi.localIP());
delay(500);
}
void loop() {
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
int len = http.getSize();
if (len <= 0) {
M5.Lcd.print("Error on HTTP getSize.");
} else {
WiFiClient * stream = http.getStreamPtr();
uint8_t* p = buff;
int l = len;
while (http.connected() && (l > 0 || len == -1)) {
size_t size = stream->available();
if (size) {
int s = ((size > sizeof(buff)) ? sizeof(buff) : size);
int c = stream->readBytes(p, s);
p += c;
Serial.printf("[HTTP] read: %d\n", c);
if (l > 0) {
l -= c;
}
}
}
M5.Lcd.drawJpg(buff, len);
}
} else {
M5.Lcd.print("Error on HTTP request.");
}
http.end();
delay(60 * 1000);
}
■押したボタンに応じて、インターネットから画像を取得する
#include <M5Stack.h>
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
const char* targetA = "http://example.com/image1.jpg";
const char* targetB = "http://example.com/image2.jpg";
const char* targetC = "http://example.com/image3.jpg";
const char* url = "";
int count = 0;
int interval = 10 * 60;
uint8_t buff[64 * 1024] = { 0 };
void setup(){
M5.begin();
M5.Lcd.setTextSize(2);
// WiFiに接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print('.');
}
M5.Lcd.print("\r\nWiFi connected\r\nIP address: ");
M5.Lcd.println(WiFi.localIP());
delay(500);
// 初期表示するURL
url = targetA;
}
void loop() {
M5.update();
// ボタンに応じて画像を切り替え
if (M5.BtnA.wasPressed()) {
beep(440, 100, 2);
url = targetA;
count = 0;
} else if (M5.BtnB.wasPressed()) {
beep(440, 100, 2);
url = targetB;
count = 0;
} else if (M5.BtnC.wasPressed()) {
beep(440, 100, 2);
url = targetC;
count = 0;
}
// ウェイト処理
if (count-- <= 0) {
count = interval;
// インターネットから画像を取得して表示
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
int len = http.getSize();
if (len <= 0) {
M5.Lcd.print("Error on HTTP getSize.");
} else {
WiFiClient * stream = http.getStreamPtr();
uint8_t* p = buff;
int l = len;
while (http.connected() && (l > 0 || len == -1)) {
size_t size = stream->available();
if (size) {
int s = ((size > sizeof(buff)) ? sizeof(buff) : size);
int c = stream->readBytes(p, s);
p += c;
Serial.printf("[HTTP] read: %d\n", c);
if (l > 0) {
l -= c;
}
}
}
M5.Lcd.drawJpg(buff, len);
}
} else {
M5.Lcd.print("Error on HTTP request.");
}
http.end();
}
// 1秒待つ
delay(1000);
}
// ヘルツ・秒数・音量を指定して音を鳴らす
void beep(int freq, int duration, uint8_t volume) {
int t = 1000000 / freq / 2;
unsigned long start = millis();
while ((millis() - start) < duration) {
dacWrite(SPEAKER_PIN, 0);
delayMicroseconds(t);
dacWrite(SPEAKER_PIN, volume);
delayMicroseconds(t);
}
dacWrite(SPEAKER_PIN, 0);
}
■メモ
【M5Stack入門】初心者におすすめしたい情報まとめ|はやぶさの技術ノート
https://cpp-learning.com/m5stack/
初心者向けM5Stackの始め方(ArduinoIDE編) | ラズパイ好きの日記
https://raspberrypi.mongonta.com/howto-start-m5stack-arduinoide/
【M5Stack入門】できること・使い方 | 技術雑記
https://algorithm.joho.info/m5stack/m5stack-how-to-use/
M5Stackであそぼう - スイッチサイエンス マガジン
https://mag.switch-science.com/2018/02/28/getting-started-with-m5stack/
「M5Stack」と3G拡張ボードでお手軽IoT「雨雲レーダーの表示デバイス」を作ろう (1/4):CodeZine(コードジン)
https://codezine.jp/article/detail/11689
M5Camera画像をHTTP GETしてM5Stackで表示! | JetLoger
https://jetloger.com/m5stack-m5camera-capture-lcd/
M5Stackで画像処理 -静止画の表示から動画作成まで-|はやぶさの技術ノート
https://cpp-learning.com/m5stack_image/
M5Stackでいろんなデータを取得・表示してみよう! - Qiita
https://qiita.com/kuracux/items/094118a495bf9efa445f
【M5Stack】Arduino IDEでの書き込みが絶望的に遅いのでPlatform IOを試してみた - Qiita
https://qiita.com/tatsuya1970/items/ceeb5a5b011d53910fbb