Help! How to get an alarm (RTC DS3231) to trigger an LED at a specific time for 30 minutes (Sunrise alarm clock)

(First of all, I have to say I know or understand basically nothing about programming, this is my first project/attempt, so please take that into account when making questions or explanations about complex things (basically explain it using very simple things please)

Hi everyone, so I´m making a sunrise alarm to wake up in the mornings more easily for a college project that I hand in in like 1-1.5 week (I´ve been trying to get the code to work for like a month but nothing goes my way).

The steps I want to achieve are:

  1. How to fade between colors (simulate sunrise) [I think I already have this one, I found [this website that generates code for leds and its effects](LED Strip Effects generator) ]
  2. how to get the rtc working [After trying many libraries and not knowing how to use them I got this one that sets up the time to the laptop automatically, and has the alarm example sketch, which I think I know how to use ¡]
  3. lastly, how to trigger the led to turn on and off at a certain time everyday

The electronics that I´m using are:

  1. Arduino UNO (elegoo brand)
  2. adafruit neopixel ring 16 RGB LEDs
  3. DS3231 RTC
  • cables
  • the project is fed with two 5V split usbs, one at 1A and the other at 2.4A (for extra juice)
    ( I believe the wiring is fine because things work independently, I just have to get the code for the whole thing right)

SO, the thing is I have 2 codes, one that makes the LEDs fade (from the generator from before, but these are not the final colors, I´ll change them) AND the other code with the RTC stuff that I think triggers an alarm.
The question is: how can I mix both codes into one??

Here I attach both codes

  1. LEDs fading (set on pin PMW 6). I know the code is super long but that´s how it was generated and I don´t know enough to shorten it.
#include <Adafruit_NeoPixel.h>

class Strip
{
public:
  uint8_t   effect;
  uint8_t   effects;
  uint16_t  effStep;
  unsigned long effStart;
  Adafruit_NeoPixel strip;
  Strip(uint16_t leds, uint8_t pin, uint8_t toteffects, uint16_t striptype) : strip(leds, pin, striptype) {
    effect = -1;
    effects = toteffects;
    Reset();
  }
  void Reset(){
    effStep = 0;
    effect = (effect + 1) % effects;
    effStart = millis();
  }
};

struct Loop
{
  uint8_t currentChild;
  uint8_t childs;
  bool timeBased;
  uint16_t cycles;
  uint16_t currentTime;
  Loop(uint8_t totchilds, bool timebased, uint16_t tottime) {currentTime=0;currentChild=0;childs=totchilds;timeBased=timebased;cycles=tottime;}
};

Strip strip_0(16, 6, 16, NEO_GRB + NEO_KHZ800);
struct Loop strip0loop0(6, true, 30);

//[GLOBAL_VARIABLES]

void setup() {

  //Your setup here:

  strip_0.strip.begin();
}

void loop() {

  //Your code here:

  strips_loop();
}

void strips_loop() {
  if(strip0_loop0() & 0x01)
    strip_0.strip.show();
}

uint8_t strip0_loop0() {
  uint8_t ret = 0x00;
  switch(strip0loop0.currentChild) {
    case 0: 
           ret = strip0_loop0_eff0();break;
    case 1: 
           ret = strip0_loop0_eff1();break;
    case 2: 
           ret = strip0_loop0_eff2();break;
    case 3: 
           ret = strip0_loop0_eff3();break;
    case 4: 
           ret = strip0_loop0_eff4();break;
    case 5: 
           ret = strip0_loop0_eff5();break;
  }
  if(ret & 0x02) {
    ret &= 0xfd;
    if(strip0loop0.currentChild + 1 >= strip0loop0.childs) {
      strip0loop0.currentChild = 0;
      if(++strip0loop0.currentTime >= strip0loop0.cycles) {strip0loop0.currentTime = 0; ret |= 0x02;}
    }
    else {
      strip0loop0.currentChild++;
    }
  };
  return ret;
}

uint8_t strip0_loop0_eff0() {
    // Strip ID: 0 - Effect: Fade - LEDS: 16
    // Steps: 5 - Delay: 2000
    // Colors: 2 (255.0.0, 255.77.0)
    // Options: duration=10000, every=1, 
  if(millis() - strip_0.effStart < 2000 * (strip_0.effStep)) return 0x00;
  uint8_t r,g,b;
  double e;
  e = (strip_0.effStep * 2000) / (double)10000;
  r = ( e ) * 255 + 255 * ( 1.0 - e );
  g = ( e ) * 77 + 0 * ( 1.0 - e );
  b = ( e ) * 0 + 0 * ( 1.0 - e );
  for(uint16_t j=0;j<16;j++) {
    if((j % 1) == 0)
      strip_0.strip.setPixelColor(j, r, g, b);
    else
      strip_0.strip.setPixelColor(j, 0, 0, 0);
  }
  if(strip_0.effStep >= 5) {strip_0.Reset(); return 0x03; }
  else strip_0.effStep++;
  return 0x01;
}

uint8_t strip0_loop0_eff1() {
    // Strip ID: 0 - Effect: Fade - LEDS: 16
    // Steps: 5 - Delay: 2000
    // Colors: 2 (255.77.0, 255.103.0)
    // Options: duration=10000, every=1, 
  if(millis() - strip_0.effStart < 2000 * (strip_0.effStep)) return 0x00;
  uint8_t r,g,b;
  double e;
  e = (strip_0.effStep * 2000) / (double)10000;
  r = ( e ) * 255 + 255 * ( 1.0 - e );
  g = ( e ) * 103 + 77 * ( 1.0 - e );
  b = ( e ) * 0 + 0 * ( 1.0 - e );
  for(uint16_t j=0;j<16;j++) {
    if((j % 1) == 0)
      strip_0.strip.setPixelColor(j, r, g, b);
    else
      strip_0.strip.setPixelColor(j, 0, 0, 0);
  }
  if(strip_0.effStep >= 5) {strip_0.Reset(); return 0x03; }
  else strip_0.effStep++;
  return 0x01;
}

uint8_t strip0_loop0_eff2() {
    // Strip ID: 0 - Effect: Fade - LEDS: 16
    // Steps: 5 - Delay: 2000
    // Colors: 2 (255.103.0, 255.129.0)
    // Options: duration=10000, every=1, 
  if(millis() - strip_0.effStart < 2000 * (strip_0.effStep)) return 0x00;
  uint8_t r,g,b;
  double e;
  e = (strip_0.effStep * 2000) / (double)10000;
  r = ( e ) * 255 + 255 * ( 1.0 - e );
  g = ( e ) * 129 + 103 * ( 1.0 - e );
  b = ( e ) * 0 + 0 * ( 1.0 - e );
  for(uint16_t j=0;j<16;j++) {
    if((j % 1) == 0)
      strip_0.strip.setPixelColor(j, r, g, b);
    else
      strip_0.strip.setPixelColor(j, 0, 0, 0);
  }
  if(strip_0.effStep >= 5) {strip_0.Reset(); return 0x03; }
  else strip_0.effStep++;
  return 0x01;
}

uint8_t strip0_loop0_eff3() {
    // Strip ID: 0 - Effect: Fade - LEDS: 16
    // Steps: 5 - Delay: 2000
    // Colors: 2 (255.129.0, 255.167.0)
    // Options: duration=10000, every=1, 
  if(millis() - strip_0.effStart < 2000 * (strip_0.effStep)) return 0x00;
  uint8_t r,g,b;
  double e;
  e = (strip_0.effStep * 2000) / (double)10000;
  r = ( e ) * 255 + 255 * ( 1.0 - e );
  g = ( e ) * 167 + 129 * ( 1.0 - e );
  b = ( e ) * 0 + 0 * ( 1.0 - e );
  for(uint16_t j=0;j<16;j++) {
    if((j % 1) == 0)
      strip_0.strip.setPixelColor(j, r, g, b);
    else
      strip_0.strip.setPixelColor(j, 0, 0, 0);
  }
  if(strip_0.effStep >= 5) {strip_0.Reset(); return 0x03; }
  else strip_0.effStep++;
  return 0x01;
}

uint8_t strip0_loop0_eff4() {
    // Strip ID: 0 - Effect: Fade - LEDS: 16
    // Steps: 500 - Delay: 20
    // Colors: 2 (255.167.0, 54.194.237)
    // Options: duration=10000, every=1, 
  if(millis() - strip_0.effStart < 20 * (strip_0.effStep)) return 0x00;
  uint8_t r,g,b;
  double e;
  e = (strip_0.effStep * 20) / (double)10000;
  r = ( e ) * 54 + 255 * ( 1.0 - e );
  g = ( e ) * 194 + 167 * ( 1.0 - e );
  b = ( e ) * 237 + 0 * ( 1.0 - e );
  for(uint16_t j=0;j<16;j++) {
    if((j % 1) == 0)
      strip_0.strip.setPixelColor(j, r, g, b);
    else
      strip_0.strip.setPixelColor(j, 0, 0, 0);
  }
  if(strip_0.effStep >= 500) {strip_0.Reset(); return 0x03; }
  else strip_0.effStep++;
  return 0x01;
}

uint8_t strip0_loop0_eff5() {
    // Strip ID: 0 - Effect: Fade - LEDS: 16
    // Steps: 20 - Delay: 5
    // Colors: 2 (54.194.239, 255.255.255)
    // Options: duration=100, every=1, 
  if(millis() - strip_0.effStart < 5 * (strip_0.effStep)) return 0x00;
  uint8_t r,g,b;
  double e;
  e = (strip_0.effStep * 5) / (double)100;
  r = ( e ) * 255 + 54 * ( 1.0 - e );
  g = ( e ) * 255 + 194 * ( 1.0 - e );
  b = ( e ) * 255 + 239 * ( 1.0 - e );
  for(uint16_t j=0;j<16;j++) {
    if((j % 1) == 0)
      strip_0.strip.setPixelColor(j, r, g, b);
    else
      strip_0.strip.setPixelColor(j, 0, 0, 0);
  }
  if(strip_0.effStep >= 20) {strip_0.Reset(); return 0x03; }
  else strip_0.effStep++;
  return 0x01;
}


  1. RTC alarm
// during an alarm the INT pin of the RTC is pulled low
//
// this is handy for minimizing power consumption for sensor-like devices, 
// since they can be started up by this pin on given time intervals.

#include <Wire.h>
#include "ds3231.h"

#define BUFF_MAX 256

// time when to wake up
uint8_t wake_HOUR = 14;
uint8_t wake_MINUTE = 10;
uint8_t wake_SECOND = 39;

// how often to refresh the info on stdout (ms)
unsigned long prev = 5000, interval = 5000;

void set_alarm(void)
{

    // flags define what calendar component to be checked against the current time in order
    // to trigger the alarm - see datasheet
    // A1M1 (seconds) (0 to enable, 1 to disable)
    // A1M2 (minutes) (0 to enable, 1 to disable)
    // A1M3 (hour)    (0 to enable, 1 to disable) 
    // A1M4 (day)     (0 to enable, 1 to disable)
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
    uint8_t flags[5] = { 0, 0, 0, 1, 1 };

    // set Alarm1
    DS3231_set_a1(wake_SECOND, wake_MINUTE, wake_HOUR, 0, flags);

    // activate Alarm1
    DS3231_set_creg(DS3231_CONTROL_INTCN | DS3231_CONTROL_A1IE);
}

void setup()
{
    Serial.begin(9600);
    Wire.begin();
    DS3231_init(DS3231_CONTROL_INTCN);
    DS3231_clear_a1f();
    set_alarm();
}

void loop()
{
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

    // once a while show what is going on
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3231_get(&t);

        // display current time
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
        Serial.println(buff);

        // display a1 debug info
        DS3231_get_a1(&buff[0], 59);
        Serial.println(buff);

        if (DS3231_triggered_a1()) {
            // INT has been pulled low
            Serial.println(" -> alarm1 has been triggered");
            // clear a1 alarm flag and let INT go into hi-z
            DS3231_clear_a1f();
        }
        prev = now;
    }
}

