Introduction: Arduino Aquaponics: EnvDAQ Upgrade With PH and Dissolved Oxygen

Picture of Arduino Aquaponics:  EnvDAQ Upgrade With PH and Dissolved Oxygen

One compliment we often hear about Environment Data Acquisition Shields (EnvDAQ) is the inclusion of a prototyping area so you can customize the board with other sensors to suit your needs.  And the most requested sensor suite we receive (and is included in the new Aquaponics Controller) are pH and Dissolved Oxygen probes.  Unlike our standard kits, this configuration runs an Arduino Mega R3 in order to handle both probes.

Parts
1 x Arduino Mega R3
1 x Ethernet Shield R3
1 x pH Kit: Probe, Circuit and BNC
1 x DO Kit: Probe, Circuit and BNC
1 x EnvDAQ Shield Kit -or-
       1 x Breadboard
       1 x DHT-22
       1 x 4.7k resistor
       1 x LDR
       1 x 10k resistor
       1 x Bi-Color (Red/Green) 5mm LED
6 x 3-Pin Female Headers (We didn't have that so we used 3 x 10-Pin Female Headers)
8 x Male-Male jumper wires



Step 1: Wiring

Picture of Wiring

Starting with a standard EnvDAQ Shield, insert the female headers in the prototyping area.  The BNC header goes in the first row (Image 2: Right to left).  Insert another female header in second row, again right to left.  This one is used for the bottom of the probe circuit - VCC, PRB, GND.  Finally, place a female header in the next to last row; the last row remains open for the jumper wire.  

Solder the headers in place.  Next, you need to solder the four adjacent pins on the header to connect the bottom of the circuits to the probes circuit header PRB(C) to the BNC and from the bottom circuit GND(C) to the probe GND(BNC).

Insert the jumper wire into the appropriate holes and bend the tip to hold them in place.  Make sure to bend the tips towards the header pin they connect to.

As an optional step you can use cable ties to keep everything nice and neat.

Finally, connect the other end of the jumper wires in the Arduino Mega pins.

Step 2: Arduino Code

Arduino IDE:  1.0.3

Before we amend the code, lets discuss how it works.  The Arduino communicates with the probe circuits over serial, with the circuits handling the grunt work making sense of the probes.  On a 60 second interval, we call each function to get the sensor data.  The pH and DO functions read from serial until a specific sequence is found, building on the preceding characters, formats a return string suitable to a GET request and returns the string.  Finally, a request is made to the webapp.

To start, declare two input strings

// In the declarations, define two input strings
String phsensorstring = "";                                                     
String dosensorstring = "";

Next, we need to set two more Serial connections, but at a 38400 baud rate.  To finish the setup we will reserve space for the input and sensor strings from the circuit.

// In setup(), start the serial outputs
Serial.begin(9600);                 // Standard Serial
Serial2.begin(38400);            // pH Serial
Serial3.begin(38400);            // DO Serial

// Still in setup(), reserve space for the sensor data
phsensorstring.reserve(30);   
dosensorstring.reserve(30);

Just as we get the DHT and LDR values, two new functions are created to get the pH and dissolved oxygen values.  They read from Serial to get the respective values, create a return string formatted as a chunk of the GET request and then reset the sensor string.

// Get pH
String getPH() { 
  char phchar;
  while (phchar != '\r') {
    phchar = (char)Serial2.read(); 
    phsensorstring += phchar;
  }
 
  String ph_reading = "&pH=" + phsensorstring;   
  phsensorstring = "";
  return(ph_reading); 
}

// Get DO
String getDO() {
  char dochar;
  while (dochar != '\r') {
    dochar = (char)Serial3.read(); 
    dosensorstring += dochar;
  }
 
  String do_reading = "&DO=" + dosensorstring;   
  dosensorstring = "";
  return(do_reading);
}

The main loop calls each function on a 60 second interval and then sends a request to the webapp

void loop() {
 
  // Get Temperature and Humidity
  String DHTSensor = "";
  DHTSensor = getDHT();
  Serial.println("DHT: " + DHTSensor);
 
  // Get LDR Reading
  String LDR = "";
  LDR = getLDR();
  Serial.println("LDR: " + LDR);
 
  // PH
  String PHSensorValue = "";
  PHSensorValue = getPH();
  Serial.println("pH: " + PHSensorValue);
 
  // DO
  String DOSensorValue = "";
  DOSensorValue = getDO();
  Serial.println("DO: " + DOSensorValue);
 
  // Send Data to Webapp 
  GAE(webapp + "adacs/arduino?" + DHTSensor + LDR + PHSensorValue + DOSensorValue);
   
  Serial.println("");   
 
  delay(60000);

}

The full Arduino sketch:

/*
  The Environment DAQ (V2) Shield with pH and Dissolved Oxygen Probes.
*/

#include <SPI.h>
#include <Ethernet.h>          // Ethernet Shield
#include <DHT.h>               // DHT.  Credit: Adafruit Industries

// Ethernet Shield
byte mac[] = {  0x90, 0xA2, 0xDA, 0x00, 0xA1, 0x90 };
//byte myIP[] = { 192, 168, 1, 15 };
//byte gateway[] = { 192, 168, 1, 1 };

char server[] = "http://www.myapsystem.appspot.com";
EthernetClient client;

// Makes it easy to change app names
String webapp = "http://www.myapsystem.appspot.com/";

// DHT-22
#define DHTPIN 3
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// Probe input strings                                                     
String phsensorstring = "";                                                     
String dosensorstring = "";                                                     

// DIGITAL PINS
int connectedOn = 6;
int connectedOff = 7;

// ANALOG PINS
int AmbientLDR = A0;          // Light Dependent Resistor

// Sending DHT data
char temp_str[10];            // Temperature string
char rh_str[10];              // Relative Humidity String

void setup() {
  // Start Serial Output
  Serial.begin(9600);          // Standard serial
  Serial2.begin(38400);        // pH serial
  Serial3.begin(38400);        // DO serial
  delay(1000);
 
  // Disable SD card if one in the slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);
 
  // Start Ethernet
  Ethernet.begin(mac);
  //Ethernet.begin(mac, myIP);
  //Ethernet.begin(mac, myIP, gateway); 
  delay(1000);        // Give Ethernet a second to initialize
  Serial.println(Ethernet.localIP());
 
  // Reserve space for the sensor data
  phsensorstring.reserve(30);   
  dosensorstring.reserve(30);
 
 
  // Start DHT
  dht.begin();
 
  // Set Pin Modes
  pinMode(connectedOn, OUTPUT);
  pinMode(connectedOff, OUTPUT);
 
  Serial.println("Setup Complete");
}

void loop() {
 
  // Get Temperature and Humidity
  String DHTSensor = "";
  DHTSensor = getDHT();
  Serial.println("DHT: " + DHTSensor);
 
  // Get LDR Reading
  String LDR = "";
  LDR = getLDR();
  Serial.println("LDR: " + LDR);
 
  // PH
  String PHSensorValue = "";
  PHSensorValue = getPH();
  Serial.println("pH: " + PHSensorValue);
 
  // DO
  String DOSensorValue = "";
  DOSensorValue = getDO();
  Serial.println("DO: " + DOSensorValue);
 
  // Send Data to Webapp 
  GAE(webapp + "adacs/arduino?" + DHTSensor + LDR + PHSensorValue + DOSensorValue);
   
  Serial.println("");   
 
  delay(60000);

}

String getDHT() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT22");
  } else {   
    float ftemp = (((9.0/5.0) * t) + 32.0);
    String temp = dtostrf(ftemp, 3, 1, temp_str);
    String rh = dtostrf(h, 3, 1, rh_str);
   
    String dhtUrl = "Temp=" + temp + "&Humidity=" + rh;
    return(dhtUrl);
  }
}

String getLDR() {
  int ambientLDR = analogRead(AmbientLDR);
  String lightUrl = "&AmbientLDR=" + String(ambientLDR);
  return(lightUrl); 
}

// Returns the current pH value
String getPH() { 
  char phchar;
  while (phchar != '\r') {
    phchar = (char)Serial2.read(); 
    phsensorstring += phchar;
  }
 
  String ph_reading = "&pH=" + phsensorstring;   
  phsensorstring = "";
  return(ph_reading); 
}

// Returns the current Dissolved Oxygen value
String getDO() {
  char dochar;
  while (dochar != '\r') {
    dochar = (char)Serial3.read(); 
    dosensorstring += dochar;
  }
 
  String do_reading = "&DO=" + dosensorstring;   
  dosensorstring = "";
  return(do_reading);
}

void GAE(String link) {
  boolean success = httpRequest(link);
  if (success == true) {
    delay(5000);
   
    boolean currentLineIsBlank = true;
   
    String readString = "";
    char newString[100];
   
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //Serial.write(c);
       
        if (c == '\n' && currentLineIsBlank) {
          //Serial.println("Reached end of request");
          while(client.connected()) {
            char f = client.read();
            readString += f;
          }
        }
       
        if (c == '\n') {
          currentLineIsBlank = true;
        } else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
       
    client.stop();
   
    Serial.println(readString);
  } else {
    Serial.println("Not connected.");
  }
}
   
   
   
