Hi all !
Hope everyone is safe and sound.
This little update is to share how I read the TDS value of the nutrients solution and make it available to the Space Vegetables Client.
Hardware
The sensor is from DF Robot . It measures the Total Dissolved Solids. It indicates how many milligrams of soluble solids are dissolved in one liter of water.
EC and TDS
EC stands for Electrical Conductivity and TDS stands for Total Dissolved Solids (already explained above).
They both are widely used to determine the strength of the nutrients solution. There's a debate on if the values should followed or just used as guidelines and follow the instructions on the nutrients solution label.
EC is measured in mS/cm or millisiemens per centimeter. TDS is measured in PPM or parts per million.
The Electrical Conductivity is a measurement of the strength of the nutrient solution. The higher the conductivity, the more dissolved solids there are in the solution. More is not always better - some plants can experience burn if the conductivity is too high.
So, low conductivity implies a low nutrient concentration and high conductivity means more food for the plants.
The TDS is acquired by taking the EC value and do a calculation to determine the TDS. Because TDS is actually a calculation it is really only a guess at what the nutrient concentration is. On top of that, there are three different conversion factors to determine TDS and different manufacturers use different conversion factors. In other words you could test the same solution with two different meters and get two totally different readings. But the EC is read the same by all meters the only difference is the conversion factor.
The recommended ? Take the EC - no conversion is needed.
Hows the conversion if needed ?
To obtain the TDS, just multiply the EC by 1000 and divide by 2.
PPM = EC * 1000 / 2
But because I found only a TDS sensor (within a price range and compatible with Arduino/Raspberry PI), i'm going with TDS.
Here's the wiring of the TDS sensor
The Arduino Pro Micro is connected via USB to the Raspberry PI. It provides power to the Arduino and to the sensor and enables serial communication between both to provide the value of the TDS.
This is not my code. Is from the DF Robot WIKI for the Sensor.
The changes I've made was to just print the TDS value to the serial port (that you can see using the serial monitor in the Arduino IDE) without any additional text.
Here's the code:
/*************************************************** DFRobot Gravity: Analog TDS Sensor / Meter For Arduino <https://www.dfrobot.com/wiki/index.php/Gravity:_Analog_TDS_Sensor_/_Meter_For_Arduino_SKU:_SEN0244> Created 2017-8-22 By Jason <jason.ling@dfrobot.com@dfrobot.com> GNU Lesser General Public License. See <http://www.gnu.org/licenses/> for details. All above must be included in any redistribution /***********Notice and Trouble shooting*************** 1. This code is tested on Arduino Uno and Leonardo with Arduino IDE 1.0.5 r2 and 1.8.2. 2. More details, please click this link: <https://www.dfrobot.com/wiki/index.php/Gravity:_Analog_TDS_Sensor_/_Meter_For_Arduino_SKU:_SEN0244> ****************************************************/ #define TdsSensorPin A0 #define VREF 5.0 // analog reference voltage(Volt) of the ADC #define SCOUNT 30 // sum of sample point int analogBuffer[SCOUNT]; // store the analog value in the array, read from ADC int analogBufferTemp[SCOUNT]; int analogBufferIndex = 0,copyIndex = 0; float averageVoltage = 0,tdsValue = 0,temperature = 25; void setup() { Serial.begin(9600); pinMode(TdsSensorPin,INPUT); } void loop() { static unsigned long analogSampleTimepoint = millis(); if(millis()-analogSampleTimepoint > 40U) { //every 40 milliseconds,read the analog value from the ADC analogSampleTimepoint = millis(); analogBuffer[analogBufferIndex] = analogRead(TdsSensorPin); //read the analog value and store into the buffer analogBufferIndex++; if(analogBufferIndex == SCOUNT) analogBufferIndex = 0; } static unsigned long printTimepoint = millis(); if(millis()-printTimepoint > 800U) { printTimepoint = millis(); for(copyIndex=0;copyIndex<SCOUNT;copyIndex++) analogBufferTemp[copyIndex]= analogBuffer[copyIndex]; averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value float compensationCoefficient=1.0+0.02*(temperature-25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0)); float compensationVolatge=averageVoltage/compensationCoefficient; //temperature compensation tdsValue=(133.42*compensationVolatge*compensationVolatge*compensationVolatge - 255.86*compensationVolatge*compensationVolatge + 857.39*compensationVolatge)*0.5; //convert voltage value to tds value //Serial.print("voltage:"); //Serial.print(averageVoltage,2); //Serial.print("V "); //Serial.print("TDS Value:"); Serial.println(tdsValue,0); //Serial.println("ppm"); } } int getMedianNum(int bArray[], int iFilterLen) { int bTab[iFilterLen]; for (byte i = 0; i<iFilterLen; i++) bTab[i] = bArray[i]; int i, j, bTemp; for (j = 0; j < iFilterLen - 1; j++) { for (i = 0; i < iFilterLen - j - 1; i++) { if (bTab[i] > bTab[i + 1]) { bTemp = bTab[i]; bTab[i] = bTab[i + 1]; bTab[i + 1] = bTemp; } } } if ((iFilterLen & 1) > 0) bTemp = bTab[(iFilterLen - 1) / 2]; else bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2; return bTemp; }
Basically, what the code does is takes 30 samples every 40 milliseconds and calculates the average. The result takes into account the temperature .
I use the value as a guideline to make sure there's nutrients in the solution. I'm following the nutrients manufacturer instructions.
Happy projects and Merry Christmas