таймер для ардуины
- Войдите на сайт для отправки комментариев
Пнд, 18/03/2013 - 10:22
Требуется каждые 15 секунд включать реле и на 240 секунд отключать. Что сделать с millis() чтоб такое реализовать? К примеру, вот такой код:
int relay = 10; void setup() { Serial.begin(9600); pinMode(relay, OUTPUT); } void loop() { int time = 0; if((millis() - time) == 12000) { digitalWrite(relay, HIGH); time = millis(); } }
Он конечно не работает)) Что исправить и чем дополнить?
1 секунду вкл. 3 секунды выкл.
отлично! всё путём.
Вот спасибки. Просто и красиво . Это почти ТО что я хотел .
Я добавил в ваш код кнопку и получил искомое.
Так код работает . Но почему он не работает вот так:
else не может быть с условием, либо if, либо else if
СПАСИБО!!!Точно!Теперь я знаю почему не работали и некоторые другие скетчи.Пошел исправлять их.
сходная проблема... есть mega2560, millis() и вывод на жк индикатор.. когда ардуина насчитывает минуту, проходит примерно 45 секунд реального времени.... кварц врет или по жизни такая точность?
примерный код...
сорри нашел косяк... строка 44, лишний вызов, остался от переноса кода....
Думаю что и не кварце дело, и не в яйцах, и не в бабине ) Так попробуйте:
спасиб ) кое что у себя поправил...
Ребята помогите пожалуйста. Вопрос в следующем:
Есть Ожидание приема с порта
while(Serial.available()== 0);
далее работа с даными приема, данные поступают около 2 раз в секунду.
Как сделать таймер, что бы при отсутствии входящих данных, через 20 секунд происходило {какое то действие}
а при поступлении таймер сбрасывался.
Извините за неподобающее оформление, ну и надеюсь не будете сильно критиковать.
Перекопала интернет, но так и не поняла.
П.с. Я не программистка, просто пришлось...
спасибо Максим Вам огромное, а обнуление таймера тут ненужно?
Не знаю что вы имеете ввиду под словами "обнуление таймера тут ненужно?" ... Если вы про отсчет 20 секунд, то нет не нужно, а что бы знать точно это вам нужно или нет покажите весь код и напишите что хотите.
На порт приходит символ, за ним 2 значения от 0 до 9. Оба значения переводятся в положение сервоприводов. Если задержка более 20 секунд, нужно вернуть их в первоначальное положение. Как то так.
Задержка, как правило, отсчитывается от определенного момента. Что таким моментом является у вас? Рискну предположить, что момент последнего поступления символа по UART.
В общем, чуть конкретизируйте этот пункт.
Ну так опишите что делает этот код или точнее что вы от него хотите. Потому как символ никак не учавствует или запутывает работу кода, а Serial.flush() уже давно (с версии IDE1.0) не очищает буффер.
именно считала, что таймер должен срабатывать если с момента последнего прихода данных прошло более 20 секунд, точнее действия по таймеру.
Символ этот D, угадал? Надо ж было так зашифровать... Често говоря из кода не ясно что вы хотите от него, опишите что хотите... какой формат команды, которую вы отправляете? D12 ?
Вся проблема в том, что я подстраиваюсь под передатчик, к которому доступа не имею. Передатчик выдает следующее символ D, вы все верно поняли, далее два значения от 0 до 9. Тоесть типа D19. Приемник должен принять не перепутав очередности, в принципе это работает хорошо. Далее первое значение от 0 до 9 перевести в угол поворота сервопривода в диапазоне от 20 до 160 градусов
аналогично со вторым.
Это все работает. Но вслучае отсутствия сигнала, с момента прихода последнего, во времени более 20 секунд - сервопривода должны занять положение в 90 градусов
Не, все эти бесконечные while ждущие чего-то - это зло. Так же как и delay().
У вас же потом будет постоянная проблема с одновременностями и проч.
Если "все остальная логика работает" (не вникал в нее), то теоретически вместе это будет так выглядить (просто скоировал ее, убраз вот только "стоять ждать")
Тогда уж наверное так должно быть:
иначе будем читать буффер, когда в нем ничего нет и не читать когда что то есть.
И странно как у вас все работает... если например приходит D23, то D попадает в переменную data, 2 просто обратно отправляется, 3 опять в data. у следующей команды D отправляется обратно и т.д.
Я бы сделал так
Интересный приемчик использовать переменную lastReceived и как переменную для хранения миллисекунд и как флаг.
Тогда уж наверное так должно быть:
Да конечно. if(Serial.available()) . Просто пока вставлял, пару раз форматирование вставало раком, "собирал " знаново и на третьей попытке - забыл ==0 убрать.
Я бы сделал так
Конечно, на вкус и цвет - фломастеры разные, но...
1. В моем варианте "логика работы" и "логика таймера" - полностью разделены. Легче поддерживать. И переписывать логику чтения/парсинга не отвлекаясь про "не забыть про таймер".
2. available() >= 3 - , а если первое чтение произойдет во не с самого начала пакета? Синхронизация сбилась навсегда?
Интересный приемчик использовать переменную lastReceived и как переменную для хранения миллисекунд и как флаг.
Да. Я обычно его и использую. Для того что-бы событие отработало один раз. Вначале я так и сделал, но когда стало ясно что у по событию нам нужно "ставить сервы в 90-то" - я закоментил строку "останавливаем таймер". Так как ничего страшного в многократном выставлянии серв в 90-то - нет. Следовательно можно обойтись без флага (без выключения таймера после сработки).
IMHO на такие вещи хорошо ложатся на паттерн "машина состояний"
Да, на вкус и цвет. С синхронизацией при глюке будет проблема, но это решается очисткой буфера.
Коль завел речь про "машину состояний", то лично я полюбляю (да, фломастеры :), делать ее не через switch, а через указатели и таблицу обработчиков. Тогда каждый режим - в отдельной функции и ковыряешься с ним потихоньку, а не в одной общей простыне. И добавить новый режим легче, без ветвистых if-фов.
а вот за машину состояний спасибо, раньше не сталкивался с этой системой, погуглил, начал переписывать свой код... в размере прилично уменьшился и стал более понятен, а то больно развесистые свитчи были...
Есть вопросы про атоматное програмирование:
пример, обратный таймер, кнопка старт,она же стоп, кнопка, плюс, кнопка минус.
у таймера по идее 2 состояния, ждет старта или останова. плюсом и минусом можно уменьшать или увеличивать счетчик как на ходу так и в остановленном состоянии, также долгим удержанием этих клавиш можно менять счетчик с увеличенным инкрементом.
вопрос в следующем куда запихивать эту обработку? в функции останова, старта или таймера,а может лучше отдельный автомат на изменение счетчика от кнопок?
А зачем его вообще пихать в состояния? состояния "ждет старта, таймер идет, таймер закончился" - это понятно. А "увеличивать/уменьшать" счетчик - нет таких состояний. Ну можно, конечно притянуть за уши, но зачем? Это же просто переменные которые нужно менять при нажатии кнопок, судя по вашему описанию в любых состояниях. Так что IMHO их просто вынесте в loop() скажем и обрабатывать эти кнопки паралельно с машиной состояний.
В качестве примера - смотрите как timeout() я обрабатываю. Его я не пихал в состояния (хотя и может он на них воздействовать).
в общем так и было, но в основном цикле, получается опять сильно развесистый свитч на обработку кнопок... там на этот плюс и минус хочу навесить еще изменение 6-7 других параметров,
Ну дык а вам никто и не обещал, что "машина состояний" приминима всегда и везде. "Серебрянной пули" для того что-бы сделать любой код красивым - не существует. switch/if - существовали до нее, так и после (кстати "машина состояний" - это скорее "идея", которая может реализованно быть по разному. через таблицу указателей, через switch, через if...)
Ну а вашими "+"/"-" - тут абстрактно не скажешь. Уже от задачи зависит. Может просто параметры в массив загнать, может сделать еще одну табличку обработчиков (только уже не "состояний", а кнопок)...
но все равно спасибо, кое что применил...
Ребят спасибо огромное всем кто откликнулся, заработало все. Дело в другом немного крылось оказалось, что передатчик посылает в эфир "D" потом отправляет от 0 - 9 состояние первого сервопривода, далее отправляет состояние второго. В целом все заработало. Удачи вам в проектах!
Попробуйте вот эту библиотеку http://blog.ilyaplot.ru/arduino_setinterval/. Мне кажется, отлично упростит задачу.