I'm trying to generate a signal which contains only several specific frequencies I know of in advance, around (16.4kHz, 16.7khZ, 17kHz,…)
the signal is generated using a microcontroller, which then outputs an analog signal into a speaker.
The problem is that due to timing limitations of the chip, I'm unable to produce the exact frequencies I need, they are shifted by around 40Hz in some direction. I'm starting to thinks that maybe this method of generation is not the optimal.
my questions are:
-
could you think of a different way, perhaps even completely analog (no microcontroller) to generate this kind of signal?
-
I know that in order to shift the frequencies by say,40Hz, I need to multiply it by a cosine (modulate it), but then it will be shifted both "left" and "right" which will make things extremely incontinent. Is there another, sophisticated way to achieve this kind of frequency shifting?
Thanks!
EDIT:
I'm currently using microchip pic16F1783 @32MHz with 8 bit DAC. I'm creating a sum of "pure" sines at the desired frequencies and then produce the wave. the constraints are of the digital world: the sampling frequency is digitalized, it can be 8MHz/integer, say 8M/100 to get sampling freq of 80KhZ. another constraint is the RAM. I create the signal in advance and put into an array that cannot have more than 450 elements. Due to all of that my signal is't created 16.4 but at 16.351
Best Answer
In principle, DDS should be easy to achieve in software - fractional accumulator, then lookup sine or cos for each tone you want to generate, then sum. On a PIC, that's going to be a tight loop, though...
I am assuming a 256 element LUT containing a complete cycle of a sine wave.
Each sample period , for each frequency, we add a fraction to the position of its pointer in the LUT, and take the sample at the (integer) part of the position. To illustrate how simple this can be, I played with a spreadsheet:
The actual DDS operation translates into pseudo-assembler (not PIC!) as
which will expand considerably from what I remember of PIC assembly language, but is starting to look feasible.
Remember that the values in the lookup table must be scaled down so that the addition result in "sum" will not overflow.