Reef Angel


Open Source Development, Lessons Learned and Sample Code

This page is dedicated to helping new users become familiar with using the Reef Angel open source aquarium controller.  The work here is inspired by a group buy to purchase many of these controllers by the Delaware Valley Reef Club and is dedicated to the DVRC members.

My efforts here are all open source and are provided to be used by anyone, for any reason, without the need for a license.  I would appreciate a mention in source code if you reuse my code.  This code is being given without warranty, use it at your own risk.  I am not responsible for any malfunctions or damage caused to your system by using this code.

Getting Started

  1. 1. Download and install the Arduino environment.

  2. 2.Download and install the ReefAngel development libraries

  3. 3.Download my starting point Arduino Sketch
    Starting Point Sketch

  4. 4.If you already know how to code or want to use some other functions I haven’t covered, the full documentation can be found here:

Starting Point Sketch

If you are unfamiliar with how to write code for the Arduino, you should read the Arduino Tutorials or browse through the Arduino Reference.

Define your outlets

You are provided with 8 controllable outlets with the base model Reef Angel controller.  Each outlet is essentially the same, so to make using them in code easier, we are going to name them.  Look for a section of code that looks like this:

#define Port8                    8
#define Port7                    7
#define WM1                    6
#define Heater                 5
#define ReturnPump        4
#define SumpLight           3
#define BlueLED              2
#define WhiteLED            1

You can go through and rename these to be anything you want.  Just replace the text between “#define” and the number.  For example, you can change “Port8” to “DosingPump”.

Menu Definition

The next big chunk of code is all for setting up the menu structure.  I’m not going to spend any time talking about menus right now since I haven’t had a chance to try them yet.  The basic premise though is that this defines a nested set of menus.  Each time you select one of the options, you are taken to another set of menus until you get down to displaying data, a setup screen, etc.  I’ll come back and add to this section later...

setup() function

For those of you familiar with the Arduino environment, you already know what goes on in here.  For those of you who aren’t familiar, here’s a brief description...  The setup() function runs once at startup of the Arduino.  Inside this function is where you will do all of your initialization of variables, start up some other processes, etc.  Since this runs only once, you won’t ever have any code in here that needs to be evaluated any time after startup, that code will live in the loop() function.

void setup()

  ReefAngel.Init();  //Initialize controller
  ReefAngel.LoadMenu(pgm_read_word(&(mainmenu_items[0])), SIZE(mainmenu_items));

  ReefAngel.Relay.On(ReturnPump);  //Turn Sump on at startup

  //ReefAngel.Timer[0].Interval=10;  // Uncomment to override feeding timer. Default is 900 seconds
  //ReefAngel.Timer[3].Interval=5;  // Uncomment to override screen saver timer. Default is 600 seconds
  //ReefAngel.Timer[3].Start();   // Uncomment to start screen saver timer if you uncommented line above


The actual file may have some other commented out code, you can delete that if you wish to.

