eepoo が 2021年02月28日17時31分18秒 に編集
コメント無し
本文の変更
世の中のキッチンタイマーはユーザインタフェースがなっとらん!ということで、最小の手間で使えるキッチンタイマーを目指しました。 ![キャプションを入力できます](https://camo.elchika.com/1b1d030e5caefc4639cf2d5bd3aa097461a7f38c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f34646666663835652d323762632d346636312d623232392d303034643363646236616664/) 電源スイッチ以外にはロータリエンコーダだけ! スイッチを入れると電源が入りバッテリーの電圧を表示します。 つまみ(ロータリエンコーダ)を右に回すと設定時間の分をインクリメント。 左に回すと10秒ずつ時間を減らします。 ロータリエンコーダをクリックするとカウントダウンを開始し、0秒で音を鳴らします。 ![中を開いたところはこんな感じ](https://camo.elchika.com/9dbb6067a988de97e235949ab70237f41edcec75/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f35326334326634352d323134632d343738652d626238362d343339633035613539613930/) 上の方にまとまっているのは、背面に取り付けてあるネオジ磁石です。
![ネオジ磁石をワッシャ代わりにして筐体を締結している](https://camo.elchika.com/b3c6560d3dce8bf2272b726f65677abd07dd1ec0/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f64663166623766302d626139622d343663622d626631382d633630656230373762303966/)
バッテリーは携帯電話の電池ですので電圧が下がりすぎないようにしないといけません。なので起動時に電圧を測るようにしています。しかし、電池がマイコンのADCの基準電圧でもあるので、単にADCで測っても客観的に測ることができません。 ツェナーダイオードの電圧との比率でバッテリーの電圧を算出しています。 スピーカーはピエゾスピーカです。ちゃんと使えばどえらい音が鳴るはずなのですが、直接PWM波形を入れるだけにして音圧は控えめにしています。 全部品を3D CADでモデル化し、筐体を設計。3D プリンタで出力。 ![外観](https://camo.elchika.com/7985312ee5d743b2327d75bf088ed44c8069c023/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f61333334303937382d346430622d346234632d623334372d623431323035343936633035/) ![フロントカバーを外したところ](https://camo.elchika.com/41b8787b141297114da83a4c12ce40e4bbc22c71/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f32336163363633302d386661342d346663372d386130312d356262656661663032633631/) ![回路図](https://camo.elchika.com/f77ce4003da7bff2ff37d9bb336c80e9e0052cda/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f66623735373465352d643937352d346165332d383337372d353764376434653932633434/) ソースは以下の通り。 ```キッチンタイマー #define ROTA 3 #define ROTB 4 #define ROTSW 2 #define PWMPIN 9 #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); byte currMin = 0; byte currSec = 0; byte lastROTA = HIGH; byte setTens = 0; byte setMins = 0; byte state = 0;//idle 回転でセット受付 クリック待ち ⇒クリックで 1になる 時刻になると 警告音発する 2 1以上でクリックでリセット bool statusChanged = false; long nextSec = 0; bool first = true; #define BEEPMAX 100 //100回beepしたら自動で止まる #define BUZZONTIME 10 #define BUZZOFFTIME 300 int beepcount = 0; bool buzzOn = false; long nextBuzz = 0; #define LEFTALONE 60000 long leftAlone = LEFTALONE;//これを過ぎたら警告音 #define LFAC 30 byte lfAlarmCount = LFAC; #define STATUSMASK 200 long nextSSReady = 0; bool ssReady = false; void startStop() { if (ssReady) { statusChanged = true; ssReady = false; } } void setup() { //Serial.begin(115200); pinMode(ROTA, INPUT_PULLUP); pinMode(ROTB, INPUT_PULLUP); pinMode(ROTSW, INPUT_PULLUP); pinMode(PWMPIN, OUTPUT); pinMode(A0, INPUT); attachInterrupt(0, startStop, FALLING); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); int voltage = analogRead(A0); float vol = -0.017653 * voltage + 14.40377551; display.setTextSize(4); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); display.print(vol); display.print("V"); display.display(); delay(500); showSetTime(); } void resetLeftAlone() { leftAlone = millis() + LEFTALONE; lfAlarmCount = LFAC; } void showSetTime() { display.clearDisplay(); display.setCursor(0, 0); display.print(setMins); display.setCursor(64, 0); display.println(setTens * 10); display.display(); resetLeftAlone(); } void checkRotation() { bool rotA = digitalRead(ROTA); if (lastROTA == HIGH) { if (rotA == LOW) { byte rotB = digitalRead(ROTB); if (rotB == LOW) { setMins++; setTens = 0; } else {// CCW 10秒戻す if (setTens == 0) {//0秒からなので分桁下がり if (setMins > 0) { setTens = 5; setMins = setMins - 1; } else { setTens = 0; setMins = 0; } } else { setTens = setTens - 1; } } showSetTime(); ssReady = true; delay(50); } } lastROTA = rotA; } void showCurrTime() { display.clearDisplay(); display.display(); display.setTextSize(4); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.print(currMin); display.setCursor(64, 0); display.println(currSec); display.display(); resetLeftAlone(); } void loop() { long curr = millis(); if (curr > leftAlone) { if (lfAlarmCount > 0) { digitalWrite(PWMPIN, HIGH); delay(5); digitalWrite(PWMPIN, LOW); delay(100); digitalWrite(PWMPIN, HIGH); delay(5); digitalWrite(PWMPIN, LOW); delay(100); lfAlarmCount--; leftAlone = curr + 1000; } } //Serial.println(state); if (!ssReady) { if (curr > nextSSReady) { ssReady = true; } } switch (state) { case 0:// idle 分秒セット ロータリスイッチをチェックする checkRotation(); if (statusChanged) { statusChanged = false; nextSSReady = curr + STATUSMASK; state = 1; currMin = setMins; currSec = setTens * 10; nextSec = curr + 1000; } break; case 1://開始されたので、カウントダウンする if ( curr > nextSec) { //Serial.println(millis()); nextSec = nextSec + 1000; if (currSec == 1) { currSec = 0; if (currMin == 0) { //Mode変えてBeepしはじめる state = 2; beepcount = 0; buzzOn = true; } else { currSec = 0; //だけにして次の秒に分桁下がり } } else { if (currSec == 0) { currMin = currMin - 1; currSec = 59; } else { currSec = currSec - 1; } } showCurrTime(); } //クリックで Abort if (statusChanged) { statusChanged = false; nextSSReady = curr + STATUSMASK; state = 0; setMins = 0; setTens = 0; showSetTime(); } break; case 2://beepする if (buzzOn) { digitalWrite(PWMPIN, HIGH); delay(BUZZONTIME); digitalWrite(PWMPIN, LOW); buzzOn = false; beepcount++; nextBuzz = curr + BUZZOFFTIME; } else { if (curr > nextBuzz) { buzzOn = true; } } if (beepcount > BEEPMAX) { digitalWrite(PWMPIN, LOW); state = 0; setMins = 0; setTens = 0; showSetTime(); } //クリックで Beepを止める if (statusChanged) { statusChanged = false; nextSSReady = curr + STATUSMASK; digitalWrite(PWMPIN, LOW); state = 0; setMins = 0; setTens = 0; showSetTime(); } break; } } ```