The Planted Tank Forum banner

Another Arduino LED light schedule sketch

29791 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 47 Posts

· Registered
113 Posts
Discussion Starter · #8 ·
You're welcome! Might as well share in case someone else can use it!

@danielt: If you make code to emulate a 24H clock and set start time to be the time of compilation, you just have to rebuild and upload to the arduino to set time once in a while. Could work as long as the power is stable!

· Registered
113 Posts
Discussion Starter · #16 · (Edited)
Glad to hear someone is using, or at least attempting to use, this!
If you can send me a copy of your code, I'd be glad to look it over. The original has not been tested with more than 2 channels, so bugs are by no means impossible.

By the way:
I have been doing some re-factoring to the code to make it more user friendly, but have not had a chance to test it yet.

· Registered
113 Posts
Discussion Starter · #20 ·
First of all, you're welcome!
The reason your schedule does not work, is that you can't define something after 24:00. If the schedule does not end in 24, it will assume lights are off after last 'valid' entry.
What you have to do is move the last 2 entries to the top like this:
(0, 0, 1)
(0, 59, 1)
(1, 0, 0)
(5, 59, 0)
and add (24, 0, 1) to the end. That should to the trick! :)

· Registered
113 Posts
Discussion Starter · #26 ·
I have actually been considering adding this, or at least a slightly simplified version of it for some time.
I have been doing some more rewrites to the project in order to simplify usage even more - and will probably add 'perceived linear' fading as an option for each channel. This code is not yet done, but testing is under way. Thanks for doing some of the numbers!

· Registered
113 Posts
Discussion Starter · #28 · (Edited)
You're welcome, happy to see someone is still using it :)
Nice interface by the way!
Anyway, on to what you are trying to do:

Passing a variable that way just passes the value of the variable at that given time.
To change the schedule after initialization you have to change the value directly in the matrix like this:

lightMatrix[Channel][Period][INTENSITY] = Variable;

Assuming you want to change period 2 in the first channel:
lightMatrix[0][1][INTENSITY] = White_Max;
Remember that array indexes start at 0, otherwise results will be rather odd...

EDIT: This must be done every time the variable is changed! (wasn't sure this came across in the original post)

The downside of doing what you do now - any changes will be lost at reset unless you have made some considerable changes to the sketch.
This will be remedied by an upcoming API edition (currently testing) but it will most likely be released as a separate sketch since it has very little in common with the current version..

· Registered
113 Posts
Discussion Starter · #33 ·
Looks like an interesting solution!
By now I am really just fiddling with the serial communication between Arduino and Python client, the light scheduling is loosely based on my previous version of this sketch. It takes a while to get anywhere since I am learning Python in the process, but that was sort of the point.
The main issue is a lack of time to spend on the project! :icon_conf

· Registered
113 Posts
Discussion Starter · #36 ·
Actually, to do this you will have to make a few changes.
First of all, you will have to move the initialization of the matrix into a function so you can call it as many times as you want. If you do that, then you can keep it like you described above:

int lightMatrix[CHANNELS][MAXPERIODS][5];

void UpdateMatrix() {
lightMatrix = {
{0, 0, (RiseHour), (RiseMin+2), 0},
{(RiseHour), (RiseMin+10), (RiseHour+12), (RiseMin+7), RBlue_max}, ////RBlue_Ch1
{(RiseHour+12), (RiseMin+12), 24, 0, 0}

Keep in mind that you have to have the definition outside the function like above!

Any time one of the variables are changed, you reinitialize the entire matrix in the easiest possible way:


This makes sure everything is always updated, and you have to do as little work as possible!
Hope this helps, always happy to help :)

· Registered
113 Posts
Discussion Starter · #41 ·
Well they are like that sometimes, a lot of the more active people there assume you have quite a bit of experience in both electronics and programming.
Declaration: the 'creation' of the array ( int lightMatrix[x][x][x]; )
Initialization: creating the contents of the array ( lightMatrix = {{x},{x}}; )

But anyway, I have made a very basic sketch to show you how I meant it:
The variable names etc. are not accurate, but the idea stands.
And it works - just not in the Arduino IDE (programming environment). Arduino has quite at few quirks like that, and I keep forgetting them. I usually use Codebender because it is more 'friendly'!

· Registered
113 Posts
Discussion Starter · #42 · (Edited)
If you want to make it 'Arduino IDE Compatible' you will have to replace the contents of the UpdateMatrix() function with one of these for each channel:

// Channel 1:
sunMatrix[0][0][Sunrise_Hr] = 0;
sunMatrix[0][0][Sunrise_Min] = 0;
sunMatrix[0][0][Sunset_Hr] = RiseHour;
sunMatrix[0][0][Sunset_Min] = RiseMin + 2;
sunMatrix[0][0][INTENSITY] = 0;
sunMatrix[0][1][Sunrise_Hr] = RiseHour;
sunMatrix[0][1][Sunrise_Min] = RiseMin + 10;
sunMatrix[0][1][Sunset_Hr] = RiseHour + 12;
sunMatrix[0][1][Sunset_Min] = RiseMin + 7;
sunMatrix[0][1][INTENSITY] = RBlue_max;
sunMatrix[0][2][Sunrise_Hr] = RiseHour + 12;
sunMatrix[0][2][Sunrise_Min] = RiseMin + 12;
sunMatrix[0][2][Sunset_Hr] = 24;
sunMatrix[0][2][Sunset_Min] = 0;
sunMatrix[0][2][INTENSITY] = 0;

It is a somewhat more tedious process!

· Registered
113 Posts
Discussion Starter · #46 ·
Just read through your build thread - damn, suddenly I'm really appreciating dealing with a small low-tech planted tank! No PH probes with grounding issues, no massive LED driver arrays to burn. Oh, and no touchscreen!
Learning Python and using Qt for GUI is somewhat more forgiving.
Congratulations on getting this far, I'm confident you will be able to complete it at some point :)

// Benjamin
1 - 20 of 47 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.