Sine wave generator

Gildardo

Member
Hi all,
I need a circuit that can create a sine wave generator. The function that I need to get is v(t) = 0.5 sine(t) +1. Where: V = Voltage and t=seconds. I need a circuit that can create other sine wave forms similar to this one.
I was wandering if Picaxe can do it easily without using opamps, resistors, capacitors and all that stuff.

I wrote some code:
_______________________________________________________
main:

establecer_0_grados: let w0= 0

preguntar_rango: if w0= 180 then establecer_360_grados
let b2 = sin w0
let w2 = 5*b2
let w3 = 500+w2
pause 50
let w0=w0+ 1
sertxd(#w3,13,10)
goto preguntar_rango

establecer_360_grados: let w0= 361

rango_de_181_a_360_grados:if w0= 540 then establecer_0_grados
let b2 = sin w0
let w2 = 5*b2
let w3 = 500-w2
pause 50
let w0=w0+ 1
sertxd(#w3,13,10)
goto rango_de_181_a_360_grados
____________________________

It worked and I could visualize it quit well using Stamp Plot. Nevertheless, I want to get that voltage signal from one of the Picaxe’s output.
Thanks in advance.
 

womai

Senior Member
Not possible without any external components; the Picaxe does not have a true built-in digital-to-analog converter (DAC).

Two possibilities:

(1) use the PWM output and vary the duty cycle depending on the level you want at each instant. You need to low-pass filter the output, i.e. add a series resistor R feeding a capacitor C. Time constant R*C must be approx. 10x larger than the PWM frequency, but approx. 10x smaller than the highest sine wave frequency you want to produce. If you need to draw current from this signal (more thana a few uA), you also need to add an op-amp follower (op-amp with its output connected to its "-" input, and the filtered PWM connected to the "+" input.

(2) faster solution: Connect the 8 output pins to a R-2R resistor array. The write the digital value (0 ... 255) to the output, this will result in an equivalent analog voltage. You can get R-2R resistor arrar in 10-pin SIP packages from e.g. Jameco or Digikey. Again you may need to buffer the signal with an op-amp follower. Advantage of this solution is that it can produce much faster sine waves. You should low-pass filter it as well (filter bandwidth approx. 0.4 times roue update frequencyif you use a steep higher-order filter).

What is the maximum and minimum sine wave frequency you want to generate?

Wolfgang
 

Ralpht

New Member
I was wandering if Picaxe can do it easily without using opamps, resistors, capacitors and all that stuff.
Lets be realistic here. There is no way a digital device will produce an analog waveform without some opamps, resistors, capacitors and all that stuff.

The PICAXE has ADC's - analog to digital converters but no true DAC's - Digital to Analog converters.

I'm afraid you might have to learn how all that stuff works...
 

hippy

Ex-Staff (retired)
This will generate a PWM sine wave function ...

Code:
#Picaxe 28X1
#No_Data
#No_Table

Symbol angle     = w0
Symbol result    = w1
Symbol duty      = w2

Symbol K_POS     = 100
Symbol K_NEG     = 100 + $80

angle = 270
PwmOut 1,200,0

Do
  result = Sin angle
  If result < $80 Then
    result = K_POS + result
  Else
    result = K_NEG - result
  End If
  duty = result << 2
  PwmDuty 1,duty
  angle = angle + 1 // 360
Loop
Connect a LED+R between the PWM Output and 0V and its brightness will vary in a sinusoidal manner though the way we perceive brightness affects what we see.

Take the output via an R to a C connected to 0V, measure the voltage where R and C join and that should give a sine wave between 0V and approx +V. I haven't tested that part.

The 'result' value has a notional value of -100 to +100 which is offset by 100 giving 0 to 200.

The 'duty' is 'result' times four ( shift left two bits ) which gives a duty of 0 to 800, which gives 0% to 100% of a PWMOUT with period 200. Altering the way 'duty' is calculated will adjust the output voltage.
 

hippy

Ex-Staff (retired)
Used a 220R plus 150nF, and tweaked the code so the PWM period was shorter ...

Code:
SetFreq M8

angle = 270
PwmOut 1,50,0

Do
  result = Sin angle
  If result < $80 Then
    result = K_POS + result
  Else
    result = K_NEG - result
  End If
  duty = result 
  PwmDuty 1,duty
  angle = angle + 1 // 360
Loop
That gives an analogue sine wave of frequency of around 0.5Hz. Scope probes x10 ( ~5V peak ), not calibrated, and circuit thrown together, so could probably do better than what is shown.
 

Attachments

Last edited:

Andrew Cowan

Senior Member
As hippy suggested, use a resistor and capacitor. It's called an RC network, and a quick google will find calculators you can use to work out what values to use for what freqencies.

A
 

hippy

Ex-Staff (retired)
The main question as identified by jglenn is what frequency of sine waves are you requiring ? Also, how many steps per full cycle do you want or need ?

Even a PICmicro running native assembly language at 8MHz which can produce a 1MHz square wave by bit-banging will only manage 3kHz with a 360 step sine wave.

At 8MHz and stepping the 'angle' at 45 degrees in my code that gives a sinewave of eight discrete steps ( not a lot ) and a frequency around 50Hz.

If you had a long sequence of PWMDUTY commands having pre-calculated the values required you could possibly get that up to about 1kHz but it wouldn't be very programmable.
 

womai

Senior Member
Alternatively, driving a R-2R resistor network with a full 8-pin output port as I proposed in my first post has potential to produce much faster signals. I'd expect even a Picaxe could reach at least several 100 Hz sine-wave frequency. You'd probably want to implement some type of DDS (direct digital synthesis) so the frequency can be adjusted in fine increments.
 

hippy

Ex-Staff (retired)
Is an R-2R DAC really faster ?

You still have to produce each step value and write it to the port, that's replacing 'PwmDuty 1,result" with "pins=result" and there's not a lot between them I'd have thought.
 

Jeremy Leach

Senior Member
Or make a sinewave using a picaxe speed-controlled DC motor (or stepper), photoemitter/transistor pair shining on a revolving disc with shaded pattern. Bit like the 'Tonewheels' in old Hammond Organs ;).
 

boriz

Senior Member
Or use an external 4-bit ripple counter, with appropriate resistor ladder to provide a 16 step (dirty) sine and clock it with PWMOUT at 16 * the required sine frequency. A 4MHz Picaxe could produce frequencies upto about 25kHz. 50kHz if you overclock. Some high pass filtering and Bob&#8217;s wife&#8217;s sister is your mum.
 

womai

Senior Member
Is an R-2R DAC really faster ?

You still have to produce each step value and write it to the port, that's replacing 'PwmDuty 1,result" with "pins=result" and there's not a lot between them I'd have thought.
I'd expected the R-2R DAC method to be faster because the moment you write the data byte to the port, the analog output changes to the desired voltage. About as simple as it gets.

On the other hand, for PWM, you need to supply a large number of pulses that get heavily low-pass filtered. If you want 8 bit level resolution your PWM period has to be 64 times slower than the maximum period (duty cycle resolution is 4x the period resolution, so 256/4=64). That means the fastest PWM you can run with e.g. a Picaxe at 16 MHz is 2 MHz (theoretical maximum) divided by 64, or ~30 kHz, or a period of around 0.03ms. You'll need to filter that with a time constant of at least 10 times slower than that to avoid excessive ripple, i.e. Tc=0.3ms. Rise time is

Tr=2.2*Tc,

and bandwidth

BW=0.35/Tr=0.35/(2.2*Tc)

That gives a necessary filter bandwidth of 500 Hz, which is the limit of that method. The resistor network method should be able to achieve well over 1 kHz.

Granted, after going through these calculations it looks like a Picaxe won't be MUCH faster even with the R-2R network. The advantage of the latter would be much more pronounced with a "true" Microchip PIC bcause while the PWM can't get any faster, the max. speed of the output port update (for R-2R) would be probably 50x - 100x faster.

Wolfgang
 

womai

Senior Member
I put together a little test circuit using the R-2R resistor ladder connected to the Picaxe's output port. Program see below. Works fine and produces a 4V peak-to-peak amplitude signal. With a phase increment of 1 degree I get approx. 0.5 Hz (clock frequency 4 MHz), so Hippy was right, it's not faster than the PWM approach (on a Picaxe).

Using an X2 part one could generate a dedicated 360 degree lookup table for the sine function (i.e. 360 one-byte values) that has amplitude and offset built in; this would remove the need to check if the value is negative and probably double the program speed. The Picaxe could re-build the lookup table by itself whenever amplitude or offset is changed. At the same time, running at 40 MHz would again speed it up by about 7x compared to a 28X1 at 4 MHz.

Wolfgang


Code:
#picaxe 28X1

setfreq em16

symbol phase = w0
symbol incr = w1
symbol ampl = w2

phase = 0
incr = 1

myloop:

    phase = phase + incr % 360
    ampl = sin phase
    
    if ampl < 128 then
        pins = ampl + 100
    else
        pins = 228 - ampl
    endif

goto myloop
 

hippy

Ex-Staff (retired)
Good idea with the lookup table. If you used 256 entries per 360 degrees and used w0 as a fixed point number ( b1.b0 ) ...

Do
w0 = w0+increment
Read b1,pins
Loop

with an increment of one ( $0100 ) that could be close to 1kHz pins update, 40Hz at 4MHz, with an 8 step sinewave that's 250Hz, 2500Hz at 40MHz.
 

womai

Senior Member
Good idea with the lookup table. If you used 256 entries per 360 degrees and used w0 as a fixed point number ( b1.b0 ) ...

Do
w0 = w0+increment
Read b1,pins
Loop

with an increment of one ( $0100 ) that could be close to 1kHz pins update, 40Hz at 4MHz, with an 8 step sinewave that's 250Hz, 2500Hz at 40MHz.

... which is precisely the DDS (direct digital synthesis) approach, in this case with a 16 bit tuning word and an 8 bit DAC. The beauty of this solution is that it is not limited to sine waves (you are free to generate any 256-point waveform you like in the lookup table) and you can get fine frequency resolution. In fact I am contemplating such an approach (but using a PIC programmed in compiled C for speed) to build a very inexpensive arbitrary waveform generator that would complement the Picaxe oscilloscope. From first experiements it looks like I should be able to ge a few hundred kHz sample rate with a 18F series PIC. Now I "only" need to find the time to work on the output stage (gain and offset), power supply, software etc. ;)

Wolfgang
 

Andrew Cowan

Senior Member
I've been planning to build something like that for a long time, however, I am planning thousands of projects...

I'd buy it!
 

womai

Senior Member
Well, I put a test circuit together that uses a 28X2 (running at 40 MHz, i.e. with an external 10 MHz resonator) driving the R-2R network. I generated the sinewave lookup table in Excel and converted it into EEPROM data for the Picaxe. The result is quite impressive (for a Picaxe, that is :), I get a sample rate of 4500 samples per second. So with a bit of low-pass filtering at the output that should be good for sine wave frequencies up to 1 kHz and beyond (practical limit with optimum filtering is approx. f_sample/2.5 = 1800 Hz).

The code below produces a nice 100 Hz sine wave with 5V amplitude (and thus gets about 45 samples per cycle, not too shabby, and looks ok - not too "steppy" - even without any filtering). If you can live with a little less speed (around half) you can run this program on a 28X1 just as well.

Wolfgang

Code:
#picaxe 28x2

' sine wave lookup table
data 0x00, (128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174)
data 0x10, (177,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216)
data 0x20, (218,220,222,224,226,228,230,232,234,235,237,239,240,241,243,244)
data 0x30, (245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255)
data 0x40, (255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246)
data 0x50, (245,244,243,241,240,239,237,235,234,232,230,228,226,224,222,220)
data 0x60, (218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179)
data 0x70, (177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131)
data 0x80, (128,125,122,119,116,112,109,106,103,100, 97, 94, 91, 88, 85, 82)
data 0x90, ( 79, 77, 74, 71, 68, 65, 63, 60, 57, 55, 52, 50, 47, 45, 43, 40)
data 0xa0, ( 38, 36, 34, 32, 30, 28, 26, 24, 22, 21, 19, 17, 16, 15, 13, 12)
data 0xb0, ( 11, 10,  8,  7,  6,  6,  5,  4,  3,  3,  2,  2,  2,  1,  1,  1)
data 0xc0, (  1,  1,  1,  1,  2,  2,  2,  3,  3,  4,  5,  6,  6,  7,  8, 10)
data 0xd0, ( 11, 12, 13, 15, 16, 17, 19, 21, 22, 24, 26, 28, 30, 32, 34, 36)
data 0xe0, ( 38, 40, 43, 45, 47, 50, 52, 55, 57, 60, 63, 65, 68, 71, 74, 77)
data 0xf0, ( 79, 82, 85, 88, 91, 94, 97,100,103,106,109,112,116,119,122,125)

symbol phase = w0
symbol phase_msb = b1

symbol incr = w1

setfreq em40

let dirsB = %11111111
let adcsetup = 0

phase = 0
incr = 0x05b0

do
    phase = phase + incr
    read phase_msb, pinsB
loop
 
Last edited:

MFB

Senior Member
We get a lot of request for help on the forum for information on how to transmit data reliably using low cost/power transmitter. FSK is certainly one method to achieve this and, from the above results, it seems that the X2 range is just about able to generate the required the two tones (of 1200 and 2200Hz) for a 1200bps link. A simple resistor DAC on three PICAXE outputs and an RC filter should do it. Is this basic approach worth investigating?
 

womai

Senior Member
I added a low-pass filter at the output (4th order Butterworth with a -3dB bandwidth of 1 kHz, if anybody is interested). That filters out the sudden steps (staircase) when there are only a few sampling points within a sine wave cycle. Now I get beautiful, smooth sine waves even at several 100 Hz (above about 300 Hz the filter starts to reduce the amplitude but the waveform is still smooth and stable, without jitter).

If anybody wants to duplicate the filter, I added the circuit schematic as an attachment to this post. All component values are rounded to common sizes. As for an op-amp, I have tested it with Maxim MAX292, Microchip MCP6022 and MCP6922 (all three are pin compatible) and all worked fine.

What the schematic does not show is a simple buffer (op-amp follower) between the output of the resistor network and the input of the filter, which minimizes the loading on the R-2R resistor network output.

Actually, Microchip offers a web-based active filter designer so you do not need to know much about filters to be able to design one.

Wolfgang
 

Attachments

geoff07

Senior Member
I realize that this is an old post but I thought I would update it with some recent experience which may be of use. I needed a tone generator for an audio project, and wondered if that could be done with a Picaxe, for simplicity.

The answer is yes, provided you don't want more than 1kHz and a few harmonics are acceptable.

With this code:
Code:
#picaxe 08M2 
#no_data 
setfreq m32 
'generate a sine wave 
symbol bptr_start = 28 
bptr = bptr_start 'point to first byte 
'load the sine wave 
   @bptrinc = 0 
   @bptrinc = 2 
   @bptrinc = 8 
   @bptrinc = 15 
   @bptrinc = 23  
   @bptrinc = 28 
   @bptrinc = 30 
   dacsetup %10100000 
   bptr=bptr_start 
do 
      daclevel @bptrinc 
      daclevel @bptrinc 
      daclevel @bptrinc 
      daclevel @bptrinc 
      daclevel @bptrinc 
      daclevel @bptrinc 
      daclevel @bptrdec 
      daclevel @bptrdec 
      daclevel @bptrdec 
      daclevel @bptrdec 
      daclevel @bptrdec 
      daclevel @bptrdec  
loop
an 08M2 running at 32MHz will generate a 1.04 kHz signal. A simple single-pole low pass filter (1K2, 0.1uF) gets rid of the worst of the DAC harmonics and the result is usable. The time taken for the loop to go around adds an extra step and thus harmonics, mostly taken care of by the filter. 12 steps per cycle isn't many but it could even be fewer (according to Shannon) with a better filter (more components) but this is a reasonable compromise.
 

MFB

Senior Member
Just about possible to produce an 8-pin FSK modulator then? A 1200 bps version would be pushing it but 300 bps should be well within range.
 

hippy

Ex-Staff (retired)
The time taken for the loop to go around adds an extra step and thus harmonics, mostly taken care of by the filter.
You could possibly reduce harmonics by repeating what's inside the DO-LOOP more times so there are fewer LOOP's encountered, a LOOP every N cycle rather than after each.

It might also help if the DACLEVEL outputs are re-ordered so the LOOP appears quarter-way into the cycle, at 2.5V halfway between 0V/5V which is the zero-crossing point of a virtual 0V if considered as a -2.5V/+2.5V wave =

Code:
   _      _      _
  / \    / \    / \
_/   \__/   \__/   \

  _      _      _
_/ \   _/ \   _/ \
    \_/    \_/    \
It is possible to replace the DO-LOOP with the following which should make the timing for each DACLEVEL output period more consistent but it will reduce the frequency -

Code:
i1: daclevel @bptrinc : goto i2
i2: daclevel @bptrinc : goto i3
i3: daclevel @bptrinc : goto i4
i4: daclevel @bptrinc : goto i5
i5: daclevel @bptrinc : goto i6
i6: daclevel @bptrinc : goto d6
d6: daclevel @bptrdec : goto d5
d5: daclevel @bptrdec : goto d4
d4: daclevel @bptrdec : goto d3
d3: daclevel @bptrdec : goto d2
d2: daclevel @bptrdec : goto d1
d1: daclevel @bptrdec : goto i1
 

geoff07

Senior Member
MFB: yes indeed, I haven't thought deeply about it but yes I think it could be used. With a 64MHz device, even 1200 should be possible. You would need quite good filters but they could be LC or active.

Hippy: yes I agree there are things that can be done to absorb the extra step, though I didn't try any of them. All I wanted was proof of concept that I could make a 1kHz line-up tone, which I can. Another pole on the filter would also help clean it up.
 

fernando_g

Senior Member
Or make a sinewave using a picaxe speed-controlled DC motor (or stepper), photoemitter/transistor pair shining on a revolving disc with shaded pattern. Bit like the 'Tonewheels' in old Hammond Organs ;).
Even better, use a small motor salvaged from a hard disk drive, and use it as a generator. Bonus: 3 phase outputs avalible.
 
Top