Цикличный отсчет времени
- Войдите на сайт для отправки комментариев
Чт, 15/06/2017 - 14:12
Здравствуйте, уважаемыепрограммисты. Я не силен в программировании поэтому обращаюсь к вам.
Задача следующая.
Необходимо написать код который циклично отсчитывал бы время назад. Например, я задал 10сек. нажал кнопку старт и процесс обратного отсчета пошел 10, 9, 8, ... 0. Как только дошел до 0 снова встал на 10 сек и отсчитывает 10, 9, 8... до 0. Накидал код, но почему-то он с каждым новым циклом прибавляет или отнимает разные значения. Не могу понять закономерность. Помогите его подправить.
unsigned long TimeLightOffOn = 10000;
void setup()
{
Serial.begin(9600);
}
void loop()
{
byte Seconds = ((TimeLightOffOn-millis())/1000UL)%60;
byte Minutes = (((TimeLightOffOn-millis())/1000UL)/60UL)%60;
byte Hours = (((TimeLightOffOn-millis())/1000UL)/3600UL)%24;
Serial.print(Hours);
Serial.print(':');
Serial.print(Minutes);
Serial.print(':');
Serial.println(Seconds);
if (Seconds == 0 && Minutes == 0 && Hours == 0) //(millis() - timer > 3000) {
TimeLightOffOn = millis() + TimeLightOffOn;
delay(1000);
}
Вот коротко какой результат получаю^
0:0:10
0:0:9
0:0:8
0:0:6
0:0:5
0:0:4
0:0:3
0:0:2
0:0:1
0:0:0
0:0:9
0:0:8
0:0:6
0:0:5
0:0:4
0:0:3
0:0:2
0:0:1
0:0:0
0:0:18
0:0:17
0:0:16
Пожалуйста вставляйте код правильно. Вот как его сейчас обсуждать, если номеров строк нет?
Накидал код
Впредь попробуйте писать, будет лучше получаться. Накидывают навоз на грядку.
Не могу понять закономерность
Всё Вы можете, просто посмотрите внимательнее на код.
В строке №ХЗ Вы пишете "TimeLightOffOn = millis() + TimeLightOffOn;", т.е. Вы затираете старое значение TimeLightOffOn новым. Т.е. Вы портите величину интервала. Вот он у Вас и растёт постоянно. Сейчас скакнуло с 9 до 18, потом ещё вдвое скакнёт. Вы уж значение интервала сохраняйте всегда неизменным - зачем его портить-то то?
Это мое первое сообщение на форуме. Поэтому по строкам вышло так... Исправлюсь. Спасибо за подсказку. Т.е. Нужно ввести беременную которая будет хранить дельту?
Semka_2005 Вот мой скетч, где я применил похожее. Если разберетесь пригодится
/*.ino реле на вентилятор 1 -->2 (Fan1_pin) реле на вентилятор 2 -->3 (Fan2_pin) lcd1602_I2C таймер обратного счета светодиод 1 -->8 (Led1_pin) светодиод 2 -->9 (Led2_pin) светодиод 3 -->10 (Led3_pin) светодиод 4 -->A0 (Led4_pin) светодиод 5 -->A1 (Led5_pin) светодиод 6 -->A2 (Led6_pin) светодиод 7 -->13 (Led7_pin) кнопка 1 -->4 (btn1_pin) кнопка смена режима /режим 10мин,20минут 40минут кнопка 2 -->5 (btn2_pin) кнопка смена режима / режим 1,режим2,режим3 кнопка 3 -->6 (btn3_pin) кнопка старт кнопка 4 -->7 (btn4_pin) кнопка стоп Принцип кода: Кнопкой btn1 меняется режим 10мин,20минут 40минут Кнопкой btn2 меняется режим вид работы Кнопкой btn3 меняется запуск Кнопкой btn4 меняется стоп */ class Cl_Sys;// предварительно объявить о создании класса Sys для послед подключения к нему #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); //------------------------ Cl_back_timer ---------------------------------- // класс таймер class Cl_back_timer { uint32_t mill; bool stat;// 0 стоит /1 обратный счет void (* Do1)(), (* Do2)(); uint32_t time ; void convert_time() { minute = time / 60000; sec = time / 1000 - minute * 60; } const uint32_t interval = 1000;// цикл обновления показаний uint32_t past = 0; uint32_t past_end; public: // указатель на следующий элемент Cl_back_timer *pnt; // конструктор Cl_back_timer(Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)()); // setup() void setup() { if (this->pnt != NULL) this->pnt->setup(); } // loop() void loop() { if (this->pnt != NULL) this->pnt->loop(); mill = millis(); if (stat && mill - past >= interval) { past = mill; if (time > interval) { time -= interval; convert_time(); Do1(); } else { stat = 0; Do2(); } } } void Start() { stat = 1; past = millis(); time = time_start; } void Stop() { stat = 0; } byte sec; byte minute; uint32_t time_start = 10000; }; // ------------------------ Cl_do_btn_3mode ---------------------------------- // класс кнопка с 1 обработчиком class Cl_do_btn { byte pin ; // нога bool inv; // инверсия void (*Do)(); bool btn, btn_old; bool bounce_btn = 0; // антидребезговый флаг uint32_t past = 0 ; public: // указатель на следующий элемент Cl_do_btn *pnt; // конструктор Cl_do_btn(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)()); // setup() void setup() { if (this->pnt != NULL) this->pnt->setup(); //pinMode(pin, INPUT);// подключить кнопку 1 без внут подтяжки pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой btn = digitalRead(pin) ; // прочитать реальное значение на выводе } // loop() void loop() { if (this->pnt != NULL) this->pnt->loop(); if (! bounce_btn && btn != digitalRead(pin)) { // если прошел фронт изм на выводн bounce_btn = 1; // выставить флаг past = millis(); // сделать временую засветку } else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время bounce_btn = 0; // то снять флаг btn_old = btn ; btn = digitalRead(pin) ; // прочитать реальное значение на выводе if (btn_old && ! btn) Do() ; } } }; //------------------------ Cl_do_btn_3mode ---------------------------------- // класс кнопка с 3 выборами #include <EEPROM.h> class Cl_do_btn_3mode { int adrEEPROM; byte pin ;// нога bool inv; // инверсия void (*Do1)(), (*Do2)() , ( *Do3)(); bool btn, btn_old; bool bounce = 0; // антидребезговый флаг uint32_t past = 0 ; byte mode;// 0,1,2 режим public: // указатель на следующий элемент Cl_do_btn_3mode *pnt; // конструктор Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM); // setup() void setup() { if (this->pnt != NULL) this->pnt->setup(); //pinMode(pin, INPUT);// подключить кнопку 1 без подтязки pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой bounce = 0 ; btn_old = 1 ; btn = digitalRead(pin)^inv ; // прочитать реальное значение на выводе byte _mode = EEPROM.read(adrEEPROM); if (_mode == 0 || _mode == 1 || _mode == 2 )mode = _mode; else mode = 0; EEPROM.update(adrEEPROM, mode); if (mode == 0) Do1(); else if (mode == 1) Do2(); else Do3(); } // loop() void loop() { if (this->pnt != NULL) this->pnt->loop(); if (! bounce && btn != (digitalRead(pin)^ inv)) { // если прошел фронт изм на выводн bounce = 1; // выставить флаг past = millis(); // сделать временую засветку } else if ( bounce && millis() - past >= 5 ) { // если прошло антидребезговое время bounce = 0; // то снять флаг btn_old = btn ; btn = digitalRead(pin)^ inv ; // прочитать реальное значение на выводе if (btn_old && ! btn) { (mode >= 2) ? mode = 0 : mode++; if (mode == 0) Do1(); if (mode == 1) Do2(); if (mode == 2) Do3(); } } } // поставить в нужный режим void Set_mode(int _mode) { switch (_mode) { case 0: mode = 0; Do1(); break; case 1: mode = 1; Do2(); break; case 2: mode = 2; Do3(); break; } } }; //------------------------ Cl_fan ---------------------------------- // класс вентилятор class Cl_fan { uint32_t time_work_old; //время работы 10 минут uint32_t time_pulse_old; //время полного импульса 1 минута uint32_t time_pulse_ON_old; //время работы в течении импульса 0,5 нинут byte pin; // нога bool inv; // инверсия bool stat; bool work; uint32_t past_pulse; uint32_t past_work; public: // указатель на следующий элемент Cl_fan *pnt; // конструктор Cl_fan(Cl_Sys *Sys, byte _pin, bool _inv); // setup() void setup() { if (this->pnt != NULL) this->pnt->setup(); work = 0; stat = 0; digitalWrite(pin, stat ^ inv); pinMode(pin, OUTPUT); } // loop() void loop() { if (this->pnt != NULL) this->pnt->loop(); if (work && millis() - past_pulse >= time_pulse_old) { past_pulse = millis(); stat = 1; digitalWrite(pin, stat ^ inv); } if (stat && millis() - past_pulse >= time_pulse_ON_old) { stat = 0; digitalWrite(pin, stat ^ inv); } if (work && millis() - past_work >= time_work_old) { work = 0; stat = 0; digitalWrite(pin, stat ^ inv); } } void ON() { time_work_old = time_work; time_pulse_old = time_pulse; time_pulse_ON_old = time_pulse_ON; past_work = millis(); work = 1; past_pulse = millis(); stat = 1; digitalWrite(pin, stat ^ inv); } void OFF() { work = 0; stat = 0; digitalWrite(pin, stat ^ inv); } uint32_t time_work = 600000; //время работы 10 минут uint32_t time_pulse = 60000; //время полного импульса 1 минута uint32_t time_pulse_ON = 30000; //время работы в течении импульса 0,5 нинут }; //------------------------ Cl_led ---------------------------------- // класс светодиод class Cl_led { byte pin ;// нога bool inv; // инверсия вывода bool led;// 0 откл / 1 вкл bool stat_blink;// 1 мигает/0 нет uint32_t past = 0; uint32_t time_blink = 500; public: // указатель на следующий элемент Cl_led *pnt; // конструктор Cl_led(Cl_Sys *Sys, byte _pin, bool _inv); // setup() void setup() { if (this->pnt != NULL) this->pnt->setup(); pinMode(pin, OUTPUT);// подключить светодиод OFF(); } // loop() void loop() { if (this->pnt != NULL) this->pnt->loop(); if (stat_blink && millis() - past >= time_blink) { past = millis(); digitalWrite(pin, led = ! led) ; } } // включить void ON() { stat_blink = 0; digitalWrite(pin, led = 1 ^ inv) ; // зажечь } // выключить void OFF() { stat_blink = 0; digitalWrite(pin, led = 0 ^ inv) ; // погасить } // начать мигать void blink() { stat_blink = 1; past = millis(); } // начать мигать с опред полупериодом void blink(uint32_t time) { time_blink = time; stat_blink = 1; past = millis(); } }; //-----------------class Cl_sys--------------------------- class Cl_Sys { public: Cl_back_timer *Start_back_timer = NULL; Cl_do_btn *Start_do_btn = NULL; Cl_do_btn_3mode *Start_do_btn_3mode = NULL; Cl_fan *Start_fan = NULL; Cl_led *Start_led = NULL; Cl_Sys() {} // setup() void setup() { Start_back_timer ->setup(); Start_do_btn ->setup(); Start_do_btn_3mode->setup(); Start_fan ->setup(); Start_led ->setup(); } // loop() void loop() { Start_back_timer ->loop(); Start_do_btn ->loop(); Start_do_btn_3mode->loop(); Start_fan ->loop(); Start_led ->loop(); } } Sys; //---------описание классов------------ Cl_back_timer ::Cl_back_timer (Cl_Sys *Sys, void (* _Do1)(), void (* _Do2)()): Do1(_Do1), Do2(_Do2), pnt(NULL) {} Cl_do_btn ::Cl_do_btn (Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do)()): pin(_pin), inv(_inv), Do(_Do), pnt(NULL) {} Cl_do_btn_3mode::Cl_do_btn_3mode(Cl_Sys *Sys, byte _pin, bool _inv, void (* _Do1)(), void (* _Do2)(), void (* _Do3)(), int _adrEEPROM) : pin(_pin), inv(_inv), Do1(_Do1), Do2(_Do2), Do3(_Do3), adrEEPROM(_adrEEPROM), pnt(NULL) {} Cl_fan ::Cl_fan (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {} Cl_led ::Cl_led (Cl_Sys *Sys, byte _pin, bool _inv): pin(_pin), inv(_inv), pnt(NULL) {} //----------Компоновка--------------------- const uint32_t time_20sec = 20000; //время 20 секунд const uint32_t time_30sec = 30000; //время 30 секунд const uint32_t time_1min = 60000; //время 1 минуты const uint32_t time_3min = 180000; //время 3 минуты const uint32_t time_10min = 600000; //время работы 10 нинут const uint32_t time_20min = 1200000; //время работы 20 нинут const uint32_t time_40min = 2400000; //время работы 40 нинут // вентилятор Cl_fan *Fan1 = new Cl_fan(&Sys,/*пин*/2,/*инверсия*/0);// подключить реле вентилятора на выв 2, вкл если на выв 1 Cl_fan *Fan2 = new Cl_fan(&Sys,/*пин*/3,/*инверсия*/0);// подключить реле вентилятора на выв 3, вкл если на выв 1 // таймер обратного счета void Do1_Back_timer(); void Do2_Back_timer(); Cl_back_timer *Back_timer = new Cl_back_timer(&Sys,/*обработчик*/ Do1_Back_timer, /*обработчик*/ Do2_Back_timer ); void Do1_Back_timer() { // отправить текущие показания lcd.setCursor(6, 0); if (Back_timer->minute < 10)lcd.print("0"); lcd.print(Back_timer->minute); lcd.print(":"); if (Back_timer->sec < 10)lcd.print("0"); lcd.print(Back_timer->sec); } void Do2_Back_timer() { // отправить последнее сообщение lcd.setCursor(6, 0); lcd.print(" END "); } // светодиоды для 1 выбора режима Cl_led *Led1 = new Cl_led(&Sys,/*пин*/8 ,/*инверсия*/ 0);// подключить светодиод на выв 8 , горит если на выв 0 Cl_led *Led2 = new Cl_led(&Sys,/*пин*/9 ,/*инверсия*/ 0);// подключить светодиод на выв 9 , горит если на выв 0 Cl_led *Led3 = new Cl_led(&Sys,/*пин*/10,/*инверсия*/0);// подключить светодиод на выв 10, горит если на выв 0 // светодиоды для 2 выбора режима Cl_led *Led4 = new Cl_led(&Sys,/*пин*/A0,/*инверсия*/0);// подключить светодиод на выв A0, горит если на выв 0 Cl_led *Led5 = new Cl_led(&Sys,/*пин*/A1,/*инверсия*/0);// подключить светодиод на выв A1, горит если на выв 0 Cl_led *Led6 = new Cl_led(&Sys,/*пин*/A2,/*инверсия*/0);// подключить светодиод на выв A2, горит если на выв 0 // индикатор работа Cl_led *Led7 = new Cl_led(&Sys,/*пин*/13,/*инверсия*/0);// подключить светодиод на выв 13, горит если на выв 0 // кнопка 1 void Do1_Btn1() { Fan1->time_work = time_10min; Fan2->time_work = time_10min; Back_timer->time_start = time_10min; Led3->OFF(); Led1->ON(); lcd.setCursor(0, 0); lcd.print("10min"); } void Do2_Btn1() { Fan1->time_work = time_20min; Fan2->time_work = time_20min; Back_timer->time_start = time_20min; Led1->OFF(); Led2->ON(); lcd.setCursor(0, 0); lcd.print("20min"); } void Do3_Btn1() { Fan1->time_work = time_40min; Fan2->time_work = time_40min; Back_timer->time_start = time_40min; Led2->OFF(); Led3->ON(); lcd.setCursor(0, 0); lcd.print("40min"); } Cl_do_btn_3mode *Btn1 = new Cl_do_btn_3mode(&Sys,/*пин*/4,/*инверсия*/ 0,/*обработчик*/ Do1_Btn1, /*обработчик*/ Do2_Btn1, /*обработчик*/ Do3_Btn1,/*adrEEPROM*/0x00); //Кнопка 2 void Do1_Btn2() { Fan1->time_pulse = time_1min; Fan1->time_pulse_ON = time_1min; Fan2->time_pulse = time_1min; Fan2->time_pulse_ON = time_30sec; Led6->OFF(); Led4->ON(); lcd.setCursor(0, 1); lcd.print("1=ON 2=1m/30"); } void Do2_Btn2() { Fan1->time_pulse = time_1min; Fan1->time_pulse_ON = time_30sec; Fan2->time_pulse = time_1min; Fan2->time_pulse_ON = time_30sec; Led4->OFF(); Led5->ON(); lcd.setCursor(0, 1); lcd.print("1=1m/30 2=1m/30"); } void Do3_Btn2() { Fan1->time_pulse = time_1min; Fan1->time_pulse_ON = time_20sec; Fan2->time_pulse = time_3min; Fan2->time_pulse_ON = time_30sec; Led5->OFF(); Led6->ON(); lcd.setCursor(0, 1); lcd.print("1=1m/20 2=3m/30"); } Cl_do_btn_3mode *Btn2 = new Cl_do_btn_3mode(&Sys,/*пин*/5,/*инверсия*/ 0,/*обработчик*/Do1_Btn2,/*обработчик*/Do2_Btn2,/*обработчик*/ Do3_Btn2,/*adrEEPROM*/0x01); //Кнопка 3 Пуск void Do_Btn3() { Fan1->ON(); Fan2->ON(); Back_timer->Start(); Led7->blink(); lcd.setCursor(13, 0); lcd.print("ON "); } Cl_do_btn *Btn3 = new Cl_do_btn(&Sys,/*пин*/6,/*инверсия*/0,/*обработчик*/ Do_Btn3); //Кнопка 4 Стоп void Do_Btn4() { Fan1->OFF(); Fan2->OFF(); Back_timer->Stop(); Led7->ON(); lcd.setCursor(13, 0); lcd.print("OFF "); } Cl_do_btn *Btn4 = new Cl_do_btn(&Sys,/*пин*/7,/*инверсия*/ 0,/*обработчик*/Do_Btn4); //-----------Main()----------------------- void setup() { lcd.init(); lcd.backlight(); Sys.setup(); } void loop() { Sys.loop(); }ПС: класс Cl_back_timer и его представитель Back_timer
Semka_2005, я не ЕвгенийП и не заметил опечатки, тем не менее, реакция на Ваш вопрос у меня была примерно такая же.
В самом деле:
- можно ввести указанную Вами переменную и решить проблему,
- можно решить проблему бе введения указанной переменной,
- можно ввести переменную и НЕ решить проблему.
И как в таком случае на Ваш вопрос следует отвечать?
Я не могу понять как решить мою задачу.
Как я это вижу я. Скажем прошло 5сек (000 - опустим для простоты) с момента первого отсчета и значение millis() = 5
TimeLightOffOn = 5 (оно задано изначально)
тогда TimeLightOffOn-millis() или 5 - 5 = 0 Первый цикл прошел и мы пришли в ноль.
Теперь чтобы мне вернуться на заданые 5 сек и произвести отсчет обратно требуется
TimeLightOffOn = (millis ()= 5) + (TimeLightOffOn = 5) = 10
Получил значение TimeLightOffOn = 10 от которого я снова могу отнимать millis ()
TimeLightOffOn-millis() или 10 - 6 = 4
TimeLightOffOn-millis() или 10 - 7 = 3
TimeLightOffOn-millis() или 10 - 8 = 2
TimeLightOffOn-millis() или 10 - 9 = 1
TimeLightOffOn-millis() или 10 - 10 = 0
Почему не работает?
Первый раз работает, судя по Вашим ранешним печатям. А вот второй раз ... продолжите вот такое же расписывание для второго раза и увидите. что интервал увеличится вдвое. Сделайте.
Я не считаю это помощью. Это решит Вашу проблему сию секунду, но "срок годности" такой помощи - до следующего раза, когда Вам потребуется тоже самое. Как только потребуется, проблема возникнет снова, т.к. Вы от такой помощи ничему не научитесь.
Вся необходимая Вам техника есть вот в этом примере - там и задача очень похоже, тоже надо постоянно отсчитывать равные интервалы.
Вставьте код правильно и вежливо попросите, не забудьте "пожалуйста". ;) Я поправлю Ваш код. + одна строка и + одно исправление. луччше два исправления, но это уж как вам захоццо. ;)
wdrakula, да ладно Вам. Пусть возьмёт "блинк без делэй" и сам разберётся.
Женя! У Вас педагогическая железа сверхпродуктивна! Может опухолью закончится... берегите себя!
Достаточно сказать ТСу два слова: интервал и начало интервала - это разные понтия! Интервал - всегда 10 и его не надо менять, начало нужно переставлять. Так, возможно(?) , он сам догадается.
unsigned long TimeLightOffOn = 10000; void setup() { Serial.begin(9600); } void loop() { byte Seconds = ((TimeLightOffOn-millis())/1000UL)%60; byte Minutes = (((TimeLightOffOn-millis())/1000UL)/60UL)%60; byte Hours = (((TimeLightOffOn-millis())/1000UL)/3600UL)%24; Serial.print(Hours); Serial.print(':'); Serial.print(Minutes); Serial.print(':'); Serial.println(Seconds); if (Seconds == 0 && Minutes == 0 && Hours == 0) //(millis() - timer > 3000) { TimeLightOffOn = millis() + TimeLightOffOn; delay(1000); }Это так? wdrakula, Пожалуйста, не сочтите за труд, поправьте код чтоб он заработал как надо!
Я вас понимаю, но я не программист и решив эту задачу сейчас, я к ней больше не вернусь в своей жизни. По крайней мере не собираюсь. У меня есть простенькая задачка которую я решу один раз в жизни и больше не вернусь к этому. Другое дело если бы я был студент и в дальнейшем мой заработок был связан с профессией программирования. А так... Решил задачу и забыл...
но я не программист
Но я то - программист. И отношусь к этому занятию очень серьёзно.
но я не программист
Но я то - программист. И отношусь к этому занятию очень серьёзно.
Дак я и не имею против вашей профессии ничего против. И именнопо этому обращаюсь к вам за квалифицированной помощью.
Это так? wdrakula, Пожалуйста, не сочтите за труд, поправьте код чтоб он заработал как надо!
дракула уволен за антисимитизм и русофобию.
подсказываю // TimeLightOffOn = millis() + TimeLightOffOn;
Это так? wdrakula, Пожалуйста, не сочтите за труд, поправьте код чтоб он заработал как надо!
код кривой, но я сохраню этот незабываемый стиль.
unsigned long TimeLightOffOn = 10000; unsigned long Interval = 10000; void setup() { Serial.begin(19200); while(!Serial); // особенность Леонарда для других плат можно можно и нужно убрать } void loop() { byte Seconds = ((TimeLightOffOn-millis())/1000UL)%60; byte Minutes = (((TimeLightOffOn-millis())/1000UL)/60UL)%60; byte Hours = (((TimeLightOffOn-millis())/1000UL)/3600UL)%24; Serial.print(Hours); Serial.print(':'); Serial.print(Minutes); Serial.print(':'); Serial.println(Seconds); if (Seconds == 0 && Minutes == 0 && Hours == 0) //(millis() - timer > 3000) { TimeLightOffOn = millis() + Interval; delay(999); //на 1000 будут пропуски, так лучше }Разницу видите? интервал - это интервал, а ваша переменная с непроизносимым именем - это начало отсчета.
Я вас понимаю, но я не программист и решив эту задачу сейчас, я к ней больше не вернусь в своей жизни. По крайней мере не собираюсь. У меня есть простенькая задачка которую я решу один раз в жизни и больше не вернусь к этому. Другое дело если бы я был студент и в дальнейшем мой заработок был связан с профессией программирования. А так... Решил задачу и забыл...
Вот за такие высказывания и гоняют тут тряпками! Если программирование микроконтроллеров - не ваше хобби или профессия, то Вы обязаны платить за услугу. Вас не стригут бесплатно в парикмахерской?
Быть долбое.ом - не стыдно, я тоже чего-то не знаю, стыдно быть наглым долбое.ом и выклянчивать услугу бесплатно.
Я вас понимаю, но я не программист и решив эту задачу сейчас, я к ней больше не вернусь в своей жизни. По крайней мере не собираюсь. У меня есть простенькая задачка которую я решу один раз в жизни и больше не вернусь к этому. Другое дело если бы я был студент и в дальнейшем мой заработок был связан с профессией программирования. А так... Решил задачу и забыл...
Вот за такие высказывания и гоняют тут тряпками! Если программирование микроконтроллеров - не ваше хобби или профессия, то Вы обязаны платить за услугу. Вас не стригут бесплатно в парикмахерской?
Быть долбое.ом - не стыдно, я тоже чего-то не знаю, стыдно быть наглым долбое.ом и выклянчивать услугу бесплатно.
Это не хобби и не профессия. Я на этом не заработаю. Это очередная жизненая задачка.
Работает! Спасибо, wdrakula!
+ поставил к вашей карме )
Работает! Спасибо, wdrakula!
+ поставил к вашей карме )
даже маленькая кружка, лучше большого спасибо.
Я вас понимаю, но я не программист и решив эту задачу сейчас, я к ней больше не вернусь в своей жизни. По крайней мере не собираюсь. У меня есть простенькая задачка которую я решу один раз в жизни и больше не вернусь к этому. Другое дело если бы я был студент и в дальнейшем мой заработок был связан с профессией программирования. А так... Решил задачу и забыл...
Правила предельно просты:
Если Вы хотите научиться на примере конкретной задачи, Вам помогут бесплатно.
Если Вы не хотите учиться, но Вам нужно решить конкретную задачу, для Вас сделают это за деньги.
Все остальное - mauvais ton.
Правила предельно просты:
Если Вы хотите научиться на примере конкретной задачи, Вам помогут бесплатно.
Если Вы не хотите учиться, но Вам нужно решить конкретную задачу, для Вас сделают это за деньги.
Все остальное - mauvais ton.
Вот с этим согласем полностью. Никого не волнует - зарабатываете вы на этом или нет.
Делай сам или плати.
Это главный принцип светлого капиталистического будущего, что мы с Путиным тут строим. ;) Вы против?
Qui ne travaille pas, ne mange pas. Ну раз уж пошли proverbes francais.
Это не хобби и не профессия. Я на этом не заработаю. Это очередная жизненая задачка.
До Вас никак не может дойти простая вещь. Я уже пытался Вам сказать, что для меня-то это профессия!
Вот, смотрите, я сегодя подвёз голосовавшую на дороге бабушку. Бесплатно. На попытку сунуть мне какую-то мелочь ответил, что типа не надо, я зарабатываю другим способом. А вот если бы на моём месте был таксист и начал бы бесплатно бабушек подвозить, это было было дико и странно, т.к. он-то как раз зарабатывает именно этим способом.
Точно также здесь. Я готов помочь начинающему коллеге чему-то научиться. И довольно часто это делаю здесь и в других местах безвозмездно. Но писать программы для решения чьих-то жизненных задач - ради бога, пожалуйста - но это моя профессиональная деятельность и бесплатно я этого не делаю также как таксист бесплатно не подвозит бабушек.
Вас я понял. "Злые" вы какие-то. ))
Работает! Спасибо, wdrakula!
+ поставил к вашей карме )
даже маленькая кружка, лучше большого спасибо.
кинуть вам денег на телефон за услугу? Сколько стоит ваш труд?
кинуть вам денег на телефон за услугу? Сколько стоит ваш труд?
такая работа стоит пива. Можешь на стоимость бутылки пива поставить свечку в храме.
О здравии р.б. Владислава.
Уважаемые!
Дерзну задать еще один вопрос в продолжение первого. Надеюсь от камней которые полетят в мою сторону я не погибну...
Код работает замечательно при зарание обозначеном времени в переменной TimeLightOffOn за пределами setup и loop. Как же мне сделать это значение не зарание фиксированным? Ведь в жизни часто все гараздо сложнее и это значение меняться в соответствии с тем какое время обратного отсчета задал пользователь. Один ставит 10сек и МК отсчитывает циклично в обратном направлении, а другой пользователь может поставит 1мин и тоже МК остчитывает.
Как же мне сделать это значение не зарание фиксированным?
А как же, кто-то говорил: "я решу один раз в жизни и больше не вернусь к этому"? Оказывается, как тут кто-то сказал:"в жизни часто все гараздо сложнее".
Теперь ответ:
Она же у Вас переменная, а не константа. Так что в любой момент Вы можете задать ей новое значение при помощи операции присваивания.
Если я правильно понимаю то переменную не в пределал Луп пользователь изминить не может.
ПИШУ код в согласии с вашей подсказкой:
unsigned long TimeLightOffOn; unsigned long Interval; void setup() { Serial.begin(9600); } void loop() { TimeLightOffOn = 5000; Interval = 5000; byte Seconds = ((TimeLightOffOn-millis())/1000UL)%60; byte Minutes = (((TimeLightOffOn-millis())/1000UL)/60UL)%60; byte Hours = (((TimeLightOffOn-millis())/1000UL)/3600UL)%24; Serial.print(Hours); Serial.print(':'); Serial.print(Minutes); Serial.print(':'); Serial.println(Seconds); if (Seconds == 0 && Minutes == 0 && Hours == 0) //(millis() - timer > 3000) { TimeLightOffOn = millis() + Interval; delay(999); //на 1000 будут пропуски, так лучше }Результат:
Вставил воть сюда, заработало:
unsigned long TimeLightOffOn; unsigned long Interval; void setup() { Serial.begin(9600); } void loop() { byte Seconds = ((TimeLightOffOn-millis())/1000UL)%60; byte Minutes = (((TimeLightOffOn-millis())/1000UL)/60UL)%60; byte Hours = (((TimeLightOffOn-millis())/1000UL)/3600UL)%24; Serial.print(Hours); Serial.print(':'); Serial.print(Minutes); Serial.print(':'); Serial.println(Seconds); if (Seconds == 0 && Minutes == 0 && Hours == 0) //(millis() - timer > 3000) { {TimeLightOffOn = 5000; Interval = 5000; TimeLightOffOn = millis() + Interval;} delay(999); //на 1000 будут пропуски, так лучше }Это правильно с точки зрения граммотного программиста?
Это правильно с точки зрения граммотного программиста?
Конечно, нет.
1. Переменная TimeLightOffOn используется в строке 14 до того, как она получит осмысленное значение.
2. Техника, используемая в строке 25 приводит к сбою при переполнении millis. Я Вам советовал изучить пример "блинк без делэй", видимо совет проигнорирован. Там работают через вычитание, а не через сложением и это правильно.
Я уж не буду придираться к мелочам, типа того, что
1. определяемые в строка 14-16 переменные получают значение, которое потом нигде не изменяется, значит их грамотнее объявить как const.
2. переменные TimeLightOffOn и Interval используются только в одной функции loop и нигде более, так каого рожна они объявлены глобальными?
3. Те же переменные всегда получают одни и те же значения. Зачем? Но, допускаю, что это "на вырост".
Ну, а строка 26 - это, наверное, для лулзов.
Это так, с первого взгляда, внимательно не смотрел.
Если я правильно понимаю то переменную не в пределал Луп пользователь изминить не может.
Вы под "пользователем" кого имеете в виду? Кто скетч пишет или кто кнопку нажимает? Если первое - Вы можете вставить переменную куда угодно, что вы ниже и продемонстрировали. Если того, кто будет пользоваться вашей прогой - он ни ни в одном из ваших скетчей ничего не сможет изменить, пока вы не добавите в программу средства связи с пользователем (например, кнопки для изменения интервала)
Это правильно с точки зрения граммотного программиста?
Конечно, нет.
1. Переменная TimeLightOffOn используется в строке 14 до того, как она получит осмысленное значение.
2. Техника, используемая в строке 25 приводит к сбою при переполнении millis. Я Вам советовал изучить пример "блинк без делэй", видимо совет проигнорирован. Там работают через вычитание, а не через сложением и это правильно.
Я уж не буду придираться к мелочам, типа того, что
1. определяемые в строка 14-16 переменные получают значение, которое потом нигде не изменяется, значит их грамотнее объявить как const.
2. переменные TimeLightOffOn и Interval используются только в одной функции loop и нигде более, так каого рожна они объявлены глобальными?
3. Те же переменные всегда получают одни и те же значения. Зачем? Но, допускаю, что это "на вырост".
Ну, а строка 26 - это, наверное, для лулзов.
Это так, с первого взгляда, внимательно не смотрел.
мигание без делэй? вот это? http://arduino.ru/tutorials/BlinkWithoutDelay
а техника вычитания это?
if(currentMillis - previousMillis > interval) {// сохраняем время последнего переключенияpreviousMillis = currentMillis;Если я правильно понимаю то переменную не в пределал Луп пользователь изминить не может.
Вы под "пользователем" кого имеете в виду? Кто скетч пишет или кто кнопку нажимает? Если первое - Вы можете вставить переменную куда угодно, что вы ниже и продемонстрировали. Если того, кто будет пользоваться вашей прогой - он ни ни в одном из ваших скетчей ничего не сможет изменить, пока вы не добавите в программу средства связи с пользователем (например, кнопки для изменения интервала)
Пользователь кто кнопки жмет. Я просто опустил этот момент. Управление пользователь энкодером будет осуществлять.
мигание без делэй? вот это? http://arduino.ru/tutorials/BlinkWithoutDelay
а техника вычитания это?
Ну, да, а Вы зачем-то используете сложение и наступаете на грабли.
Если я правильно понимаю то переменную не в пределал Луп пользователь изминить не может.
Вы под "пользователем" кого имеете в виду?
Пользователь кто кнопки жмет. Я просто опустил этот момент. Управление пользователь энкодером будет осуществлять.
Тогда да, обычно в loop(). Только чтобы енкодер работал, вам надо будет от delay() в коде loop() избавится совсем.
Женя! Я не исправлял его логичческие ошибки. Там не только сложение было, но я же говорил, что у меня скилл коррекционной педагогики не прокачен.
Сегодня я томный и похмельный, снова матерью Терезой побуду.
Вот вам таймер, нормальный. В мониторе порта стандартного ИДЕ нужно выбрать в правом нижнем углу, рядом со скоростью, "возврат каретки" или "новую строку", только не обе вместе ;).
вводим число секунд таймера в мониторе. Если ничего не вврдим, то нажатие Ентер - просто старт/стоп таймера. После "стопа" счет продолжится с того же места.
Все понятно?
void setup() { Serial.begin(115200); while (!Serial); Serial.print ("!!!Please choose CR or NL in the right down corner!!!"); Serial.println("Input Interval or press Enter to Start/Stop:"); } void loop() { static uint32_t Interval=10; static uint32_t startTime=millis(); static uint32_t lastShow = millis(); uint32_t currentTime = millis(); uint32_t secLeft = Interval - (currentTime-startTime)/1000L; byte buf[8] = "0000000"; byte i=0; static byte isRunning = 0; //Reading input while (Serial.available()) { if (i<7) buf[i++] = Serial.read(); } if (i == 1 && (buf[0] == 13 || buf[0] == 10)) { isRunning = 1 - isRunning; return; } if (i>1) { if (i< 8) buf[i] = 0; Interval = atoi(buf); Serial.print("New Interval is:"); Serial.println(Interval); Serial.println("Input Interval or press Enter to Start/Stop:"); startTime = currentTime; return; } //Show countdown if (isRunning) { if (secLeft < 1) {startTime = currentTime; return;} if (currentTime - lastShow > 999) { lastShow = currentTime; Serial.print(secLeft/3600); Serial.print(":"); Serial.print((secLeft%3600)/60); Serial.print(":"); Serial.println(secLeft%60); } } else startTime = currentTime - 1000L*(Interval-secLeft); }Женя! Я не исправлял его логичческие ошибки. Там не только сложение было, но я же говорил, что у меня скилл коррекционной педагогики не прокачен.
Сегодня я томный и похмельный, снова матерью Терезой побуду.
Вот вам таймер, нормальный. В мониторе порта стандартного ИДЕ нужно выбрать в правом нижнем углу, рядом со скоростью, "возврат каретки" или "новую строку", только не обе вместе ;).
вводим число секунд таймера в мониторе. Если ничего не вврдим, то нажатие Ентер - просто старт/стоп таймера. После "стопа" счет продолжится с того же места.
Все понятно?
void setup() { Serial.begin(115200); while (!Serial); Serial.print ("!!!Please choose CR or NL in the right down corner!!!"); Serial.println("Input Interval or press Enter to Start/Stop:"); } void loop() { static uint32_t Interval=10; static uint32_t startTime=millis(); static uint32_t lastShow = millis(); uint32_t currentTime = millis(); uint32_t secLeft = Interval - (currentTime-startTime)/1000L; byte buf[8] = "0000000"; byte i=0; static byte isRunning = 0; //Reading input while (Serial.available()) { if (i<7) buf[i++] = Serial.read(); } if (i == 1 && (buf[0] == 13 || buf[0] == 10)) { isRunning = 1 - isRunning; return; } if (i>1) { if (i< 8) buf[i] = 0; Interval = atoi(buf); Serial.print("New Interval is:"); Serial.println(Interval); Serial.println("Input Interval or press Enter to Start/Stop:"); startTime = currentTime; return; } //Show countdown if (isRunning) { if (secLeft < 1) {startTime = currentTime; return;} if (currentTime - lastShow > 999) { lastShow = currentTime; Serial.print(secLeft/3600); Serial.print(":"); Serial.print((secLeft%3600)/60); Serial.print(":"); Serial.println(secLeft%60); } } else startTime = currentTime - 1000L*(Interval-secLeft); }Интересно... я всегда считал, что чем меньше строчек тем проще код. Почему Вы считаете что у меня сложнее я покане понимаю. Просто потому что я использую метод сложения, а не вычитания?
Попробовал вогнать Ваш код в ИДЭ и получил токую ошибку:
Жесть. 1 - то что вы пишите в скетче это не программа, а исходник. А вот исходник компилируется в программу. А значит что зависимости от объема текста в скетче и объема программы нет никакой. Если строитель откроет проект строительства высотного дома найдет детский рисунок , то ему станет понятно как строить этот дом.
2 - что такое сложность программы. Сложность для компилятора или для программиста. А если у программиста вообще нет знаний, то он вообще больше 2 двух строк коментария не поймет ничего.
3- я не пытаюсь вас тролить. Программирование это не умение затролить друг друга на форуме. Программирование это умение писать программы, которые компилируются компилятором и дальше нормально работают.
4 - не в сложении и вычитании дело, а в провереном опыте. Вас не удивляет факт, что с понедельника до пятницы пять дней, а с пятницы до понедельника всего два дня. Скорее это не потому что понедельник день тяжелый. А потому что это проверенный жизнью факт.
Попробовал вогнать Ваш код в ИДЭ и получил токую ошибку:
Есть такое на старых ИДЕ.
нужно buf описать, как char [], а не как byte [].
Строка № 16
Нужно так:
================
Да. И смысл не проще/сложнее, а в том, что показанный код без делеев, то есть неблокирующий.
Для своего проекта Вы просто заменяете блок чтения ввода на свой энкодер, а блок вывода - на свой экранчик.
Для своего проекта Вы просто заменяете блок чтения ввода на свой энкодер, а блок вывода - на свой экранчик.
Разбираю ваш код на косточки. где экранчик поменять я понимаю, а вот где заменить код чтения ввода я не понимаю. Наверно потому, что у меня работает только энтр. т.е. старт/стоп причем отсчет начинается с значения переменной Interval в строчке 10. Сколько я там сек ставлю от такого числа и отсчитывает. А на цифры введенные в ком порте не реагирует. Какие бы не вводил считать начинает или продолжает с переменной Interval. И не могу еще понять как сбросить. Мне не нужно чтобы он продолжал отсчет после паузы. Нужно чтоб сбрасывался после стоп и при старте начинал опять.
руки кривые? Я специально 1.6.5 поставил (не на Виндоус, а на Линух - но это не должно иметь значение) - все там нормально, кроме дебильного слова "вргужаем". Курсор в строку ввода поставьте и "возврат каретки" выберите.
Код чтения с ком-порта даже коментарием выделен. Что именно вам не ясно?
Но, я повторю, я не спец в коррекционной педагогике. Может кто другой возмется?