Chapter 6. PWM – Writing Analog Information
In the previous chapter, we read information from analog sensors. It is time to write information on analog devices like motors. Writing analog information is not that straightforward. The BeagleBone processor has a Pulse Width Modulation (PWM) subsystem that can write analog information on some specific GPIO pins. In this chapter, we will learn how PWM works and how it can be used to interface analog output devices. Then we will write a program to fade an LED and drive a servo motor using PWM. In this chapter, will cover the following topics:
What is PWM?
BeagleBone's PWM
Writing on analog components
Fading LED circuit setup
Program to fade in and fade out an LED
Micro servo motor circuit setup
Program to control micro servo motor
Typically variable voltage is generated by analog circuits. Digital circuits generate only HIGH
(3.3V) or LOW
(0V) voltage. Digital microprocessors/microcontrollers cannot produce analog voltages themselves. They need a Digital to
Analog Convertor (DAC). We have seen in the previous chapter that BeagleBone has a built-in ADC that converts captured analog voltage to a value. This raises our hope that BeagleBone might have a DAC to generate analog output voltage. But this is not true. Instead of providing a DAC, it uses a mechanism called PWM, which achieves similar results. Some of the GPIO digital pins are driven by BeagleBone's PWM subsystem. It can generate any voltage inside the 0V to 3.3V range on these pins.
Suppose that we have connected an analog output device DC motor to one of the GPIO pins on BeagleBone (with capacitor filter). The speed of a DC motor changes proportionally to the voltage applied. The more voltage applied, the higher the motor speed. The connected...
PWM can be implemented via program. One can write a program with digitalWrite()
and setInterval()
to create the desired frequency and desired duty cycle. But context switching and interrupts will make it inaccurate. Also, it will keep the CPU busy. The correct solution is to support this functionality at hardware level inside the CPU. The BeagleBone CPU has a Pulse Width Modulation
Subsystem (PWMSS), which allows the accurate creation of a PWM pattern without keeping the CPU busy. The CPU will be free to do other work while the PWM subsystem takes care of the PWM wave generation. This subsystem has control over only a few GPIO pins. It can switch output very fast on these pins and can control on/off timing. So, not all GPIO pins are capable of generating PWM.
PWMSS has a set of
Time Base Counter (TBCNT) register and
Output Compare Register (OCR) to generate the desired PWM pattern. OCRs are used to set the duty cycle. You can get detailed information about PWMSS in BeagleBone...
Writing on analog components
BoneScript provides the function analogWrite()
to generate a PWM wave on any GPIO pin from the previous diagram. After a call to analogWrite()
, the pin will generate PWM waves of a specified duty cycle. Here is the prototype of the analogWrite()
function.
The code is as follows:
Where
pin
– BeagleBone pin identifier string
value
– duty cycle ratio of the PWM as value between 0
and 1
freq
– frequency of PWM in Hz
callback
– name of function which will be called automatically when analogWrite()
finishes.
Here, freq
and callback
parameters are optional. If freq
is not specified, the default value 2 kHz is used. The duty cycle ratio value is not taken as a percentage but as a ratio between 0 to 1. It is a ratio of time it was ON to period. We can get that by dividing the percentage value by 100. So, a 50% duty cycle will be 0.5 value. Sometimes, you need to read the datasheet of the analog output device to find out the correct...
Though we have studied LEDs as digital devices, they are not actually digital devices. They emit light as per voltage put across them. If the voltage is high, they emit more light. If we provide an LED with a digital value, it will be ON or OFF. It will either light up with full brightness or not at all. If we provide intermediate values, it will still glow. But not with its full intensity. As we can apply any voltage between 0V to 3.3V using PWM on an LED now, we can change the brightness of the LED from lowest to highest and from highest to lowest. This will look like the LED is fading in and out.
The circuit setup is similar to what we did in Chapter 3, Blinking External LEDs to blink external LEDs. At that time, we used P8_10 as the GPIO pin. Now we are connecting the LED to pin P9_21, which supports the PWM. You will need an LED, 470Ω resistor and a breadboard to set up this circuit. Power off the board and attach components to BeagleBone as shown in the diagram...
Program to fade in and fade out LED
Write the following code in Cloud9 and save it as fadeLED.js
. Run the program and you should see the LED fading in and out alternatively.
The code for fadeLED.js
is as follows:
In Chapter 3, Blinking External LEDs we used the function digitalWrite()
with a similar setup. Here, we are using the analogWrite()
function. We are initializing the variable duty_cycle
with a value of zero. We use the variable increment
as a Boolean flag to keep track of fading in or fading out...
Micro servo motor circuit setup
We are going to control a micro servo motor. Servo motors are special types of DC motors tightly coupled with a feed-backing control circuit that positions a shaft in a precise angle. They are used where fast, accurate, and limited angle movement is needed, for example, robot arm movement and CNC machine. The position of the motor shaft can be controlled through PWM. There is no need for extra motor driver chip.
A micro servo motor can rotate 180 degrees. The frequency/period is specific as per the servo motor. A typical servo motor expects approximately a 20 millisecond period to drive the motor. A servo motor changes shaft angle as per pulse width. If the specified pulse width is 1 millisecond or less, it remains at angle zero. That translates to approximately 3% duty cycle. If the pulse width is 1.5 milliseconds, then the servo shaft will change to a 90 degree angle. If a 2 millisecond pulse is given, the servo shaft will be at a maximum 180 degrees. It...
Program to control a micro servo motor
Write the following code in Cloud9 and save it as microServo.js
. Run the program and you should see the servo motor moving from 0 to 180 degrees to and fro.
The code for is microServo.js
as follows:
In this program, we created loopTimer
, which will increment/decrement the shaft angle by one degree. We know that we have a limit of 3% to 14.5% to drive...
In this chapter, we learned some theory about PWM. We saw that PWM is a way of creating analog values on digital pins. It can be used to drive analog output devices like motors, LEDs, speakers, and so on. We studied PWM waves and how a duty cycle can be used to control analog devices. BeagleBone has a special subsystem dedicated to generating PWM that work on subset of GPIO pins. Then we wrote a program to control the brightness of an LED via PWM. We also wrote a program to control the servo motor angle. Until now, we have done many physical computing exercises. Let's connect our BeagleBone to the Internet and control these physical components from the Internet. We will do this in next chapter. That will be our first step toward the Internet of Things (IoT).