Go Down

Topic: analog inputs unexpected behavior (Read 326 times) previous topic - next topic

AndresRBDM

Hello guys, have been reading the forum for the last weeks and it has been of great help. This is my first post here since I havent found a similar problem in previous post.
So I am using analog inputs to sample current and voltage. Im trying to build some sort of mpp tracker. Im now just working at 0-5 volts levels testing the algorithm but for some reason for the same code in different sketches I am getting different readings for the exactly same setup. I have been scratching my head for more than 2 hours now but cant find the reason for it.
For my tests I use A0 and A1 and connect them to 5V, 0V and 3.3V. With 0V and 5V test everything worked fine but using 3.3V into A0 to simulate a intermediate value and 5V to A1 I get unexpected readings. the voltage measured at the 3.3 V pin is 3.291V so the expected value of analog read is 673 (~3.286V). When I did the first test while writing the code I got the following values

A0 samples   669   669   669   669   669   669   669   669   669   669   
read time   216   124   124   124   124   124   124   124   124   124   
A1 samples   1023   1023   1023   1023   1023   1023   1023   1023   1023   1023   
read time    120   120   120   120   120   120   120   120   120   120   
A0 samples   670   670   670   670   670   670   670   670   670   670   
read time   120   124   124   124   124   124   124   124   124   124   
A1 samples   1023   1023   1023   1023   1023   1023   1023   1023   1023   1023   
read time    120   120   120   120   120   120   120   120   120   120   


First observation I dont get 673 as expected but 670 which might be close "enough".
I use that same code in other sketch where I added other functionalities but surprisingly the readings are different. Here I get 10 readings and get an average.

A0 avg value    661
A1 avg value    1023
A0 avg value    662
A1 avg value    1023
A0 avg value    662
A1 avg value    1023
A0 avg value    662
A1 avg value    1023
A0 avg value    662
A1 avg value    1023


Now the reading for the same code and setup is different 662 vs 670. That would mean that i will be off by almost 58.58mV from the original value 3.291.

Is this an expected behavior for arduino uno? is it possible that the compiler generates some kind of bug while converting the code? Or am I missing something ? (most probably I am!)

thanks for your help!

jremington

#1
Mar 14, 2018, 11:13 pm Last Edit: Mar 14, 2018, 11:13 pm by jremington
After switching between ADC channels, it is usually a good idea to make two readings, and throw the first one away.

Delta_G

Your readings are all referenced to a 5V reference.  If your 5V reference isn't *exactly* 5V then your readings will seem to be off as the Arduino now thinks that 4.95 is 5V or something. 

There is an internal 1.1V reference that is a bit more stable and might get you better results. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

AndresRBDM

After switching between ADC channels, it is usually a good idea to make two readings, and throw the first one away.
Thanks for the tip, according to the first test it seems all readings are pretty stable even the first one. But i still have to test with the real current sensor and voltage divider to check if that would be necessary.

Your readings are all referenced to a 5V reference.  If your 5V reference isn't *exactly* 5V then your readings will seem to be off as the Arduino now thinks that 4.95 is 5V or something. 

There is an internal 1.1V reference that is a bit more stable and might get you better results. 
Hi @Delta_G, that might explain why i get 670 instead of 673 in the first test, but wouldnt the reference be the same when running both sketches? I mean I understand the reading will be a bit off due to the reference not being 5V exactly but shouldnt I get the same readings in both test if the code is the same?
I just want to find a logical explanation to this before I continue building the whole circuits, otherwise when everything is plugged I'll get strange results and would not know where the problem is!


Delta_G

#4
Mar 15, 2018, 01:38 pm Last Edit: Mar 15, 2018, 01:39 pm by Delta_G
IDK, I can't see any of your code.  Maybe one of them does something wrong.  It really isn't fair to ask anyone why those two codes do things differently if you're not going to show them the codes in question.
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

AndresRBDM

IDK, I can't see any of your code.  Maybe one of them does something wrong.  It really isn't fair to ask anyone why those two codes do things differently if you're not going to show them the codes in question.
My bad! here it comes. First test :
Code: [Select]

