Aquarium PWM LED V1 (Legacy)

This project came up on my mind when I realized the exorbitant price of an aquarium LED light controller. The starting price for a professional equipment like this one can be as high as 1000€.

So, if you can build your own controller with the exact same functions (or even a better one) why spend a fortune in an equipment that, in my opinion, doesn’t worth what it costs.

For this project I used four LED strings. Each string comprises three LEDs. The LEDs have a forward voltage around ~4.0V and forward current around ~750mA meaning that a IRF3205 MOSFET is enough to switch each string. These LEDs are known as 3W High Power LED.

My estimative for a project with twelve 3 Watt LEDs is around 50 EUR (this value includes all electronics LEDs and driver).

// If there is no input, automatically jump to main display when gotomain = gotomaincounter. Change this time by manipulating the gotomaincouter value.

gotomainfunction();

if(analogRead(SetClockPlus)<20)

{

gotomain=0;

Wire.beginTransmission(DS1307_I2C_ADDRESS);

Wire.write(0x06);

Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS,1);

year=bcdToDec(Wire.read());

if(day==29&&year%4==0&&month==2){year=year+4;}

elseyear++;

if(year>=31){year=8;}

Wire.beginTransmission(DS1307_I2C_ADDRESS);

Wire.write(0x06);

Wire.write(decToBcd(year));

Wire.endTransmission();

delay(settingdelay);

}

SwitchClockMode(7);

}

// Set Pre-sunrise

voidSetPresunrise(void)

{

presunrise=EEPROM.read(presunriseMemoryBank);

lcd.setCursor(0,0);

lcd.print("Pre-sunrise:");

lcd.setCursor(14,0);

lcd.print(":00");

lcd.setCursor(12,1);

lcd.write((uint8_t)1);lcd.write((uint8_t)1);

lcd.setCursor(12,0);

if(presunrise>=10)

lcd.print(presunrise,DEC);

if(presunrise<10)

{

lcd.print("0");

lcd.print(presunrise,DEC);

}

// If there is no input, automatically jump to main display when gotomain = gotomaincounter. Change this time by manipulating the gotomaincouter value.

gotomainfunction();

if(analogRead(SetClockPlus)<20)

{

gotomain=0;

presunrise++;

if(presunrise>=10){presunrise=6;}

EEPROM.write(presunriseMemoryBank,presunrise);

delay(settingdelay);

}

SwitchClockMode(8);

}

// Set sunrise

voidSetSunrise(void)

{

sunrise=EEPROM.read(sunriseMemoryBank);

lcd.setCursor(0,0);

lcd.print("Sunrise:");

lcd.setCursor(14,0);

lcd.print(":00");

lcd.setCursor(12,1);

lcd.write((uint8_t)1);lcd.write((uint8_t)1);

lcd.setCursor(12,0);

if(sunrise>=10)

lcd.print(sunrise,DEC);

if(sunrise<10)

{

lcd.print("0");

lcd.print(sunrise,DEC);

}

// If there is no input, automatically jump to main display when gotomain = gotomaincounter. Change this time by manipulating the gotomaincouter value.

gotomainfunction();

if(analogRead(SetClockPlus)<20)

{

gotomain=0;

sunrise++;

if(sunrise>=19){sunrise=10;}

EEPROM.write(sunriseMemoryBank,sunrise);

delay(settingdelay);

}

SwitchClockMode(9);

}

// Set sunset

voidSetSunset(void)

{

sunset=EEPROM.read(sunsetMemoryBank);

lcd.setCursor(0,0);

lcd.print("Sunset:");

lcd.setCursor(14,0);

lcd.print(":00");

lcd.setCursor(12,1);

lcd.write((uint8_t)1);lcd.write((uint8_t)1);

lcd.setCursor(12,0);

if(sunset>=10)

lcd.print(sunset,DEC);

if(sunset<10)

{

lcd.print("0");

lcd.print(sunset,DEC);

}

// If there is no input, automatically jump to main display when gotomain = gotomaincounter. Change this time by manipulating the gotomaincouter value.

gotomainfunction();

if(analogRead(SetClockPlus)<20)

{

gotomain=0;

sunset++;

if(sunset>=24){sunset=19;}

EEPROM.write(sunsetMemoryBank,sunset);

delay(settingdelay);

}

SwitchClockMode(0);

x=0;// As "copyright()" won't run each cycle, variable "x" must be zeroed (0), so when it jumps into the main screen it will be printed immediately.

y=-1;// As "PrintBrightnessOnLCD()" runs in a pace of 100x, variable "y" must be set to -1 so when it rolls over it will be printed immediately.

}

// Below you will see the function where you can configure the PWM cycle: sunrise, daylight, sunset and moonlight.

voidLED_PWM(void)

{

// Pre-sunrise 1

if(hour==presunrise)

{

Brightness_WhiteString1=0.5*minute;

Brightness_WhiteString2=0.5*minute;

Brightness_BlueString=18+(0.2*minute);

Brightness_RedString=4*minute;

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

// Pre-sunrise 2

if(hour>=presunrise+1&&hour<=sunrise-1)

{

Brightness_WhiteString1=30;

Brightness_WhiteString2=30;

Brightness_BlueString=30;

Brightness_RedString=240;//equals to maxBrightness

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

// Sunrise

if(hour==sunrise)

{

Brightness_WhiteString1=30+(0.875*4*minute);

Brightness_WhiteString2=30+(0.875*4*minute);

Brightness_BlueString=30+(0.875*4*minute);

Brightness_RedString=240;//equals to maxBrightness

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

// Sunlight

if(hour>=sunrise+1&&hour<=sunset-1)

{

Brightness_WhiteString1=maxBrightness;

Brightness_WhiteString2=maxBrightness;

Brightness_BlueString=maxBrightness;

Brightness_RedString=maxBrightness;

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

// Sunset

if(hour==sunset)

{

Brightness_WhiteString1=maxBrightness-(4*minute);

Brightness_WhiteString2=maxBrightness-(4*minute);

Brightness_BlueString=maxBrightness-(0.925*4*minute);

Brightness_RedString=maxBrightness-(4*minute);

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

// Moonlight 1

if(hour>=sunset+1&&hour<=23)

{

Brightness_WhiteString1=0;

Brightness_WhiteString2=0;

Brightness_BlueString=18;

Brightness_RedString=0;

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

// Moonlight 2

if(hour>=0&&hour<=presunrise-1)

{

Brightness_WhiteString1=0;

Brightness_WhiteString2=0;

Brightness_BlueString=18;

Brightness_RedString=0;

ShiftPWM.SetOne(WhiteString1,Brightness_WhiteString1);

ShiftPWM.SetOne(WhiteString2,Brightness_WhiteString2);

ShiftPWM.SetOne(BlueString,Brightness_BlueString);

ShiftPWM.SetOne(RedString,Brightness_RedString);

}

}

// This is a function with debugging purposes

voidLED_PWM_Debug(void)

{

ShiftPWM.SetOne(WhiteString1,50);

ShiftPWM.SetOne(WhiteString2,50);

ShiftPWM.SetOne(BlueString,50);

ShiftPWM.SetOne(RedString,50);

}

Some important remarks that should not be forgotten:

1) Before compiling the code you need to download, uncompress and install the following libraries: RTClib and ShiftPWM. To install simply copy them into the “libraries” folder. Alternatively you can read the official tutorial: Installing Additional Arduino Libraries

2) The pinout for the IRF3205 N-Channel Power MOSFETs is the following:Gate | Drain | Source

If you’re using other transistors to switch the LEDs and you are not sure about its pinout, you should read the datasheet.

3) The ground of the LED driver (Driver V-) should be connected to the power-supply’s ground. The positive of the LED driver (Driver V+) should NOT be connected to the positive of the power-supply.

4) The circuit can be powered via Arduino’s USB port or applying a 12V voltage at Arduino’s Vin pin.

5) The only trimmer (variable resistor) in the circuit has a value of 10kOhm and it’s used to regulate contrast of the LCD.

6) In order to view all data available on the LCD I recommend you to use a 20×4 char LCD instead of a 16×2 char LCD.

7) Some LCD boards have the backlight LED pins inverted. So, before connecting it to the circuit, make sure to check the datasheet to make avoid damage on your LCD.

8) This project is no longer supported, so, if you have strange characters on the LCD please use an older version of the Arduino IDE (1.0.5 was reported to work).

This is the final result of the illumination system in my South American aquarium biotope:

If you need to ask me a question, suggest an enhancement or report a bug, please use the contact form below:

Your name

Your e-mail (double check your e-mail or I won't be able to contact you)