RGB LED Day/Night controller

lberry.88

New member
Folks,

Have been working on this for a few weeks now. I have 5M of LED RGB strip lighting in my 70L lank. It is the cheap stuff which you can buy for about £10 from eBay.

The aim was to create a timing system which slowly turns on the LED strip, and is able to control the intensity of the individual colours. This allows for a redder dawn, fading over an hour up to maximum intensity daylight. Then the same again as it fades through dusk into darkness. There is then a secondary program to simulate moonlight which again can have different intensities: the default is for a slightly bluer moonlight however all times and intensities are user changeable.

Future updates are to include temperature sensor and cooling fan system to cool the LEDs, storm and lunar cycle simulation and LCD display.

The parts for the timer cost no more than £10 and could be used with any LED or lighting system so long as you know what is positive and negative for your lighting and power input.

I have attached the code, fritzing file if you are interested in giving it a go. I will update the with relevant libraries when I find them all....

I hope this is helpful to people, it has worked well for me!

Any questions or comments please let me know.

Luke

/*
// RGB LED aquarium lighting controller //

// - Summary - //
// Able to independently control all three channels of RGB to simulate dawn, day, dusk, darkness and moonlight.
// Length of each event can be programmed and each of the independednt colours can be controlled separately to give a red dawn and a red dusk etc.

// The system uses a DS1307 RTC to kick off lighting schedules:
// * Fade up on a given slope delay a set amount
// * Fade back down such photoperiod (duration) lasts the correct amount of time.
// * The fade length and photoperiod can be adjusted below.

// There are two channels for each LED. Day and moonlight - labled night.
// This allows the moonlight intenstity settings to be set separatley to day however the pins can go to the same transistor.
// Day channels are labeled dred, dblue, dgreen.
// Moonlight channels labeled nred etc .

// All times are set in minutes.


* Copyright (c) 2015, User "lberry.88" at tropicalfishforum.co.uk forums
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

// RTC Pin arrangement
// SDA - Pin 4
// SCL - Pin 5



// Pins to control LEDs. Change these if you're using different pins.

int dblueLed = 5; // Blue Day LED
int dredLed = 6; // Red Day LED
int dgreenLed = 10; // Green day LED.
int ngreenLed = 11; // Green night LED
int nredLed = 9; // Red night LED
int nblueLed = 3; // Blue night LED


// Set up RTC
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68



// RTC variables
byte second, rtcMins, oldMins, rtcHrs, oldHrs, dayOfWeek, dayOfMonth, month, year;

// Variables: These control the behavior of lighting. Change these to customize behavoir

int minCounter = 0; // counter that resets at midnred. Don't change this.

int dredStartMins = 450 ; // minutes after midnight to start red day channel.
int dgreenStartMins = 450; // minutes after midnight to start green day channel.
int dblueStartMins = 460; // minutes after midnight to start blue day channel.

int ngreenStartMins = 0; // minutes after midnight to start green night channel.
int nblueStartMins = 0; // minutes after midnight to start blue night channel.
int nredStartMins = 0 ; // minutes after midnight to start red night channel.

int dredPhotoPeriod = 600; // photoperiod in minutes for day red. Change this to alter the total time
int dgreenPhotoPeriod = 600; // photoperiod in minutes for day green. Same as above.
int dbluePhotoPeriod = 590; // photoperiod in minutes for day blue. Same as above.

int ngreenPhotoPeriod = 300; // photoperiod for moonlight green. Same as above.
int nbluePhotoPeriod = 300; // photoperiod for moonlight blue.
int nredPhotoPeriod = 300 ; // photoperiod for moonlight red.

int fadeDuration = 60; // duration of the fade on and off for sunrise and sunset. User changable

int dredMax = 255; // max intensity for day red.
int dgreenMax = 255; // max intensity for day green.
int dblueMax = 255; // max intensety for day blue.
int nblueMax = 20; // max intensity for moonlight blue.
int ngreenMax = 20; // max intensity for moonlight green.
int nredMax = 30; // max intensity for moonlight red.


/****** LED Functions ******/
/************DO NOT ADJUST***************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
void setLed(int mins, // current time in minutes
int ledPin, // pin for this channel of LEDs
int start, // start time for this channel of LEDs
int period, // photoperiod for this channel of LEDs
int fade, // fade duration for this channel of LEDs
int ledMax // max value for this channel
) {
if (mins > start && mins <= start + fade) {
analogWrite(ledPin, map(mins - start, 0, fade, 0, ledMax));
}
if (mins > start + fade && mins <= start + period - fade) {
analogWrite(ledPin, ledMax);
}
if (mins > start + period - fade && mins <= start + period) {
analogWrite(ledPin, map(mins - start + period - fade, 0, fade, ledMax, 0));
}
}

/***** RTC Functions *******/
/***************************/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers.
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}

