Didn't quite know where to put this one!
After being inspired by the guys over at open music lab (
http://www.openmusiclabs.com/learning/digital/pwm-dac/dual-pwm-circuits/), I had a quick look for nice quick and easy code, implementing their technique.
I had a quick search and didn't seem to find anything so I thought i'd have a quick go myself. I wrote it to use timer 1 and pins 9 and 10, at 31.25kHz and 16bit output. Since not all of us have precision resistors, take this example with a slight pinch of salt. I used a 1.8k resistor and a 470k resistor, if this was ideal, i'd being a 1.8k resistor and a 460.8k resistor but this value isn't available to the standard user! If less error is required, a 2.2k resistor and 560k resistor can be used, with perfect resistors, this should give about 0.56% error.
I wrote the code using direct timer and port manipulation for speed. Implementing a 10000-time for loop, and using micros (ensuring to divide the total time by 1.024 as 1micros-uS is = 1.024uS as far as i'm aware), I calculated the direct implementation to take about 1.23uS to execute. Changing all the instructions back to analogWrite and digitalWrite drastically increased execution time to 14.68uS, nearly 12x longer!
I will include a schematic of how to connect the resistors and capacitor. The low pass filter is set at about 18.8kHz.
Code:
long WriteVal = 32768; //Value to be written to output, needs to be long to support 16bit
void setup(){
DDRB = DDRB | 0x18; //Set pins 9 and 10 as outputs
TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM12) | _BV(WGM10); //Pin 9 & 10, fast PWM wgm
TCCR1B = _BV(CS10); //Set prescaler to 1, 32.5KHz PWM freq
}
void loop(){
if(WriteVal>255){
PORTB = 0x10; //Write pin 10 high, all other pins of B register low
OCR1A = WriteVal>>8; //Write output value bitshifted 8 to the right to pin 9
}
else if(WriteVal<256){
PORTB = 0x08; //Write pin 9 high, all other pins of B register low
OCR1B = WriteVal; //As output value will be <256, write it straight to pin 10
}
}
As can be seen, its really simple and just includes some bitshifts and direct manipulation of registers. Using my multimeter, I can verify that with a wrote value of 32768, the voltage is 2.345v. The supply voltage being 4.69v states that with a value of 32768 (half way), the voltage should be 2.345v. This seems acceptable proof to me!
Kudos to Openmusiclabs for a brilliant article!