Помогите нубу с таймером
- Войдите на сайт для отправки комментариев
Это отдельный кусочек кода из программы автозапуска. Мне хотелось избавиться от Delay() в функции запуска движка и после поиска в интернете я почувствовал себя тупым потому ,что не понял как из примеров с миганием можно сделать таймер который не крутится постоянно , а работает только тогда когда нужно . Из программы автозапуска скопипастил вот такой таймер
if (millis() > Time1 + 60000) { Time1 = millis(); if (timer1 > 0) { timer1--; } }
#define Btn_pin 4 #define Pin_btn 9 #define Pin_led 13 #define P_led 10 #define Pi_led 11 unsigned long Time, Time1, Time2 = 0; int timer, timer1 ; void setup() { Serial.begin(9600); pinMode( Pi_led, OUTPUT); pinMode( P_led, OUTPUT); pinMode(Pin_led, OUTPUT); pinMode(Pin_btn, INPUT_PULLUP); pinMode(Btn_pin, INPUT_PULLUP); } void loop() { if (millis() > Time + 1000) { Time = millis(); zapusk(); if (timer > 0) { timer--; } } if (millis() > Time1 + 60000) { Time1 = millis(); if (timer1 > 0) { timer1--; } } if (millis() > Time2 + 10000) { Time2 = millis(), detection(); } if ( digitalRead (Pin_btn) == LOW) { // Условие запуска startengine(); } } void startengine() { if ( digitalRead (Btn_pin) == LOW) { // Доп проверка timer1 = 15 ; timer = 25; digitalWrite (P_led , HIGH); // Включаем нагрузку 1 Serial.println("start"); } } void zapusk() { if (timer == 20 ) { digitalWrite (Pi_led , HIGH); // Если прошло определённое время то включаем нагрузку 2 // starter == true; Serial.println("ACC"); } if (timer == 15 ) { digitalWrite (Pin_led , HIGH); // Если прошло определённое время то включаем нагрузку 3 Serial.println("starter"); } if (timer == 10 ) { digitalWrite (Pin_led , LOW); // и выключаем её через определённый промежуток времени Serial.println("starter off"); } } void stape() { // Функция остановки digitalWrite (P_led , LOW); digitalWrite (Pin_led , LOW); digitalWrite (Pi_led , LOW); Serial.println("stop"); timer = 0; timer1 = 0; } void detection() { if ( digitalRead (Btn_pin) == LOW) { // Функция остановки по кнопке Serial.println("knock stop"); stape(); } if (timer1 == 0 ) { // Функция остановки по таймеру stape(); } }
Код работает, но немного напрягает такой момент, если в loop () ввести пример blink это который с delay из примеров ардуино то счётчики начинают чудить. В основной программе при отправке сообщений на сервер и в других местах программы присутствуют короткие Delay, но программа в принципе работает, отсюда возникают вопросы
1 ) Правильно ли я делаю . Если нет то пожалуйста покажите пример подобной программы, потому что к сожалению я не понял как применить идеальный таймер в моей ситуации .
2) Есть ли смысл заморачиваться с титановыми велосипедами ?
Заранее благодарю всех откликнувшихся!
Не знаю, поможет ли
https://github.com/DetSimen/Arduino_TimerList
если в loop () ввести пример blink это который с delay из примеров ардуино то счётчики начинают чудить.
Это нормально.
1 ) Правильно ли я делаю .
Нет, ибо
других местах программы присутствуют короткие Delay
Если используются замеры времени на миллис, то делэи использовать нельзя. А если используются делэи, то счётчики времени нужно делать на прерываниях таймера.
Дак может и напрягаться на этот счёт некому...
Не знаю, поможет ли
https://github.com/DetSimen/Arduino_TimerList
Смотрел изначально ваш материал по таймеру и понял , что я слишком туп чтобы его понять или не дорос. Если у вас есть пример с вариантом подобным моему , чтобы я мог его подёргать на своей атмеге посмотреть как он работает ,глядишь и понимание прийдет , буду вам очень благодарен.
Если используются замеры времени на миллис, то делэи использовать нельзя. А если используются делэи, то счётчики времени нужно делать на прерываниях таймера.
[/quote
У меня там весь код такой ( конечно же не у меня, а там откуда я его взял (анатомия автозапуска , возможно видели этот проект на драйве или гитхабе) делэй вперемешку с миллис ) , спасибо за подсказку .В основном коде каждую минуту отправка сообщения на mqtt сервер и при отправке сообщения реализован delay(200) ,получается код виснет часики и так не особо точные (устройство находится в машине ) а с делеями и вовсе шляпа выходит , прискорбно.
В общем спасибо за широкие и развёрнутые ответы, мне в принципе нужен был лишь издали похожий пример не более того вставлять таймер в мой код не нужно , ну а блинк без делей я как нить сам найду в гугле авось не забанили тока он мне на ....
Вдогонку: Никогда так
if
(millis() > Time1 + 60000) {
не делай.
Да, чтобы избежать глюков, связанных с переполнением millis(), правильно писать так
Вдогонку: Никогда так
if
(millis() > Time1 + 60000) {
не делай.
Ок а как делать правильно?
Вам же написали в #9! Вы совсем не читаете? :)
Да, чтобы избежать глюков, связанных с переполнением millis(), правильно писать так
Я почему то думал что в варианте который я использую миллис не считает до тех пор пока ему не присвоится значение ~20 секунд , то есть счётчик остановлен , а после запуска начинается обратный отсчёт timer -- .Или я что то непонимаю?
Ну вот, как-то так. Фактически у вас есть конечный автомат "от вермени" (мигалка), который управляет светодиодом (первый everyMillis) он использует текущий заданный интервал мигания.
Затем есть ещё 2 конечных автомата от вермени (тоже по сути мигалки), которые включаются или выключаются флагами, которые управляются кнопкой. И есть опросник кнопки, который должен быть самоблокирующимся, чтобы не срабатывать много раз повторно. Кнопка только управляет автоматами - таймерами, которые саовыключаются после второго срабатывания.
Надеюсь работает, не проверял. :)
Надеюсь работает
Напрасно надеетесь. Не только не работает, но даже и не компилируется.
Вам же написали в #9! Вы совсем не читаете? :)
Если бы один человек написал так делать не правильно , нужно делать вот так , я б и вопроса не задал.
Мелкие описки. Теперь - компиляется. :)
Акей, пусь будет 1 человек.
Вдогонку: Никогда так
if
(millis() > Time1 + 60000) {
не делай.
Делай так
Спасибо добрый человек ! Вечерком попробую .
В качестве гайда по неблокирующим делеям, может поможет:
Короткое нажатие на кнопку меняет направление, долгое - крутить двигатель. Перекидывание полярности двумя реле, третье - ход.
Мелкие описки.
А программе без разницы, мелкие там описки или крупные
Теперь - компиляется. :)
Но, не работает :(
Дико извиняюсь если кто то успел прочитать )) Det, таймер работает.
и чего бы ему не работать? )))
Uint32 _t now = millis (); прописал перед сетапом , я так то электросварщик думаю мне простительно образование 3 класса ))
Да ты шо? О_О
Наконец-то написал и даже компилируется
В loop() там всего несколько строчек получилось
Всё остальное вынесено в отдельные функции! Ещё пока не проверил, но думаю, что работать будет. И ещё мне пришла в голову мысль, написать как-то так
а потом проверять как-то так
В loop тогда вообще всего несколько строчек
Только что проверил, - компилируется без ошибок! а как работает пока не проверял.
Кстати заметил, что созданная мною переменная isPressed почему-то подсвечивалась - пришлось её переименовать в is_Pressed!
Всё остальное вынесено в отдельные функции! Ещё пока не проверил, но думаю, что работать будет. И ещё мне пришла в голову мысль, написать как-то так
Для одного интервала - будет. Для нескольких - надо несколько функций писать
а всего то надо только внимательно прочитать и спросить, что непонятна.
https://github.com/DetSimen/Arduino_TimerList
Но, не работает :(
А это уже в раздел "Ищу исполнителя". Там - помогут подправить, не смею отбирать хлеб.
А это уже в раздел "Ищу исполнителя". Там - помогут подправить, не смею отбирать хлеб.
Т.е. Вы публикуете суперкод, а мне с ним в "Ищу исполнителя"? Как похоже на Вашего Учителя :)
Не, не пойду - амфибиотропная асфиксия :(
Буду страдать и надеяться, что кто-нибудь даром подправит :)
Но, не работает :(
А это уже в раздел "Ищу исполнителя". Там - помогут подправить, не смею отбирать хлеб.
В качестве гайда по неблокирующим делеям, может поможет:
Короткое нажатие на кнопку меняет направление, долгое - крутить двигатель. Перекидывание полярности двумя реле, третье - ход.
То есть если вмэтот код добавить делэй код не будет блокироваться?
А если мы в него рельсу пихнём...
Пытаюсь разобраться, как правильно. Нужно создать класс, например Prog_Timer
Значение передавать в частную переменную
и использовать её в функции, переписанной так
Правильно ли я думаю?
В вызывать функцию и проверять, наверно придется так
Нет не правильно, внимательно читаем то что находится рядом с millis(), видим например циферки 800, 300, видим что 300 больше чем а 800 меньше чем, делаем выводы что это "с 300та до 800от", как часы дня в режиме работы, типа как приходишь в собес а там тётенька "вас много а я одна, у меня обед". Люблю эту фразу из совка, особенно люблю читать как тоскующих по Брежневу за неё нещадно увольняют :3
По поводу delay() советую раз запомнить чтобы отложилось: это синхронная функция. Синхронное можно делать когда:
1. точно знаем когда, что. точно не провороним тактовый сигнал
2. прочих асинхронных сигналов нет
Под "асинхронными" здесь подразумеваются любые события, которые не укладываются в обозначенные темпоральные кванты (то бишь синхронная схема читает состояния только раз в надцать наносекунд/минут/лет и никак иначе, вот допустим тактируется 110 - значит обязательно на 0й, на 110й, на 220й и т. д., то есть на 8030й можно (потому что 8030/110) = целое число), на 8000й низя, так как частота строба 110 нс. И всё. Ни левее ни правее надо чтобы было на графике. Поэтому либо на delay полностью всё, либо если надо выдрать из кода delay(), то вся очередь автоматически становится асинхронной, и от всех вхождений delay() надо избавиться. Даже от delay(15) могут возникать выверты.
Слово service_ в названии функции призвано обозначить, что она вписана в loop() и должна прорабатывать (возвращаться назад в loop) как можно быстрее.
All, кто-нибудь, возможно кто-то знает более внятное объяснение как показать человеку разницу между синхронным выполнением процессов и асинхронным. Я хз.
Очень интересно ! Но ни хрена не понятно . На самом деле очень мало по форумам так конкретно отвечают , спасибо большое за пояснения , просто я прочитал неблокирующая задержка как код которому все ни по чём . А в своих потугах обещаю избавиться от делеев... По крайней мере от тех которые вызываются регулярно.
http://arduino.ru/forum/programmirovanie/vopros-po-ispolzovaniyu-millis вот здесь неплохо расписано , как раз мой случай миллис и автозапуск .
Нет, неблокирующие задержки работают только если весь остальной код тоже неблокирующий. Вчитайтесь в слово - это "неблокирующая" задержка. А не "неблокируемая", понимаете разницу? Она сама других не блокирует, но ее заблокировать может любой делей. Поэтому Вам надо избавиться в коде АБСОЛЮТНО ОТ ВСЕХ ДЕЛЕЕВ, а не только от каких-то тех, которые вам больше мешают
Переделал свой код, теперь он выглядит так
Работает, но как-то странно - интервал таймера вроде бы не всегда одинаковый! А по идее должно работать так:
1. После включения светодиод переключается каждые 500мс (то есть медленно мигает)
2. Если кнопка нажата - переключение каждые 50мс (мигает быстро)
3. Если отпущена - запустить таймер на 2000мс, и когда время прошло, переключиться с режима быстрого мигания на на медленный.
Не знаю, как правильно написать такой кусочек? Так
или так
В коде этот фрагмент начинается с 51 строки (она выделена).
junior_develope - опять в коде while? - строка 52 ?
Как вы (новички) не поймете. что использование в коде конструкции while(Timer) превращает ваш код в банальный блокирующий делей???
У вас в программе уже есть цикл - это сама процедура loop() . Никаких других while for или do() для работы таймеров на миллис КАТЕГОРИЧЕСКИ НЕ НУЖНО.
Да Вы правы! Спасибо!
Если не трудно, подскажите пожалуйста, как тогда здесь можно обойтись без while. Чем его можно заменить?
как тогда здесь можно обойтись без while. Чем его можно заменить?
Для начала вам надо выделить то, что сейчас внутри while - в отдельное состояние. И подумать, что произойдет. если в это время кто-то снова нажмет кнопку. Я бы, например. разделил в отдельные переменные состояние светодиода и состояние кнопки. Так, как сейчас - одна переменная stste - логику прописать будет трудно.
а можно вот так переписать (сорри за возможные опечатки - проверить негде)
Нет, неблокирующие задержки работают только если весь остальной код тоже неблокирующий. Вчитайтесь в слово - это "неблокирующая" задержка. А не "неблокируемая", понимаете разницу? Она сама других не блокирует, но ее заблокировать может любой делей. Поэтому Вам надо избавиться в коде АБСОЛЮТНО ОТ ВСЕХ ДЕЛЕЕВ, а не только от каких-то тех, которые вам больше мешают
Останутся только те делэй которые используются для первоначальной установки связи с сервером , а так то устройство работает с ноября месяца и постоянно что то изменяется .
Подскажите такой вариант жизнеспособен ?
А какие переменные у вас инициализируются, для начала?
Подскажите такой вариант жизнеспособен ?
Что касается кода в loop() - почему бы и нет? Насколко я вижу, вы сначала миллисом отмеряете интервал в 100мс, потом накапливаете 100 таких интервалов - получаете 10 секунд, а сделав так 6 раз - получаете минуту. Да, можно делать и так, хотя по-моему проще все три интервала отмерить непосредственно с помощью миллис, без вложенных циклов.
Что касается функций something() в конце программы - если честно, я не понял, к чему они. В коде они нигде не вызываются. И в коде этих функций встречается странный фрагмент:
очевидно, что если в третьей строке des2 =0 - условие в четвертой строке никогда не выполнится....
Функция здесь и не вызывается это просто пример не буду же я портянку на ~450 строк выкладывать. Странно, но эта хрень работает на макете - вызывается функция счётчик в третьей строке сбрасывается и начинает считать от нуля четвертая строка срабатывает по условию... Не знаю насколько это будет стабильно видимо нужно пробовать.