Monday, 4 January 2021

Ultrasonic Sensor HCSR04 with MSP430

The explanation for this project can be found here: Project Link

Subscribe to the channel for more such content.


Below is the code:

#include "msp430.h"


#define TRIG_PIN BIT1 // Corresponds to P2.1

#define ECHO_PIN BIT1 // Corresponds to P1.1


//#define TXD BIT2 // TXD on P1.2


volatile unsigned long start_time;

volatile unsigned long end_time;

volatile unsigned long delta_time;

volatile unsigned long distance;


void wait_ms(unsigned int ms)

{

unsigned int i;

for (i = 0; i <= ms; i++)

{

__delay_cycles(1000);

}

}


#if defined(__TI_COMPILER_VERSION__)

#pragma vector = TIMER0_A0_VECTOR

__interrupt void ta1_isr(void)

#else

void __attribute__((interrupt(TIMER0_A0_VECTOR))) ta1_isr(void)

#endif

{

switch (TAIV)

{

//Timer overflow

case 10:

break;

//Otherwise Capture Interrupt

default:

// Read the CCI bit (ECHO signal) in CCTL0

// If ECHO is HIGH then start counting (rising edge)

if (CCTL0 & CCI)

{

start_time = CCR0;

} // If ECHO is LOW then stop counting (falling edge)

else

{

end_time = CCR0;

delta_time = end_time - start_time;

distance = (unsigned long)(delta_time / 0.00583090379);


//set a range

if (distance / 10000 >= 2.0 && distance / 10000 <= 10)

{

//turn on LED P1.0;

P1OUT |= BIT0;

}

else

P1OUT &= ~BIT0;

}

break;

}

TACTL &= ~CCIFG; // reset the interrupt flag

}



void reset_timer(void)

{

//Clear timer

TACTL |= TACLR;

}


void main(void)

{

// Stop Watch Dog Timer

WDTCTL = WDTPW + WDTHOLD;


// Set ECHO (P1.1) pin as INPUT

P1DIR &= ~ECHO_PIN;

// Set P1.1 as CCI0A (Capture Input signal).

P1SEL |= ECHO_PIN;

// Set TRIGGER (P2.1) pin as OUTPUT

P2DIR |= TRIG_PIN;

// Set TRIGGER (P2.1) pin to LOW

P2OUT &= ~TRIG_PIN;

P1DIR |= BIT0;

P1OUT &= ~BIT0;

//P1DIR |= BIT6;

/* Use internal calibrated 1MHz clock: */

BCSCTL1 = CALBC1_1MHZ; // Set range

DCOCTL = CALDCO_1MHZ;

BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO = 1MHz


// Stop timer before modifying the configuration

TACTL = MC_0;


CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;

// Select SMCLK with no divisions, continuous mode.

TACTL |= TASSEL_2 + MC_2 + ID_0;


// Global Interrupt Enable

__enable_interrupt();


while (1)

{

// send ultrasonic pulse

reset_timer();

// Enable TRIGGER

P2OUT |= TRIG_PIN;

// Send pulse for 10us

__delay_cycles(10);

// Disable TRIGGER

P2OUT &= ~TRIG_PIN;

// wait 500ms until next measurement

wait_ms(500);

}

}


Wednesday, 30 December 2020

Chevening Interview Prep Questions (few examples)


Below are the set of questions that you may want to consider during the interview prep session:

1. Why do you want to study in the UK?

2. Why did you choose this course/program?

3. What do you intend to do after the Chevening MSc program?

4. State some examples exhibiting your leadership skills.

5. How will this scholarship help you in the development of your home country?

6. What will you do if you don't get the scholarship?

7. What are your greatest achievements?

8. What are your strengths and weaknesses?

9. Why did you select these three universities?

10. Why is a particular uni your first preference?

11. Which leader (could be from your field) do you admire and why?

12. Why are you interested in Chevening Scholarship particularly (the main advantage is the network, think of other reasons as well)?

13. What are the other activities which you are interested in doing in the UK besides focussing on academics?

14. What changes would you like to bring about in your field in your home country?

15. Are there any challenges that you face during your time in the UK (eg. staying away from the family) and would you able to successfully complete the MSc. program?

16. State any examples showcasing your networking skills or do you have the networking skills and how will you use it to leverage the condition in your home country (in your field)?

17. Do you need an MSc. degree to bring about changes in your field of interest (in your home country)? Justify why an MSc. program a prerequisite for you.

18. Is your work experience in line with the field that you want to pursue your MSc. in?

19. Have you already got admission in any of the universities (it will be best if you have already got the admission)

20. Would you like to change the preferences of uni? (rearranging the order)

21. Do you have any questions?

Also, prepare the most commonly asked questions:

1. Tell us something about yourself (keep this answer brief and to the point)

2. Where do you see yourself in 5 to 10 years time?

3. Your strengths and weaknesses.




Sunday, 18 October 2020

CCS code - Graph utility (temperature monitoring)

Do check the youtube video on Graph Tool of CCS : 


Do SUBSCRIBE to my channel!

