2024-08-05 04:53 AM - edited 2024-08-05 04:57 AM
Hello everyone,
I’m currently working on a project where I need to generate an ultrasonic trigger signal using the Nucleo-L432KC board and CubeIDE. I can successfully generate a constant 40 kHz signal, and I am able to control the number of cycles in each burst (8, 10, or 20 cycles) and the duration of the wait time (20 to 50 ms) between bursts based on the distance to be measured. However, I’m facing issues when trying to sweep the frequency from 38 kHz to 42 kHz.
My Setup:
1. Board: Nucleo-L432KC
2. Development Environment: CubeIDE
3. Clock Configuration: 80 MHz system clock
4. Timer Configuration:
•Prescaler: 0
•Period: 1000 - 1 (to generate 40 kHz signal)
•Output Compare Mode: Toggle
•Timer instance is TIM2.
The Problem:
I need to sweep the frequency from 38 kHz to 42 kHz at certain intervals. To achieve this, I attempted to dynamically change the timer period. Here’s what I tried:
Dynamic Period Update:
•Adjust the period and pulse width in the main loop.
•Use HAL functions to stop and start the timer to update the settings.
In my main loop, I start with a period of 900 (for 38 kHz) and increment it by 10 to sweep up to 1100 (for 42 kHz). After reaching 1100, I reset the period back to 900 and repeat the process. However, this approach did not work without adding Hal delay for at least 10-20 ms. Therefore, the signal generated is not as expected. There is a significant difference between the generated signal and the expected one. The updates are not being processed correctly, possibly due to the loop running too quickly or the timer not updating as expected.
What I Need:
- Advice on a more effective approach to dynamically change the frequency.
- Alternative methods or configurations that might work better for generating a variable frequency signal.
If it is possible to achieve this with my current Nucleo-L432KC board, any detailed help and guidance would be greatly appreciated. I am open to suggestions and willing to try different approaches to get this working correctly.
Any help or suggestions would be greatly appreciated!
Thanks in advance for your assistance!
2024-08-05 06:17 AM
1. Enable the update interrupt for the timer and change the period in the interrupt handler. Change (increment/decrment) the period in the handler. You might want to add your handler code in the original interrupt handler (in stm32l4xx_it.c), not using HAL for saving cycles. 40k interrupts/s seems possible, but it will keep your CPU core busy. Keep an eye on other irqs like SystemTick, adjust irq priorities if needed.
2. Prepare an array of the periods you want to use over time, setup TIM2 triggered DMA for self-modifying the period. This approach used less CPU cycles, but more RAM for the array.
hth
KnarfB
2024-08-09 01:05 AM
Hi KnarfB,
Thank you for your suggestions. I’ve been working on implementing your first suggestion by enabling the update interrupt and trying to modify the period in the interrupt handler. However, I’ve run into some issues, and after a certain point, the settings seem to get mixed up, leading to unexpected behavior.
I also tried setting up the TIM2-triggered DMA as you suggested for self-modifying the period, but I’m struggling to get that working correctly as well. I’m not entirely sure if the problem is with the DMA setup, the interrupt handling, or something else entirely.
Would you be able to provide more detailed guidance or examples on how to properly implement these approaches? I think I might be missing some critical steps.
Thanks again for your help!
2024-08-09 07:16 AM
Init TIM2 to a period of 900-1.
Init TIM2_CH1 to Output Compare CH1.
Let PA5 be the TIM2_CH1 output pin.
Set Output Compare Channel 1 Mode to Toggle on match
Leave Pulse value at 0.
in NVIC Settings tab, activate TIM2 global interrupt.
In main.c implement a HAL callback for the interrupt handler like so:
/* USER CODE BEGIN 0 */
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance==TIM2) {
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
uint32_t period = __HAL_TIM_GET_AUTORELOAD(&htim2);
period += 10;
if(period > 1100-1)
period = 900-1;
__HAL_TIM_SET_AUTORELOAD(&htim2, period);
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
}
}
/* USER CODE END 0 */
Start the timer in your main loop:
HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1); // on PA5
Observe the chirp on pin PA5 with a LA / scope.
The LD3 related lines are just to observe the interrupt timing on another pin to make sure that the interrupt works as expected.
hth
KnarfB