Pulse Width Modulation (PWM) is a technique for creating a digital square wave signal. A square wave has 3 main characteristics
- Amplitude – The amount the signal changes between On and Off states
- Frequency – The number of times the signal repeats in a given time frame
- Duty Cycle – The proportion of On time to Off time usually expressed as a percentage
In these digital systems the amplitude is fixed between 0 and 1, between 0V and VCC. In my testing this was +5V.
In it’s simplest form a PWM square wave can be created with a few lines of code. The following code would produce a signal with a 1 second Frequency and a 10% duty cycle. This would be functional but the Arduino would be dedicated to producing this signal the whole time and would not do anything else. This is why the blink without delay example is so important to learn.
digitalWrite(IOPin, HIGH);
delayMicroseconds(100);
digitalWrite(IOPin, LOW);
delayMicroseconds(900);
With a software generated signal any variation in the code execution time can cause variations in the output. Conditional statements may not execute on every loop so it is hard to guarantee that each loop will take exactly the same amount of time. Modern microcontrollers have dedicated hardware modules to generate a code independent square wave. Values for Duty cycle and Frequency are written to registers within the controller and the hardware generates the appropriate signal on the desired output pin.
The registers for the Hardware PWM module can be written to directly as described here, but the joy of the Arduino environment is that somebody is likely to have written a library to simplify that process. The TimerOne library provides control over the HardwarePWM module connected to timer 1 (aptly). This library has easy functions for setting the frequency and duty cycle of the square wave being generated
- pwm(pin, duty, period) – Generates a PWM waveform on the specified pin.
The minimum freqeuncy supported by the library is 1ms and the maximum is 8.3s. The duty is specified as a 10 bit value, between 0 and 1023, and this correlates to the 0% and 100% values respectively.