Простой кухонный таймер 4симв.TM1637, энкодер, аккум.18650
- Войдите на сайт для отправки комментариев
Пт, 21/08/2020 - 17:06
Простой кухонный таймер, после включения энкодером устанавливается количество минут. Долгое нажатие на энкодер запускает таймер. Через 10 секунд бездействия дисплей на минимальную ярскость переходит, через минуту устройство уходит в спящий режим. В режиме непосредственно обратного отсчета через минуту просто отключается дисплей. Нажать на энкодер или повернуть - экран заново загорается.
потребление всей схемы при питании от 5 вольт:
23 мА - индикатор TM1637 на минимальной яркости
21 мА - с отключенным индикатором TM1637
120 мкА - спящий режим МК, ожидание движения энкодера
потребление всей схемы при питании от аккумулятора через повышайку:
50...80 мА - индикаторы на максимальной яркости
29 мА - индикатор TM1637 на минимальной яркости
23 мА - с отключенным индикатором TM1637
520 мкА - спящий режим МК, ожидание движения энкодера
#include "TM1637.h" // https://github.com/DetSimen/TM1637 // http://arduino.ru/forum/otvlechennye-temy/tm1637 #include <avr/sleep.h> #include <avr/interrupt.h> #include <avr/wdt.h> #define min_step_encoder 5 // сколько минут прибавлять/убавлять при одном шелчке энкодера #define pin_sw_encoder 2 // int0 #define pin_clk_encoder 3 // int1 #define pin_dt_encoder 4 #define pin_beeper 5 #define pin_dio_tm1637 8 #define pin_clk_tm1637 9 /* 21.08.2020 atmega328p от кварца 16МГц, потребление всей схемы при питании от 5 вольт 23 мА - индикатор TM1637 на минимальной яркости 21 мА - с отключенным индикатором TM1637 120 мкА - спящий режим МК, ожидание движения энкодера*/ /* 20.08.2020 atmega328p от внутреннего RC генератора 8МГц, потребление всей схемы при питании от 5 вольт 16 мА - индикатор TM1637 на минимальной яркости 14 мА - с отключенным индикатором TM1637 120 мкА - спящий режим МК, ожидание движения энкодера*/ TM1637 Display(pin_clk_tm1637, pin_dio_tm1637, enTM1637Type::Time); volatile int currEncoder; unsigned long timer_every_sec; unsigned char currentSec; unsigned char mainTimerMin; bool mainMode; volatile unsigned long unusedTimer; void setup() { // put your setup code here, to run once: initAll(); } void loop() { // put your main code here, to run repeatedly: if (swEncoder()) { if (mainMode) { offAllAndSleep(); return; } else if (mainTimerMin) { mainMode = true; timer_every_sec = millis(); currentSec = 0; } } signed char cme = moveEncoder(); if ((cme != 0) && (!mainMode)) { changeTimer(cme); showTM1637(false); } if ((millis() - timer_every_sec) >= 1000UL) { timer_every_sec = millis(); if (mainMode) { if (actionTimer()) { initTM1637(); Display.SetBrightness(7); Display.Print("bEEP"); analogWrite(pin_beeper, 255); delay(15000); offAllAndSleep(); return; } } showTM1637(false); } } void initTM1637() { pinMode(pin_clk_tm1637, OUTPUT); pinMode(pin_dio_tm1637, OUTPUT); Display.Start(); } void offTM1637() { Display.Clear(); Display.Stop(); digitalWrite(pin_clk_tm1637, LOW); pinMode(pin_clk_tm1637, INPUT); digitalWrite(pin_dio_tm1637, LOW); pinMode(pin_dio_tm1637, INPUT); } void mcuSleep() { cli(); wdt_disable(); uint8_t x = (MCUCR & ~(1 << BODSE)) | (1 << BODS); MCUCR = x | (1 << BODSE); MCUCR = x; #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif cbi(ADCSRA, ADEN); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); sleep_enable(); sleep_mode(); } void initEncoder() { pinMode(pin_sw_encoder, INPUT); pinMode(pin_dt_encoder, INPUT); pinMode(pin_clk_encoder, INPUT); attachInterrupt(1, intEncoder, FALLING); } void initBeeper() { pinMode(pin_beeper, OUTPUT); digitalWrite(pin_beeper, LOW); } void offBeeper() { digitalWrite(pin_beeper, LOW); pinMode(pin_beeper, INPUT); } bool swEncoder() { static bool lastStatus; static bool currStatus; static bool startCalc = 0; static unsigned long firstTime; currStatus = digitalRead(pin_sw_encoder); if (currStatus != lastStatus) { unusedTimer = millis(); if (!currStatus) { if (!startCalc) { startCalc = true; firstTime = unusedTimer; } } else { startCalc = false; } } else { if (startCalc && (!currStatus)) { if ((millis() - firstTime) >= 3000UL) { startCalc = false; return true; } } } lastStatus = currStatus; return false; } void intEncoder() { static unsigned long lastInt; unusedTimer = millis(); if ((unusedTimer - lastInt) >= 100UL) { if (digitalRead(pin_clk_encoder) == digitalRead(pin_dt_encoder)) ++currEncoder; else --currEncoder; lastInt = unusedTimer; } } signed char moveEncoder() { signed char exitSt = 0; static int lastEncoder; cli(); if (lastEncoder != currEncoder) { if (currEncoder > lastEncoder) exitSt = 1; else exitSt = -1; lastEncoder = currEncoder; } sei(); return exitSt; } void initAll() { initTM1637(); initEncoder(); initBeeper(); mainTimerMin = 0; mainMode = false; unusedTimer = millis(); showTM1637(true); } void offAllAndSleep() { offTM1637(); offBeeper(); mcuSleep(); initAll(); } void showTM1637(bool flReset) { static unsigned char lastSt; // 1-full br 2 - minimal br 3 - off tm1637 if (flReset) { lastSt = 1; Display.SetBrightness(7); Display.Clear(); return; } if ((millis() - unusedTimer) >= 60000UL) { if (lastSt == 3) { return; } else { lastSt = 3; if (mainMode) offTM1637(); else offAllAndSleep(); return; } } else if ((millis() - unusedTimer) >= 10000UL) { if (lastSt != 2) { lastSt = 2; Display.SetBrightness(0); } } else if (lastSt != 1) { if (lastSt == 3) initTM1637(); lastSt = 1; Display.SetBrightness(7); } if (mainMode) { Display.ToggleColon(); if (mainTimerMin > 59) { Display.PrintAt(0, ' '); Display.PrintAt(1, (mainTimerMin / 60 + '0')); Display.PrintAt(2, ((mainTimerMin % 60) / 10 + '0')); Display.PrintAt(3, ((mainTimerMin % 60) % 10 + '0')); } else { if ((mainTimerMin % 60) > 9) Display.PrintAt(0, ((mainTimerMin % 60) / 10 + '0')); else Display.PrintAt(0, ' '); if (mainTimerMin) Display.PrintAt(1, ((mainTimerMin % 60) % 10 + '0')); else Display.PrintAt(1, ' '); Display.PrintAt(2, (currentSec / 10 + '0')); Display.PrintAt(3, (currentSec % 10 + '0')); } } else { Display.PrintAt(0, ' '); if (mainTimerMin > 59) { // show hours Display.ShowPoint(true); Display.PrintAt(1, (mainTimerMin / 60 + '0')); Display.PrintAt(2, ((mainTimerMin % 60) / 10 + '0')); Display.PrintAt(3, ((mainTimerMin % 60) % 10 + '0')); } else { Display.ShowPoint(false); Display.PrintAt(1, ' '); if ((mainTimerMin % 60) > 9) Display.PrintAt(2, ((mainTimerMin % 60) / 10 + '0')); else Display.PrintAt(2, ' '); Display.PrintAt(3, ((mainTimerMin % 60) % 10 + '0')); } } } bool actionTimer() { if (!currentSec) { if (!mainTimerMin) { return true; } else { --mainTimerMin; } currentSec = 59; } else { --currentSec; } return false; } void changeTimer(signed char cmec) { if (cmec == 1) { mainTimerMin += min_step_encoder; if (mainTimerMin >= 240) mainTimerMin = 240; } else { if (mainTimerMin <= min_step_encoder) mainTimerMin = 0; else mainTimerMin -= min_step_encoder; } }
-


