Sunday, February 21, 2016

C/C++ on Intel Edison/Galileo – part3: PWM

In this blog post, we are going to look into the ways of mraa functions used for controlling the PWM module available on the Galileo/Edison. In this tutorial, we will using PWM to control the intensity with which the LED glows, connected to port D5. The LED starts of with lowest intensity and then gradually increase the intensity until it reaches the maximum intensity and then decreases the intensity gradually until the LED is at the lowest intensity and the cycle continues.


What is PWM?


PWM stands for pulse width modulation. As the name suggests, there is a “pulse” and with “width”, we mess(“modulation”). The idea here is to change the width of the pulse, resulting in another pulse that meets our needs.

Why do we need it?


With digital systems like Arduino, Galileo/Edison, most often, we are dealing with two discrete voltage levels, 0 (GND, logical low) or 1 (logical high, represented by 5 V, 3.3V or 1.8V). PWM is one of the means of achieving (keep in mind the raw output is still digital. The pulse that is being generated still toggles between logical low and logical high) voltages between the two designated logical voltage levels. You could use PWMs to generate signals for driving things like speaker, buzzers etc.. PWMs are also used to control servo motors.

How does it work?


The basic principle behind PWM is that we turn on and off the voltage so fast across a device such that, due to the physical limitations of the device across which the PWM is applied, perceives the voltage as something between logic 0 (GND) and logic high (Vcc).

How do we make it work?


There are two parameters in the pulse that can be controlled to achieve the desired effect, period and duty cycle.
Period is the time interval after which a wave or signal would repeat itself. In a pure digital system, we can generate only two(binary) voltage levels, either logical 0 or logical 1. This kind of signal is called square wave.

[caption id="attachment_92" align="aligncenter" width="760"]776ed-square1 Square wave[/caption]

So going by the definition of period, the following shows how period is measured (the time interval after which pattern repeats)

ed894-square2

The other thing that can be controlled is the duty cycle. Duty cycle defines the amount of time the signal stays “on”. It is measured in terms of percentage. In the above images, the duty cycle is said to be 50% because the signal stays on for half the time in any given period. The key here is, if you increase the duty cycle, the output voltage perceived would be somewhere nearer to logical high (say 5V). Conversely, decreasing the duty cycle results the perceived voltage to tend to 0. Hence 100% duty cycle would mean that the signal stays on all the time, which means the output voltage is Vcc and 0% duty cycle means that the output voltage is 0V.

Hardware connections


Connect LED to port D5

93930-galileo_blog1_bb

e620c-img_20150328_105323

The program


https://gist.github.com/navin-bhaskar/e42e07806efb32300703

 

Firstly, PWM context is created using the function "mraa_pwm_init"
pwmPin = mraa_pwm_init(PWM_PIN);

The mraa_pwm_init() accepts the pin number at which PWM is to be enabled. Note that not all pins are PWM capable if you give wrong pin number then a 'NULL' value is returned.
Next, we set the period for the PWM pulse
mraa_pwm_period_us(pwmPin, 5000);   

The function mraa_pwm_period() accepts the PWM context as first argument and second argument should be period specified in micro seconds.
Then the PWM train is enabled at the selected pin
mraa_pwm_enable(pwmPin, 1);

Then we register a signal handler called "handler" that will be called whenever user presses "ctrl+c".
signal(SIGINT, handler);

This signal handler will clear a flag that will exit the while() loop within which we be chnaging the intensity of the LED.
Once out of the loop the PWM is disabled
mraa_pwm_enable(pwmPin, 0);

Within a while controlled by flag, called keep running, using the varible called 'delta' we increase or decrease the duty cycle depending on whether the duty cycle is at the maximum or minimum respectively. Using the function mraa_pwm_write() the duty cycle of the PWM pulse is modified
while (keepRunning)
{
if (duty >= 1)
{
duty = 1; // Intensity of LED at highest
delta = -0.05; // Need to decrease the duty cycle
}
else if (duty <= 0)
{
duty = 0; // Intensity of LED at the lowest
delta = +0.05; // Need to increase the duty cycle
}
mraa_pwm_write(pwmPin, duty);
/* Wait for some time */
usleep(50000);

duty = duty + delta;
}

Downloading, compiling and running it


When on Galileo/Edison's Linux console, download the file from git hub using 'wget'
wget https://raw.githubusercontent.com/navin-bhaskar/C-CPP-on-Intel-Edison-Galileo/master/part3-pwm/pwm.c 

Compilation command:
gcc -o pwm pwm.c -lmraa

Run the application with following command:
./pwm

To exit the application, hit "ctrl+c"

No comments:

Post a Comment