void setup() {
Serial.begin(9600);
// init I2C
Wire.begin();
}

/***** Main Loop ***********/
/***************************/
void loop()

{
// get time from RTC and put in hrs and mins variables
getDateDs1307(&second, &rtcMins, &rtcHrs, &dayOfWeek, &dayOfMonth, &month, &year);
minCounter = rtcHrs * 60 + rtcMins;

// determine if it is day or night, and act accordingly
if ((minCounter > dredStartMins || minCounter > dgreenStartMins || minCounter > dblueStartMins || minCounter > ngreenStartMins)
&& (minCounter < dredStartMins + dredPhotoPeriod || minCounter < dgreenStartMins + dgreenPhotoPeriod
|| minCounter < dblueStartMins + dbluePhotoPeriod || minCounter < ngreenStartMins + ngreenPhotoPeriod || minCounter < nredStartMins + nredPhotoPeriod
|| minCounter < nblueStartMins + nbluePhotoPeriod )) { //day// set LED states

setLed(minCounter, dredLed, dredStartMins, dredPhotoPeriod, fadeDuration, dredMax);
setLed(minCounter, dgreenLed, dgreenStartMins, dgreenPhotoPeriod, fadeDuration, dgreenMax);
setLed(minCounter, ngreenLed, ngreenStartMins, ngreenPhotoPeriod, fadeDuration, ngreenMax);
setLed(minCounter, dblueLed, dblueStartMins, dbluePhotoPeriod, fadeDuration, dblueMax);
setLed(minCounter, nredLed, nredStartMins, nredPhotoPeriod, fadeDuration, nredMax);
setLed(minCounter, nblueLed, nblueStartMins, nbluePhotoPeriod, fadeDuration, nblueMax);
}
else { //night state
analogWrite(dredLed, 0);
analogWrite(dgreenLed, 0);
analogWrite(dblueLed, 0);
analogWrite(nredLed, 0);
analogWrite(ngreenLed, 0);
analogWrite(nblueLed, 0);
}
Serial.print("Minute Counter: ");
Serial.println(minCounter);




// Get ready for next iteration of loop
delay(1000);
}
 

Attachments

  • RGB LED controller_bb.jpg
    RGB LED controller_bb.jpg
    93 KB · Views: 2
I am trying to get a timelapse of it running though a whole 'day' in one hour but the camera on my phone keeps auto adjusting the light level making it appear to be the same brightness throughout! (Never thought I would complain about the camera being too good!) Am going to try tomorrow with a worse camera!

The only issues I have had so far have been:
1) The voltage losses in the circuit have meant I needed to crank my power supply to 13V to get the same light intensity as without the arduino and the leds running off of the controller they ship with.
2) The tip120s get hot... Very hot... Have a cooling fan blowing air over them ATM...
 
I wonder if you could run the strip off an LDD or similar driver? I'm sure there is a better purpose built circuit or board out there which wont get so darn hot.
 
I will have to do some research on those - getting into LDDs is probably sensible. I will definitely want to have it on a PCB for a smaller form factor than breadboard - after all this is squashed into the top of a 70l Juwel...
 
Awesome. I have my tank running off a Raspberry Pi controlling the LED's and a DJ power strip that I modded with a relay board so I could control the outlets from the RPi. I then wrote a website for the tank that I can log in to and control everything the public facing site it at http://messowires.com/

I made a database that the site and my python scripts can read/write to and I have a script watching for changes to the database and then runs a command doing whatever it needs to do.

I love to see things like this.
 
Thanks man - it started off as a Sunday afternoon project.... Four weeks later I have got to this point! The website looks awesome will definitely keep checking it.

I have some NTD4963N MOSFETs on order to replace the TIP120 transistors I have handling the dimming. They have a much lower voltage drop (negligible compared to the 2V of the TIPs) which should allow me to run either at 12V input for the same brightness as my current 15V setting.... Or turn up the voltage to 15V and get more intensity. Oh and the MOSFETs will solve the heat dissipation issue as they are a much higher eficiency system. They should be here by Monday so I'll keep you all updated.
 
Back
Top