Trying to understand counters and DAC's
turbosupra
Posts: 1,088
Hello,
I cannot figure out how to alter the output of this so that I do not get a rising and falling (very choppy) saw tooth signal. I was expecting ground to rail PWM square waves? I understand most of the code, but I'm a little green on using the ctr to generate a signal ... what am I missing?
I want to start with this simple code and then once I understand it better, connect the prop pin to a simple circuit with an LM358 op to have a DAC circuit.
I cannot figure out how to alter the output of this so that I do not get a rising and falling (very choppy) saw tooth signal. I was expecting ground to rail PWM square waves? I understand most of the code, but I'm a little green on using the ctr to generate a signal ... what am I missing?
I want to start with this simple code and then once I understand it better, connect the prop pin to a simple circuit with an LM358 op to have a DAC circuit.
{{ DAC Demo You can easily replicate it though, by setting up a counter for DUTY mode and trying various values for FRQx to see the effect that they have. }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 LEFT_DAC_PIN = 26 RIGHT_DAC_PIN = 27 var long leftChannel long rightChannel PUB Main | phl,phr ctra := %00110<<26 + LEFT_DAC_PIN 'init counters for DACs, DUTY single-ended mode ctrb := %00110<<26 + RIGHT_DAC_PIN dira[LEFT_DAC_PIN] := 1 'set DAC pins to output dira[RIGHT_DAC_PIN] := 1 repeat frqa += 80000 'convert to Triangle and write absolute value to DAC L frqb += 80000 'convert to Triangle and write absolute value to DAC R {repeat phl += 80000'63_000_000 'DDS Sawtooth Osc L frqa := ||phl 'convert to Triangle and write absolute value to DAC L phr += 80000'63_200_000 'DDS Sawtooth Osc R frqb := ||phr 'convert to Triangle and write absolute value to DAC R}
Comments
The prop is purely digital and it's by "slowing down" that state behind the RC component you are getting an average of the 0 and 1 the counter is putting out.
For a fixed voltage output, use
frqa := 80000 ' or other value
frqb := 80000
repeat
An r/c is next after I get my head wrapped around this, and the r/c will feed the lm358
I still would expect something other than the choppy saw tooth output, which was why I posted
I actually tried that (specifically the code below) before posting and it gave me a flat line on the scope at ground which was what finally prompted me to swallow my pride and post
Am I misunderstanding you by chance?
Lawson
80000 is hardly any voltage output.
I'm using a prop scope and I changed the value to -1 as T Chap recommended in the post below yours and am now seeing a flatline of ~3.3v ... is this what you expected? I ranged from 50nS to 50uS and saw the same thing.
Frqa 0 = 0V
Frqa -1 is the max voltage (4billionish) = 3v3
One more question if I could, is the formula for expected voltage 3.3/4294967296? To get different averaged voltage values (I figure 250 hz is fast enough for the oscillation portion) in the R/C network?
So 500hz wasn't enough to get rid of the sawtooth-ishness and so I bumped it to 5000 hz.
I also noticed that (2^32) / 330 [=13015052] does not equal 1/100th of a volt, it actually equals 1/200th of a volt, probably because of my time domain, using 2 wait cnts. The correct value for my current code is that 26030105 = 1/100th of a volt.
On top of that, the value is skewed a bit, because 150 * 26030105 = 1.45v instead of 1.5v. Is there a standard compensation value for this? Maybe this is because I'm not doing floating point math and I'm truncating the decimal values?
frqx := ( centi_volts * ( POSX / 3.3 / 100) ) << 1
(POSX / 3.3 / 100) should be computed as a constant, while the "<< 1" sacrifices 1 bit of precision to work around the signed multiplication in spin.
Lawson
You are the teacher, I am the student so I can't be getting too technical ... but I will keep a lookout for smoke now : )
I did this
conn := ((POSX / 33) / 10) ' ((2147483648 / 3.3) / 100)
and
frqa := ((150 * conn) << 2) yielded 1.43v
Is that the value you see as well?
For some reason when I use frqa := 2147483648, the output value is 1.72v, but when I use frqa := 2147483648/2, the output value is 2.8, when I set frqa := 2147483648/4, the output value is 3.09 and finally frqa := 2147483648/8, the output value is 3.12 ... what?
What am I missing? It's doing the opposite of what I expect. I'm trying to build a look up or value table so that I can write code and say that if the input value is this, multiply by this to get the output value I want.
I would have thought to lose the sign bit you would shift right and sacrifice the lowest bit.
I was trying it with the shl, but I wasn't getting the results I thought I should be getting, so I switched to hard coded numbers and once it makes sense, I'll start working on the formula or using Lawsons formula. Here is the whole code block, it's pretty simplistic I think?
Your voltages don't make sense, are you using the RC that is suggested by the Prop manual? 10k and .01?
Try each value for frqa above and see what you get. The middle value should be around 1.655
If you divide -2_147_483_646 by 2, you do get a higher voltage output. The closer you get to -1, the closer to 3v3.
When you roll over -1 back to 0, the voltage goes back to 0.
The values I observed are italicized next to yours in the code block and they are very close. Do you think Lawson's formula is applicable now?
I guess I can also have the loop continue to check an address or long for a value and it can just update the frqX to whatever value I need based on centivolts + skew?