Есть ли лучший выбор, кроме использования delay() для 6-часовой задержки?

Я проектирую эту инкубаторную систему, и мне нужно каждые 6 часов двигать двигатель вперед и назад. Есть ли лучший выбор, кроме использования delay() ? Задержка на 6 часов кажется немного непрофессиональной.

, 👍6

Обсуждение

Используйте RTC-чип., @Majenko

Объяснение, пожалуйста, если вы не возражаете, @henzup

https://www.circuitbasics.com/how-to-use-a-real-time-clock-module-with-the-arduino/, @Majenko

> Задержка в 6 часов кажется немного непрофессиональной. Непрофессиональное отношение исходит из более важных, но игнорируемых вопросов: - Имеет ли значение, когда / если Arduino был перезапущен / сброшен во время работы? - Полезно ли иметь какую-либо обратную связь о фактическом состоянии цикла? - Какова требуемая точность для этих 6 часов? - Полезно ли / требуется ли синхронизировать этот период с какими-либо реальными мировыми часами?, @DataFiddler

Насколько точными вам должны быть 6 часов, и какой процессор / plaftorm вы используете? Многие процессоры будут иметь спящие режимы, в которых вы можете просто перевести его в спящий режим на определенное время (хотя во многих случаях это будет выглядеть как сброс, он просыпается, поэтому вам нужно сохранить некоторое состояние и проверить причину загрузки при запуске), но точность часто не очень хорошая., @jcaron


5 ответов


Лучший ответ:

9

Здесь есть несколько вариантов, и несколько человек указали на некоторые проблемы.

"Лучший" ответ - вероятно, использовать плату часов реального времени (RTC), чтобы помочь вам определить время и эффективно установить целевое время (следующий запуск двигателя в 23:14 ...) каждый раз, когда цикл перезапускается. Сохранив эту цель выключенной (например, на EEPROM или SD-карту), вы защитите себя от потенциального выключения и сброса arduino посередине.

Вторичный ответ; установите loop() так, чтобы он включал относительно короткий оператор delay(), а затем проверьте время, прошедшее с момента последнего включения двигателя. Это позволит вам обрабатывать другие элементы, как кто-то еще отметил в этой теме. Это я псевдокодировал ниже.

unsigned long lastMotorRunTime;

void loop()
{
    /*
     * делайте все, что угодно
     */
    if(millis()-lastMotorRunTime > 21600000)  // прошло 6 часов
    {
         runTheMotor(); // заполнитель для нужных вам двигательных движений
         lastMotorRunTime = millis();
    }
   /* 
    * занимайтесь другими делами. 
    */
   delay(100); // цикл примерно каждые 1/10 секунды или что-то еще работает
}

Учитывая, что вам, похоже, не нужна детальная точность - несколько секунд в любом случае не имеют значения - это должно работать разумно. Обратите внимание, ЧТО он потерпит неудачу, если Ardiuno будет сброшен - тогда он будет вращать двигатель только (в моем псевдокоде) через 6 часов после последнего сброса Arduino. Вероятно, лучше предположить, что сброс arduino означает перемещение двигателя "сейчас", если речь идет о том, чтобы обеспечить периодическое движение, а не точное время.

Для точного хронометража, как уже отмечалось, потребуется РТК.

(Обновлено: изменено lastMotorRunTime на unsigned long)

,

Должно быть unsigned long lastMotorRunTime, чтобы избежать проблем с опрокидыванием; см. https://arduinoprosto.ru/q/12587/how-can-i-handle-the-millis-rollover, @MarkU

Задержка () кажется здесь совершенно бесполезной., @Edgar Bonet

задержка @EdgarBonet, вероятно, бесполезна, но она указывает на идею и может быть заменена чем-то более полезным, например: https://www.arduino.cc/en/Reference/LowPowerSleep, @Patrick M

Re “_ это указывает на идею и может быть заменено чем-то более полезным”: комментарий "занимайся другими делами" идеально подходит для этой роли., @Edgar Bonet

