Università degli Studi di Messina
Master's degree program in
Engineering and Computer Science
A.Y. 2021/22
Embedded Systems
Analog output with PWM
Prof. Francesco Longo
No pure analog output
● The Arduino UNO board cannot produce a pure analog output signal (there is no
pin that can be configured as pure analog output pin)
● This is because the ATMEGA328 microcontroller does not have any Digital to
Analog Converter (DAC) on board
● Historically, microcontrollers have no DAC on board because:
○ DACs are relatively expensive
○ Far fewer applications need analogue output than input
○ Roughly the same functionalities can be achieved more cheaply using PWM
and a small amount of external filtering
● Some modern and advanced microcontrollers actually have DACs on board, for
example:
○ microcontrollers belonging to the STM8AL series produced by
STMicroelectronics for automotive applications have 12-bit DACs on board
○ microcontrollers belonging to the SAMD21 series produced by Microchip have
10-bit DACs on board
Pulse Width Modulation (PWM)
● PWM is a technique for controlling the average amount of power delivered to a load
by an electrical signal
● The average value of voltage (and current) fed to the load is controlled by turning a
switch between supply and load on and off at a fast rate
● The longer the switch is on compared to the off periods, the higher is the total
power supplied to the load
● The PWM switching frequency has to be high enough not to affect the load, which
is to say that the resultant waveform perceived by the load must be as smooth as
possible
● The rate (or frequency) at which the power supply must switch can vary greatly
depending on load and application.
Duty Cycle
● The term duty cycle describes the proportion of 'on' time with respect to the regular interval or
'period' of time of the considered waveform (Duty Cycle = Pulse Width x 100 / Period)
● A low duty cycle corresponds to low power, because the power supply is off for most of the time
while a high duty cycle corresponds to high power, because the power supply is more on than off
● Duty cycle is expressed in percent, 100% being fully on and 0% being fully off
● When a digital signal is on half of the time and off the other half of the time, the digital signal has a
duty cycle of 50% and resembles a "square" wave
Duty Cycle (2)
● The average amount of power perceived by the load is proportional to the duty
cycle
● Varying the duty cycle, it is possible to vary the average amount of power perceived
by the load which will then ‘see’ the equivalent of an analog output signal
PWM with the Arduino UNO
● Microcontrollers used on Arduino boards are equipped with ad-hoc hardware for implementing PWM on
specific pins (usually indicated with the ~ on the boards)
● The Arduino IDE provides the analogWrite() function to control the PWM duty cycle
BOARD PWM PINS PWM FREQUENCY
Uno, Nano, Mini 3, 5, 6, 9, 10, 11 490 Hz (pins 5 and 6: 980 Hz)
● Thus, roughly every 1/500 of a second (~1/1000 of a second on pins 5 and 6), the PWM output will produce a
pulse
● The analogWrite() function has two parameters:
○ the first parameters is the number of the pin that we want to use as PWM output
○ the second parameter is an integer from 0 to 255:
■ with 0 as second parameter, the microcontroller will not produce any pulse at all, so that the
output is actually off all the time (correspondent to 0V)
■ with 255 as second parameter, the microcontroller will produce a pulse that lasts all the way
until the next pulse is due, so that the output is actually on all the time (correspondent to 5V)
■ with a value somewhere in between 0 and 255 as second parameter, the microcontroller will
produce a pulse with a duty cycle proportional to the value (corresponding to a value between
0V and 5V)
■ thus the value of the second parameter will indicate the amount of power provided to the load
Change the brightness of the LED using PWM
● If we attach an external LED to a PWM output pin, we will not be able to see the LEDs
turning on and off at the PWM frequency
● To our eyes, the effect will be that the brightness of the LED is proportional to the PWM
duty cycle
// define LED pin
#define LED 6
//fading time
#define delayTime 5
void setup(){
//set LED pin as output
pinMode(LED, OUTPUT);
}
// main loop
void loop(){
// fading the LED from full on to full off
for (int i=0; i<255; i++){
analogWrite(LED, i);
delay(delayTime);
}
//fading the LED from full off to full on
for(int i=255; i>0; i--){
analogWrite(LED, i);
delay(delayTime);
}
}
RGB LEDs
● RGB (Red, Green and Blue) LEDs look just like regular white LEDs, but inside the
usual LED package, there are actually three LEDs, one red, one green, and one blue
● By controlling the brightness of each of the individual LEDs it is possible to mix
pretty much any color the same way a pixel on a screen actually works
● RGB LEDs come into two kind: common cathode and common anode
● We will use common cathode RGB LEDs
Using RGB LEDs with the Arduino UNO
● The RGB LED has four leads. There is one lead going to the anode of each of the single LEDs within the
package and a single lead that is connected to all three cathodes of the LEDs.
● The common negative connection of the LED package is the second pin from the flat side, it is also the
longest of the four leads and should be connected to ground
● Each LED inside the package requires its own resistor to limit the current flowing through it
● The three positive leads of the LEDs (one red, one green and one blue) should be connected to the Arduino
UNO output pins using these resistors
The code
// define pins // main loop
#define BLUE 3 void loop(){
#define GREEN 5 // fades out red to green
#define RED 6 for (int i=0; i<255; i++){
//fading time between colors analogWrite(RED, --redValue);
#define delayTime 10 analogWrite(GREEN, ++greenValue);
delay(delayTime);
void setup(){ }
//set output pins //now redValue = 0, greenValue = 255
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT); // fades out green to blue
pinMode(BLUE, OUTPUT); for (int i=0; i<255; i++){
//let's start with pure red color analogWrite(GREEN, --greenValue);
digitalWrite(RED, HIGH); analogWrite(BLUE, ++blueValue);
digitalWrite(GREEN, LOW); delay(delayTime);
digitalWrite(BLUE, LOW); }
} //now greenValue = 0, blueValue = 255
// global variables // fades out blue to red
//let's start with pure red color for (int i=0; i<255; i++){
int redValue = 255; analogWrite(BLUE, --blueValue);
int greenValue = 0; analogWrite(RED, ++redValue);
int blueValue = 0; delay(delayTime);
}
//now blueValue = 0, redValue = 255, let's start again
}