void read_IV (){
  int Isense[samples];
  int Vsense[samples];
  int tiempos1[samples];
  int tiempos2[samples];
  for (int i=0; i<samples; i++) {
    int tiempo = micros();
    Isense[i]= analogRead(isense_pin);
    //delayMicroseconds(10);
   
    int tiempo1= micros();
    Vsense[i]=analogRead(vsense_pin);
    //delayMicroseconds(10);      // stabilize ADC S&H
    int tiempo2= micros();
    tiempo= tiempo1 -tiempo;
    tiempo2=tiempo2-tiempo1;
   
    tiempos1[i]=tiempo;
    tiempos2[i]=tiempo2;
   
    }
  Serial.print("A0 samples\t"); 
  print_values(Isense,samples);
  Serial.print("read time\t");
  print_values(tiempos1,samples);
  Serial.print("A1 samples\t");
  print_values(Vsense, samples);
  Serial.print("read time \t");
  print_values(tiempos2, samples);
 
   
//  Isense = Isense/samples;
//  Vsense=Vsense/samples;
//  Serial.print (Isense); Serial.print("\t");
//  Serial.print (Vsense); Serial.print("\t");
//
////  PVvoltage = Vsense*volts_scale;   // Current and voltage scaled by 100
//  PVcurrent = Isense*current_scale;
//  Serial.print (PVvoltage); Serial.print("\t");
//  Serial.print (PVcurrent); Serial.print("\t");

 
  }



second test:
Code: [Select]

void read_IV (){
  int Isense=0;
  int Vsense=0;
  for (int i=0; i<samples; i++) {
    Isense= Isense + analogRead(isense_pin);
    //delayMicroseconds(10);
    Vsense=Vsense + analogRead(vsense_pin);
    //delayMicroseconds(10);      // stabilize ADC S&H evaluate if required
    }
  Isense= Isense/samples;
  Vsense=Vsense/samples;
  PVvoltage = (long)Vsense*volts_scale;   // Current and voltage scaled by 10000
  PVcurrent = (long)Isense*current_scale;
              Serial.print("A0 avg value \t");// only for debug
              Serial.println (Isense);        // only for debug
              Serial.print("A1 avg value \t"); //  only for debug
              Serial.println (Vsense);        //  only for debug
             
  }




Only minor difference is the sample averaging!

MarkT

#6
Mar 15, 2018, 02:56 pm Last Edit: Mar 15, 2018, 02:58 pm by MarkT
After switching between ADC channels, it is usually a good idea to make two readings, and throw the first one away.
Not here, the 0V, 3.3V and 5V rails are less than 10k impedance, the first reading will be absolutely fine.

The 3.3V reading is expected to be 1024 * V3/V5, where V3 and V5 are the actual voltages on those rails,
in other words the ADC only measures the _ratio_ between its input voltage and the 5V rail (unless you've
reprogrammed it to use the Vref or the internal 1.1V reference)

Measure the voltages carefully and you should see the ADC is +/- one count from expected
(unless you are pulling larges currents from the 5 or 3V rails, in which case IR losses will
disturb your measurements)

[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

AndresRBDM

Not here, the 0V, 3.3V and 5V rails are less than 10k impedance, the first reading will be absolutely fine.

The 3.3V reading is expected to be 1024 * V3/V5, where V3 and V5 are the actual voltages on those rails,
in other words the ADC only measures the _ratio_ between its input voltage and the 5V rail (unless you've
reprogrammed it to use the Vref or the internal 1.1V reference)

Measure the voltages carefully and you should see the ADC is +/- one count from expected
(unless you are pulling larges currents from the 5 or 3V rails, in which case IR losses will
disturb your measurements)


MarkT, agree with you. The first test was done to check if any delay would be necessary but it seems is not needed. A0 is connected directly to 3.3 V and A1 to 5V through a 47K resistor  ;D .

Im using the default reference so 5V. Nothing is connected to the board just the analog signals and a Digital pin just to start running the program. What i dont get is why for the same code (99% same due to the averaging) and exact same connections the readings differ! Whatever the voltage at the 5V and 3V rails it is the same for both test so the readings should be the same right?

 

wvmarle

I recall this internal reference is +/- 10% so you still need to do some calibration. After that for an individual system it should indeed be very stable, but not exactly precise. For precision you have to use an external precision reference such as the TL431, the B-grade (highest) of which has a <0.5% error on a 2.495V output.

Arduinos are open hardware so it's easy to look up which exact regulators your board has, and check the data sheet for expected errors. The commonly used AMS1117-5.0 regulator produces anywhere between 4.9V and 5.1V according to the data sheet, that's +/- 2% already. The 3.3V regulator will also have a 1-2% error. The ADC is also not perfect and will add its own error, probably also 1-2%.

The error you measure (58.6 mV on 3300 mV) is less than 1.8% difference. That's not too bad. Those three system errors can easily account for that.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Go Up