Arduarium Controller

The Arduarium Controller is a project to build a modular open source aquarium monitor/controller. Right now it's in the beta stage as the PCB has been designed and sent to the fab house.

Arduarium Controller Protoype Video:

The PH jumps around a little bit because it's breadboarded and when I move it there's interference.

If the code has been helpful for you a donation is always welcome.

Goals Of Project

Currently Working:

 

 

Planned To Integrate:

  • Be able to view and control aquarium online
  • Automatic feeding
  • Calcium
  • Nitrate
  • Ammonia
  • Oxygen
  • Nitrite

 

Currently all the capabilities for the above have been built into the PCB board; however due to monetary constraints support will be added in as I have time.

Current Code (Rev. 0.5)

The current code has LCD/Keypad (ByVac BV4218), DS1B820 temp sensor, Heater SSR and RTC. It also added in support to configure lights/off/off and and a PH sensor.

Revision Information:

0.5

  • Added in configure and display ORP

0.4.1

  • Changed pH function. 100 values are now average, much more accurate.

0.4

  • Added in support for PH probe
  • Added in PH configuration
  • Added in configuration for lights on/off/fade times
  • Storing values in eeprom so after power outages everything works good
  • commented some code
  • need to clean up some code
  • Fixed a mistake where 1PM was showing up as 13AM
  • Store temperature settings on eeprom

#include <Client.h>
#include <Ethernet.h>
#include <Server.h>
#include <OneWire.h> // one wire library for i2c
#include <Wire.h> // i2c
#include <ByVacLCD.h> // library for byvac i2c lcd controller
#include <WProgram.h>
#include <DS1307.h> // DS1307 RTC library

#define eeprom 0x50

/*
PINS
*/
int temp_ssr = 8; // pin the heater ssr is on
int lights = 9;        // pin the DAYLIGHTS are on
int fans = 10;        // if you have fans to cool leds
int ph_pin = 0;      // analog pin ph sensor is connected to
int orp_pin = 1;


/*
Variables
DO NOT CHANGE
*/
int temp_ssr_toggle; // toggle so we can have 0.5 degree variance so it's not constantly turning on/off
int temp_set = 8025;
int f_lock; // used in config menus to lock in function
int t_lock; // used in config menus to lock in function
char* ampm[] = {"AM", "PM"}; // to hold what time am or pm
int amorpm; // probably could be boolean
int key_pressed; // is the key on the keypad being held down
int num_keys; // number of keys in keypad buffer
int key_pushed; // what key was pressed on keypad
int step; // variable used for functions with steps
int x; // counter for for() loops
long analog_reading; // generic analog reading variable
int ph_reading; // variable to hold ph reading
int counter; // reusable counter variable
int ph10; // value of ph10 solution
int ph7; // value of ph7 solution
int value; // generic value variable
float reading; // generic
int ph_value; // value of ph_reading after math
float last_val; // last value used for averaging
long total; // total of averages
int lights_on; // lights on hour
int lights_off; // lights off hour
int lights_fade_time; // lights fade time in hours
int temp_broken[3];

/*
variables you can change
*/
int temp_variance = 25; // 25 is 1/4 of a degree 50 is 1/2 degree etc.


//ADDRESSES for EEPROM
// DO NOT CHANGE!!

int ph71=1; // hundreds part of ph7 solution
int ph72=2; //10's part of ph7 solution
int ph73=3; // ones part of ph7 solution
int ph101=4; //hundreds part of ph10 solution
int ph102=5; //10's part of ph10 solution
int ph103=6; //ones part of ph10 solution
int lights_on_adr=7; // variable to hold hour of lights on
int lights_off_adr=8; // hold value of hour of lights off
int lights_fade_adr=9; // hold value of how many hours to fade in and out
int temp_adr1=10;
int temp_adr2=11;
int temp_adr3=12;
int temp_adr4=13;

OneWire ds(2); // temp sensor on pin 2
ByVacLCD lcd = ByVacLCD(0x21,4,20); // byvac lcd setup

