Truncated match.
PICList
Thread
'sine wave generation (again? :)'
1999\02\21@182057
by
Gerhard Fiedler

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.
thanks,
ge
1999\02\21@191051
by
Scott Dattalo

On Sun, 21 Feb 1999, Gerhard Fiedler wrote:
{Quote hidden}>
> 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.
>
Check out
http://www.interstice.com/~sdattalo/technical/software/pic/picsine.html
http://www.brouhaha.com/~eric/pic/sine.html
For mine and Eric Smith's pic sine generators. Eric's routine is faster,
mine has more frequency resolution (i.e. phase accumulators). The phase
accumulators allow you to create sine waves whose frequencies are not
limited to an integer multiple of PIC instruction cycles. I suspect that
this coupled with the hardware pwm will provide a quite decent sine wave
(with the appropriate lowpass filter). If you want to move the solution
into a smaller part, then check out this noninterrupt driven,
singlecycleresolution, 256 level, all software PWM routine:
http://www.interstice.com/~sdattalo/technical/software/pic/pwm256.txt
Scott
1999\02\22@044007
by
Gerhard Fiedler

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.
>
>Check out
>
>http://www.interstice.com/~sdattalo/technical/software/pic/picsine.html
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 lowpass filter). If you want to move the solution
>into a smaller part, then check out this noninterrupt driven,
>singlecycleresolution, 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.
thanks again,
ge
1999\02\22@162618
by
Gerhard Fiedler

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.
>>
>>Check out
>>
>>http://www.interstice.com/~sdattalo/technical/software/pic/picsine.html
>
>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
resistoroutput 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_(n1) + 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 ontime 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
too heavy.
ge
1999\02\22@214835
by
Scott Dattalo

On Mon, 22 Feb 1999, Gerhard Fiedler wrote:
{Quote hidden}> 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
> resistoroutput 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_(n1) + 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 ontime 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
> too heavy.
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:
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 16bit multiply you
mentioned doesn't need to be in the isochronous loop. Also, precomputing
all of the constants removes the need for the addition and subtraction.
BTW
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 tablelookup per iteration.
Scott
1999\02\23@034143
by
Gerhard Fiedler

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
frequency.
thanks a lot,
ge
More... (looser matching)
 Last day of these posts
 In 1999
, 2000 only
 Today
 New search...