Gesture control for PowerPoint presentation

Basic idea of the project

The intention of this tutorial is to learn how to control computer keyboard and mouse events using your micro-controller. For demonstration I have chosen to name the project as gesture control for PowerPoint presentation. At the end of this tutorial you will be able to control the slides using your gestures. Now in order to control the operating system you need a language like python, java, c++ etc. I find python affable and powerful so I’ll be using that for coding. You can use any language you want but the logic and algorithm will remain the same, only the syntax will differ. I won’t be teaching you python in this post that is beyond the scope of this post. If you want to learn the language there is plethora of content available online. You just need a net connection and off you go.
P.S. : If you like the posts do like and share them with others.

Python

Python is an easy to learn high level programming language. It is a beautiful and a very powerful language. The packages that are available make it kind of limitless. Some of the places where python is used are mentioned below.

  • Google makes extensive use of Python in its web search systems.
  • The popular YouTube video sharing service is largely written in Python.
  • The Dropbox storage service codes both its server and desktop client software primarily in Python.
  • The Raspberry Pi single-board computer promotes Python as its educational language.
  • NASA, Los Alamos, Fermilab, JPL, and others use Python for scientific programming tasks.

So we know that most of the big shots use python. Now they use it for a reason and the reason being that its simply an awesome language. If you want to start learning programming you ought to start with python. Here are a list of sites and books that you may use for learning python.

  1. https://www.python.org/about/gettingstarted/ (This is the official page where you can learn how to install the IDE and get started.)
  2. Learning Python, 5th Edition (This is a good book if you are new to programming and otherwise as well.)
  3. http://www.learnpython.org/
  4. http://www.tutorialspoint.com/python/

Once you get the hang of it then you can directly use the documentations for learning how to use the packages.

pySerial and PyUserInput

We will be requiring these modules in our project. The names are quite self explanatory the former is for serial communication while the latter is for the mouse and keyboard events. The links to these modules are:

Well download these and install them. I recommend you to use 32bit python 2.7 version modules as well as the language. Because most of the modules are available for 2.7 version.

Components and Software requirements

  • A microcontroller board with UART capability e.g. MSP430G2 Launchpad, Arduino Uno board etc.
  • An accelerometer e.g. ADXL335 etc..
  • Python 2.7 , pySerial & PyUserInput modules

Connections

connections

I have used fritzing for making this. Here is the link to their home page.  http://fritzing.org/home/

Logic

We will calibrate the accelerometer and take readings for left and right position. Use the serial monitor for this. Read my tutorial titled Capacitive Accelerometer Interfacing if you don’t know what I am talking about. Next once you have those digital values you need to make the program for slide control. We know that left arrow and right arrow keys are used for navigation purpose. So in our python script the if statements will contain code for left arrow button press and right arrow button press. Note that you are reading the values that the controller is sending serially using python and taking decisions based on that value.

Energia Code

int x_pin = A0;
void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(x_pin,INPUT);
  analogReference(INTERNAL2V5);
}

void loop()
{
  // put your main code here, to run repeatedly:
  int x = analogRead(x_pin);
  Serial.println(x);
  delay(500);
}

Python Script

__author__ = 'MANPREET'
'''
This is a file for controlling keyboard events.
'''
from pykeyboard import PyKeyboard
import serial
import time

comPort = raw_input("Please enter the COM port number")
baudRate = raw_input("Please enter the baud rate")
myserial = serial.Serial(comPort, baudRate)
k = PyKeyboard()
TRUE = 1;
try:
    while (TRUE):
        if (myserial.inWaiting()):
            mydata = myserial.readline()
            x = int(mydata)
            print(x)
            if x > 650:
                k.tap_key(k.left_key)
                print("left")
                time.sleep(1)
            if x < 550:
                k.tap_key(k.right_key)
                print("right")
                time.sleep(1)
except KeyboardInterrupt:
    print("stop")

Code Explanation

The Energia code is pretty straightforward but still just to cover that as well. We have declared A0 i.e. P1.0 pin as input and changed the ADC reference voltage to 2.5V in line 7. Next part is just getting the ADC reading and sending it serially.

The python code demands some explanation. So lets begin understanding the code .

from pykeyboard import PyKeyboard
import serial
import time

This code will import three modules PyKeyboard, serial and time. For the pykeyboard we have imported the constructor. Then you have made one object k using the same.

comPort = raw_input("Please enter the COM port number")
baudRate = raw_input("Please enter the baud rate")
myserial = serial.Serial(comPort, baudRate)
k = PyKeyboard()

myserial is an object of the serial module that you have imported. You will use this to access its functions. The raw_input() is for taking the com port and baud rate values from the user. Example COM11 and 9600.

TRUE = 1;
try:
    while (TRUE):
        if (myserial.inWaiting()):
            mydata = myserial.readline()
            x = int(mydata)
            print(x)
            if x > 650:
                k.tap_key(k.left_key)
                print("left")
                time.sleep(1)
            if x < 550:
                k.tap_key(k.right_key)
                print("right")
                time.sleep(1)
except KeyboardInterrupt:
    print("stop")

Well this is an infinite loop and you are checking this block for keyboard interrupt i.e. ctrl+c . This is done so that you can come out of the program properly without having to kill the program. Next we are checking if there is data in the serial buffer. If yes then we are storing it in mydata variable. Convert it into integer and store it as some variable say x. Next step is easy write two if statements and include the code and condition for left arrow button press and right arrow button press. For more details of the PyKeyboard module visit : https://pypi.python.org/pypi/PyUserInput/0.1.9
For running the python script install python 2.7. Copy paste the python script code into notepad and save it as gersturecontrol.py(or any name for that matter) Then follow these steps.

  1. Open command prompt(Press windows+r, then type cmd and press enter.)
  2. opening_command_prompt

  3. Change the directory to the one containing your python script i.e. the .py file. Use cd for that.
  4. file_location

  5. Use python gesturecontrol.py for running your code
  6. running the program

  7. For stopping the code press ctrl+c

Thank you for reading the post and hope that it was helpful.If you like the post do share it with others and spread the knowledge.

Capacitive Accelerometer Interfacing

Well in this post I’ll be telling briefly what is an accelerometer and how to interface it with a microcontroller. To be honest I woke up in the middle of the night and couldn’t go back to sleep, so I decided to write this post which I was planning on writing for some time now.

Accelerometer

It is basically a device which is used for measuring acceleration or change in motion. You use one more often than you know. There is an inbuilt accelerometer in your cellular mobile phones and tablets. So now you know what is used for detecting the tilts in your phone. Next time you play temple run or similar game you would know that all this fun is possible due to a technology called accelerometer and other stuff. Then modern laptop hard disks have accelerometers to detect fall. If fall is detected the writing head in retraced so that the disk is not damages and there are no scratches. There are numerous other applications and examples. I just gave food for thought you can explore the rest on your own.

Types of Accelerometer

Well as you may have already guessed there are various types of accelerometers.

  • Capacitive Accelerometer
  • Magneto-resistive Accelerometer
  • Piezo-electric Accelerometer

There are various other types these three being examples.This is a video one of my instructors showed me. The guy explains the working and construction quite well.

This is an article having good information about accelerometers

http://www.engineersgarage.com/articles/accelerometer?page=1

Data from accelerometers

Now that you know how accelerometers work. Let’s come to the topic at hand i.e. using one with your microcontroller.

Well there are different types of accelerometers depending on the type and method of obtaining data. While the data acquisition may be different but processing part is same once you get the reading. So the data may be available as an analog signal or may be it may be available inside the accelerometer in a register which you need to access via a protocol like SPI etc..

ADXL 335

So I’ll be talking about this accelerometer. You can look at the datasheet before deciding to use it.

So this accelerometer gives the output as three analog signals. There are three pins x,y,z for the three axes. Then there is Vcc and GND.

For actually using this signals you need to convert them into digital form. For this you use the inbuilt 12bit ADC that is available in msp430g2553.(If your controller does not have an inbuilt ADC, which won’t be the case, you can use an external ADC or if your application requires faster conversion and better precision and stability then you can use external ADC.) So once you have the data in digital form, next step would be calibration of the accelerometer.

Calibration

Now you have the data in digital form but what to do with it and how to see it? The answer is you send the digital reading serially and observe it on a serial monitor. So you make variables and store the digital reading in those and view the numbers on screen. Now you will make a table for these variables and decide the limits. Suppose you want to detect forward tilt, you can note what are the range of values that the accelerometer gives for the gesture and the using a simple if statement write whatever you want your application to do on a forward tilt.

Position Digital Range of X Digital Range of Y
Forward N.A <658
Backward N.A >705
Left >497 N.A
Right <460 N.A
Stop 470 to 485 695 to 705

 

The above code is an example of finding the ranges. You can then use basic if else for this. If you want a video showing the calibration process do tell me.

Code for gesture controlled bot

void setup()
{
  pinMode(P2_0,OUTPUT);
  pinMode(P2_1,OUTPUT);
  pinMode(P2_2,OUTPUT);
  pinMode(P2_3,OUTPUT);
  pinMode(A0,INPUT);//X
  pinMode(A3,INPUT);//Y
  pinMode(P1_4,INPUT);
  //pinMode(A2,INPUT);//Z
  Serial.begin(9600);
  Serial.println("Start");
}
void loop()
{
  int x = analogRead(A0);
  int y = analogRead(A3);
  int m = digitalRead(P1_4);
  //Serial.print(x);
  //Serial.print(','); //use these lines for calliberation
  //Serial.println(y);
   if(y>520)
  {
  digitalWrite(P2_0,HIGH);
  digitalWrite(P2_1,LOW);
  digitalWrite(P2_2,HIGH);
  digitalWrite(P2_3,LOW);
  Serial.println("BACKWARD");
  //delay(100);
  }
  if(y<460)
  {
  digitalWrite(P2_0,LOW);
  digitalWrite(P2_1,HIGH);
  digitalWrite(P2_2,LOW);
  digitalWrite(P2_3,HIGH);
  Serial.println("FORWARD");
  //delay(100);
  }
  if(x>445)
  {
  digitalWrite(P2_0,LOW);
  digitalWrite(P2_1,LOW);
  digitalWrite(P2_2,LOW);
  digitalWrite(P2_3,HIGH);
  Serial.println("LEFT");
  //delay(100);
  }
  if(x<430)
  {
  digitalWrite(P2_0,LOW);
  digitalWrite(P2_1,HIGH);
  digitalWrite(P2_2,LOW);
  digitalWrite(P2_3,LOW);
  Serial.println("RIGHT");
 // delay(100);
  }
  if(x>430 && x< 445 && y>460 && y<500)
  {
  digitalWrite(P2_0,LOW);
  digitalWrite(P2_1,LOW);
  digitalWrite(P2_2,LOW);
  digitalWrite(P2_3,LOW);
  Serial.println("STOP");
  //delay(100);
  }  
}

(If you would like the embedded c code email me.)

P.S.

If you like my articles do like them. Well just want to say a little appreciation goes a long way. Thank you for reading the post.

Line Follower using msp430g2 launchpad

In this post I’ll be writing about line follower bot. This post covers how a light sensor works and how to make your own light sensor. All criticisms are welcome.

Introduction

A line follower bot is as the name suggests a bot that follows a line. Now this line can be either a dark one on a white surface or a white line on a black surface. So once you switch the bot ON it will keep on following the path that you create using the line.

Sensors

Theory

For this we’ll be needing a light sensor which may be based on visible light or infrared. The concept used is that different colours absorb different wavelengths of light and reflect different wavelengths. Have you ever wondered why a book that appears red to you is that coloured? The physics behind is that a red material will absorb all other colours of white light and reflect the red colour. With that being said it will make sense that black colour absorbs all wavelengths or colours while white reflects all colours. We will use this concept to make our sensors.

Components

We can make the sensor using the following combinations.

  • LED and LDR
  • IR LED and IR diode

What remains common in both the combinations is the use of transistor as a switch. We use transistor as a switch to make the sensor give us digital output i.e. high and low.

The theory on transistor as a switch can be found in the following literatures.

I’ve made one circuit taking reference from Boylestad and the site whose link I’ve posted above. This circuit will give you ~2V when there is no IR light falling on the IR receiver and will give you ~0V when IR light falls on the receiver. So whenever there is any obstacle near the IR led we’ll get logic 0 and whenever there is no obstacle near the IR led we will get logic 1. Note that you can get ready made IR sensors for this application. I’ve given this basic introduction so that those of you who want to know how to make your own sensor get some guidance.

Circuit

100120141333

Well with that being taken care let’s develop the logic for our line follower.

Line follower logic and concept

Well I’ll be using a sensor that I got after I attended an internship on embedded c and advanced robotics. This sensor gives logic 0 when there is no IR light reflected to it and logic 1 when there is IR light reflection. To keep things simple our track background colour is white and the path is black. So when the sensor is on white background it’ll reflect light and when it is on the path it wont reflect light. Now lets develop our logic. We’ll need two sensors in order for this line follower to work. When there is a straight path both the sensors will point on white surface thus giving logic 1. So when we have this condition satisfied we’ll send data 1010 to the motor driver port pins.(I’ve connected the motors in such a way that 10 corresponds to forward movement and 01 corresponds to backward movement. This is done so that there is no confusion.) Now lets imagine there is a smooth left turn on the path. The left sensor will go on the black path first while the right sensor will be on the white background. Thus l=0 and r=1.(‘l’ corresponds to the left sensor data and ‘r’ corresponds to right sensor data.) To stay on track we need to make a left turn. This can be done in two ways. First is to make the left wheel stop so that the right wheel rotates and the bot takes a left turn. Second is to make left wheel rotate in backward direction and the right wheel move in forward direction. On similar grounds when there is a smooth right turn the bot needs to turn right. This can be achieved by same two methods just the motor data is interchanged. So this is the concept behind a line follower.

Motor driver

A microcontroller can supply limited current, so in order to drive any heavy load requiring high voltage and current we need to connect a motor driver IC between the microcontroller and the load which in this case is a motor. So I’ll be using the driver IC L239D. This IC has four H bridges that will allow us to control two motors using the same IC. The connections are pretty simple. You just need to see the data sheet for the connections. If you find any difficulty just Google how to use that IC you’ll get required information. And you can comment here posting your doubts and I’ll revert as soon as possible.

Code in Embedded C

/*
 *  line_follower.c
 *  Created on	: 10-Jan-2014 4:19:47 PM
 *  Author	  	: Manpreet Singh Minhas
 *  Website		: https://learningmsp430.wordpress.com/
 */

#include <msp430g2553.h>
// P1IN&BIT0 I've connected the left sensor to P1.0
// P1IN&BIT1 right sensor to P1.1
void main()
{
	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
	P1DIR |= BIT2|BIT3|BIT4|BIT5;// Make P1.2 P1.3 P1.4 P1.5 as output
	P1DIR &= ~BIT0|~BIT1;	// Make P1.0 P1.1 as input
	P1OUT =0;
	for(;;)
	{
		if((P1IN&0x03) == 0x03)
		{
			P1OUT |= BIT2|BIT4;
			P1OUT &= ~(BIT3|BIT5);
		}
		if((P1IN&0x03) == 0x02)
		{
			P1OUT |= BIT4;
			P1OUT &= ~(BIT2|BIT3|BIT5);
		}
		if((P1IN&0x03) ==0x01)
		{
			P1OUT |= BIT2;
			P1OUT &= ~(BIT3|BIT5|BIT4 );
		}
	}

}

Code in Arduino

/*
 *  line_follower.ino
 *  Created on	: 10-Jan-2014 4:19:47 PM
 *  Author	  	: Manpreet Singh Minhas
 *  Website		: https://learningmsp430.wordpress.com/
 */
void setup()
{

  pinMode(2,INPUT);
  pinMode(3,INPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);

}
void loop()
{
  int l = digitalRead(2);
  int r = digitalRead(3);
  if(l==HIGH && r==HIGH)
  {
        digitalWrite(4,HIGH);
        digitalWrite(5,LOW); // 12 and 13 for left motor
        digitalWrite(6,HIGH);// 10 and 11 for right motor
        digitalWrite(7,LOW );
  }

    if(l==LOW && r==HIGH)
  {
        digitalWrite(4,HIGH);
        digitalWrite(5,LOW);
        digitalWrite(6,LOW);  // 
        digitalWrite(7,LOW );
  }

    if(l==HIGH && r==LOW)
  {
        digitalWrite(4,LOW);
        digitalWrite(5,LOW);
        digitalWrite(6,HIGH);
        digitalWrite(7,LOW );
  }
}

I’ve written the code in both embedded C and arduino. You will energia for burning the ‘.ino’ code.

Circuit Diagram

line_follower_circuit

Video

Please visit http://robokart.com/ for the sensors,chassis and other robotics related parts(for people living in India)

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 &amp;= ~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&lt;0xFE;j++){
for(i =0;i&lt;3000;i++){}
--TA0CCR1;                   // Increase the duty cycle slowly
}
for(j=0;j&lt;0xFE;j++)

{
for(i =0;i&lt;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 &lt;msp430g2553.h&gt;
int i=1;
void main(void) {
WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

P1OUT = BIT0;
P1DIR |= BIT0|BIT6|BIT2;
P1SEL |= BIT2;
P1SEL2 &amp;= ~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 &amp;= ~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 &lt;msp430g2553.h&gt;
int i;
int j;
void main(void) {
WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

P1OUT = BIT0;
P1DIR |= BIT0|BIT6|BIT2;
P1IE |= BIT1;
P1DIR &amp;= ~BIT1;
P1REN |= BIT1;
P1OUT |= BIT1;
P1IES |= BIT1;
P1SEL |= BIT2;
P1SEL2 &amp;= ~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&lt;0xFE;j++){
for(i =0;i&lt;3000;i++){}

--TA0CCR1;
}
for(j=0;j&lt;0xFE;j++){
for(i =0;i&lt;3000;i++){}
++TA0CCR1;
}
TA0CCR1=0xFF;
P1IFG &amp;= ~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.