🍅
M5StackCore2(C)でポモドーロタイマーを作った
作ったもの
- ポモドーロタイマー(トマトタイマー)
- 例えば、赤画面(25分)→緑画面(5分)を無限ループする
- 設定変更には書き込みが必要
- タイマーが0になったときに音を鳴らす(+バイブレーション)
- 立てると実行、倒して画面を上に向けると一時停止
- 右ボタンで一時停止してリセットするか確認(左ボタン:YES、中ボタン:NO)
TODO
- メニューダイアログで設定を変えられるようにしたい
デモ
(デモ用に赤10秒、緑5秒)
コード
M5Core2 Version 0.1.5
音を鳴らす部分は公式のisoをそのまま使っています。
-
workTimer_sec
、breakTimer_sec
で2つのタイマー時間(秒)を設定
#include <M5Core2.h>
#include <Wire.h>
const int workTimer_sec = 10; // Total time in seconds for the work timer
const int breakTimer_sec = 5; // Total time in seconds for the break timer
enum TimerState {
STOPPED,
RUNNING,
FINISHED
};
enum Orientation {
Up,
Side
};
TimerState timerState = STOPPED;
int remainingTime = workTimer_sec; // Initialize with the work timer duration
bool workTimer = true; // true: work timer (workTimer_sec), false: break timer (breakTimer_sec)
bool resetPrompt = false;
Orientation getOrientation(float xOffset = 0.0, float yOffset = 0.0, float threshold = 0.5) {
float ax, ay, az;
M5.IMU.getAccelData(&ax, &ay, &az);
ax -= xOffset;
ay -= yOffset;
if (abs(ax) > threshold || abs(ay) > threshold) {
return Side;
}
return Up; // Default orientation
}
void displayTime(int minutes, int seconds, uint32_t bgColor) {
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setBrightness(200);
M5.Lcd.fillScreen(bgColor);
String timeStr = "";
if (minutes < 10) {
timeStr += "0";
}
timeStr += String(minutes) + ":";
if (seconds < 10) {
timeStr += "0";
}
timeStr += String(seconds);
M5.Lcd.setTextFont(7);
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(320 / 2 - 75, 240 / 2 - 25);
M5.Lcd.print(timeStr);
}
void displayResetPrompt() {
M5.Lcd.setTextFont(1);
M5.Lcd.setTextSize(2);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setBrightness(200);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(60, 150);
M5.Lcd.print("Reset?");
M5.Lcd.setCursor(40, 200);
M5.Lcd.print("Yes");
M5.Lcd.setCursor(150, 200);
M5.Lcd.print("No");
}
void setup() {
M5.begin();
M5.Lcd.begin();
M5.IMU.Init();
M5.Lcd.setBrightness(200);
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
}
void loop() {
M5.update();
if (resetPrompt) {
if (M5.BtnA.wasPressed()) {
resetPrompt = false;
workTimer = true;
remainingTime = workTimer_sec;
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
} else if (M5.BtnB.wasPressed()) {
resetPrompt = false;
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
}
return;
}
static uint32_t timerStart = millis();
static uint32_t elapsedTime = 0;
Orientation orientation = getOrientation(0.0, 0.0, 0.5);
if (orientation == Side && (timerState == STOPPED || timerState == RUNNING)) {
timerState = RUNNING;
if (millis() - timerStart >= 1000) {
elapsedTime += 1000;
timerStart = millis();
remainingTime--;
if (remainingTime >= 0) {
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
} else {
// Timer has finished
M5.Axp.SetLDOEnable(3, true);
delay(100);
M5.Axp.SetLDOEnable(3, false);
delay(100);
M5.Spk.DingDong();
workTimer = !workTimer; // Switch to the other timer
remainingTime = workTimer ? workTimer_sec : breakTimer_sec;
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
}
}
} else if (orientation == Up) {
timerState = STOPPED;
}
// Right button (Button C) pressed
if (M5.BtnC.wasPressed()) {
resetPrompt = true;
displayResetPrompt();
}
if (resetPrompt) {
if (M5.BtnA.wasPressed()) {
resetPrompt = false;
workTimer = true;
remainingTime = 10;
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
} else if (M5.BtnB.wasPressed()) {
resetPrompt = false;
int minutes = remainingTime / 60;
int seconds = remainingTime % 60;
displayTime(minutes, seconds, workTimer ? RED : GREEN);
}
return;
}
}
まとめ
- M5StackCore2でポモドーロタイマーを作りました
- おおむねChatGPTにコードを書いてもらって細かい修正は自分で
- あまり電池がもたないのがネックかもしれません
Discussion