Здравствуйте Все. Есть термометр на ардуино, который отправляет данные о критической температуре каждые 10 мин, с помощью GSM модуля. Интервал отправки, реализован мной с помощью функции millis(). Но поскольку, через 50 дней счётчик millis() обнуляется (а железка ведь должна работать постоянно), у меня есть сомнения, по поводу того, правильно ли я реализовал, "защиту", от этого "глюка". Меня терзают смутные сомнения, что всё можно реализовать гораздо проще. Вот "кусочек" кода: if((millis() == 4294967295)) { delay(1); // millis() тут по идее должна сбросится на 0, через 50 дней работы. currentTime = millis(); // И переменная должна быть равна 0. loopWarm = currentTime; loopKalt = currentTime; } currentTime = millis(); if(loopWarm >= 4294967294-600000) // Эта моя "защита", от возможного наложения, в 10 мин, если температура будет критической в этот момент, чтобы модуль не смог "забросать" SMS ками. { count_on = 0; // Не разрешит отправить СМС, если значение loopWarm больше 4294367294 (если оно будет больше, то при прибавлении 600000, будет переполнение unsigned long). } else { count_on = 1; } if(myTemp < 30) { loopWarm = currentTime; // Если температура ниже 30. } if((myTemp >= 30)&&(currentTime >= (loopWarm + 600000))) // Сработает, если температура выше, или равна 30, и если текущее время, больше loopWarm, на 10 мин (600000 милисекунд). { sms_on = 1; // Разрешает отправку SMS loopWarm = currentTime; } if((sms_on == 1)&&(count_on == 1)) { sms(String ("TempCritical: "), String (myTemp), String (" gradus C"), String("+7700000000")); // ВПИШИТЕ НОМЕР, с которого Вы будете звонить на модуль sms_on = 0; count_on = 0; } Сильно, не пинайте, я в программировании новичок. Подскажите, какие вы видите ошибки в коде, и как его можно оптимизировать, или вообще изменить. Заранее благодарю, за помощь.
Если переписать условие срабатвания как (currentTime - loopWarm) >= 600000 то оно будет работать и до перепеолнения millis. и после, и во время без всяких дополнительных проверок.
А чем Вам delay не delay?У Вас в эти 10 минут между посылками процессор производит сложные вычисления?Или простые решения не для Вас?
Вопрос-то не об этом. Суть вопроса в применении конкретной функции millis, а не в том, как вообще сделать задержку в цикле. И не надо советовать плохое. Человек пытается написать цикл без делай - и это очень хорошо. И пусть в этом случае можно все сделать и с использованием делай - зато когда ему понадобится от него избавиться - он же будет готов.
В чем плохое?В данном конкретном случае именно delay чтбы процессор эти 10 минут не жил своей жизнью. millis да это круто где то только это и нужно но в данном случае именно так.И упадет проблема с переполнением.На Си небось delay используете?Или как?
Во-первых, нет никакой "проблемыы с переполнением". Во-вторых. в системах , реагирующих на внешние события - делаи использовать нельзя. От языка программирования это не зависит.
У меня в коде, и так delay много, а я еще планирую в будущем, ещё датчиков к железке подцепить: хотя Вы конечно правы: у меня показания температуры посылаются через радио модуль NRF24L01, а СМС, это так, дополнительная мера безопасности - не будет же модуль постоянно смски посылать.
То есть, вот так должно без проблем с переполнением работать? currentTime = millis(); if(myTemp < 30) { loopWarm = currentTime; // Если температура ниже 30. } if((myTemp >= 30)&&((currentTime - loopWarm) >= 600000)) // { sms(String ("TempCritical: "), String (myTemp), String (" gradus C"), String("+770000000")); // loopWarm = currentTime; } currentTime = millis(); if(myTemp1 > 18) { loopKalt = currentTime; // Если температура выше 18. } if((myTemp1 <= 18)&&((currentTime - loopKalt) >= 600000)) // { sms(String ("TempDown: "), String (myTemp1), String (" gradus C"), String("+77000000")); // loopKalt = currentTime; }
Есть, конечно, даже в Ардуино IDE - см функцию attachInterrupt и другие ... еще можно писать напрямую через регистры МК. ...или я не понял, о чем вы спрашиваете Никак не делаю. В событийном программировании (event-driven programming) нет нужды делать паузы. Если подпрограмме нечем заняться - она возвращает управление диспетчеру задач. Честно говоря, Airbus, я не вполне понимаю, с чем Вы пытаетесь спорить. То ли Вы недостаточно ясно выражаетесь, то ли просто далеки от этого...
Да не собираюсь я с Вами спорить.Я вообще далек от программирования.Если Вас это успокоит считайте так.
Ну тогда не сочтите за нотацию, а просто как совет - чем раньше Вы избавитесь от delay в своих скетчах - тем лучше. Delay вообще можно применять только в программах, которые выполняют одновременно СТРОГО ОДНО действие. А таких задач в сфере Ардуино очень мало. Даже мигание двумя светодиодами - уже два действия и написать его через delay весьма трудно, а через millis - запросто.
Ну а можно мигать так. Тоже программа на millis() построена Спойлер: Программа Код (C++): /**/ uint32_t mill;// переменная под millis() //--------Cl_Led---------------------------- // класс светодиод class Cl_Led { Cl_Led *next; // <-- указатель на след элемент const byte pin; const bool inv; bool led; bool stat;// 1 мигает 0 нет uint32_t past, time; public: static Cl_Led *start; //<-- статический указатель на начало списка static void setup() { for (Cl_Led *ii = start; ii != NULL; ii = ii->next)ii->init(); } static void loop() { for (Cl_Led *ii = start; ii != NULL; ii = ii->next)ii->run(); } Cl_Led(byte _pin, bool _inv) // <-- конструктор : pin(_pin), inv(_inv) { this->next = start ; start = this; } void init() { pinMode(pin, OUTPUT); OFF(); } void ON() { led = 1; digitalWrite(pin, led ^ inv); stat = 0; } void OFF() { led = 0; digitalWrite(pin, led ^ inv); stat = 0; } void blink(uint32_t _time = 500) { time = _time; past = mill; stat = 1; led = 1; digitalWrite(pin, led ^ inv); } void run() { if (!stat) return; if (mill - past >= time) { past = mill; led = !led; digitalWrite(pin, led ^ inv); } } }; Cl_Led *Cl_Led::start = NULL; //------Cl_Btn------------------------------------------ // класс кнопка class Cl_Btn { Cl_Btn *next; // <-- указатель на след элемент const byte pin; void (*Do1)(); bool btn, btn_old; bool bounce = 0; // антидребезговый флаг uint32_t past = 0 ; public: static Cl_Btn *start; //<-- статический указатель на начало списка static void setup() { for (Cl_Btn *ii = start; ii != NULL; ii = ii->next)ii->init(); } static void loop() { for (Cl_Btn *ii = start; ii != NULL; ii = ii->next) { ii->run(); } } Cl_Btn(byte _pin, void (*_Do1)()) : pin(_pin), Do1(_Do1) { this->next = start ; start = this; } void init() { pinMode(pin, INPUT_PULLUP); btn_old = digitalRead(pin); } void run() { if (! bounce && btn != digitalRead(pin)) { // если прошел фронт изм на выводн bounce = 1; // выставить флаг past = mill; // сделать временую засветку } else if ( bounce && mill - past >= 5 ) { // если прошло антидребезговое время bounce = 0; // то снять флаг btn_old = btn ; btn = digitalRead(pin) ; // прочитать реальное значение на выводе if (btn_old && ! btn) Do1(); } } }; Cl_Btn *Cl_Btn::start = NULL; //---------Компановка--------------------------- Cl_Led Led1(/*пин*/13,/*инв*/0); void Do_Btn1() { Led1.ON(); } void Do_Btn2() { Led1.OFF(); } void Do_Btn3() { Led1.blink(200); } Cl_Btn Btn1(/*пин*/2,/*обраб наж*/Do_Btn1); Cl_Btn Btn2(/*пин*/3,/*обраб наж*/Do_Btn2); Cl_Btn Btn3(/*пин*/4,/*обраб наж*/Do_Btn3); //----------main()-------------------------- void setup() { Cl_Led::setup(); Cl_Btn::setup(); } void loop() { mill = millis(); Cl_Led::loop(); Cl_Btn::loop(); } /*Скетч использует 1614 байт (5%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 67 байт (3%) динамической памяти, оставляя 1981 байт для локальных переменных. Максимум: 2048 байт. */
Вот так будет дергать верно даже после того как millis() начнет с начала: Код (C++): if(millis() - lastTime > interval) { lastTime = millis(); .... } При условии, что переменные беззнаковые, само собой.
Это не совсем так. Delay можно применять и при выполнении разных задач одновременно. Вот тут объяснил как: http://forum.amperka.ru/threads/Потоки-в-avr.9856/ И ни чего страшного в 'delay' нет, просто надо с умом подходить к решению задач.
Спасибо, почитал с интересом. но вообще, подобных библиотек и систем много, мне идея FreeRTOS понравилась больше(теоретически, на практике не пробовал). Что касается моего поста - я имел в виду традиционное программирование, без multi-task надстроек.