Electronics > Microcontrollers
STM32F103 DDS + PWM DAC.
DELTA67:
Hi everybody,
I'm trying to port this arduino DDS signal generator to the Blue Pill:
https://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/
I configured TIM1 to genrate a PWM carrier frequency at 281KHz and fires an interrupt each overflow. At this freq the duty resolution is 8bits so a 256 bytes sine LUT is provided.
In the TIM1 interrupt handler an index in the LUT is incremented and the corresponding value is put in the CCR to adjust the duty cycle.
The LPF is 1k + 0.1u.
The result is the attached screen shot. a beautiful 1KHz sine wave.
--- Code: ---volatile uint8_t i;
void TIM1_UPhandler(void){
TIM1->CCR[0] = SINE_LUT[i++];
TIM1->SR = 0; // clear interrupt flag bits
}
--- End code ---
The questions, please:
1- How to calculate the best values for the LPF elements?
I've read some where that the value of R depends on the GPIO pin output driving capability. How?
2- What's the MAXimum sine frequency I can get from this configuration? How to compute it?
3- How to generate all the range from 0 to MAX Hz?
I've tried the algorithm given in the above link but with no success:
--- Code: ---
unsigned int freq = 1000; // starting freq = 1000 Hz
unsigned int refclk = 281000;
volatile unsigned int phaccu; // phase accumulator
volatile unsigned char phase;
volatile unsigned int tword; // tunning word (phase increment)
tword = (1<<24)*freq/refclk;
void TIM1_UPhandler(void){
phaccu += tword; // increment the phase accu
phase = phaccu >> 24; // use upper 8 bits as index
TIM1->CCR[0] = SINE_LUT[phase];
TIM1->SR = 0; // clear interrupt flag bits
}
--- End code ---
What I'm missing?
4- Can we use only 1/4 of the LUT to generate the sine wave? How?
Any ideas, suggestions, algorithms .... are very appreciated.
Thanks
gpr:
Some python code to generate quarter of sine lookup table with arbitrary number of bits precision: https://github.com/gproskurin/learning/blob/master/embedded/stm32_midiplayer/lookup_gen.py
Corresponding C++ code to look up those tables: https://github.com/gproskurin/learning/blob/2fa53b832005f817e942e5689e60af3b52bd38db/embedded/stm32_midiplayer/src/player.cc#L73-L122
May be not ready to use in your project as-is, but you can easily tweak it for your needs
As a bonus, has generation of music notes frequencies if you need it :)
DELTA67:
Thanks gpr for the links.
Perhabs we can save the 1/4 length LUT in the flash then with some formula we generate a full LUT in the RAM.
pcprogrammer:
You can also use DMA to make it work independent of the processor.
Take a peak at my project here: https://github.com/pecostm32/STM32F303_Sine_Square_Generator/tree/main
It uses the integrated DAC of the F303, but DMA can also be used to generate PWM output. Have the target address be the compare register of a timer and read the samples from FLASH. Pulse the DMA based on another timer to set the output frequency.
The output frequency is determined by the number of samples in the full sine table and how fast you output them to the PWM timer.
The maximum frequency is basically half the carrier frequency, but it won't be a nice sine anymore unless the low pass filter has a much lower cutoff point. The amplitude will be very low then.
When using DMA the quarter LUT is not very handy, but when doing it in software there is no need to unpack it to a full one. Just use the given phase to determine the quadrant and adjust the values based on it. See attached files for how this can be done.
The low pass filter calculations can be simple as long as a first order is good enough for you. Just take a resistor of say 15K and calculate the capacitor to go with it to set the filter to half or a third of the carrier frequency.
DELTA67:
--- Quote from: pcprogrammer on November 08, 2024, 02:57:35 pm ---The output frequency is determined by the number of samples in the full sine table and how fast you output them to the PWM timer.
--- End quote ---
Here the speed of samples is constant and equals the frequency of the PWM carrier. How can I change the Nr of samples for each frequency?
--- Quote from: pcprogrammer on November 08, 2024, 02:57:35 pm ---You can also use DMA to make it work independent of the processor.
--- End quote ---
Yes I'm planing to use it later. In this pahe I'm just trying to grasp the principles.
Is there any idea how to compute R of the LPF in function of the GPIO pin fan out?
Why the code taken from the arduino don't work?
Navigation
[0] Message Index
[#] Next page
Go to full version