Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Readable, who the fuck needs a black background.
- Hack a Day
- Projects
- Lists
- Contests
- Stack
- More
- Sign up
- Log In
- Three Dollar EC - PPM Meter [Arduino]
- A project log for Fly Wars : A Hackers Solution To World Hunger
- Using Technology And A Hackers Mindset To Increase Food Security For The Coming Billions Last Updated [21/9/2015]
- Michael RatcliffeMichael Ratcliffe • 09/04/2015 at 13:56•108 Comments
- This Blog will Cover How to build a cheap EC meter for your aquaponics/Hydroponics or water quality related projects. We are not going to get into what the ideal value of PPM or EC is, Just cover how to measure and quantify a fluid.
- We will be using this for the Urine based aquaponics unit, we need to be able to control the strength of the growing fluid in the system but for the person on a budget a EC meter is just to much money. the Solution a $3 EC Meter for any Arduino.
- You can use this to measure drinking water quality to with a small change to the code and changing R1 [see below].
- Parts:
- -MCU of your choice with ADC
- -DS18B20 waterproof temperature sensor
- -500 ohm [or 1kohm resistor]
- -Type A Two Prong american plug to Figure 8
- -Female Socket for Figure 8 connector
- So why are we using a plug:
- -Cheap
- -Available worldwide
- -Standard size [makes calibration easy]
- Use the solid prong one like below and not the one with holes:
- images.jpg
- Wiring it up:
- Note: You want the Solid Prong type plug
- Do not Plug the pronged plug into the mains
- Pinout.png
- Operating Principal
- PPM is calculated from the EC of a fluid, EC is the inverse of the electrical resistance of the fluid. We are estimating the EC or PPM of a fluid by measuring the resistance between two probes [The plug pins] when the plug is submerged in the liquid of interest.
- Ec measurement needs to be done using AC or the liquid of interest is polarised and will give bad readings. This has got to be a great example of asking why instead of just accepting a statement as fact, it turns out we can take a very fast DC reading without suffering polarisation. meaning we can make a really cheap EC sensor.
- Want to use it and dont care how it works? Skip to the main EC code and using the wiring diagram it will work.
- Temperature Compensation
- Temperature has an effect on the conductivity of fluids so it is essential that we compensate for this.
- It is common to use a liner approximation for small temperature changes[1] to convert them to their equivelant EC at 25*C:
- EC25 = EC /( 1 + a (T - 25) )
- EC25- Equivelant EC at 25'C
- EC - Measured EC
- T- Temperature [Decgrees C] of Measurment
- a = 0.019 °C [Commonly used for nutrient solutions]
- Deciding on Value of R1
- //##################################################################################
- //----------- Do not Replace R1 with a resistor lower than 300 ohms ------------
- //##################################################################################
- We can change the Value of R1 in the voltage divider to change the range of EC we want to measure. Below is the Equivalent Voltage divider circuit.
- Voltage Divider.png
- Ra
- Ra the resistance of the digital pins is not stated in the data sheet instead we need to pull it out from a graph.
- Going off the graph on page [387] of the atmel 2560 Data Sheet “Figure 32-25. I/O Pin Output Voltage vs. Source Current (VCC = 5V)”
- V=IR
- Ra= V/I [From Figure] V=0.4 I=1.5e-4 R=25 ohms estimated
- Rc
- Rc will change with EC [PPM] of the measured fluid. we will calculate the maximum and minimum values we expect to see for the range of fluids we wish to measure taking into account temperature changes and the cell constant K. [We will estimate K to be 3 for the plug probe, estimate from previous tests]
- EC = EC25*( 1 + a (T - 25))
- R=(1000/(EC*K)) +Ra
- Min temp=0 [we arnt going to care about EC if the pond is frozen]
- Max Temp = 40 *C [I doubt a pond should be above this]
- Minimum EC 25=0.3 EC= 0.3*(1+0.019*(0-25) Min EC= 0.16 S/sm
- Maximum EC 25= 3 EC= 0.3*(1+0.019*(40-25) Max EC = 3.9 S/cm
- Min Resistance = 1000/(MaxEC*K)+25 = 1000(3.9*2.88) =114 ohms
- Max Resitance = 1000/(MinEC*K)+25 = 1000/(0.16*2.88) = 2195 ohms
- R1
- Now we have enough information to calculate a good value for R1 to get the best resolution over our intended measuring range. We could sum it all up mathematically and differentiate to find the peak, but that hurts my head so I just did a quick excel spreadsheet for the Voltage divider for the EC I expect to see:
- Exel.png
- As we can see we get the largest difference using a value for R1 of 500 ohm, I only had 1Kohm to hand so I will have to live with a little less range.
- So we chose a 500 ohm resistor
- EC – Range /Voltage Range * (5/ADC steps)
- (3.9-0.16)/3.14 * 5/1024 = 5.8e-3 resolution so that is a resolution of 0.0058
- To put this is PPM [Tranchen [Australia] PPMconversion: 0.7] this is a resolution of 4ppm.
- Much more than we need for aquaponics or hydroponics.
- If you want to measure the quality of drinking water you will need to calculate the expected Ec values and increase R1 accordingly.
- Calibration Code
- If you want the best readings from your system it is advisable to calibrate your sensor with some known fluid. But If you dont need to if you use the plug probe shown above, it will still work well.
- >Add your EC in S/cm into the definitions
- >Plug your K value from the terminal window into the main EC code
- you will need to use the modified one wire and Dallas library [download from www.michaelratcliffe.com] or add a pull up for the temperature probe data line [google it]
- /*
- ElCheapo Arduino EC-PPM measurments Calibration
- This Script is used for calibration of the sensor and fine tuning of the Cell Constant K
- Submerge the sensor and temperature probe in the calibration solution and leave for a while so the temperature probe can settle
- Change the value of the calibration solution to suit the solutiton strength
- Stir the probe to make sure the solution is well mixed and upload the code to the arduino
- Open the terminal for an update of the estimated Cell Constant K [should be around 3] and use this new value in the main EC code.
- 28/8/2015 Michael Ratcliffe Mike@MichaelRatcliffe.com
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- Parts:
- -Arduino - Uno/Mega
- -Standard American two prong plug
- -1 kohm resistor
- -DS18B20 Waterproof Temperature Sensor
- See www.MichaelRatcliffe.com/Projects for a Pinout and user guide or consult the Zip you got this code from
- */
- //************************** Libraries Needed To Compile The Script [See Read me In Download] ***************//
- // Both below Library are custom ones [ SEE READ ME In Downloaded Zip If You Dont Know how To install Use them or add a pull up resistor to the temp probe
- #include <OneWire.h>
- #include <DallasTemperature.h>
- //************************* User Defined Variables ********************************************************//
- float CalibrationEC=1.38; //EC value of Calibration solution is s/cm
- //##################################################################################
- //----------- Do not Replace R1 with a resistor lower than 300 ohms ------------
- //##################################################################################
- int R1= 1000;
- int Ra=25; //Resistance of powering Pins
- int ECPin= A0;
- int ECGround=A1;
- int ECPower =A4;
- //*************Compensating for temperature ************************************//
- //The value below will change depending on what chemical solution we are measuring
- //0.019 is generaly considered the standard for plant nutrients [google "Temperature compensation EC" for more info
- float TemperatureCoef = 0.019; //this changes depending on what chemical we are measuring
- //************ Temp Probe Related *********************************************//
- #define ONE_WIRE_BUS 10 // Data wire For Temp Probe is plugged into pin 10 on the Arduino
- const int TempProbePossitive =8; //Temp Probe power connected to pin 9
- const int TempProbeNegative=9; //Temp Probe Negative connected to pin 8
- //***************************** END Of Recomended User Inputs *****************************************************************//
- OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices
- DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.
- float TemperatureFinish=0;
- float TemperatureStart=0;
- float EC=0;
- int ppm =0;
- float raw= 0;
- float Vin= 5;
- float Vdrop= 0;
- float Rc= 0;
- float K=0;
- int i=0;
- float buffer=0;
- //*********************************Setup - runs Once and sets pins etc ******************************************************//
- void setup()
- {
- Serial.begin(9600);
- pinMode(TempProbeNegative , OUTPUT ); //seting ground pin as output for tmp probe
- digitalWrite(TempProbeNegative , LOW );//Seting it to ground so it can sink current
- pinMode(TempProbePossitive , OUTPUT );//ditto but for positive
- digitalWrite(TempProbePossitive , HIGH );
- 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
- sensors.begin();
- 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);
- Serial.println("ElCheapo Arduino EC-PPM measurments Calibration");
- Serial.println("By: Michael Ratcliffe Mike@MichaelRatcliffe.com");
- Serial.println("Free software: you can redistribute it and/or modify it under GNU ");
- Serial.println("");
- Serial.println("Make sure Probe and Temp Sensor are in Solution and solution is well mixed");
- Serial.println("");
- Serial.println("Starting Calibration: Estimated Time 60 Seconds:");
- };
- //******************************************* End of Setup **********************************************************************//
- //************************************* Main Loop - Runs Forever ***************************************************************//
- //Moved Heavy Work To subroutines so you can call them from main loop without cluttering the main loop
- void loop()
- {
- i=1;
- buffer=0;
- sensors.requestTemperatures();// Send the command to get temperatures
- TemperatureStart=sensors.getTempCByIndex(0); //Stores Value in Variable
- //************Estimates Resistance of Liquid ****************//
- while(i<=10){
- digitalWrite(ECPower,HIGH);
- raw= analogRead(ECPin);
- raw= analogRead(ECPin);// This is not a mistake, First reading will be low
- digitalWrite(ECPower,LOW);
- buffer=buffer+raw;
- i++;
- delay(5000);
- };
- raw=(buffer/10);
- sensors.requestTemperatures();// Send the command to get temperatures
- TemperatureFinish=sensors.getTempCByIndex(0); //Stores Value in Variable
- //*************Compensating For Temperaure********************//
- EC =CalibrationEC*(1+(TemperatureCoef*(TemperatureFinish-25.0))) ;
- //***************** Calculates R relating to Calibration fluid **************************//
- Vdrop= (((Vin)*(raw))/1024.0);
- Rc=(Vdrop*R1)/(Vin-Vdrop);
- Rc=Rc-Ra;
- K= 1000/(Rc*EC);
- Serial.print("Calibration Fluid EC: ");
- Serial.print(CalibrationEC);
- Serial.print(" S "); //add units here
- Serial.print("Cell Constant K");
- Serial.print(K);
- if (TemperatureStart==TemperatureFinish){
- Serial.println(" Results are Trustworthy");
- Serial.println(" Safe To Use Above Cell Constant in Main EC code");
- }
- else{
- Serial.println(" Error -Wait For Temperature To settle");
- }
- }
- //************************************** End Of Main Loop **********************************************************************//
- EC PPM Measurement Code
- >If you are using PPM and not EC make sure you note what conversion factor you are using [it isnt universal]
- >Dont call the read function more than once every 5 seconds or you will get bad readings and a damaged probe
- I tested this code in a solution for 48 hours reading at 5 second intervals without any polarisation or probe damage, the longer you leave between readings the longer your probe will last. 5 seconds is the minimum wait between readings not the maximum.
- you will need to use the modified one wire and Dallas library [download from www.michaelratcliffe.com] or add a pull up for the temperature probe data line [google it]
- /*
- ElCheapo Arduino EC-PPM measurments
- This scrip uses a common USA two prong plug and a 47Kohm Resistor to measure the EC/PPM of a Aquaponics/Hydroponics Sytem.
- You could modift this code to Measure other liquids if you change the resitor and values at the top of the code.
- This Program will give you a temperature based feed controller. See Read me in download file for more info.
- 28/8/2015 Michael Ratcliffe Mike@MichaelRatcliffe.com
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
- Parts:
- -Arduino - Uno/Mega
- -Standard American two prong plug
- -1 kohm resistor
- -DS18B20 Waterproof Temperature Sensor
- Limitations:
- -
- -
- See www.MichaelRatcliffe.com/Projects for a Pinout and user guide or consult the Zip you got this code from
- */
- //************************** Libraries Needed To Compile The Script [See Read me In Download] ***************//
- // Both below Library are custom ones [ SEE READ ME In Downloaded Zip If You Dont Know how To install] Use them or add a pull up resistor to the temp probe
- #include <OneWire.h>
- #include <DallasTemperature.h>
- //************************* User Defined Variables ********************************************************//
- //##################################################################################
- //----------- Do not Replace R1 with a resistor lower than 300 ohms ------------
- //##################################################################################
- int R1= 1000;
- int Ra=25; //Resistance of powering Pins
- int ECPin= A0;
- int ECGround=A1;
- int ECPower =A4;
- //*********** Converting to ppm [Learn to use EC it is much better**************//
- // Hana [USA] PPMconverion: 0.5
- // Eutech [EU] PPMconversion: 0.64
- //Tranchen [Australia] PPMconversion: 0.7
- // Why didnt anyone standardise this?
- float PPMconversion=0.7;
- //*************Compensating for temperature ************************************//
- //The value below will change depending on what chemical solution we are measuring
- //0.019 is generaly considered the standard for plant nutrients [google "Temperature compensation EC" for more info
- float TemperatureCoef = 0.019; //this changes depending on what chemical we are measuring
- //********************** Cell Constant For Ec Measurements *********************//
- //Mine was around 2.9 with plugs being a standard size they should all be around the same
- //But If you get bad readings you can use the calibration script and fluid to get a better estimate for K
- float K=2.88;
- //************ Temp Probe Related *********************************************//
- #define ONE_WIRE_BUS 10 // Data wire For Temp Probe is plugged into pin 10 on the Arduino
- const int TempProbePossitive =8; //Temp Probe power connected to pin 9
- const int TempProbeNegative=9; //Temp Probe Negative connected to pin 8
- //***************************** END Of Recomended User Inputs *****************************************************************//
- OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices
- DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.
- float Temperature=10;
- float EC=0;
- float EC25 =0;
- int ppm =0;
- float raw= 0;
- float Vin= 5;
- float Vdrop= 0;
- float Rc= 0;
- float buffer=0;
- //*********************************Setup - runs Once and sets pins etc ******************************************************//
- void setup()
- {
- Serial.begin(9600);
- pinMode(TempProbeNegative , OUTPUT ); //seting ground pin as output for tmp probe
- digitalWrite(TempProbeNegative , LOW );//Seting it to ground so it can sink current
- pinMode(TempProbePossitive , OUTPUT );//ditto but for positive
- digitalWrite(TempProbePossitive , HIGH );
- 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
- sensors.begin();
- 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
- Serial.println("ElCheapo Arduino EC-PPM measurments");
- Serial.println("By: Michael Ratcliffe Mike@MichaelRatcliffe.com");
- Serial.println("Free software: you can redistribute it and/or modify it under GNU ");
- Serial.println("");
- Serial.println("Make sure Probe and Temp Sensor are in Solution and solution is well mixed");
- Serial.println("");
- Serial.println("Measurments at 5's Second intervals [Dont read Ec morre than once every 5 seconds]:");
- };
- //******************************************* End of Setup **********************************************************************//
- //************************************* Main Loop - Runs Forever ***************************************************************//
- //Moved Heavy Work To subroutines so you can call them from main loop without cluttering the main loop
- void loop()
- {
- GetEC(); //Calls Code to Go into GetEC() Loop [Below Main Loop] dont call this more that 1/5 hhz [once every five seconds] or you will polarise the water
- PrintReadings(); // Cals Print routine [below main loop]
- delay(5000);
- }
- //************************************** End Of Main Loop **********************************************************************//
- //************ This Loop Is called From Main Loop************************//
- void GetEC(){
- //*********Reading Temperature Of Solution *******************//
- sensors.requestTemperatures();// Send the command to get temperatures
- Temperature=sensors.getTempCByIndex(0); //Stores Value in Variable
- //************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*(Temperature-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(" EC: ");
- Serial.print(EC25);
- Serial.print(" Simens ");
- Serial.print(ppm);
- Serial.print(" ppm ");
- Serial.print(Temperature);
- Serial.println(" *C ");
- /*
- //********** Usued for Debugging ************
- Serial.print("Vdrop: ");
- Serial.println(Vdrop);
- Serial.print("Rc: ");
- Serial.println(Rc);
- Serial.print(EC);
- Serial.println("Siemens");
- //********** end of Debugging Prints *********
- */
- };
- Got any questions let me know.
- The next tutorial will be on coding a self learning nutrient doser.
- References:
- [1]
- John J. Barron & Colin Ashton "The Effect of Temperature on Conductivity Measurement" Technical Services Department, Reagecon Diagnostics Ltd
- http://www.reagecon.com/pdf/technicalpapers/Effect_of_Temperature_TSP-07_Issue3.pdf
- Previous Log
- Arduino Hall Effect Water Flow Meter
- 08/28/2015 at 00:12 • 2 comments
- Next Log
- Updated Uptime Counter
- 09/12/2015 at 16:28 • 5 comments
- Discussions
- Log In/Sign up to comment
- vikash kumar wrote 12/04/2018 at 10:10
- I'm not able to get the code of the modified onewire dallas library. Kindly help me to get the modified onewire dallas library installed as soon as possible.
- charlie bart wrote 07/20/2018 at 12:54
- Hi everybody.
- I've been successfully reading EC with your code and my arduino UNO & Mega.
- But the thing is, when i try with my ESP32 on an ADC port, i get incoherent voltages. Same thing with an arduino + ADS1115.
- For example :
- Arduino+EC sensor+ 1.55mS calibration solution : Value read : 403 (so 1.96v)
- Arduino+EC sensor+ 2.8mS calibration solution : Value read : 277 (so 1.35v)
- Arduino without sensor plugged : Value read : 1023 (so 5v)
- Arduino+ADS1115@15bits+EC sensor+ 1.55mS calibration solution : Value read : 24560 (so 4.6v)
- Arduino+ADS1115@15bits+EC sensor+ 2.8mS calibration solution : Value read : 25520 (so 4.79v)
- Arduino+ADS1115@15bits without sensor plugged : Value read : 27000 (so 5v under 15bits)
- I'm always using a 1kohms resistor for those tests (between +5v and analog signal).
- I don't have the numbers now for the ESP32+sensor@3.3v but it's the same than with the ADS (voltages read higher than on arduino).
- Do someone have an idea about what is happening here?
- I'm reaching the limit of my basic knowledge here :-(
- 466 wrote 04/10/2018 at 16:29
- Nice project you got here!
- Looking forward, creating an EC meter myself :)
- Would you mind explaining:
- Minimum EC 25=0.3 EC
- and
- Maximum EC 25= 3 EC
- ?
- Where do those values come from?
- (Ok, 3 EC: 3 could be cell constant? but 0.3? did not find any info about it)
- Thanks!
- Cedric wrote 03/03/2018 at 12:39
- Hi Michael, instead of a plug, I'm planning on using pin headers as the probe. However, I'm not sure what should the K constant would be. How did you get the K constant of the plug?
- Zaidan Alif Muttaqin wrote 02/02/2018 at 10:05
- Hi Mike, can you solve my problem? the temperature is always -127 C.
- Cody Lawson wrote 02/28/2018 at 03:36
- Kind of late reply but -127 reading means bad probe or bad connection. If you have another probe try using that. If only one probe try resoldering the contacts or making a new plug depending on how it connects. That error likes to randomly pop up with these probes.
- carlos.bruckner wrote 01/28/2018 at 14:48
- Hi there. I've been playing with a similar project for a few days and fighting some distortion on my readings as the conductivity goes up. My guess is that it is due to polarization.
- I'd like to add a few notes and questions:
- a) When you say "You want the Solid Prong type plug" you meant the right end of the cable or to not use plugs with those little holes on the side? I changed one with the little holes to to another one (solid, round, little smaller area) and I think I got better readings.
- b) The first reading gets discarded. Can I do that before setting the power pin, to high?, ie:
- analogRead(ECPin);// first reading discarded, outside "HIGH zone"
- digitalWrite(ECPower,HIGH); // or PORTA = B00000010; (for digital pin 23)
- sensorValue = analogRead(ECPin);
- digitalWrite(ECPower,LOW);
- That way we spend less time with ECPower "on", so less polarization.
- d) By my calculations, the resolution at a given water resisitance Rw is:
- Res = R1 / (R1+Rw)^2 - which means that you should use R1 as close to Rw as possible.
- However, while having the water at around 974uS (and my system reading it as 530~550ohm), to improve resolution, I used a 520ohm resistor, but the readings were more accurate when I used 1500ohm. My guess is that bigger resistance R1 means less voltage on the water, and thus, less polarization. If that makes sense, I think it is worth noticing.
- Oh, and my K is currently 1.965.
- Anyways, great project and great description, it was exactly what I was looking for.
- Cody Lawson wrote 01/23/2018 at 22:36
- Have you experimented with the ESP32 at all? My RO system already runs on one and it actually has multiple analog inputs compared to the ESP8266. I started to dive into it but the coding looked beyond my level. It appears a lot of the ADC stuff is still in development.
- Some more helpful info. I called HM Digital and found out their inline probe K value is 0.67. Not sure if HM Digital is very big in the UK but in the US they seem to be the standard with RO units. Unfortunately their monitors do not have a data out but doesn't mean you can't recycle the probe! Also no data on the internal thermister (said they would have to call Korea) so an external temp probe is still needed.
- If using their probes (or similar inline push fitting style) make sure you calibrate them INSIDE their T-fitting. The prongs are compressed together slightly while in the fitting and it appears the calibration point takes that into account. Results still weren't perfect using the 0.67 and 10,000K resistor but they were significantly better compared to measuring a naked probe. At ~100ppm I read 105, ~13-14 I read 15.46, and at ~3-4 I read around 6 ppm. My other probe from China I calculated K to be around 0.565. I would say a K range of 0.4-0.8 would be good for these smaller probes.
- Cody Lawson wrote 01/22/2018 at 03:42
- Great project! I ended up making a few interactive graphs with your equations for both the Arduino and ESP8266 boards. Both the K value and R1 have sliders so you can see how each will change the curve. Apparently if you double the R1 value but halve the K value you get roughly the same curve. That was one of a few different "OOOOOHHHHHHH, that's how that works!" moments. At least this felt better than plugging random numbers in and hoping for the best haha.
- Arduino: https://www.desmos.com/calculator/qzbszykkbj
- ESP8266: https://www.desmos.com/calculator/moptex4ufc
- Feel free to reuse these if you want. Figured someone out there would appreciate the little extra help :)
- Graph Instructions:
- The X axis is the "Raw" variable, so 1 - 1024. The Y axis is PPM (Hana 0.5). The adjustable equation is the Red line. Sliders can be found at the bottom of the menu on the left. It starts off with what you chose in the tutorial. The next 4 lines can be used for comparison. They are set near my calibration point with Purple = R 10000, K 0.5; Orange = R 10000, K 1; Blue = 20000, K 0.5; Green = R 20000, K 1. Both Orange and Blue should basically be on top of each other (what I referenced earlier).
- If you want to convert back to EC just delete the *500 at the very end of the equation. To change to a different PPM just change 500 to 640 or 700. To change the range or step of K or R1 click on either the min or max number found on either side of the slide. Everything else I am going to assume you guys can figure it out.
- frozenfritz wrote 12/12/2017 at 17:32
- Hi Michael, I have a question for you: why do you use A8 as a power source? could I also youse a "normal" digital pin from an arduino? Really nice project btw!
- Michael Ratcliffe wrote 12/14/2017 at 19:24
- Yep, for a driving pin you can use a digital pin.
- cyberdevil001 wrote 12/10/2017 at 00:30
- Hi Michael,
- I'm using your code to measure and log the TDS that comes out of my RO system to replace the existing TDS meter. I only noticed that it seems to have issues with the low value measuring of the output water. This is currently 0 while before the DI resin this is between 1 and 7. Currently using the following probe: https://www.aliexpress.com/item/New-G1-4-0-8MPA-Water-quality-probe-TDS-conductivity-test-water-quality-testing-probe/32630094172.html?spm=2114.01010208.3.226.RCrLgm&ws_ab_test=searchweb0_0 . Calibrated this on 342ppm calibration water and when measuring 0 ppm water (demineralised water), it actually shows a few ppm instead:
- Rc: 261350.00 EC: 0.00 Simens 2 ppm 21.69 *C
- Rc: 261350.00 EC: 0.00 Simens 2 ppm 21.75 *C
- Rc: 261350.00 EC: 0.00 Simens 2 ppm 21.75 *C
- Rc: 348816.65 EC: 0.00 Simens 1 ppm 21.75 *C
- Rc: 261350.00 EC: 0.00 Simens 2 ppm 21.75 *C
- Rc: 208870.00 EC: 0.01 Simens 3 ppm 21.75 *C
- Rc: 261350.00 EC: 0.00 Simens 2 ppm 21.75 *C
- Is there a way that I can tweak it so it will be able to measure these low values? Currently using the 1kOhm resistor as I'm still in the process to understand the R1 calculation you did in combination with my probe.
- Thanks!
- cyberdevil001 wrote 12/10/2017 at 02:28
- I did try replacing the 1kOhm resistor with 2 in parallel (=500Ohm) and this seems to provide a bit more stable value, but still off, even with a new sample of 0ppm. (Higher value was spot on the calibration point) Also increased the resolution on the output of EC:
- Rc: 268250.00 EC: 0.0050 Simens 2 ppm 16.56 *C
- Rc: 268250.00 EC: 0.0050 Simens 2 ppm 16.62 *C
- Rc: 178650.00 EC: 0.0075 Simens 3 ppm 16.62 *C
- Rc: 268250.00 EC: 0.0050 Simens 2 ppm 16.62 *C
- Rc: 268250.00 EC: 0.0050 Simens 2 ppm 16.69 *C
- So it is close, but for what I need to use it, the 2ppm off is still to much. Maybe 2 spot calibration could solve it?
- cyberdevil001 wrote 12/11/2017 at 12:07
- Trying to see if a 16-bit ADC will solve my issue. Will update in a few days.
- Michael Ratcliffe wrote 12/14/2017 at 19:31
- Hey, I made this with higher ppm in mind.
- Some advice to make it work better for low EC Start with the ones at the top:
- >Increase the Value of R1 [ google voltage dividers and resistance of fluid vs ppm for your probe constant] I would imagine a 5-10K reistor would work better for you but I haven't done the maths.
- > Potentially increase the delay after powering the probe up and taking a reading [LOW EC water shouldn't polarise easily]
- Also you will need to look for a data sheet on temperature correction for low EC water, the one I use in the sketch is a estimate for hydroponics solutions]. Distilled water will absorb CO2 and this means distilled water does have a very small ppm.
- yuyouliang wrote 11/09/2017 at 05:09
- Dear Michael, thank you for sharing this project. It's wonderful. I have some questions. Could you explain
- why EC = 1000/(Rc*K)? Why the number is 1000? And the unit is S/cm? not ms/cm? Thanks.
- denysafari wrote 10/29/2017 at 09:16
- HI michael , i built this one, but i had a problem. the temperature result is negative (-127). could you help me please?
- kutlutug wrote 11/13/2017 at 08:43
- I have the same problem. My temperature is -127 and my ec numbers dont change in different liquids even wiring the plugs polars with a wire. Is this problem about my hardware?
- wootten91 wrote 09/17/2017 at 18:32
- Hi Michael, Great project. We are a robotics team of students. We are trying to make a remote probe for water quality measurements using the Particle Electron device. This differs from Arduino in that it runs on 3.3 Volts (compared to 5 Volts for Arduino). How can we adapt the wiring to make this work with the Particle? Thanks for the help.
- raychajahanvi21 wrote 08/26/2017 at 06:55
- hey , Micheal I was trying to download zip file but it is showing me error !!!
- can you please help me with that!!
- rleyden310 wrote 08/07/2017 at 19:57
- I added at pH meter ( http://www.ebay.com/itm/Analog-PH-Probe-Sensor-Shield-and-PH-Probe-Kit-For-Arduino-R3-Water-Detect/331878771777?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649 ) and get interference on the pH readings. I even tried using a separate Arduino for the pH reading and the problem persists although as an offset (~ -2 pH) rather than wildly swinging readings. Any ideas how to fix this? Correcting the pH offset caused by the EC probe seems an "OK" solution but I worry that it may not be stable.
- Michael Ratcliffe wrote 08/07/2017 at 20:25
- Sure, its a grounding loop problem. you can solve/fix it mechanically or electrically.
- mechanically: make sure the ph meter and Ec probe are as far away from each other as possible
- Electronically: Turn the EC meter pin's into a high impedance state when not in use. By setting both pins to inputs using pinmode, you will need to reset them as outputs before taking a reading.
- ie pinmode output --> delay(20) --> Read EC -->> pimode input.
- Also this is not the most recent code, just the proof of concept. Check out the main blog for a more recent one with calibration routine etc
- rleyden310 wrote 08/07/2017 at 21:13
- Thanks Michael,
- Setting power and ground pins to input between measurements seems to have corrected the offset. I figured it was a ground problem but tried to fix it by setting the EC pin to output, low - wrong direction. My current hydroponic tank is small so I can only get the probes about 10" apart.
- So where is your main blog? "http://www.michaelratcliffe.com/" seems to be mostly coming soon pages.
- Michael Ratcliffe wrote 08/07/2017 at 21:36
- Glad it solved the issue, if your dosing the pH make sure to keep an eye on the system because the probes dont last long.
- Most of the blogs can be found here:
- https://www.element14.com/community/community/design-challenges/vertical-farming/blog/2015/09/13/automated-green-house-blogs-main-page
- Nuno Silva wrote 05/09/2017 at 12:58
- Hi Michael,
- I am trying to use your hardware and software to test portable water.
- In my case I am calibrating the system for 0,01288 S/cm and I would like to ask you what do you think the R1 should be for this project.
- If I follow your methodology Vdrop and Vout Range I should use a 30K ohms resistor.
- This is the way?
- Thanks
- Nuno
- Michael Ratcliffe wrote 08/07/2017 at 21:41
- I havent tested at such a low EC, you might need to use a larger probe surface area to get it to work.
- But hey give it a shot and see if a 30k works?
- daniele bordignon wrote 03/17/2017 at 09:12
- Hi Michael. Great post, i'm going to build one of these. I was guessing.. The sensor can stay into water 24/24 7/7?
- Is it durable (after 3 or 6 months, one year..)?
- ctsai2 wrote 03/16/2017 at 13:35
- Hi Michael,
- Can I use this code on DUE instead?
- Michael Ratcliffe wrote 08/07/2017 at 21:42
- Sorry for the late reply,
- I havent tested on a DUO, it may have different v drop for digital pins [can work it out from data sheet]. this would be possible, but if it has extra circutry on the analog pins to reduce noise etc it wont work.
- ctsai2 wrote 02/07/2017 at 17:35
- Dear Michael,
- Thanks for sharing this thread.
- I need to make a salinity/EC meter for 35ppt/50000EC. Can I use your setup? And what is the reason R1 should be greater than 300ohm?
- Michael Ratcliffe wrote 02/08/2017 at 10:09
- An EC of 50? That is going to be challenging, I cannot confirm 100%.
- But the bet way may be to reduce the probe area [cut them shorter?] to keep the current reqirments down.
- R1: this limits the current drawn by the probe, the arduino digital pin can only supply 20ma.
- ctsai2 wrote 02/15/2017 at 18:57
- Yes, EC of 50 mS/cm. Right now I have it set up the same as yours. Have not shorten the probes yet. calculated using 1000ohms resistor. Is there anything else I should be concern and change? Because I don't want to burnt any pin. And yes, the conductivity is very high, it's seawater that I am measuring.
- Thank you.
- ctsai2 wrote 03/15/2017 at 18:41
- Michael,
- I cut the probe short, change the Calibration value, but my best R1 for resistor is below 300ohms. Since the seawater resistance is so low compare to fresh/drinking water, can I use R1<300 ohm?
- Or is this reversed, that I can only use R1 > than like 500 ohms?
- Instead of using analog i/o pins, the ECpower is connect directly to the 5V on the board, since we will have constant flowing water so not worrying about polarized the fluid. Does that also up my current drawn to 500mA?
- Trying hard to make this work. Following your direction I already build one to measure 400-1000ppm and it works. Now moving onto measuring 32,000ppm to 40,000ppm
- Thanks for any of your help
- geert2 wrote 02/05/2017 at 13:20
- Dear Michael,
- More respect every day. One remark and a cry for help.
- The Electric conductivity is an indicator for ammonia. Meaning that if you have a dead fish in the system, or algae that start dying, , you will notice the EC going thourgh the roof. This means the EC probe is one of the most telling indicators if something is going very wrong.
- I started to work on the system with a NODECMU Kit, and got quite far.
- However the readings are defenitely not right (see below).
- This could be because of the way the analog port reacts in a NODEMCU, or for any other reeason I don't understand, such as using digital pins for delivering the current.
- I am definitely out of my depth. Could you please help me?
- For water:
- Rc: 32808.05 EC: 0.01 Simens 6 ppm 25.50 *C
- raw993.00
- Vdrop: 3.20
- Rc: 32808.05
- 0.01Siemens
- Salt water:
- Rc: 2752.90 EC: 0.12 Simens 79 ppm 25.50 *C
- raw748.00
- Vdrop: 2.41
- Rc: 2752.90
- 0.13Siemens
- My code:
- //************************** Libraries Needed To Compile The Script [See Read me In Download] ***************//
- // Both below Library are custom ones [ SEE READ ME In Downloaded Zip If You Dont Know how To install] Use them or add a pull up resistor to the temp probe
- #include <Onewire.h>
- #include <Dallastemperature.h>
- //************************* User Defined Variables ********************************************************//
- //##################################################################################
- //----------- Do not Replace R1 with a resistor lower than 300 ohms ------------
- //##################################################################################
- int R1= 1000;
- int Ra=25; //Resistance of powering Pins
- int ECPin= A0;
- int ECGround=D7;
- int ECPower =D8; // originally A4 is used by air pressure measurement
- //*********** Converting to ppm [Learn to use EC it is much better**************//
- // Hana [USA] PPMconverion: 0.5
- // Eutech [EU] PPMconversion: 0.64
- //Tranchen [Australia] PPMconversion: 0.7
- // Why didnt anyone standardise this?
- float PPMconversion=0.64;
- //*************Compensating for temperature ************************************//
- //The value below will change depending on what chemical solution we are measuring
- //0.019 is generaly considered the standard for plant nutrients [google "Temperature compensation EC" for more info
- float TemperatureCoef = 0.019; //this changes depending on what chemical we are measuring
- //********************** Cell Constant For Ec Measurements *********************//
- //Mine was around 2.9 with plugs being a standard size they should all be around the same
- //But If you get bad readings you can use the calibration script and fluid to get a better estimate for K
- float K=2.88;
- //************ Temp Probe Related *********************************************//
- #define ONE_WIRE_BUS D2 // Data wire For Temp Probe is plugged into pin 10 on the Arduino // with me on 2
- //const int TempProbePossitive =8; //Temp Probe power connected to pin 9 // I don' have that?
- //const int TempProbeNegative=9; //Temp Probe Negative connected to pin 8 //should I do that?
- //
- //***************************** END Of Recomended User Inputs *****************************************************************//
- OneWire oneWire(ONE_WIRE_BUS);// Setup a oneWire instance to communicate with any OneWire devices
- DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature.
- //
- float Temperature=10;
- float EC=0;
- float EC25 =0;
- int ppm =0;
- float raw= 0;
- float Vin= 3.3; // is only 3.3 v with esp was 5
- float Vdrop= 0;
- float Rc= 0;
- float buffer=0;
- //*********************************Setup - runs Once and sets pins etc ******************************************************//
- void setup()
- {
- Serial.begin(9600);
- // pinMode(TempProbeNegative , OUTPUT ); //seting ground pin as output for tmp probe
- // digitalWrite(TempProbeNegative , LOW );//Seting it to ground so it can sink current
- // pinMode(TempProbePossitive , OUTPUT );//ditto but for positive
- // digitalWrite(TempProbePossitive , HIGH );
- 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
- // sensors.begin();
- 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
- Serial.println("ElCheapo Arduino EC-PPM measurments");
- Serial.println("By: Michael Ratcliffe Mike@MichaelRatcliffe.com");
- Serial.println("Free software: you can redistribute it and/or modify it under GNU ");
- Serial.println("");
- Serial.println("Make sure Probe and Temp Sensor are in Solution and solution is well mixed");
- Serial.println("");
- Serial.println("Measurments at 5's Second intervals [Dont read Ec morre than once every 5 seconds]:");
- };
- //******************************************* End of Setup **********************************************************************//
- //************************************* Main Loop - Runs Forever ***************************************************************//
- //Moved Heavy Work To subroutines so you can call them from main loop without cluttering the main loop
- void loop()
- {
- GetEC(); //Calls Code to Go into GetEC() Loop [Below Main Loop] dont call this more that 1/5 hhz [once every five seconds] or you will polarise the water
- PrintReadings(); // Cals Print routine [below main loop]
- delay(10000);// original is 5000
- }
- //************************************** End Of Main Loop **********************************************************************//
- //************ This Loop Is called From Main Loop************************//
- void GetEC(){
- //*********Reading Temperature Of Solution *******************//
- sensors.requestTemperatures();// Send the command to get temperatures
- Temperature=sensors.getTempCByIndex(0); //Stores Value in Variable
- //************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*(Temperature-25.0));
- //EC25 = EC;
- 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(" EC: ");
- Serial.print(EC25);
- Serial.print(" Simens ");
- Serial.print(ppm);
- Serial.print(" ppm ");
- Serial.print(Temperature);
- Serial.println(" *C ");
- //********** Usued for Debugging ************
- Serial.print("raw");
- Serial.println(raw);
- Serial.print("Vdrop: ");
- Serial.println(Vdrop);
- Serial.print("Rc: ");
- Serial.println(Rc);
- Serial.print(EC);
- Serial.println("Siemens");
- //********** end of Debugging Prints *********
- };
- Michael Ratcliffe wrote 02/06/2017 at 00:28
- Replied to the second post :)
- Next
- Going up?
- About Us Contact Hackaday.io Give Feedback Terms of Use Privacy Policy Hackaday API
- © 2018 Hackaday
- By using our website and services, you expressly agree to the placement of our performance, functionality, and advertising cookies. Learn More
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement