The Planted Tank Forum banner

Improved Arduino LED lighting code

109K views 223 replies 51 participants last post by  Lingwendil 
#1 · (Edited)
I wasn't happy with any existing Arduino code for LED control so I wrote my own. I think it's quite nice though it needs polishing and probably some features added. It does light timing, sunrise/sunset fading and all that jazz.

Some improvements over existing code:

  • Shorter and simpler
  • Accurately set clock from a script on your PC. You don't need to modify any code or upload any sketches!
  • Much, much smoother dimming, especially at the low end (due to a combination of higher resolution PWM output and every-second dimming adjustment instead of every-minute).
  • Higher resolution PWM also means you can dim your LEDs down to a lower intensity than before if your driver is capable. I've found I can dim my LEDs down far enough to be used as moonlights.
  • Flexible timing logic. You can do anything you want (with minor modifications) so long as it's on a 24hr cycle.
There are also some limitations:

  • Your Arduino needs to have either a DS3231(eg: ChronoDot) or DS1307 Real Time Clock chip connected via I2C (because I have one of those). These are probably the two most common RTC chips.
  • It only provides 2 PWM outputs (because I only have 2 LED strings). Of course you can modulate as many strings as you want from a single PWM signal but they'll modulate in unison.
  • It should work with the Arduino Duimilanove/Uno and probably any other micro-controller that uses the Atmega168/328 chip. In particular it will not work as-is with the Arduino Mega due to a difference in the onboard timers.
  • It depends on a few libraries but I've bundled them up in a download link below.
  • Only compiles with versions 0022/0023 of the Arduino IDE, not version 1.0 (yet!)

It works great for me. I'd love feedback, error reports, suggestions, free beers, etc. Post in the thread or PM me.

I hope this will be useful to people! :thumbsup:

Get the code:
Latest version
Libraries bundle

Installing libraries:
The libraries that don't come with the Arduino environment by default are bundled in the zipfile above. Just extract that zip into the libraries folder inside your sketchbook folder and then restart the Arduino IDE. If libraries doesn't exist, create it first.

Until I get around to writing documentation just post or PM installation questions/issues and I'll try to help.

Latest Version:
05/2014 -- O2surplus has made some significant improvements to this code, adding LCD and temp sensor support, please see his posts later on in this thread for the code.
 
See less See more
#3 ·
What does the RTC circuit that you have look like? Is it a breakout board? Mine is integrated into my driver because I built it myself, but the principle is the same either way. You just need to power and ground it somehow (5V and GND from the Arduino) and then connect the data pins (SCL and SDA) from the chip to the Arduino. On most Arduino boards (including mine) SDA (data line) is on analog pin 4, and SCL (clock line) is on analog pin 5.

Here's a tutorial that might be applicable Adafruit also sells an RTC breakout board kit with everything you need except wires for under $10. I don't have one but I modeled my RTC circuit after theirs and it works great, so might be an option if you want to add an RTC to an existing setup.
 
#4 ·
I'll give it a try! Took me nearly an hour to hunt down and install the extra libraries, but I got the code to compile without issue. I'll hook up the Dueminlanove this weekend and see what happens. Good job sink- Now if you could only show me how to integrate that coding into the controller that I built, that would be awesome!
 
#5 ·
You are welcome. Glad to know it compiles. Once past that step it should run fine. Please let me know what you think! As an aside, you'll probably want to change a couple of variables in the code to match your own needs regarding sunrise/sunset time and in particular how bright you want daylight to be because my default may be quite dim for others. The lines are all towards the beginning of the file and are commented pretty well as to what they do and possible values. I'll write up more detailed instructions when I have some time.

I'd love to make a bundle with the required libraries but I'm not sure if the licenses permit it. In the meantime I'll edit the original post with links to the needed libraries. Thanks for pointing out that task might not be trivial.

I'm willing to help with any driver integration you need. Do you mean the RTC or the code?
 
#6 ·
Sink,

I found the TimerOne and Time libraries at Arduino.cc, so I think you could zip them up together with your code and be good to go. There's one thing you need to fix though, your code cannot be unzipped and moved directly into the Arduino IDE. The IDE will not recognize the folder until it is renamed. I had to change the name of the folder to "akl_tank_control" and the file name to "akl_tank_control.pde" and then it would open and compile properly. This is detail that may cause trouble for people who are not familiar with some of the Arduino IDE's file naming requirements.

I'll have to shoot you a PM with the coding for my controller. It works great as is, but I like the fact that your code updates the PWM every second, instead of once per minute. I've got the hardware side of things nailed down but I could use your help to improve the software.

Here's a photo of the controller board- without the 16x2 LCD on top.



I've got enough boot loaded ATMEGA328's to build 30 more, and a newer design that supports the MeanWell ELN-P's as well as my Cat4101's.

Maybe a trade- Chips or a completed controller for software?
 
#7 ·
I found the TimerOne and Time libraries at Arduino.cc, so I think you could zip them up together with your code and be good to go. There's one thing you need to fix though, your code cannot be unzipped and moved directly into the Arduino IDE. The IDE will not recognize the folder until it is renamed. I had to change the name of the folder to "akl_tank_control" and the file name to "akl_tank_control.pde" and then it would open and compile properly. This is detail that may cause trouble for people who are not familiar with some of the Arduino IDE's file naming requirements.
Clearly I too am unfamiliar with the IDE's file naming requirements :icon_smil. I just uploaded a version that should be better in that regard. I also bundled the libraries up and added a link above. Thanks much for the input.

I'll have to shoot you a PM with the coding for my controller. It works great as is, but I like the fact that your code updates the PWM every second, instead of once per minute. I've got the hardware side of things nailed down but I could use your help to improve the software.

I've got enough boot loaded ATMEGA328's to build 30 more, and a newer design that supports the MeanWell ELN-P's as well as my Cat4101's
Driver looks great! I'd love to help on the software end.

Maybe a trade- Chips or a completed controller for software?
Sounds very reasonable. I do love the barter system. I'll shoot you an email :icon_smil
 
#8 ·
Sink,

I loaded the code into my Duemilanove and connected it up to my Cat4101's, Looks good so far. I made some changes to the code to run the leds at max (1023) all day,and set the night time level to a minimum (20) for moon lighting at night. I think a pwm value of 20 works out to be a hair less than 2%. I should know by 10pm whether or not the leds will continue to run at such a low setting.
I did notice that there's something amiss with the time display in the serial monitor. The time displayed is 1 hour less than the correct time on my PC. Any idea what's causing that? Must be something to do with the DS1307 and daylight savings time?
 
#9 ·
Sink,

I loaded the code into my Duemilanove and connected it up to my Cat4101's, Looks good so far. I made some changes to the code to run the leds at max (1023) all day,and set the night time level to a minimum (20) for moon lighting at night. I think a pwm value of 20 works out to be a hair less than 2%. I should know by 10pm whether or not the leds will continue to run at such a low setting.
Your LEDs should run all the way down to a setting of 1 without any problems. The CAT4101s OTOH don't seem to have particularly precise dimming below about 1% though it will still work. I've lowered the default PWM frequency from 500Hz to 150Hz in an effort to improve that so I'm curious to see how your results are.

I did notice that there's something amiss with the time display in the serial monitor. The time displayed is 1 hour less than the correct time on my PC. Any idea what's causing that? Must be something to do with the DS1307 and daylight savings time?
That's an interesting one. The DS1307 is completely naive of timezones so the issue would be with the time your computer is putting out somehow not compensating for DST. I presume you set the clock using the timerset.pde sketch?
 
#13 ·
Well, we'll have to see what "coding magic" "Sink" can pull off! LOL Then I'll show you how to reprogram the controller. He's got a day job- so let's not rush him.LOL
 
#14 ·
Sink,

