Saturday, March 17, 2012

Arduino Timer Configuration for 10bit Analog Output

Two things matter for PWM analog output:

1. PWM Frequency
2. PWM Resolution

The Atmega1280 comes with a couple of timers that control PWM on specific pins.  These timers are, by default, set for 8bit operation and a prescale value of 64.  That means that the timer resets every 256 ticks and each tick is 64 clock cycles.  The Atmega1280 runs at 16 MHz so, by default the timer frequency is 1/64th of that, or 250 KHz and the timer cycle is 1/256th of that, or ~977 Hz.

This is fine so long as you want fairly crude signals, but I wanted signals good to the millisecond and better bit depth.

The manual for the Atmega1280 is fairly clear:  http://www.atmel.com/Images/doc2549.pdf

PWM frequency can be increased by setting the prescale value to 1 (i.e. the 16 MHz clock).  PWM resolution can be increased by increasing the number of timer ticks in the cycle from 256 (8 bit) to 1024 (10 bit).  This produces a PWM of 16 MHz / 1 / 1024 = 15.6 KHz.  Much better!

Since I am interested in signals << 1KHz, I can simply run the PWM output through an RC circuit with a time constant of 1 msec  (e.g. 1 uF capacitor and 1K resistor).  This produces a reasonable sine function for frequencies up to ~50 Hz.

This code, which runs in setup(), applies the aforementioned settings for Timer 1, which controls pins 11 to 13 on the Arduino Mega.  To understand it, one has to dig through the manual for the descriptions of registers TCCR1A and TCCR1B.


  // set Timer1 (pins 13 and 12 and 11)
  TCCR1B = 0x09;  // set Control Register to no prescaling 
                  // WGM02 = 1


  TCCR1A = 0x03;  // set WGM01 and WGM00 to 1 (10 bit resolution)

No comments:

Post a Comment