void setup() {
  Wire.begin();
  Serial.begin(9600);
  lcd.init();
  lcd.backlightOnOff(0);
  pinMode(temp_ssr, OUTPUT);
  analogWrite(fans, 0);
  analogWrite(lights, 0);
 
  int eeprom_values[3];
  eeprom_values[0] = readEEPROM(eeprom, ph71);
  eeprom_values[1] = readEEPROM(eeprom, ph72);
  eeprom_values[2]=readEEPROM(eeprom, ph73);
  ph7 = (eeprom_values[0] * 100) + (eeprom_values[1] * 10) + eeprom_values[2];
 
  eeprom_values[0] = readEEPROM(eeprom, ph101);
  eeprom_values[1] = readEEPROM(eeprom, ph102);
  eeprom_values[2]=readEEPROM(eeprom, ph103);
  ph10 = (eeprom_values[0] * 100) + (eeprom_values[1] * 10) + eeprom_values[2];
 
  eeprom_values[0] = readEEPROM(eeprom, temp_adr1);
  eeprom_values[1] = readEEPROM(eeprom, temp_adr2);
  eeprom_values[2]=readEEPROM(eeprom, temp_adr3);
  eeprom_values[3]=readEEPROM(eeprom, temp_adr4); 
  temp_set = (eeprom_values[0] * 1000) + (eeprom_values[1] * 100) + (eeprom_values[2] * 10) + eeprom_values[3];

  lights_on = readEEPROM(eeprom, lights_on_adr);
  lights_off = readEEPROM(eeprom, lights_off_adr);
  lights_fade_time = readEEPROM(eeprom, lights_fade_adr);
}

void loop(){
  print_time();
  control_lights();
  display_ph(); 
  display_orp();
 
  Serial.print("temp_set: ");
  Serial.println(temp_set);
 
  /*
  switch loop so you can configure everything
  */
  if(lcd.key_query() > 0){
    switch(lcd.get_key()){
      case 0:
        lights_control();
        break;
      case 11:
        config();
        break;
      case 10:
        settings();
        break;
    }
  }
 
/*****************
****** TEMP SENSOR BLOCK
*****************/
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
 
  if ( !ds.search(addr)) {
      ds.reset_search();
      return;
  }


  if ( OneWire::crc8( addr, 7) != addr[7]) {
      return;
  }

  if ( addr[0] != 0x28) {
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);         // Read Scratchpad


  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }


  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Tc_100 = c2f(Tc_100);
 
  Whole = (Tc_100 / 100);  // separate off the whole and fractional portions

  Fract = (Tc_100 % 100);

  if (SignBit) // If its negative
  {
     //Tc_100 = 0 - Tc_100;
  }

  lcd.setCursor(0,0);
  lcd.print("Temp: ");
  lcd.print(Whole);
  lcd.print(".");
  lcd.print(Fract);
/*************
******** END TEMP BLOCK
*********/



  control_temp(Tc_100);

}


void control_temp(int Tc_100){
  if(Tc_100 >= temp_set){
    temp_ssr_toggle = 0;
  }else if(Tc_100 < (temp_set - temp_variance)){
    temp_ssr_toggle = 1;
  }

  if(temp_ssr_toggle == 1){
     digitalWrite(temp_ssr, HIGH);
  }else if(temp_ssr_toggle == 0){
    digitalWrite(temp_ssr, LOW);
  }
}

