# STM32F103RB ADC (pics included) strange values for temperature sensor (LM35)

I've connected one battery/2 batteries (GND and A0) and the measuremet displayed on the com26 port is ok. I've connected the LM35 (The LM35 has 1 celsius degree for 10mV measured value) on the VCC and GND and the output pin is connected to the A0(analog input). The value read on the com26 port at room temperature (26 celsius degrees) is 40 celsius degrees. I don't understand what is the problem. The sensor is ok because I've used a multimeter and the output value is 262mV, divided by 10 =26 celsius degrees. but the uC measures 400mV (instead of 262mV) that means 40 degrees. I've used external power source for the LM35 sensor and the same problem. I've used 3.3 and 5V for the LM35 (from the uC board) and the same problem...I'm very courios about this problem ...

** Update: I've made firmware upgrades, stm32 library updates, picture 2 updates... In picture two, first rows readings are from a 1.28V battery the rest are from the LM35 sensor. Battery seemns ok but for LM35 I get 367mV instead of 270mV (measured with a multimeter) I don't know why the value from L35 is not ok from the uC's ADC**

code below:

  #include "test_env.h"
Serial pc(USBTX, USBRX);
DigitalIn userButton(USER_BUTTON);
DigitalOut led(LED1);

// Calculate the corresponding acquisition measure for a given value in mV
#define MV(x) ((0xFFF*x)/3300)

void notify_completion(bool success) {
led = 0;
pc.baud(9600);
int count = 0;
bool enFlag = true;
while (1) {

count++;
if (userButton == 0) {
enFlag = (enFlag == true) ? false : true;
//pc.close();
}
if (enFlag) {
float final = (float) 3300 / 65535 * (float) meas; // normal 0.0008  or 3.3v-3300mV  0,8058608058608059 3300/4095

pc.printf("%d;%d val in mV: %d, tmp:%d  \n", count, meas, (int) final, int(analogValue.read() * 3300));

}

led = !led;

wait(2.f);
}

}


• Can you please also tell what the other values in your picture are? It seems like there is a problem in calculating the voltage from the ADC value. – Douwe66 Feb 9 '15 at 9:54
• Also rather than screen-shots it's better to post code / output as text. It helps others in the future with similar problems find the question via search engines and makes it easier for anyone answering when they can copy the code into an answer with any fixes. – PeterJ Feb 9 '15 at 10:09

The mbed AnalogIn read_u16 function scales the ADC value into the full range of a 16 bit value [0 .. 0xffff] so you are mis-scaling the value in your code. Assuming your shown values were using the 3V3 analog reference then 486 * 3300 / 0xffff == 24 which seems to be a factor of 10 out. There seem tohave been some bugs in the Nucleo port of the ADC functions if you look at some of the comments attached to the web page.

EDIT

In your followup you have used the AnalogIn.read() method as a check but this value is a floating point number scaled between 0 and 1.0. To turn this ADC scaled value back into a voltage you have to multiply by the reference voltage in volts.

Here is an example mbed program that I used to read an light-dependent resistor. Provided the voltage is not too low the result returned by the ADC matches closely with my multimeter. Once it gets below 100mV the ADC gets less accurate. I was using a Nucleo-F030 for this so a similar board:

#include <mbed.h>

Serial serial(SERIAL_TX, SERIAL_RX);

int
main()
{
serial.baud(115200);
while (true)
{
serial.printf("adc: %f V 16bit: %hu value: %d mV\r\n",
wait_us(1000000);
}
}


With this I get the following output (where the multimeter reads 1.19V):

adc: 1.167692 16bit: 23173 value: 1166 mV
adc: 1.232161 16bit: 24405 value: 1228 mV
adc: 1.173333 16bit: 23141 value: 1165 mV
adc: 1.231355 16bit: 24405 value: 1228 mV


Schematic of LDR test circuit using Nucleo-F030R8 board.

simulate this circuit – Schematic created using CircuitLab

• hello patthoyts and 10x for your answer, the precision of the ADC (STM32F103RB) is 12 bits ( so I'm using 486 * 3300 / 0xfff ) or 4096 levels. Why you put 0xffff (65535 levels) ? – Andrew Feb 9 '15 at 10:54
• While the microcontroller you are using may use 12 bit ADC precision - the documentation for the framework API you are using states that they are re-scaling to 16 bit. This is to help code be portable among the various platforms supported by mbed. Some default to 16 bit ADCs and some use 12 bit so the API function rescales them all to 16 bits for consistency. This is documented on the API page for this class. – patthoyts Feb 9 '15 at 10:57
• Update: I've made firmware upgrades, stm32 library updates, picture 2 updates... In picture two, first rows readings are from a 1.28V battery the rest are from the LM35 sensor. Battery seemns ok but for LM35 I get 367mV instead of 270mV (measured with a multimeter) I don't know why the value from L35 is not ok from the uC's ADC** – Andrew Feb 9 '15 at 22:28
• If the analog values are actually converted and scaled to floats, I can't think of a bigger waste of processing time. – Scott Seidman Feb 9 '15 at 22:34
• Hello, Scott Seidman, do you think this scalling is my problem? The floating conversion is a temporary workaround because I've wanted to be sure that no other cast is made, this is not the final solution, is an experimental one. – Andrew Feb 9 '15 at 22:51

I fixed the problem: a 10uF polarized cap (connected between GND and the Analog input) did the work. Input A / D signal was noisy and definitely helped capacitor between GND and input A / D. The system measures fine.