@MarkU Хороший улов на неподписанном длинном - отредактировал исправление. Да; Эдгар Бонет и Патрик М. Я мог бы вообще не вводить задержку (), но поместил ее туда, чтобы немного яснее показать возможности., @Shaun Vince

Вы также захотите включить какой-нибудь механизм состояния и / или считыватель положения, чтобы убедиться, что двигатель работал в нужное время. Я работал над кодировщиками, которые дрожали и вызывали "больше движения", в результате чего время отключалось слишком рано. Перебои в подаче питания, периодические сбои или скачки напряжения - все это может привести к нарушению движения. Здесь много идей, и вы демонстрируете отличное предварительное планирование их решения., @J.Hirsch


3

Использование функции delay() для 6-часовой задержки немного неудобно, но вполне выполнимо. Однако это будет не очень точно, потому что точность зависит от точности часов Arduino, и он заблокирует весь остальной код, который вы, возможно, захотите запустить.

Использование синхронизации с millis() позволит вашему Arduino делать другие вещи во время ожидания. Однако это будет так же неточно.

В течение длительного времени, особенно если вы хотите, чтобы все было более точно, вы можете использовать внешние часы реального времени, такие как DS3231. Вы можете получить их в виде модулей на прорывных платах, а также доступны библиотеки.

Эти RTCS имеют резервную батарею, поэтому они также продолжают работать некоторое время без внешнего питания, а также будут сохранять время, когда Arduino сбрасывается. Большинство из них также имеют настраиваемое время будильника, которое вы можете использовать.

Для вашего приложения я бы также реализовал простой сторожевой таймер, чтобы убедиться, что Arduino все еще ждет и работает и не разбился. Обратите внимание, что сторожевой таймер не будет хорошо работать с delay(); простая 6-часовая задержка всегда будет вызывать его, а синхронизация с millis () или внешним RTC - это путь сюда.

,

Некоторые из этих модулей поддерживают функцию сигнализации. Пусть ваш код установит время при компиляции, а затем забудет об этом. ЦИКЛ: При запуске цикла считайте показания часов, рассчитайте время срабатывания будильника, необходимое для разворота, и установите его. При срабатывании аварийного сигнала включите двигатель в обратном направлении и повторите ЦИКЛ. Если вы вставите аккумулятор в модуль, это сохранит время даже при отключении питания., @Gil


3

Поскольку это для инкубатора, я подозреваю, что вам не нужна высокая точность. Таким образом, delay() будет работать отлично, если вы не хотите делать что-то еще в то же время (например, контролировать температуру, управлять нагревателем и / или освещать светодиоды для превышения / понижения температуры). В этом случае вы можете использовать цикл, который обрабатывает все эти операции с некоторой удобной скоростью, например, один раз в секунду или один раз в минуту, используя функцию delay() в цикле. (Я предполагаю, что ваш инкубатор медленно реагирует на нагреватель, поэтому медленный отбор проб будет в порядке.) Затем дайте циклу поработать в течение 6 часов, которые вы можете определить простым подсчетом 1-минутных (или любых других) задержек цикла. И если вы обнаружите, что ваше 6-часовое время постоянно высокое или низкое, отрегулируйте лимит счета, чтобы компенсировать это.

,

0

Нет ничего плохого в том, чтобы использовать здесь задержку.

Проблема возникает только в том случае, если вы хотите заставить Arduino делать что-то еще. В этом случае вы хотите использовать миллиси использовать его, чтобы вычислить, сколько времени прошло (см. Мигание без задержки).

,

2

У меня есть автоматическая система полива, которая (помимо всего прочего) срабатывает вовремя. Для этого я использую отличную библиотеку таймеров. Он допускает несколько полезных временных взаимодействий, таких как Pulse или Oscillate, в дополнение к After, которые решат вашу проблему - или Every, если вы хотите выполнить повторяющийся 6-часовой блок кода

В конце концов - за экраном - это так же непрофессионально, как millis() - сама библиотека использует millis() и планировщик. Но код выглядит чище, его легче писать и обновлять.

,