Некорректная отработка интервала
- Войдите на сайт для отправки комментариев
Добрый день!
Есть такой код
#define led_pin 3 int regim = 1; int flag = 0; int f1 = 0; int f = 0; int count; unsigned long previousMillis = 0; unsigned long previousMillis1 = 0; unsigned long interval = 1000; unsigned long interval_1 = 60000; void setup() { Serial.begin(9600); pinMode(led_pin, OUTPUT); pinMode(2, INPUT_PULLUP); } void loop() { if (digitalRead(2) == LOW && flag == 0) { regim++; flag = 1; if (regim > 3) regim = 1; } if (digitalRead(2) == HIGH && flag == 1) flag = 0; if (regim == 1) { count = 0; f1 = 0; f = 0; } if (regim == 2) { if (f == 0) { Serial.print(millis()); Serial.println(" Start"); } f = 1; unsigned long currentMillis = millis(); if (count < 255) { digitalWrite(led_pin, HIGH); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; count = count + 5; } } if (currentMillis - previousMillis1 >= interval_1) { previousMillis1 = currentMillis; regim = 3; } analogWrite(led_pin, count); } if (regim == 3) { if (f1 == 0) { Serial.print(millis()); Serial.println(" Stop"); Serial.println(""); } f1 = 1; digitalWrite(led_pin, LOW); } }
При нажатии на кнопку включается нарастающий ШИМ (regim==2), при повторном нажатии этой же кнопки ШИМ выключается (regim==3). Если при включенном ШИМ в течении периода заданном interval_1 кнопка не была нажата - ШИМ отключается самостоятельно. Так вот этот интервал не всегда соответствует заданному. Если бы отличался на пару секунд я бы и не обращал на это внимания. Но разница доходит порой до 20-30 секунд. Сделал печать в порт меток времени включения-выключения. Например вот некоторые результаты вывода в порт для интервала в 60 секунд
15:41:34.059 -> 43354 Start 15:41:50.720 -> 60000 Stop 15:41:50.720 -> 15:42:12.607 -> 81895 Start 15:42:50.702 -> 120000 Stop 15:42:50.702 -> 15:43:02.246 -> 131574 Start 15:43:50.668 -> 180000 Stop 15:43:50.668 -> 15:44:25.316 -> 214640 Start 15:44:50.637 -> 240000 Stop 15:44:50.637 -> 15:45:10.902 -> 260271 Start 15:45:50.620 -> 300000 Stop 15:45:50.620 -> 15:58:50.233 -> 1079889 Start 15:59:47.610 -> 1137242 Stop 15:59:47.610 -> 16:05:05.152 -> 1454894 Start 16:05:44.558 -> 1494330 Stop 16:05:44.558 ->
Как видно только в одном случае разница около 3 секунд. В остальных случаях разница намного больше от заданных 60 секунд. В чем ошибка?
обратите внимание, что у вас отметка "Stop" почти всегда выводится при "круглых" значениях миллис. Задуматесь, почему так...
Подсказка - обратите внимание, в какой момент вы пускаете секундомер для большего интервала.
Подсказка - обратите внимание, в какой момент вы пускаете секундомер для большего интервала.
Ну, я думал что пуск секундомеров что для одного, что для второго интервала происходит в 44 строке. но судя по вашему ответу понимаю что я ошибаюсь? Добавил после 34 строки
previousMillis1=millis();
вроде бы заработало как нужно. Или и это неправильно? Тогда можно еще одну подсказку?
з/ы. Сколько не пытаюсь разобраться с этим millis всегда у меня проблемы с правильным пуском. Никак не могу понять когда нужно запускать секундомер.
Ну, я думал что пуск секундомеров что для одного, что для второго интервала происходит в 44 строке
строка 44 к пуску секундомеров вообще никакого отношения не имеет, ни к первому, ни ко второму
з/ы. Сколько не пытаюсь разобраться с этим millis всегда у меня проблемы с правильным пуском. Никак не могу понять когда нужно запускать секундомер.
если честно, я не очень разбирался в логике вашего кода. Но из самых общих соображений, если сообщение "Start" означает начало интервала - то где-то рядом с этой строкой и надо пускать секундомер.
А у вас как-то странно все - "Старт" в одном месте, запуск секундомера в другом, его окончание - в третьем... по логике, для периодического процесса все эти три вещи должны происходить в одном блоке кода.
строка 44 к пуску секундомеров вообще никакого отношения не имеет, ни к первому, ни ко второму
Как тогда должен выглядеть пуск секундомера?
А у вас как-то странно все - "Старт" в одном месте, запуск секундомера в другом, его окончание - в третьем... по логике, для периодического процесса все эти три вещи должны происходить в одном блоке кода.
Возможно я просто не совсем удачно обозначил метки. Start это запуск одного режима. Stop - переход в другой
строка 44 к пуску секундомеров вообще никакого отношения не имеет, ни к первому, ни ко второму
Как тогда должен выглядеть пуск секундомера?
пуск секундомеров у вас происходит в строке 49 для меньшего интервала и в строке 53 - для большего. А строка 44 - это только запрос текущего времени
У Вас достаточно плохо комментирована программа (от слова - никак). Что Вы предполагали, делая те или иные действия приходится догадываться. Потратьте пол-часа, поставьте комментарии, и сами поймете и остальные обойдутся без хрустальных шаров.
пуск секундомеров у вас происходит в строке 49 для меньшего интервала и в строке 53 - для большего.
Что-то я окончательно запутался. Может в 48 и 54 или 49 и 55?
У Вас достаточно плохо комментирована программа (от слова - никак). Что Вы предполагали, делая те или иные действия приходится догадываться. Потратьте пол-часа, поставьте комментарии, и сами поймете и остальные обойдутся без хрустальных шаров.
Проставил, получилось как-то так...
Start Stop заменил на ШИМ включен - выключен
Попробуйте переместить 58_ю строчку (
previousMillis1 = currentMillis;) под 52_ю
Не надо "запускать секундомер", millis() и так тикает без посторонней помощи. Следует запомнить его показания на момент старта.
В общем, если я правильно понял, мне нужно сохранять previousMillis1=millis() как можно чаще перед тем как проверять условие.
Как я уже говорил поставил эту строку после 34 строки и вроде бы начал интервал отрабатывать нормально.
p/s Что интересно - меня подвел Proteus. Я сначала в нем проверял работу и там первоначальный код все красиво отрабатывал, а вот в железе вылез баг.
previousMillis1=millis сохранять в момент начала режима, т е отсчёт вести с момента включения шим
поддерживаю. previousMillis1=millis - это точка отсчета, относительно которой по превышении значения заданного интервала произойдет событие. Короче говоря, засекаем время в момент когда побежали и постоянно проверяем когда выйдет запланированное побегать время. Как только это произошло, можно идти в душ и смывать трудовую испарину :)
В общем, если я правильно понял, мне нужно сохранять previousMillis1=millis() как можно чаще перед тем как проверять условие.
совершенно не правильно. зачем запоминать то, что вам не требуется, вам ведь интересен интервал времени с момента некоторого события?
другое дело если вам требуется перезапускать таймер каждый раз, если что-то произошло. На пример нажата кнопка и начинаем отсчет заново, а если кнопка не нажата делаем нечто когда прошел определенный промежуток времени.
В общем, если я правильно понял, мне нужно сохранять previousMillis1=millis() как можно чаще перед тем как проверять условие.
совершенно не правильно. зачем запоминать то, что вам не требуется, вам ведь интересен интервал времени с момента некоторого события?
другое дело если вам требуется перезапускать таймер каждый раз, если что-то произошло. На пример нажата кнопка и начинаем отсчет заново, а если кнопка не нажата делаем нечто когда прошел определенный промежуток времени.
Ну на данный момент я остановился на том что previousMillis1=millis() запоминаю при каждом нажатии кнопки. Пока вроде бы работает нормально. Если и это неправильно ткните уже мне пожалуйста пальцем куда его вставить.
Ну на данный момент я остановился на том что previousMillis1=millis() запоминаю при каждом нажатии кнопки. Пока вроде бы работает нормально. Если и это неправильно ткните уже мне пожалуйста пальцем куда его вставить.
я всего лишь прокомментировал ваше сообщение
В общем, если я правильно понял, мне нужно сохранять previousMillis1=millis() как можно чаще перед тем как проверять условие
к сожалению в вашем коде ковыряться достаточно сложно, как и в любом чужом - уж слишком много времени требуется на вникание в алгоритм, который вы пытаетесь реализовать. могу рекомендовать располагать фигурные скобки одной функции на одном уровне, а для функций находящихся внутри другой функции увеличить отступ - читабельнее код становится
обратите внимание на строку 10 и сравните у себя в посте 8
обратите внимание на строку 10 и сравните у себя в посте 8
Разве фигурные скобки нельзя пропускать если в условии выполняется только один оператор?
"работает - не трож" (с)
А вот разобраться в каждой строчке стоит однозначно.