PWM in microcontrollers

What is PWM? Why do we need it?

Well those of you who know about principles of communication PWM stands for pulse width modulation. Now modulation refers to change in output signal in proportion to the input signal. Now in communication systems in order to transmit data over antenna  we modulate the signal and translate it to a higher frequency. But how does PWM help in microcontrollers? Lets consider an LED which is connected to the port pin of your microcontroller. Suppose the high logic level corresponds to 3 Volts and low logic level corresponds to 0 Volt. So when you make the port pin ON the LED will get 3Volts. But suppose the LED is too bright for your application you want to change the brightness somehow. One way is to use a potentiometer to vary the voltage. But that would require an external hardware as well as manpower(you have to manually adjust the pot value). Suppose that you want to use the software and the timer hardware inbuilt in your microcontroller to change this voltage, then what would you do? The answer my friend is PWM. We give pules of varying duty cycle at the output of port pin. This in turn will give us varying average DC values.

How varying voltage is obtained using PWM?

261120131291

Thus we can vary the duty cycle and in turn vary the dc voltage available at the port pin. When we vary the duty cycle we are in turn varying the pulse width and doing pulse width modulation. This PWM can be used to vary the speed of DC motors without using a DAC(if you don’t want precise speed control you can use this.) Now about the frequency of pulses. The time delay should be small enough that there are no jerks in the motor. One other application is dimming effect in LED’s. So if you want to make LED ON in an expensive way(I’ll tell expensive why very soon) i.e by making a subtle transition from the OFF state to ON state you use PWM. Just change the duty cycle of the pulses gradually from 0 to 100%. This will give you the elegant transition. Now coming to the expensive part. Suppose you own a car and there is this interior light system which uses a proximity sensor or any other sensor to detect your presence and stars the lights. What would look more elegant to you the lights abruptly turning ON or the slow and smooth transition? Well I would like the cool effect. Now this will raise the cost of that system drastically. So these are two applications of this PWM concept.

Persistence of vision and dimming effect

Well you might know about the persistence of vision concept. If the change is taking place in less than tenth of a second then human eye is unable to distinguish the change. This concept is used in motion pictures. Now suppose your PWM frequency is 1Hz i.e 1 cycle per second. You will clearly see the LED’s turning on and OFF. So the trick is to make the LED’s toggle at a rate or frequency that gives the human eyes the illusion that LED is  continuously ON . So that is the small part that one needs to take care while using PWM for the dimming effect. But lower the frequency lower the power dissipated, so use a frequency that is just enough to make the LED’s not seem flickering.

Timer A and PWM

Well now we have a background knowledge of PWM, so let’s learn how to achieve PWM using Timer A of msp430. I had covered how to use Timer A in up mode. So we’ll learn how to obtain PWM in up mode and most importantly get the output on a port pin and know which pin it is.

Well for Timer A initializing please refer my earlier post. Now we’ll focus on OUT modes.

out_modes

Well the description given is clear enough. But still one example will aid to the understanding of the modes.

example_out_mode_in_up_mode

The Output modes are explained in terms of Timer A up mode. We’ll be using the TA0CCR0 and TA0CCR1 register for this particular experiment. Since we are using TA0CCR1 we have to see the output at the OUT1 of Timer A0. Now since this is a special output, we have to select the port special function mode. This is given in the data sheet.

port_functions

Look at the P1.2 functions. We are interested in TA0.1. So we need to make the port pin as output and then select the function 2 i.e set the P1SEL BIT2. With that we cover the PWM and its generation.

Code

/*
* main.c
* Created on    : 26-Nov-2013 1:52:12 AM
* Author        : Manpreet Singh Minhas
* Website       : https://learningmsp430.wordpress.com
*/

// Aim : To create dimming effect using PWM.

#include "msp430g2553.h";
void main(void) {
WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

P1DIR |= BIT2;               // Initialize port for Output signal
P1SEL |= BIT2;
P1SEL2 &= ~BIT2;
TA0CCR0 = 0xFF;              // Give the time delay small enough to avoid visible flickering
TA0CCR1 = 0xFF;              // Give initial duty cycle 0
TA0CCTL1 = OUTMOD_2;
TA0CTL |= TASSEL_1|ID_0|MC_1;
int i;
int j;
for(;;)
{
for(j=0;j<0xFE;j++){
for(i =0;i<3000;i++){}
--TA0CCR1;                   // Increase the duty cycle slowly
}
for(j=0;j<0xFE;j++)

{
for(i =0;i<3000;i++){}
++TA0CCR1;                   // Decrease the duty cycle slowly
}
TA0CCR1=0xFF; // Give initial count again
}
}