Any suggestions, explanations, edits and help will be greatly appreciated!!!
(Also, this is way too much and don´t have time for it but in the future I´d like to also make it a sunset lamp, basically the same function but only changes adding a second alarm in the afternoon and changing the colors)

At a glance, those two sketches are written in a manner that will make combining them relatively easy.

google

 arduino combine two sketches

and look around for something you can get your teeth into.

Other than just doing it for you, it will take a little work.

a7

I cant believe i didn´t think of doing that! thanks!

(I´ll be back with updates :blush:)

OK.

I made a Frankensketch, the two sketches do not conflict at the first steps.

The LED sketch by itself doesn't seem too lively. Do you have that doing anything interesting at all? I'll try to see if I did something to make it tots underwhelming.

I just renamed the LED setup function to setupLED() and the LED loop function to loopLED()

then added a call to setupLED() in the one true setup function at the end
and a call to loopLED() in the one true loop function at the end.

I don't have LEDs and an RTC hooked up, but it compiles so will be doing something, perhaps something plausible and close to what you need to do to proceed with the logic that will run the LEDs only at sunset or whatever.

Off to the beach for now, CU.

a7

Thank you so much a7!! It works!! You have no idea how much you´ve helped me, you literally saved my project. Thank you so so so much for your help and your time :smiling_face_with_three_hearts: :hugs:
Hope you have many more great sunny beach days to come!