I have used this code for temperature monitoring: 


#include <msp430g2553.h>


int temp = 0;

int temp1 =0;

void main(void){

WDTCTL = WDTPW | WDTHOLD; //stop the watchdog timer



//Select 1.5 V, 64 clock cycles, enable ADC interrupt, Turn on the reference generator

ADC10CTL0 = SREF_1 + REFON + ADC10ON + ADC10SHT_3 + ADC10IE;


//Select input channel 10 and divide the clock frequency by 4

ADC10CTL1 = INCH_10 + ADC10DIV_3;


while(1){

//Enable and Start conversion

ADC10CTL0 |= ENC + ADC10SC;


//Enter low power mode

__bis_SR_register(LPM0_bits + GIE);


//fetch the temperature value from ADC10MEM register

temp1 = ADC10MEM;


//convert it into degree celsius

temp = ((temp1 * 27069L - 18169625L)>>16);


}

}


//ISR

#pragma vector = ADC10_VECTOR

__interrupt void adc_interrupt(void)


{

__bic_SR_register_on_exit(CPUOFF);

}


Sunday, 27 September 2020

MSP430 with a DC motor

The explanation for this project can be found here: Video explanation

Subscribe to the channel for more such content.

Below is the code:


#include <msp430g2553.h>

int count = 0;
void main()
{
WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer

P1DIR |= BIT6|BIT2;
P1SEL |= BIT6; //P1.6 TA0.1 output signal for DC motor
P1OUT &= ~(BIT2);  //P1.2 for DC motor 

P1DIR &= ~BIT3; //Button P1.3
P1REN |= BIT3;
P1OUT |= BIT3;
P1IE |= BIT3;
P1IES |= BIT3;
CCR0 = 1000-1;
CCTL1 = OUTMOD_7;

__enable_interrupt();
__low_power_mode_0();



}
#pragma vector=PORT1_VECTOR
__interrupt void P1_Func()
{
int i = 0;
count = count + 1;
switch (count)
{
case 1: CCR1 = 850-1;
TACTL = TASSEL_2 + MC_1;
break;
case 2: CCR1 = 250-1;
count = 0;
break;
}

while(i<500)
{
if((P1IN&BIT3))
i++;
else
i=0;
}
P1IFG &= ~BIT3;
}

Friday, 28 August 2020

MSP430 with RGB LED - Pulse Width Modulation (PWM)

This post is related to the Pulse width modulation using MSP430 launchpad and RGB LED. 

All the details for the implementation of this project are provided on My YouTube channel : https://www.youtube.com/watch?v=o-tf9ZC-rSQ

Do Subscribe to the channel to see more content related to embedded systems.


Below is the CCS code:

#include <msp430.h>

#define MAX_TIME (1000)
#define MAX_COUNT (50)
int rv = 750; //red
int gv = 0;   //green
int bv = 0;   //blue
int fac = 50;  //change by a factor of 50

int c = 0;
int d = 0;

inline void update_colors(void)
{
if(d<15) 
{
rv = rv - fac;
bv = bv + fac;
gv = 0;
d++;

TA1CCR2 = rv;
TA1CCR1 = bv;
TA0CCR1 = gv;
}

if(d>14 && d<30) 
{
rv = 0;
bv = bv - fac;
gv = gv + fac;

d++;

TA1CCR2 = rv;
TA1CCR1 = bv;
TA0CCR1 = gv;

}

if(d>29 && d<45) 
{
bv = 0;
rv = rv + fac;
gv = gv - fac;

d++;

TA1CCR2 = rv;
TA1CCR1 = bv;
TA0CCR1 = gv;
}

if(d==45) 

d=0;

}


int main()
{
WDTCTL = WDTPW + WDTHOLD;

P2DIR |= (BIT1 | BIT5);
P2SEL |= (BIT1 | BIT5);

TA1CCR0 = MAX_TIME;
TA1CCTL1 = OUTMOD_7;
TA1CCTL2 = OUTMOD_7;
TA1CCR1 = rv;
TA1CCR2 = bv;
//Start the timer 1
TA1CTL = TASSEL_2 | MC_1;


P1DIR |= BIT6;
P1SEL |= BIT6;
TA0CCR0 = MAX_TIME;
TA0CCTL1 = OUTMOD_7;
TA0CTL |= TAIE;
TA0CCR1 = gv;

//Start timer 0
TA0CTL |= TASSEL_2 | MC_1;

//Turn off CPU and interrupt enabled
_BIS_SR((LPM0_bits | GIE));

while(1) {}
return 0;
}

__attribute__((interrupt(TIMER0_A1_VECTOR)))
void tim0_a1_isr(void)
{
++c;
if(c >= MAX_COUNT)
{
update_colors();
c=0;
}
TA0CTL &= ~TAIFG;
}

Thursday, 16 July 2020

Pulse Width Modulation using MSP430 Timer (Launchpad)

Video based Tutorial for PWM generation using MSP430 is covered on my YouTube channel:

Please Subscribe to the Channel!

Code used for generation of PWM:

#include <msp430g2553.h>

void main(void)
{
 WDTCTL = WDTPW + WDTHOLD;  // Stop WDT
 P1DIR |= BIT6;             // P1.6 set for output
 P1SEL |= BIT6;             // select TA0.1 output signal
 CCR0 = 1000-1;             // PWM Time Period/ frequency (1 KHz)
 CCTL1 = OUTMOD_7;          // reset/set mode 7 for output signal
 CCR1 = 750-1;                // PWM Duty cycle is 75%
 TACTL = TASSEL_2 + MC_1;   // SMCLK and Up Mode
 _BIS_SR(LPM0_bits);        // Enter LPM0
}


You can change the value in CCR1 and get different Ton/ Duty cycles. This will cause the LED to appear brighter or dimmer (higher the value or closer it is to CCR0 value, the LED will appear brighter).
Time period or frequency of the PWM signal can be changed by selecting different clock frequency or by dividing the clock frequency and by changing the CCR0 value.

Monday, 6 July 2020

MSP430 Timer in Compare Mode - Part 1 (Up Mode)


Video based Tutorial for Timer in Compare mode is available on My YouTube Channel: https://youtu.be/Drisf7VQI60

Please Subscribe to the Channel!

Code:


#include <msp430g2553.h>

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  P1DIR |= 0x40;                            // P1.6 output
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
  CCR0 = 65000;
  TACTL = TASSEL_2 + MC_1;                  // SMCLK, upmode

  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

// Timer A0 interrupt service routine  - CCR0 vector
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
  P1OUT ^= 0x40;                            // Toggle P1.6
}


Monday, 1 June 2020

MSP430 UART - internal temperature sensor value on PC

Video explanation of the project is available on my 
YouTube channel: https://youtu.be/2g9ohxlH3s0

Do Subscribe to it for more projects related to embedded systems.

Software Code used on Code Composer Studio:

#include <msp430.h>


unsigned int i; //Counter
void int_char();
int j=0;
char str[4];
int temp = 0;


int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

/*Port 2 disabled*/
P2DIR = 0xFF; //All P2.x output
P2OUT &= 0x00; //reset


/* Use Calibration values for 1MHz Clock DCO*/
DCOCTL = 0;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

/* Configure Pin Muxing P1.1 RXD and P1.2 TXD */
P1SEL = BIT1 | BIT2 ;
P1SEL2 = BIT1 | BIT2;

/* Place UCA0 in Reset to be configured */
UCA0CTL1 = UCSWRST;

/* Baud Rate configuration */
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 104; // 1MHz 9600
UCA0BR1 = 0; // 1MHz 9600
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1

/* Take UCA0 out of reset */
UCA0CTL1 &= ~UCSWRST;

/*Configure ADC10*/
ADC10CTL0 = SREF_1 + REFON + ADC10ON + ADC10SHT_3 + ADC10IE;

ADC10CTL1 = INCH_10 + ADC10DIV_3;
while(1)
{

j=0;
IE2 |= UCA0RXIE; //Enable USCI_A0 RX interrupt


__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled

temp = ADC10MEM; //ADC10 conversion value stored in temp
temp = ((temp * 27069L - 18169625L)>>16); //value converted to degree celsius
j=temp;
int_char(); //convert int to char string
UC0IE |= UCA0TXIE; //transmit the value
//i=0; //reset the counter
}
}

/* RX ISR : Start conversion on demand, i.e. whenever t is received*/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if (UCA0RXBUF == 't')
{
ADC10CTL0 |= ENC + ADC10SC; //Start Conversion
}
}

/* TX ISR : Transmit the temperature value*/
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{

UCA0TXBUF = str[i++]; // TX next character
if (i==sizeof str -1) //Tx over?
{
UC0IE &= ~UCA0TXIE; //Disable Tx interrupt
i=0;
}
}
/*ADC10 ISR: switch ON the CPU*/
#pragma vector = ADC10_VECTOR
__interrupt void adc_interrupt(void)
{
__bic_SR_register_on_exit(CPUOFF); // Return to active mode

}

/*Convert the int value to char string*/
void int_char()
{
int s=0;
s=j%10;
str[2]=(char)(s+48);
j=j/10;
s=j%10;
str[1]=(char)(s+48);
j=j/10;
s=j%10;
str[0]=(char)(s+48);
str[3]='\0';
}

Wednesday, 11 March 2020

MSP430G2553 internal temperature sensor with LCD - Software code and Circuit diagram

Below is the Circuit Diagram and the Software Code for displaying the internal temperature sensor data on LCD.

Circuit Diagram:

Note: Connect a 47K ohm resistor between the RST pin and VCC (3.3V)
Vcc for MSP = 3.3V and Vcc for LCD = 5V
LCD used is JHD162A

Circuit Diagram


Software Code:

The lcd.h can be accessed here: https://binabhatt.blogspot.com/2018/05/pulse-rate-detector-using-msp430.html

#include <msp430.h>
#include "lcd"
/*
 * main.c
 */
void int_char();
int j=0;
char str[4];
int temp = 0;
int main(void) {

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

P1OUT=0x00;      //Configure Port1 for LCD

P1DIR |= (BIT0 + BIT6); // P1.0 output

InitializeLcm();

ClearLcmScreen();
PrintStr("Temp is");
ADC10CTL0 = SREF_1 + REFON + ADC10ON + ADC10SHT_3 + ADC10IE;

ADC10CTL1 = INCH_10 + ADC10DIV_3;

ADC10CTL0 |= ENC + ADC10SC; //Start Conversion

__bis_SR_register(LPM0_bits + GIE);

temp = ADC10MEM;
temp = ((temp * 27069L - 18169625L)>>16); //temperature in degree celsius
j=temp;
int_char();
LcmSetCursorPosition(2,0);
PrintStr(str);

return 0;
}

//Interrupt vector  ADC10
#pragma vector = ADC10_VECTOR
__interrupt void adc_interrupt(void)
{
__bic_SR_register_on_exit(CPUOFF); // Return to active mode

}

//Convert int to char for LCD
void int_char()
{
int s;
s=j%10;
str[2]=(char)(s+48);
j=j/10;
s=j%10;
str[1]=(char)(s+48);
j=j/10;
s=j%10;
str[0]=(char)(s+48);
str[3]='\0';
}

Video Explanation:

Wednesday, 19 February 2020

Pulse Rate detector using MSP430 - Circuit Diagram

Hello All,

I have uploaded the snapshot of the circuit diagram for Pulse Rate detector using MSP430g2553. Hope it helps! If it did then do your bit by subscribing to my YouTube channel where I post videos related to Embedded systems!

Circuit diagram

Pin connections between the micro-controller and the LCD (JHD162A) are as follows:

Micro-controller
LCD
3
4
4
6
6
11
7
12
14
13
15
14

Wednesday, 5 February 2020

MSP430G2553 internal temperature sensor

MSP430 Launchpad - Internal Temperature Sensor

Code:


#include <msp430g2553.h>

int temp = 0;
int main(void){
WDTCTL = WDTPW | WDTHOLD; //stop the watchdog timer


//Select 1.5 V, 64 clock cycles, enable ADC interrupt, Turn on the reference generator
ADC10CTL0 = SREF_1 + REFON + ADC10ON + ADC10SHT_3 + ADC10IE;

//Select input channel 10 and divide the clock frequency by 4
ADC10CTL1 = INCH_10 + ADC10DIV_3;

//Enable and Start conversion
ADC10CTL0 |= ENC + ADC10SC;

//Enter low power mode
__bis_SR_register(LPM0_bits + GIE);

//fetch the temperature value from ADC10MEM register
temp = ADC10MEM;

//convert it into degree celsius
temp = ((temp * 27069L - 18169625L)>>16);

return 0;
}

//ISR
#pragma vector = ADC10_VECTOR
__interrupt void adc_interrupt(void)

{
__bic_SR_register_on_exit(CPUOFF);
}

Explanation: https://youtu.be/51pAz11NklA

Saturday, 12 October 2019

Zynq SOC's Gigabit Ethernet: Part 1 to 4

Zynq SOC's Gigabit Ethernet: Part 1 to 4


I have uploaded a series of videos related to the Zynq (xilinx) SOC's Gigabit Ethernet using Zedboard  on my Youtube Channel. These videos cover the introduction to ethernet, design, and implementation parts using vivado and xilinx sdk. Below is the link for the entire playlist consisting of 4 videos. Do check them all and remember to like, share and subscribe (if you found them helpful!)


Check the first part here:


 
Part 1





Cheers!

Wednesday, 9 May 2018

Pulse rate detector using MSP430 - Software/Code

I have uploaded a series of videos on youtube on how to execute this project on my channel:
Youtube Channel
Pulse rate detector video
Please subscribe to my channel, if you found the project helpful. I'll be encouraged to do more projects with your support, do like/comment/subscribe and please find below the source code for the project:

MAIN.c


#include <msp430.h>
#include "lcd"
void delay(int);
void configWDT();
void configIO();
void configIR();
void configT();
void disableT();
void int_char();

int i=0;
int j=0;
char str[4];

int main(void)
{

configWDT();

configIO();

configIR();

InitializeLcm();

ClearLcmScreen();

PrintStr("Place finger tip");
LcmSetCursorPosition(2,0);
PrintStr("on the sensor");

while(1)
  {
  delay(10);
  //P1OUT |= BIT6;
  }

}

void configWDT()
  {
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  }

void configIO()
{
P1OUT=0x00;

P1DIR |= (BIT0 + BIT6); // P1.0 output
}

void configIR()
{
  P1REN |= BIT3; // P2 Enable Pullup/Pulldown
  P1OUT |= BIT3; // P2 pullup
  P1IE |= BIT3; // P2 interrupt enabled
  P1IES |= BIT3; // P2 Hi/lo falling edge
  P1IFG &= ~(BIT3); // P2 IFG cleared just in case
  _EINT();
}

void enablePulseIR()
{
  P2REN |= BIT1; // P2 Enable Pullup/Pulldown
  P2OUT |= BIT1; // P2 pullup
  P2IE |= BIT1; // P2 interrupt enabled
  P2IES |= BIT1; // P2 Hi/lo falling edge
  P2IFG &= ~(BIT1); // P2 IFG cleared just in case
//   _EINT();

}

void disablePulseIR()
{
  P2REN &= ~BIT1; // P2 Enable Pullup/Pulldown
  P2OUT &= ~BIT1; // P2 pullup
  P2IE &= ~BIT1; // P2 interrupt enabled
  P2IES &= ~BIT1; // P2 Hi/lo falling edge
  P2IFG |= (BIT1); // P2 IFG cleared just in case

}

void configT()
{
CCTL0 = CCIE;                             // CCR0 interrupt enabled
CCR0 = 50000;
TACTL = TASSEL_2 + MC_1;                  // SMCLK, upmode
}

void disableT()
{
  TACTL = 0X00;
}

void delay(int a)
{
    for(;a>0;a++)
    _delay_cycles(7);
}

void printResult()
{
int_char();
ClearLcmScreen();
PrintStr("Pulse Rate/min =");
LcmSetCursorPosition(2,0);
PrintStr(str);
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
if(i<350) i++;
else
{
P1OUT &= (~BIT0);                            // Toggle P1.0
disableT();
configIR();
disablePulseIR();
j=j*4;
printResult();
i=0;
j=0;
}
}

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
if((P1IFG & 0x08) == 0x08)
{
P1OUT |= BIT0;
configT();
enablePulseIR();
P1IFG &= ~BIT3;
ClearLcmScreen();
PrintStr("Please wait :");

}
}
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
P2IE &= ~BIT1;
j++;
P2IE |= BIT1;
P2IFG &= ~BIT1;
}

void int_char()
{
int s;
s=j%10;
str[2]=(char)(s+48);
j=j/10;
s=j%10;
str[1]=(char)(s+48);
j=j/10;
s=j%10;
str[0]=(char)(s+48);
str[3]='\0';
}


lcd.h


//
// MSP430 LCD Code
//
#define LCM_DIR P1DIR
#define LCM_OUT P1OUT

//
// Define symbolic LCM - MCU pin mappings
// We've set DATA PIN TO 4,5,6,7 for easy translation
//
#define LCM_PIN_RS BIT1 // P1.1
#define LCM_PIN_EN BIT2 // P1.2
#define LCM_PIN_D7 BIT7 // P1.7
#define LCM_PIN_D6 BIT6 // P1.6
#define LCM_PIN_D5 BIT5 // P1.5
#define LCM_PIN_D4 BIT4 // P1.4

#define LCM_PIN_MASK ((LCM_PIN_RS | LCM_PIN_EN | LCM_PIN_D7 | LCM_PIN_D6 | LCM_PIN_D5 | LCM_PIN_D4))

#define FALSE 0
#define TRUE 1

//
// Routine Desc:
//
// This is the function that must be called
// whenever the LCM needs to be told to
// scan it's data bus.
//
// Parameters:
//
// void.
//
// Return
//
// void.
//
void PulseLcm()
{
    //
    // pull EN bit low
    //
    LCM_OUT &= ~LCM_PIN_EN;

    __delay_cycles(200);

    //
    // pull EN bit high
    //
    LCM_OUT |= LCM_PIN_EN;
    __delay_cycles(200);

    //
    // pull EN bit low again
    //
    LCM_OUT &= (~LCM_PIN_EN);
    __delay_cycles(200);
}

//
// Routine Desc:
//
// Send a byte on the data bus in the 4 bit mode
// This requires sending the data in two chunks.
// The high nibble first and then the low nible
//
// Parameters:
//
// ByteToSend - the single byte to send
//
// IsData - set to TRUE if the byte is character data
// FALSE if its a command
//
// Return
//
// void.
//
void SendByte(char ByteToSend, int IsData)
{
    //
    // clear out all pins
    //
    LCM_OUT &= (~LCM_PIN_MASK);

    //
    // set High Nibble (HN) -
    // usefulness of the identity mapping
    // apparent here. We can set the
    // DB7 - DB4 just by setting P1.7 - P1.4
    // using a simple assignment
    //
    LCM_OUT |= (ByteToSend & 0xF0);

    if (IsData == TRUE)
    {
        LCM_OUT |= LCM_PIN_RS;
    }
    else
    {
        LCM_OUT &= ~LCM_PIN_RS;
    }
    //
    // we've set up the input voltages to the LCM.
    // Now tell it to read them.
    //
    PulseLcm();

    //
    // set Low Nibble (LN) -
    // usefulness of the identity mapping
    // apparent here. We can set the
    // DB7 - DB4 just by setting P1.7 - P1.4
    // using a simple assignment
    //
    LCM_OUT &= (~LCM_PIN_MASK);
    LCM_OUT |= ((ByteToSend & 0x0F) << 4);

    if (IsData == TRUE)
    {
        LCM_OUT |= LCM_PIN_RS;
    }
    else
    {
        LCM_OUT &= ~LCM_PIN_RS;
    }

    //
    // we've set up the input voltages to the LCM.
    // Now tell it to read them.
    //
    PulseLcm();
}

//
// Routine Desc:
//
// Set the position of the cursor on the screen
//
// Parameters:
//
// Row - zero based row number
//
// Col - zero based col number
//
// Return
//
// void.
//
void LcmSetCursorPosition(char Row, char Col)
{
    char address;

    //
    // construct address from (Row, Col) pair
    //

    if (Row == 0)
    {
        address = 0;
    }
    else
    {
        address = 0x40;
    }

    address |= Col;
    SendByte(0x80 | address, FALSE);
}

//
// Routine Desc:
//
// Clear the screen data and return the
// cursor to home position
//
// Parameters:
//
// void.
//
// Return
//
// void.
//
void ClearLcmScreen()
{
    //
    // Clear display, return home
    //
    SendByte(0x01, FALSE);
    SendByte(0x02, FALSE);
}

//
// Routine Desc:
//
// Initialize the LCM after power-up.
//
// Note: This routine must not be called twice on the
// LCM. This is not so uncommon when the power
// for the MCU and LCM are separate.
//
// Parameters:
//
// void.
//
// Return
//
// void.
//
void lcd_delay()
{
__delay_cycles(100000);
}

void InitializeLcm(void)
{
    //
    // set the MSP pin configurations
    // and bring them to low
    //
    LCM_DIR |= LCM_PIN_MASK;
    LCM_OUT &= ~(LCM_PIN_MASK);
    //
    // wait for the LCM to warm up and reach
    // active regions. Remember MSPs can power
    // up much faster than the LCM.
    //
   lcd_delay();

    //
    // initialize the LCM module
    //
    // 1. Set 4-bit input
    //
    LCM_OUT &= ~LCM_PIN_RS;
    LCM_OUT &= ~LCM_PIN_EN;

    LCM_OUT = 0x28;
    PulseLcm();
//SendByte(0x33, FALSE);
//SendByte(0x32, FALSE);
    //
    // set 4-bit input - second time.
    // (as reqd by the spec.)
    //
    SendByte(0x28, FALSE);

    //
    // 2. Display on, cursor off
    SendByte(0x0c, FALSE);

    //
    // 3. Cursor move auto-increment
    //
    SendByte(0x06, FALSE);
}

//
// Routine Desc
//
// Print a string of characters to the screen
//
// Parameters:
//
// Text - null terminated string of chars
//
// Returns
//
// void.
//
void PrintStr(char *Text)
{
    char *c;
    c = Text;

    while ((c != 0) && (*c != 0))
    {
        SendByte(*c, TRUE);
        c++;
    }
}

Sunday, 4 February 2018

Stress measurement using Raspberry Pi

Introduction:

The aim of this project is to measure the stress that a subject applies on a stress-ball and categorize it into three possible levels, i.e. high, medium or low, and the same is displayed on the thermometer on the screen.
The FSR-402 (force sensor) is mounted on a stress ball and the analog signal generated by it on the application of pressure is supplied to AD7705 which converts the same into a digital signal and feeds it to raspberry pi where the software classifies the pressure in any of the available 3 different categories and displays the output in the form of a graph and thermometer on the screen.

Set-up/Project in action


Software:

The Raspberry pi gets the digital sensor input on its GPIO pin from AD7705. The communication interface used is SPI with the device at /dev/spidev0.0. The file related to the same is accessed whenever a read/write has to be performed.

After initialization, a new thread is started which reads the ADC output continuously and stores it in a buffer. The window.CPP file reads the value from the adcreader, whenever a sample is present and a timer event will trigger to plot all the data collected during the 20ms refresh rate on the screen.

Code is available on Github: https://github.com/waffles1/stress_measurement

Hardware:

Hardware can be divided into two parts:
1. The Analog-Digital Converter (ADC) Circuit
2      2. Pressure sensor circuit
Analog-Digital Converter required the following components:
1 x MCP1525
1 x 0.1µF
2 x 1 µF
1 x AD7705
The pressure sensor circuit required the following components:
1 x FSR402
2 x 1kΩ
1 x 1MΩ



Implementation of the circuit diagram:
Circuit
The maximum resistance of the FSR is 10MΩ and the minimum is 300Ω (provided in the datasheet). Upon applying pressure on the FSR, the value of the resistance decreases which results in a voltage drop greater than 80mV and less than 1.9V (wheat-stone bridge was used). The 1kΩ resistors provide a voltage drop of 1.5V at Ain-. Using the 1MΩ resistor, the differential input range is 1.49-1.5Vwhich is well within the voltage drop range. The wheat-stone bridge provides a differential input to the AD7705.

Conclusion:

Application of pressure results in a change in the waveform. The thermometer of QT displays the amount of pressure. A full bar means maximum pressure while an empty bar means no pressure. The AD7705 A/D converter was used to change analog to digital values and was displayed on the monitor. Video will be made available soon on my YouTube channel, do subscribe to my channel for video explanations:



Monday, 15 January 2018

Controlling an LCD using MSP430 via a shift register 74HC595

Introduction

In this post, we will control an LCD using MSP430G2553 via a shift register, 74HC595.

I have already executed a project on controlling an LCD in 4 bit mode using an MSP430  (Pulse Rate Detector): https://youtu.be/dle8M3QlXc4

Although, 4 bit mode reduces the amount of pins required for operation when compared with 8 bit mode, we can further reduce the number of pins required from MSP430 to 3 by using a shift register!

These three pins are required for ENABLE (LCD ENABLE pin), Data and Clocks respectively.

74HC595

74HC595 is a high speed 8-bit serial in, parallel out shift register consisting of a storage register and 3 state-outputs.

Both the shift and the storage registers have a separate clock (SH_CP, ST_CP). During the positive transition of the SH_CP, data is shifted and the content is transferred to storage register during positive transition of ST_CP (check the datasheet of 74HC595 for detailed explanation and pin diagram).

In this project, both the clocks are tied together to reduce the number of pins, thus, the shift register will always be one clock ahead of the storage register. Thus, if we want to receive a serially transferred 8 bit data, an extra clock pulse should be provided after the transmission of the 8-bit serial data as the storage register lags by a single clock pulse w.r.t the shift register.
The OE pin is active low, hence, it is connected to ground for extracting the parallel output.

Circuit Diagram

The hardware connections are straight-forward. The shift register output is connected to the LCD data lines and RS control pin (Data/Command control). Both the clocks are tied together and controlled via a single port pin of MSP430, one pin is connected to ENABLE of LCD and the third port pin is connected to the DATA pin of the shift register. The R/W pin of LCD is grounded as only write operation is performed for this project.

OE pin of shift register is grounded and MR is pulled to 5Volts, Q0 - Q3 are each connected to D4 - D7 of the LCD, and Q4 is connected to RS.


Circuit Diagram

Software

Comment below your email ID to get access to the Software/Code for this project.

Demonstration

Check the project in action:

Sunday, 19 November 2017

MSP430 with Bluetooth Low Energy RN4020 (BLE)

In this post, we'll see how to use a Bluetooth Low Energy (BLE) module, microchip's RN4020 with the MSP430 launchpad. I have used the MSP430G2553 microcontroller for this purpose. There is a lot of documentation available about BLE on the official website (Bluetooth.com) and just typing the term in google will lead you to several other sources. I may cover certain topics related to BLE in a separate post!

You'll need to know how UART works for this tutorial, I would suggest having a look at this URL:UART
Before connecting the BLE module to the micro-controller, we need to configure RN4020 as a peripheral and also create a private service and its characteristics. The steps required to do the same are as follows:

Connect RN4020 to an FTDI adapter (USB to TTL converter) like the one below:


Connect 3.3 V Vcc to RN4020 WAKE and Vcc respectively, GND to grounds and RX, TX to TX, and RX respectively.

Open Tera term and select the serial port, enable Local echo and select CR+Linefeed for Transmit and Receive from setup, and also set the correct baud rate under Serial Port option, i.e. 115200.

Now type the following commands, after the execution of each command, an ACK or acknowledgment signal will be received on the terminal.

SF,1 //factory default
SB, 4 // baud rate set as 115200
SS, C0000001 //set device information and battery service
PZ //clears all settings of the private service and characteristics
PS, 11223344556677889900AABBCCDDEEFF //define private service with UUID
PC,010203040506070809000A0B0C0D0E0F, 08, 02 //the specified characteristic with write property is added, size is 2 bytes
SR, 20000000 //auto advertise
R, 1 //reboot

Check the list of services by typing LS, the UUID of Device Information, Battery and our private service and its characteristics with their UUIDs and handles will be displayed.

The characteristic that we created will be used to turn the LED ON/OFF via an android application. On typing 00, the LED will turn OFF, if it was ON and on typing 01, the LED will turn ON (if it was OFF). You may create additional characteristics as per your requirement, refer the RN4020 user-guide to know more about different AT commands used to configure the module.

Now download BLE Scanner Application from the Android store: BLE Scanner App

Connect with the RN4020 module from the list of devices and enter 00 or 01 as the value of the private characteristic, do select byte array and not Text to enter the value successfully. After entering the same, you can observe that tera terminal shows a command WC, handle, value. Here the value is either 00 or 01.

If on connecting the MSP430 micro-controller, you are able to read the value, you would then be able to make a decision. Have a look at the code which is loaded on MSP430G2553 which causes an interrupt to be generated whenever any value is transmitted by the BLE module. The code is self-explanatory.


#include <msp430.h>

#include<stdio.h>

char buffer[20]; //buffer to receive

volatile unsigned int receive = 0;

//configure UART

void Configure_UART()

{

P1SEL = BIT1 + BIT2;

P1SEL2 = BIT1 + BIT2;

UCA0CTL1 |= UCSSEL_2;

UCA0BR0 = 0X08;

UCA0BR1 = 0X00;

UCA0MCTL = UCBRS2 + UCBRS0;

UCA0CTL1 &= ~UCSWRST;

}
//configure pins

void Configure_Pins()

{

P1DIR |= BIT0; //Pin 0, LED connection

P1OUT &= ~BIT0;

&nbsp;

}
//main loop

void main(void)

{

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

BCSCTL1 = CALBC1_1MHZ; // Set range

DCOCTL = CALDCO_1MHZ;

Configure_UART();

Configure_Pins();

UC0IE |= UCA0RXIE;

__bis_SR_register(CPUOFF + GIE); //set cpuoff and enable interrupts
}

//cpu is turned on whenever interrupt occurs and in main routine its off(stack restored)
#pragma vector = USCIAB0RX_VECTOR

__interrupt void USCI0RX_ISR(void)

{

P1OUT &=~BIT6;

buffer[receive++] = UCA0RXBUF;

if(UCA0RXBUF == '\n')

{
receive = 0;

__bic_SR_register(GIE); //disable interrupt as we want to make a decision now

char conn = buffer[0];

if(conn != 'C')

{

char c = buffer[9]; //decide number to be accessed

switch(c)

{

case '1': P1OUT |= BIT0;

break;

case '0': P1OUT &= ~BIT0;

break;

}

}

__bis_SR_register(GIE); //okay to talk again

}

}

Finally, the demo can be found on Youtube: Demo Video

Saturday, 18 November 2017

MSP430G2553 with a Light Dependent Resistor

In this tutorial, we will connect a Light Dependent Resistor to an MSP430 and turn ON the LED connected to Port 1, pin 0 if the light is below a threshold value else we will turn it OFF.

The LDR is connected to Port 1, pin 7 (configured to act as input channel for the ADC). The SAR ADC on MSP430 converts the analog values supplied by the LDR to digital values.

As displayed in the video (link given below), the LDR is connected in a voltage divider circuit with a 10K Ohms resistor. The detailed theory about the operation of the voltage divider circuit and the formula for calculating the voltage due to variation in resistance of the LDR can be found on: http://robotics.hobbizine.com/ldrlaunch.html

Youtube video link: Demo Video

#include <msp430.h>

unsigned int value = 0;

void ConfigureADC(void)

{
ADC10CTL1 = INCH_7 + ADC10DIV_0;
ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON + ADC10IE;
ADC10AE0 |= BIT7;
}

void ConfigurePins(void)
{
P1OUT = 0;
P1DIR |= BIT0;
}

void main(void) {

WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

BCSCTL1 = CALBC1_1MHZ;

DCOCTL = CALDCO_1MHZ;

ConfigurePins();

ConfigureADC();

while(1)

{

ADC10CTL0 |= ENC + ADC10SC;

__bis_SR_register(CPUOFF + GIE);

value = ADC10MEM;

if(value <= 511)

{

P1OUT |= BIT0; //turn ON the Light

}

else

{

P1OUT &= ~BIT0; //turn if OFF

}

}

}

#pragma vector = ADC10_VECTOR

__interrupt void ADC10_ISR(void)

{

__bic_SR_register_on_exit(CPUOFF);

}

You may use this circuit with a bulb and power the circuit with a solar panel during day time and use the saved power to turn ON the bulb after evening. Another interesting project along similar lines is: Solar Powered Project using MSP430
Kindly comment if you want to know anything specific about the H/W or S/W part!
Next post will be on an MSP430 + Bluetooth low energy module!

MSP430G2553 - Toggle LED with a switch

In this post, we'll learn to use a switch to toggle an LED using MSP430G2553 μcontroller.

The LED and switch are connected to Port 1, pin 0 and pin 3 respectively. Clicking the switch generates an interrupt. Initially, the LED is in OFF state, if the switch is pressed, the LED starts blinking till next interrupt occurrence/switch press.

If pull mode is enabled by setting PxREN register then either the pull up or pull down option can be selected by setting or clearing the corresponding bit in PxOUT register. One can either select high to low or low to high transition as the trigger for interrupt by setting/clearing the corresponding bit in PxIES register. Detailed information regarding the port settings can be found in the datasheet.
The state of the switch is tracked by a variable named "blink".

Do check the demonstration video: MSP430 with a switch and an LED

#include<msp430.h>

unsigned int blink = 0;

void main(void)

{

 WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

 P1DIR |= BIT0; // Set P1.0 to output direction

 P1OUT &= ~BIT0; //clear pin

 P1REN |= BIT3; //enable pull mode 

 P1OUT |= BIT3; //pull up

 P1IES |= BIT3; //triggers when button pressed, high to low 

 P1IE |= BIT3; //enable interrupt 

__enable_interrupt(); //global/general interrupts enabled
for(;;) 

 { 

if (blink > 0)
{
P1OUT ^= BIT0; //toggle LED
__delay_cycles(100000); //delay of 10000 cycles at 1MHz
  }

 }
}
//Port 1 Interrupt Service Routine

#pragma vector = PORT1_VECTOR

__interrupt void Port_1(void)
{
blink ^= 0x01;
P1IFG &= ~BIT3; // P1.3 interrupt flag cleared
P1OUT &= ~BIT0; // clear LED to start in off state
}