Arduino/Analog output

In this activity, we show how to dim an LED using a technique called PWM, which stands for Pulse Width Modulation.

Introduction edit

PWM is a technique for getting analog results with digital means. Digital control is used to create a square wave, which is a signal switched between on and off. This on-off pattern can simulate voltages in between full on (5 Volts) and off (0 Volts) by changing the portion of the time the signal spends on versus the time that the signal spends off. The duration of "on time" is called the pulse width. To get varying analog values, you change, or modulate, that pulse width. If you repeat this on-off pattern fast enough with an LED for example, the result is as if the signal is a steady voltage between 0 and 5v controlling the brightness of the LED.

In the graphic below, the space between each pair of green lines represents a regular time period of two milliseconds.

 

Step 1 edit

Hook up the LED to pin 9 of the Arduino, as shown in the diagram below.

 

Step 2 edit

Connect the Arduino to your computer.

Step 3 edit

Paste the following code into Arduino and run it:

/*
 Fading
 
 This example shows how to fade an LED using the analogWrite() function.
 
 The circuit:
 * LED attached from digital pin 9 to ground.
 
 Created 1 Nov 2008
 By David A. Mellis
 Modified 17 June 2009
 By Tom Igoe
 
 http://arduino.cc/en/Tutorial/Fading
 
 */

int ledPin = 9;    // LED connected to digital pin 13

void setup()  {
  // nothing happens in setup
}

void loop()  {
  // fade in from min to max in increments of 5 points:
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);        
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  }

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);        
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  }
}

Code explanation edit

We have two new concepts here. The first is the “for” loop. This is a kind of control structure. This is used when we want to repeat a block of code over and over again until some condition is satisfied.

The statements inside the parentheses are what controls the conditions of the for loop. The first one sets up the loop. It is called every time the loop starts. In this example, we create an integer called “fadeValue” and set it to 255.

The next statement is checked every time the loop repeats. If it is true, the loop repeats again. If it is false, the loop stops. In this case, we check if the “fadeValue” is greater than or equal to zero.

The last statement is also run every time the loop repeats, but at the end instead of the start. In this case, we decrease the “fadeValue” by 5 every time.

The second new concept is the “analogWrite” function. This is the function that writes an analog value (PWM wave) to a pin. As such, it requires two arguments: first, the relevant pin and, second, a value between 0 and 255. Since a call to analogWrite() is made on a scale of 0 - 255, analogWrite(pin, 255) requests a 100% duty cycle (always on) and analogWrite(pin, 127) a 50% duty cycle (on half the time) for example. It can be used to light an LED at varying brightnesses, like we do here, or drive a motor at various speeds, among other things.

After a call to analogWrite(), the pin will generate a steady square wave of the specified duty cycle until the next call to analogWrite(), or a call to digitalRead() or digitalWrite() on the same pin.

Generally, on current Arduinos, analogWrite() only works on pins 3, 5, 6, 9, 10, and 11.

Step 4 edit

Try changing the numbers in the for loop, and see what effect this has on the LED. You can change the initial value (currently 255), the final value (currently 0) and the step value (currently negative 5).

Step 5 edit

Try changing the delay value, and see what effect this has.

Step 6 edit

Using copy and paste, make a second copy of the for loop beneath the first one. In this second loop, change the initial value to 0, the final value to 255, and the step value from negative to positive 5. Also, change the greater than sign to a less than sign. The code should now look like the following:

/*
 Fading
 
 This example shows how to fade an LED using the analogWrite() function.
 
 The circuit:
 * LED attached from digital pin 9 to ground.
 
 Created 1 Nov 2008
 By David A. Mellis
 Modified 17 June 2009
 By Tom Igoe
 
 http://arduino.cc/en/Tutorial/Fading
 
 */

int ledPin = 9;    // LED connected to digital pin 13

void setup()  {
  // nothing happens in setup
}

void loop()  {
  // fade in from min to max in increments of 5 points:
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);        
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  }

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);        
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  }
  //Now fade back in, so we get a pulsing effect
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);        
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  }
}

Step 7 edit

Try changing the values in the second loop, the way you did in steps 4 and 5, and see what effect this has.

Step 8 edit

Make some more copies of the loop and use different values in each one. Can you think of other ways to produce different patterns, other than just making new loops one after the other?

Step 9 edit

Once you get this running, grab your Arduino and shake it back and forth. What you are doing here is essentially mapping time across the space. To our eyes, the movement blurs each LED blink into a line. As the LED fades in and out, those little lines will grow and shrink in length. Now you are seeing the pulse width.

Attribution edit

Certain portions of this course are based on the Arduino documentation for PWM and used with permission under the CC-BY-SA 3.0 license.