Searching \ for '[PIC]: Sine wave oscillator' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/math/index.htm?key=sine
Search entire site for: 'Sine wave oscillator'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Sine wave oscillator'
2002\03\22@033622 by Tim Forcer

flavicon
face
At 05:17 22/03/2002, Dave Dilatush wrote:

>  Date:    Thu, 21 Mar 2002 00:46:07 +0000
>  From:    Dave Dilatush <spam_OUTdilatushTakeThisOuTspamCOMCAST.NET>
>  Subject: Re: [PIC] Sine wave oscillator
>
>  Shawn wrote...
>
> > ... I would like to replace a 625Hz analog
> > sine wave oscillator with a low-end PIC
> > microcontroller -- say 16F84 or 8-pin model.
> > Is it better to use a look-table approach
> > to replicate the sine wave or can excellent
> > results be achieved by generating a square
> > wave then filtering?
>
>  It depends.  ... modulating the PIC's
>  PWM output ... the resulting signal contains
>  little energy at the lower-numbered harmonics
>  it is much easier to filter into a pure
>  sinewave than a square wave of the same frequency.

You are not restricted to PICs with PWM outputs!  You can use a look-up
table for a one-bit oversampled waveform just as easily as for multi-bit
sampling.

>  On the other hand, if you don't need a
>  particularly pure sine wave out of this
>  device (say, 2% or 3% THD or thereabouts)

That's a LOT of THD.

>  then filtering a square wave ... easier
>  with regard to software design.
>
>  I don't recommend trying to generate a
>  very high-purity sine wave by filtering
>  a square wave ...

Sound advice, but you can generate something MUCH closer to a sine wave
than a square wave and save on analogue filtering.

For a student exercise in this Department, we use a PIC16F84 with an 8MHz
resonator to produce four pairs of waveforms.  One is a pair of
pseudo-random binary sequences (PRBS), the other three are 1kHz sine/cosine
pairs.  A selected pair of outputs are filtered with a quad opamp to
provide a stereo signal generator.  The three sine/cosine pairs are generated:

1) Conventional 2-bit (four level) binary coding, 16 samples per cycle.

2) 1-bit oversampled binary coding, 64 samples per cycle.

3) 2-digit ternary coding, 16 samples per cycle.

Ternary (three-state) coding uses the fact that PIC outputs can take three
states: HI, LO and OFF, so two outputs can produce up to nine (three
squared) levels using an appropriate resistor network.  Even before any
analogue filtering, the waveform is remarkably close to sinusoidal.

After filtering, there is no visible difference on the 'scope between the
signal waveforms produced by these different schemes.  What is interesting
is that a single stage of plain CR filtering of the nine-level signal
provides a waveform that is remarkably close to sinusoidal, and sounds
fairly "clean".  In contrast, at this stage the four-level and oversampled
signals have very audible odd harmonic content, very "edgy".

In case you're wondering, the PRBS provides either a digital noise source
or, after going through the same filter chain, an audio pink noise source.

Two pairs of two-output generators, plus two pairs of one-output
generators, means there's one pin spare - but that would be a shame.  So
the final output pin provides a SYNC pulse to flag when the 16-bit PRBS
register goes through the all-1 state as it generates its 32767 bit sequence.

Total use of PIC '84 resources: 238 words and 54 registers, although I'm
sure many folk on this list could cut down both of those.

> > ... And finally, would the answer change if I were
> > generating say a 1MHz wave?

Yup!  My code needs an 8MHz oscillator for everything to happen in
sufficiently close timing for 16k/64k samples per second.  If you were only
trying to produce a single waveform, rather than eight plus sync, then
simple arithmetic shows you could get up to around 4kHz with a 4MHz
oscillator - although that simplicity masks the fact that there are more
instructions required for the ternary coding than the binary coded
versions, for example.  Even with a 20MHz oscillator, the instruction rate
of 5M instructions/s would be barely enough to produce a square wave, let
alone a coded sinewave!

HTH,

Tim Forcer
Department of Electronics & Computer Science
The University of Southampton, UK

--
http://www.piclist.com hint: To leave the PICList
.....piclist-unsubscribe-requestKILLspamspam@spam@mitvma.mit.edu


2002\03\22@084036 by Dave Dilatush

picon face
Tim Forcer wrote...

>You are not restricted to PICs with PWM outputs!  You can use a look-up
>table for a one-bit oversampled waveform just as easily as for multi-bit
>sampling.

The main advantage of using a software DDS approach (i.e., a sine
lookup table together with a PWM output or DAC) is that you can
get a sine wave which is both easily tunable--simply by varying
the phase increment register value--and capable, with appropriate
output filtering, of generating a high-quality sinusoidal output.
And in contrast to a tunable analog oscillator (a Wein bridge
arrangement, for example), the tuning is repeatable as well.

In one implementation I'm using a PIC16F877 and a 12-bit DAC to
generate a 0-10KHz sine wave, tunable in 0.002Hz increments with
THD around 0.1% over the range.

You wrote of using 1-bit oversampled binary coding, 64 samples
per cycle; I'd be interested in knowing how well this lends
itself to tuning over a wide frequency range while maintaining
spectral purity.

My guess would be that while generating fixed-frequency sine
waves with this technique is straightforward, generating sine
waves continuously tunable over a wide range is not; but I'm open
to being corrected on this point.

Dave D.

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-requestspamKILLspammitvma.mit.edu


2002\03\22@095159 by Bob Ammerman

picon face
If you only need to generate the fixed frequency of 625Hz, you could easily
do it with a 12C509A by using a single bit highly oversampled output.

Use a 4MHz crystal to get 1,000,000 instructions per second. This
corresponds to 1600 instructions for each cycle of the 625Hz output.

You would compute the ideal oversampled output waveform as a long string of
zeros and ones using a program on a PC. (Anybody have any pointers to how to
do this part?).

Then, given the sequence of zeros and ones you would (manually, or via a
program you write on the PC) generate ASM code for the body of the frequency
generating loop on the PIC:

You would like to just generate:

   BCF    GPIO,0    for each zero, and
   BSF    GPIO,0    for each one

But this won't work because you only have a total of 1024 instructions
available and it takes 1600 to generate a full cycle.
However, you can take advantage of sequences of three or more consecutive
zeros or ones like this:

Save one instruction for a sequence of 3 zeros(ones) in a row:

   BCF(BSF)    GPIO,0
   goto    $+1

Also, save one instruction for a sequence of 4 zeros(ones) in a row:

   BCF(BSF)    GPIO,0
   nop
   goto    $+1

For N or more zeros(ones) in a row, where N >= 5 you can save N-2
instructions using:

   BCF(BSF)    GPIO,0
   call      DelayN

Where off to the side in another part of the source you have:

Delay10:    nop
Delay9:      nop
Delay8:      nop
Delay7:      nop
Delay6:      nop
Delay5:      retlw    0

You will, of course, have to have a general structure of:

loop:
   BCF(BSF)    GPIO,0
   .
   .
   goto loop

and will have to make sure the entire loop takes exactly 1600 instructions,
including the final GOTO. Also, the final goto will have to occur at a time
when you are sending several identical bits.

Here is a puzzle/challenge:

How can you reduce the program memory requirements by a factor of
approximately 2?

Bob Ammerman
RAm Systems

--
http://www.piclist.com hint: To leave the PICList
.....piclist-unsubscribe-requestKILLspamspam.....mitvma.mit.edu


2002\03\22@100045 by SHAWN

picon face
Thank you Bob. I'm glad I joined this  group -- the variety of responses
have been very educational and thought provoking.
Shawn
{Original Message removed}

2002\03\22@101305 by SHAWN

picon face
thanks, Tim
----- Original Message -----
From: "Tim Forcer" <EraseMEtmfspam_OUTspamTakeThisOuTECS.SOTON.AC.UK>
To: <PICLISTspamspam_OUTMITVMA.MIT.EDU>
Sent: Friday, March 22, 2002 1:26 AM
Subject: [PIC]: Sine wave oscillator


{Quote hidden}

sine/cosine
> pairs.  A selected pair of outputs are filtered with a quad opamp to
> provide a stereo signal generator.  The three sine/cosine pairs are
generated:
{Quote hidden}

sequence.
>
> Total use of PIC '84 resources: 238 words and 54 registers, although I'm
> sure many folk on this list could cut down both of those.
>
> > > ... And finally, would the answer change if I were
> > > generating say a 1MHz wave?
>
> Yup!  My code needs an 8MHz oscillator for everything to happen in
> sufficiently close timing for 16k/64k samples per second.  If you were
only
{Quote hidden}

--
http://www.piclist.com hint: To leave the PICList
RemoveMEpiclist-unsubscribe-requestTakeThisOuTspammitvma.mit.edu


2002\03\22@123331 by Scott Dattalo

face
flavicon
face
On Fri, 22 Mar 2002, Bob Ammerman wrote:

> If you only need to generate the fixed frequency of 625Hz, you could easily
> do it with a 12C509A by using a single bit highly oversampled output.
>
> Use a 4MHz crystal to get 1,000,000 instructions per second. This
> corresponds to 1600 instructions for each cycle of the 625Hz output.
>
> You would compute the ideal oversampled output waveform as a long string of
> zeros and ones using a program on a PC. (Anybody have any pointers to how to
> do this part?).

I discuss it briefly here. Maybe you didn't see the post the other day.

http://www.dattalo.com/technical/theory/sqwave.html

On this page I have two Octave/MATLAB scripts that allow you to plot the
harmonics of a pulse train. This is obviously synthesis instead of
analysis. However, after a consider derivation there is a formula
presented for synthesis

  +-------------------------------------+
  |  0 = (-m1 + m2 + (M/2)*n) % (M/n)   |
  +-------------------------------------+

