👻
M5 Atom Matrixの環境構築から実行まで
Arduino IDE環境構築方法
ArduinoIDEのダウンロード先
ライブラリーのインポート
参考サイトhttps://2kuru.com/m5stack_atom_matrix_spec/
追加のボードマネージャURLに以下のURLを追加します。https://dl.espressif.com/dl/package_esp32_index.json
ボードマネージャを開き「esp32」を検索してインストールします。
(この今選択している所の隣の箇所です)
ATOMシリーズを使う場合はボード情報に
ツール > ボード >ESP32 Arduino > ESP32 Pico Kit または
ツール > ボード >ESP32 Arduino > M5Stick-C を選択します
スケッチ例の実行
「ファイル」>「スケッチ例」>「M5Atom」>「Basics」>「Buttom」を開き、「ATOM Matrix」に書き込みます。
そうするとボタンで色が変わるライトを書き込めます。
他にさまざまな表現ができるサンプルコード事例
今回は自身が用意したコードになります。
加速度で色が変わるコード
これは傾きで色が変わるコードです。
シリアルモニターを使ってどのように値が変わるのかを見てみましょう
#include "M5Atom.h"
uint8_t DisBuff[2 + 5 * 5 * 3]; // RGB色値を格納するためのバッファ
float accX = 0, accY = 0, accZ = 0;
bool IMU6886Flag = false;
void setBuff(uint8_t Rdata, uint8_t Gdata, uint8_t Bdata) {
DisBuff[0] = 0x05; // 行数
DisBuff[1] = 0x05; // 列数
for (int i = 0; i < 25; i++) { // 各LEDに色を設定
DisBuff[2 + i * 3 + 0] = Rdata;
DisBuff[2 + i * 3 + 1] = Gdata;
DisBuff[2 + i * 3 + 2] = Bdata;
}
}
void setup() {
M5.begin(true, false, true); // Atom-Matrixの初期化(シリアルポート、LEDの初期化)
Serial.begin(115200); // シリアルモニタの初期化
if (M5.IMU.Init() != 0)
IMU6886Flag = false;
else
IMU6886Flag = true;
delay(10); // 10msの遅延
setBuff(0x00, 0x00, 0x00); // 初期状態でLEDを消灯
M5.dis.displaybuff(DisBuff); // LEDに初期色を表示
}
void loop() {
if (IMU6886Flag == true) {
M5.IMU.getAccelData(&accX, &accY, &accZ); // 加速度データを取得
// デバッグ: 加速度データをシリアルモニタに表示
Serial.printf("accX: %.2f, accY: %.2f, accZ: %.2f\r\n", accX * 1000, accY * 1000, accZ * 1000);
// 傾きに応じてRGB値を設定
uint8_t Rdata = map(accX * 1000, -1000, 1000, 0, 255);
uint8_t Gdata = map(accY * 1000, -1000, 1000, 0, 255);
uint8_t Bdata = map(accZ * 1000, -1000, 1000, 0, 255);
setBuff(Rdata, Gdata, Bdata); // LEDに色を設定
M5.dis.displaybuff(DisBuff); // LEDに色を表示
}
delay(100); // 100msの遅延
M5.update(); // 状態の更新
}
時間で色が変わるコード
プログラミングは関数や変数という様々な機能を持ったパーツのような物を組み合わせています。
今回は一か所を変えると光る色の順番と秒数を変えられるコードを作りました。
#include "M5Atom.h"
uint8_t DisBuff[2 + 5 * 5 * 3]; // RGB色値を格納するためのバッファ
unsigned long previousMillis = 0; // 前回の更新時刻
const long interval = 10000; // 色の遷移間隔 (ミリ秒単位)
int currentColor = 0; // 現在の色インデックス
int transitionStep = 0; // 色の遷移ステップ数
const int transitionSpeed = 5; // 遷移速度 (小さいほど速い)
// 色の順番を定義
enum Color { RED, GREEN, BLUE, NUM_COLORS };
// 色の順序を変更するには、ここで順番を変えます
Color colorOrder[NUM_COLORS] = { GREEN, BLUE, RED }; // 順番を変更する部分
// 遷移にかける時間(秒単位)
const float transitionDurationSec = 10.0; // 10秒間隔
void setBuff(uint8_t Rdata, uint8_t Gdata, uint8_t Bdata) {
DisBuff[0] = 0x05; // 行数
DisBuff[1] = 0x05; // 列数
for (int i = 0; i < 25; i++) { // 各LEDに色を設定
DisBuff[2 + i * 3 + 0] = Rdata;
DisBuff[2 + i * 3 + 1] = Gdata;
DisBuff[2 + i * 3 + 2] = Bdata;
}
}
void setup() {
M5.begin(true, false, true); // Atom-Matrixの初期化(シリアルポート、LEDの初期化)
Serial.begin(115200); // シリアルモニタの初期化
delay(10); // 10msの遅延
setBuff(0xFF, 0x00, 0x00); // 初期状態でLEDを赤色に設定
M5.dis.displaybuff(DisBuff); // LEDに初期色を表示
}
void setColorOrder(Color order[]) {
for (int i = 0; i < NUM_COLORS; i++) {
colorOrder[i] = order[i];
}
}
void loop() {
unsigned long currentMillis = millis(); // 現在の時間を取得
// 色の遷移間隔に基づくタイミング管理
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // 更新時刻を保存
currentColor = (currentColor + 1) % NUM_COLORS; // 次の色に切り替え
transitionStep = 0; // 遷移ステップをリセット
}
// 現在の色と次の色を決定
uint8_t Rdata = 0, Gdata = 0, Bdata = 0;
uint8_t RdataNext = 0, GdataNext = 0, BdataNext = 0;
// 現在の色を決定
switch (colorOrder[currentColor]) {
case RED:
Rdata = 255;
Gdata = 0;
Bdata = 0;
break;
case GREEN:
Rdata = 0;
Gdata = 255;
Bdata = 0;
break;
case BLUE:
Rdata = 0;
Gdata = 0;
Bdata = 255;
break;
}
// 次の色を決定
switch (colorOrder[(currentColor + 1) % NUM_COLORS]) {
case RED:
RdataNext = 255;
GdataNext = 0;
BdataNext = 0;
break;
case GREEN:
RdataNext = 0;
GdataNext = 255;
BdataNext = 0;
break;
case BLUE:
RdataNext = 0;
GdataNext = 0;
BdataNext = 255;
break;
}
// グラデーションの計算
float transitionRatio = (float)transitionStep / 255;
uint8_t RdataFinal = Rdata + (RdataNext - Rdata) * transitionRatio;
uint8_t GdataFinal = Gdata + (GdataNext - Gdata) * transitionRatio;
uint8_t BdataFinal = Bdata + (BdataNext - Bdata) * transitionRatio;
setBuff(RdataFinal, GdataFinal, BdataFinal); // LEDに色を設定
M5.dis.displaybuff(DisBuff); // LEDに色を表示
transitionStep += transitionSpeed; // 遷移ステップを更新
if (transitionStep > 255) {
transitionStep = 255; // 遷移ステップの最大値を設定
}
// 適切な遷移速度を調整
int transitionDelay = (transitionDurationSec * 1000) / 255; // 遷移速度に基づくミリ秒単位の遅延
delay(transitionDelay); // 遷移速度に基づく遅延
M5.update(); // 状態の更新
}
文字列の表示
一文字ずつ英文字を表示できるようにしたコードです。
#include "M5Atom.h"
const uint8_t FONTDATA[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x0, 0x8, 0xa, 0x4a, 0x40, 0x0, 0x0, 0xa, 0x5f, 0xea, 0x5f, 0xea, 0xe, 0xd9, 0x2e, 0xd3, 0x6e, 0x19, 0x32, 0x44, 0x89, 0x33, 0xc, 0x92, 0x4c, 0x92, 0x4d, 0x8, 0x8, 0x0, 0x0, 0x0, 0x4, 0x88, 0x8, 0x8, 0x4, 0x8, 0x4, 0x84, 0x84, 0x88, 0x0, 0xa, 0x44, 0x8a, 0x40, 0x0, 0x4, 0x8e, 0xc4, 0x80, 0x0, 0x0, 0x0, 0x4, 0x88, 0x0, 0x0, 0xe, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x1, 0x22, 0x44, 0x88, 0x10, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x4, 0x8c, 0x84, 0x84, 0x8e, 0x1c, 0x82, 0x4c, 0x90, 0x1e, 0x1e, 0xc2, 0x44, 0x92, 0x4c, 0x6, 0xca, 0x52, 0x5f, 0xe2, 0x1f, 0xf0, 0x1e, 0xc1, 0x3e, 0x2, 0x44, 0x8e, 0xd1, 0x2e, 0x1f, 0xe2, 0x44, 0x88, 0x10, 0xe, 0xd1, 0x2e, 0xd1, 0x2e, 0xe, 0xd1, 0x2e, 0xc4, 0x88, 0x0, 0x8, 0x0, 0x8, 0x0, 0x0, 0x4, 0x80, 0x4, 0x88, 0x2, 0x44, 0x88, 0x4, 0x82, 0x0, 0xe, 0xc0, 0xe, 0xc0, 0x8, 0x4, 0x82, 0x44, 0x88, 0xe, 0xd1, 0x26, 0xc0, 0x4, 0xe, 0xd1, 0x35, 0xb3, 0x6c, 0xc, 0x92, 0x5e, 0xd2, 0x52, 0x1c, 0x92, 0x5c, 0x92, 0x5c, 0xe, 0xd0, 0x10, 0x10, 0xe, 0x1c, 0x92, 0x52, 0x52, 0x5c, 0x1e, 0xd0, 0x1c, 0x90, 0x1e, 0x1e, 0xd0, 0x1c, 0x90, 0x10, 0xe, 0xd0, 0x13, 0x71, 0x2e, 0x12, 0x52, 0x5e, 0xd2, 0x52, 0x1c, 0x88, 0x8, 0x8, 0x1c, 0x1f, 0xe2, 0x42, 0x52, 0x4c, 0x12, 0x54, 0x98, 0x14, 0x92, 0x10, 0x10, 0x10, 0x10, 0x1e, 0x11, 0x3b, 0x75, 0xb1, 0x31, 0x11, 0x39, 0x35, 0xb3, 0x71, 0xc, 0x92, 0x52, 0x52, 0x4c, 0x1c, 0x92, 0x5c, 0x90, 0x10, 0xc, 0x92, 0x52, 0x4c, 0x86, 0x1c, 0x92, 0x5c, 0x92, 0x51, 0xe, 0xd0, 0xc, 0x82, 0x5c, 0x1f, 0xe4, 0x84, 0x84, 0x84, 0x12, 0x52, 0x52, 0x52, 0x4c, 0x11, 0x31, 0x31, 0x2a, 0x44, 0x11, 0x31, 0x35, 0xbb, 0x71, 0x12, 0x52, 0x4c, 0x92, 0x52, 0x11, 0x2a, 0x44, 0x84, 0x84, 0x1e, 0xc4, 0x88, 0x10, 0x1e, 0xe, 0xc8, 0x8, 0x8, 0xe, 0x10, 0x8, 0x4, 0x82, 0x41, 0xe, 0xc2, 0x42, 0x42, 0x4e, 0x4, 0x8a, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x8, 0x4, 0x80, 0x0, 0x0, 0x0, 0xe, 0xd2, 0x52, 0x4f, 0x10, 0x10, 0x1c, 0x92, 0x5c, 0x0, 0xe, 0xd0, 0x10, 0xe, 0x2, 0x42, 0x4e, 0xd2, 0x4e, 0xc, 0x92, 0x5c, 0x90, 0xe, 0x6, 0xc8, 0x1c, 0x88, 0x8, 0xe, 0xd2, 0x4e, 0xc2, 0x4c, 0x10, 0x10, 0x1c, 0x92, 0x52, 0x8, 0x0, 0x8, 0x8, 0x8, 0x2, 0x40, 0x2, 0x42, 0x4c, 0x10, 0x14, 0x98, 0x14, 0x92, 0x8, 0x8, 0x8, 0x8, 0x6, 0x0, 0x1b, 0x75, 0xb1, 0x31, 0x0, 0x1c, 0x92, 0x52, 0x52, 0x0, 0xc, 0x92, 0x52, 0x4c, 0x0, 0x1c, 0x92, 0x5c, 0x90, 0x0, 0xe, 0xd2, 0x4e, 0xc2, 0x0, 0xe, 0xd0, 0x10, 0x10, 0x0, 0x6, 0xc8, 0x4, 0x98, 0x8, 0x8, 0xe, 0xc8, 0x7, 0x0, 0x12, 0x52, 0x52, 0x4f, 0x0, 0x11, 0x31, 0x2a, 0x44, 0x0, 0x11, 0x31, 0x35, 0xbb, 0x0, 0x12, 0x4c, 0x8c, 0x92, 0x0, 0x11, 0x2a, 0x44, 0x98, 0x0, 0x1e, 0xc4, 0x88, 0x1e, 0x6, 0xc4, 0x8c, 0x84, 0x86, 0x8, 0x8, 0x8, 0x8, 0x8, 0x18, 0x8, 0xc, 0x88, 0x18, 0x0, 0x0, 0xc, 0x83, 0x60};
/*
* 文字列をスライドで表示
*/
void dispCharS(const char mes[], uint8_t R, uint8_t G, uint8_t B, uint8_t Rb = 0, uint8_t Gb = 0, uint8_t Bb = 0) {
uint8_t DisBuffString[2 + 5 * 5 * 3];
DisBuffString[0] = 0x05;
DisBuffString[1] = 0x05;
int len = strlen(mes);
for (int j = 0; j < len; j++) {
char str = mes[j];
if (str < 32 || str > 127) {
Serial.println("dispChar Error...");
continue;
}
int start = ((int)str - 32) * 5;
for (int row = 0; row < 5; row++) {
for (int i = 0; i < 5; i++) {
if ((FONTDATA[start + row] & (1 << (4 - i))) != 0) {
DisBuffString[2 + ((row) * 5 + i) * 3 + 0] = R;
DisBuffString[2 + ((row) * 5 + i) * 3 + 1] = G;
DisBuffString[2 + ((row) * 5 + i) * 3 + 2] = B;
} else {
DisBuffString[2 + ((row) * 5 + i) * 3 + 0] = Rb;
DisBuffString[2 + ((row) * 5 + i) * 3 + 1] = Gb;
DisBuffString[2 + ((row) * 5 + i) * 3 + 2] = Bb;
}
}
}
M5.dis.displaybuff(DisBuffString);
if (len > 1) {
delay(400);
for (int i = 0; i < 25; i++) {
DisBuffString[2 + i * 3 + 0] = Rb;
DisBuffString[2 + i * 3 + 1] = Gb;
DisBuffString[2 + i * 3 + 2] = Bb;
}
M5.dis.displaybuff(DisBuffString);
delay(50);
}
}
}
/*
* 1文字を表示する(コードを数値で指定することも可能)
*/
void dispChar(char str, uint8_t R, uint8_t G, uint8_t B, uint8_t Rb = 0, uint8_t Gb = 0, uint8_t Bb = 0) {
if (str < 32 || str > 127) {
Serial.println("dispChar Error...");
return;
}
uint8_t DisBuffString[2 + 5 * 5 * 3];
DisBuffString[0] = 0x05;
DisBuffString[1] = 0x05;
int start = ((int)str - 32) * 5;
for (int row = 0; row < 5; row++) {
for (int i = 0; i < 5; i++) {
if ((FONTDATA[start + row] & (1 << (4 - i))) != 0) {
DisBuffString[2 + ((row) * 5 + i) * 3 + 0] = R;
DisBuffString[2 + ((row) * 5 + i) * 3 + 1] = G;
DisBuffString[2 + ((row) * 5 + i) * 3 + 2] = B;
} else {
DisBuffString[2 + ((row) * 5 + i) * 3 + 0] = Rb;
DisBuffString[2 + ((row) * 5 + i) * 3 + 1] = Gb;
DisBuffString[2 + ((row) * 5 + i) * 3 + 2] = Bb;
}
}
}
M5.dis.displaybuff(DisBuffString);
}
void setup() {
M5.begin(true, false, true);
}
void loop() {
// 文字列を表示変更
dispCharS("HEY", 0xff, 0x8c, 0x0, 0, 0, 0); // Orange
delay(2000); // 表示が終わったら少し待つ
}
ビルドエラーが起こった場合
In file included from C:\XXXX\user\AppData\Local\Temp\.arduinoIDE-unsaved2024631-10260-1q3exql.th2f\Button\Button.ino:14: C:\XXXX\user\Documents\Arduino\libraries\M5Atom\src/M5Atom.h:82:8: error: extended character “ is not valid in an identifier 82 | #error “This library only supports boards with ESP32 processor.” | ^ C:\XXXX\user\Documents\Arduino\libraries\M5Atom\src/M5Atom.h:82:64: error: extended character ” is not valid in an identifier 82 | #error “This library only supports boards with ESP32 processor.” | ^ exit status 1 Compilation error: exit status 1
解決方法
M5Atom.hファイルを開く:
C:\XXXX\user\Documents\Arduino\libraries\M5Atom\src\M5Atom.h
ファイルをテキストエディタで開きます。
問題のある引用符を修正する: 次の行を見つけます。
#error “This library only supports boards with ESP32 processor.”
この行の引用符(“ と ”)を標準のダブルクオート(")に置き換えます。
#error "This library only supports boards with ESP32 processor."
ファイルを保存して閉じる。
これでコンパイルエラーが解消されるはずです。
Discussion