Мой Arduino застрял и постоянно зацикливается в условии if
Я использую RTC, и когда условие if истинно, время застревает, и условие продолжает зацикливаться. Пожалуйста, помогите
Вот мой код:
// СОЕДИНЕНИЯ:
// DS1302 CLK/SCLK --> 5
// DS1302 DAT/IO --> 4
// DS1302 RST/CE --> 2
// DS1302 VCC --> 3,3 В - 5 В
// DS1302 GND --> ЗАЗЕМЛЕНИЕ
#include <Servo.h>
#include <ThreeWire.h>
#include <RtcDS1302.h>
ThreeWire myWire(4,5,2); // ввод-вывод, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
int servoPin = 3;
Servo Servo1;
void setup ()
{
Serial.begin(57600);
Servo1.attach(servoPin);
// Serial.print("скомпилировано:");
// Serial.print(__DATE__);
Serial.println(__TIME__);
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__TIME__);
printDateTime(compiled);
Serial.println();
if (Rtc.GetIsWriteProtected())
{
Serial.println("RTC was write protected, enabling writing now");
Rtc.SetIsWriteProtected(false);
}
if (!Rtc.GetIsRunning())
{
Serial.println("RTC was not actively running, starting now");
Rtc.SetIsRunning(true);
}
RtcDateTime now = Rtc.GetDateTime();
if (now < compiled)
{
Serial.println("RTC is older than compile time! (Updating DateTime)");
Rtc.SetDateTime(compiled);
}
else if (now > compiled)
{
Serial.println("RTC is newer than compile time. (this is expected)");
}
else if (now == compiled)
{
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
}
}
void loop ()
{
RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
Serial.println();
delay(5000);
//вот моя проблема>>>>
if(now.Hour() == 22 && now.Minute() == 40)
{
Servo1.write(0);
delay(1000);
Servo1.write(90);
delay(1000);
}
///////////////////////
delay(5000);
}
#define countof(a) (sizeof(a) / sizeof(a[0]))
void printDateTime(const RtcDateTime& dt)
{
char datestring[20];
//%02u/%02u/%04u
snprintf_P(datestring,
countof(datestring),
PSTR("%02u:%02u:%02u"),
// дт.Месяц(),
// дт.День(),
// dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
Serial.print(datestring);
}
@kirby hipona, 👍0
Обсуждение1 ответ
Лучший ответ:
Вашему вниманию предлагается следующая часть вашего кода...
//вот моя проблема>>>>
if(now.Hour() == 22 && now.Minute() == 40)
{
Servo1.write(0);
delay(1000);
Servo1.write(90);
delay(1000);
}
В этом коде вы используете оператор if и спрашиваете: если now.Hour равен 22 И если now.Minute равен 40, то напишите 0 на свой сервопривод, затем задержка на 1000 затем напишите 90 на свой сервопривод и ждать еще 1000
Ваше внимание обращается на то, что до сих пор.Часы меняются или до сих пор. Минута меняет вашу запись 0, задержка, запись 90, задержка будет продолжаться дальше и дальше и дальше до сих пор.Час меняется (что займет некоторое время) или сейчас.Минута изменения. Поскольку минуты составляют 60 секунд, ваш код будет повторяться для всех этих 60 секунд...
Если бы вы изменили свой код, включив в него, о, скажем, сейчас. Second() (вот так) --
if(now.Hour() == 22 && now.Minute() == 40 && now.Second() == 00)
Тогда ваш код будет повторяться снова и снова до сих пор. Вторые изменения (которые займут 1 секунду).
К тому времени, когда ваш цикл вернется к оператору "if", значение Second больше не будет равно 00, и оно не будет "зависать" для вас...
Как я уже обратил внимание, ваша 5-секундная задержка будет проблемой, поэтому вы можете обнаружить, что ее изменение позволит сработать «исправлению» now.Second.
В следующей части кода измените задержку (5000)
void loop ()
{
RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
Serial.println();
delay(5000);
}
что-то вроде delay(1000) или около того.
Таким образом, он будет ждать только 1 секунду, прежде чем выйти из цикла и проверить цикл с помощью только что добавленного now.Second(). Это приведет к тому, что printDateTime(now) будет происходить каждую секунду, а не каждые 5 секунд, но он не должен "зависать".
Надеюсь, это поможет вам лучше понять, как работает время (и его части).
переменная состояния была бы гораздо лучшим решением. с задержкой в 5 секунд в цикле() код может пропустить точную секунду, @Juraj
Стремление к точному равенству запланированного времени — плохой подход, независимо от того, насколько короткой является задержка. Правильное условие должно выглядеть как (current_time >= запланированное_время && event_has_not_been_triggered_yet)
. Т.е. это должно быть сравнение «больше или равно», а не сравнение на равенство., @AnT
Ах, опыт говорит! Мне это нравится, гораздо лучшее решение..., @Wendall
Этот подход может быть дополнительно модифицирован с помощью дополнительных настроек, например: если приведенное выше условие верно, но с запланированного времени прошло *слишком много* времени (из-за какой-то неудачной операции блокировки в loop()
), то просто отмените событие. . Зависит от конкретного приложения. Поднять тревогу, чтобы разбудить людей
утро буднего дня, как правило, не является «выбрасываемым» событием. Кормить кошку, если ей уже давно пора спать, вероятно, стоит., @AnT
Спасибо, Александр! Я не знаю, как использовать «редактор» так же хорошо, как вы, мне не удалось добавить исходный код ОП так же хорошо, как вы. Еще раз спасибо!, @Wendall
Вы можете использовать четыре пробела, чтобы [отметить](https://arduino.stackexchange.com/editing-help#syntax-highlighting) его как блок кода., @Alexander
- Разница между «time_t» и «DateTime»
- Создание таймера с использованием часов реального времени с указанием времени начала и остановки
- Библиотека времени Arduino и библиотеки RTC
- Ошибка модуля часов реального Времени-DS3231
- DS3231 rtc.begin() всегда возвращает false
- Adafruit RTC begin() не возвращает false
- Как установить управляющий регистр в модуле RTC DS3231 для Arduino UNO R3?
- DS3231 Не совпадает время при выключении Arduino
Эм... Что значит "Время застряло"? Ваше состояние верно в течение целой минуты., @AnT
когда условие истинно, временной интервал rtc застревает, и приведенный выше код продолжает зацикливаться, @kirby hipona
Это функция
loop()
, которая продолжает зацикливаться. Для этого оно и предназначено, как следует из названия. С чего вы взяли, что "застрял временной интервал rtc" мне не понятно., @AnTВремя застопорилось, а состояние продолжает срабатывать.., @kirby hipona
Что заставило вас поверить, что «время застряло»??? Условие **должно** срабатывать снова, снова и снова в течение целой минуты. Это то, что вы написали в своем коде., @AnT
Я смотрю на последовательный монитор, и время зависает, когда условие достигнуто. И он продолжает запускать сервопривод снова и снова.., @kirby hipona
Опубликуйте вывод последовательного монитора из
printDateTime(now);
вloop()
. Вы видите, что одно и то же время печатается непрерывно?, @AnTds1302 не очень хороший rtc, ds1307 лучше, но ds3231 однозначно лучший. ds1302 может зависнуть и могут быть проблемы с кристаллом. Не могли бы вы перейти на ds3231. У ds3231 внутренний кристалл, поэтому с кристаллами плохого качества проблем не возникает., @Jot
AnT Он зависает в заданном состоянии, сервопривод продолжает срабатывать от 5 до 10 раз, и после запуска отсчет времени продолжается., @kirby hipona
Я не использую кристалл, @kirby hipona
думаю, у меня проблема с задержкой в секундах, @kirby hipona
Я не использую кристалл
-- Итак... как же тогда "тикают" часы...?, @MajenkoВы же знаете, что минута длится целую минуту, не так ли? Это не какая-то мгновенная вещь, которая происходит только на мгновение. Это минута. За минуту может произойти многое., @Majenko
Задержки в вашем цикле() составляют 12 секунд. Так что вполне ожидаемо увидеть это, если оно будет срабатывать примерно 5 раз в минуту., @AnT