I uploaded the TimeSet code.....Worked perfectly. I also uploaded the TankControl code again after lowering the minimum PWM state to "5" and stting the fade duration to 1 hour. All I can say is "WOW!" The dimming is completely linear, seamless, and totally natural looking. That has got to be the best Dimming Simulation that I've ever seen! I now have 90 little "moon lights" over my tank. Too cool! Thanks so much for creating and posting the codes!:biggrin::proud:
 
#16 ·
I'd like to thank the Academy...:icon_wink I'm glad it works for you.

Just kidding. You are welcome and thanks for testing. Cleaning this up and making it available to others is the least I can do in return for all of the knowledge I've shamelessly mined from this forum so far.
 
#18 ·
Sink made it so easy " a cave man could do it". He wrote a program that pulls the current time from your computer and transfers it directly to the arduino.

Look for the TimeSet sketch is his code bundle.
 
#20 ·
Strictly speaking an LCD would only display time, you can't actually set it using it :icon_mrgr. For that you need some buttons.

Anyway I thought about adding a display and/or buttons to my controller but ultimately I didn't see the relatively minor value being worth the added complexity. I'm very much a minimalist. You shouldn't have to set the clock very often at all--that's largely the point of the RTC--and tweaking something is a 2 minute job with a laptop.

In some way I intend this to be demo code and to be as easily adaptable as possible to different setups. To that end I don't make any assumptions about what hardware/driver/controller you have beyond there being an Arduino and a DS1307.
 
#23 ·
Okay - Justin AKA "XM-L Pioneer". What other ideas do you have? I've got my soldering iron warmed up. LOL:biggrin:
 
#28 ·
Aaron / Sink -

I'm getting closer to my control box build (seriously - I almost have my plumbing done, electronics in the near future finally!).

How would I go about re-programming my unit? Can I ship the Typhoon back to you Aaron, or is there a USB AVR programmer solution?

If you are taking requests for new projects - I'd be interested in some simple timer code to make an autodoser work a 4-relay module that they sell on Ebay. I have a arduino duemilanove and RTC available to dedicate to the unit. If there isn't code out there already, I figured I'd give it a shot programming myself. Course the last time I programmed was in 1997!
 
#29 ·
Hey Tony,

Sink is still working on the code. He's going to send me the new code for testing once he's finished. I'll test the code out and report back to him with any bugs, or changes that need to be addressed. When we're confident that the code will work, he or I will post it up so that you guys can get your hands on it. The only things that you'll need to reprogram the controller will be a USB/ FTDI adapter ($15) and the arduino software (free). Here's a photo of the FTDI adapter connected to the controller.
 

Attachments

#30 ·
Hi. Haven't forgotten about you guys, honest. I'm traveling for work stuff. I did much of the code rewrite already (made some great progress while bored waiting for my connecting flight at JFK) but I need to debug it on some actual hardware before I let others test it. O2surplus, I'll shoot you an email next week. Hopefully we can get a controller sent over here so it arrives soon after I get home and I can get you guys some improved firmware to play with.

As an aside, I figured out before I left that while the DS1307 on my homemade controller is very accurate on battery (less than 2s/day drift) it's wildly inaccurate when the controller is powered up. I guess there is some interference happening from the driver circuit due to me not knowing how to design the board properly. This is unique to my board and has nothing to do with the code.

Anyway, the easiest fix is to pick up a tiny ChronoDot RTC board that can be plugged right into the Arduino. It a significantly more accurate RTC using a different chip (DS3231). The end result is that you have one of these (or were thinking about getting one) my code will support it very shortly.
 
#32 ·
I've done quite a bit of tinkering with the Typhon code, but it's a lower priority than the mountain of stuff that will get me fired if I don't do it ;). Inexcusable delay though, and I apologize about that. I'll do my best to get it done.

