Introduction: Aquarium Control Center

This instructable was created in fulfillment of the project requirement of the Makecourse at the University of South Florida (www.makecourse.com)

Step 1: Design

The enclosure has space for 6 GFCI outlets, 4 of which can each be set with their own on/off times, and 2 of which are battery backup outlets. On/off times are controlled by 6 buttons and displayed on an LCD screen. The entire unit should be powered by a single 120v source.

Step 2: Interior

Because of the limited space inside the enclosure, I was forced to route the USB power cable and breadboard through the original button holes for external mounting. A redesign is on the way that includes a 10% increase in internal volume and standoffs which hold the breadboard right under the unit's faceplate and allows the Arduino to sit right underneath it to open up room for more wires and a backup battery source.

Step 3: Control Schematic

This is the control schematic. It shows the LCD screen connected to the primary I2C bus, and the Real Time Clock connected to the secondary I2C bus through analog inputs A4 and A5. Four relays are controlled by output pins 2 through 5, and six buttons are read through input pins 8 through 13.

Step 4: Arduino Sketch

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//|Include libraries for LCD display, I2C communication, and Real Time Clock.|//
#include

#include
#include "RTClib.h"
//|Define input pins.|//
#define state1 8
#define state2 9
#define state3 10
#define state4 11
#define on 12
#define off 13
//|Define output pins.|//
#define relay1 2
#define relay2 3
#define relay3 4
#define relay4 5
//|Create objects for LCD display and Real Time Clock.|//
LiquidCrystal_I2C myDisplay(0x27,16,2);
RTC_DS1307 rtc;
//|Declare variables for the state of each button (high/low).|//
int button1State;
int button2State;
int button3State;
int button4State;
int buttonOnState;
int buttonOffState;
//|Declare variables for the {hour,minute} of each outlet's On and Off state.|//
int outlet1On[2] = {0,0};
int outlet1Off[2] = {0,0};
int outlet2On[2] = {0,0};
int outlet2Off[2] = {0,0};
int outlet3On[2] = {0,0};
int outlet3Off[2] = {0,0};
int outlet4On[2] = {0,0};
int outlet4Off[2] = {0,0};
//|Holds the value for the current outlet being displayed and modified.|//
int i = 1;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//|Setup.|//
void setup()
{
//|Initialize and turn on LCD display.|//
myDisplay.init();
myDisplay.backlight();
//|Initialize I2C for time reading.|//
Wire.begin();
rtc.begin();

//|Set input pins as INPUT and output pins as OUTPUT.|//
pinMode(state1, INPUT);
pinMode(state2, INPUT);
pinMode(state3, INPUT);
pinMode(state4, INPUT);
pinMode(on, INPUT);
pinMode(off, INPUT);
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
//|Set input pins HIGH and output pins LOW.|//
digitalWrite(state1, HIGH);
digitalWrite(state2, HIGH);
digitalWrite(state3, HIGH);
digitalWrite(state4, HIGH);
digitalWrite(on, HIGH);
digitalWrite(off, HIGH);
digitalWrite(relay1, HIGH);
digitalWrite(relay2, HIGH);
digitalWrite(relay3, HIGH);
digitalWrite(relay4, HIGH);
if(! rtc.isrunning()) {
rtc.adjust(DateTime(__DATE__, __TIME__));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//|Main loop.|//
void loop()
{
//Set the state of each button based on real time actuation.|//
button1State = digitalRead(state1);
button2State = digitalRead(state2);
button3State = digitalRead(state3);
button4State = digitalRead(state4);
buttonOnState = digitalRead(on);
buttonOffState = digitalRead(off);
//Create a DateTime variable with the current time.|//
DateTime now = rtc.now();

//Turn the outlet on/off if the current time is equal to the stored On/Off time for that outlet.|//
if(outlet1On[0] != outlet1Off[0] || outlet1On[1] != outlet1Off[1]){
if(now.hour() == outlet1On[0] && now.minute() == outlet1On[1])
{
digitalWrite(relay1, LOW);
}
if(now.hour() == outlet1Off[0] && now.minute() == outlet1Off[1])
{
digitalWrite(relay1, HIGH);
}
}
if(outlet2On[0] != outlet2Off[0] || outlet2On[1] != outlet2Off[1]){
if(now.hour() == outlet2On[0] && now.minute() == outlet2On[1])
{
digitalWrite(relay2, LOW);
}
if(now.hour() == outlet2Off[0] && now.minute() == outlet2Off[1])
{
digitalWrite(relay2, HIGH);
}
}
if(outlet3On[0] != outlet3Off[0] || outlet3On[1] != outlet3Off[1]){
if(now.hour() == outlet3On[0] && now.minute() == outlet3On[1])
{
digitalWrite(relay3, LOW);
}
if(now.hour() == outlet3Off[0] && now.minute() == outlet3Off[1])
{
digitalWrite(relay3, HIGH);
}
}
if(outlet4On[0] != outlet4Off[0] || outlet4On[1] != outlet4Off[1]){
if(now.hour() == outlet4On[0] && now.minute() == outlet4On[1])
{
digitalWrite(relay4, LOW);
}
if(now.hour() == outlet4Off[0] && now.minute() == outlet4Off[1])
{
digitalWrite(relay4, HIGH);
}
}

//|Set the current outlet being displayed/modified based on user input.|//
if(button1State==LOW)
{
i=1;
}
if(button2State==LOW)
{
i=2;
}
if(button3State==LOW)
{
i=3;
}
if(button4State==LOW)
{
i=4;
}
//Advance the current On time by 10 minutes per button press. Hours and minutes roll over in 24 hour format.|//
if(buttonOnState==LOW)
{
if(i == 1)
{
outlet1On[1] = outlet1On[1] + 5;
if(outlet1On[1] == 60)
{
outlet1On[0] = outlet1On[0] + 1;
outlet1On[1] = 0;
}
if(outlet1On[0] == 24)
{
outlet1On[0] = 0;
}
}
if(i == 2)
{
outlet2On[1] = outlet2On[1] + 5;
if(outlet2On[1] == 60)
{
outlet2On[0] = outlet2On[0] + 1;
outlet2On[1] = 0;
}
if(outlet2On[0] == 24)
{
outlet2On[0] = 0;
}
}
if(i == 3)
{
outlet3On[1] = outlet3On[1] + 5;
if(outlet3On[1] == 60)
{
outlet3On[0] = outlet3On[0] + 1;
outlet3On[1] = 0;
}
if(outlet3On[0] == 24)
{
outlet3On[0] = 0;
}
}
if(i == 4)
{
outlet4On[1] = outlet4On[1] + 5;
if(outlet4On[1] == 60)
{
outlet4On[0] = outlet4On[0] + 1;
outlet4On[1] = 0;
}
if(outlet4On[0] == 24)
{
outlet4On[0] = 0;
}
}
}

//Advance the current Off time by 10 minutes per button press. Hours and minutes roll over in 24 hour format.|//
if(buttonOffState==LOW)
{
if(i == 1)
{
outlet1Off[1] = outlet1Off[1] + 5;
if(outlet1Off[1] == 60)
{
outlet1Off[0] = outlet1Off[0] + 1;
outlet1Off[1] = 0;
}
if(outlet1Off[0] == 24)
{
outlet1Off[0] = 0;
}
}
if(i == 2)
{
outlet2Off[1] = outlet2Off[1] + 5;
if(outlet2Off[1] == 60)
{
outlet2Off[0] = outlet2Off[0] + 1;
outlet2Off[1] = 0;
}
if(outlet2Off[0] == 24)
{
outlet2Off[0] = 0;
}
}
if(i == 3)
{
outlet3Off[1] = outlet3Off[1] + 5;
if(outlet3Off[1] == 60)
{
outlet3Off[0] = outlet3Off[0] + 1;
outlet3Off[1] = 0;
}
if(outlet3Off[0] == 24)
{
outlet3Off[0] = 0;
}
}
if(i == 4)
{
outlet4Off[1] = outlet4Off[1] + 5;
if(outlet4Off[1] == 60)
{
outlet4Off[0] = outlet4Off[0] + 1;
outlet4Off[1] = 0;
}
if(outlet4Off[0] == 24)
{
outlet4Off[0] = 0;
}
}
}
//|Display the On/Off times for currently selected outlet on LCD display.|//
if(i==1)
{
myDisplay.clear();
myDisplay.print("Outlet 1");
myDisplay.setCursor(0,1);
if(outlet1On[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet1On[0]);
myDisplay.print(':');
if(outlet1On[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet1On[1]);
myDisplay.setCursor(6,1);
if(outlet1Off[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet1Off[0]);
myDisplay.print(':');
if(outlet1Off[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet1Off[1]);
myDisplay.setCursor(11,0);
if(now.hour() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.hour(),DEC);
myDisplay.print(':');
if(now.minute() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.minute());
delay(100);
}
if(i==2)
{
myDisplay.clear();
myDisplay.print("Outlet 2");
myDisplay.setCursor(0,1);
if(outlet2On[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet2On[0]);
myDisplay.print(':');
if(outlet2On[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet2On[1]);
myDisplay.setCursor(6,1);
if(outlet2Off[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet2Off[0]);
myDisplay.print(':');
if(outlet2Off[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet2Off[1]);
myDisplay.setCursor(11,0);
if(now.hour() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.hour(),DEC);
myDisplay.print(':');
if(now.minute() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.minute());
delay(100);
}
if(i==3)
{
myDisplay.clear();
myDisplay.print("Outlet 3");
myDisplay.setCursor(0,1);
if(outlet3On[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet3On[0]);
myDisplay.print(':');
if(outlet3On[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet3On[1]);
myDisplay.setCursor(6,1);
if(outlet3Off[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet3Off[0]);
myDisplay.print(':');
if(outlet3Off[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet3Off[1]);
myDisplay.setCursor(11,0);
if(now.hour() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.hour(),DEC);
myDisplay.print(':');
if(now.minute() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.minute());
delay(100);
}
if(i==4)
{
myDisplay.clear();
myDisplay.print("Outlet 4");
myDisplay.setCursor(0,1);
if(outlet4On[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet4On[0]);
myDisplay.print(':');
if(outlet4On[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet4On[1]);
myDisplay.setCursor(6,1);
if(outlet4Off[0] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet4Off[0]);
myDisplay.print(':');
if(outlet4Off[1] < 10)
{
myDisplay.print('0');
}
myDisplay.print(outlet4Off[1]);
myDisplay.setCursor(11,0);
if(now.hour() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.hour(),DEC);
myDisplay.print(':');
if(now.minute() < 10)
{
myDisplay.print('0');
}
myDisplay.print(now.minute());
delay(100);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Step 5: Sketch Description

- First it is necessary to include libraries for the LCD display, I2C communications bus and Real Time Clock

- Next, all input and output pins are defined

- Objects are created for LCD screen and Real Time Clock that will be called on to perform built in functions later in the code

- All variables are declared - HIGH/LOW states of buttons, On/Off states of outlets, number "I" to keep track of current outlet being displayed

- In the setup code:

- Initialize the LCD display and I2C bus. Set each button pin as input and each relay pin as output

- Set the HIGH/LOW state of each pin. Set each button pin as HIGH and each relay pin as HIGH

- In the main loop:

- Set button state values to be read from the inputs.

- Create DateTime variable that holds the current time information.

- The next section checks to see if the current time matches the on or off times of any of the outlets. If it does, the outlet is turned on or off accordingly

- The next section of code keeps track of which outlet the user has chosen to display and modify

- The next section keeps track of all outlets on/off times and advances the time by five minute increments when the corresponding button is pressed. Minutes roll over upon reaching 60 and hours roll over upon reaching 24

- Finally, this code runs the LCD display

Step 6: Wiring With Line Voltage

If you would like to know how to wire the outlets safely, refer to THIS TUTORIAL, which was invaluable in helping me wire my project.