Analog value problem

Hy guys... I am using (trying to use) arduino uno with nextion display to watch batteries voltage and water and fuel tank in the boat... I am using a VDO resistors in the tank which goes from 10-180 ohms (10 when full, 180 when empty), so i added voltage regulator before to step down the voltage on 5V, and I am using 1 k resistor with the VDO tank sensor (resistor) to form a voltage divider... The problem is, when I power on the arduino and the display, everything works fine, but when i start to move VDO tank resistor it is giving me different analog input almoust every time on the same levels althougt the resistence remains the same... For example when it is full it shows 100%, and on the half it shows 50%... when I move the VDO resistor up and down few times, and i return it in the full position, the display shows let's say 86% instead of 100%... And then I move it on the half, it shows 24%... The VDO resistor is 100% good! I disconnected everything and just performed a measurment of an input value only with 1k ohm resistor and VDO resistor (sensor) and the same thing happens... First time on a half tank it flickers around lets say 80-90 and when i move it fast few times, it shows 120 on the half tank where it showed 80-90 last time... I tried taking down average measurments for smoothing, the same thing happens... Here is the code, it is quite simple... thanks in advance

float value;
float value2;
float value3;
int value4;

void setup() {
  Serial.begin(9600);
  pinMode(A0, INPUT); // Pin A0 set as input (batteries)
  pinMode(A1, INPUT); //Pin A1 set as input (batteries)
  pinMode(A2, INPUT); //Pin A2 set as input (water tank)

}

void mjerenje() // function for measuring batteries, diesel and water tank
{
  value = analogRead(A0);
  value = (value * 18 / 1023); // value conversion for batteries

  value2 = analogRead(A1);
  value2 = (value2 * 18 / 1023); // value conversion for batteries

  value3 = analogRead(A2);
  value4 = map(value3, 6, 160, 100, 0); //value conversion for water tank
  value4 = constrain(value4, 0, 100); //constrains the value between 0 and 100



  char buffer[10];
  dtostrf(value, 3, 1, buffer); //converts a float to a char array with 1 decimal
  Serial.print("t0.txt="); //command for printing in a text area (batteries)
  Serial.write(0x22);
  Serial.print(buffer); //prints out batteries value
  Serial.write(0x22);
  Serial.write(0xff); // end command
  Serial.write(0xff);
  Serial.write(0xff);

  char bufer[10];
  dtostrf(value2, 3, 1, bufer); //converts a float to a char array with 1 decimal
  Serial.print("t1.txt="); //command for printing in a text area (batteries)
  Serial.write(0x22);
  Serial.print(bufer); //prints out batteries value
  Serial.write(0x22);
  Serial.write(0xff); // end command
  Serial.write(0xff);
  Serial.write(0xff);

  Serial.print("t5.txt="); //command for printing in a text area (water tank)
  Serial.write(0x22);
  Serial.print(value4); // prints out water tank value
  Serial.write(0x22);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);

}

void loop() {

  static unsigned long vrime; // delay every 5 seconds for debouncing
  if (millis() - vrime >= 5000)
  {
    vrime += 5000;
    mjerenje(); // calling the measure function every 5 seconds
  }

}

As there is just one ADC in an Arduino, it's multiplexed, and switching ADCs takes time to get a proper reading. The common trick is to take two readings, discarding the first, to allow the ADC to get charged properly, like this:

void mjerenje() // function for measuring batteries, diesel and water tank
{
  value = analogRead(A0); // Ignore this one.
  value = analogRead(A0); // The actual reading.
  value = (value * 18 / 1023); // value conversion for batteries

Same for the other readings. This should help stabilising signals big time. Next: use a metal film resistor (much better temperature stability than regular carbon resistors).

Now there is another problem, and that is the resolution. You're using only the lowest 156 points of the 1024-point scale. That's not much. You can overcome this by using the external reference (the AREF pin): create a second voltage divider (using metal film resistors), and connect the mid point of that one to the AREF. A 1K + 200Ω resistor would be a good combination. Make that 10k and 2k for lower current. This would get you to about 900 points difference between full and empty.

Both the reference voltage and the result of the voltage divider are dependent on the sometimes unstable Vcc of the Arduino, but that instability doesn't matter as it's a ratio, so it cancels out, for the most stable results possible.

To lower the current you may consider doubling the value of the pull-up resistors. At 1k you have up to 5 mA passing through.

void mjerenje() // function for measuring batteries, diesel and water tank
{
  value = analogRead(A0); // Ignore this one.
  value = analogRead(A0); // The actual reading.
  value = (value * 18 / 1023); // value conversion for batteries

Do you mean litterally to write this code? I tried everything you suggested except metal film resistor because i don't have them at home... the same thing happens except I now have a bigger resolution because i used external AREF...when i started up the arduino, full was showing me around 60, after i moved VDO resistor few times now shows me 150 on full... now 80... it was showing 200 also for a minute on full... This is driving me crazy

Resistor type is just for temperature stability, and it won't ever cause this great swings.

Use the code like that indeed - two readings for each measurement, discarding the first.

If that doesn't work, it's likely a wiring issue. Measure the actual voltage at the VDO resistor and at the Arduino pin.

Looks like you are right... It is a wiring problem on the breadboard, loose contact somewhere... I feel like an idiot for not cecking that before posting a topic... Thank you friend

Typical for breadboards. Happens a lot. That's why you have to solder everything firmly together when the circuit is finished :slight_smile: