2020-07-16 11:21 AM
Hey Everyone;
I`m working with the STM32L031K6T6 in a project that I require 2 ADC channels.
The ADC look to be working with a huge measurement error:
Project description:
Signal Type: Sinusoidal ( 1Vpp) with offset of 1.492 ( Offset provide by independent power source - Voltage Reference IC , as shown below)
Sampling rate: 1920Hz
For the analog voltage in STM32L031k6T6, i have an independent voltage source with reference in 2.985. ( All voltages were read with Fluke multimeter)
With my sinusoidal source disconnected my voltage in the PA0 is 1.492V
My ADC reading is currently : 2112
However the ADC read should be 2047 for the voltage.
I did some change in the code as suggested in the post :
https://community.st.com/s/question/0D50X0000B8jGv5/adc-accuracy-offset-and-gain-big-errors
Initially without the calibration my adc was reading 2145 ( with high oscilation in the values +- 10 steps)
The I include the calibration:
if (HAL_OK != HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED))
Error_Handler();
The calibration improved my reading and start to read 2130 ( Stable)
My next step was change the sampling time
I change it to 79 cycles
static void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
hadc.Init.DMAContinuousRequests = ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */
/* USER CODE END ADC_Init 2 */
}
Then my reading start to be 2112 ( Stable reading )
My Power supply and reference voltages are pretty clean
Considering the maximum amplitude noise my adc in this board will have error of 5 steps.
However my reading are far away of the correct value.
What I should to do to fix it?
Question 2:
AFter my code run the first time, the code stop in:
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
Everything that I found in internet says about memory problem in my code, however the memory is ok
The error is
How I can solve it?
The STM look a formidable MCU, however the simple code ( Attached Atollic + CubeMX ) is not running well.
Can you help me solve it?
Thank you and best regards
2020-07-16 02:45 PM
This is a very well written question. Thank you for putting in the effort.
From the device datasheet and reference manuals:
> VDDA and VSSA must be connected to VDD and VSS, respectively.
My guess is it's working okay since VDD and VDDA are different by only 0.3V, which is near the max allowed without protection diodes blowing up, but of course accuracy and function are not guaranteed here.
I also see another note:
> Analog power supply and positive reference voltage for the ADC, VDDA ≥ VDD
In either case, your design is violating both of these.
2020-07-16 07:13 PM
Dear TDK,
Thank you for your fast answer.
As you mentioned, the VDDA must be no more that VCC - 0.3.
I did the changes in the board and update voltage reference. Previosly I was with MCP1501T-30 ( 3V) and I updated to MCP1501T-33 (3V3)
As result nothing change about the error.
My DC component is 1.492V that in 12 bits adc with VREF equal to 3.3 (3.285V) should result in the reading 1860 is reading 1925 +- 10. The same 65 steps of the previous case.
The second failure the HardFault_Handler didn't stop with the component change, I believe that this fault is not connected with VDDA.
Can someone explain me what is happening with this ADC?
Thank you and best regards
2020-07-16 07:48 PM
The datasheet doesn't say they need to be close, it says they need to be tied to each other.
My guess is you don't have enough capacitance on VDDA and it gets pulled down during sampling.
The hard fault is almost certainly due to a bug in the code. Perhaps a missing ISR, perhaps a buffer overrun. The SCB register should contain details on what went wrong.