cancel
Showing results for 
Search instead for 
Did you mean: 

trigger DMA with ADC1 and ADC2 using different timer

VidhiPa
Associate II

Hi, 

I want to have 2 ADC interrupts with DMA. ADC1 is triggered using TIM1 at 4kHz, while ADC2 is triggered using TIM4 at 74kHz. Two different timers are used for different ADC to have different sampling time. The ADC2 is set as Medium priority while the ADC1 is at low priority.

Questions are as below:

1. If more lines are added in "hadc==&hadc2" then it changes the ADC2 interrupt frequency from 74kHz to lower values. I did not understand why ?

2. How to confirm the conversion + sampling time for each ADCs ?

3. There is another timer interrupt triggered at 4 kHz, how to understand the priorities of all 3 Interrupts (ADC1(TIM2), ADC2(TIM4), TIM1) with respect to each other ?

Here is the code snippet. 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc==&hadc1)

{

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);

//2.5 cycles for sampling time

VA=ADC1_buffer1[0]; 
VB=ADC1_buffer1[1]; 
VC=ADC1_buffer1[2]; 
 
IA=ADC1_buffer1[3];
IB=ADC1_buffer1[4];
IC=ADC1_buffer1[5];
 
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
 
Please help me !

}

if(hadc==&hadc1)

{

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);

// 12.5 cycles for sampling time

 X=ADC_buffer1[0];
 Y=ADC_buffer1[1];
 z=ADC_buffer1[2];
 
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);

}

}

10 REPLIES 10

Presentation here is very lacking. Can't see the code related to "hadc==&hadc2"

Post / attach something that is at least functionally complete / compilable.

Identify parts involved.

If you toggle a GPIO in the DMA callback a scope can check frequency of HT/TC interrupts.

Output triggers to additional channels you can get scope pins too.

Priorities shouldn't be a significant issue unless you're doing excessive amount of things in the handlers or call-backs, and/or blocking. Could perhaps explain why frequencies are off, but again code really not showing that.

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

> 1. If more lines are added in "hadc==&hadc2" then it changes the ADC2 interrupt frequency from 74kHz to lower values. I did not understand why ?

You're interrupting too much and the CPU can't keep up. Lower the interrupt rate by increasing buffers and/or using DMA.

> 2. How to confirm the conversion + sampling time for each ADCs ?

The reference manual information is correct. If you want to verify, do 5000 conversions and measure the duration to do all of them. You cannot usefully measure the duration of a single ADC conversion.

> 3. There is another timer interrupt triggered at 4 kHz, how to understand the priorities of all 3 Interrupts (ADC1(TIM2), ADC2(TIM4), TIM1) with respect to each other ?

Interrupts are independent. Highest priority wins. Typically they can pre-empt each other but it can be configured differently.

If you feel a post has answered your question, please click "Accept as Solution".

Hi Tesla, 

Thank you for the response. Please find the corrected code asbelow

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc==&hadc1)

{

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);

//2.5 cycles for sampling time

VA=ADC1_buffer1[0]; 
VB=ADC1_buffer1[1]; 
VC=ADC1_buffer1[2]; 
 
IA=ADC1_buffer1[3];
IB=ADC1_buffer1[4];
IC=ADC1_buffer1[5];
 
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
 
Please help me !

}

if(hadc==&hadc2)

{

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);

// 12.5 cycles for sampling time

 X=ADC_buffer1[0];
 Y=ADC_buffer1[1];
 z=ADC_buffer1[2];
 
/*I cant show the whole code here, but here there are 2 control loops running, which has filtering of the measurement signals coming from ADC, PI controllers, and PWM compare register update. */
 
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);

}

}

I am using Nucleo-G431RB evaluation board. 


@Tesla DeLorean wrote:

If you toggle a GPIO in the DMA callback a scope can check frequency of HT/TC interrupts. 


I am using scope to find out the frequency. 

The other TIM1 interrupt also has a motor control code, running at 4 kHz.

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
 
if (htim==&htim1)
{
/*
filtering the measured signal,
calculate the angle and amplitude, 
PI controller, 
saturators using if, else, 
update the compare registers of PWM
*/
}
}
 

@TDK wrote:

> 1. If more lines are added in "hadc==&hadc2" then it changes the ADC2 interrupt frequency from 74kHz to lower values. I did not understand why ?