Alternate which involves LPM and interrupt

/*
* main.c
* Created on     : 27-Nov-2013 3:52:12 PM
* Author         : Manpreet Singh Minhas
* Website        : https://learningmsp430.wordpress.com
*/
#include <msp430g2553.h>
int i=1;
void main(void) {
WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

P1OUT = BIT0;
P1DIR |= BIT0|BIT6|BIT2;
P1SEL |= BIT2;
P1SEL2 &= ~BIT2;
TA0CCR0 = 0x7FF;
TA0CCR1 = 0x7FF;
TA0CCTL1 = OUTMOD_2;
TA0CTL |= TASSEL_2|ID_0|MC_1|TAIE;
_BIS_SR(LPM0_bits|GIE);
}

#pragma vector=TIMER0_A1_VECTOR
__interrupt void TimerA(void)
{
switch(i){
case 1:
--TA0CCR1;
if(TA0CCR1==0)
{
i=2;
}
break;
case 2:
++TA0CCR1;
if(TA0CCR1==0x7FF){i=1;TA0CCR1 = 0x7FF;}
break;
}
P1OUT ^= BIT0|BIT6;
TA0CTL &= ~TAIFG;

}

Alternate version

/*
* main.c
* Created on     : 26-Nov-2013 1:52:12 AM
* Author         : Manpreet Singh Minhas
* Website        : https://learningmsp430.wordpress.com
* Aim            : Well this is nothing but the same program written differently.
*                       In this the dimming effect will take place once when you push
*                       the button connected to P1.1.
*/
#include <msp430g2553.h>
int i;
int j;
void main(void) {
WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

P1OUT = BIT0;
P1DIR |= BIT0|BIT6|BIT2;
P1IE |= BIT1;
P1DIR &= ~BIT1;
P1REN |= BIT1;
P1OUT |= BIT1;
P1IES |= BIT1;
P1SEL |= BIT2;
P1SEL2 &= ~BIT2;
TA0CCR0 = 0xFF;
TA0CCR1 = 0xFF;
TA0CCTL1 = OUTMOD_2;
//TA0CTL |= TASSEL_2|ID_0|MC_1|TAIE;
TA0CTL |= TASSEL_2|ID_0|MC_1;
_BIS_SR(LPM0_bits|GIE);
}
#pragma vector=PORT1_VECTOR
__interrupt void Port1(void){
P1OUT ^= BIT0|BIT6;
for(j=0;j<0xFE;j++){
for(i =0;i<3000;i++){}

--TA0CCR1;
}
for(j=0;j<0xFE;j++){
for(i =0;i<3000;i++){}
++TA0CCR1;
}
TA0CCR1=0xFF;
P1IFG &= ~BIT1;
}

Effect Video

You can see the effect in this video.

Interrupt concept and Low Power Modes (LPM)

Interrupts

I had  written about hardware interrupts earlier. Now I’ll write about interrupts in general. How to write program to enable interrupts and handle those. Basically there are two types of interrupts.

  • Hardware Interrupts
  • Software Interrupts

As the name suggests hardware interrupts are given on the pins of the controller. An example of this can be found in by blog post.

Software interrupts on the other hand are made by using software. And these are vectored interrupts i.e. the program counter is loaded with the contents of vector address of the interrupt that occurred. In fact all interrupts are vectored. All peripherals can generate an interrupt specific to their operation.

I’ll be taking the example of TimerA interrupt . But lets see a little theory about how to handle interrupts.

First I’ll tell you what is maskable and non-maskable interrupt.  Maskable interrupts can be disabled using software and non-maskable interrupt cannot be disabled. RST is a non-maskable interrupt. Now masking is done to avoid accidental triggering of the interrupt which can distort the program flow.

All the maskable interrupts have to be enabled. This is done by setting the GIE(General Interrupt Enable) bit of status register. So if you include the msp430.h file you can use the GIE macro defined in the header file and OR(bitwise) it with status register(SR), to enable the interrupts by setting that bit.

Now finally let’s see what happens when an interrupt occurs.

interrupt_acceptance 

So when an interrupt occurs the PC and SR contents are pushed onto the stack after the current instruction is executed. This is known as context saving. Depending on priority the interrupt with highest priority is processed first. Thus the PC is loaded with the contents of the vector address and context switching takes place.

returning_from_interrupts

