Skip to main content
JJ.5
Associate II
June 24, 2023
Solved

NUCLEO-H743ZI2, Sampling low frequency signal with high ADC sampling rate causes gaps, glitches.

  • June 24, 2023
  • 13 replies
  • 7479 views

Hello,

I'm currently using the ADC on the NUCLEO-H743ZI2 board to sample a low frequency sine wave signal.

The ADC is configured to DMA, circular buffer, continuous sampling mode and oversampling ratio of 4 with 2 bits shift.

When I set the ADC sampling rate to 250KHz and the sine wave signal is 100Hz.

Here is the sampled signal I got:

JJ5_0-1687644290255.png

 

When I reduced the ADC sampling rate to 125KHz, the sampled data is correct:

JJ5_1-1687644471198.png

Does anyone know what's causing this?

Do I have to reduce the sampling rate?

 

This topic has been closed for replies.
Best answer by waclawek.jan

 

CDC_Transmit_FS((uint8_t*)&adc_buf[BUF_LEN_HALF], BUF_LEN_HALF*2);

 

You are probably hitting the USB FS transfer capability limit.

JW

13 replies

waclawek.jan
Super User
June 25, 2023

Looks like an error in the method how you read out the DMA buffer.

Try sawtooth signal instead of sine.

JW

JJ.5
JJ.5Author
Associate II
June 25, 2023

Thanks for the reply.

I can't generate a sawtooth signal.

But I have verified the data in the DMA buffer is glitched instead of the read method.

Here is the graph by reading the u16_t value directly from the DMA buffer.

The input sine wave is 2KHz and the sampling rate is 350KHz

JJ5_0-1687730979343.png

I'm not sure it's the issue of high sampling rate, it's only taking 175 samples per period of input signal.

I also checked the input signal is a normal 2KHz sine wave using oscilloscope.

JJ.5
JJ.5Author
Associate II
June 25, 2023

 

 

MasterT
Lead II
June 26, 2023

What is  Priority of the DMA channel?

To debug, I always do set-reset IO pin  inside half/ full/ complete dma interrupt, than oscilloscope shows if sampling frequency is correct.

void DMA1_Stream1_IRQHandler(void)
{
 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET); 
 // HAL_DMA_IRQHandler(&hdma_adc1); 
 HAL_DMA_IRQHandler(hadc3.DMA_Handle); 
 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET); 
}

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
 flag_adcv = 1;
 // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); 

// SCB_InvalidateDCache_by_Addr((uint32_t *) &inp[ 0], 2*SIZE_FFT);
 // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); 
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
 flag_adcv = 2;
 // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); 
 
// SCB_InvalidateDCache_by_Addr((uint32_t *) &inp[SIZE_FFT], 2*SIZE_FFT);
 // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); 
}

 

JJ.5
JJ.5Author
Associate II
June 26, 2023

Thanks for the suggestion.

Both DMA priority are set to low.

I am using DMA 1 Stream 0 for ADC and DMA 2 Stream 0 for DAC.

Right now, DAC is producing the sine wave signal gets feed to the ADC input. 

I also did use the HAL_GPIO_WritePin() in half callback and complete callback to check the sampling frequency is correct.

--------------------------------------------------------------------------------

I just found that when I reduce the functions inside the half and complete callback.

The ADC is less likely to produce the glitch. Below is the code and graph.


 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	CDC_Transmit_FS((uint8_t*)&adc_buf[BUF_LEN_HALF], BUF_LEN_HALF*2);
	adc_buf_counter++;

	for(int i=0; i<BUF_LEN_HALF; i++)
	{
		float val = (float)adc_buf[i+BUF_LEN_HALF];
		DSP_buf1[i] = val;
	}
	arm_scale_f32(...);
	arm_biquad_cascade_df1_f32(...);
	arm_biquad_cascade_df1_f32(...);
	arm_mult_f32(...);
	arm_mult_f32(...);
	arm_add_f32(...);
	arm_scale_f32(...);
	arm_mean_f32(...);
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
}

 

JJ5_0-1687742693333.png

 

 

 

 

 

With less functions:

 

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	CDC_Transmit_FS((uint8_t*)&adc_buf[BUF_LEN_HALF], BUF_LEN_HALF*2);
	adc_buf_counter++;

	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
}

 

Glitches are less likely to occur, but they are still there.

 

LCE
Principal II
June 26, 2023

It looks like you are doing a little bit too much in the callbacks, so that the buffers are filled while you are still working with them.

Try to increase DMA buffer size, reduce calculations, maybe even try to use DMA's double buffer mode.

waclawek.jan
waclawek.janBest answer
Super User
June 26, 2023

 

CDC_Transmit_FS((uint8_t*)&adc_buf[BUF_LEN_HALF], BUF_LEN_HALF*2);

 

You are probably hitting the USB FS transfer capability limit.

JW

JJ.5
JJ.5Author
Associate II
June 27, 2023

I am using USB2.0 cable and USB2.0 port. The transfer speed should reach 12Mbits/s. 

And I'm only sending 32bits in roughly 200Ksamples/s to 300Ksamples/s, which shouldn't exceed 12Mbits/s.

I will double check the transfer.

Thank you.

victagayun
Senior III
June 27, 2023

Is this board with STlinkV3? IT can reach 15Mbps thru UART.

JJ.5
JJ.5Author
Associate II
June 27, 2023

I believe it has STlinkV3.

I can try to use it intead of USB FS.

Thanks!

LCE
Principal II
June 27, 2023

With 32 bit x 300k you're at 9.6 Mbit/s, that is quite close to the limit and means that your buffering and transfer scheme has to be on point. I don't know how close to the 12 Mbit/s you can really get.

Anyway, starting with transmitting data only, see it that gets through, keep the callbacks simpler.
Even a x * 100 MHz MCU needs some time for the calculations and data transfers that you put into the callbacks.

You might want to measure processing time of these functions with the cycle counter.

JJ.5
JJ.5Author
Associate II
June 27, 2023

I believe you are correct.

The actual transfer speed is around 7Mbit/s to 8Mbit/s.

Thanks a lot!

I assumed the actual rate is the same on the datasheet, but it's not.:sad_but_relieved_face:

LCE
Principal II
June 28, 2023

You are probably hitting the USB FS transfer capability limit.

That was @waclawek.jan idea, so you should mark his reply as the solution.

I assumed the actual rate is the same on the datasheet, but it's not.

Welcome to the real world... ;)