Попытка одолеть delay()
- Войдите на сайт для отправки комментариев
Всем привет! Столкнулся с типичной, как я понял проблемой для новичка - как обойтись без delay()?
Много есть в инете на эту тему, но в моём случае всё усложняет динамическая индикация, которой постоянно нужен ресурс МК. Вопрос показался интересным, ведь решив его, можно , по аналогии решать другие подобные. Итак, на преобразование температуры датчиком DS18B20 уходит 750мс, пусть 800мс с запасом.
Как сделать, чтобы индикация при этом не прекращалась?
Проблему-то я решил, всё работает, но сильно пришлось усложнить код.
От этого сомнения, и вопросы
//======== попытка избавится от delay ============= //==== с сохранением динамической индикации ))) == void loop() { for (int i = 0; i < 8; i++) { digitalWrite(RAZR[i], HIGH); // выбор разряда PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY по адресу [a] в текущий разряд [i] if (i == 2) PORTD = PORTD | 0b10000000; // зажигаем точку delayMicroseconds(500); // задержка для индикатора digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации } switch (key) { // key это ключ для выполнения выбранной части программы (одной из трёх) case 0: // ключ в положении 0 (индикацию теряем только на время работы шины и расчёты) if ((millis() - last_millis) >= 3200) { // частота измерений температуры 3200мс(задержка) + 800мс(конвертация) = 4сек last_millis = millis(); // + 10мс обмен по шине и преобразование ( очень примерно ) w = 0; // при w = 0 передаём первые два байта команд датчику start(); // peredacha(); key = 1; // изменяем значение ключа } break; case 1: // ключ в положении 1 if ((millis() - last2_millis) >= 800) { // ждём датчик last2_millis = millis(); key = 2; // изменяем значение ключа } break; case 2: // ключ в положении 2 w = 2; // при w = 2 (смещение цикла) передаём вторые два байта команд start(); peredacha(); chtenie(); // читаем значение темп-ры crc_8(); // проверяем контр.сумму schet(); // преобразуем в значения десятичных разрядов key = 0; // первоначальное значение ключа break; } }
: это нормальное решение, или можно сделать лучше?
Или сойдёт для начала?
Прошу конструктивной критики и направления в нужную сторону...
Это первоначальный вариант, как видим, значительно проще
void loop() { for (int i = 0; i < 8; i++) { digitalWrite(RAZR[i], HIGH); // выбор разряда PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY по адресу [a] в текущий разряд [i] if (i == 2) PORTD = PORTD | 0b10000000; // зажигаем точку delayMicroseconds(500); digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации } if ((millis() - last_millis) >= 4000) { // частота измерений температуры 4сек last_millis = millis(); start(); peredacha(); chtenie(); schet(); crc_8(); } }
Задержка была в функции peredacha() просто delay(800)
Там же был и второй вызов функции start() после задержки
Логику работы разных вещей нужно разделять. У тебя должен быть класс-таймер. Класс для работы с дисплеем, к нему прикреплен экземпляр таймера. Класс для работы с датчиком, к нему тоже свой отдельный таймер.
А можно еще тот кусок глянуть, который датчик читает?
Логику работы разных вещей нужно разделять. У тебя должен быть класс-таймер. Класс для работы с дисплеем, к нему прикреплен экземпляр таймера. Класс для работы с датчиком, к нему тоже свой отдельный таймер.
Спасибо, пока не понятные для меня слова, но буду учиться.
А можно еще тот кусок глянуть, который датчик читает?
У меня отдельно передача и чтение. Всё пока сырое, не упакованное в циклы, но работает
Это чтение из датчика
"закат Солнца вручную"
"закат Солнца вручную"
Точно! )))
Неблокирующий опрос ds18b20. Извиняюсь что без 100500 цифр "после запятой")) Лишнее сами уберете
Неблокирующий опрос ds18b20.
Спасибо, будем посмотреть!
Rumata, это читерство :) мало того что "точность теряется" - так вы еще и отправляете команды датчику целыми байтами, а не побитно, как уважаемый автор. А вдруг библиотека не каждый бит верно обрабатывает?? - это на самотек пускать нельзя!
Ведь если я не ошибаюсь, ТС не только для себя старается, он торит путь всем последующим новичкам. Ведь у него что не тема - так сразу замах на типовое решение вопроса, как было с цифрами после запятой. И тут тоже - он ведь не просто свою проблемку решает. он вопрос для общества разрабатывает:
он ведь не просто свою проблемку решает. он вопрос для общества разрабатывает:
Да нет же, пытаюсь сам пока разобраться, мне пока не до общества, сам мало-чего понимаю)))
Но процесс "разбирания" интересен, жаль маловато времени на хобби остаётся
//======= функция передачи команд датчику DS18B20 ================
Только у меня ащющение, что ТС вырезан из цельного куска стоеросового дерева?
Rumata , ещё раз спасибо, посмотрел, упростил, даже ещё проще , чем в примере получилось.
Вообще без флагов и ключей, только два счётчика. Зато работает!
команды датчику целыми байтами, а не побитно, как уважаемый автор. А вдруг библиотека не каждый бит верно обрабатывает??
Я для целей надежности передачи после каждой команды использую макрос "КАК СЛЫШНО? ПРИЁМ!", просто вырезал из кода перед публикацией. Это мое секретное ноу-хау ))
упростил, даже ещё проще , чем в примере получилось.
Вообще без флагов и ключей, только два счётчика. Зато работает!
Как-то странно упростил... один счетчик в этом коде явно лишний - он вообще ничего не делает
Только у меня ащющение, что ТС вырезан из цельного куска стоеросового дерева?
Не!
Из цельного дуба вырезана вот эта лестница. Это ж скока, суки, древесины попортили!
Как-то странно упростил... один счетчик в этом коде явно лишний - он вообще ничего не делает
Спасибо за замечание! И правда, посмотрел ещё раз на свежую голову, и тоже это заметил.
Но больше всего смутило, что код работает! И долго бы я бился головой об стену, если бы не выяснил, что в
Proteus не требуется время для преобразования датчиком. Закоментировал delay() в старом варианте скетча, и всё равно, всё работает!
Так что приношу свои извинения. Вот последний вариант
Осмелюсь предложить свой вариант избавления от делеев:
Осмелюсь предложить свой вариант избавления от делеев:
https://github.com/DetSimen/Arduino_TimerList
Спасибо за помощь! Разберусь, испытаю и обязательно отпишусь, когда позволит время.
Добрался пока только до первого варианта. Ещё раз спасибо Alexey_Rem. Думал о том, чтобы использовать задержки динамической индикации "для дела", но самому сделать пока показалось сложновато.
В общем всё работает отлично ,(проверяю в Proteus), но смущают данные датчика
похоже, команды повторяются 8раз подряд. Возможно в железе так работать не будет.Позже с этим разберусь.
Для сравнения выкладываю работу датчика в последнем варианте #17( это то, как я понял код , что дал Rumata)
По объёму, Ваш код ,вместе со всем скетчем, занимает 2314байт памяти устройств(7%) и 99байт(4%)динамической памяти
А предыдущий 2404(7%) и 100(4%) соответственно
Так, что надо будет с этим ещё позаниматься, возможно я где-то накосячил...
P.S. Вариант от DetSimena пока только глянул, там мне много с чем разбираться ещё придётся,
не все сразу понятно. Позже отпишусь.
Рад помочь
В общем понял, почему датчик опрашивается по 8раз. Так и написано в коде. Переменная synchr изменится с 800 на 801 только после 8-ми проходов через case 800: и так же case 1000: Теперь дело за малым - найти решение)))
Добавил флаг, и всё за чих - пыхало!
Так что Proteus не проведёшь!)))
Получается, Alexey_Rem я тоже внёс свои 5копеек(может меньше) в Ваш код)))
Вместе и папу легче отметелить :)
Вот, наконец я разобрался, насколько смог конечно, самые азы, в "будильнике" от DetSimena.
Спасибо за помощь! Насколько я понял, это что-то вроде планировщика задач в windows. И это уже получается С++, язык высокого
уровня? Я так далеко ещё не заходил, читаю пока Кернигана и Ритчи, и то, в самом начале. Остальные знания беру в интернете, по ходу возникновения вопросов,там много есть про С.
Всё написано понятно, и даже я смог спокойно запустить. Индикация заработала от 4мс, ниже не получалось, но и этого в принципе достаточно. Код занял(в целом) 3336байт (10%) памяти устройств и 123байта(6%) дин. памяти, что очень неплохо, учитывая, что
можно запустить еще 3-4-ре датчика (а может и больше).
Ещё раз спасибо DetSimen, и всем ответившим в теме.
Ну, нальёшь при случае.
Ну, нальёшь при случае.
Хорошо))))
Код занял(в целом) 3336байт (10%) памяти устройств и 123байта(6%) дин. памяти, что очень неплохо, учитывая, что можно запустить еще 3-4-ре датчика (а может и больше).
Вы думаете - если код опроса одного датчика занимает ХХХХ байт, то код опроса 4 датчиков займер 4 * ХХХХ байт? - большое заблуждение.
Не стоит рассуждать о размере кода в таком ключе
Вы думаете - если код опроса одного датчика занимает ХХХХ байт, то код опроса 4 датчиков займер 4 * ХХХХ байт? - большое заблуждение.
Не стоит рассуждать о размере кода в таком ключе
Вы правы, конечно же это не так прямолинейно, я и не говорил этого. Но всё же, думаю, что возможности контроля и размер кода взаимосвязаны. Как, например , сравнить Windows и CP/M
И снова делей:(. Даже два
И снова делей:(. Даже два
Точно! Но первый делей не опасен, т.к. работает один раз. А второго(в индикации) в этом варианте и не пробовал избегать, т.к. минимальный заявленный счётчик 1мс. Но теперь вижу, что всё равно индикация работает через 4мс.
Так что , спасибо за подсказку, попробую убрать и его.
Вот убрал, работает уже на 2мс. Это наверно потому, что убрал delay500мкс.
Добавил 1-ну глобальную переменную k.
Первый delay() как-бы и не вижу смысла убирать...
Может я туплю, но в сетапе у вас назначается 4 пина на разряды, а tmrIndTimer() считает их 8?
Может я туплю, но в сетапе у вас назначается 4 пина на разряды, а tmrIndTimer() считает их 8?
Точно, протупил здесь! Но всё работает, потому что в шапке всё правильно назначено. Просто сетап взял из старой версии)))
Спасибо за замечание
В общем, для своей текущей задачи решил пока оставить вариант от Alexey_Rem, как самый " тонкий , звонкий и прозрачный".
(к тому же я там в соавторах))).
Т. к. датчиков добавлять больше не планировал. Другие варианты интересны на будущее.
Дальше по плану доделать шину и ещё думаю попробовать меню и eeprom сделать
Пока использовать сторонние библиотеки избегаю, они для меня пока как кот в мешке, смутно представляю ещё себе их работу.
Однако хочу понимать каждый цикл в своей программе.
Ещё раз всем спсб.
А где желогика.
просто другая логика!
Сравниваем показания таймера миллис с последним запомненным показанием онаго для СОБЫТИЯ/процесса (при этом можно добавлять дополнительные условия) и заданными в предыдущий раз , когда те звезды сошлись, интервалом и условиями. И вот тогда наступит новая реинкарнация типоПроцесса, в которой можно сделать всеЧто необходимо и задать условия( интервал, доп триггеры) для следующей реинкарнации.
и так для каждого процесса по-отдельности.
нужно только помнить, что это неНастоящщая мультизадачность, пока происходит каждая реинкарнация, остальные ждут ее завершения. И тайминги будуть съезжать. Я использую это для процессов типа померять температуру от 18b20 : В сетапе запустили преобразование, выставили переменную сравнения миллис на 3 минуты. Через примерно три минуты провалились в процесс, считали температуру, которая уже точно созрела, чтонить с этой температурой посчитали, выставили какиенить переменные для других проуессов, запустили новое преобразование, выставили новый интервал, через который надо опросить датчик(и) , и все, вернулись в лууп. А там другие, похожие процессы, прсыпаются периодически, смотрят свои переменные, что то делают и засыпают.
можно интервалы менять в зависимости от скорости изменения показаний датчиков, тоже весьма прикольно получается...
вот и сказочке конец, дочитал кто - молодец :)
ухты, публикация изменилась в кои то веки чтотто новое:)
можно интервалы менять в зависимости от скорости изменения показаний датчиков, тоже весьма прикольно получается...
Ну это уже следующая ступень для меня. Как говорится : бери ношу по себе, чтоб не падать при ходьбе)))
можно интервалы менять в зависимости от скорости изменения показаний датчиков, тоже весьма прикольно получается...
Ну это уже следующая ступень для меня. Как говорится : бери ношу по себе, чтоб не падать при ходьбе)))
это называется - развиваем свою логику (логическое мышление) и вникаем в причинно-следственные связи.
это называется - развиваем свою логику (логическое мышление) и вникаем в причинно-следственные связи.
У меня ещё куча делеев в шине. Вот где сложно победить. Скорее их лучше не трогать, пока думаю ещё об этом.
Я использую это для процессов типа померять температуру от 18b20 : В сетапе запустили преобразование, выставили переменную сравнения миллис на 3 минуты. Через примерно три минуты провалились в процесс, считали температуру, которая уже точно созрела, ...
За 3 минуты она и "протухнуть" может)))