Есть ли лучший выбор, кроме использования delay() для 6-часовой задержки?
Я проектирую эту инкубаторную систему, и мне нужно каждые 6 часов двигать двигатель вперед и назад. Есть ли лучший выбор, кроме использования delay() ? Задержка на 6 часов кажется немного непрофессиональной.
@henzup, 👍6
Обсуждение5 ответов
Лучший ответ:
Здесь есть несколько вариантов, и несколько человек указали на некоторые проблемы.
"Лучший" ответ - вероятно, использовать плату часов реального времени (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
Использование функции delay()
для 6-часовой задержки немного неудобно, но вполне выполнимо. Однако это будет не очень точно, потому что точность зависит от точности часов Arduino, и он заблокирует весь остальной код, который вы, возможно, захотите запустить.
Использование синхронизации с millis()
позволит вашему Arduino делать другие вещи во время ожидания. Однако это будет так же неточно.
В течение длительного времени, особенно если вы хотите, чтобы все было более точно, вы можете использовать внешние часы реального времени, такие как DS3231. Вы можете получить их в виде модулей на прорывных платах, а также доступны библиотеки.
Эти RTCS имеют резервную батарею, поэтому они также продолжают работать некоторое время без внешнего питания, а также будут сохранять время, когда Arduino сбрасывается. Большинство из них также имеют настраиваемое время будильника, которое вы можете использовать.
Для вашего приложения я бы также реализовал простой сторожевой таймер, чтобы убедиться, что Arduino все еще ждет и работает и не разбился. Обратите внимание, что сторожевой таймер не будет хорошо работать с delay()
; простая 6-часовая задержка всегда будет вызывать его, а синхронизация с millis ()
или внешним RTC - это путь сюда.
Некоторые из этих модулей поддерживают функцию сигнализации. Пусть ваш код установит время при компиляции, а затем забудет об этом. ЦИКЛ: При запуске цикла считайте показания часов, рассчитайте время срабатывания будильника, необходимое для разворота, и установите его. При срабатывании аварийного сигнала включите двигатель в обратном направлении и повторите ЦИКЛ. Если вы вставите аккумулятор в модуль, это сохранит время даже при отключении питания., @Gil
Поскольку это для инкубатора, я подозреваю, что вам не нужна высокая точность. Таким образом, delay() будет работать отлично, если вы не хотите делать что-то еще в то же время (например, контролировать температуру, управлять нагревателем и / или освещать светодиоды для превышения / понижения температуры). В этом случае вы можете использовать цикл, который обрабатывает все эти операции с некоторой удобной скоростью, например, один раз в секунду или один раз в минуту, используя функцию delay() в цикле. (Я предполагаю, что ваш инкубатор медленно реагирует на нагреватель, поэтому медленный отбор проб будет в порядке.) Затем дайте циклу поработать в течение 6 часов, которые вы можете определить простым подсчетом 1-минутных (или любых других) задержек цикла. И если вы обнаружите, что ваше 6-часовое время постоянно высокое или низкое, отрегулируйте лимит счета, чтобы компенсировать это.
Нет ничего плохого в том, чтобы использовать здесь задержку.
Проблема возникает только в том случае, если вы хотите заставить Arduino делать что-то еще. В этом случае вы хотите использовать миллис
и использовать его, чтобы вычислить, сколько времени прошло (см. Мигание без задержки).
У меня есть автоматическая система полива, которая (помимо всего прочего) срабатывает вовремя. Для этого я использую отличную библиотеку таймеров. Он допускает несколько полезных временных взаимодействий, таких как Pulse
или Oscillate
, в дополнение к After
, которые решат вашу проблему - или Every
, если вы хотите выполнить повторяющийся 6-часовой блок кода
В конце концов - за экраном - это так же непрофессионально, как millis()
- сама библиотека использует millis()
и планировщик. Но код выглядит чище, его легче писать и обновлять.
- Как повторить код
- Как справиться с rollover millis()?
- Почему мои часы реального времени показывают неверное время с моего ПК?
- Обратное вращение шагового двигателя
- Arduino uno + cnc Shield v3 + драйвер шагового двигателя A4988 + AccelStepper?
- Двигатель постоянного тока шумит, но не вращается
- Несколько неблокирующих таймеров обратного отсчета?
- Почему сервопривод вращается на 360 градусов?
Используйте 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