Непонятная работа millis()
- Войдите на сайт для отправки комментариев
Втр, 17/04/2018 - 23:40
Вообще-то не уверен, в программировании или в железе спрашивать надо... Простите, если что.
Значит, с delay() наигрался, сел изучать millis(). Накатал первый скетч:
int timeout=1000; unsigned long nextmove; void setup() { // put your setup code here, to run once: Serial.begin(9600); nextmove = millis()+timeout; } void loop() { // put your main code here, to run repeatedly: int currenttime = millis(); if (currenttime >= nextmove) { Serial.print(nextmove); Serial.println(" milliseconds passed; "); nextmove=currenttime + timeout; } }
Открываю монитор порта и вижу вот такое:
Ну и, собственно, это что? Китайская железяка так себя ведет, или это секретная фишка такая?
Заранее спасибо за ответы.
Ну и, собственно, это что? Китайская железяка так себя ведет, или это секретная фишка такая?
обычное дело - китайцы миллис палёный прошили в контроллер.
рекомендую пользоваться российскими контроллерами - там всё по ГОСТу. О_О
*
int
currenttime = millis();
Угу. millis() он большой в маленький холодильник int не помещается. Нужен большой двухкамерный unsigned long .
Угу. millis() он большой в маленький холодильник int не помещается.
если свернуть в рулон, то помешается и в bool
Угу. millis() он большой в маленький холодильник int не помещается. Нужен большой двухкамерный unsigned long .
Ну между прочим в моем крутом коде натурально unsigned long :)
Ну между прочим в моем крутом коде натурально unsigned long :)
В одном месте. А во втором - int. Код у тебя не крутой, а так - в мешочек :)
ЗЫРЬ СТРОКУ 12!!!
А. Понял. Спасибо :)
Ну между прочим в моем крутом коде натурально unsigned long :)
вместо выепываться - перечитал бы свой код:
int
currenttime = millis();
Все, все, не пинайте сильно :D Спасибо!
Какое спасибо! А где вопрос про переполнение и борьбу с ним?
и, вдогонку - вот это nextmove=currenttime + timeout; не переживёт переполнения миллис.
кури пример Мигаем светодиодом без delay()
Покурил, спасибо :) Заодно и эту http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis, правда, не уверен, что все правильно понял, но что сложение - это плохо, уже, буду надеяться, усвоил :)
Добрый совет - никогда так не говорите. Хотите задать вопрос - задавайте, но никогда не высказывайтесь столь пренебрежительно - выглядите не очень умно.
Да уж. Выступил :/
Кстати, раз уж Вы поняли про переполнение, чего не исправили свой код? Или исправили, просто сюда не выложили?
Исправил, да. Думал, чего ж людям голову морочить... В общем, задача у меня вполне конкретная (и, собственно, вряд ли я буду в тему ардуино дальше вгрызаться, пока/если не появится новое непреодолимое желание :) ) - организовать подсветку в пруду на даче. Должны быть две группы по два RGB-прожектора, которые бы тупо переливались в классическом порядке перебора цветов (красный-оранжевый-желтый-зеленый-голубой-синий-фиолетовый-белый) с разной скоростью (на одной группе - медленно, на другой - очень медленно, фонари не должны притягивать взгляд динамикой вот этого перелива, но цвет таки должен меняться). В идеале было бы круто, если бы скорость можно было менять с радиопульта, но можно и обойтись.
Стандартными средствами (в смысле купленными на али фонарями и контроллером с управлением по радиоканалу) у меня это сделать так и не получилось - на самом деле проект этот тянется уже вот третий сезон. Фонари ip68 протекли :), контроллер глючит, сбиваясь без всякой системы с заданной программы на что-то свое... Фонари переделал, залил эпоксидкой, уж не протекут точно, правда, долговечность их пока неясна. Теперь вот взялся за контроллер :)
На данный момент сумел сделать управление ШИМ через millis() на один канал, правда, цикл выглядит по-дурацки, но я пока millis() же ковырял :) Странная формула для PWM - c Вашей же, ЕвгенийП, подсказки, постарался осмыслить статью про нелинейную регулировку яркости http://radiolaba.ru/polezno-znat/regulirovka-yarkosti-svetodioda.html. Работает нормально, но значения ШИМ меньше 1, как выяснилось, к включению светодиода не приводят, поэтому там диапазон ограничен 16-100.
Задача решается в лет с помощью цифрового автомата. Но надо знать основы программирования, которые даже не синтаксис языка.
В следующей жизни, наверное :) Но, с другой стороны, если у меня получится код допилить до нужного состояния, то на выходе ведь и получится цифровой автомат?
Не , не получится . Это как решение квадратного уровнения. Вроде просто. Но этому надо научиться. А вы "решение крадратного уровнения подбираете на ощуп с некоторой погрешностью"(разумеется это аналогия).
Да, примерно так все и происходит. Но пока что есть ощущение, что прикладную задачу решить рано или поздно получится. Посмотрим, может, оно пройдет в процессе :)
Позволю себе предложить Вам следующие простые правки :
Кстати, Вы уверены, что 16 и 100 выдавать не надо ?
и, вдогонку - вот это nextmove=currenttime + timeout; не переживёт переполнения миллис.
кури пример Мигаем светодиодом без delay()
При беглом взгляде прочиталась купи пример.
Подумал: уже миллис на продажу выставили.....
GarryC, спасибо большое, мне только это осознать надо будет на досуге :)
С первого взгляда вот это не понял:
while
(1)
Это просто бесконечный цикл?
Насчет 16 и 100 - я думал, что они будут как раз выдаваться последней итерацией в цикле?
GarryC, спасибо за подсказку и изящное решение. Я, надо сказать, добился того же результата, но по сравнению с Вашим циклом совершенно трансанально :) Единственное что, если i объявлять равным 16, то вот тут "
if
((i==99) || (i==17)) di=0-di;"
тоже надо"
if
((i==99) || (i==16)) di=0-di;",
иначе цикл на втором шаге сбивается и начинает творить полную хрень.Попробовал таки объявить переменные как паблики и убрать цикл - хуже, вроде бы, не стало :)
Получилось вот так:
Еще раз спасибо! Дальше буду RGB пилить.
Жесть
22
unsigned
long
currenttime1 = millis();
23
unsigned
long
currenttime2 = millis();
Может одним обойдетесь.
12
unsigned
long
pasttime1=0;
13
unsigned
long
pasttime2=0;
А это правильно.
qwone, ну да. Наверно, обойдусь :) Спасибо.
Может одним обойдетесь.
Ничо-ничо! Запас он карман не тянет! :)
Ну тогда еще в карман
и в код
qwone, спасибо. Это меня надолго заткнет :)
Пух, привыкай использовать enum правильно, пора.
enum class enumColor: byte
{Init = 0, Off, Red, Orange, Yellow, Green, Sky, Blue, Violet, White};
обращаться потом, кашеш, сложнее:
enumColor color = enumColor::Green;
зато имена внутри enum-ов наружу не светят и не пересекаются с глобальными именами.
А просто enum имеет смысл применять только когда нужны именованные константы.
Нашел откуда взялась такая странная вещественная арифметика для ШИМ. Там даже в статье сказано верно: заранее рассчитанные таблицы заполнения ШИМ. Округлите ШИМ до целого и сложите в программную память 1 раз для всех светодиодов. Оно ещё и места меньше займет и куда как ползеней будет.
В целом, спасибки. Долго думал, чего давать детишкам на следующем занятии после "вумного светофора", который считает кол-во пешеходов возле него и переключается по результату.
Arhat109-2, рассказ про цифровой автомат это самое важное ,что вы можете и должны объяснить детям.Но надо именно для и под Ардуину.
Форум слегка вырос, что несомненно радует. Когда я тут два года назад между путешествием на пляж заяснял что такое конченный автомат и как его можно обобщенно реализовать для управления МК - меня тут многие, что теперь "гуру" поднимали насмех от непонимания вопросу. Спасибо, повеселили. Это первое что им дается ещё с "вумным светофором" и без delay().
Было как-то так: http://arduino.ru/forum/programmirovanie/novichkam-avtomatnoe-programmir...
Arhat109-2, а еще лучше научить детишек не "засирать" loop() "грязью". А всю грязь выносить в отдельные функции. Так же делать с setup()
В конечном варианте там и нет ничего кроме набора исполнителей конечных автоматов, типа так:
Собственно это и есть весь луп. :) Все остальное прописывается в таблицах состояний и функций переходов.
Там тоже все строго по задаче:
"Светофор переключает "красный", "Желтый" и "Зеленый" сигналы по времени и по порядку. При этом, Зеленый перед выключением мигает 3 раза. Состояния светофора для авто: "красный-вкл" - 30сек, "желтый вкл" - 2сек, "зеленый вкл" - 30сек, макро "мигалка": ("зеленый выкл" - 0.5сек, "зеленый вкл" - 0.5сек) х 2 раза. При включенном одном цвете остальные - выключены. Состояние "Желтый" переводит автомат "датчик пешеходов" в состояние счет, если тот был в состоянии "ожидание включения". Состояние светофора "красный" - опускает шлакбаум. состояние светофора "зеленый" поднимает шлакбаум.
Датчик пешеходов имеет состояния: "Выключен" - 45сек, "Ожидание включения" - без ограничения времени, "Счет". Если в состоянии "счет", к светофору скопилось 5 и более пешеходов, то датчик переводит светофор в режим мигания зеленым (меняет состояние автомата "светофор") сразу после срабатывания. И сам переходит в состояние "выключен" и затем в состояние "ожидание включения".
Автомат шлакбаум или "закрыть" или "открыть" или "без изменений". Всего три состояния. Управляется извне, другими автоматами.
.. вот, берем это "ТЗ" и тупо пишем таблицы состояний, функции исполнения состояния и .. а всё. Остальное уже есть готовое. :)
Как показала практика - одного трехчасового занятия (при начальном знании языка) вполне достаточно для написания, освоения и даже на поиграть время остается навалом. Сейчас пробую при ПОЛНОМ незнании языка дать одновременно с языком. Правда только "С" версию .. сложнее, уже третье занятие пойдет на выходных. Но, тоже проблемы больше не в конечных автоматах, а в правилах самого языка, которые приходится давать постепенно в два-три захода, начиная с "тут пишем волшебное слово..", потом "да, и тут и вообще везде оно пишется так.." и только потом "это - синтаксическое правило ..". :)
В целом, при небольших функциях управления автоматами (менее 1мсек), такой код на Мега2560 вполне тянет до 100 управляемых устройств с вполне нормальным средним временем реакции в пределах 0.1 секунды. Проверено.
Точно также, наша "машинка по линии" .. есть вариант на полностью "автоматном" программировании и она в цикл 2мсек укладывается "только так", несмотря на то что замеряет по 3 раза все 5-7 датчиков линии обыкновенным analogRead() .. а то ту всё пид-да-пид нужен .. нафига? :)
Тупо до безобразия: берешь ТЗ, выписываешь автоматы (устройства), прописываешь их состояния и методы переходов, часть и вообще можно положить на прерывания .. и всё. "рабочий код - готов" ву-а-ля. :)
Было как-то так: http://arduino.ru/forum/programmirovanie/novichkam-avtomatnoe-programmir...
Просмотрел. Последнее сообщение вставило нипадецки! По этому поводу нам пора заводить что-то вроде лурковского "правила №34".
Ну .. там оно как раз к месту. Во всем примере была использована неверная обработка интервалов через millis(). Ничто конечно не мешает переварить пример верно, но .. :)
qwone, силюсь понять, а что вот в этом случае значит "проинициализировать выводы"? Объявить пины и задать PinMode? Или что-то еще?
Да, и кстати вот - меня тоже с момента прочтения статьи про нелинейную регулировку яркости вяло так интересовало, действительно ли analog.Write() передает на пин дробные значения? Но поскольку визуально все устраивает, то спросить так и не собрался - до сих пор :)
Tollmuch, а какие параметры у функции analog.Write?
DetSimen,
17
PWM = pow(i / 16.06, 1 / 0.33);
18
analogWrite(PWMPin, PWM);
паняна. В этом случае PWM округляется до целого. Не знаю, чесным округлением или простым отбрасыванием дробной части.
А в каких-то других случаях может дробное значение передаваться?
тип параметров функции прописан в ее обьявлении. Ничего другого туда не передашь.
еще можно почитать про overloaded functions C++ и написать самому.
А в каких-то других случаях может дробное значение передаваться?
Там стоит счтёчик который тикает. Параметр analogRead - количество тиков, которые надо отсчитать.
А теперь сами ответьте - есть смыл старать впихнуть ему дробное знаение? Он что, два с половиной тика отсчитает?
ЕвгенийП, нет, конечно. Но в принудительном округлении (на моей конкретной задаче :) ) тоже, наверно, смысла нет, раз "оно само"?
Само оно отбрасывает дробную часть. Например 1,999999 - получится 1. Если хочешь окрулять до ближайшего, то передавай типа f+0.5 - тогда будет само округлять до ближайшего к f целого
Ну вот. Взял я изящный, аккуратный код уважаемого qwone и опять сделал из него чего-то некрасивое. Правда, работает. На одну группу пока. Интервал коротенький в тестовых целях.
А если немного поглубже копнуть, то лучше копаться здесь.http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov
Вот классы, да. С ними, конечно, куда как опрятнее все выглядит. Спасибо большое, qwone, за участие и ценные советы, попробую себя сорганизовать на копание поглубже :)