Thanks once again,
Marta <3

Yay!

I’m risking getting sand imbedded in my iPad, but I wonder if you mean you have also gone on to make the LEDs function at the time of the alarm.

And if you’d like to post the whole thing so others might see and admidpre your work, feel free.

If you did get the sunset timing, maybe you also were able to get sunrise?

I guess the LEDs move really slowly - I cranked down a few magic numbers so it played a bit faster just so I could see it working.

a7

Hahahahh be careful with the sand! (tip: ziplock bags work amazing for that, see-through, touchscreen and water/sandproof lol)

Exactly, i got the leds to turn on at the time i wanted!
I still have to make some changes for the exact colors, and timing and all that, but the big task was getting it to work, now only the easy part is left, making it perfect!

The main goal was to simulate the sunrise to get it to function as a sunrise alarm clock at whatever time you choose to wake up at (which scientists and studies say is so much better for our bodies (circadian rhythm) to wake up to instead of a blaring alarm).

But now that I have the basis of it, I´m gonna try to also get it to recreate sunset with very warm and orange colors in the evening, to help us wind down.

I guess the LEDs move really slowly - I cranked down a few magic numbers so it played a bit faster just so I could see it working.

It´s supposed to be reeeaally slow, even slower than it actually is now lol, I´m gonna make it last about 30 minutes total, from dark to complete brightness.

Of course! when I have it all finished and ready I´ll upload it here for everyone to feel free to use!