Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 10 months ago.
Different values between read() and read_u16() on F401RE
When reading voltage from AnalogIn on the F401RE, I get different values when using .read() and .read_u16() methods. I updated the firmware and libraries.
the following code:
AnalogIn analog_value(A0); uint16_t meas = (analog_value.read_u16()); float final_1 = (float) 3300 / 65535 * (float) meas; float final_2 = analog_value.read() * 3300; printf("Voltage: %dmV or %dmV\n\r", (int) final_1, (int) final_2);
provides the following output:
/media/uploads/drinkinggourd/screen_shot_2015-02-25_at_23.15.13.png
I read some other posts related to this, but things are a little confusing between some of the answers, and the official sample code that uses such calculation as:
define MV(x) ((0xFFF*x)/3300)
Thanks!
2 Answers
9 years, 10 months ago.
Julien, just tried your program on Nucleos with both a F401RE and a F103RB, set the voltage using a potentiometer at A0, GND and 3.3V. The output is almost identical, well there's a small difference of 0...10mV due to rounding errors at the internal calculation as well as separate measurements. From your program I just changed the format statement to:
printf("Voltage: Fin1=%5dmV, Fin2=%5dmV\n\r", (int) final_1, (int) final_2);
- Voltage: Fin1= 1274mV, Fin2= 1274mV
- Voltage: Fin1= 1271mV, Fin2= 1281mV
- Voltage: Fin1= 1275mV, Fin2= 1274mV
- Voltage: Fin1= 1272mV, Fin2= 1274mV
- Voltage: Fin1= 1270mV, Fin2= 1271mV
- Voltage: Fin1= 1273mV, Fin2= 1274mV
- Voltage: Fin1= 1274mV, Fin2= 1276mV
- Voltage: Fin1= 1274mV, Fin2= 1274mV
So I could not find the large differences you've seen.
But the define you mentioned is probably an old mistake:
define MV(x) ((0xFFF*x)/3300)
That defines the value of x millivolts, if the analog measurement range equals the 12bit ADC resolution the most STM32 provide. But the internal range of read_u16() is defined as unsigned 16bit as the naming implies. And the range of read() is defined as a float in the range [0.0, 1.0]. You'll find the definitions at the classes of your program within the workspace, e.g. at the mbed compiler.
So your calculation is correct, final_1 calculates from the relation of a 16bit value to it maximum value (65535) multiplied by 3300mV. And final_2 calculates from the precalculated value 0...1 multiplied by again 3300mV.
And if you want to use the define mentioned above: just replace 0xFFF by 0xFFFF when using read_u16(). :-)
Considering you find pretty much the same for both situations, there is a good chance Andy is right: If you have a smaller potentiometer it would work correctly, if he has a large one, possibly on a breadboard with some more capacitance for example, it could cause a dip in the voltage when it is sampled for the second time.
posted by 10 Mar 20159 years, 10 months ago.
Can you try something. Change the code to be
AnalogIn analog_value(A0); float final_2 = analog_value.read() * 3300; uint16_t meas = (analog_value.read_u16()); float final_1 = (float) 3300 / 65535 * (float) meas; printf("Voltage: %dmV or %dmV\n\r", (int) final_1, (int) final_2);
Did the values swap over? If so it's not your calculations.
You are initializing the ADC and then reading it quickly twice in a row. Depending on the impedance of the driver and the input it's quite possible that you would get different values for the two reads.