Showing posts with label PWM. Show all posts
Showing posts with label PWM. Show all posts

Saturday, May 12, 2012

Arduino PWM Filter

To get nice analog signals from the Arduino PWM pins it is necessary to filter the output.  Arduino PWM is somewhat slow, frequency of 15.6 kHz at 10 bit timer resolution (see this post on configuring the timer).  Luckily this is fine if you do not care about signals faster than 1 kHz.  Indeed I find that the Arduino can't really generate sine curves faster than about 0.1 kHz.  So it makes sense to just filter signals to maximally attenuate the PWM noise while retaining signals slower than 0.1 kHz.

This requires us to design a low-pass filter.  Now, doing some research, it is easy to find recipes for all kinds of analog filter designs, however, a simple RC filter does just fine for our needs.  I found a nice tutorial online explaining how the RC filter works.  The main formula needed is that the time constant of the RC circuit is related to the cutoff frequency as:  Tau = RC = 1/(2*pi*f)

So we have PWM at 15.6 kHz and we want to pass signals of 1 kHz, which means we should put our cutoff frequency at just a little above 1 kHz, say f = 2 kHz.  We get Tau = 1/(2*pi*2 kHz) = 8e-5 sec.  For a resistor of 1 kOhm, that gives a capacitor of 0.08 uF.  However, the attenuation of an RC filter is rather poor with only a -20 dB decrease per decade.  This means that for this cutoff we will be attenuating the PWM signal by only ~20 dB or ~10 times.  So a 5 V pwm will still show up as a ~500 mV signal on our output.  

To improve our results, I sometimes use a combination of a 1 kOhm resistor and a 1 uF capacitor with Tau = 1 msec.  This gives a cutoff frequency of 159 Hz, acceptable given that the Arduino has trouble with signals faster than 100 Hz and attenuates the PWM frequency significantly more (~-40dB) or only ~50 mV left of our 5 V PWM signal.

Friday, March 16, 2012

Arduino as Analog Function Generator

I realized that outputting functions over the serial port is a little too much overhead.  However, my MFCs can be controlled by analog signals on input pin 4 in the miniDIN.  So I decided to see if the Arduino can output reasonable signals by PWM.

I generated a sin using PWM and filtered the signal using a simple RC circuit (tau = 1 msec).  It took a little fiddling with the Control Register of the appropriate timer (I had to remove prescaling) to get good output PWM frequency, but it looks pretty good.

This is my test code:


unsigned long t0;


void setup() {
    pinMode(9, OUTPUT); 
    t0 = millis();
    
    TCCR1B = 0x01;
}


void loop() {
    analogWrite(9, (int) (255.0 * 0.5 *(1.0 + sin( (float) ((millis()-t0) % 1000) * 2.0 * 3.14 * 5.0 / 1000))));    
}

UPDATE: click here for explanation of my choice of RC filter

Along the way, I found this useful blog with info about the Arduino:
http://softsolder.com
http://softsolder.com/2010/09/05/arduino-mega-1280-pwm-to-timer-assignment/
http://softsolder.com/2009/02/21/changing-the-arduino-pwm-frequency/