Skip to main content
arjun.binu
Associate III
December 26, 2022
Solved

Issues with timer driven ADC which results in improper readings

  • December 26, 2022
  • 5 replies
  • 2322 views

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.

This topic has been closed for replies.
Best answer by arjun.binu

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.

5 replies

KiptonM
Senior III
January 4, 2023

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
January 5, 2023

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

ST Technical Moderator
January 5, 2023

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 "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Piranha
Principal III
January 9, 2023

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

arjun.binu
arjun.binuAuthorBest answer
Associate III
January 11, 2023

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.