boolean httpRequest(String link) { 
  // if there is a successful connection
  if (client.connect(server, 80)) {
    Serial.println("GET " + link + " HTTP/1.0");    // For dev mode
    client.println("GET " + link + " HTTP/1.0");
    client.println(); 
   
    // Turn connected LED on
    digitalWrite(connectedOff, LOW);
    digitalWrite(connectedOn, HIGH);
   
    return true;
  } else {
    // You couldn't make the connection   
    Serial.println("Connection Failed");
    //errors += 1;
    client.stop();
   
    // Turn connected LED on
    digitalWrite(connectedOn, LOW);
    digitalWrite(connectedOff, HIGH);
   
    return false;
  }
}

Comments

chinmayeeraj (author)2017-08-07

I highly appreciate the efforts put in to make the instructions for the pH and DO upgrade circuits. However, I'm unable to find the instructions to make the base EnvDAQ cards. Kindly guide me to the relevant page

Aqualogue (author)2016-12-03

This is a truly terrific project. I too am interested in enter the com code on your portal. Is this accessible to demo? Also, where do you source this EnvDAQ unit?

countryman (author)2016-01-23

I'm trying to register on you webpage. What is the 'Commerical Code' you require? Thanks.

pucheta (author)2015-11-18

I see you dont use isolated power circuit to sensors circuits. You have had measurement problems with interference between ph and oxygen sensors?

JohnN42 (author)2015-08-22

hi, i found this as a good solution for my research. do you have the code for the pH and DO sensor? Also, does it record the data it collects in ASCII file? thanks. you can contact me on my facebook account that i used to sign in. Hope you can contact me as soon as possible.

venman_2 (author)2015-04-21

Does this log and record the data it collects?

percy9427 (author)2015-02-24

Does the EnvDAQ shield support galvanic isolation on the Ph and DO circuits? I found that with multiple sensors in the water, isolation was needed since the sensors read such minuscule voltage differences.

adong13 (author)2014-08-31

where can I find all the parts of this arduino aquaponics? im from the phillipines and i want o have this one

About This Instructable

27,737views

86favorites

License:

Bio: It's pronounced "Iowa Aquaponics".
More by IAquaponics:Arduino Aquaponics:  EnvDAQ Upgrade with pH and Dissolved OxygenArduino Aquaponics:  JSON Pump ControllerArduino Aquaponics:  Real-Time-Clock Part I
Add instructable to: