Мой 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);
}

, 👍0

Обсуждение

Эм... Что значит "Время застряло"? Ваше состояние верно в течение целой минуты., @AnT

когда условие истинно, временной интервал rtc застревает, и приведенный выше код продолжает зацикливаться, @kirby hipona

Это функция loop(), которая продолжает зацикливаться. Для этого оно и предназначено, как следует из названия. С чего вы взяли, что "застрял временной интервал rtc" мне не понятно., @AnT

Время застопорилось, а состояние продолжает срабатывать.., @kirby hipona

Что заставило вас поверить, что «время застряло»??? Условие **должно** срабатывать снова, снова и снова в течение целой минуты. Это то, что вы написали в своем коде., @AnT

Я смотрю на последовательный монитор, и время зависает, когда условие достигнуто. И он продолжает запускать сервопривод снова и снова.., @kirby hipona

Опубликуйте вывод последовательного монитора из printDateTime(now); в loop(). Вы видите, что одно и то же время печатается непрерывно?, @AnT

ds1302 не очень хороший rtc, ds1307 лучше, но ds3231 однозначно лучший. ds1302 может зависнуть и могут быть проблемы с кристаллом. Не могли бы вы перейти на ds3231. У ds3231 внутренний кристалл, поэтому с кристаллами плохого качества проблем не возникает., @Jot

AnT Он зависает в заданном состоянии, сервопривод продолжает срабатывать от 5 до 10 раз, и после запуска отсчет времени продолжается., @kirby hipona

Я не использую кристалл, @kirby hipona

думаю, у меня проблема с задержкой в секундах, @kirby hipona

Я не использую кристалл -- Итак... как же тогда "тикают" часы...?, @Majenko

Вы же знаете, что минута длится целую минуту, не так ли? Это не какая-то мгновенная вещь, которая происходит только на мгновение. Это минута. За минуту может произойти многое., @Majenko

Задержки в вашем цикле() составляют 12 секунд. Так что вполне ожидаемо увидеть это, если оно будет срабатывать примерно 5 раз в минуту., @AnT


1 ответ


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

2

Вашему вниманию предлагается следующая часть вашего кода...

//вот моя проблема>>>>

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