いろんな事情から、ATOMS3 LITEを買ったので使ってみる。買ったのはだいぶ前なのだけど、ついつい放置しがちで必要にならないとさわらない。

買ったままで通電すると、出荷時の検査に使われたと思われるプログラムが動作している。多色LEDが色変わりで点灯し、シリアルコンソールには状態が表示されている。

AP:
SSID: ATOM-S3-B08184952EE4
PSWD: 88888888
IP address: 192.168.4.1
WiFi scan start
Send command 0x21 to address 0x2ee4
BLE update ok
IR Send >>> addr:2EE4 cmd:21
BLE update ok
Send command 0x22 to address 0x2ee4
IR Send >>> addr:2EE4 cmd:22
BLE update ok
Send command 0x23 to address 0x2ee4
IR Send >>> addr:2EE4 cmd:23
WiFi scan done
9 networks found
1: MyPiAP (-42)*
2: ESP_0E1F69 (-55)
3: ESP_085409 (-61)
4: MyPlace (-75)*
5: DIRECT-GMMFCBROTHER101 (-79)*
6: IODATA-899760-2G (-92)*
7: HR02a-02A81D (-93)*
8: IO-Guest-899760-2G (-94)*
9: SGP200W-BBAA-bg (-94)*
(snip)
UDP broadcast OK
WiFi scan total: 9
1. MyPiAP -42BLE update ok
Send command 0x24 to address 0x2ee4
IR Send >>> addr:2EE4 cmd:24
UDP broadcast OK
BLE update ok
APモードも動いているようだ。何が動いているのかは確認してみたけれど、Webは動いていないみたい。あくまで、ハードウエアの動作確認用ということかな。
まずは、ボードマネージャのM5Stackをアップデートする。

次のライブラリマネージャーもアップデートする。ATOMS3 LITE向けのライブラリはないようだ。一応、M5AtomS3とM5GFXをアップデートしておく。

ATOMS3 LITE用のライブラリはないので、M5Unifiedを使うようにということだ。しかし、ボタンのサンプルだけでもATOMS3 LITEでは不要な機能ばかりが含まれていて、まったく初心者向けではない。
M5Stack社としては、コーディングはUIFlowでGUIでやってねというスタンスのようだ。ブロックモジュールに機能が隠蔽されてしまって、まったくよくないと思う。
とりあえず、ボタンのサンプルスケッチをATOMS3 LITEで利用する部分だけにダイエットしてみると、こんなに短くなった。理解もしやすい。
#include <M5Unified.h>
void setup(void){
M5.begin();
}
void loop(void){
M5.update();
// ボタンの状態を表す文字列の配列
static constexpr const char* const names[] = { "none", "wasHold", "wasClicked", "wasPressed", "wasReleased", "wasDecideClickCount" };
// BtnAの状態を判定
int state = M5.BtnA.wasHold() ? 1
: M5.BtnA.wasClicked() ? 2
: M5.BtnA.wasPressed() ? 3
: M5.BtnA.wasReleased() ? 4
: M5.BtnA.wasDecideClickCount() ? 5
: 0;
// stateが0でない場合(つまり、何らかのボタンイベントが発生した場合)
if (state){
// シリアルモニターにイベントの種類とクリック回数を表示
M5.Log.printf("BtnA:%s count:%d\n", names[state], M5.BtnA.getClickCount());
}
M5.delay(1);
}
M5Unifiedでは機種判定が抽象化されているので、自分でどのハードウエアを使っているのか気にする必要はない。でも、それでいいんだろうかな?
しかし、M5Unified対応デバイスはGithubのリポジトリを見ろということになっている。なんだかな... ATOMS3 LITEは対応している。
m5stack/M5Unified: Unified library for M5Stack series
https://github.com/m5stack/M5Unified
ボードの判定はM5.begin()の中で行われ、M5.getBoard()で結果が取得できる。
M5Unified Library Data Definitions
https://docs.m5stack.com/en/arduino/m5unified/m5unified_appendix
M5Unifiedではボタンの処理も抽象化されていて、ライブラリから以下のステイトが取得できる。正直普通のボタン検知だと、ここまでいらないと思うのだけど。ゲームとかやるのに必要なのかな...
M5Unified Button Class
https://docs.m5stack.com/ja/arduino/m5unified/button_class
isPressed():押されている間ずっと true(レベル)
wasPressed():押した瞬間だけ true(立ち上がりエッジ)
isReleased():離されている間ずっと true(レベル)
wasReleased():離した瞬間だけ true(立ち下がりエッジ)
wasClicked():クリック成立の瞬間だけ true(デバウンス済み)
wasHold():長押しが成立した瞬間だけ true
isHolding():長押し成立中は true(レベル)
wasDecideClickCount():連続クリック数(シングル/ダブル…)が確定した瞬間だけ true
getClickCount():直近で確定したクリック数(1, 2, 3…)
スケッチでは、M5.updat()でボタンAの状態を読み取り、その結果をログとして出力している。
Arduinoスケッチでよくみる、以下のようなシリアルの初期化がない。
Serial.begin(115200);
Serial.println("ATOM S3 Lite Button Test Start");
これも、M5Unifiedが初期化して隠蔽している。ただし、通信速度は固定のようなので、必要があれば自分で初期化してもいい。
ATOMS3 LITEが採用しているESP32-S3では、「USB書き込み」はROMブートローダが提供する機能で、これはダウンロードモード(GPIO0=LOWでリセット)時だけ起動する。そのために、スケッチをビルドして書き込む前に、サイドのボタンを長押しして書き込みモードにしておく必要がある。この長押しが有効な場合、ATOMS3 LITEでは緑色のLEDが点灯する。
通常のプログラム実行中は、ユーザアプリがUSBを占有しており、PC側のesptool.pyはROMブートローダと通信できないので、何もしないと書き込みに失敗してしまう。
プログラムの書き込みが終わったら、電源を入れ直してリセットする。ボタンを押すと、シリアルコンソールに文字が出てきた。

