Всем наше здравствуйте. Вопрос для самопроверки. Делаю мозги для мульти варки и необходимо несколько таймеров для отсчета и индикации времени. В разных режимах с момента закипания, с момента включения и т.д. Модуля реального времени у меня нет поэтому пользуюсь средствами millisардуино. Как сделать индикацию времени с момента наступления события я вроде представляю вычесть из текущей отметки millisсобственно millis сколько он там натикал с момента включения. Однако уж очень это энергоёмко. Есть ли более изящный способ? Чтобы на индикатор выводить время не с включения ардуино а именно с нужного момента? Код (C++): uint16_t T1; //переменная для отсчета времени с момента включения ардуино static uint16_t T2; // переменная для отсчета времени с момента события uint16_t T3; //разница времени #define KNOPKA 1 //для примера приведена кнопка void setup() { pinMode (KNOPKA, INPUT); } void loop() { T1 =millis(); // засекаем время с начала работы ардуино(можно и без этой переменной) //Здесь в коде что то неопределенно долго делается //как только происходит какое либо событие, нажатие кнопки старт или срабатывание //температурного датчка. начинается отсчет таймера if(digitalRead(KNOPKA) == HIGH || Temp >98) { T2 = millis(); //засекаем текущее время T3 = T1 - T2 ; // или проще millis() - T2 ; //далее переменную T3 преобразуем в минуты и часы и выводим на дисплей } }
У millis тип Код (C++): unsigned long millis() в uint16_t только одна минута влезет. Зачем вам Код (C++): T1 =millis(); // засекаем время с начала работы ардуино(можно и б ? сохраняйте время события. и отнимайте его от millis() чтобы получить прошедшее от события время.
Условие Код (C++): if(digitalRead(KNOPKA) == HIGH || Temp >98) проверяет состояние, а не событие. Например, пока температура больше 98 время как бы события постоянно обновляется, не течет. Это: Код (C++): //Здесь в коде что то неопределенно долго делается в принципе так можно делать. Но обычно функция loop завершается сразу после проверки состояний и короткой реакции на них. Если что-то делается "неопределенно долго ", другие функции в это время недоступны.
в смысле вы имели в виду такую конструкцию? Тут только минуты и часы, т.к секунды не нужны. Код (C++): static unsigned long Timer = millis(); if (millis() - Timer > 59999) { Minuty++ ; Timer = millis(); if(Minuty >59) { Minuty =0; Chasy++; } } Интересно конечно, но сурово. всем большое спасибо, все уяснил, тему можно зарыть.
Так нельзя делать: Timer = millis(); время будет дрейфовать. Нам нужен тик 1 раз в минуту, поэтому задаём интервал строго 60 сек. : Timer += 60000; И расчёт секунд тоже не тривиальная задача. Она должна быть решена тут же, в расчёте минут.
как непросто однако оказалось. Нееее я лучше по простому Код (C++): millis() - T2; а потом переведу в минуты и секунды. Но для общего развития пытаюсь все таки понять как можно решить этот вопрос. так допустимо? или я неправильно понял? Код (C++): static bool Flag =1; //или вынести в инициализацию static unsigned long Timer ; if (Flag ==1) { Timer = millis(); // для того чтобы получить время для сравнения Flag =0; } if (millis() == Timer += 60000) { Minuty++ ; Flag =1; if(Minuty >59) { Minuty =0; Chasy++; } } кстати нашел на другом Ардуиновском форуме вообще интересное решение каждые 0.5 секунд меняем состояние ноги в данном случае 13, потом считываем и при каждом HIGH на ноге прибавляем 1 сек к таймеру. Код (C++): if (millis() - previousMillis >500) { previousMillis = millis(); //запускаем таймер digitalWrite(13, !digitalRead(13));//меняем значение порта каждые 0.5секунд if(digitalRead(13)==HIGH)//если 13 нога лог1 то... { sek++;//переменная секунда + 1 } но как я писал обойдусь по простому вычту время когда была нажата кнопка или датчик температуры превысил порог, из millis() а потом просто и непринужденно переведу в минуты и часы. большое спасибо, что находите время на консультацию даже по таким мелочам
много таймеров https://github.com/DetSimen/Arduino- секундный таймер делается вапще на раздва. + еще 7 асинхронных с разной выдержкой.
Вот например простейшие часы. Код (C++): template <typename T> Print &operator << (Print &s, T n) { s.print(n); return s; } extern TTimerList TimerList; THandle hSecondTick; byte hours = minutes = seconds = 0; // часы, минуты, секунды void setup() { hSecondTick = TimerList.AddSeconds(tmrSecondTick, 1); // раз в секунду будет вызываться tmrSecondTick } void tmrSecondTick(void) { seconds++; if (seconds<60) return; seconds=0; minutes++; if (minutes>59) { minutes=0; hours++; } if (hours>23) hours=0; Serial<<hour<<':'<<minutes<<'\n'; } void loop() { }
Спасибо вам большое. и за скетч и за ссылку. Я только начал подбираться к битовым операциям в С++, поэтому пока неуразумею что к чему, вопросов будет черезчур много). так что сам потихоньку буду вникать а то некрасиво получится и скетч дали еще и разжуют ) так не научусь сам ничему .а пока что такие выражания типа Код (C++): cli(); TCCR5A = 0; TCCR5B = 0; TCNT5 = 0; вводят в панику). Еще раз большое спасибо. постараюсь разобрать сам скетч по строкам чтоб осознать что к чему и главное зачем.
бодрый вечер всем. написал свой первый собственный таймер Код (C++): static unsigned long Counter_05_sec = millis(); //static if (millis() - Counter_05_sec > 499) { Counter_05_sec = millis(); switch_30 = !switch_30 ; // Serial.println("switch_30"); //Serial.println(switch_30); if (switch_30 ==1) { Sekundy_t++; if (Sekundy_t>59) { Minuty++ ; Sekundy_t=0; } if (Minuty>59) { Chasy++; Minuty=0; } } } проще некуда. вставлять можно в любое место кода. не надо захватывать и вычитать millis(). можно наплодить их кучу в разных местах. НО, он собака отстает на секунду каждую минуту. это ошипка кода? или особенность Дуни? ставлю 498 и все идет секунда в секунду по секундомеру с телефона. а вообще меня millis() ,бесить начал уже. в конструкции switch case . я думал что захват millis(), произойдет в момент перехода в нужный case. Фига с два, у меня 5 таймеров в 5 разделах case. и они все захватывают millis() одновременно в момент как я вхожу в этот цикл. Написано немного сумбурно но код сильно большой чтоб его выкладывать. к тому же сам стараюсь понять в чем цимес. Гуру С++ напишете методичку как работает millis(), с разными примерами. как работает static long при захвате. Все будут премного благодарны за этот труд! Кстати первый раз за карьеру ардуньщика столкнулся с тем что мне уже не хватает памяти Дуни про мини)
У вас дрейф точки отсчёта происходит. millis () - Counter_05_sec это не 500 мс. Прибавляйте к Counter_05_sec строго 500 а не неизвестную величину millis ()
Cпасибо понял!!! даже если и неправильно понял, выражение Код (C++): if (millis() == Counter_05_sec + 500) решило все вопросы. прогнал уже 20 минут отклонения нет ни на секунду!
прошу "звонок другу"). подсказки или ссылки на ресурс. Конечно самому хочется додуматся, оно и закрепится надолго. но не придумывается ничего лучше. Код (C++): static unsigned long Counter_05_sec = millis(); //static if (millis() - Counter_05_sec == 1000) //if (millis() - Counter_05_sec > 498) { Counter_05_sec = millis(); Sekundy_t++; Serial.println(Sekundy_t); if (Sekundy_t>59) { Minuty++ ; Sekundy_t=0; Serial.println(Minuty); } if (Minuty>59) { Chasy++; Minuty=0; } } работает нормально, точность устраивает. но хочется конечно знать и правильный способ. при переходе с полусекунд на секунды возможная погрешнасть по моему вообще минимальна
Теперь вашей функции надо передавать управление не реже 1 раза за 1мс. Иначе она пропустит отсчёт. Это новая ошибка. В прежней редакции можно было дёргать её 1 раз в 0.5 сек. Но и это условие можно смягчить. И даже если время выделять, она может дрейфовать на 1мс/с. Это старая ошибка, которую вы не стали исправлять. Только смягчили за счёт условия "не реже 1 раза за 1мс". Три статических переменных: Sekundy_t Minuty Chasy Как то жирно по моему. Не удивительно, что памяти не хватает. Их можно из millis() запросто извлечь. Вряд ли они очень часто нужны.
вечер добрый. спасибо)ю как перевести millis() в минуты и часы написал , но это в принципе не ново. Код (C++): byte Chasy, Minuty, Sekundy_t, ms; unsigned long Current; unsigned long n; void setup() { Serial.begin(9600);// put your setup code here, to run once: } void loop() { static unsigned long start = millis(); //получаем текущее время Current = millis()- start; // полуяаем разницу между текущим временем и началом старта millis() Chasy=int(Current/3600000); //вычисляем часы и минуты n=Current%3600000; Minuty=byte(n/60000); n=n%60000; Sekundy_t=byte(n/1000); ms=n%1000; } но не нравится мне такие таймеры. я не понял почему но Код (C++): static unsigned long start = millis(); Current = millis()- start; в этом моменте у меня часто происходят косяки. причину пока не могу уловить. или не заводится функция, или наоборот хрен обнулишь начальную переменную start. (но это мои тараканы и воюю с ними пока безуспешно) а таймер типа Код (C++): static unsigned long Counter_05_sec = millis(); if (millis() - Counter_05_sec >= 1000) Заводится всегда и в любом месте программы. И главное начинает отсчет с нужного момента, без всяких усилий. Сейчас думаю как же идеологически правильно это должно быть
Функция ldiv выполняет деление с остатком. http://www.atmel.com/webdoc/avrlibc...dlib_1ga5b688b463f9faaa82f31ac7587e06849.html результат http://www.atmel.com/webdoc/avrlibcreferencemanual/structldiv__t.html