/* * Hydroponics system monitor * J. Devine * Runs on Arduino Pro 5V * Sensors: * DFRobot pHmeter V1.1 * Waterproof DS18B20 water temperature sensor * TMP36 air temperature sensor * HC-SR04 distance sensor (for water level..) * A european two pin plug for EC measurements * Output in CSV; no error handling yet * write out all the results in the following format: * uptime (ms),water level (cm), pH, pH Voltage, water temp (degrees C), air temp (degrees C), RC, EC, PPM * * This code is entirely based on some awesome examples, re-worked for this application * The internal pullup library is needed to avoid an external 4.7k resistor on the DS18B20 * Great blog entry by josh levine @bigjoshlevine - Thanks! I was thinking EXACTLY the same thing * https://wp.josh.com/2014/06/23/no-external-pull-up-needed-for-ds18b20-temp-sensor/ * * PPM code * Modified from ElCheapo Arduino EC-PPM measurments * 28/8/2015 Michael Ratcliffe Mike@MichaelRatcliffe.com * * Pinouts: * * Pin 10 - DS18B20 data pin * Pin 12 - HC-SR04 Trig * Pin 13 - HC-SR04 Echo * Pin A2 - pH Meter V1.1 data (DF Robot breakout) * Pin A3 - TMP36 data pin * Pin D4 - EC/PPM Power * Pin A1 - EC/PPM Pin * Pin A3 - EC/PPM Ground * * Licensed under GPL V3. Read the license here: * https://www.gnu.org/licenses/gpl-3.0.en.html * */ #define SensorPin A2 //pH meter Analog output to Arduino Analog Input 2 #define Offset 0.00 //deviation compensate //#define LED 13 #define samplingInterval 20 #define printInterval 800 #define ArrayLenth 40 //times of collection int pHArray[ArrayLenth]; //Store the average value of the sensor feedback int pHArrayIndex=0; //PPM code // Modified from ElCheapo Arduino EC-PPM measurments // 28/8/2015 Michael Ratcliffe Mike@MichaelRatcliffe.com int R1= 400; int Ra=25; //Resistance of powering Pins int ECPin= A1; int ECGround=A3; int ECPower = 4; //User variales for the PPM/EC measurement float PPMconversion=0.7; float TemperatureCoef = 0.019; //this changes depending on what chemical we are measuring float K=2.85; //Fixed variables //float Temperature=10; variable substituted for Ftemp in this code float EC=0; float EC25 =0; int ppm =0; float raw= 0; float Vin= 5; float Vdrop= 0; float Rc= 0; float buffer=0; //water temperature float Ftemp=10; // DS18S20 Temperature chip i/o #include //this is the onewire version with the pullup high. OneWire ds(10); // on pin 10 int echopin = 13; int trigpin = 12; int vcc = 11; long duration, distance; //tmp36 readout int sensorPin = 0; void setup(void) { //PPM Measurement setup code pinMode(ECPin,INPUT); pinMode(ECPower,OUTPUT);//Setting pin for sourcing current pinMode(ECGround,OUTPUT);//setting pin for sinking current digitalWrite(ECGround,LOW);//We can leave the ground connected permanantly delay(100);// gives sensor time to settle delay(100); //** Adding Digital Pin Resistance to [25 ohm] to the static Resistor *********// // Consule Read-Me for Why, or just accept it as true R1=(R1+Ra);// Taking into acount Powering Pin Resitance pinMode(echopin, INPUT); pinMode(trigpin, OUTPUT); // pinMode(LED,OUTPUT); Serial.begin(9600); // Serial.println("pH meter experiment!"); //Test the serial monitor } void loop(void) { static unsigned long samplingTime = millis(); static unsigned long printTime = millis(); static float pHValue,voltage; if(millis()-samplingTime > samplingInterval) { pHArray[pHArrayIndex++]=analogRead(SensorPin); if(pHArrayIndex==ArrayLenth)pHArrayIndex=0; voltage = avergearray(pHArray, ArrayLenth)*5.0/1024; pHValue = 3.5*voltage+Offset; samplingTime=millis(); } if(millis() - printTime > printInterval) //Every 800 milliseconds, print a numerical, convert the state of the LED indicator { // Serial.print("Voltage:"); // Serial.print(voltage,2); // Serial.print(" pH value: "); // Serial.println(pHValue,2); // digitalWrite(LED,digitalRead(LED)^1); printTime=millis(); } byte i; byte present = 0; byte data[12]; byte addr[8]; int Temp; ds.reset_search(); if ( !ds.search(addr)) { // Serial.print("No more addresses.\n"); ds.reset_search(); return; } // Serial.print("R="); for( i = 0; i < 8; i++) { // Serial.print(addr[i], HEX); // Serial.print(" "); } if ( OneWire::crc8( addr, 7) != addr[7]) { // Serial.print("CRC is not valid!\n"); return; } if ( addr[0] == 0x10) { // Serial.print("Device is a DS18S20 family device.\n"); } else if ( addr[0] == 0x28) { // Serial.print("Device is a DS18B20 family device.\n"); } else { // Serial.print("Device family is not recognized: 0x"); // Serial.println(addr[0],HEX); 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 // Serial.print("P="); // Serial.print(present,HEX); // Serial.print(" "); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); // Serial.print(data[i], HEX); // Serial.print(" "); } Temp=(data[1]<<8)+data[0];//take the two bytes from the response relating to temperature // Serial.println("One, then 0"); // Serial.println(data[1]); //msb // Serial.println(data[0]); //lsb //Temp=Temp>>4;//divide by 16 to get pure celcius readout Ftemp =(Temp * 0.0625); //next line is Fahrenheit conversion //Temp=Temp*1.8+32; // comment this line out to get celcius // Serial.print("T=");//output the temperature to serial port // Serial.print(Temp); // Serial.print(" "); //Serial.print(" fT=");//output the temperature to serial port // Serial.print(Ftemp); // Serial.print(" "); // Serial.print(" CRC="); // Serial.print( OneWire::crc8( data, 8), HEX); // Serial.println(); //getting the voltage reading from the temperature sensor int reading = analogRead(sensorPin); // converting that reading to voltage, for 3.3v arduino use 3.3 float ATvoltage = reading * 5.0; ATvoltage /= 1024.0; // print out the voltage //Serial.print(ATvoltage); Serial.println(" volts"); // now print out the temperature float temperatureC = (ATvoltage - 0.5) * 100 ; //converting from 10 mv per degree wit 500 mV offset //to degrees ((voltage - 500mV) times 100) //Serial.print(temperatureC); Serial.println(" degrees C"); // now convert to Fahrenheit //float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; //Serial.print(temperatureF); Serial.println(" degrees F"); //delay(1000); digitalWrite(trigpin, LOW); // Added this line delayMicroseconds(4); // Added this line digitalWrite(trigpin, HIGH); delayMicroseconds(20); // Added this line digitalWrite(trigpin, LOW); duration = pulseIn(echopin, HIGH); distance = (duration/2) / 29.1; Serial.print(millis()); Serial.print(';'); Serial.print(distance); // if (distance >= 200 || distance <= 0){ // Serial.println("Out of range"); //} //else { //Serial.print(distance); //Serial.println(" cm"); // } //delay(500); //write out all the results in the following format // uptime (ms),water level (cm), pH, pH Voltage, water temp (degrees C), air temp (degrees C), RC, EC, PPM Serial.print(';'); Serial.print(pHValue,2); Serial.print(';'); Serial.print(voltage,2); Serial.print(';'); Serial.print(Ftemp); Serial.print(';'); Serial.print(temperatureC); Serial.print(';'); GetEC(); PrintReadings(); delay(5000); } double avergearray(int* arr, int number){ int i; int max,min; double avg; long amount=0; if(number<=0){ Serial.println("Error number for the array to avraging!/n"); return 0; } if(number<5){ //less than 5, calculated directly statistics for(i=0;imax){ amount+=max; //arr>max max=arr[i]; }else{ amount+=arr[i]; //min<=arr<=max } }//if }//for avg = (double)amount/(number-2); }//if return avg; } void GetEC(){ //************Estimates Resistance of Liquid ****************// digitalWrite(ECPower,HIGH); raw= analogRead(ECPin); raw= analogRead(ECPin);// This is not a mistake, First reading will be low beause if charged a capacitor digitalWrite(ECPower,LOW); //***************** Converts to EC **************************// Vdrop= (Vin*raw)/1024.0; Rc=(Vdrop*R1)/(Vin-Vdrop); Rc=Rc-Ra; //acounting for Digital Pin Resitance EC = 1000/(Rc*K); //*************Compensating For Temperaure********************// EC25 = EC/ (1+ TemperatureCoef*(Ftemp-25.0)); ppm=(EC25)*(PPMconversion*1000); ;} //************************** End OF EC Function ***************************// //***This Loop Is called From Main Loop- Prints to serial usefull info ***// void PrintReadings(){ //Serial.print("Rc: "); Serial.print(Rc); Serial.print(';'); //Serial.print(" EC: "); Serial.print(EC25); Serial.print(';'); //Serial.print(" Simens "); Serial.print(ppm); //Serial.print(" ppm "); Serial.println(';'); }