'sine wave generation (again? :)'
i need to produce an approx. sine wave (i guess a few % THD is fine, i'm
not sure about this requirement), but with a rather precise frequency in
the range from 300Hz to 2500Hz, and with a resolution of 0.5%. i'd like to
be able to switch it on (ie. be in sync) within at max. 50ms.
i'm considering the following options:
- vco (like the exar2206 -- ? not sure about the number) with a pll and a
simple square from the pic to sync it. this is easiest in firmware, but
i've never used a pll and i'm not sure what difficulties i might have to
expect in terms of stability.
- vco fed by the pic with a pwm signal (i probably will have a hardware pwm
in the pic), and getting the vco output back to the pic into a control
loop, which outputs to the pwm into the vco.
- a resistor adder approach with maybe five points or so. at 5 points and
2500Hz, that's 20microsec per step; for a resolution of 0.5% i need a step
increment of 100ns, which i guess is not possible with a pic. but i
probably can "cheat" and use step lengths which might differ by 1, which
would give me the necessary overall resolution for the frequency at 20MHz
or maybe even 10MHz clock.
- just thought of a variant of the above: a programmable (digital)
oscillator and a shift register (with the resistors at the parallel
outputs). needs more points (since i don't have three output states as with
the pic) or some logic to create positive/negative outputs, but maybe is
easier. the oscillator would have to bring 4..40kHz with the 0.5% resolution.
the magic sine approach or output the (stepped) sine directly from the
pic's hardware pwm seem not to be viable because of the frequency resolution.
if somebody has any comments to/experiences with the above options, or
knows of a digitally controlled oscillator with something resembling a sine
at the output, that would be great.
|At 16:09 02/21/99 -0800, Scott Dattalo wrote:
>On Sun, 21 Feb 1999, Gerhard Fiedler wrote:
>> i need to produce an approx. sine wave (i guess a few % THD is fine, i'm
>> not sure about this requirement), but with a rather precise frequency in
>> the range from 300Hz to 2500Hz, and with a resolution of 0.5%. i'd like to
>> be able to switch it on (ie. be in sync) within at max. 50ms.
thanks. i've seen that before when i did some research, but i didn't
understand what i would do with a sine function in this application, but
now i guess i got it :)
>(with the appropriate low-pass filter). If you want to move the solution
>into a smaller part, then check out this non-interrupt driven,
>single-cycle-resolution, 256 level, all software PWM routine:
that's an intriguing idea: a reduced i2c slave and the sine generator in an
8pinner... but for now i guess i leave it in the bigger one as a software
module, with the hardware pwm.
|At 01:37 02/22/99 -0800, Gerhard Fiedler wrote:
>At 16:09 02/21/99 -0800, Scott Dattalo wrote:
>>On Sun, 21 Feb 1999, Gerhard Fiedler wrote:
>>> i need to produce an approx. sine wave (i guess a few % THD is fine, i'm
>>> not sure about this requirement), but with a rather precise frequency in
>>> the range from 300Hz to 2500Hz, and with a resolution of 0.5%. i'd like to
>>> be able to switch it on (ie. be in sync) within at max. 50ms.
>thanks. i've seen that before when i did some research, but i didn't
>understand what i would do with a sine function in this application, but
>now i guess i got it :)
just in case anybody made/is going to make the same mistake i made, here's
how to get a pretty good frequency resolution for a sine output. the
resistor-output approach (and also the magic sine waves) works (and my head
worked :) with fixed parts (angles) of a sine wave. therefore you have to
work with sample rates which are integer multiples of the desired
frequency. using an approach that outputs arbitrary voltages (as opposed to
fixed steps with the resistor ladder approach), you're not longer stuck
with integer multiples of the frequency, since the sample points don't have
to be at the same angles in each period.
so my solution looks like this (the terms in  after a variable gives the
unit and scale for it, as an example for the scales of the different values):
20MHz pic w/ 8 bit hardware pwm: f_sample=40kHz, t_sample=25us (this gives
me at least 16 samples per period, for frequencies up to 2500Hz)
i calculate all times with a resolution of 0.5us, which gives me a
frequency resolution of 3Hz at 2500Hz (and 0.1Hz at 300Hz)
t_sine [0.5us] = 2*10^7 / f_sine [0.1Hz]
the actual time is calculated also in [0.5us] resolution and reduced into
the interval 0..t_sine:
t_(n) [0.5us] = t_(n-1) + t_sample
if ( t_(n) >= t_sine )
t_(n) = t_(n) - t_sine
then i use this time and the frequency to calculate the angle of the next
sample for the sine function (which has to be scaled to fit the input range
of the used sine function, which here is 14 bit for 2*pi, ie. 16384):
phi [2*pi/16384] = ( t_(n) [0.5us] * (f_sine [0.1Hz] * scale) ) / (2^16)
with scale = (0.5us * 0.1Hz * 16384) * 2^16 = 53.69
output = sin ( phi )
this output value gives me, appropriately scaled (eg. scott's sine function
returns -127..+127, so i'd have to add 128 to get an 8bit pwm range of
0..255), the pwm on-time for the next sample period. at 20MHz, there's 128
instruction cycles between samples, which seems to be enough, considering
that scott's function needs only 54 IIRC. the rest is a 16bit add, a 16bit
subtract, a 16x16bit multiplication and an 8bit add plus some "glue" -- not
|On Mon, 22 Feb 1999, Gerhard Fiedler wrote:
It took me a couple of passes to understand this, but you're (mostly)
describing a phase accumulator. The way I usually think about it is:
Imagine a counter that rolls over after 2^N counts. At evenly spaced time
intervals, add a constant (delta phi) to the counter. The rollover
frequency of the counter is (obviously) determined by the constant you add
at each of the time intervals. What's not so obvious is that you can use
fix point arithmetic to get rollover frequencies that are not an integer
number of cpu cycles. You don't get something for nothing though - in the
trade off you introduce some frequency jitter.
The equation for the frequency is:
delta phi 1
f = --------- * ------
delta t 2^N
You know delta t - that's dictated by how fast some isocronous routine
increments the phase accumulator. Usually you want this as small as
possible since that gives better frequency resolution. You also know the
frequency, f (that's what you're trying to generate). So you can solve for
delta phi = f * delta t * 2^N
If you had a 20Mhz crystal and used the isochronous software pwm routine I
mentioned in the last post, then delta t = 51.2uS. For N=14 bits you get a
really simple equation (if I did the arithmetic correctly):
delta phi = 0.83886 * f
So to generate 2500Hz, delta phi would be 2097. This multiplication, btw
only needs to be performed once per frequency. So the 16-bit multiply you
mentioned doesn't need to be in the isochronous loop. Also, pre-computing
all of the constants removes the need for the addition and subtraction.
The sine wave routine executes in 65 cycles. However, there are two ways
to speed it up. One is to unroll a loop (it only loops four times). The
other is to completely rewrite the routine and take advantage of the fact
that the sine values are generated consecutively - this will save on
average one table-look-up per iteration.
At 18:48 02/22/99 -0800, Scott Dattalo wrote:
>you're (mostly) describing a phase accumulator.
if i had heard that term before, maybe i wouldn't have taken such a long
way around it! :)
>If you had a 20Mhz crystal and used the isochronous software pwm routine I
>mentioned in the last post, then delta t = 51.2uS. For N=14 bits you get a
>really simple equation (if I did the arithmetic correctly):
>delta phi = 0.83886 * f
>So to generate 2500Hz, delta phi would be 2097.
i still see one problem here. 51.2us=19.5kHz, that's less than 8 points per
period at 2500Hz. if i rewrite the pwm for a resolution of 128 (and double
the frequency), i guess the free cycles would be less than half, too, and
that's probably not enough. what i was trying to figure out is how to get
an interrupt out of the hardware pwm module (like when the counter is
reset), but i guess that's not possible. or only with feeding the pwm
output back to RB0 and make sure the pwm register never gets 0. any ideas
on that? i'd like to use the hardware pwm, because it gives me 4 times the
thanks a lot,
More... (looser matching)
- Last day of these posts
- In 1999
, 2000 only
- New search...