void print_time(){
  lcd.setCursor(0,13);
  int hour;
  int minute;
  hour = RTC.get(DS1307_HR,true);
  minute = RTC.get(DS1307_MIN,true);
  if(hour < 10 && hour > 0 || hour >= 13 && hour <= 21){
    lcd.print(" ");
  }
  if(hour >= 13 && hour != 0){
    lcd.print(hour - 12);
    amorpm = 1;
  }else if(hour == 0){
    lcd.print("12");
    amorpm = 0;
  }else if(hour == 12){
    lcd.print("12");
    amorpm = 1;
  }else{
    lcd.print(hour);
    amorpm = 0;
  }
  lcd.print(":");
  if(minute < 10){
    lcd.print("0");
  }
  lcd.print(minute);//read minutes without update (false)
  lcd.print(ampm[amorpm]);


 
// convert celsius to farenheit for aquarium
float c2f(float cel) {
return (cel * (9.0/5.0)) + (float)3200;
}

void config(){
  f_lock = 0;
  lcd.clear();
  while(f_lock == 0){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Configuration");
    lcd.setCursor(1,0);
    lcd.print("1 To Set Time");
    lcd.setCursor(2,0);
    lcd.print("2 To Set Temp");
    lcd.setCursor(3,0);
    lcd.print("3 Lights On/Off Time");
    delay(1000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("4 To Configure PH");
    lcd.setCursor(1,0);
    lcd.print("5 To Configure ORP");
    delay(1000);
   
    num_keys = lcd.key_query();
    key_pressed = lcd.get_key();
   
    if(key_pressed == 1){
      set_time();  
    }else if(key_pressed == 2){
      set_temp();
    }else if(key_pressed == 3){
      configure_lights();
    }else if(key_pressed == 4){
      configure_ph();
    }else if(key_pressed == 5){
      configure_orp();
    }
   
    // breakout condition to head back to regular loop
    if(num_keys > 0 && key_pressed == 11){
      lcd.clear();
      f_lock = 1;
    }
  }
}

void set_temp(){
  int key_count = 0;
  f_lock = 0;
  lcd.clear();
 
  while(f_lock == 0){
    lcd.setCursor(0,0);
    lcd.print("Set Temp");
   
    num_keys = lcd.key_query();
    key_pressed = lcd.get_key();
   
    lcd.setCursor(1,0);
    lcd.print("Ex. 79.50 = 7950");
    lcd.setCursor(2,0);
    lcd.print("Set To");
    lcd.setCursor(3,0);
    lcd.print("Press # To Exit");
  if(num_keys > 0){
    if(key_count == 0 && key_pressed < 9 && key_pressed >= 7  && key_pressed != 11){
      temp_set = key_pressed * 1000;
      lcd.setCursor(2,7);
      lcd.print(key_pressed);
      key_count++;
    }else if(key_count == 1 && key_pressed != 11){
      temp_set = temp_set + (key_pressed * 100);   
      lcd.setCursor(2,8);
      lcd.print(key_pressed);
      key_count++;
    }else if(key_count == 2 && key_pressed != 11){
      temp_set = temp_set + (key_pressed * 10);   
      lcd.setCursor(2,9);
      lcd.print(key_pressed);
      key_count++;
    }else if(key_count == 3 && key_pressed != 11){
      temp_set = temp_set + key_pressed;   
      lcd.setCursor(2,10);
      lcd.print(key_pressed);
      key_count++;
    }
  }
 
  if(num_keys > 0 && key_pressed == 10 && key_count < 4){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Need To Set Temp");
    lcd.setCursor(1,0);
    lcd.print("Temp is 4 Digits");
    delay(1500);
    lcd.clear();
    key_count = 0;
    temp_set = 0;
  }
    // breakout condition to head back to regular loop
    if(num_keys > 0 && key_pressed == 11 && key_count == 4){
      //break up value into single digits to write to eeprom
      temp_broken[0] = temp_set / 1000;
      temp_broken[1] = (temp_set - (temp_broken[0] * 1000)) / 100;
      temp_broken[2] = (temp_set - (temp_broken[0] * 1000) - (temp_broken[1] * 100)) / 10;
      temp_broken[3] = (temp_set - (temp_broken[0] * 1000) - (temp_broken[1] * 100) - (temp_broken[2] * 10));
      //write values to eeprom. delay is needed because otherwise it won't work right.
      writeEEPROM(eeprom, temp_adr1, temp_broken[0]);
      delay(20);
      writeEEPROM(eeprom, temp_adr2, temp_broken[1]);
      delay(20);
      writeEEPROM(eeprom, temp_adr3, temp_broken[2]);
      delay(20);
      writeEEPROM(eeprom, temp_adr4, temp_broken[3]);
      delay(20);
     
      lcd.clear();
      f_lock = 1;
    }
  }
}

void settings(){
  f_lock = 0;
  lcd.clear();
 
  while(f_lock == 0){
    lcd.setCursor(0,0);
    lcd.print("Settings");  
   
    num_keys = lcd.key_query();
    key_pressed = lcd.get_key();
   
    lcd.setCursor(1,0);
    lcd.print("Temp: ");
    lcd.setCursor(1,6);
    lcd.print(temp_set / 100);
    lcd.print(".");
    lcd.print(temp_set  % 100);
   
    lcd.setCursor(2,0);
    lcd.print(RTC.get(DS1307_HR,true));
    lcd.print(":");
    lcd.print(RTC.get(DS1307_MIN,false));
    lcd.print(":");
    lcd.print(RTC.get(DS1307_SEC,false));
    lcd.print(" ");                
    lcd.print(RTC.get(DS1307_DATE,false));
    lcd.print("/");
    lcd.print(RTC.get(DS1307_MTH,false));
    lcd.print("/");
    lcd.print(RTC.get(DS1307_YR,false));

    // breakout condition to head back to regular loop
    if(num_keys > 0 && key_pressed == 10){
      lcd.clear();
      f_lock = 1;
    }
  }
}

void set_time(){
  int d_count = 0;
  int n_count = 0;
  int t_lock = 0;
  int month;
  int day;
  int year;
  int hour;
  int minute;
  f_lock = 0;
  lcd.clear();
 
  while(f_lock == 0){
    lcd.setCursor(0,0);
    lcd.print("Set Time");
    lcd.setCursor(3,0);
    lcd.print("Press # To Set");
   
    if(d_count == 0){
      while(t_lock == 0){
        num_keys = lcd.key_query();
        key_pressed = lcd.get_key();

        lcd.setCursor(1,0);
        lcd.print("Month: ");
        if(num_keys > 0 && key_pressed != 11){
          if(n_count == 0){
            month = key_pressed;
            lcd.print(month);
            n_count++;
          }else if(n_count == 1){
            month = (month * 10) + key_pressed;
            lcd.print(month);
            n_count++;
          }
        }
        if(key_pressed == 11){
          lcd.clear();
          t_lock = 1;
        }
      }
      d_count++;
      t_lock = 0;
      n_count = 0;
    }else if(d_count == 1){
      while(t_lock == 0){
        lcd.setCursor(1,0);
        lcd.print("Day: ");

        num_keys = lcd.key_query();
        key_pressed = lcd.get_key();
       
        if(num_keys > 0 && key_pressed != 11){
          if(n_count == 0){
            day = key_pressed;
            lcd.print(day);
            n_count++;
          }else if(n_count == 1){
            day = (day * 10) + key_pressed;
            lcd.print(day);
            n_count++;
          }
        } 
        if(num_keys > 0 && key_pressed == 11){
          t_lock = 1;
        }
      }
      n_count = 0;
      t_lock = 0;
      d_count++;
    }else if(d_count == 2){
      while(t_lock == 0){
        lcd.setCursor(1,0);
        lcd.print("Year: ");
       
        num_keys = lcd.key_query();
        key_pressed = lcd.get_key();
       
        if(num_keys > 0 && key_pressed != 11){
          if(n_count == 0){
            lcd.setCursor(1,6);
            lcd.print(key_pressed);
            n_count++;
          }else if(n_count == 1){
            lcd.setCursor(1,7);
            lcd.print(key_pressed);
            n_count++;
          }else if(n_count == 2){
            lcd.setCursor(1,8);
            lcd.print(key_pressed);
            n_count++;
          }else if(n_count == 3){
            year = key_pressed;
            lcd.setCursor(1,9);
            lcd.print(key_pressed);
            n_count++;
          }
        }
        if(num_keys > 0 && key_pressed == 11 && n_count == 4){
          t_lock = 1;
        }
      }
      n_count = 0;
      t_lock = 0;
      d_count++;
    }else if(d_count == 3){
      lcd.clear();
      while(t_lock == 0){
        lcd.setCursor(2,0);
        lcd.print("In 24HR Format");
        lcd.setCursor(3,0);
        lcd.print("Press # When Done");       
        lcd.setCursor(1,0);
        lcd.print("Hour: ");
       
        num_keys = lcd.key_query();
        key_pressed = lcd.get_key();
       
        if(num_keys > 0 && key_pressed != 11){
          if(n_count == 0){
            hour = key_pressed;
            lcd.print(hour);
            n_count++;
          }else if(n_count == 1){
            hour = (hour * 10) + key_pressed;
            lcd.print(hour);
            n_count++;
          }
        } 
        if(num_keys > 0 && key_pressed == 11){
          t_lock = 1;
        }
      }
      n_count = 0;
      t_lock = 0;
      d_count++;
    }else if(d_count == 4){
      lcd.clear();
      while(t_lock == 0){
        lcd.setCursor(3,0);
        lcd.print("Press # When Done");
        lcd.setCursor(1,0);
        lcd.print("Minute: ");
       
        num_keys = lcd.key_query();
        key_pressed = lcd.get_key();
       
        if(num_keys > 0 && key_pressed != 11){
          if(n_count == 0){
            minute = key_pressed;
            lcd.print(minute);
            n_count++;
          }else if(n_count == 1){
            minute = (minute * 10) + key_pressed;
            lcd.print(minute);
            n_count++;
          }
        } 
        if(num_keys > 0 && key_pressed == 11){
          t_lock = 1;
        }
      }
      d_count++;
      t_lock = 0;
      n_count = 0;
    }else if(d_count == 5){
      RTC.stop();
      RTC.set(DS1307_SEC,1);        //set the seconds
      RTC.set(DS1307_MIN, minute);     //set the minutes
      RTC.set(DS1307_HR, hour);       //set the hours
      RTC.set(DS1307_DOW,4);       //set the day of the week
      RTC.set(DS1307_DATE, day);       //set the date
      RTC.set(DS1307_MTH, month);        //set the month
      RTC.set(DS1307_YR, year);         //set the year
      RTC.start();
      d_count++;
    }else if(d_count == 6){
      lcd.clear();
      lcd.setCursor(1,0);
      lcd.print("Done");
      lcd.setCursor(3,0);
      lcd.print("Press # To Exit");
      delay(1000);
    }
 
    // breakout condition to head back to regular loop
    if(lcd.key_query() > 0 && lcd.get_key() == 11 && d_count == 6){
      lcd.clear();
      f_lock = 1;
    }
  }
}

void control_lights(){
  int hour;
  int minute;
  int stepper;

  hour = RTC.get(DS1307_HR,true);
  minute = RTC.get(DS1307_MIN,false);

  if(hour == lights_on && hour < (lights_on + lights_fade_time)){
    stepper = minute * 4;
    analogWrite(fans, 255);
    analogWrite(lights, stepper);
  }else if(hour >= (lights_on + lights_fade_time) && hour < (lights_off - lights_fade_time)){
    analogWrite(fans, 255);
    analogWrite(lights, 255);
  }else if(hour == (lights_off - lights_fade_time) && hour < lights_off){
    stepper = 240 / minute;
    analogWrite(fans, 255);
    analogWrite(lights, stepper);   
  }else if(hour < lights_on || hour >= lights_off && hour <= 23){
    analogWrite(fans, 0);
    analogWrite(lights,0);
  }

}

/*

A little function to allow you manual control of the lights. ie. you want to show your aquarium off
when you have company.

*/
void lights_control(){
  f_lock = 0;
  lcd.clear();
   
  while(f_lock == 0){
    lcd.setCursor(0,0);
    lcd.print("Lights Control");
    lcd.setCursor(1,0);
    lcd.print("Press 1 Lights On");
    lcd.setCursor(2,0);
    lcd.print("Press 2 Lights Off");   
    lcd.setCursor(3,0);
    lcd.print("Press # To Exit");
   
    if(lcd.key_query() > 0){
      key_pushed = lcd.get_key();
    
      if(key_pushed == 1){
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Lights On");
        for(int x = 0; x <= 255; x++){
          analogWrite(fans,255);
          analogWrite(lights, x);
          delay(100);
        }
      }else if(key_pushed == 2){
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Lights Off");
        for(int x = 255; x >= 0; x--){
          analogWrite(fans,0);
          analogWrite(lights, x);
          delay(100);
        }
      }
        // breakout condition to head back to regular loop
      if(key_pushed == 11){
        lcd.clear();
        f_lock = 1;
      }     
    }
  }
}

/*

Configure the ph monitor. To get here press # and than 4.

The idea is to take measurements of 2 known ph's and than store the values into eeprom. That way we don't have to
come up with a new equation for everybody.

*/
void configure_ph(){
  step = 0;
  counter == 0;
  f_lock = 0;
  int broken[2];
 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Place in PH 10");

  while(f_lock == 0){
    if(step == 0){
      lcd.setCursor(1,0);
      lcd.print("Change To 800");
      lcd.setCursor(2,0);
      lcd.print("Reading: ");
   
      for(x=0; x<100;x++){
        analog_reading += analogRead(ph_pin);
        delay(10);
      }
   
      analog_reading = analog_reading / 100;
   
      lcd.print(analog_reading);

      lcd.setCursor(3,0);
      lcd.print("Press * When Done");
   
      if(lcd.get_key() == 10){
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Writing Values");
        //break up value into single digits to write to eeprom
        broken[0] = analog_reading / 100;
        broken[1]= (analog_reading - (broken[0] * 100)) / 10;
        broken[2] = analog_reading - (broken[0] * 100) - (broken[1] * 10);
        //write values to eeprom. delay is needed because otherwise it won't work right.
        writeEEPROM(eeprom, ph101, broken[0]);
        delay(10);
        writeEEPROM(eeprom, ph102, broken[1]);
        delay(10);
        writeEEPROM(eeprom, ph103, broken[2]);
        delay(10);
        
        step = 1;
       
        delay(1000);
      }     
    }else if(step ==1){
      lcd.setCursor(0,0);
      lcd.print("Place In PH 7");
      lcd.setCursor(1,0);
      lcd.print("Press * To Start");

      if(lcd.get_key() == 10){
          lcd.clear();
          step = 2;
      }    
    }else if(step == 2){    
      lcd.setCursor(0,0);
      lcd.print("This Will Take Time");
      lcd.setCursor(1,0);
      lcd.print("Calculating...");
       
      for(x=0; x<1000;x++){
        analog_reading += analogRead(ph_pin);
        delay(10);
      }
   
      analog_reading = analog_reading / 1000;
      lcd.setCursor(2,0);
      lcd.print("Reading: ");
      lcd.print(analog_reading);
      delay(5000);
      lcd.setCursor(3,0);
      lcd.print("Done");
     
      broken[0] = analog_reading / 100;
      broken[1]= (analog_reading % 100) / 10;
      broken[2] = analog_reading - (broken[0] * 100) - (broken[1] * 10);
     
      writeEEPROM(eeprom, ph71, broken[0]);
      delay(10);
      writeEEPROM(eeprom, ph72, broken[1]);
      delay(10);
      writeEEPROM(eeprom, ph73, broken[2]);
      delay(10);
     
      step = 3;
    }else if(step == 3){
     
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Finished Configuring");
      delay(1000);
      lcd.clear();
      f_lock = 1;
    }
   
    if(lcd.get_key() == 11){
      lcd.clear();
      f_lock = 1;
    }
  }
}

/*

Set up on/off times, moonlight, fade times for your lights

*/
void configure_lights(){
  f_lock = 0;
  t_lock = 0;
  step = 0;
  counter = 0;
  lights_on = 0;
  lights_off = 0;
  lights_fade_time = 0;
  lcd.clear();
  lcd.clear_buffer();
 
  while(f_lock == 0){
    if(step == 0){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set Lights ON");
      lcd.setCursor(1,0);
      lcd.print("24 Hour Format");
      lcd.setCursor(3,0);
      lcd.print("Press # When Done");
      lcd.setCursor(2,0);
      lcd.print("Hour: ");
      while(t_lock == 0){
        key_pressed = lcd.get_key();
     
        if(key_pressed < 10 && counter == 0){
          lights_on = key_pressed;
          lcd.print(lights_on);
          counter++;
        }else if(key_pressed < 10 && counter == 1){
          lights_on = (lights_on * 10) + key_pressed;
          lcd.setCursor(2,7);
          lcd.print(lights_on);
          counter++;
        }else if(key_pressed == 11 && counter >= 1){
          Serial.print("lights on: ");
          Serial.println(lights_on);
          writeEEPROM(eeprom, lights_on_adr, lights_on);
          delay(10);
          step = 1;
          t_lock = 1;  
        }
      }
    }else if(step == 1){
      counter = 0;
      t_lock = 0;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set Lights OFF");
      lcd.setCursor(1,0);
      lcd.print("24 Hour Format");
      lcd.setCursor(3,0);
      lcd.print("Press # When Done");
      lcd.setCursor(2,0);
      lcd.print("Hour: ");
     
      while(t_lock == 0){
        key_pressed = lcd.get_key();
   
        if(key_pressed < 10 && counter == 0){
          lights_off = key_pressed;
          lcd.setCursor(2,7);
          lcd.print(lights_off);
          counter++;
        }else if(key_pressed < 10 && counter == 1){
          lights_off = (lights_off * 10) + key_pressed;
          lcd.setCursor(2,7);
          lcd.print(lights_off);
          counter++;
        }else if(key_pressed == 11 && counter >= 1){
          Serial.print("lights off: ");
          Serial.println(lights_off);
          writeEEPROM(eeprom, lights_off_adr, lights_off);
          delay(10);
          step = 2;
          t_lock = 1;
        }
      }
    }else if(step == 2){
      counter = 0;
      t_lock = 0;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("ON/OFF Fade Time");
      lcd.setCursor(1,0);
      lcd.print("In Hours");
      lcd.setCursor(3,0);
      lcd.print("Press # When Done");
      lcd.setCursor(2,0);
      lcd.print("Hours: ");
     
      while(t_lock == 0){
        key_pressed = lcd.get_key();
     
        if(key_pressed < 10 && counter == 0){
          lights_fade_time = key_pressed;
          lcd.setCursor(2,7);
          lcd.print(lights_fade_time);
          counter++;
        }else if(key_pressed < 10 && counter == 1){
          lights_fade_time = (lights_fade_time * 10) + key_pressed;
          lcd.setCursor(2,7);
          lcd.print(lights_fade_time);
          counter++;
        }else if(key_pressed == 11 && counter >= 1){
          writeEEPROM(eeprom, lights_fade_adr, lights_fade_time);
          delay(10);
          step = 3;
          t_lock = 1;
        }
      }
    }
   
    if(lcd.key_query() > 0 && lcd.get_key() == 11 && step == 3){
      f_lock = 1;
      lcd.clear();
    }
  }
  lcd.clear_buffer();
}

//write to eeprom function
/*
please note that you can only write one byte at a time currently. that means you need to break large numbers up
*/

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.send(data);
  Wire.endTransmission();
}

//read eeprom function

byte readEEPROM(int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

/*

TAKE THE PH READING

*/
int read_ph(){
  reading = 0;
 
  /***************
  TODO:
  either change the number of readings or the delay
  we still want rock solid readings, but faster is better
  */
 
  for(x=0; x<100;x++){
    reading += analogRead(ph_pin);
    delay(10);
  }

  reading = reading / 100;

/*
  If you want accurate results you NEED to configure the PH first. It will store 2 known values into the eeprom.
  that way we don't need to have everybody having a different ph equation.
  */
  ph_value = ((reading - float(ph7)) / ((float(ph10) - float(ph7)) / 3) + 7) * 10;

  return ph_value;
}

/*

DISPLAY PH ON LCD

*/
void display_ph(){
  ph_value = read_ph();
 
  // DISPLAY PH ON 1ST CHARACTER SECOND LINE
  lcd.setCursor(1,0);
  lcd.print("PH: ");
  // separate off the whole part
  value = ph_value / 10;
  lcd.print(value);
  lcd.print(".");
  //separate off the decimal
  value = ph_value  % 10;
  lcd.print(value);
}

void configure_orp(){
  f_lock = 0;
 
  while(f_lock == 0){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Change to 400");
    lcd.setCursor(1,0);
    lcd.print(analogRead(orp_pin));
   
    key_pressed = lcd.get_key();
   
    if(key_pressed == 11){
      f_lock = 1;
    }
  }
}

void display_orp(){
  lcd.setCursor(2,0);
  lcd.print("ORP: ");
  lcd.print(analogRead(orp_pin));
}

Add to Technorati Favorites

Comments

Hello! i saw in the source

Hello!

i saw in the source code, the temperature is in Farenheit not in Celsius. How can I convert it to celsius?

It's actually returned in

It's actually returned in celsius you just need to remove a line.
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Tc_100 = c2f(Tc_100);
 
  Whole = (Tc_100 / 100);  // separate off the whole and fractional portions
Remove the Tc_100 = c2f(Tc_100); line and your temp will be in celsius.

Sounds really promising.. and

Sounds really promising.. and could also be repurposed as a hydroponic controller with the ability to monitor concentrations for the different nutrients.

Are you planning to use the 1280P or the 644? (I am currently using the 644 on the sanguino breakout board)

Can I buy one from you ?

kind regards
gwen hastings

Very good post, thanks a lot.

Very good post, thanks a lot.

Glad you like it. Andrew

Glad you like it.
Andrew

I never thought about the

I never thought about the hydroponics application. It would definitely fit.

I'm actually designing it to work the the 328. Since I'm trying to save outputs/inputs by using I2C and SPI it's got tons of functionality without using hardly any pins.

When they are availabe (which should be very soon) I'll be posting them up here and you can definitely buy one. If you'd like to stay a little more up to date you can contact me and I'll let you know about progress.

Andrew, Simply Brilliant.

Andrew,

Simply Brilliant. Have been looking at ways to build and Aquarium controller for a few years and a friend turned me on to the Arduino yesterday. I was a programmer in a previous career (now I am a Systems Admin so no time for programming in years). How is the LCD/keypad shield coming? Have you thought of how to mount the controller in a water resistant housing? I was thinking the resisters for the PH & ORP and their BNC connectors might need to be connected via short cables so they would go through the side of a case for adjustments, and easy connecting, etc.

Just my 2 cents worth thought

Yeah, everything is going to

Yeah, everything is going to go in a water resistant housing. Attaching things via wires introduces interference so I don't know how well that would work.
The BNC connectors are definitely going to be sticking out the side of the box though... as soon as I find one that I like.

Absolutely Brilliant

Absolutely Brilliant Mate!....this will go far.

Hey mate, very impressed with

Hey mate, very impressed with your work!
But i have a question, if i buy all the seperate shields, and program my audrino with your code, plug it all in, (plus buy the LCD, ect, will i be able to get all the functionality you have currently? and also do you have a schematic of the Entire system, maybe your breadboard?
Thank you very much, sorry if i sound a bit confused

Yep, I only have the 4

Yep, I only have the 4 shields hooked up at the moment. Hooking up all 4 shields (+ lcd etc.) will give you all the functionality I have at the moment.
 
I like your idea of a schematic of the entire system. I'll work on that.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.