Just got a KS0429 keyestudio TDS Meter V1.0 that I’ve been trying to setup and calibrate for days following the sample code in the sensor’s wiki without much luck.
The problem I have is that the TDS readings are off. I am using a 1000ppm TDS calibration solution (NaCl at 25C/77F, 90ml).
I wired the black cable from the sensor to the photon’s ground pin, the red cable to the photon’s VIN pin and the yellow cable to the photon’s A1 pin.
When introducing the sensor in the calibration solution I get the following readings:
analogRead(TdsSensorPin) = 1343
temperature (measured manually with an independent thermometer) = 22.2
tds = 668.3 <- [ this should be 1000 I believe ]
The constants I set in the sample firmware are:
#define TdsSensorPin A1
#define VREF 4.8 // analog reference voltage(Volt) of the ADC
#define SCOUNT 30 // sum of sample point
#define ADCRANGE 4096.0
#define KVALUE 0.5
At this point I’ve run out of ideas and I’m hoping someone might be able to shed a light on what part of my code needs to be corrected and why.
Here is the firmware I am using:
#define TdsSensorPin A1
#define VREF 4.8 // analog reference voltage(Volt) of the ADC
#define SCOUNT 30 // sum of sample point
#define ADCRANGE 4096.0 // 1024.0
#define KVALUE 0.5 // 2.12
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;
float temperature = 22.2;
float median_raw = 0;
char vitalsvalue[255];
unsigned long VITALS_INTERVAL = 60000;
unsigned long vitalsStart = 0; // the time the vitals check started
bool vitalsSuccess;
void setup() {
Serial.begin(9600);
Particle.variable("vitalsvalue", vitalsvalue, STRING);
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];
median_raw = getMedianNum(analogBufferTemp,SCOUNT);
averageVoltage = median_raw * (float)VREF / ADCRANGE; // 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 compensationVoltage=averageVoltage/compensationCoefficient; //temperature compensation
tdsValue=(133.42*compensationVoltage*compensationVoltage*compensationVoltage - 255.86*compensationVoltage*compensationVoltage + 857.39*compensationVoltage)*KVALUE; //convert voltage value to tds value
Serial.print("raw:");
Serial.print(median_raw);
Serial.print(" voltage:");
Serial.print(averageVoltage);
Serial.print("V ");
Serial.print(" compensationCoefficient:");
Serial.print(compensationCoefficient);
Serial.print(" compensationVoltage:");
Serial.print(compensationVoltage);
Serial.print(" TDS Value:");
Serial.print(tdsValue);
Serial.println("ppm");
publishVitals();
}
//****************************************************/
}
int publishVitals() {
char jsonData[255];
// assuming lightvalue to be char* or similar
snprintf(jsonData, sizeof(jsonData), "{ \"status\": \"active\", \"raw\": \"%f\", \"voltage\": \"%f\", \"tds\": \"%f\", \"temperature\": \"%f\" }", median_raw, averageVoltage, tdsValue, temperature);
strcpy(vitalsvalue, jsonData);
if ( (millis() - vitalsStart) >= VITALS_INTERVAL ) { // Completed
// This prints the value to the USB debugging serial port (for optional debugging purposes)
Serial.printlnf("data: %s", vitalsvalue);
vitalsStart += VITALS_INTERVAL; // this prevents drift in the intervals
vitalsSuccess = Particle.publish("vitals", vitalsvalue, PRIVATE);
Serial.printlnf("vitals published to the cloud: %s", (vitalsSuccess ? "success" : "failed"));
return 1;
} else {
return 0;
}
}
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;
}
Any help is greatly appreciated!