The image above shows how to return from an Interrupt Sub Routine (ISR). An ISR is nothing but the code you write for handling the interrupt. The address of this ISR is stored at the vector address of the interrupt you want to handle.

One has to use “RETI” instruction to return to the main program. What RETI does is it pops the PC and SR contents back from the stack. Thus original state of program is restored.

Interrupt Vector Addresses

Now these are device specific. So one has to refer datasheet of the required microcontroller for this. Since I’ll be using msp430g2553 for this I’ll post the vector address table for the device.

vector_address_table

That is that.

Low Power Modes(LPM) of Operating modes of msp430

Now-a-days its all about reducing the power consumption. And Texas Instruments msp430 is a low power microcontroller. That means that there must be low power modes. Those are nothing but LPM. These are selected by setting or resetting the bits of SR. These modes are well explained in the user guide. I’ll post the page concerning these modes.

modes

All the SCG1,SCG0,OSCOFF,CPUOFF are bits of the status register(SR). You can use the bits defined in the header file for setting these bits. I’ll explain more about this after the program.

Now when you enter a LPM. You can come out of it when there is an interrupt. Now we know that PC and SR are pushed onto the stack. So if you want to come out of the LPM on exit from ISR you need to change the SR contents pushed onto the stack. The process is given in the user guide.

entering_exit

The bic instruction is used to clear the corresponding bits of SR that are used for controlling LPM.

In LPM basically we shut the oscillators which consume the maximum power. Thus depending on your need you can shut down the ACLK,SMCLK,MCLK and DCO.

Program

;Name             : Manpreet Singh Minhas
;Date                 : 22 Nov 2013
;Website        : https://learningmsp430.wordpress.com/
;Software        : IAR Embedded Workbench

Aim                  : To blink an LED by using TimerA interrupt and use msp430 in LPM.
#include “msp430g2553.h”     ; Include the header file
ORG 0FFFEH                                                                    ; Power On Reset Vector address
        DW MAIN                                                                    ; Here MAIN is nothing but a macro for 0C000H
                                                                                             ; memory location. You might as well write
                                                                                             ; 0C000h. We try to make the code as reader
                                                                                             ; friendly as possible, that is why MAIN macro.

                               
ORG 0C000H                                                                 ; Starting address of FLASH MEMORY in
                                                                                          ; msp430g2553 where the program will be burnt.
MAIN:        MOV.W #WDTPW|WDTHOLD,&WDTCTL  ; Stop watchdog timer
                  MOV.W #03FFH,SP                                         ; Initialize stack pointer to top of
                  MOV.B #BIT2,&P1DIR                                             ; RAM. You’ll have to use device’s
                  MOV.W #08000H,&TA0CCR0                               ; datasheet for finding this address.
                  BIC.B #BIT2,&P1OUT                                            
                  MOV.W #TASSEL_1|ID_0|MC_1|TAIE,&TA0CTL ; Initialize timer
UP:           MOV.W #LPM3|GIE,SR                                             ; Enable interrupts and enter LPM3
                 JMP UP
TMR_ISR:    XOR.B #BIT2,&P1OUT                                         ; Toggle LED
                      BIC.W #TAIFG,&TA0CTL                                      ; Clear the interrupt flag bit
                      RETI
       
ORG 0FFF0H
        DW TMR_ISR
END

The above code will make led connected P1.2 to blink after 1 sec delay. You can change the BIT2 to BIT0 or BIT6 if you don’t want to use an external LED. I’ve used TimerA in up mode. And I’m using ACLK for this part. I’ve connected a 32kHz crystal there.  So you need to connect it there by soldering. Then it’s given in the user manual that when the count goes from TA0CCR0 value to 0, the TAIFG flag is set. I’ve enabled the interrupts in SR by setting the GIE bit, also you need to enable it in the peripheral’s control register. I’ve enabled the TimerA interrupt by setting TAIE bit of TA0CTL. Now it’s vital to clear the interrupt flag of the interrupt that you are handling. In this case the TAIFG flag in TA0CTL register. So that we can acknowledge the next interrupt. Its easy to forget this so just beware. And regarding the LPM3 macro that I’ve used it just sets the corresponding bits of SR. The definition is:

#define LPM3                (SCG1+SCG0+CPUOFF)

So either you can write LPM3 or the corresponding SR bits. And instead of using mov instruction you can use bis instruction as well.

<

p>If any doubts feel free to ask. Thank you for reading this. Hope this was useful and informative.

Blinking LED(hello world! of micro controllers)

