Программирование Arduino Uno R3 для срабатывания реле каждые 24 часа
Я запрограммировал Arduino UNO R3 на срабатывание реле каждые 24 часа с момента включения
Я вычислил миллисекунды и использовал функцию delay()
24 часа * 60 минут каждый час * 60 секунд каждую минуту * 1000 миллисекунд каждую секунду
поэтому я использовал:
delay(86400000)
86 миллионов 400 тысяч миллисекунд
и в настоящее время я все еще тестирую его... Будет ли это работать? Если нет, есть ли лучшая встроенная функция/библиотека или даже внешняя библиотека для этого?
триггер реле не должен быть очень точным в точное время каждый день Мне не нужно, чтобы он был очень точным, он может смещаться на несколько минут каждые несколько месяцев или около того, меня это устраивает
А как насчет нескольких месяцев или лет использования? Сильно ли это сдвинет сроки? Я где-то читал об использовании функции millis() а другие используют модуль RTC (часы реального времени)
Я не хочу использовать модуль RTC Ищу программное решение... ИЛИ если мой предыдущий метод с использованием delay() будет работать в течение такого очень большого количества миллисекунд?
Спасибо
@Felix0004, 👍4
Обсуждение3 ответа
Лучший ответ:
Да, delay() будет работать, как и другие методы, основанные на счетчике millis(). Тем не менее, delay() сделает невозможным выполнение каких-либо других действий в это время.
Поищите Моргание без задержки, чтобы узнать, как добиться такой задержки, но при этом иметь возможность выполнять другие действия. вещи в вашем коде во время ожидания.
Кастинг
При работе с большими числами, такими как 24-часовая задержка, убедитесь, что эти числа явно указаны как unsigned long
или выражены с помощью "UL" расширение (например, 86400000UL
). Это явно указывает C++ ожидать "unsigned long" (что в терминах Arduino Uno является 32-битным числом без знака).
В вашем случае (при таком явно большом числе) компилятор автоматически выберет нужный тип. В других случаях (например, если вы измените выражение на 24*60*60*1000
), компилятор не будет автоматически генерировать беззнаковое длинное значение, и вам нужно принудительно его создать, изменив первую часть выражение в unsigned long: 24UL*60*60*1000
или, альтернативно, (unsigned long) 24*60*60*1000
.
Точность
Точность синхронизации будет зависеть от типа генератора на вашей конкретной плате Arduino. Во многих Arduino или их клонах используется керамический осциллятор, точность которого обычно составляет примерно от 0,1 до 0,5%, что означает возможное отклонение в 43 секунды в день и, как таковое, может быть слишком неточным для ваших целей. Если в вашем Arduino есть кварцевый осциллятор, он будет намного более точным (приблизительно до 150 частей на миллион, что означает максимальное отклонение около 1 секунды в день при нормальных условиях).
Спасибо большое StarCat У меня есть arduino uno R3 (третья версия), и я вижу прямоугольный кристалл на плате, поэтому я думаю, что он такой же точный, как вы описали.... 1 секунда в день, это около 365 секунд (6 минут) в год... так что это нормально. И я буду использовать расширение UL Unsigned Long в своем коде... лучше, даже если оно работает с обычной задержкой() без назначения этого типа данных. Я ценю ваш вклад И ссылка на статью, которую вы разместили о выполнении нескольких дел одновременно во время ожидания программы, очень полезна, большое спасибо., @Felix0004
Суффикс «UL» не нужен, так как компилятор выберет тип данных, достаточно большой для хранения значения. Однако это **обязательно** необходимо, по крайней мере, для первого фактора, если вы хотите написать выражение вроде «24UL * 60 * 60 * 1000»., @Edgar Bonet
@EdgarBonet, это правда, конечно. Мое мнение таково, что явное приведение типов, где это уместно, не повредит и предотвратит трудно найти ошибки в случаях, когда это не так однозначно (как в вашем примере). Я расширил объяснение в ответе., @StarCat
Обновление: я тестировал проект в течение полных 24 часов с 21:03 вечера среды, так как я включил Arduino до вечера четверга следующего дня, и я заметил, что он сдвинулся / задержался примерно на 3 минуты, потому что он сработал реле около 9: 18:00 (это задержка около 3 минут), поэтому 3 минуты смены * 30 дней в месяц = 90 минут (полуторачасовая смена по времени каждый месяц). Я собираюсь протестировать это еще на 24 часа и посмотреть ..., @Felix0004
delay() принимает unsigned long; Я думаю, то, что вы делаете, сработает.
В случае сомнений вы всегда можете сделать что-то вроде этого:
for (int hours = 0; hours < 24; hours++) {
for (int mins = 0; mins < 60; mins++) {
for (int secs = 0; secs < 60; secs++) {
delay(1000);
}
}
}
Однако это будет крайне неточно, потому что часы неточны, а также будут дрейфовать в зависимости от температуры, что усугубляется тем, что вместо кристалла используется резонатор.
Таким образом, вы не получите точности в несколько минут в месяц, независимо от "задержки" метод, который вы используете; оборудование для этого не подходит.
Большое спасибо ocrdu У меня arduino uno R3 (третья ревизия) и я вижу на плате прямоугольный кристалл, значит, он точнее?, @Felix0004
Насколько мне известно, у UNO R3 на плате тоже есть резонатор для процессора, а кристалл используется только для тайминга USB. Это может отличаться в разных версиях платы. Тем не менее, даже с кристаллом я сомневаюсь, что вы получите желаемую точность., @ocrdu
Хм, не знал об этом. Значит, единственное решение — полностью использовать другую плату Arduino? Мне просто нужно, чтобы реле срабатывало один раз в день, вот и все... не обязательно точное время., @Felix0004
Ну, что я бы сделал, так это просто попробовал бы это со временем, скажем, в два часа (или сколько бы времени вы ни удосужились понаблюдать за вещью), посмотреть, достаточно ли близко, и если нет, ввести калибровочный коэффициент в код компенсации. Измерительное оборудование облегчило бы этот процесс. Если окажется, что вы не можете правильно настроить таким образом из-за нестабильности часов, вы всегда можете добавить точный модуль RTC. Возможно, примитивная инженерия, но попробовать стоит., @ocrdu
1. Насчет «_Я думаю, что то, что ты делаешь, сработает_»: сработает. delay()
может обрабатывать до ULONG_MAX
миллисекунд, что составляет около 49,7 дней. 2. Касательно «_ввести калибровочный коэффициент_»: если эксперимент провести всего за несколько часов, это, скорее всего, сработает. Но тогда отклонение частоты приведет к нарушению калибровки в более длительных масштабах времени. Вы можете ожидать, что тактовая частота будет «случайным блужданием» с типичным законом √t во временных масштабах более нескольких секунд., @Edgar Bonet
Привет, Эдгар, я тестировал проект в течение полных 24 часов с 21:03 вечера среды, так как я включил Arduino до вечера четверга следующего дня, и я заметил, что он сдвинулся / задержался примерно на 3 минуты, потому что он сработал реле около 9 :06 вечера (это примерно 3-минутная задержка), поэтому 3-минутная смена * 30 дней в месяц = 90 минут (полуторачасовая временная смена каждый месяц). Я собираюсь протестировать его еще 24 часа и посмотреть..., @Felix0004
@Felix0004: 3 минуты в день — это 3×60÷86400 ≈ 0,002 или 2000 частей на миллион. Довольно высокий, но все еще в пределах допуска типичного керамического резонатора., @Edgar Bonet
@EdgarBonet, и еще через 24 часа происходит еще 3-минутный дрейф, он начался в 21:09 ... так что это своего рода постоянный дрейф в течение 3 минут каждый день, что составляет полтора часа каждый месяц, это все еще много. Да., @Felix0004
Можно попробовать поместить Uno в «духовку» с регулируемой температурой, скажем, в пластиковый корпус с очень маломощным нагревателем (подойдет даже подходящий резистор) и термодатчиком. Это должно уменьшить некоторые колебания частоты кристалла.
Но я не могу постоянно нагревать uno, мне нужно постоянное решение :) Спасибо, Джей Роберт., @Felix0004
- DS3231 + кнопка для включения подсветки
- Вызов метода в основном скетче из библиотеки.
- Глобальные переменные занимают много места в динамической памяти.
- Ошибка: "'lcd' does not name a type" при использовании библиотеки LiquidCrystal.
- 4-битный счетчик вверх и вниз
- Как я могу прервать задержку() при нажатии кнопки?
- Альтернативы дисплею Nextion
- Как сгенерировать файлы .a и .so для добавления в проект arduino
«Несколько минут каждые несколько месяцев» — это около 20 частей на миллион. Вы можете ожидать дрейфа часов около 1000 ppm на Uno. Даже если вы откалибруете дрейф, дрейф частоты, скорее всего, нарушит вашу калибровку и составит менее 20 частей на миллион в день или около того. Вам действительно нужен RTC для удовлетворения ваших требований к точности. См. [Точность тактовой частоты Arduino] (http://jorisvr.nl/article/arduino-frequency) для подробного экспериментального анализа стабильности частоты Arduino (у Uno есть резонатор, аналогичный тому, что у Pro Mini)., @Edgar Bonet
Итак, нет программного решения, для этого должно быть аппаратное решение, с использованием внешнего модуля RTC или, может быть, путем создания моей собственной схемы печатной платы с установкой на нее кварцевого генератора и подключением его к цифровому выводу arduino? И ссылка, которую вы разместили, очень полезная, спасибо, я пойду ее читать. Я не хочу использовать RTC, поэтому мне не нужно каждый раз менять батарею, или я могу просто подключить разъем батареи к контакту питания постоянного тока 3,3 В Arduino? Большое спасибо, Эдгар, очень признателен, @Felix0004
Вывод 3,3 В Uno — это выход питания, вы не можете питать Arduino через него. Если вы замените Arduino на голый ATmega на собственной печатной плате, вы можете заменить резонатор на кварцевый генератор с частотой 16 МГц. Он может по-прежнему дрейфовать слишком сильно, но скорость дрейфа будет постоянной, и вы сможете ее откалибровать. В качестве альтернативы, синхронизируйте ATmega с его внутреннего RC-генератора и [подключите тактовый кристалл к контактам TOSC его асинхронного таймера] (https://wiki.logre.eu/index.php/Horloge_analogique_24h/en). При таком использовании асинхронный таймер похож на RTC, встроенный в ATmega., @Edgar Bonet
Спасибо, Эдгар, за ваш очень информативный вклад, вклад и вашу очень любезную помощь. Я изучу вашу идею более глубоко и постараюсь применить ее практически в ближайшее время. и да, контакт Arduino 3,3 В - это выходная мощность, я имею в виду, чтобы использовать его для питания модуля RTC, а не для питания Arduino, я нашел местный источник питания, в котором есть 3 разных модели модулей RTC, только PCF8523, DS1307 и DS3231 и DS1302 IC и DS1307 ИС с 8 погружениями, я провел небольшое исследование и обнаружил, что DS3231 является наиболее точным с высокой точностью, поскольку он имеет датчик температуры, который периодически регулирует любой дрейф / сдвиг синхронизации., @Felix0004