cancel
Showing results for 
Search instead for 
Did you mean: 

Issues with timer driven ADC which results in improper readings

arjun.binu
Associate III

ADC conversion of 3 channels (where DMA requests are performed in continuous mode) is triggered by Timer 3 Trigger out event. Timer 3 is made to follow a PWM generated by Timer 17 by assigning Timer 17 CCR1 to Timer 3 ARR. To validate the ADC readings, we tried varying Timer 17 PWM from 100 to lower values like 20. While doing so, I noticed that ADC readings are not proper and it varies in opposite direction after crossing a certain duty cycle of 50.

I have configured the ADC and timers using CubeMX and later used HAL library.

Your help and support is greatly appreciated.

Relevant code:

ADC initialization

 hadc1.Instance = ADC1;

 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;

 hadc1.Init.Resolution = ADC_RESOLUTION_12B;

 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

 hadc1.Init.LowPowerAutoWait = DISABLE;

 hadc1.Init.LowPowerAutoPowerOff = DISABLE;

 hadc1.Init.ContinuousConvMode = DISABLE;

 hadc1.Init.NbrOfConversion = 3;

 hadc1.Init.DiscontinuousConvMode = DISABLE;

 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T3_TRGO;

 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;

 hadc1.Init.DMAContinuousRequests = ENABLE;

 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_160CYCLES_5;

 hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;

 hadc1.Init.OversamplingMode = DISABLE;

 hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;

Timer 3 initialization

 htim3.Instance = TIM3;

 htim3.Init.Prescaler = 1600 - 1;

 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim3.Init.Period = 1;

 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

 if (HAL_TIM_Base_Init(&htim3) != HAL_OK)

 {

   Error_Handler();

 }

 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

 if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)

 {

   Error_Handler();

 }

 if (HAL_TIM_OnePulse_Init(&htim3, TIM_OPMODE_SINGLE) != HAL_OK)

 {

   Error_Handler();

 }

 sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;

 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

Timer 17 initialization

 htim17.Instance = TIM17;

 htim17.Init.Prescaler = 1600 - 1;

 htim17.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim17.Init.Period = 100 - 1;

 htim17.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 htim17.Init.RepetitionCounter = 0;

 htim17.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

 if (HAL_TIM_Base_Init(&htim17) != HAL_OK)

 {

   Error_Handler();

 }

 if (HAL_TIM_PWM_Init(&htim17) != HAL_OK)

 {

   Error_Handler();

 }

 sConfigOC.OCMode = TIM_OCMODE_PWM1;

 sConfigOC.Pulse = 0;

 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

 sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;

 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

 sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

 sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

 if (HAL_TIM_PWM_ConfigChannel(&htim17, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

 {

   Error_Handler();

 }

 sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;

 sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

 sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

 sBreakDeadTimeConfig.DeadTime = 0;

 sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

 sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

 sBreakDeadTimeConfig.BreakFilter = 0;

 sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

 if (HAL_TIMEx_ConfigBreakDeadTime(&htim17, &sBreakDeadTimeConfig) != HAL_OK)

 {

   Error_Handler();

 }

This was implemented in STM32G030F6P6.

1 ACCEPTED SOLUTION

Accepted Solutions
arjun.binu
Associate III

ADC readings are now proper after configuring Timer 3 properly so as to trigger ADC readings. This was done by selecting the "PWM Generation No output" for Channel 1.

This article helped me to properly configure it.

https://community.st.com/s/article/using-timers-to-trigger-adc-conversions-periodically

Thanks everyone.

View solution in original post

5 REPLIES 5
KiptonM
Lead

I do not see what channels you are reading.

Change:

hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_160CYCLES_5;

 hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;

To the maximum value and see if it makes a difference.

The sample time may be too short which would give the response you describe. This is just a guess.

S.Ma
Principal

When possible route these interconnect signals through gpio and jumper wires to viee and debug better.

FBL
ST Employee

Hello @arjun.binu​,

I can see that you set   hadc1.Init.NbrOfConversion = 3;

Could you explain why ? Actually, this parameter refers to the number of ranks that will be converted within the group sequencer.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

The topic's first sentence literally says that he is converting 3 channels...

arjun.binu
Associate III

ADC readings are now proper after configuring Timer 3 properly so as to trigger ADC readings. This was done by selecting the "PWM Generation No output" for Channel 1.

This article helped me to properly configure it.

https://community.st.com/s/article/using-timers-to-trigger-adc-conversions-periodically

Thanks everyone.