This post is about the blinking led’s. Those of you who know c/c++/java or any programming language for that matter would have definitely written the first program as hello world. In case of micro controllers blinking led’s is the hello world sort of thing.

Theory:

On launchpad there are two surface mount led’s (smd led’s), they differ from normal led’s in the sense that there are tiny as compared to the normal ones. We generally use current limiting resistors while using led’s of any sort, but Texas has taken care of that for us already by connecting these on board led’s with current limiting smd resistors. We make use of port 1 pins 0 and 6 to which these led’s are connected. When the port is made high the led glows and when its made low the led turns OFF. Thus we first configure the P1.0 and P1.6 pins as output pins using the direction register. Then we toggle the output register after some delay so that the change is registered by human eyes(persistence of vision remember??).

Code:

//Author: Manpreet Singh Minhas
//Date : 2/10/2013
//learningmsp430.wordpress.com
#include <msp430g2211.h>// include the header file for msp430g2211
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;                                                                          //stop watchdog timer
P1DIR|=BIT0+BIT6;                                                                                                    //set the port 1 pin 0 and pin 6 as output you can do this by using hex                                                                                                                                              *command word as well i.e 01000001 or 0x041 or 41h
P1OUT|=BIT0; // make port1 pin0 i.e P1.0 high
int i=0;
for(;;){                                                                                                                               // infinite loop so that the action is repeated indefinitely

P1OUT ^= (BIT0+BIT6);                                                                                                 // toggle using ex-or with 1 ( refer truth table of ex-or operation.)
for(i=0;i<20000;i++){

// some delay for the human eye to observe the change
}

}
}

Video:

*: Those of you who don’t know what is a command word. Command word is 8bit or 16 bit data that is given to the special function registers to configure the device how we want. In this case it is the P1DIR and P1OUT registers. Thus these two are command word registers and the data we send is command word. In msp430g2xx1 making P1DIR.x high/1 makes the port pin as output and low/0 makes it input. P1OUT makes the port high if the bit is set and makes it low if the bit is reset.

Led patterns using msp430g2231

led-patterns
This application is generation of led patterns using msp430g2231.
Components Required:
msp430g2231 (1)
1k resistors (8)
preset 4.7k (1)
rgb led 2pin (8)
berg wires (8/9)
toggle switch(1)
705009_RB_00_FB.EPS_1000

Theory:
In this application we utilize all 8 ports of the micro-controller. Each port is connected to one of the led’s via current limiting resistors. Now all we need to do is set all the ports as output and then change the patterns by varying the port pins that are high/low. We are using code composer studio for this. The program is written in c. We can either use the launchpad directly for connections via breadboard or we can make a PCB for it. The advantage of PCB is that you can carry is with you without having to take the launchpad as well your laptop with you. Or you can build a shield/booster pack of led’s like in the image shown below.

021020131203

Code:
#include
main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR |= 0XFF; // set all the ports as output ports
int x = 0X01;
long i=0;
int j=1;
int k=0;
int l=0;
for(;;)
{

for(k=1;k<=5;k++){
x=0x01;
for(j=1;j<=8;j++){

P1OUT = x;
x*=2;
for(i=0;i<=10000;i++)
{
}
}
}
for(k=1;k<=5;k++){
x=0x80;
for(j=1;j<=8;j++){

P1OUT = x;
x/=2;
for(i=0;i<=10000;i++)
{
}
}
}

for(k=1;k<=5;k++){

P1OUT=0xAA;
for(l=0;l<=1;l++){
for(i=0;i<=64000;i++)
{}}
P1OUT=0x55;
for(l=0;l<=1;l++){
for(i=0;i<=64000;i++)
{}}
}

for(k=1;k<=5;k++){

P1OUT=0x18;

for(i=0;i<=20000;i++)
{}
P1OUT=0x24;

for(i=0;i<=20000;i++)
{}
P1OUT=0x42;

for(i=0;i<=20000;i++)
{}
P1OUT=0x81;

for(i=0;i<=20000;i++)
{}

}
for(k=1;k<=5;k++){

P1OUT=0x81;

for(i=0;i<=20000;i++)
{}
P1OUT=0x42;

for(i=0;i<=20000;i++)
{}
P1OUT=0x24;

for(i=0;i<=20000;i++)
{}
P1OUT=0x18;

for(i=0;i<=20000;i++)
{}

}

}
}

My instructable link:

http://www.instructables.com/id/LED-patterns-using-msp430-launchpad/

YouTube Video:
http://www.youtube.com/watch?v=g9NRDXL0vOk

Note: If anyone wants the PCB file, just let me know.