We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi all,
I've been looking into this challenge for a couple of days, I figured now would be a good time for me to ask some questions on a forum like this. I have done some C++ programming in the past; I'm slowly getting back into the mindset and vernacular but am not a seasoned programmer. Basically what I'd like to do is employ a low-cost MCU with DAC to act as a sine wave frequency generator in the range of about 100 kHz to 1 MHz, with a frequency resolution ideally of about 5 Hz. I am looking at the STM32F072 and STM32L151; currently I am prototyping on a STM32F4 Discovery Board that has an STM32F407, connected to a suitable opamp circuit as described in this ST Application Note.
Sofar, I've managed to make a simple phase accumulator (rising sawtooth) at a frequency of 100 kHz and a samplerate of 2 MHz; when I use the arm_math.h function arm_sin_f32 to convert this into a sine wave, I unfortunately get regular discontinuities, which after some investigation I presume are due to some type of processor overload. Therefore I'd like to investigate using arm_sin_q15; the reduced resolution is not a problem for my application.
I have been learning about the Q15 data type and understand that it is essentially a signed 16-bit integer that goes from -1 to 0 to 0.9999ish - the latter being 32767/32768 = 0.9999695. This discussion was enlightening in this. Also, the CMSIS DSP documentation mentions that the q15_t input for the sine function accepts an input ranging from 0 to 0.9999, which is internally mapped to the range of 0 to 2pi.
My question is: how do I (elegantly) construct a phase accumulator with Q15 as a data type, if the data type itself can't handle values more than (the equivalent of) 1? With floats or ints, what I did was: if phase >= 2pi (phase -= 2pi); - this requires though that the phase parameter can overshoot the 2pi value...
Perhaps there is a way to do this with modulo? Or is there another approach in general that is recommended in terms of simplicity, elegance & efficiency? I am considering also to build a complex oscillator as mentioned in this article.
Perhaps I should just normalize first to a lower integer value to represent the 2pi wrapping point? That seems like an expensive extra computational step...
Thanks in advance for any help.
Here's a screenshot of my scope showing the float sine with discontinuities. I used the two DMA callback functions to ping-pong fill the DAC buffer
Ah... I can just simply use an unsigned 16-bits integer for the phase parameter of course. Duh...