Предусмотреть однократную задержку в выполнении функции
- Войдите на сайт для отправки комментариев
Сб, 26/05/2018 - 01:55
Здравствуйте, подскажите, пожалуйста, реально ли организовать следующее:
нужна функция, которая будет подавать импульс длительностью 300 мс, при этом очень хотелось бы не тормозить выполнение остальной программы, тоесть delay (300) не подходит. Примеры с millis() тут тоже не актуальны, так как они выполняются обычно в loop, где цикл за циклом после выполнения остальных задач проверяется не подошло ли нужное время, а у меня именно отдельная функция.. Как можно реализовать задержку в ней, не прерывая остальных задач?
Спасибо!
void Swich::swich () { digitalWrite (lamp_pin, HIGH); delay (300); digitalWrite (lamp_pin, LOW); }
Вас жестоко обманули. Миллис работает и в отдельной функции: В начале функции ставим иф с проверкой интервала и в каждом проходе заглядываем туда. Когда интервал достигнут, выполнили функцию и задали новый. В лупе и остальных функциях не должно быть делеев и тяжелых циклов.
Да, спасибо, организую так, буду заглядывать туда в каждом проходе, просто до этого, попадал в свою функцию c millis() один раз по условию, при следующих следующих проходах, после выполнения моей функции условие уже не соблюдалось и в эту функцию уже не попадал. Думал вдруг можно как то паролельно работать с этим..
Думал вдруг можно как то паролельно работать с этим..
Можно и параллельно, только всё равно придётся куда-то заглядывать. Как вариант централизованного "заглядывания":
1. Допустим, все функции имеют сигнатуру void Function();
2. Заводим список указателей на функции:
3. Делегируем принятие решений обработчику:
4. Делегируем вызов этих функций:
5. Когда нужно - вызываем делегат для принятия решений и делегат для вызова функций:
Таким образом - мы отделили механизм принятия решений от собственно вызова функций, что позволяет при желании настроить разное поведение их вызова. В механике принятия решений прослеживаются начатки по вызову шлюза к различным состояниям системы. В механике вызова функций можно добавить анализ состояния системы после каждого вызова функции, добавив ещё один промежуточный интерфейс (как раз тот самый шлюз к состояниям системы) - таким образом, обеспечивается довольно гибкое поведение системы. При этом сами функции делают только свою работу.
Механизм довольно легко расширяется, добавляются связанные с функциями параметры, цепочки вызовов и т.п., при желании.
Ни на что не претендую - просто как вариант давно известной архитектуры.
Ну метры они такие даже скетчи у них мудренные оказываются . Так переписал- компилируется. но там еще обкатывать и обкатывать.
ПС: Но мой Менеджер задачи работает. Если кому интересен то он здесь.#165
Ну метры они такие даже скетчи у них мудренные оказываются .
Привычка к STL ;) Юзаю простенькую реализацию Vector в проектах, потому и написал пример, основываясь на, так сказать. Потом - это псевдокод, назначение которого - просто продемонстрировать алгоритмику, ничего более. А там - хоть вектор, хоть Queue, хоть Deque, хоть List, хоть чёрт лысый - любой контейнер с нужным поведением, не вопрос.
Ага. Потому грамотно задачу описывать не просто в течении 300мсек, а задать погрешность. И если погрешность допустим 0,2мкс - то аппаратно, 20мкс - то из прерывания, а если 20мсек - то из цикла как выше пишут. Правда с учетом что они там явно переигрывают, и просто код
ничем не хуже для двух функций. Для большего массив функций завести и циклом вызывать.
Как луп крутится конечно важно, но для вывода через прерывание таймера тоже есть важные подробности: как часто и долго обрабатываются другие прерывания и как часто и надолго ли прерывания запрещаются. Вобщем универсального подхода нет.
Спасибо! За советы, суть уловил. Выглядит как то что нужно, есть конечно ряд нового для меня, попытаюсь разобратся.
а вот как бы было у меня. Без всяких флагов.
Ну и самый "железный" способ, -попросить таймер поднять и опустить через заданное время свою аппаратную ногу (9пин):
Пример эксклюзивный, в интернетах такого применения нет :)
а вот как бы было у меня. Без всяких флагов.
Строго говоря, у тоби есть флаг - хэндл таймера ;)
Ну да. Согласен.
ТС, вариант от dimax наиболее изящный. Изучай.
Спасибо, большое, накидали много вариантов, "железный" вариант от dimax выглядит круто, но очень сложно, с регистрами и прочим мне пока не разобраться, к сожалению, тут даже не знаю как это читать...Впринципе понял вариант DetSimen. Только подскажите, про INVALID_HANDLE? THandle может принимать такое значение? Ведь это проверка, на то что таймер запущен. Впринципе можно обойтись и без нее, или реализовать иначе. Просто компиллятор ругается на это. 'INVALID_HANDLE' was not declared in this scope. А так, это отличный вариант, посылаем импульс и тут же взводим таймер на его отключение, и впринципе больше не заботимся об этом, работаем дальше. Сейчас пробую разобратся с кодом DIYMan и qwone там конечно намного сложнее с хранением функций в векторе много непонятного, но разобратся будет полезно, спасибо!
надо аптамушта скачать 2 файла атсюда
https://github.com/DetSimen/Arduino-
и бросить в директорию с проектиком
DetSimen это само собой, потключенную библиотеку я увидел, ему я так понял не нравится само значение INVALID_HANDLE , я тоже думал что THandle это должно быть целое число.. Без проверки на INVALID_HANDLE все отлично работает..
тогда добавь или в h файл или в свой
const THandle INVALID_HANDLE = -1;
в биб-ке я утром уже определение поправил, можешь еще раз скачать файлеги и заменить старые
Да спасибо! Посмотрел библиотеку, она реализует тот же "железный" способ как и у dimax? Менеджер задач осознать пока не получилось..
Да, те же таймеры в обертке.
Кстати на новую версию компиллятор ругается const THandle INVALID_HANDLE = -1, вообще ведь можно обойтись без этого? Ведь эта проверка, на выполнение задачи не обязательна?
А какими словами ругается?
Проверка нужна. Можно тогда везде вместо INVALID_HANDLE вручную подставить -1
Все, на сегодня. Зеленый змий зовет с ним бароца.
Желаю побед! Ошибка под катом
Потом растолкукйте, пожалуйста, зачем проверка? В вашем примере, впринципе невозможен вариант повторного включения уже включенного таймера, как и отключение отключенного, он линейный и все последовательно включается и отключается, я правильно понимаю?
Ошибку поправил, выложил.
Проверка затем, что таймеры работают асинхронно с loop(). Предположим, вызвал ты гдета PulseOn() и пока проходят 300 миллисекунд до PulseOff() никто не мешает вызвать PulseOn() еще раз, например по ошибке. И что в этом случае произойдет? Хэндл то у таймера один. Таймер конечно добавится еще один, но предыдущий хэндл перепишется новым, а старый перейдет в раздел потерянных. Причем, ранее добавленный таймер и дальше будет работать, мешая новому, только доступа до него уже не будет, чтобы остановить и удалить, так как старый хэндл затёрт. Поэтому добавление таймера происходит только если предыдущий удален.
Паняна?