Nano + RTC - not executing on time or at all

Hi ladies and gents

I was wondering if anyone could help? I've written some code to automatically send out an IR signal/command at set times. However, I've woke up this morning to see the progress of it and it hasn't worked. I've tested the commands individually by calling them in setup, then I've tested them by changing the times to +1 minute from the current time and the if statement works too. But when it's changed to the correct times I need, it isn't working. Would someone be able to lay their eyes on my code and shed some wisdom here, please?

#include <Arduino.h>

#include <IRremote.hpp>
#include "RTClib.h"

RTC_DS1307 rtc;
const int RELAY_PIN = 4;

#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  Serial.begin(57600);

  if (!rtc.begin()) {
    Serial.flush();
    while (1) delay(10);
  }

#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) || defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
  delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif

#if defined(IR_SEND_PIN)
  IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
#else
  IrSender.begin(3, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
#endif

  if (!rtc.isrunning() || rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void startChange() {
  digitalWrite(RELAY_PIN, HIGH);
  while (millis() < millis() + 5000) {}
  digitalWrite(RELAY_PIN, LOW);
}

void sendUp() {
  uint16_t irSignal[67] = {8930, 4520, 530, 570, 530, 620, 530, 570, 530, 620, 530, 620, 480, 620, 530, 570, 530, 620, 530, 1670, 530, 1720, 530, 1670, 530, 1720, 530, 1670, 530, 1720, 530, 1670, 530, 1720, 530, 1720, 480, 620, 530, 1670, 530, 620, 530, 570, 530, 620, 530, 620, 480, 620, 530, 620, 480, 1720, 530, 570, 530, 1720, 530, 1720, 480, 1720, 530, 1670, 530, 1720, 530}; // Protocol=NEC Address=0x0 Command=0x5 Raw-Data=0xFA05FF00 32 bits LSB first
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
  wait();
}

void sendOff() {
  uint16_t irSignal[67] = {8930, 4520, 530, 620, 480, 620, 530, 570, 530, 620, 530, 570, 530, 620, 530, 620, 480, 620, 530, 1720, 480, 1720, 530, 1670, 530, 1720, 530, 1720, 480, 1720, 530, 1670, 530, 1720, 530, 620, 480, 1720, 530, 1720, 480, 620, 530, 570, 530, 620, 530, 570, 530, 620, 530, 1720, 480, 620, 530, 620, 480, 1720, 530, 1670, 530, 1720, 530, 1670, 530, 1720, 530}; // Protocol=NEC Address=0x0 Command=0x6 Raw-Data=0xF906FF00 32 bits LSB first
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
  wait();
}

void sendOn() {
  uint16_t irSignal[67] = {8880, 4520, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 1720, 480, 1720, 530, 1720, 480, 1720, 530, 1720, 480, 1720, 530, 1720, 480, 1720, 530, 1720, 480, 1720, 530, 1720, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 1720, 530, 1720, 480, 1720, 530, 1720, 480, 1720, 530}; // Protocol=NEC Address=0x0 Command=0x7 Raw-Data=0xF807FF00 32 bits LSB first
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
  wait();
}

void sendBlue() {
  const uint16_t irSignal[67] = {8930, 4470, 530, 620, 480, 620, 530, 620, 530, 570, 530, 620, 530, 570, 530, 620, 530, 570, 530, 1670, 580, 1670, 530, 1720, 530, 1670, 530, 1720, 530, 1670, 530, 1670, 580, 1670, 530, 620, 530, 1670, 530, 570, 580, 1670, 530, 620, 530, 570, 530, 620, 530, 620, 480, 1720, 530, 620, 480, 1720, 530, 570, 530, 1720, 530, 1720, 480, 1720, 530, 1720, 480}; // Protocol=NEC Address=0x0 Command=0xA Raw-Data=0xF50AFF00 32 bits LSB first
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ);
  wait();
}

void sendDown() {
  uint16_t irSignal[67] = {8880, 4470, 580, 570, 530, 570, 580, 570, 530, 620, 530, 570, 530, 620, 530, 570, 530, 620, 530, 1670, 530, 1720, 530, 1720, 480, 1720, 530, 1720, 480, 1720, 530, 1670, 530, 1720, 530, 620, 480, 620, 530, 1670, 530, 620, 530, 570, 530, 620, 530, 570, 530, 620, 530, 1670, 530, 1720, 530, 570, 530, 1720, 530, 1670, 530, 1720, 530, 1670, 530, 1720, 530}; // Protocol=NEC Address=0x0 Command=0x4 Raw-Data=0xFB04FF00 32 bits LSB first
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ);
  wait();
}

void sendWhite() {
  uint16_t irSignal[67] = {8930, 4520, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 1720, 530, 1720, 480, 1720, 530, 1670, 530, 1720, 530, 1720, 480, 1720, 530, 1670, 530, 1720, 530, 1670, 530, 620, 530, 1720, 480, 620, 530, 620, 480, 620, 530, 620, 480, 620, 530, 620, 480, 1720, 530, 620, 480, 1720, 530, 1720, 480, 1720, 530, 1670, 530}; // Protocol=NEC Address=0x0 Command=0xB Raw-Data=0xF40BFF00 32 bits LSB first
  IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ);
  wait();
  
}

void wait() {
  while (millis() < millis() + 1000) {}
}