I do have an improved version of my simpler code (see first post in this thread) that I wrote a few months ago. It supports the ChronoDot RTC (the DS3231) and now you can set the time to the second from a PC without having to reflash the Arduino. Much cleaner than the previous way. I didn't post it because it isn't very documented yet, but it does work fine. If anybody wants this, let me know and I'll clean it up.
 
#34 ·
Okay, I've posted the latest version of my code (not the Typhon stuff yet, sigh) on bitbucket. I also updated the libraries.zip archive to include the library for the ChronoDot. The links in the first post point to the latest version of the code.

This one works a bit differently. Once you've uploaded the tank-control sketch to the Arduino, you can get the time/set the time using a Python script (client.py) you run on your PC while connected to the Arduino over USB. You'll need to change the "PORT" line in that script to match your system. You also need to install the "serial" library for Python for your system. Once that is done, you run the script and enter "sync" at the prompt to set the Arduino time from your PC system time. You can also enter "time" to see what the Arduino thinks the current time is. Finally, either "quit" or "exit" will quit the program.

It needs to be documented better and I'll get around to that eventually, but if you have any problems just PM me and I can help.
 
#36 ·
Sink,

The errors I was getting were while using the newest version of the Arduino IDE (1.0)

After finding the errors I PMed you about I looked at them in C++ and not knowing enough to fix them I decided to try them in the .0023 beta of the arduino IDE and it uploaded fine.

I'm working on the remaining steps, but just wanted to post this in case anyone had the same problem. It seems the 1.0 checks all included codes, while the beta did not?
 
#38 ·
Welcome to the exciting world of Arduino 1.0, which broke compatibility with nearly every existing library for no particularly good reason. The internet is littered with posts like this. In your case the included Time library is incompatible with 1.0. Probably others are too, but it didn't get far enough in the compilation to find out.

I'm not using the Arduino IDE at all but my hacked together build environment is based on the Arduino 0023 core libraries so the code is written to compile against that. I will eventually upgrade even though there isn't a very good technical reason to do so: the new core uses more RAM than before -- a big deal on a microprocessor -- and adds few useful features. But since it'll likely require modifying the libraries I'm not in a big hurry to do so. Use 0022 or 0023 for now :red_mouth.

Thanks for the report. Please let me know about any other issues you run into and I'll update the docs. Or write it up for me and I'll include it in the distribution :proud:.
 
#41 ·
You're welcome, let me know how it works when you have it all hooked up.

I just uploaded a new version with a bit better comments in the code for what people need to change to make it work. It doesn't add any features so no need to upgrade.
 
#42 ·
Well i'm playing catch up on this whole Code thing.. I'm basically worthless at it. BUT i bought an arduino Uno and a chronoDOt RTC and by gosh i'm gonna make this thing work. so a few questions:
If i were to reduce the code to only have one driver running off of it, what would i need to edit?
Also, for the life of me, i can't figure out what the heck Python is. I got it, installed it, and i am still just absolutely clueless.

In my defense, i am not an idiot.. i'm just an engineer. so i've never had a good reason to try and delve into this. Thanks in advance for the help!!
 
#47 ·
Unless you need that output pin for some other task- I don't see a need to modify the code at all. Since you say that you'll only be running one driver- just edit the start/stop times for one of the PWM channel pins and leave the other pin alone. You may find that you want to add another group of leds in the future and the code left, "as= is" will allow for that.
 
#43 ·
Just remove the lines that reference one of the channels.

"const int kChan1Pin = 10; // Channel 1 Pin" is where the second channel is assigned to pin 10

" if (state[1] >= 0 && state[1] <= 1023) Timer1.setPwmDuty(kChan1Pin, state[1]);" Where the second channel state is set.

Really, all I did was delete that first line and try uploading it via the Arduino alpha ide, it told me what else wouldn't work.

Once I deleted the lines it told me to it uploaded and worked just fine.

Python is another program that works in a slightly different language. Let me see if I can remember how I set my RTC.
 
This is an older thread, you may not receive a response, and could be reviving an old thread. Please consider creating a new thread.
Top