There are a few key things that are happening in here.

  1. 1.ReefAngel.Init()
    This is a function that is given to us form the Reef Angel libraries.  It does a lot of things for you automatically like setting up the LCD screen, mapping control pins for outlets, and a lot of other things you don’t need to worry about.  You should ALWAYS leave this line in your setup() function.  If you don’t, your controller won’t work.

  2. 2.ReefAngel.LoadMenu(...)
    This is letting the Reef Angel know about the menus that we setup earlier.  All of the menus will get passed to the core code and will be displayed.  NOTE: I haven’t tested this yet and it may not work as described.

  3. 3. ReefAngel.Relay.On(ReturnPump)
    This turns on the outlet that is connected to the return pump in my sump.  Since I always want this running unless I’m feeding or doing a water change, this is OK to put in the setup().

  4. 4.ReefAngel.Timer[#]
    The Reef Angel has default timers setup for feeding and starting the screen saver on the LCD.  If you want to change those default times, you can do that here.

loop() function

The loop() function runs over and over again until the Arduino is powered off.  Inside of the loop() function is where you will spend the bulk of your time writing code.  This code section can get very big very quickly.  I suggest writing helper functions for things that you find you are doing over and over again.  It will make your loop() function easier to read and will help prevent copy and past errors.  This function is where you will do things like turn on and off lights, run a wavemaker, and setup your heater.  Since there is so much code here, I’m going to just focus on a few key elements one at a time.

Drawing the GUI

Your Reef Angel comes with a nice graphical user interface (GUI) by default.  Unless you are a master with the Arduino and the LCD on the Reef Angel, I suggest you leave it alone.  Reef Angel has provided a very simple way to start the GUI and publish it to the LCD.

  ReefAngel.StandardGUI();  //Draw the Standard GUI

Just place that one line at the top of your loop() function and you’re all set.  Can’t get much easier than that!

Standard Lights (NOT Metal Halides!)

The Reef Angel has some nice helper functions for turning outlets on and off at a certain time.  This is accomplished through the StandardLights() function in the Reef Angel core. This function is NOT for use with metal halide lights!  While you can use it for them, there is a much better way to do that, scroll down for details about that function.

  ReefAngel.StandardLights(BlueLED,12,30,22,0);  //Setup lights to turn on at 12:30PM and off at 10:00PM

This function is quite simple.  You will see a line just like this repeated multiple times in my loop() function.  Here’s how this function works:  ReefAngel.StandardLights(OutletName,OnHour,OnMinute,OffHour,OffMinute)

Simply replace the fillers with the actual names and times. 

  1. OutletName: This is the name you gave the outlet that the light is plugged into

  2. OnHour:  The hour you want the light to turn on in 24 hour/military time.  ie 8:00AM = 8, 8:00PM = 20

  3. OnMinute:  The minute you want the light to turn on.  ie 8:30AM = 30.

  4. OffHour: The same as OnHour, except this is the time the light turns off.

  5. OffMInute: The same as OnMinute, except this is the time the light turns off.

You can also set this up to turn lights on and off multiple times during a day.  Just use another StandardLights() function to set more on and off times.  Don’t let them overlap though!

Metal Halide Lights

The MH function provided by the default libraries adds the ability to set a delay time before the light can turn back on to help prevent damage to your lights.

This function is identical to the StandardLights function with the addition of a restart delay. In the event of a power failure, this delay will keep your MH lights from turning on until at least 30 minutes after the power is restored.  The function is defined as: MHLights(OutletName,OnHour,OnMinute,OffHour,OffMinute,Delay).

Simply replace the fillers with the actual names and times. 

  1. OutletName: This is the name you gave the outlet that the light is plugged into

  2. OnHour:  The hour you want the light to turn on in 24 hour/military time.  ie 8:00AM = 8, 8:00PM = 20

  3. OnMinute:  The minute you want the light to turn on.  ie 8:30AM = 30.

  4. OffHour: The same as OnHour, except this is the time the light turns off.

  5. OffMInute: The same as OnMinute, except this is the time the light turns off.

  6. Delay:  The number of minutes to wait before restarting the MH lights.

Standard Heaters

Yet another helper function provided to you is the ability to control your tanks temperature by turning on and off your heaters.  There isn’t much to this function, but it is VERY nice to have.

  ReefAngel.StandardHeater(Heater,759,761);  // Setup Heater to turn on at 75.9F and off at 76.1F

This function lets you set the temperature to turn on your heater and the temperature to turn it back off.  You can set this range to be larger if you want, but the smallest you can go is in 0.1 degree increments.  Here’s how the function works: ReefAngel.StandardHeater(OutletName,OnTemp,OffTemp)

To use, replace the fillers with the actual name and temperatures.

  1. OutletName: This is the name you gave the outlet that the heater is plugged into

  2. OnTemp: This is the temperature that you want the heater to turn on at

  3. OffTemp: This is the temperature that you want the heater to turn off at

That’s all there is to it!  Multiple heaters?  No problem, just copy this line and change the name of the outlet to match the other heater(s).

PWM Control

If you are running a dimmable LED lighting system, the Reef Angel provides PWM outputs to allow you to dim them.  In the standard setup, you have two PWM outputs.  By default one is assigned to daylight LEDs and the other is assigned to actinic LEDs.  There are two separate functions for setting the values, one for actinic and one for daylight.  The elements are identical, so I’m going to just combine them for this discussion.

Pretty simple description here:  PWM.SetActinic(PWM Value)

  1. PWM Value: This is the duty cycle of the PWM signal you are setting (0 - 100%)

You should take note that not all LED drivers will turn on at 0%.  You may need to start at or above 10%.

PWM Sunrise/Sunset

But what’s the point of dimmable drivers if you just set a value and leave it?  Here’s a really simple function (that I didn’t write) that you can use to do a sunrise and sunset simulation.  You need two bits of code.  Let’s start off with the part that does all of the calculations.

I’m not going to spend much of any time explaining what’s going on here.  Suffice it to say that this function calculates what value your PWM should be set to one minute at a time.  Just copy this chunk of code at place it at the end of your Sketch.

Using this function is very straight forward.  It is used by placing the new function inside of the SetActinic and SetDaylight PWM functions.

  ReefAngel.MHLights(BlueLED,12,30,22,0,30);  //Turn on at 12:30PM and off at 10:00PM, 30 minute delay

ReefAngel.PWM.SetActinic(50); //Set the Actinic LEDs to 50%
ReefAngel.PWM.SetDaylight(48); //Set the Daylight LEDs to 48%

ReefAngel.Relay.On(ReturnPump); //Turn on the ReturnPump
ReefAngel.Relay.Off(ReturnPump); //Turn off the ReturnPump

byte PWMSlope(byte startHour, byte startMinute, byte endHour, byte endMinute, byte startPWM, byte endPWM, byte Duration, byte oldValue)


   int Now = NumMins(hour(), minute());

   int Start = NumMins(startHour, startMinute);

   int StartD = Start + Duration;

   int End = NumMins(endHour, endMinute);


   //Time correction if end time chosen is after midnight

   if ( Start > End ) {

      End= End+1440;   // 1440mins = 24hr*60mins   


   int StopD = End - Duration;

   if ( Now >= Start && Now <= StartD )

      return constrain(map(Now, Start, StartD, startPWM, endPWM),startPWM, endPWM);


   else if ( Now >= StopD && Now <= End ) {

      byte v = constrain(map(Now, StopD, End, startPWM, endPWM),startPWM, endPWM);

      return endPWM-v+startPWM;


   else if ( Now > StartD && Now < StopD ) return endPWM;

    // lastly return the existing value

    return oldValue;



We’re replacing a simple number for the PWM percentage with our PWMSlope function.  Here’s how you use it:  PWMSlope(StartHour, StartMinute, EndHour, EndMinute, StartPWM, EndPWM, Duration, Old Value)

  1. StartHour: The hour you want to start changing the PWM

  2. StartMinute: The minute you want to start changing the PWM

  3. EndHour: The hour you want to stop changing the PWM

  4. EndMinute: The minute you want to stop changing the PWM

  5. StartPWM:  The starting PWM value

  6. EndPWM: The ending PWM value

  7. Duration: How long you want the fade up/down to take.  If you set you end time to 10:00a with a 1 hour duration, it will fade from 9:00a to 10:00a.

  8. Old Value: This is the current PWM value. You should just use “ReefAngel.PWM.GetActinicValue()” or “ReefAngel.PWM.GetDaylightValue()”.

This function works for BOTH sunrise and sunset.  For a sunrise, StartPWM is going to be lower than EndPWM.  For a sunset, StartPWM is going to be higher than EndPWM.

Relay Control

The only thing we haven’t mentioned yet is the ability to simply turn on and off an outlet.  This is not on a timer, has no timeouts or anything fancy.  It is just like flipping a simple switch.

The use of this function is really simple: Relay.On(OutletName) or Relay.Off(OutletName)

  1. OutletName: This is the name of the outlet that you wish to turn on or off.