Hey guys,
A couple of months ago I found myself needing to generate an analog DC
voltage on an AVR microcontroller's digital I/O pin as part of a test
procedure. I was not free to alter the hardware, so I had to work with
what I had - I decided to use PWM. My first stab looked something like
this:
for(i=0; i<256; i++)
{
if (sample < i) set_bit();
else clr_bit();
}
This generates a square wave whose duty cycle is controlled by the value
of "sample". Only problem was that the capacitance on the I/O line was
not quite high enough to filter this sufficiently for my needs. So I
changed the code to bit reverse the 8 ls bits of "i" in the compare:
for(i=0; i<256; i++)
{
if (sample < bit_rev[i]) set_bit();
else clr_bit();
}
This jacked the frequency way up and the filter was easily able to
handle it. Instead of a nasty-looking sawtooth, I saw a nice smooth DC.
Now for the question - is bit-reversal optimal for maximizing the i/o
frequency, or is there something better?
--
Jim Thomas Principal Applications Engineer Bittware, Inc
jthomas@bittware.com http://www.bittware.com (603) 226-0404 x536
Failure is always an option
PWM trick
Started by ●November 16, 2007
Reply by ●November 16, 20072007-11-16
Jim Thomas wrote:> Hey guys, > > A couple of months ago I found myself needing to generate an analog DC > voltage on an AVR microcontroller's digital I/O pin as part of a test > procedure. I was not free to alter the hardware, so I had to work with > what I had - I decided to use PWM. My first stab looked something like > this: > > for(i=0; i<256; i++) > { > if (sample < i) set_bit(); > else clr_bit(); > } > > This generates a square wave whose duty cycle is controlled by the value > of "sample". Only problem was that the capacitance on the I/O line was > not quite high enough to filter this sufficiently for my needs. So I > changed the code to bit reverse the 8 ls bits of "i" in the compare: > > > for(i=0; i<256; i++) > { > if (sample < bit_rev[i]) set_bit(); > else clr_bit(); > } > > This jacked the frequency way up and the filter was easily able to > handle it. Instead of a nasty-looking sawtooth, I saw a nice smooth DC. > > Now for the question - is bit-reversal optimal for maximizing the i/o > frequency, or is there something better?This is what delta sigma is for. Noise shaping 1: for(;;) { x = sample + carry_over; if(x & 0x80) set_bit(); else clr_bit(); carry_over = x&0x7F; } Noise shaping 2: for(;;) { x = sample + (carry_over0<<1) - carry_over1; if(x & 0x80) set_bit(); else clr_bit(); carry_over1 = carry_over0; carry_over0 = x&0x7F; } The noise shapings of the higher order are less interesting because they require multiplication. Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
Reply by ●November 16, 20072007-11-16
Jim Thomas <jthomas@bittware.com> wrote in news:13jreihamk8eu45 @corp.supernews.com:> Now for the question - is bit-reversal optimal for maximizing the i/o > frequency, or is there something better?Many microcontrollers have PWM modules that you set the frequency, and then update the duty cycle as needed. At the very least, consider using timers to flip your bits in interrupts. You should be able to go pretty fast then, and your timing will be much more dependable. -- Scott Reverse name to reply
Reply by ●November 16, 20072007-11-16
Jim Thomas wrote:> Hey guys, > > A couple of months ago I found myself needing to generate an analog DC > voltage on an AVR microcontroller's digital I/O pin as part of a test > procedure. I was not free to alter the hardware, so I had to work with > what I had - I decided to use PWM. My first stab looked something like > this: > > for(i=0; i<256; i++) > { > if (sample < i) set_bit(); > else clr_bit(); > } > > This generates a square wave whose duty cycle is controlled by the value > of "sample". Only problem was that the capacitance on the I/O line was > not quite high enough to filter this sufficiently for my needs. So I > changed the code to bit reverse the 8 ls bits of "i" in the compare: > > > for(i=0; i<256; i++) > { > if (sample < bit_rev[i]) set_bit(); > else clr_bit(); > } > > This jacked the frequency way up and the filter was easily able to > handle it. Instead of a nasty-looking sawtooth, I saw a nice smooth DC. > > Now for the question - is bit-reversal optimal for maximizing the i/o > frequency, or is there something better? >See http://www.wescottdesign.com/articles/sigmadelta.html. There's no reason you can't do it with a one-bit output, and maybe you can use Vladimir's 2nd-order filter. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Do you need to implement control loops in software? "Applied Control Theory for Embedded Systems" gives you just what it says. See details at http://www.wescottdesign.com/actfes/actfes.html
Reply by ●November 19, 20072007-11-19
On Nov 16, 8:42 am, Jim Thomas <jtho...@bittware.com> wrote:> > Now for the question - is bit-reversal optimal for maximizing the i/o > frequency, or is there something better?Cool - years ago I used a bit-reversed PWM to implement an analog output on a digital ASIC to close a clock tracking loop. It worked pretty well. I haven't seen it discussed though so I always wondered if I was missing something obviously wrong with it. Since then I've seen similar problems solved using the noise shaping technique Vladimir described. I'd guess the complexity is about the same, but noise shaping seems more elegant to me. EB
Reply by ●November 22, 20072007-11-22
There is another similar trick that can be used to generate PWM. if (sample > rand(scaled to same range as sample)) set_bit() else clr_bit(); This can be called at irregular intervals. I used this as an idle task on an application. Regards -- Walter Banks Byte Craft Limited Tel. (519) 888-6911 Fax (519) 746 6751 http://www.bytecraft.com walter@bytecraft.com Jim Thomas wrote:> Hey guys, > > A couple of months ago I found myself needing to generate an analog DC > voltage on an AVR microcontroller's digital I/O pin as part of a test > procedure. I was not free to alter the hardware, so I had to work with > what I had - I decided to use PWM. My first stab looked something like > this: > > for(i=0; i<256; i++) > { > if (sample < i) set_bit(); > else clr_bit(); > } > > This generates a square wave whose duty cycle is controlled by the value > of "sample". Only problem was that the capacitance on the I/O line was > not quite high enough to filter this sufficiently for my needs. So I > changed the code to bit reverse the 8 ls bits of "i" in the compare: > > for(i=0; i<256; i++) > { > if (sample < bit_rev[i]) set_bit(); > else clr_bit(); > } > > This jacked the frequency way up and the filter was easily able to > handle it. Instead of a nasty-looking sawtooth, I saw a nice smooth DC. > > Now for the question - is bit-reversal optimal for maximizing the i/o > frequency, or is there something better? > > -- > Jim Thomas Principal Applications Engineer Bittware, Inc > jthomas@bittware.com http://www.bittware.com (603) 226-0404 x536 > Failure is always an option
Reply by ●November 26, 20072007-11-26
Vladimir Vassilevsky wrote:> This is what delta sigma is for. > > Noise shaping 1: > > for(;;) > { > x = sample + carry_over; > if(x & 0x80) set_bit(); > else clr_bit(); > carry_over = x&0x7F; > } > > Noise shaping 2: > > for(;;) > { > x = sample + (carry_over0<<1) - carry_over1; > if(x & 0x80) set_bit(); > else clr_bit(); > carry_over1 = carry_over0; > carry_over0 = x&0x7F; > } > > The noise shapings of the higher order are less interesting because they > require multiplication.That's pretty cool Vladimir. Thanks for the reply. If this ever comes up again, I'll try it this way. -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (603) 226-0404 x536 The secret to enjoying your job is to have a hobby that's even worse - Calvin's Dad
Reply by ●November 26, 20072007-11-26
Scott Seidman wrote:> Jim Thomas <jthomas@bittware.com> wrote in news:13jreihamk8eu45 > @corp.supernews.com: > >> Now for the question - is bit-reversal optimal for maximizing the i/o >> frequency, or is there something better? > > > Many microcontrollers have PWM modules that you set the frequency, and then > update the duty cycle as needed.Thanks for the suggestion. In my experience, the PWM features of most microcontrollers are limited to certain pins. I was not at liberty to rearrange any pins because the hw/sw in the "real" application was already doing exactly what it was supposed to be doing. My task was to write some test software for when this card was plugged into a test jig.> > At the very least, consider using timers to flip your bits in interrupts. > You should be able to go pretty fast then, and your timing will be much > more dependable.Since the PWM was the only thing going on at the time, I don't think an IRQ would make it go any faster - especially when the context switching overhead is taken into account. -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (603) 226-0404 x536 The secret to enjoying your job is to have a hobby that's even worse - Calvin's Dad
Reply by ●November 26, 20072007-11-26
emeb wrote:> On Nov 16, 8:42 am, Jim Thomas <jtho...@bittware.com> wrote: >> Now for the question - is bit-reversal optimal for maximizing the i/o >> frequency, or is there something better? > > Cool - years ago I used a bit-reversed PWM to implement an analog > output on a digital ASIC to close a clock tracking loop. It worked > pretty well. I haven't seen it discussed though so I always wondered > if I was missing something obviously wrong with it. > > Since then I've seen similar problems solved using the noise shaping > technique Vladimir described. I'd guess the complexity is about the > same, but noise shaping seems more elegant to me.Yes, it does. Unfortunately for me, the bit-reversed PWM is working too well, so I cannot justify revisiting it. But if there's a next time... -- Jim Thomas Principal Applications Engineer Bittware, Inc jthomas@bittware.com http://www.bittware.com (603) 226-0404 x536 The secret to enjoying your job is to have a hobby that's even worse - Calvin's Dad
Reply by ●November 26, 20072007-11-26
Jim Thomas <jthomas@bittware.com> wrote in news:13kll479jpttd22 @corp.supernews.com:> Since the PWM was the only thing going on at the time, I don't think an > IRQ would make it go any faster - especially when the context switching > overhead is taken into account.You're doing 2 comparisons, 1 increment, and a set or clear bit every pass through your loop! Compare this to two set or clear for each PWM period. You should be able to go many times faster, at least, using a timer, context switching or no. -- Scott Reverse name to reply






