Different Voltage Values for Turbidity Sensor

Hello everyone,
I am trying to use keyestudio Turbidity Sensor and I am facing some problems in the readings and calibration.
Whenever I place my Turbidity Sensor into a water sample (clean water), it gives a voltage reading which I write it down for calibration, when I finish calibration and coding, the sensor works perfectly.
The problem is let's say I place the Turbidity Sensor next day in the same water sample I was testing, I get different voltage readings from the previous testing, and the voltage readings is slightly decreasing every 5 seconds until in goes to a specific value (which is not the same value everytime), overall the voltage value provided by the sensor is not stable.
I tried applying passive Low Pass Filter to reduce any noise but no significant change.
Does anybody have an idea about how to probably calibrate these sensors?
My first impression is that I may need to use a higher ADC resolution like 16bit instead of the 10bit Arduino ADC, I don't know if that will solve the problem, but that's why I am asking for help here.
Thanks.

The device I am using is described here:
https://wiki.keyestudio.com/KS0414_Keyestudio_Turbidity_Sensor_V1.0

And Also I’ve attached a picture of the circuit I have built for this sensor testing.

And Finally this the code I am running for testing

float SensorValue, turbVol, Turbidity;
float Vclear = 2.82;
void setup() {
  Serial.begin(9600);
  pinMode(A0, INPUT);
}

void loop() {
  SensorValue = analogRead(A0);
  turbVol = SensorValue * (5.0/1023.0);
  Serial.print(SensorValue);
  Serial.print(" | ");
  Serial.println(turbVol);
  delay(2000);
}

Please post a link to the device.
I would look at parameters like accuracy, resolution and repeatability.

Post a link to the device spec sheet.

Post your code in code tag thingies.

Post an image or 2 of your project, all powered up and not properly working.

Hi, @mahmoudfahmy2001
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".

This will help with advice on how to present your code and problems.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

This is the device I am using: KS0414 Keyestudio Turbidity Sensor V1.0 - Keyestudio Wiki

And also here’s a picture of the circuit.
I will add them to the main question also.

For a Uno put a 103 ceramic cap into the Aref pin and ground will help stabilize the readings.

Post your code.

Another thing that may help is to ground one of the unused AD pins, like A3 to gnd. Take a reading off A3 then take a reading from the sensor connected, then take a reading from A3 repeat as wanted. The reading off A3 is discarded.

Another thing to note many breadboards have a split in the two rails at the top and bottom. Making the power and grounds not continuous until a jumper is placed in the middle.

I notice your sensor is connected differently that the example shows.

KS0414 Keyestudio Turbidity Sensor V1.0 - Keyestudio Wiki

Thank you for your help @Idahowalker
I will try your suggested solutions above and provide you with the result.
The sensor is connected similar to the example expect that I've connected a Low Pass Filter to the Data pin of the sensor. I did this to reduce the noise, however I will try to measure with out this filter also.

Thanks for the link. Did You read the warning about the unprotected upper end if the sensor?
Note the inaccurazy of 3.5% of full scale? That makes an uncertainty of 1023 * 0.035 = 35 units reading analog. A wobbling within those 35 units is thinkable, as I think.
No data for repeatability as I could read from the phone.

Hi, @mahmoudfahmy2001
That device has its detector and emitter mounted externally, commercial units have them enclosed in a light tight container.
Your sensor could be influenced by the ambient light.

Can I suggest you do your measurements in a light tight container?
A paper cup by the way is not light tight, to make it light tight stick aluminium foil around it to block any leakage.

Tom... :grinning: :+1: :coffee: :australia:

and if the ambient light comes from 50 or 60 hz mains.....

Thanks for your answer, the problem is that the sensor gives different voltage everytime. Thus, I think that the ambient light is affecting the sensor readings.

Thank you all for helping
It seems that what you said is right because when I used a proper container the Sensor gave the same voltage at every testing trail (in the range of 2.65-2.85 which acceptable).
However, I should mentioned that what @Idahowalker was useful since the readings became more stable than before when I added a 104 ceramic capacitor to the ARef pin.
There is still an acceptable variance in the voltage values but as long as it gives the needed Turbidity Percentage for pure water.

Have you considered adding a software filter?

Here in this task, I use a Simple Kalman filter to smooth the data

void fReadBattery( void * parameter )
{
  float adcValue = 0.0f;
  const float r1 = 50500.0f; // R1 in ohm, 50K
  const float r2 = 10000.0f; // R2 in ohm, 10k potentiometer
  float Vbatt = 0.0f;
  int printCount = 0;
  float vRefScale = (3.3f / 4096.0f) * ((r1 + r2) / r2);
  uint64_t TimePastKalman  = esp_timer_get_time(); // used by the Kalman filter UpdateProcessNoise, time since last kalman calculation
  SimpleKalmanFilter KF_ADC_b( 1.0f, 1.0f, .01f );
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 1000; //delay for mS
  for (;;)
  {
    adc1_get_raw(ADC1_CHANNEL_0); //read and discard
    adcValue = float( adc1_get_raw(ADC1_CHANNEL_0) ); //take a raw ADC reading
    KF_ADC_b.setProcessNoise( (esp_timer_get_time() - TimePastKalman) / 1000000.0f ); //get time, in microsecods, since last readings
    adcValue = KF_ADC_b.updateEstimate( adcValue ); // apply simple Kalman filter
    Vbatt = adcValue * vRefScale;
    xSemaphoreTake( sema_CalculatedVoltage, portMAX_DELAY );
    CalculatedVoltage = Vbatt;
    xSemaphoreGive( sema_CalculatedVoltage );
    
      printCount++;
      if ( printCount == 3 )
      {
      log_i( "Vbatt %f", Vbatt );
      printCount = 0;
      }
    
    TimePastKalman = esp_timer_get_time(); // time of update complete
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    //log_i( "fReadBattery %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete( NULL );
}
////

denyssene/SimpleKalmanFilter: A basic implementation of Kalman Filter for single variable models. (github.com)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.