The Planted Tank Forum banner

Another Arduino LED light schedule sketch

29833 Views 109 Replies 23 Participants Last post by  boxhead1990
Here is the Arduino code I use to control the schedule of my LED lights.

Back story:
I've been redoing my 14G low-tech and wanted to try out LED, so I ordered a 10W ebay-special and planned to hook it up to an Arduino I had lying around. While waiting for it to arrive, I looked around for examples of how others had handled the software side of things. None of the code I found seemed to fit my needs.
I realize a lot of people have done the same, but I wanted something that allowed for individual schedules for any number of channels, including siesta and different length sunrise/sunset.

So in the end, I wrote my own code to control the lights.

Some things that need to be addressed before looking at the code:

1: This is not a complete sketch to control aquarium lights!
While it would work on a setup identical to mine, it wouldn't on much else. The code is meant as a helping hand for those that are not overly comfortable with programming, and find handling more complicated schedules difficult. I have removed all but the essentials in this sketch.

2: This has nothing to do with your hardware!
Ok, that may not be strictly true. But my point is: There are a lot of great guides out there regarding the hardware side of things, I will only be dealing with the software. This is the part that I have found relatively little of on these forums, whereas the hardware gurus seem very active. I provide a way to control the PWM signal, the rest is up to you.

Now, let's get started! :)

- Any number of individual channels (limited by you Arduino's number of PWM pins)
- Pretty much any light schedule that repeats every 24 hours
- Suitable for RGB lights
- Reasonably smooth fading w. a resolution of 1/255 updated every second

Hardware requirements:
- Arduino (Uno in my case)
- RTC module (DS1307 is used in the example)
- PWM outputs wired CORRECTLY to your LED drivers

Other requirements:
- Some (not necessarily a lot) proficiency with Arduino coding

There are a lot of comments in the code, and I hope it is not too difficult to understand.

I have made a considerable rewrite, making it much easier to add more channels.
Concept explained:

A lot of this is explained in the code, but I'll try to summarize it here.
To define a schedule for a channel, you set a series of 'Points'. This should be considered a chart, where the line represents the intensity of light over a 24 hour period.
Intensity is a value in the range 0-255. 0 = OFF, 255 = Fully ON

To make lights turn on in the morning with a 30 minute 'sunrise', you would add 2 Points:
08:00 - Intensity = 0
08:30 - Intensity = 255

From 08:00 to 08:30 channel is going from 0-255

It's pretty simple, really.

:sleep: Enough rambling, here is the code. Let me know if you have questions or find it useful!

Link to source:
New location of source:
  • Like
Reactions: litzel
1 - 20 of 26 Posts

· Registered
26 Posts

I was hoping you can help me a bit with your code. I came across this thread searching for sunrise/sunset code for my marine build.

I am new to Arduino as well as coding, but I usually can dissect it and figure out what does what.

I used this code with the only deviation being I have 9 CHANNELS and 3 MAXPERIODS.

The code compiles, however the results are not what I expect. I vaguely understand most of the code except for:

int lightMatrix [CHANNELS][MAXPERIODS][5] =

Channels index the array 9
Maxperiods index the array 3

5 = ? what does the 5 index in this statement?

I think that this is where my issue might be.

Thanks for the help, and the code!

· Registered
26 Posts
Just a thought that might be my answer...

The function is only finding 2 channels when I have 9. Now, I did not change the code and left it as it was originally written...which was for a 2 channel set-up.

I am now thinking I will need to expand upon the function in order to find all channels and periods.
Does that sound like I may be on the right track??

Thanks for anything.

· Registered
26 Posts
Thanks for taking the time man...

Yes I've had that set up from the beginning.

#define CHANNELS 9
#define MAXPERIODS 3

Also changed

int lightValue [CHANNELS] = {0,0,0,0,0,0,0,0,0};

So, those are in place as well as my 9 channels in the lightMatrix.
The code is commented well, and easy enough to adjust to my set up.
That's why I'm stumped as to why it's not working. It compiles fine. Just not getting desired results.

I think I have narrowed it down to the void function. The Intensity value is not being picked up by the lightValue array.
Still hunting...
I removed the pinMode call in setup...I don't think it is necessary as the code uses analogWrite and the LEDs are on pwm pins, but I can try adding that back.

I can also try changing "#define" to "const" drawback with using #define is that it replaces anything with the word CHANNELS with the 9 value. That might be my bug, but I doubt it.
Gut is still telling me I have an issue in that void function somewhere. It's just not finding what period it is.

· Registered
26 Posts's me again. I never got back to thank you for this code, or to let you know I got it up and running without any issues across 9 channels with 3 periods.

I've been running it as my default lighting schedule since the end of May. It's still the older version, but I don't have any issues with it. And I really don't plan to change it.

My question this time is about the timing/intensity matrix.

Is it possible to use a variable within it? Specifically the Intensity?

Current Example:

{0, 0, 9, 45, 0},
{10, 45, 16, 55, 90}, ////Wht_Ch1
{17, 55, 24, 0, 0}

I am trying to pass a variable(without success) from a touch "dimming/blending" screen so I will be able to change it without changing the sketch every time.

Something like this:

{0, 0, 9, 45, 0},
{10, 45, 16, 55, White_Max}, ////Wht_Ch1
{17, 55, 24, 0, 0}

I figured it would be as simple as passing the variable value into the matrix like that, but it has not. I've tried various ways and variables with out success.

Will the schedule only accept a number between 0 and 255?

Thanks for any help or ideas!

EDIT: here is a photo to try and make clear what I am talking about.

This is a control screen where I can currently dim and blend each of my LED colors.
I would like to be able to set maximum value to the lighting schedule from here.


· Registered
26 Posts
Thanks so much for the quick response, and compliment.

Makes perfect sense to me now. You know...sometimes I get in a rut thinking a specific solution that I can't get by that, and I just need a slap in the head to see things another way.

I'm going to give it a go.

I'm also thinking that I might be able to solve the reset/power loss issue by saving the max lighting value in EEPROM or SD card when the user pushes "enter" on my dimming screen. But, I'll cross that bridge when I get to it.

Another bridge down the road is setting the start time. The total period would be fixed(easier math). Now that I see how I have to designate the variable I hope I can bang that code out too.

Thanks again!!

· Registered
26 Posts
Thanks Benjaf!

I was able to code this quite quickly with your help. EEPROM and all.

I am now able to set the Maximum lighting value from the TFT screen, and I won't lose settings if I lose power, or reset the board.

Now...on to being able to set/alter the start time from the screen.

· Registered
26 Posts
Hi Benjaf...I'm here to bother you again.

I am now trying to incorporate being able to set a start time from the GUI.

How I am trying to code it is similar to how you showed me to add a variable to the intensity.

For every channel I have called it out like this:

sunMatrix[0][0][Sunset_Hr] = RiseHour;
sunMatrix[0][0][Sunset_Min] = RiseMin;
sunMatrix[0][1][Sunrise_Hr] = RiseHour;
sunMatrix[0][1][Sunrise_Min] = RiseMin;
sunMatrix[0][1][Sunset_Hr] = RiseHour;
sunMatrix[0][1][Sunset_Min] = RiseMin;
sunMatrix[0][2][Sunrise_Hr] = RiseHour;
sunMatrix[0][2][Sunrise_Min] = RiseMin;

And then in the matrix array I am trying something like this:

{0, 0, (RiseHour), (RiseMin+2), 0},
{(RiseHour), (RiseMin+10), (RiseHour+12), (RiseMin+7), RBlue_max}, ////RBlue_Ch1
{(RiseHour+12), (RiseMin+12), 24, 0, 0}
{0, 0, (RiseHour), (RiseMin+8), 0},
{(RiseHour), (RiseMin+14), (RiseHour+12), (RiseMin+2), Blue_max}, ////Blue_Ch1
{(RiseHour+12), (RiseMin+8), 24, 0, 0}

To avoid timing conflicts between Hours and to make sure minutes do not increase above 59.

I am unsure if the Update function is able to pick up which period the schedule is in, or if I can't use the math like I am?

I am hoping you have a suggestion for me.


· Registered
26 Posts
I am 80% sure I can't do the math within the matrix. I have changed the variable naming to:

sunMatrix[CHANNELS][0][Sunset_Hr] = RiseHour;
sunMatrix[CHANNELS][0][Sunset_Min] = RiseMin;
sunMatrix[CHANNELS][1][Sunrise_Hr] = RiseHour;
sunMatrix[CHANNELS][1][Sunrise_Min] = RiseMin;
sunMatrix[CHANNELS][1][Sunset_Hr] = RiseHour;
sunMatrix[CHANNELS][1][Sunset_Min] = RiseMin;
sunMatrix[CHANNELS][2][Sunrise_Hr] = RiseHour;
sunMatrix[CHANNELS][2][Sunrise_Min] = RiseMin;

And I am getting the Blue's....whether they ramp up/down I am unsure. But, I am guessing the white's are not coming on because I have them starting 2 hours after the blues which I designated RiseHour+2 in the matrix.

Getting closer though...

· Registered
26 Posts
Thanks for the help!!

I am having an issue though. It's probably due to my lack of experience. A year ago I didn't even know what Arduino was, and never had any experience writing code until 10 months ago.
So, I don't understand the compilation error I am receiving. What it means that is. My lack of vocabulary with all of this.

I made the adjustments you recommended, but it won't compile. It is giving me an error on this line


"expected primary expression before {"

I'm unsure what this means...I kind of hunt and peck a few things, but no success.

· Registered
26 Posts
I'm checking that out.

Something odd happening. I woke up in the middle of the night and all the blue LEDs were on?
This morning I turned on the LEDs to find all channels on??

Maybe Sunday I'll have time to actually sit and sift through all the code.
At least I know something is happening. Lol!

· Registered
26 Posts
Hi Benjaf,

I've been wrestling around with code, and I don't think I am any closer.

I posted the code on the Arduuino forum seeking help, and those guys are so f'n cryptic with their direction. The best I got was that "you can't initialize an array in that way"
"Your Declaration is correct, but your initialization is not".

Why can't they just show me??

· Registered
26 Posts
Awesome! Awesome! Awesome!

Thank you so much for taking the time!!

One of the comments from the Arduino forum (I was trying not to bother you too much) stated I couldn't shortcut it the way I was trying to do, and I would have to initialize all the elements of the array.

But, I still had hope....;)

It is a tedious process, but I'm too far in to turn back now.

Thank you so much. You have full credit in my code, and shout outs on my You Tube channel and Build thread.

· Registered
26 Posts
Hi Benjaf...yep it's me again.

Just having an issue I can't seem to sort, and was hoping you could nudge me in the right direction.

Long story short I am having difficulties with the ramping up of the LEDs. This started happening when I had to undo your nice tidy array in order to integrate my UI.
What is happening is the increasing intensity of the LEDs has become jerky. It ramps up in steps rather than the nice smooth increase from 0 to the max LED vlaue.
Just a rough example...the LEDs come on at about 20%, 40% a few seconds later, and so on. Noticeable increase to the eye.

I've been trying to figure out why this is happening, and correct the issue for some time now, and finally had to bother you yet again.

Funny thing is nothing else is effected. Timing schedules for all the periods is correct with no issues, and the fading from max led value to 0 is still silky smooth.

Do you have any idea what might be causing this?
I could send my code if you need.

Thanks again!

· Registered
26 Posts
I know..sorry.

The light schedule is grouped pretty close near the top of the sketch.

I do a function call UpdatateMatrix();
In the LED navigation code at the 'enter' buttons, and in the PrintMoonPhase();

I hope that narrows it down so you don't have to go through every line of code.

No hurry. Please look at you leisure. The scheduler is working. I'm just annoyed because I know how it used to work before I messed with it.

I appreciate the time.

· Registered
26 Posts
Thanks for taking the time to look!

Too bad there is not an obvious answer. However, you did give me an idea as to a possible solution.
I did not know about the bug in the original code about starting from a zero value.
I tried to get clever by integrating Lunar Illumination into the lighting period of the string of LEDs I'm using. (Moonmax > UVmax > Moonmax) instead of (0 > UVmax > 0)

This string happens to be the starting point of the whole schedule.

Maybe this is the answer??

Thanks for the nudge! :)

· Registered
26 Posts
Hi Benjaf,

Thanks for the code update, and the nudge in the right direction!

The new code compiled without issue.

Here's how you helped:
"How often is UpdateSun() method called when the stepping occurs?"
That's what got me thinking....I know eveyone could smell the smoke. :)

Even though it was not the UpdateSun() function call, but the UpdateMatrix() call. Obviously I was wrong in my thinking of how the function/calculation worked. I thought I could UpdateMatrix() before the loop, and it would hold those values for the UpdateSun() function which was in the main loop.

However, both have to be in the main loop to get my silky smooth ramping back...

  UpdateSun(GetSeconds(Hours, Minutes, Seconds));
I don't know why I had it in my head I needed to keep it out of the main loop?

But, back in business!!!!

Thank you sir!!!

· Registered
26 Posts
Alas were right.

I'm going to have to hook it up to the serial port and try to trouble shoot it.

I changed it back to the old calculation. The new calculation with "progress" would start the lighting, but would not fade at the scheduled time.

I also found it steps on the fade as well. It just isn't as noticeable because it does fade smoothly to a point, but once it reaches that point it steps 3 or 4 times down to zero.
I can only assume this is what's happening on the ramping. It probably steps 4 times to a certain value, and then smoothed out the rest of the way.

My new thought is perhaps the "float" may be taking longer to calculate due to breaking it out of the array???

Still not sure. Bottom line the code is not happy....

The search continues. I will let you know if I discover the issue.
1 - 20 of 26 Posts
This is an older thread, you may not receive a response, and could be reviving an old thread. Please consider creating a new thread.