
2025/12/03 3:48
Minimum Viable Arduino Project: Aeropress Timer
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Summary
このプロジェクトは、Adafruit Trinket M0 マイクロコントローラを中心に構築されたUSB電源付きの30秒タイマーで、Aeropress コーヒーマシン用です。
- ハードウェア: アルミニウム製プッシュボタンが1つだけで、Pin 0 と GND に接続されます。内部プルアップ抵抗を利用してデバウンス処理を行います。Pin 1 にはピエゾブザーがあり、オーディオフィードバックを提供します。Trinket の内蔵 Neopixel RGB LED は毎秒緑色に点滅し、経過した各秒を視覚的に確認できます。
- ファームウェア: コードはボタンのデバウンスを 30 ms の遅延で行い、押下時に1秒間隔のループを開始します。開始と終了時には短く chirp 音が鳴り、タイマー完了後に LED をオフにします。小規模なカラー テストルーチンで緑と赤の配線が正しいこと(初期は逆だった)を確認しました。
- エンクロージャ: デバイスは OpenSCAD で設計された単一ユニボディ3Dプリントパーツに収められています。統合ブザークリップがあり、以前のレーザーカット木製プロトタイプを置き換えました。USB 電源が基板に供給され、Trinket の側スロットから LED がキッチンカウンターへ照射されます。
- 範囲と将来作業: 本設計はバッテリー充電回路やディープスリープモードを意図的に省略し、構築時間を数時間の週末作業に抑えています。予定される改良点には、ブザーの二進制モード調整、LED の再配置による照射改善、あるいはより高度なタイミングオプションの追加が含まれます。
完成したツールは低コストでプラグ&プレイ可能であり、複雑な電力管理を必要とせずに信頼性の高いタイミングとフィードバックを提供できることを示しています。
本文
プロジェクト概要
これは最小限ながら実用的な Arduino プロジェクトです。Adafruit Trinket M0 をベースに、エアロプレス用の専用 30 秒タイマーを作成します。
-
ハードウェア
- Trinket M0(USB 電源)
- アルミ製ボタン(ピン 0 に接地、内部プルアップ使用)
- ピエゾブザー(ピン 1)
- ボード上の Neopixel RGB LED(視覚フィードバック用)
-
筐体
- OpenSCAD で設計し、Ultimaker で印刷
- シングルユニボディ構造。ブザー用クリップと USB ポートが側面開口にフラッシュ
このタイマーの必要性
エアロプレスは正確に 30 秒後にプランジを行う必要がありますが、手動でタイマーを設定すると誤差が生じやすいです。本プロジェクトは簡単で電池不要な設計で、USB に接続したままで使用できるため、その煩わしさを解消します。
コード
#include <Adafruit_DotStar.h> const int PIN_BUTTON = 0; const int PIN_BUZZER = 1; Adafruit_DotStar strip(1, 7, 8, DOTSTAR_BGR); void setup() { pinMode(PIN_BUTTON, INPUT_PULLUP); pinMode(PIN_BUZZER, OUTPUT); digitalWrite(PIN_BUZZER, LOW); strip.begin(); strip.setBrightness(255); colorTest(); // 電源投入時に LED テスト } void colorTest() { const unsigned int COLORS[] = { strip.Color(0, 0, 0), // 消灯 strip.Color(255, 0, 0), // 赤 strip.Color(0, 0, 0), strip.Color(0, 255, 0), // 緑 strip.Color(0, 0, 0), strip.Color(0, 0, 255), // 青 strip.Color(0, 0, 0) }; for (int i = 0; i < 7; ++i) { strip.setPixelColor(0, COLORS[i]); strip.show(); delay(100); } } void loop() { const int TIMER_DURATION = 30; // 秒 waitForButton(); // ユーザー入力待ち startBeep(); // 短いブザーで確認音 for (int sec = 0; sec < TIMER_DURATION; ++sec) { strip.setPixelColor(0, strip.Color( 0, (sec % 2 == 0) ? 0 : 255, // 毎秒緑色を点滅 0)); strip.show(); delay(1000); } endBeep(); // タイマー終了通知 strip.setPixelColor(0, strip.Color(0, 0, 0)); strip.show(); } void waitForButton() { int previous = HIGH; unsigned long lastDebounce = 0; const unsigned long debounceDelay = 30; while (true) { int state = digitalRead(PIN_BUTTON); if (state != previous) { lastDebounce = millis(); previous = state; } if ((millis() - lastDebounce) > debounceDelay && state == LOW) { return; // ボタンが押された } } } void startBeep() { digitalWrite(PIN_BUZZER, HIGH); delay(40); digitalWrite(PIN_BUZZER, LOW); } void endBeep() { for (int i = 0; i < 3; ++i) { digitalWrite(PIN_BUZZER, HIGH); delay(20); digitalWrite(PIN_BUZZER, LOW); delay(250); } }
結果
タイマーはキッチンに設置されます。眠そうなユーザーが朝にボタンを押すだけで、デバイスは一度ブザー音を鳴らし、緑色LEDを点滅させながら 30 秒カウントダウンします。そして再びブザーで終了を知らせ、エアロプレスのプランジ作業へ移行できるようにします。