Хорошо, но "маловато будет" :)
Мне, частенько, 2 или 3 таймера нужно на кухне. Люблю готовить. Добавив еще одну матрицу и кнопку можно получить 10 таймеров.
Кроме того неплохо-бы сохранять предыдущее значение таймера - крутить не от нуля.
Я все железки делаю под свои простые задачи :) так что развития конкретно данного проекта не будет. Вот с дребезгом контактов не доработал, энкодер пропускает, но надеюсь время найду - доделаю.
Опять же, каждое увеличение функционала - > увеличение кнопок/регуляторов, а в данном случае - просто замена механического таймера газовой плиты Gefest.
Врет mykaida, сдается мне. Тому, кто любит готовить, таймеры не нужны - он время чует. А вот ежели повар вместо готовки форум читает...
andycat, функции TM1637::Start() и TM1637::Stop() это protected функции класса, которые предваряют/завершают передачу данных в дисплей. Для чего ты их приспособил к энергосбережению? Для энергосбережения надо ноги в INPUT переводить и отключать в регистре энергосбережения пошти всё. :)
void TM1637::Start(void) const // выдает старт условие на шину { digitalWrite(FClockPin, HIGH); digitalWrite(FDataPin, HIGH); digitalWrite(FDataPin, LOW); digitalWrite(FClockPin, LOW); } void TM1637::Stop(void) const // выдает стоп условие на шину { digitalWrite(FClockPin, LOW); digitalWrite(FDataPin, LOW); digitalWrite(FClockPin, HIGH); digitalWrite(FDataPin, HIGH); }DetSimen, да когда начинал, понадеялся что это поможет индикаторам поменьше кушать (каюсь - даташит не читал), но не помогло, да так и осталось....
ЗЫ. Из 120 мкА потребления в спящем режиме, 99.99 % это именно индикатор, если переводить схему на более экономный источник питания, не помешает транзисторный ключ. У меня 18650 аккумуляторов много, не стал заморачиваться.
Здравствуйте! Можно схемку на этот таймер?
andycat, что я делаю не так? помогите решить проблему? я не силен в написании кода. смиренно прошу помощи :)
d:\DiskD\Arduino\timer_2\timer_2.ino: In function 'void initTM1637()':
d:\DiskD\Arduino\timer_2\timer_2.ino:77:17: error: 'void TM1637::Start() const' is protected within this context
Display.Start();
^
In file included from d:\DiskD\Arduino\timer_2\timer_2.ino:1:0:
d:\DiskD\Arduino\libraries\TM1637/TM1637.h:54:7: note: declared protected here
void Start(void) const; // выдает старт условие на шину
^~~~~
d:\DiskD\Arduino\timer_2\timer_2.ino: In function 'void offTM1637()':
d:\DiskD\Arduino\timer_2\timer_2.ino:82:16: error: 'void TM1637::Stop() const' is protected within this context
Display.Stop();
^
In file included from d:\DiskD\Arduino\timer_2\timer_2.ino:1:0:
d:\DiskD\Arduino\libraries\TM1637/TM1637.h:56:7: note: declared protected here
void Stop(void) const; // выдает стоп условие на шину
^~~~
Compilation error: Error: 2 UNKNOWN: exit status 1
тут ответ
http://arduino.ru/forum/proekty/prostoi-kukhonnyi-taimer-4simvtm1637-enk...
удалите в скетче строки 75 и 80 вызовы Start и Stop
Аккумулятора 18650 хватает на несколько месяцев при использовании таймера два...три раза в неделю. Больше всего сжирает конечно BEEPER.
для приготовления яичницы таймер не нужен, нужна регулировка огня, а другое я не пробовал )))
PS вру, могу сварить суп харчо и компот