2017-10-22 08:58 PM
Hi.
Now I'm trying to implement the ADC on the STM32F103C8.
but I came across some problem when I voltage leveling test.
The code is here
x = getPot()*3.3/4095; //get analog value and convert to volts, 12bit ADC if(x < 2.2) { GPIO_SetBits(GPIOA, GPIO_Pin_4); GPIO_SetBits(GPIOA, GPIO_Pin_5); GPIO_ResetBits(GPIOA, GPIO_Pin_6); GPIO_SetBits(GPIOA, GPIO_Pin_7); alram = 1; } else { GPIO_SetBits(GPIOA, GPIO_Pin_4); GPIO_SetBits(GPIOA, GPIO_Pin_5); GPIO_SetBits(GPIOA, GPIO_Pin_6); GPIO_SetBits(GPIOA, GPIO_Pin_7); alram = 0; }the below is what I got the outputs from ports.
As you can see that above image, when I set 2.2v to the ADC then the output is such a mess.
Is there any good way to get a clean operation?
2017-10-22 09:23 PM
x = getPot()*3.3/4095; //get analog value and convert to volts, 12bit ADC
if(x < 2.2)
==> For precise calculation, don't use float with 24 bit mantissa. Try to use integer or something like Q31 format.
Anything analog has noise, this noise level will have at least one LSB amplitude.
Where comes from the noise? Well, mostly from the application itself, the HW, the wires (acting as antenna), etc...
Typically, for a good analog performance, the analog supply should be separated (MCU package dependent). Then, the wires should be at least a twisted pair with ground. Ideally for some STM32, the ADC has differential mode, then the twisted pair becomes like the USB differential pair, which rejects common mode noise (if the signal is disturbed, so is its 'ground' hence it is cancelled out). After this, characterizing the noise will enable proper digital filtering (oversampling is the generic brute force way to reduce noise)...
2017-10-23 12:01 AM
Thanks, Would you mind giving me some snippet code of that?
2017-10-23 01:19 AM
This is an old SW (Std lib for STM32F437), so to be considered as pseudo code.
________________ Attachments : Adc.c.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hy9n&d=%2Fa%2F0X0000000b6S%2FuUM482hqY39pDlu0Gk0bUg59EpHkMoFVR7EZ5a5boeo&asPdf=falseAdc.h.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyCX&d=%2Fa%2F0X0000000b6R%2F.zmaGMlYUpaGF5CvDWLLVkhc8Kix9HAOO2p0_PD.hz4&asPdf=false2017-10-23 01:41 AM
==> For precise calculation, don't use float with 24 bit mantissa. Try to use integer or something like Q31 format.
The problem of shown calculation is IMHO more a (massive) waste of performance then a loss of precision.
The F1 parts have no FPU, and you gain nothing compared to integer calculations.
if(x < 2.2)
{...
} else ...Apart from that, I suggest a filtering instead of hard decision on just one value ( x ).
2017-10-23 03:09 AM
Another thing to consider when precisely converting ADC value to volts: You should use the actual Vdda value instead of 3.3 V in your equation. See the 'Converting a supply-relative ADC measurement to an absolute voltage value' paragraph on page 375 of the link below (this is the RM for STM32F303, but the principle is the same):
For precise conversion you should know what is the Vdda value and for that, you should do another ADC conversion of Vref_int channel.
Best regards.
2017-10-23 06:27 AM
Digging in the sample code will enable the possibiity to compensate for the MCU VDDA and Temperature (if linear interpolation points are available)