You're interrupting too much and the CPU can't keep up. Lower the interrupt rate by increasing buffers and/or using DMA. 

I am using buffers to reduce the control loops to 20kHz and another at 10kHz,

What is the effective way of obtaining ?

  1. Ia, Ib, Ic, Va, Vb, Vc measurement at 4kHz,
  2. one control loop running at 4 kHz, 
  3. Vdc, Vac, IL measurements at 74kHz 
  4. and 2 control loops running at 20 kHz, and 10kHz.

I am using 

ADC1(TIM2) interrupt at 4kHz for the measurement,

ADC2(TIM4) for 2 control loops running at 20 and 10 kHz within TIM4 interrupt running at 74 kHz,

TIM1 interrupt for PWM and control loop running at 4kHz. 

Please find attached screenshot of the ADC1, ADC2 and NVIC settings. 


@TDK wrote:

Interrupts are independent. Highest priority wins. Typically they can pre-empt each other but it can be configured differently.


where can i set the priority of timer interrupt with respect to ADC interrupts ?

 

Thanking you!

I would do the 74 kHz samples on ADC1, and the 20, 10, and 4 kHz samples on ADC2. Use large enough buffers so you only have to process data every few ms or tens of ms. Use decimation or averaging to get 4/10 kHz out of 20kHz sampling.

Interrupt priority is the "preemption priority" column in your screenshot. Numerically lower values are higher priority, 0 is the highest priority, 15 is the lowest priority.

If you feel a post has answered your question, please click "Accept as Solution".

So, If I have understood correctly, What I want to do is too much too ask to MCU. That is the reason Higher frequency ADC2 interrupt changes its frequency when further tasks are added in it  ?

"void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)" function. 

Correct. Generally you should keep interrupts below 10 kHz. And even then, only if they have quick routines. You can do more of course, but 74kHz is pushing it, especially with HAL.

Processing a bunch of samples at once is going to be more computationally efficient than one sample at a time.

If you feel a post has answered your question, please click "Accept as Solution".

Hi TDK, 

thank you for supporting me, but could you explain me better this ?


@TDK wrote:

 Use large enough buffers so you only have to process data every few ms or tens of ms. Use decimation or averaging to get 4/10 kHz out of 20kHz sampling.


because I think I could not make you understand well what I want. give me a chance to explain it better. 

1. ADC2 with DMA is triggered using TIM4 at 74 kHz. inside "HAL_ADC_ConvCpltCallback" I am using a counter so that 2 control loops can run at lower rate i.e. 1 loop at 18.5kHz (every 4th of the interrupt frequency)and another loop at 9.25kHz (every 8th of the interrupt frequency). ADC2 also has 3 channels (No. of conversions) to sample and convert at 12.5 cycles. 

2. ADC1 is triggered with TIM2 at 4kHz, inside "HAL_ADC_ConvCpltCallback" I am taking measured values from ADC buffers to some variables. ADC1 also has 6 channels (No. of conversions) to sample and convert at 2.5 cycles.

3. TIM1 is triggered at 4kHz to switch the PWM as well as use as a interrupt to update the PWM compare registers using control loop running at 4kHz. 

4. TIM3 frequency is 74 kHz to have the PWM for one MOSFET. 

How can I efficiently run the above tasks so that I do not overwork the MCU (SYSCLK and all peripheral clocks = 170 MHz).

5. If I have ADCx clock prescaler set as "Synchronous clock mode divided by 4" i.e. ADC Clock is 42.5 MHz with SYSCLK = 170 MHz. ADC resolution set at 12-bit with total no. of conversions = 3. each channels has Sampling time set to 12.5 Cycles. Please also help me to understand the total conversion time for all the 3 channels, when in Scan mode. Because From the Manual I only understood for one channel Tconv = (Tsamplingtime + 12.5 )*Tadcclk. 

 

I highly appreciate your patience and support. I am new to STM. 

Thanking you !

TDK
Guru

I laid out the guidelines I would use in a previous post and mentioned the issues with interrupts happening at a high frequency. Can't write the actual code for you. I don't think I have the capacity to help much more. Perhaps there is a coworker or someone else more invested in the project.

I suggest working on one thing at a time and optimizing it to use a small amount of computational resources. Interrupts should all be independent so you can combine them at the end.

If you feel a post has answered your question, please click "Accept as Solution".