void loop() {
  DateTime now = rtc.now();

  if (now.hour() == 6 && now.minute() == 30 && now.second() < 2) {
    sendOn(); // light on & 1 blue
  } else if (now.hour() == 7 && now.minute() == 0 && now.second() < 2) {
    sendUp(); // 2 blue
  } else if (now.hour() == 7 && now.minute() == 30 && now.second() < 2) {
    sendUp(); // 3 blue
  } else if (now.hour() == 8 && now.minute() == 0 && now.second() < 2) {
    sendWhite(); // white on
  } else if (now.hour() == 8 && now.minute() == 1 && now.second() < 2) {
    sendUp(); // 4 white
  } else if (now.hour() == 8 && now.minute() == 30 && now.second() < 2) {
    sendUp(); // 5 white
  } else if (now.hour() == 9 && now.minute() == 0 && now.second() < 2) {
    sendUp(); // 6 white
  } else if (now.hour() == 9 && now.minute() == 30 && now.second() < 2) {
    sendUp(); // 7 white
  } else if (now.hour() == 9 && now.minute() == 31 && now.second() < 2) {
    sendUp(); // 8 white
  } else if (now.hour() == 19 && now.minute() == 30 && now.second() < 2) {
    sendDown(); // 7 white
  } else if (now.hour() == 19 && now.minute() == 31 && now.second() < 2) {
    sendDown(); // 6 white
  } else if (now.hour() == 20 && now.minute() == 0 && now.second() < 2) {
    sendDown(); // 5 white
  } else if (now.hour() == 20 && now.minute() == 30 && now.second() < 2) {
    sendDown(); // 4 white
  } else if (now.hour() == 21 && now.minute() == 0 && now.second() < 2) {
    sendDown(); // 3 white
  } else if (now.hour() == 21 && now.minute() == 1 && now.second() < 2) {
    sendBlue(); // 3 blue
  } else if (now.hour() == 21 && now.minute() == 30 && now.second() < 2) {
    sendDown(); // 2 blue
  } else if (now.hour() == 22 && now.minute() == 0 && now.second() < 2) {
    sendDown(); // 1 blue
  } else if (now.hour() == 22 && now.minute() == 30 && now.second() < 2) {
    sendOff(); // light off & 1 blue
  }

    if(now.dayOfTheWeek() == 1 && now.hour() == 8 && now.minute() < 2) {
      //startChange();
    }
}

Any help appreciated.

Many thanks
James

P.S - for anyone wanting to do a similar project now or in the future, these ir signals/commands are for the aquarium "bar" type lights with the normal "chinese" type remote that comes with almost all LED products. Please feel free to use them!

Not sure if this causes your problem but that condition will always be true.

It will be false when millis() is within 1000ms of rolling over, a bit over 49 days after the arduino is powered on/reset.

And same goes for your startChange function.

This is a function I’ll be using at a much later date, I’ve commented it out for now though so it doesn’t run

This is supposed to be a replacement for delay(). It should, in theory, do the same thing but without the downsides of using delay

In what way is it better than delay() ?

I need the loop to be able to continue checking the time and to my understanding, delay() temporarily breaks the loop until complete

And what does your function do ?

Your code, even if you correct it so that it waits for the time you require instead of 49 days, has the same problem as using delay().

Hang on… this case is only supposed to run for 1.5 seconds haha. I was reading a write up on alternative uses for delay and this is what I was presented with. I’m now thinking this is my issue!

Supposedly wait 1.5s but I’m now learning otherwise haha

It doesn't. At the moment that you start using while-loops or for-loops for that, your code will be a blocking code.

This would be a non-blocking delay replacement.

/*
  non-blocking delay
  In:
    delay duration in milliseconds
  Returns:
    true if delay is in progress, else false
 */
bool wait(uint32_t duration)
{
  // indicates if delay is in progress
  static bool delayInProgress = false;
  // start time of the delay
  static uint32_t startTime;
  
  if(delayInProgress == false)
  {
    startTime= millis();
    delayInProgress = true;
  }

  if(millis() - startTime >= duration)
  {
    delayInProgress = false;
  }

  return delayInProgress;
}

You will have to call this continuously, e.g. from loop().

void loop()
{
  bool delayComplete = wait(1000);
  if (delayComplete == false)
  {
    Serial.println("Delay completed");
  }

  // do somethinge else here
}
1 Like

Thank you! I’ll implement this in just a moment and run some tests. The reason delay would be an issue for me is in the future, when I end up using the redundant functions, it’ll have to constantly monitor 2 switches while running as it’s for a pump. So if I used delay and it couldn’t monitor the switches (float switches) the pumps could run dry

Before you go to the effort of implementing that, can you explain why you need to delay at all? The timing of the rest of your code is controlled by the RTC so that things start 1 minute or 30 minutes after the previous thing. Why do you need to wait/delay after a thing is done?

Sorry about the slow reply. I was getting strange behaviour when each function was executed. It was executed numerous times. Sometimes it would execute the functions 4 times, sometimes 3 etc. after I added a delay it only executed it once

You need to detect when the conditions become true rather than when they are true. See the StateChangeDetection example in the IDE

Using a delay (of any kind) is a fudge to get round the problem rather than fixing it

To help make @UKHeliBob 's suggestion easier, I have a suggestion. The RTClib library has built-in functions for comparing dates & times, so you can do things like:

DateTime now = rtc.now();
static DateTime before = DateTime(0);
DateTime time1 = DateTime(now.year(), now.month(), now.day(), 6, 30, 0); // date/time at 06:30 today
DateTime time2 = DateTime(now.year(), now.month(), now.day(), 7, 0, 0); // date/time at 07:00 today
...
if (now >= time1 && before < time1) {
    sendOn(); // light on & 1 blue
} else if (now >= time2 && before < time2) {
    sendUp(); // 2 blue
...
before = DateTime(now); // put this just before end of loop()

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.