автополив на ардуине
- Войдите на сайт для отправки комментариев
Ср, 04/07/2018 - 18:15
добрый день. есть ардуина, есть часы реального времени и релюха. хочу сделать автополив цикличный раз в день, два, три (как выбиру). можно было бы запилить какой-нибудь delay или millis, но это не спасет меня от выключения искричества. для этого и приобрел часы 1307. вот, собственно и сам вопрос скорее по логике, нежели чем по коду: как увязать цикл полива в определенное время (через сутки, например) и текущую дату и, в случае отключения тока, не столкнуться с выполнением цикла заново? пока только пришел к подсчету дней с начала года и вычисления сл. дня полива. но это не элегантно, кажется. помогите
выберу, конечно же
а поиском не ищется?
полив в нужные дни недели в нужное время на нужное количество минут:
// street pump for Arduino pro mini 5v #include <TM1637.h> #include <RTClib.h> #include <EEPROM.h> #include <avr/wdt.h> uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); void get_mcusr(void) \ __attribute__((naked)) \ __attribute__((used)) \ __attribute__((section(".init3"))); void get_mcusr(void) { mcusr_mirror = MCUSR; MCUSR = 0; wdt_disable(); } #define count_keys 5 #define start_pin_keys 2 #define pos_eeprom_min_pump 19 #define pos_eeprom_hour_time 20 #define pos_eeprom_min_time 21 #define pos_eeprom_stat_days 22 // 7 bytes 0-off 1=on Monday....Sunday #define period_read_key 100UL #define min_count_key_down 2 #define max_time_options 10000UL // 10 sec #define period_flash_led_days 50UL #define period_get_real_time 60000UL // 1 min byte tmPoint = 0; unsigned long timer_get_real_time = 0; unsigned long timer_read_key = 0; unsigned long timer_every_sec = 0; unsigned long timer_flash_led_days; unsigned long timer_time_options; unsigned long timer_pumping; byte keys_down[count_keys]; byte keys_begin[count_keys]; byte keys_click[count_keys]; boolean startFlashLedDays = false; byte currentFlashLedDays; byte nextFlashLedDays; TM1637 mytm(1, 0); // TM1637 0-CLK 1-DIO RTC_DS1307 myrtc; // DS1307 A4-SDA A5-SCL byte daysWeek[7]; // 1-day enable 0-day disable byte minPump; // period for pumping by min byte hourTime; // hour for pump byte minTime; // min for pump byte deviceMode = 0; // 0 - main mode // 1 - set day pump // 2 - set period min pumping // 3 - set real time on DS1307 // 4 - pumping byte currentDay; // current day of week from 0 = monday byte currentHour; // current hour of day byte currentMin; // current min of hour void setup() { // put your setup code here, to run once: for (byte i = 17; i >= 11; --i) { // init led Monday....Sunday, A3...A0 D13...D11 and OFF pinMode(i, OUTPUT); digitalWrite(i, HIGH); } pinMode(0, OUTPUT); digitalWrite(0, LOW); // CLK TM1637 display pinMode(1, OUTPUT); digitalWrite(1, LOW); // DIO TM1637 display pinMode(2, INPUT); digitalWrite(2, HIGH); // key select day pump / set day real time pinMode(3, INPUT); digitalWrite(3, HIGH); // key set day pump / set month real time pinMode(4, INPUT); digitalWrite(4, HIGH); // key select time hour pump / set hour real time pinMode(5, INPUT); digitalWrite(5, HIGH); // key select time min pump / set min real time pinMode(6, INPUT); digitalWrite(6, HIGH); // key select period min pump / set year real time pinMode(7, OUTPUT); digitalWrite(7, LOW); // OFF relay pump pinMode(8, OUTPUT); digitalWrite(8, LOW); // OFF reserv relay pinMode(9, OUTPUT); digitalWrite(9, LOW); // off unused pin pinMode(10, OUTPUT); digitalWrite(10, LOW); // off unused pin pinMode(A6, OUTPUT); digitalWrite(A6, LOW); // off unused pin pinMode(A7, OUTPUT); digitalWrite(A7, LOW); // off unused pin if (! myrtc.begin()) while (1); // init DS1307 mytm.init(); // init TM1637 mytm.set(5); // BRIGHT TM1637 MAX=7 mytm.point(0); mytm.display(0, 0x0A); mytm.point(1); mytm.display(1, 0x0B); mytm.point(0); mytm.display(2, 0x0C); mytm.point(1); mytm.display(3, 0x0D); unsigned long delp = millis(); while ((millis() - delp) <= 5000); // delay 5 sec for RTC mytm.point(1); mytm.display(0, 0x0E); mytm.point(0); mytm.display(1, 0x0F); mytm.point(1); mytm.display(2, 0x00); mytm.point(0); mytm.display(3, 0x09); delp = millis(); while ((millis() - delp) <= 10000); // delay 10 sec for RTC //myrtc.adjust(DateTime(2018, 3, 1, 12, 24, 10)); // test getCurrentTime(); // load day and time from DS1307 showCurrentTimeAndDay(); loadDataFromEeprom(); for (byte i = 0; i < count_keys; ++i) keys_begin[i] = 0; // reset keys wdt_enable(WDTO_4S); delp = millis(); while ((millis() - delp) <= 1000); // delay 1 sec fo test // flash led - start and test wdt for (byte i = 0; i < 10; ++i) { digitalWrite(LED_BUILTIN, HIGH); delay(50); digitalWrite(LED_BUILTIN, LOW); delay(50); } } void loop() { wdt_reset(); // put your main code here, to run repeatedly: //delay(5000); // test wdt unsigned long current_millis = millis(); // get current time every 1 min if ((current_millis - timer_get_real_time) >= period_get_real_time) { timer_get_real_time = current_millis; getCurrentTime(); // compare time and day for start pumping if ((currentHour == hourTime) && (daysWeek[currentDay] == 1) && ((currentMin - minTime) >= 0) && ((currentMin - minTime) <= 4) && (deviceMode == 0)) { timer_pumping = current_millis; deviceMode = 4; } } // end timer options if ((deviceMode > 0) && (deviceMode < 4)) { if ((current_millis - timer_time_options) >= max_time_options) { deviceMode = 0; } } // operate keys if ((current_millis - timer_read_key) >= period_read_key) { timer_read_key = current_millis; for (byte i = 0; i < count_keys; ++i) { if (digitalRead(i + start_pin_keys) == 0) { // key id down if (keys_begin[i] == 1) { ++keys_down[i]; } else { keys_begin[i] = 1; keys_down[i] = 0; keys_click[i] = 0; } } else { // key is up if (keys_begin[i] == 1) { if (keys_down[i] >= min_count_key_down) { // short click keys_begin[i] = 0; keys_down[i] = 0; keys_click[i] = 1; } else { // no click keys_begin[i] = 0; keys_down[i] = 0; keys_click[i] = 0; } } } } // analize keys if (keys_click[0] == 1) { if (deviceMode == 0) { timer_time_options = current_millis; deviceMode = 1; currentFlashLedDays = 0; } else if (deviceMode == 1) { timer_time_options = current_millis; if ((++currentFlashLedDays) > 6) currentFlashLedDays = 0; } } if (keys_click[1] == 1) { if (deviceMode == 1) { if (daysWeek[currentFlashLedDays] == 1) daysWeek[currentFlashLedDays] = 0; else daysWeek[currentFlashLedDays] = 1; EEPROM.update((currentFlashLedDays + pos_eeprom_stat_days), daysWeek[currentFlashLedDays]); } else if (deviceMode == 0) { showCurrentTimeAndDay(); } } if ((keys_click[2] == 1) && (deviceMode == 0)) { if ((++hourTime) > 23) hourTime = 5; EEPROM.update(pos_eeprom_hour_time, hourTime); showStartTimePumpAndPoint(); } if ((keys_click[3] == 1) && (deviceMode == 0)) { if ((minTime += 5) > 55) minTime = 0; EEPROM.update(pos_eeprom_min_time, minTime); showStartTimePumpAndPoint(); } if (keys_click[4] == 1) { if (deviceMode == 0) { timer_time_options = current_millis; deviceMode = 2; mytm.clearDisplay(); showPeriodTimePump(); } else if (deviceMode == 2) { timer_time_options = current_millis; if ((minPump += 5) > 30) minPump = 5; EEPROM.update(pos_eeprom_min_pump, minPump); showPeriodTimePump(); } } // end analize keys } // flash days led every 1 sec and othen action every sec if ((current_millis - timer_every_sec) >= 1000UL) { timer_every_sec = current_millis; timer_flash_led_days = current_millis; startFlashLedDays = true; nextFlashLedDays = 0; // other actions every sec if (deviceMode == 0) { // show start pump time and flash point showStartTimePumpAndPoint(); } if (deviceMode == 4) { if (((current_millis - timer_pumping) <= (minPump * 60000UL)) && (minPump < 40)) { digitalWrite(8, HIGH); // reserv ON unsigned long delp = millis(); while ((millis() - delp) <= 300); digitalWrite(7, HIGH); // pump ON showTimePumping((current_millis - timer_pumping) / 1000); } else { digitalWrite(7, LOW); // pump OFF unsigned long delp = millis(); while ((millis() - delp) <= 300); digitalWrite(8, LOW); // reserv OFF deviceMode = 0; } } else { digitalWrite(7, LOW); // pump OFF digitalWrite(8, LOW); // reserv OFF } if (deviceMode != 1) { // ON led active days for (byte i = 0; i <= 6; ++i) if (daysWeek[i] == 1) digitalWrite((17 - i), LOW); // led on } // other actions every sec } // flash days leds if ((current_millis - timer_flash_led_days) >= period_flash_led_days) { timer_flash_led_days = current_millis; if (startFlashLedDays) { if (deviceMode != 1) { byte workled = 99; if (nextFlashLedDays == 0) { // begin loop // nothing off led // find first free led for (byte i = 0; i <= 6; ++i) { if (daysWeek[i] == 0) { workled = i; break; } } if (workled <= 6) { digitalWrite((17 - workled), LOW); // led on } else { startFlashLedDays = false; } currentFlashLedDays = nextFlashLedDays; ++nextFlashLedDays; } else { // off current led if ((currentFlashLedDays > 0) || ((daysWeek[0] == 0) && (currentFlashLedDays == 0))) digitalWrite((17 - currentFlashLedDays), HIGH); // led off if (nextFlashLedDays > 6) { startFlashLedDays = false; } else { // find first free led for (byte i = nextFlashLedDays; i <= 6; ++i) { if (daysWeek[i] == 0) { workled = i; break; } } if (workled <= 6) { digitalWrite((17 - workled), LOW); // led on currentFlashLedDays = workled; nextFlashLedDays = (workled + 1); } else { startFlashLedDays = false; } } } } else { // flash for set day pump mode // currentFlashLedDays - is current select day by user for (byte i = 0; i <= 6; ++i) { if (i == currentFlashLedDays) { if (nextFlashLedDays == 0) { if (daysWeek[i] == 1) digitalWrite((17 - i), HIGH); else digitalWrite((17 - i), LOW); ++nextFlashLedDays; } else { if (daysWeek[i] == 1) digitalWrite((17 - i), LOW); else digitalWrite((17 - i), HIGH); startFlashLedDays = false; } } else { if (daysWeek[i] == 1) digitalWrite((17 - i), LOW); else digitalWrite((17 - i), HIGH); } } } } } // end loop // clear keys for (byte i = 0; i < count_keys; ++i) keys_click[i] = 0; // -- } void getCurrentTime() { DateTime now = myrtc.now(); currentHour = now.hour(); currentMin = now.minute(); currentDay = now.dayOfTheWeek(); if (currentDay == 0) currentDay = 6; else --currentDay; } void loadDataFromEeprom() { minPump = EEPROM.read(pos_eeprom_min_pump); if ((minPump < 5) || (minPump > 30)) minPump = 5; hourTime = EEPROM.read(pos_eeprom_hour_time); if ((hourTime < 5) || (hourTime > 23)) hourTime = 5; minTime = EEPROM.read(pos_eeprom_min_time); if (minTime > 55) minTime = 0; for (byte i = 0; i <= 7; ++i) if (EEPROM.read(i + pos_eeprom_stat_days) == 1) daysWeek[i] = 1; else daysWeek[i] = 0; } void showStartTimePumpAndPoint() { mytm.point(0); mytm.display(0, (hourTime / 10)); tmPoint = !tmPoint; mytm.point(tmPoint); mytm.display(1, (hourTime % 10)); mytm.point(0); mytm.display(2, (minTime / 10)); mytm.point(0); mytm.display(3, (minTime % 10)); } void showPeriodTimePump() { mytm.point(0); tmPoint = !tmPoint; mytm.point(tmPoint); mytm.point(0); mytm.display(2, (minPump / 10)); mytm.point(0); mytm.display(3, (minPump % 10)); } void showTimePumping(word unTimePump) { mytm.point(0); mytm.display(0, (unTimePump / 60) / 10); tmPoint = !tmPoint; mytm.point(tmPoint); mytm.display(1, (unTimePump / 60) % 10); mytm.point(0); mytm.display(2, (unTimePump % 60) / 10); mytm.point(0); mytm.display(3, (unTimePump % 60) % 10); } void showCurrentTimeAndDay() { if ((currentDay > 0) && (currentDay < 4)) mytm.point(0); else mytm.point(1); mytm.display(0, (currentHour / 10)); if ((currentDay == 0) || (currentDay == 2) || (currentDay == 3)) mytm.point(0); else mytm.point(1); mytm.display(1, (currentHour % 10)); if ((currentDay == 2) || (currentDay == 5) || (currentDay == 6)) mytm.point(1); else mytm.point(0); mytm.display(2, (currentMin / 10)); if ((currentDay == 3) || (currentDay == 6)) mytm.point(1); else mytm.point(0); mytm.display(3, (currentMin % 10)); }спасибо. с циклами в каждый день я разобрался, но, может быть, вы подскажите. как ссорудить цикл через поределенное количество суток?
спасибо. с циклами в каждый день я разобрался, но, может быть, вы подскажите. как ссорудить цикл через поределенное количество суток?
ну например хранить в переменной количество суток и каждый millis() деленный на количество миллисекунд в сутки уменьшать эту переменную - как будет равно нулем - значит прошло нужное количество дней.
вот пример подсчет часов и потом дней
// timer every hour if ((work_mode == 0) || (work_mode == 3)) { if ((current_millis - timer_hour) >= 3600000UL) { // for test = 1000UL // by real 1 hour = 3600000UL ms timer_hour = current_millis; if ((++hour_counting) >= 24) { ++day_counting; hour_counting = 0; if (day_counting >= day_period) { // start pump time_pumping_mode = current_millis; TM1637_clear(); work_mode = 2; day_counting = 0; } EEPROM.write(pos_eeprom_current_days, day_counting); } } // end hour timer }ну это не решает вопрос с отключением света на, скажем, 12 часов. тогда ведь это время прибавится к заданному интервалу
ну это не решает вопрос с отключением света на, скажем, 12 часов. тогда ведь это время прибавится к заданному интервалу
все решаемо, например если есть RTC то в EEPROM сохранить время включения полива и когда до не го дойдет счетчик - полить, или сохранять каждый час счетчик в EEPROM и лет через несколько МК выкинуть.
у меня в деревне свет часто отключают, но +- сутки ничего не рашает для полива домашнего растения (согласно установленного женой ТЗ), потому сохраняю в EEPROM только счетчик суток.
можно и без RTC - соорудить ардуине простейшее аварийное питание из батарейки 2032 и диода и она будет сохранять свой счетчик не хуже RTC
вот и мне хотелось бы без насилия над eeprom. вот только как это изобразить я ума ни приложу
есть у меня 18650 ворох (правда без защиты и контроллера) и, как вариант это решение. только тут зависимость от самой батарейки - рано или поздно она помрет, а я и знать не знаю.
все зависит от задачи/желания/стоимости,
я тут прикинул - минимум 5 лет проживет EEPROM при записи каждый час, вы хорошо с электроникой дружите? нужно оно вам паять дополнительную электронику?
мне например лишняя деталь - уже проблема, со школы толком ничего не паял, проще программно решить вопрос.
сдохнет attiny85 - проще другую поставить, чем городить огород с батарейкой/аккумулятором/RTC
паяю норм, с этим проблем нет, а вот с программированием хуже) я именно по этому и не хочу городить аккум, тк думаю что есть более элегантное решение, прост не могу продумать логику.
100 000 циклов это 11 лет.
паяю норм, с этим проблем нет, а вот с программированием хуже) я именно по этому и не хочу городить аккум, тк думаю что есть более элегантное решение, прост не могу продумать логику.
100 000 циклов это 11 лет.
я предполагаю худший вариант китайского чипа - 50 % ресурса, + еще можно логику придумать равномерной записи по всей EEPROM, тогда ресурс в разы увеличивается - быстрее насос умрет, или как у меня недавно в молнию на БП конденсатор взорвался, благо остальное все живо осталось.
Подтверждаю - циклическая запись в EEPROM дает просто адский ресурс. Однако, думаю, что топикстартеру проще взять FRAM и писать туда хоть каждую минуту, если ему паяльник ближе математики.
с кодом я разбирусь, верен заветам Ильича (учиться учиться и еще раз учиться)
прост меня пнуть нужно в правильную сторону)
элегантное решение может быть не в цикле, а в произвольном выборе дней недели для полива, тк часы возвращают их как цифру. сравниваем и поливаем.
элегантное решение может быть не в цикле, а в произвольном выборе дней недели для полива, тк часы возвращают их как цифру. сравниваем и поливаем.
элегентное оно только на бумаге. Цветы ничего не знают про дни недели, их нужно поливать каждые 2-3 дня, так что циклом задавать проще.
элегантное решение может быть не в цикле, а в произвольном выборе дней недели для полива, тк часы возвращают их как цифру. сравниваем и поливаем.
угу, произвольно выберется понедельник 22:00 и вторник 07:00 потом через воскресенье 21:00 и получится за две недели цветок засохнет.
повторюсь - все зависит от задачи, под нее уже и решение придумывается.
в идеале мне нужно поливать кустик раз в два- пять дней не опасаясь выключения света и как можно меньше лазия к зеленому другу. есть уно, мини, нано, часики 1307, релюхи-помпы все дела)
это и понятно, что нужно циклом делать, только как учесть вероятные отключения искричества?
это и понятно, что нужно циклом делать, только как учесть вероятные отключения искричества?
э....так выше же уже обмусолили тему и варианты - нет?
вот полный код (выше кусок) поливалки каждые несколько суток с ежесуточным сохранением в EEPROM, и RTC нафиг не надо.
#include <avr/io.h> #include <util/delay.h> #include "EEPROM.h" #include "tm1637.h" #define pos_eeprom_pump_sec 0x25 #define pos_eeprom_count_days 0x27 #define pos_eeprom_current_days 0x29 #define period_read_key 100UL #define min_count_key_down 2 // 0.2 sec #define min_count_key_long 20 // 2 sec #define max_count_key_short 10 // 1 sec #define max_time_show_options 20000UL // 20 sec #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif // PB0 pin 5 - TM1637_DIO_PIN #define PB0_OUT sbi(DDRB,PB0) #define PB0_IN cbi(DDRB,PB0) #define PB0_HIGH sbi(PORTB,PB0) #define PB0_LOW cbi(PORTB,PB0) // PB1 pin 6 - TM1637_CLK_PIN #define PB1_OUT sbi(DDRB,PB1) #define PB1_IN cbi(DDRB,PB1) #define PB1_HIGH sbi(PORTB,PB1) #define PB1_LOW cbi(PORTB,PB1) // PB2 pin 7 - relay pump #define PB2_OUT sbi(DDRB,PB2) #define PB2_IN cbi(DDRB,PB2) #define PB2_HIGH sbi(PORTB,PB2) #define PB2_LOW cbi(PORTB,PB2) // PB3 pin 2 - key 1 #define PB3_OUT sbi(DDRB,PB3) #define PB3_IN cbi(DDRB,PB3) #define PB3_HIGH sbi(PORTB,PB3) #define PB3_LOW cbi(PORTB,PB3) #define PB3_READ bitRead(PINB,PB3) // PB4 pin 3 - key 2 #define PB4_OUT sbi(DDRB,PB4) #define PB4_IN cbi(DDRB,PB4) #define PB4_HIGH sbi(PORTB,PB4) #define PB4_LOW cbi(PORTB,PB4) #define PB4_READ bitRead(PINB,PB4) unsigned long key_time; byte day_counting; // current counting byte hour_counting = 0; // current counting byte sec_pumping; // default/minimum 1 sec pump byte day_period; // default/minimum 1 day pump byte count_key1_down = 0; byte mode_key1 = 0; // 0-none 1-short 2-long boolean key1_is_begin = false; boolean key1_next = true; byte count_key2_down = 0; byte mode_key2 = 0; // 0-none 1-short 2-long boolean key2_is_begin = false; boolean key2_next = true; byte work_mode = 0; // 0-counting 1-options 2-pumping 3-test pump unsigned long time_options_mode; unsigned long time_pumping_mode; byte point_togl = 0; // display point unsigned long timer_sec = 0; // show display timer unsigned long timer_hour = 0; // every hour - main timer void setup() { // put your setup code here, to run once: PB3_IN; PB3_HIGH; // key 1 PB4_IN; PB4_HIGH; // key 2 PB2_OUT; PB2_LOW; // relay OFF // load conf from eeprom sec_pumping = EEPROM.read(pos_eeprom_pump_sec); day_period = EEPROM.read(pos_eeprom_count_days); day_counting = EEPROM.read(pos_eeprom_current_days); TM1637_init(); TM1637_set_brightness(6); } void loop() { // put your main code here, to run repeatedly: unsigned long current_millis = millis(); if ((current_millis - key_time) >= period_read_key) { key_time = current_millis; // operate key1 if (PB3_READ == 0) { // key1 is down if (key1_is_begin) { if ((++count_key1_down) >= min_count_key_long) { // long click key1_is_begin = false; count_key1_down = 0; mode_key1 = 2; } } else { if (key1_next) { key1_is_begin = true; key1_next = false; count_key1_down = 0; mode_key1 = 0; } } } else { // key1 is up key1_next = true; if (key1_is_begin) { if ((count_key1_down >= min_count_key_down) && (count_key1_down <= max_count_key_short)) { // short click key1_is_begin = false; count_key1_down = 0; mode_key1 = 1; } else { // no click key1_is_begin = false; count_key1_down = 0; mode_key1 = 0; } } } // end key1 // operate key2 if (PB4_READ == 0) { // key2 is down if (key2_is_begin) { if ((++count_key2_down) >= min_count_key_long) { // long click key2_is_begin = false; count_key2_down = 0; mode_key2 = 2; } } else { if (key2_next) { key2_is_begin = true; key2_next = false; count_key2_down = 0; mode_key2 = 0; } } } else { // key2 is up key2_next = true; if (key2_is_begin) { if ((count_key2_down >= min_count_key_down) && (count_key2_down <= max_count_key_short)) { // short click key2_is_begin = false; count_key2_down = 0; mode_key2 = 1; } else { // no click key2_is_begin = false; count_key2_down = 0; mode_key2 = 0; } } } // end key2 } // analize keys if ((mode_key1 == 2) && (mode_key2 == 2)) { if (work_mode == 0) { // enter to options mode time_options_mode = current_millis; TM1637_clear(); ShowSecDay(); work_mode = 1; } else { if (work_mode == 1) { // clear counting hour_counting = 0; day_counting = 0; // save options EEPROM.write(pos_eeprom_pump_sec, sec_pumping); EEPROM.write(pos_eeprom_count_days, day_period); EEPROM.write(pos_eeprom_current_days, day_counting); // exit options mode TM1637_clear(); work_mode = 0; } } } else { if (mode_key1 == 2) { if (work_mode == 1) { // save options EEPROM.write(pos_eeprom_pump_sec, sec_pumping); EEPROM.write(pos_eeprom_count_days, day_period); // test pump time_pumping_mode = current_millis; TM1637_clear(); work_mode = 3; } } else { if (mode_key1 == 1) { if (work_mode == 1) { time_options_mode = current_millis; // change pump sec if ((++sec_pumping) > 9) sec_pumping = 1; // show ShowSecDay(); } } else { if (mode_key2 == 1) { if (work_mode == 1) { time_options_mode = current_millis; // change period pump days if ((++day_period) > 9) day_period = 1; // show ShowSecDay(); } } else { // no keys if (work_mode == 1) { if ((current_millis - time_options_mode) >= max_time_show_options) { // save options EEPROM.write(pos_eeprom_pump_sec, sec_pumping); EEPROM.write(pos_eeprom_count_days, day_period); // exit options mode TM1637_clear(); work_mode = 0; } } } } } } // end analize keys // analize pump mode if ((work_mode == 2) || (work_mode == 3)) { PB2_HIGH; if ((current_millis - time_pumping_mode) >= (sec_pumping * 1000)) { time_pumping_mode = current_millis; // end pumping PB2_LOW; TM1637_clear(); work_mode = 0; } } // end pump mode // loop show display if ((current_millis - timer_sec) >= 1000UL) { timer_sec = current_millis; if (point_togl == 0) point_togl = 1; else point_togl = 0; TM1637_display_colon(point_togl); switch (work_mode) { case 0: { ShowTimer(); break; } case 1: { ShowSecDay(); break; } case 2: { ShowPump(); break; } case 3: { ShowPump(); break; } } } // timer every hour if ((work_mode == 0) || (work_mode == 3)) { if ((current_millis - timer_hour) >= 3600000UL) { // for test = 1000UL // by real 1 hour = 3600000UL ms timer_hour = current_millis; if ((++hour_counting) >= 24) { ++day_counting; hour_counting = 0; if (day_counting >= day_period) { // start pump time_pumping_mode = current_millis; TM1637_clear(); work_mode = 2; day_counting = 0; } EEPROM.write(pos_eeprom_current_days, day_counting); } } // end hour timer } // end main loop mode_key1 = 0; mode_key2 = 0; } void ShowTimer() { TM1637_display_digit(TM1637_SET_ADR_00H, day_counting); TM1637_display_segments(TM1637_SET_ADR_01H, 0b01000000); TM1637_display_digit(TM1637_SET_ADR_02H, (hour_counting / 10)); TM1637_display_digit(TM1637_SET_ADR_03H, (hour_counting % 10)); } void ShowSecDay() { TM1637_display_segments(TM1637_SET_ADR_00H, 0b01000000); TM1637_display_digit(TM1637_SET_ADR_01H, sec_pumping); TM1637_display_segments(TM1637_SET_ADR_02H, 0b01000000); TM1637_display_digit(TM1637_SET_ADR_03H, day_period); } void ShowPump() { TM1637_display_segments(TM1637_SET_ADR_00H, 0b01000000); TM1637_display_segments(TM1637_SET_ADR_01H, 0b01000000); TM1637_display_digit(TM1637_SET_ADR_02H, ((millis() - time_pumping_mode) / 1000) / 10); TM1637_display_digit(TM1637_SET_ADR_03H, ((millis() - time_pumping_mode) / 1000) % 10); }