PDA

View Full Version : D/A chip for low frequency



Pablo1234
05-15-2010, 10:57 PM
Howdy guys, I am currently starting on the prop, I have held off way too long on this. I have been playing with the basic stamp for about 7 years and I need more power for what I am doing now.

What would you recomend for a Digital to Analog converter for low frequency range of 0.1 Hz to 12 Hz generation. I am currently working on a multichannel programable LFO and I want control over the PWM, phase and Amplitude·of the signal. Any sugetions? I have the Prop, regulators·and a 5Mhz crystal on order right now and just need a good choice for the Digital to analog. I'm also looking to do level detection so I will need an A/D also but thats not so critical at the moment.·

Leon
05-15-2010, 11:01 PM
How many bits do you need? At that frequency almost anything will do - there are plenty around using I2C and SPI.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Leon Heller
Amateur radio callsign: G1HSM

Pablo1234
05-15-2010, 11:18 PM
Well I am familler with I2C I/O and Eproms so that would probably be my direction. I'm gessing 8 or 12 bit would be good. thier just Occilators driveing some Bulbs and LED's for LDR's and posibaly some FETS as VCR's. I may take a stabe at Transconductance amps also. I am realy excited after reading some of the documentation on the prop. Its absolutly amazing realy.
I also need it to be in DIP form. surface mount is a bit tough for my old hands.

on a side note is thier an I2C LCD avalible?

Post Edited (Pablo1234) : 5/15/2010 3:38:17 PM GMT

Leon
05-16-2010, 12:00 AM
10- or 12-bit will be more common, I doubt if there is any demand for 8-bits. You shouldn't have any problem finding what you want in DIL.

There are LCDs with serial interfaces, so there might I2C ones. I made my own serial LCD using an AVR, and I've often thought of making an I2C or SPI version.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Leon Heller
Amateur radio callsign: G1HSM

Ariba
05-16-2010, 12:17 AM
You can use a simple RC circuit and a counter of the Propeller to produce a high resolution DAC for such low frequencies.
If one of the counters of a cog is initialized in DUTY mode, you only need to write the DAC value to the PHSx register.
So you can have 2 RC-DACs per cog.

The following code outputs a value at pin PA0 and increases it all 2 seconds.


CON _clkmode = xtal1 + pll16x
_xinfreq = 5_000_000

DAC = 0

PUB Main | val
dira[DAC] := 1 'Set up DAC
ctra := %00110 << 26 + DAC 'counter A in DUTY mode

val := 0
repeat 'loop
frqa := val << 16 'set DAC (lower 16 bit of val)
waitcnt(clkfreq*2 + cnt) 'wait 2 seconds
val += 6000 'increase value




Andy

Pablo1234
05-17-2010, 12:29 AM
http://www.mouser.com/ProductDetail/Maxim-IC/MAX521BCPP+/?qs=sGAEpiMZZMswix2y39yldWlrlADk%2feI6kkd%252bVFaX 4gY%3d

This is the DAC I'm looking at right now.

I don't want to do square wave outs and integrate them, I want control over the shape of the wave Tri, Saw, reverse saw and sine from .0 hz to 12 hz. I also need control over the amplitude and phase. doing this in anolog with a pulse output is how I am currently doing it with a basic stamp and its alot of extra circuitry, intigrator for square to·Tri or Saw·and high pass filter to readjust amplitude and set sine. Total pain in the but.

Leon
05-17-2010, 01:03 AM
That's got eight DACs. Look for one with a single DAC, it'll be cheaper. Here is a nice one:

www.linear.com/pc/productDetail.jsp?navId=H0,C1,C1156,P2333 (http://www.linear.com/pc/productDetail.jsp?navId=H0,C1,C1156,P2333)

The buffered output will save you having to provide a buffer.

Linear is very liberal with free samples.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Leon Heller
Amateur radio callsign: G1HSM

Phil Pilgrim (PhiPi)
05-17-2010, 03:33 AM
Pablo,

With the Propeller there's much less external circuitry needed to get what you want. Here's a program I wrote to output low-frequency sine waves:




CON

_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000

FREQ = 6111 'Frequency in millihertz.
OUTPIN = 0

PUB start | t, dt, phase, amplitude

ctra := %00110 << 26 | OUTPIN
dira := 1 << OUTPIN
phase~
dt := clkfreq / 1000
t := cnt + dt
repeat
phase += FREQ << 15 / 3907
amplitude := sin(phase >> 10) << 15 + $8000_0000
waitcnt(t += dt)
frqa := amplitude

PUB sin(x) : value | t

if (x & $fff == $800)
value := $ffff
else
if (x & $800)
t := -x & $7ff
else
t := x & $7ff
value := word[*$e000][*t]
if (x & $1000)
value := -value




It uses a counter's DUTY mode output and the exact RC network that Andy showed above to filter it. Here's what the output looks like:

http://forums.parallax.com/attachment.php?attachmentid=70374

It's hardly what I'd call a "pain in the butt". http://forums.parallax.com/images/smilies/smile.gif For your app, an external DAC would be overkill.

-Phil

Addendum: BTW, this is the raw output from the pin that the RC network is filtering:

http://forums.parallax.com/attachment.php?attachmentid=70377

'Notice the frequency and time scale? 12Hz is glacial by comparison.

Post Edited (Phil Pilgrim (PhiPi)) : 5/16/2010 9:17:19 PM GMT

Pablo1234
05-17-2010, 07:13 AM
Phil, can you output Triangle waves, Sine waves, forward saw and revers saw waves selectable with control over Phase, PWM, amplitude and Frequency with just a simple RC network?

I need 6 programable LFO's so the 8 channel will save me some pins

Phil Pilgrim (PhiPi)
05-17-2010, 10:55 AM
Yes, absolutely! However, to use the counters' DUTY mode output to do six outputs, you will need three cogs, since each cog has only two counters. You could also try the PWMx8 object in the OBEX to do up to eight outputs at once. But the PWM frequency is much less than the DUTY mode rate, so more filtering will be required, and you may get rounding on the peaks of the sawtooth waves.

Here's some output that alternates between sine and sawtooth every cycle:

http://forums.parallax.com/attachment.php?attachmentid=70384

Andy's RC filter was a bit too aggressive for a sawtooth waveform, so I reduced the resistor to 6.8K to obtain this scope trace.

-Phil

Pablo1234
05-18-2010, 02:14 AM
very cool, I can't wait to get my chip this week.
I am getting sick as a dog but I think I can program from bed lol.
The main isue I had with integrating with an CR network on my stamp was that it would go from a tri wave at high freq to a saw at the lower frequencys. also the amplitude would change. I need to look more into how the Prop is programed and what its limitations are but I beleve I will be able to get closer to what I want with it x10. Some of the projects you guys have done are super impressive. I love the cnc router project.

Pablo1234
05-21-2010, 06:15 AM
OK I am nolonger bedridden. The flu is almost gone. I just recived my prop, 3.3v regulator and 5MHz crystal.
I also have been reading the docs and I think I'm gona try the bst with PropBasic unless someone thinks it would be better for me to use Spin. I am very unfamiler with Spin, Multicore programing and the Propellor. I am very familer with PBasic, VB 6 and computer programing though.

Could someone start me off with PropBasic by rewriting this Spin Phil wrote the other day?


CON

_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000

FREQ = 6111 'Frequency in millihertz.
OUTPIN = 0

PUB start | t, dt, phase, amplitude

ctra := %00110 << 26 | OUTPIN
dira := 1 << OUTPIN
phase~
dt := clkfreq / 1000
t := cnt + dt
repeat
phase += FREQ << 15 / 3907
amplitude := sin(phase >> 10) << 15 + $8000_0000
waitcnt(t += dt)
frqa := amplitude

PUB sin(x) : value | t

if (x & $fff == $800)
value := $ffff
else
if (x & $800)
t := -x & $7ff
else
t := x & $7ff
value := word[­$e000][­t]
if (x & $1000)
value := -value

ok I wana try and break this down to see if I under stand it


CON

_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000

this sets the·prop to the external crystal _xinfreq at 5,000,000 and xtal1 sets the proper internal RC network for the crystal and pll16x is the multiplier of _xinfreq x 16 = 80,000,000 hz

so ctra and ctrb will incrament every 12.5 microseconds with no modifiers.

the rest i get but I am a bianary person not boolian·so BITSHIFTING and·useing OR to add numbers kinda complicates it a bit for me. Not that I dont understand the·concept but i'm not understanding why you shift 0 (OUTPIN) to the 26th bit of ctra.

then phase an internal variable to the subroutine·is reset to 0 useing ~

dt is then set to··dt·:=·clkfreq·/·1000·= 80,000

then t is set to the current count + 80,000

so all that would be the initalization for the return loop that follows it. and the sin is a look up table in the rom to offset the amplitude to create a sin wave from a ramped signal.



I know I dont fully understand this yet but I want to.

Pablo1234
05-21-2010, 06:23 AM
·this is how I did it on my stamp, it outputs a square wave with some data in memory I have control of the freq, phase relationship and on/off time independantly for each lfo. suprisingly with Inc_Base at 16 the code execution comes out to be perfect 1hz when the multiplier is set at 10. I know I'm not getting exact Freq with useing the loop to set my timebase but its close enough for what I am doing, and the relationship of the frequencys is realy what I want control of.


' {$STAMP BS2p}
' {$PBASIC 2.5}
Count_Base_0 CON 5000
Inc_Base CON 16
LFO1_Freq_T1 VAR Byte
LFO2_Freq_T1 VAR Byte
LFO3_Freq_T1 VAR Byte
LFO4_Freq_T1 VAR Byte
LFO1_Freq_T2 VAR Byte
LFO2_Freq_T2 VAR Byte
LFO3_Freq_T2 VAR Byte
LFO4_Freq_T2 VAR Byte
LFO_PWM VAR Byte
LFO_Phase VAR Byte
LFO1_Count VAR Word
LFO2_Count VAR Word
LFO3_Count VAR Word
LFO4_Count VAR Word
LFO1_State PIN 3 'Pulse out
LFO2_State PIN 4
LFO3_State PIN 5
LFO4_State PIN 6
Config_Set PIN 12
Edit_P_Button PIN 13
DATA @0, 1 'LFO1 T1 Multiplier 1 to 16
DATA @1, 0 'Phase Incrament -16 to 16
DATA @2, 5 'T1 and T2 offset -11 - 11
DATA @16, 1 'LFO1 T1 Multiplier 1 to 16
DATA @17, 0 'Phase Incrament -16 to 16
DATA @18, 0 'T1 and T2 offset -11 - 11
DATA @32, 1 'LFO1 T1 Multiplier 1 to 16
DATA @33, 0 'Phase Incrament -16 to 16
DATA @34, 0 'T1 and T2 offset -11 - 11
DATA @48, 1 'LFO1 T1 Multiplier 1 to 16
DATA @49, 0 'Phase Incrament -16 to 16
DATA @50, 0 'T1 and T2 offset -11 - 11

Setup:
READ 0, LFO1_Freq_T1
PUT 0, LFO1_Freq_T1
READ 1, LFO_Phase
PUT 1, LFO_Phase
READ 2, LFO_PWM
PUT 2, LFO_PWM
GET 0, LFO1_Freq_T1
GET 1, LFO_Phase
GET 2, LFO_PWM
LFO1_Count = (Count_Base_0 - (LFO_Phase * LFO1_Freq_T1))
LFO_PWM = (LFO_PWM * 2) * LFO1_Freq_T1
LFO1_Freq_T2 = LFO1_Freq_T1 * Inc_Base - LFO_PWM
LFO1_Freq_T1 = LFO1_Freq_T1 * Inc_Base + LFO_PWM

READ 16, LFO2_Freq_T1
PUT 16, LFO2_Freq_T1
READ 17, LFO_Phase
PUT 17, LFO_Phase
READ 18, LFO_PWM
PUT 18, LFO_PWM
GET 16, LFO2_Freq_T1
GET 17, LFO_Phase
GET 18, LFO_PWM
LFO2_Count = (Count_Base_0 - (LFO_Phase * LFO2_Freq_T1))
LFO_PWM = (LFO_PWM * 2) * LFO2_Freq_T1
LFO2_Freq_T2 = (LFO2_Freq_T1 * Inc_Base) + LFO_PWM
LFO2_Freq_T1 = (LFO2_Freq_T1 * Inc_Base) - LFO_PWM

READ 32, LFO3_Freq_T1
PUT 32, LFO3_Freq_T1
READ 33, LFO_Phase
PUT 33, LFO_Phase
READ 34, LFO_PWM
PUT 34, LFO_PWM
GET 32, LFO3_Freq_T1
GET 33, LFO_Phase
GET 34, LFO_PWM
LFO3_Count = (Count_Base_0 - (LFO_Phase * LFO3_Freq_T1))
LFO_PWM = (LFO_PWM * 2) * LFO3_Freq_T1
LFO3_Freq_T2 = (LFO3_Freq_T1 * Inc_Base) + LFO_PWM
LFO3_Freq_T1 = (LFO3_Freq_T1 * Inc_Base) - LFO_PWM

READ 48, LFO4_Freq_T1
PUT 48, LFO4_Freq_T1
READ 49, LFO_Phase
PUT 49, LFO_Phase
READ 50, LFO_PWM
PUT 50, LFO_PWM
GET 48, LFO4_Freq_T1
GET 49, LFO_Phase
GET 50, LFO_PWM
LFO4_Count = (Count_Base_0 - (LFO_Phase * LFO4_Freq_T1))
LFO_PWM = (LFO_PWM * 2) * LFO4_Freq_T1
LFO4_Freq_T2 = (LFO4_Freq_T1 * Inc_Base) + LFO_PWM
LFO4_Freq_T1 = (LFO4_Freq_T1 * Inc_Base) - LFO_PWM

Main:
DO
IF LFO1_State = 0 AND LFO1_Count = (Count_Base_0 + LFO1_Freq_T1) THEN
LFO1_Count = Count_Base_0
HIGH LFO1_State
ELSEIF LFO1_State = 1 AND LFO1_Count = (Count_Base_0 + LFO1_Freq_T2) THEN
LFO1_Count = Count_Base_0
LOW LFO1_State
ENDIF
LFO1_Count = LFO1_Count + 1
IF LFO2_State = 0 AND LFO2_Count = (Count_Base_0 + LFO2_Freq_T1) THEN
LFO2_Count = Count_Base_0
HIGH LFO2_State
ELSEIF LFO2_State = 1 AND LFO2_Count = (Count_Base_0 + LFO2_Freq_T2) THEN
LFO2_Count = Count_Base_0
LOW LFO2_State
ENDIF
LFO2_Count = LFO2_Count + 1
IF LFO3_State = 0 AND LFO3_Count = (Count_Base_0 + LFO3_Freq_T1) THEN
LFO3_Count = Count_Base_0
HIGH LFO3_State
ELSEIF LFO3_State = 1 AND LFO3_Count = (Count_Base_0 + LFO3_Freq_T2) THEN
LFO3_Count = Count_Base_0
LOW LFO3_State
ENDIF
LFO3_Count = LFO3_Count + 1
IF LFO4_State = 0 AND LFO4_Count = (Count_Base_0 + LFO4_Freq_T1) THEN
LFO4_Count = Count_Base_0
HIGH LFO4_State
ELSEIF LFO4_State = 1 AND LFO4_Count = (Count_Base_0 + LFO4_Freq_T2) THEN
LFO4_Count = Count_Base_0
LOW LFO4_State
ENDIF
LFO4_Count = LFO4_Count + 1
LOOP
RETURN

Post Edited (Pablo1234) : 5/20/2010 10:29:02 PM GMT

Pablo1234
05-21-2010, 02:36 PM
ok i understand now, setting ctra := %00110 is setting the duty cycle and then its bitshifted to 26 to 30 then pin 0 is set for apin in ctra. So as I read the docs I am getting this.

So how do I detect my on time and off time, not in the duty but the output. Say I want to have a triangle wave that ramps up·for 100mS and ramps down for 66mS. This would be on for·5/8ths and off for 3/8ths of 6Hz. I want to specify frequency and change·the duty of my output wave.

How do·I make an offset of my phase relationship between LFO 1·,2, 3, 4, 5, 6? and at what incrament would it be in. at 12Hz and 1 mS slice time·I am gessing 2.3 deg phase incraments, correct?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
A woman is the only thing I am afraid of that I know will not hurt me. - Abraham Lincoln