About This Project
This is my final project entry and it is my favorite. I call it tanker. It is a aquarium controller that manages many aspects of the aquarium such as lighting, temperature, water flow, energy consumption, feeding and soon CO2 control. It uses a waterproof temperature probe (DS18B20) as its basis for regulating the temp at 77.0F, a ACS712 to monitor energy consumption, and several relays to control the outlets devices such as the filter, heater and lights are plugged into. I added a small OLED screen via I2C on the case of the Mega to see real time temperature and connection status to Cayenne without a computer or smartphone. The filter relay is setup so if the internet is down, it defaults to “on.” I also hacked a inexpensive fish food feeder for controlled automated feeding by adding a relay and repurposing the micro switch inside so the Arduino knows when to stop the rotation of the food drum. I did have a AC solenoid setup for the CO2 control but I decided to remove it due to safety concerns. It was getting too hot in my opinion so I’m looking into other means for that aspect. I also plan to upgrade the power supply to a 2A instead of the 700ma currently. 700 should be enough to run it but I’m having power dropouts when the relays flip and it occasionally makes the ESP8266 drop the connection momentarily. I also may add a dosing pump for the plant food and a real time clock for calculating kWH. The cover and CO2 holders I designed and printed with my Ultimaker 2 clone. Overall I’m very happy with the project. This is my second version of the aquarium controller.
When feeding the fish, one presses “feed fish…” and that turns on the “Fish Eating” indicator. That triggers the pump to turn off so the fish can eat in peace and prevent food from wasting by getting into the filter. Code side as follows:
#include <CayenneESP8266Shield.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SimpleTimer.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
SimpleTimer timer;
char token[] = "token";
char ssid[] = "wifi ssid";
char password[] = "password here";
#define EspSerial Serial
ESP8266 wifi(EspSerial);
#define OLED_RESET 12
Adafruit_SSD1306 display(OLED_RESET);
#define LOGO16_GLCD_HEIGHT 64
#define LOGO16_GLCD_WIDTH 128
#define foodTrig 9
#define foodThrow 8
#define currentPin A2
#define filterPin 7
const unsigned long sampleTime = 100000UL;
const unsigned long numSamples = 500UL;
const unsigned long sampleInterval = sampleTime / numSamples;
const int adc_zero = 510;
int feedButton;
int filterButton;
int trigger;
float temp;
int feedingTimer;
int currentTimer;
int displayTimer;
bool online = false;
void setup()
{
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
for (int16_t i = 0; i<display.height(); i += 2) {
display.drawCircle(display.width() / 2, display.height() / 2, i, WHITE);
display.display();
delay(1);
}
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(5,25);
display.println("tanker 2.1");
display.display();
for (int16_t i = 0; i<display.height(); i += 2) {
display.drawCircle(display.width() / 2, display.height() / 2, i, BLACK);
display.display();
delay(1);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(5,25);
display.println("tanker 2.1");
display.display();
EspSerial.begin(9600);
delay(10);
sensors.begin();
Cayenne.begin(token, wifi, ssid, password);
feedingTimer = timer.setInterval(600000, feedingDone);
currentTimer = timer.setInterval(5000, getCurrent);
displayTimer = timer.setInterval(10000, displayUpdate);
timer.disable(feedingTimer);
pinMode(foodTrig, INPUT_PULLUP);
pinMode(currentPin, INPUT);
pinMode(filterPin, OUTPUT);
pinMode(foodThrow, OUTPUT);
Cayenne.virtualWrite(V3, LOW);
}
void loop()
{
timer.run();
Cayenne.run();
if (filterButton == 1)
{
digitalWrite(filterPin, 1);
}
else
{
digitalWrite(filterPin, 0);
}
if (feedButton == 1)
{
Cayenne.virtualWrite(V3, HIGH);
timer.enable(feedingTimer);
digitalWrite(foodThrow, HIGH);
delay(500);
trigger = digitalRead(foodTrig);
while (trigger == HIGH)
{
trigger = digitalRead(foodTrig);
delay(100);
}
digitalWrite(foodThrow, LOW);
feedButton = 0;
Cayenne.virtualWrite(V1, LOW);
}
}
void feedingDone()
{
Cayenne.virtualWrite(V3, LOW);
timer.disable(feedingTimer);
}
void getCurrent()
{
unsigned long currentAcc = 0;
unsigned int count = 0;
unsigned long prevMicros = micros() - sampleInterval;
while (count < numSamples)
{
if (micros() - prevMicros >= sampleInterval)
{
int adc_raw = analogRead(currentPin) - adc_zero;
currentAcc += (unsigned long)(adc_raw * adc_raw);
++count;
prevMicros += sampleInterval;
}
}
float rms = sqrt((float)currentAcc / (float)numSamples) * (75.7576 / 1024.0);
int watts = rms * 120;
Cayenne.virtualWrite(V4, rms);
Cayenne.virtualWrite(V11, rms);
Cayenne.virtualWrite(V15, watts);
}
void displayUpdate()
{
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Temp:");
display.print(temp);
display.setCursor(25,30);
display.print("Cayenne");
display.setCursor(30,50);
if (online == true)
{
display.print("Online");
}
else
{
display.print("OFFLINE!");
}
display.display();
}
CAYENNE_CONNECTED()
{
online = true;
}
CAYENNE_DISCONNECTED()
{
online = false;
digitalWrite(filterPin, 0);
}
CAYENNE_OUT(V0)
{
sensors.requestTemperatures();
temp = sensors.getTempFByIndex(0);
Cayenne.virtualWrite(V0, temp);
Cayenne.virtualWrite(V10, temp);
}
CAYENNE_IN(V1)
{
feedButton = getValue.asInt();
}
CAYENNE_IN(V5)
{
filterButton = getValue.asInt();
}
What’s Connected
Arduino Mega
ESP8266-01S
Mega Protoboard
AC/DC 5V 700ma power supply
Dallas 18B20 waterproof temp probe
.96" Bi Color OLED Display
ACS712 Current sensor
hacked generic fish food auto feeder (added 5v relay inside)
4x 5v Relay board
Cascade Canister Filter
100W Aquarium heater
2x Compact Fluorescent Lights
Coming soon: CO2 valve
Connected via Cayenne dashboard:
Arduino Mega (for ambient temp & humidity)
Triggers & Alerts
I use several triggers for this project. I use two triggers to control the aquarium heater based on the temp sensor, two triggers to control the filter when the fish are eating, and a notification/alarm if the temp gets out of range.
Scheduling
The scheduler turn on and off the light everyday and also feeds the fish once a day in the evening.