なんだか面倒なので、M5Unifiedに頼らないスケッチに変更する。ボタンの状態判定の結果を多色LEDに反映させてみる。もっとも、ボタンを指で押すとLEDは隠れてしまうのだけど。
// NeoPixel LEDを制御するためのライブラリ
#include <Adafruit_NeoPixel.h>
// ATOM S3 Liteのハードウェアピン定義
const int BUTTON_PIN = 41; // ボタンが接続されているGPIOピン
const int LED_PIN = 35; // NeoPixel LEDのデータピン
// 多色LEDの設定
Adafruit_NeoPixel pixels(1, LED_PIN, NEO_GRB + NEO_KHZ800);
// ボタンの状態を管理するための変数
bool lastButtonState = HIGH; // 前回のボタンの状態 (HIGH=離されている)
unsigned long pressStartTime = 0; // ボタンが押され始めた時間
const unsigned long HOLD_TIME_MS = 500; // 長押しと判定する時間 (ミリ秒)
void setup() {
Serial.begin(115200); // シリアル通信の初期化
Serial.println("ATOM S3 Lite Button Test");
// ボタンピンを入力モードに設定し、内部プルアップを有効にする
// (ATOM S3 Liteは外部プルアップがあるため必須ではない)
pinMode(BUTTON_PIN, INPUT_PULLUP);
// 多色LEDの初期化
pixels.begin();
pixels.clear(); // LEDを消灯状態にする
pixels.show(); // 状態をLEDに反映
}
void loop() {
// 現在のボタンの状態を読み取る (押されているとLOW, 離されているとHIGH)
bool currentButtonState = digitalRead(BUTTON_PIN);
// --- ボタンが押された瞬間 (HIGH -> LOW) ---
if (lastButtonState == HIGH && currentButtonState == LOW) {
pressStartTime = millis(); // 押された時間を記録
Serial.println("Button Pressed");
}
// --- ボタンが離された瞬間 (LOW -> HIGH) ---
else if (lastButtonState == LOW && currentButtonState == HIGH) {
// 押されていた時間を計算
unsigned long pressDuration = millis() - pressStartTime;
// 押されていた時間が短ければ「クリック」と判定
if (pressDuration < HOLD_TIME_MS) {
Serial.println("-> Clicked!");
pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // 緑色に点灯
pixels.show();
}
// 離した瞬間にLEDを消す(指の下なので見えないだろうけど)
pixels.clear();
pixels.show();
}
// --- ボタンが押され続けている間 (LOWのまま) ---
if (currentButtonState == LOW) {
// 押されている時間が長押し時間を超えたかチェック
if (millis() - pressStartTime > HOLD_TIME_MS) {
// 「長押し」と判定
Serial.println("-> Held!");
pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // 赤色に点灯
pixels.show();
}
}
// 次のループのために、現在のボタンの状態を保存
lastButtonState = currentButtonState;
// CPUの負荷を下げるための短い待機
delay(20);
}

作成されたバイナリも三割強ダイエットされている。
M5Unified:
Wrote 471424 bytes (258683 compressed) at 0x00010000 in 3.2 seconds (1175.2 kbit/s).
nonM5Unified:
Wrote 323456 bytes (173751 compressed) at 0x00010000 in 2.5 seconds (1036.7 kbit/s).
100円投げ銭 https://kinneko.booth.pm/items/1963720
オリジナル投稿:
ATOMS3 LITEを使ってみる|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/10460262