But this only allows you to synthesize pulse trains by piece-wise
combining pairs of pulses. A sad consequence is that your constrained by
the number of pulses that are available in your pulse train. For example,
I discovered that 12 possible pulses in the train are good for n (the
harmonic) = 3. For n= 5 you have to go to 120 pulses and in general the
number of pulses goes as K*n! (that's factorial, not excitement).

If you want to generate a sine-weighted pulse stream that's somewhat less
confining but also less spectrally pure (or to be more precise, contains
energy in the lower harmonics) then consider this Octave program I just
threw together:

http://www.dattalo.com/pulses2sine.m

It generated this graph:

http://www.dattalo.com/p1.png

The idea is to divide the period of the sine wave into a bunch of tiny
steps. Each step defines a point at which the pulse stream can change
states. Group a chunk of these steps together. The number of high pulses
in the chunk is proportional to the value of the sine wave sample. In
other words, The pulse stream is essentially a collection of PWM wave
forms.


> Then, given the sequence of zeros and ones you would (manually, or via a
> program you write on the PC) generate ASM code for the body of the frequency
> generating loop on the PIC:

<snip>

> and will have to make sure the entire loop takes exactly 1600 instructions,
> including the final GOTO. Also, the final goto will have to occur at a time
> when you are sending several identical bits.
>
> Here is a puzzle/challenge:
>
> How can you reduce the program memory requirements by a factor of
> approximately 2?

You could apply tertiary weighting like Michael suggests. Or perhaps
easier is to apply binary weighting and resistor sum 2 (or more outputs).
You've got to pass through a resistor as part of the LPF anyways...


Scott

--
http://www.piclist.com hint: To leave the PICList
spamBeGonepiclist-unsubscribe-requestspamBeGonespammitvma.mit.edu


2002\03\22@144113 by Bob Ammerman
picon face
> On Fri, 22 Mar 2002, Bob Ammerman wrote:
>
> > If you only need to generate the fixed frequency of 625Hz, you could
easily
> > do it with a 12C509A by using a single bit highly oversampled output.
> >
> > Use a 4MHz crystal to get 1,000,000 instructions per second. This
> > corresponds to 1600 instructions for each cycle of the 625Hz output.
> >
> > You would compute the ideal oversampled output waveform as a long string
of
> > zeros and ones using a program on a PC. (Anybody have any pointers to
how to
> > do this part?).
>
> I discuss it briefly here. Maybe you didn't see the post the other day.
>
> http://www.dattalo.com/technical/theory/sqwave.html

Yeah, I took a look at that, but didn't see how I got the 'best' pulse
train.

How about this idea: Do a simple delta encoding by treating the output as a
simple 1=up, 0=down kind of thing and comparing the computed value of the
integral to the correct value of the sign at each step to determine the next
output bit. The maximum slope occurs at the zero crossings, so at those
points we would expect to see a sequence of repeated ones or zeros.

> > Here is a puzzle/challenge:
> >
> > How can you reduce the program memory requirements by a factor of
> > approximately 2?

My thought here is that the waveform is symetrical. So if we replace all the
BCF GPIO,0 and BSF GPIO,0 instructions with XORWF GPIO,F and make sure that
W always contains a one, then our loop can encode only half the waveform, as
long as it contains an odd number of XORWF GPIO,F instructions.

Bob Ammerman
RAm Systems

--
http://www.piclist.com hint: To leave the PICList
TakeThisOuTpiclist-unsubscribe-requestEraseMEspamspam_OUTmitvma.mit.edu


2002\03\23@025259 by Tim Forcer

flavicon
face
Dave Dilatush wrote:

[cut]

>  You wrote of using 1-bit oversampled binary
>  coding, 64 samples per cycle; I'd be
>  interested in knowing how well this lends
>  itself to tuning over a wide frequency
>  range while maintaining spectral purity.

Badly!  At least, in terms of '84 assembler it would be decidedly non-trivial!!

>  My guess would be that while generating
>  fixed-frequency sine waves with this
>  technique is straightforward, generating
>  sine waves continuously tunable over a
>  wide range is not; but I'm open
>  to being corrected on this point.

I'd guess exactly the same.

Tim Forcer

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\03\24@020236 by Scott Dattalo

face
flavicon
face
On Fri, 22 Mar 2002, Bob Ammerman wrote:

>
> How about this idea: Do a simple delta encoding by treating the output as a
> simple 1=up, 0=down kind of thing and comparing the computed value of the
> integral to the correct value of the sign at each step to determine the next
> output bit. The maximum slope occurs at the zero crossings, so at those
> points we would expect to see a sequence of repeated ones or zeros.

Good idea. I took it one step further and simulated a sigma-delta (or
delta-sigma, depending on which side of the world you're on). I think this
is what you're in fact describing. I wrote another Octave script that
synthesizes a sine wave:

http://www.dattalo.com/swsd.m

That produced this plot:

http://www.dattalo.com/p2.png

There are three 400Hz sine waves and one pulse train in the plot. The red
sine wave is an 8-bit quantized that would be generated from a look up
table or whatever in a PIC. The green one is the output of a software
integrator that has one side driven by the Red sine wave and the other
driven by the pulse stream. This green sine wave is quantized to 16-bits
and never leaves the PIC.  The magenta stuff at the bottom is the pulse
stream. The Blue sine wave is what you get when you run the pulse stream
through a simple RC low-pass filter.

In this example, the simulation runs for 4 mSec. The pulse edges are
quantized to 4us intervals. The integrator "time constant" is 1/64. Which
is to say that the output of the integrator is 1/64 times the difference
of the inputs. So if the inputs are close to one another the integrator's
output doesn't change too much, but if they're far apart - say 256 counts
then the integrator output changes by 256/4 counts.

One subtle point I neglected to mention in the comments is that the
comparator reference is actually the red sine wave ( the one that is
obtained from the look up table).

For this graph, the RC time constant is 22k *0.01uF. As you can see there
is a little overshoot. A close up of a section of the curve:

http://www.dattalo.com/p3.png

Illustrates this effect as well. The output swings 0101010, and the RC
filter settles toward the mid range (128).

If the filter is made slightly more aggresive by change R to a 33k ohm
resistor, you get:

http://www.dattalo.com/p4.png

The filtered output is much better in that there's less HF noise, but it's
clear that the RC filter is also attenuating the sine wave.

BTW, Roman did something similar to this a while back

http://centauri.ezy.net.au/~fastvid/picsound.htm

He called BTC for binary time constant. There's no code on his web page,
but AFAICT from his description, this is fairly close if not identical.

----
Now for the PIC code... later on.

{Quote hidden}

Yep. BTW, the stuff I did in the simulation is intended for dynamic
creation of the Pulses. If you want to statically create them (to boost
the sampling frequency), then you could just take the output from the
simulation and write a script to generate the XORWF's.

Scott

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


More... (looser matching)
- Last day of these posts
- In 2002 , 2003 only
- Today
- New search...