Официальный сайт компании Arduino по адресу arduino.cc
Вопрос по нестандартному использованию millis()
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Помогите пожалуйста советом! Нужно реализовать следующую задачу. Запускать функции scan1(), scan2().... scanN() через определенное время используя функцию millis() или любой другой инструмент. Функций будет много (до 30), запускать нужно все через одинаковое время (не важно, в какой последовательности), и основное требование - переменная точки отсчета getData_Millis должна быть только одна! Конструкция приведенная ниже (упрощенная для наглядности) работает некорректно, идут пропуски запуска функций, то одной то другой
#define scan_Period 500 #define getData_Period 5000
uint32_t getData_Millis = 0;
uint32_t scan_Millis = 0;
void setup(){
Serial.begin(115200);
}
void loop(){
if (millis() - scan_Millis >= scan_Period){
scan_Millis = millis(); scan1(); scan2();
scanN(); }
}
void scan1(){
if (millis() - getData_Millis >= getData_Period){
Serial.println("Считали датчик1 ");
getData_Millis = millis();
}
}
void scan2(){
if (millis() - getData_Millis >= getData_Period){
Serial.println("Считали датчик2 ");
getData_Millis = millis();
}
}
void scanN(){
if (millis() - getData_Millis >= getData_Period){
Serial.println("Считали датчик3 ");
getData_Millis = millis();
}
}
Собери в массив все указатели на функции. В loop() в одном месте проверяй не закончился ли нужный интервал и вызывай очередную функцию из массива.
Спасибо большое !
А что нестандартного в таком использовании миллиса?
Сентябрь на дворе, школьники домашку решают...
ну и помог бы школьнику...
Дак тебе и так сказали, что надо делать. Если нужен готовый код, давай пицот р.
Дак тебе и так сказали, что надо делать. Если нужен готовый код, давай пицот р.
Деда! Кончай демпинговать! Час работы программера от 20 до 40 баксов! На мелких проектах выше. Ты с такими ценами милостыню просить будешь.
Ты с такими ценами милостыню просить будешь.
Дак я уже и так, не далее чем в мае, просил-побирался.
Дак тебе и так сказали, что надо делать. Если нужен готовый код, давай пицот р.
Деда! Кончай демпинговать! Час работы программера от 20 до 40 баксов! На мелких проектах выше. Ты с такими ценами милостыню просить будешь.
стоит то он конечно стоит, но кто ему пенсионеру их даст, Дет реалист однако )))
Проси больше - все равно урежут ))
Еще нашел удобный макрос для использования функции millis(). Использовать можно просто вставляя нужное время как аргумент.
Не надо искать "удобные макросы", почти все они написаны неграмотными помогальщиками типа гайвера. Вот и в этом строка 9 - бред
не всё так однозначно, если бы не Гайвер я бы и не узнал что в IDE есть плоттер )))
Еще нашел удобный макрос для использования функции millis(). Использовать можно просто вставляя нужное время как аргумент.
Попробуйте сами использовать Ваш макрос в коде два раза. Макросы ведь для этого нужны?
Еще нашел удобный макрос
А теперь попробуйте этот удобный макрос использовать
1. дважды в одном коде.
2. в цикле.
Я уж не говорю про совершенно верное замечание из #12
не всё так однозначно, если бы не Гайвер я бы и не узнал что в IDE есть плоттер )))
Как написал один из иностранцев под одним из его видео (сорри, вольный перевод по памяти )) - "хороший блогер, никакой программист" )))
Но он там честно предупреждает )))
Но кто эти инструкции читает?... )
Но он там честно предупреждает )))
Но кто эти инструкции читает?... )
1. А кому тогда нахрен нужен такой макрос? И тем более, что исправить так, чтобы было можно - как два пальца.
2. А про то, что он сработает только 1 раз и то отсчитает время не от вызова, а от включения питания там тоже написано?
Не защищайте безграмотный бред - ставите себя в неловкое положение.
Не защищайте безграмотный бред - ставите себя в неловкое положение.
Зато тема есть, в песочницу, Пишем макросы правильно, прямо на основе кода Гайвера и сделать.
PS помню стрельбы, первым стреляет Замполит, после его стрельбы общее построение и,
капитан...сейчас показал Вам, как не надо стрелять )))
2. А про то, что он сработает только 1 раз и то отсчитает время не от вызова, а от включения питания там тоже написано?
Минуточку. Не в защиту, а для самообразования - а почему только один раз? Разве макрос при компиляции не будет заменен кодом? Т.е. вот это
будет заменено вот этим?
И если да, то почему сработает один раз? И если нет - то тоже почему? ))
А напишите вот так в исходнике
static
uint32_t tmr;
static
uint32_t tmr;
и откомпилируйте.
А почему от включения... потому что на старте tmr = 0.
А напишите вот так в исходнике
static
uint32_t tmr;
static
uint32_t tmr;
и откомпилируйте.
Это понятно. Но речь таки об однократном использовании в блоке
А почему от включения... потому что на старте tmr = 0.
Это первое срабатывание. А почему оно будет только одно? Вот что меня заинтересовало
Это первое срабатывание. А почему оно будет только одно? Вот что меня заинтересовало
Виноват, не заметил строки
if
(flag) tmr = millis();\
Строка 9 - это вот.
Очень было бы интересно узнать, чего в ней, всё-таки, бредового. Раз уж замечание про бредовость вызвало такое пятикратное плюсование. ))
Строка 9 - это вот.
Очень было бы интересно узнать, чего в ней, всё-таки, бредового.
Вот тока не надо снова!!! Если ты серьёзно написал, то прочти пожалуйста тему (до достижения дзена)!
http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis
Написал серьёзно. И утверждаю что эта строчка к переполнению не имеет никакого отношения.
Не знаю кто такой Гайвер, но чувствую, он тут для всех вроде красной тряпки для быка. ))
Мне по барабану разные Гайверы, но в данном случае строчка правильная, и абсолютно по делу.
-------
От себя могу предложить такую версию макроса
Она, во многих случаях, будет правильно компилироваться при использвании несколько раз даже в пределах одного блока.
В ардуиновском случае будет точно, если не перенастраивать флаги компилятора используемые по умолчанию.
Не знаю кто такой Гайвер, но чувствую, он тут для всех вроде красной тряпки для быка. ))
Мне по барабану разные Гайверы, но в данном случае строчка правильная, и абсолютно по делу.
Просвещу )))
Вот Вам барабан ...это я о 1,84 млн подписчиков
Написал серьёзно. И утверждаю что эта строчка к переполнению не имеет никакого отношения.
Не знаю кто такой Гайвер, но чувствую, он тут для всех вроде красной тряпки для быка. ))
Мне по барабану разные Гайверы, но в данном случае строчка правильная, и абсолютно по делу.
-------
От себя могу предложить такую версию макроса
Она, во многих случаях, будет правильно компилироваться при использвании несколько раз даже в пределах одного блока.
В ардуиновском случае будет точно, если не перенастраивать флаги компилятора используемые по умолчанию.
Ты токашто заслужил высокое звание "Человек-дурак". Теперь у тебя здесь привилегии.
Ты токашто заслужил высокое звание "Человек-дурак". Теперь у тебя здесь привилегии.
Дет, спасибо. Заслужить такую высокую оценку от тебя - особенно почётно!
Он завтра проспится, может поймет, что сам дурь написал. Но ему можно у него давно здесь привилегии. Он ведь модератор.
Он ведь модератор.
Причём здесь ЭТО! Неужто не понятно что дважды EVERY_MS() в одном блоке не прокатит!
Вот поэтому он и каличный макрос. Костыль!
А for здесь ВООБЩЕ не к месту!
Очень было бы интересно узнать, чего в ней, всё-таки, бредового.
Вам правда интересно? Или так, потрепаться? Если интересно могу пояснить и привести пример, когда из-за этого всё валится. Если же Вы это просто для поддержания разговора, то ... в лом. Устал я сегодня.
Он ведь модератор.
Причём здесь ЭТО! Неужто не понятно что дважды EVERY_MS() в одном блоке не прокатит!
Вот поэтому он и каличный макрос. Костыль!
А for здесь ВООБЩЕ не к месту!
Я скомпилировал и запустил. - работает.
Запускал в симуляторе Atmel Studio 7. Поэтому времена задержек маленькие, чтобы не ждать. Переменные i и к для контроля значений при отладке. В Arduino IDE компилируется без ошибок. Но если заливать скетч, то надо поменять задержки на 1000 и 2000
Вам правда интересно? Или так, потрепаться? Если интересно могу пояснить и привести пример, когда из-за этого всё валится. Если же Вы это просто для поддержания разговора, то ... в лом. Устал я сегодня.
Так, в целом - да, сегодня свободный день, поэтому потрепаться. Но не посраться, а потрепаться именно по делу.
Просто всегда режут слух заявления типа "бред", если они никак не объясняются и ничем не подкрепляются.
Я понимаю, что никто не идеален, и каждый может ошибаться. Поэтому даже не стал спорить с тем что "бред", а просто сказал, что мне так не кажется. И попросил разъяснить, если я что-то не увидел.
Вот например wdracula мне сразу ответил, почему считает код бредом. Ему показалось, что там ведётся упорная борьба с переполнением millis( ), про которую, да, говорено уже тыщщу раз. Я же, в свою очередь, написал что строка, обсуждаемая, совсем не про то. Ну, будет у него время/желание - посмотрит внимательней, и наверно со мной согласится. А может и переубедит меня - кто знает. ))
ЕвгенийП, ситуацию "когда из-за этого всё валится" - да наверно можно придумать. Я и не говорил что в том первоначальном варианте всё идеально. Но всё же, согласитесь, между "бред" и "не идеально" есть разница, вот я о чём.
Примеры посмотреть интересно - но это, разумеется, по Вашему желанию, если устали не очень сильно.
Понимаете, ошибка - ошибке рознь. В строке о которой шла речь (девятой), происходит увеличение неинициализированной переменной (это, кстати, очень характерно для гивера, он часто так делает). Такие ошибки я считаю бредом, хотя, это, конечно, вопрос терминологии.
В результате, полюбуйтесь, что получается в весьма штатной, совсем не "надуманной" ситуации
Куда пропали первые пять интервалов? Вот туда и пропали - ждали пока миллис до 500 дорастёт.
В Arduino IDE компилируется без ошибок. Но если заливать скетч, то надо поменять задержки на 1000 и 2000
Для проверки задержки лучше взять некратные - результат будет выглядеть интереснее.
Инициализированной нулём, если не ошибаюсь. Хотя, да, меня такое использование переменных тоже коробит, и я всегда в тексте инициализирую явно все переменные, даже глобальные.
Кроме тех, для которых начальное значение действительно не важно.
В результате, полюбуйтесь, что получается в весьма штатной, совсем не "надуманной" ситуации
Спасибо, теперь хотя бы понятно, о чём речь.
Но профессионалы говорят - "это не баг, это фича!". ))
Программа отработала именно так, как её написали. Где же тут что порушилось?
И если уж считать что ошибка есть, то она не в той "бредовой" строке, а здесь.
Изменяем - и всё работает уже по-другому.
Но точно ли мы хотели по-другому?
А если мы, например, пишем какие-нибудь большие настенные часы, и должны увеличивать счётчик секунд именно в соответствии с количеством прошедших секунд?
Должны ли мы пропустить несколько интервалов, из-за того что какое-нибудь, допустим, чтение даллас-температуры провисело неизвестно сколько времени, не возвращая управление в основной loop( )? Или всё же лучше эти интервалы приплюсовать, хоть и с опозданием?
Нет, это фича, однозначно. И очень полезная, кстати - она позволяет отсчитывать интервалы без накопления погрешности. То есть, видите сами - погрешность для каждого отдельного интервала есть - а накопления нет. И в среднем, за время выполнения программы (1 секунда) мы имеем ожидаемые десять 100-миллисекундных тиков.
Должны ли мы пропустить несколько интервалов, из-за того что какое-нибудь, допустим, чтение даллас-температуры провисело неизвестно сколько времени, не возвращая управление в основной loop( )? Или всё же лучше эти интервалы приплюсовать, хоть и с опозданием?
Нет, это фича, однозначно. И очень полезная, кстати - она позволяет отсчитывать интервалы без накопления погрешности. То есть, видите сами - погрешность для каждого отдельного интервала есть - а накопления нет. И в среднем, за время выполнения программы (1 секунда) мы имеем ожидаемые десять 100-миллисекундных тиков.
про "фичу" это вы Гайверу расскажите... он любит прикрывать свои косяки подобными росказнями
У него есть замечательная библиотека GyverTimer. В первой версии он отсчитывал интервалы вот этим способом:
но так как писать код у него не очень получается, нередко выходило, что выполнения кода в ЛУП длилось больше интервала и таймер начинал отставать. Это особенно забавно, когда Алекс использует эту библиотеку для отсчета времени в часах (проект "Часы-метеостанция") - народ массово начал жаловаться. что часы почему-то отстают на несколько минут в сутки.
Тогда он написал вторую версию - ту за которую вы тут копья ломаете, где последняя строчка такая
часы теперь не отстают, но так как проблемы с кодом в Луп остались теми же - теперь народ жалуется, что таймер срабатывает неравномерно :)
Что характерно - после исправления GyverTimer-а с первой версии на вторую Алексу не пришло в голову заменить библиотеку в старых проектах - поэтому "Часы-метеостанция" как отставали. так и отстают. Почему - да потому что Гайвер не имеет понятия о принципах повторного использования кода и в каждый свой проект вкладывает копии всех используемых библиотек, вместо того чтоб включать только ссылки. Таким образом, отслеживать акутуальность кода библиотекв каждом проекте становится невероятно сложно - вот он и не отслеживает...
Программа отработала именно так, как её написали.
Все программы так работают. Вы знаете хоть одно исключение?
Где же тут что порушилось?
Заказанные интервалы не отработали. Вы считаете. что это не порушилось? Ну, значит, не порушилось.
Нет, это фича, однозначно.
Этот расскажите кому-нибудь другому. Я точно знаю чем отличается фича от бага - первая документирована, а второй - нет.
Пассажа про накопление погрешности я не понял вовсе. Каким там боком накопление ... это выходит за рамки моей понималки.
Ладно, Datak, со званием я несколько погорячился, прошу прощения.
Но, люди, призываю вас, забудьте про дефайны и макросы вместе с Си, как страшный сон, в 80% случаев они работают не так, как вы планировали. А у новичков - в 146% случаев.
Ладно, Datak, со званием я несколько погорячился, прошу прощения.
Но, люди, призываю вас, забудьте про дефайны и макросы вместе с Си, как страшный сон, в 80% случаев они работают не так, как вы планировали. А у новичков - в 146% случаев.
до макросов я еще не дорос, а вот что не так с дефайнами, а то использую
до макросов я еще не дорос, а вот что не так с дефайнами, а то использую
Используй лучше constexpr. На худой конец простой const. На размер кода это никак не влияет, а с типами они тебе лохануться не дадуть.
Не зря ж в твоём теперь FT879D.h нет ни одного #define.
до макросов я еще не дорос, а вот что не так с дефайнами, а то использую
Используй лучше constexpr. На худой конец простой const. На размер кода это никак не влияет, а с типами они тебе лохануться не дадуть.
Не зря ж в твоём теперь FT879D.h нет ни одного #define.
мои дефайны за рамки байта не распространяются )))
кстати, хотел энкодер за прерывание PCINT зацепить, ан нет, компилятор орёт - повторное определение в библиотеке CustomSoftwareSerial, впрямую не увидел, но она подтягивает Interrupt.h видимо там и как тут не быть )))
мои дефайны за рамки байта не распространяются )))
Вот тут-то и засада!
Я скомпилировал и запустил. - работает.
Моя реплика относилась к другому (Гайверовскому) макросу EVERY_MS. Касательно
#define EVERY_MS(X) for (static uint32_t T = millis(); millis() - T >= (X); T += (X))
здесь, с виду, всё нормально.
За исключением того, что первое выполнение произойдёт сразу, а не через Х.
мои дефайны за рамки байта не распространяются )))
Вот тут-то и засада!
" нам учитель задаёт с иксами задачу..."
Вот тут-то и засада!
а вот так считается более корректным?
#define EVERY_MS(X) for (static uint32_t T = millis(); millis() - T >= (X); T += (X))
здесь, с виду, всё нормально.
За исключением того, что первое выполнение произойдёт сразу, а не через Х.
Почему?
а вот так считается более корректным?
Я бы ещё внешние скобки добавил - здоровая привычка. Но идейно это всё равно менее правильно, чем
В данном конкретном случае как бы разницы и нет, но если говорить об использовании таких конструкций вообще, то есть много ситуации, когда сразу описать нужный тип выгоднее, чем писать преобразование.
Хотя, сам я часто использую дефайны - привычки, формировавшиеся десятилетиями, не так легко вытравить. А вот начинающим советовал бы не привыкать.