MSP430FG4618 experiments board....battery monitor

  • (2 Pages)
  • +
  • 1
  • 2

16 Replies - 2766 Views - Last Post: 19 February 2012 - 05:28 PM Rate Topic: -----

#1 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 12:51 PM

I am using is 12 bit ADC...so 2^12= 4096.....dividing the range 0-2.5 v gives me 0.000614...Now for simplicity. I will consider

two cases only low voltage( Low battery will turn a segment ON at the LCD) and High voltage( battery full lights up another segment

On at LCD to indicate)

The corresponding values for :high voltage=3V ...at divider= 1.5 V and ADC value=1.5/0.000614= 2459 (0x99C in hex)

: Low voltage= 2.5 V at divide = 1,25V and ADC value=1.25/0.000614=2049(0x801 in hex)
Hello, I m using MSP430FG4618 experiments board.... I want to display the status of the battery ...using a LCD ...which is configured....to display a full battery sign when BAT-FULL command and Low Battery sign when BAT_LOW command...these are defined in LCD_defs.h in the code below.
Basically i want to use ADC reference and internal voltage divider to monitor the battery.... The code I have written below..is supposed to do that... but it is not working ....whatever....happens the battery sign doesnt respond....is the approach adopted alright?????

#include <msp430fg4618.h>
#include <stdbool.h>
#include  "LCD_defs.h"

void Single_Measure(unsigned int);
void Single_Measure_REF(unsigned int, unsigned int);

unsigned int ADCValue;                                                  // Measured ADC Value
unsigned int i;
bool ADCDone;                                                           // ADC Done flag

void main(void) {
    WDTCTL = WDTPW + WDTHOLD;                                           // Stop watchdog timer
    P1DIR |= 0x01;                                                      // Set P1.0 to output direction
    __bis_SR_register(GIE);
    //LCD_A S0-S21 configuration
          LCDAPCTL0 = LCDS24 | LCDS20 | LCDS16 | LCDS12 | LCDS8 | LCDS4;

          // LCD_A configuration
          LCDACTL = LCDFREQ_192 | LCD4MUX | LCDSON | LCDON;   // (ACLK = 32768)/192, 4-mux LCD, LCD_A on, Segments on
          LCDAVCTL0 = LCDCPEN;                                // Charge pump enable
          LCDAVCTL1 = VLCD_3_44;                              // VLCD = 3,44 V

    ADCDone = false;
    Single_Measure_REF(INCH_11, REF2_5V);

    while(1) {

        if (ADCDone) {
            ADCDone = 0;
            i = ADCValue;
            if (i>=0x99C){ // if VCC>=2.5 ( for simplicity i will display any value above 2.5 as battery full
             //any value less than 2.5 will be battery low
             BAT_FULL;
             } else

             BAT_LOW;


                }// Set breakpoint here
        }
    }
    /// BATTery INDICATION ROUTINE





void Single_Measure_REF(unsigned int chan, unsigned int ref) {
    ADC12CTL0 &= ~ENC;                                                  // Disable ADC conversion
    ADC12CTL0 = SHT0_2 + REFON + ADC12ON +ref ;
    ADC12MCTL0=SREF_1+chan;                                            // selecting reference and channel 11(( Avcc-Avss)/2)
    __delay_cycles(128);                                                // Delay to allow Ref to settle
    ADC12IE=0x01;
    // Use reference,
   // ADC12CTL0 = SREF_1 +  REFON + ADC12ON + ref + ADC12IE;               // 16 clock ticks, internal reference on
    ADC12CTL1 = ADC12SSEL_3;
    __enable_interrupt();                                                                    // ADC On, enable ADC interrupt, Internal = 'ref'
                                        // Set 'chan', SMCLK

    ADC12CTL0 |= ENC + ADC12SC;
    // Enable and start conversion
}

#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR(void) {
	//ADCValue =(void(*)())& ADC12MEM;
    ADCValue =(unsigned int)ADC12MEM0;                                                // Saves measured value.
    ADCDone = 1;                                                     // Sets flag for main loop.
    ADC12CTL0 &= ~ENC;                                                  // Disable ADC conversion
}



cheers any help will be appreciated..!!

This post has been edited by crastonhill: 18 February 2012 - 12:52 PM


Is This A Good Question/Topic? 0
  • +

Replies To: MSP430FG4618 experiments board....battery monitor

#2 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 01:04 PM

How many times are you actually taking your readings, looking at your comments, it looks like only once.

Jim
Was This Post Helpful? 0
  • +
  • -

#3 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 01:47 PM

I am not sure what you mean?? which readings are you referring to??
Was This Post Helpful? 0
  • +
  • -

#4 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 05:59 PM

I an referring to how many times are you reading the voltage from the ATOD converter. It looks to me like you are taking one reading and one reading only. You start your one and only reading before you enter your loop with a call to Single_Measure_REF() you then proceed to your loop. When the ATOD completes the conversion it generates an interrupt. When you service the interrupt, you place the value from the ATOD into your ADCValue variable, change the status of ADCDone and then disable the interrupt.

Now as I said in my previous post I am just reading your comments, I do not have the datasheet for your processor so I can't verify this. However it seems logical that a function named Single_Measure is only going to do a single measurement.

So my question is how many times are you actually checking the status of your "battery"?

Jim

This post has been edited by jimblumberg: 18 February 2012 - 06:00 PM

Was This Post Helpful? 0
  • +
  • -

#5 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 06:18 PM

ohh yeah got you... Yeah it is just a single measurement....!! The part that I am not sure about is whether the code is using the ADC reference as it is meant to be used...In this application.

P.s I am attaching a link to family user guide for this microcontroller....read the chapter for ADC12(chapter 17)

http://www.ti.com/li...9f/slau049f.pdf
Was This Post Helpful? 0
  • +
  • -

#6 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 07:35 PM

Quote

The part that I am not sure about is whether the code is using the ADC reference as it is meant to be used


To convert the value you receive from your ADC into a voltage you would take the unsigned value retrieved from your ADC and multiply it by the reference voltage divided by the ADC resolution. So if you are using a 2.5 volt reference and your resolution is 12 bit you would multiply the ADC value by (2.5/4095). Also the maximum voltage that you can measure is vref. So if you use the internal voltage references you have a choice between 2.5 and 1.5 volts. So if you read 3047 from the ADC your voltage would be 3047 * (2.5/4095) = 1.8597.

Also if you want to "monitor" the voltage you need to read the ADC more than once.

Jim
Was This Post Helpful? 0
  • +
  • -

#7 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 08:46 PM

Yeah....thats what I did in the very first post....I am using Vref 2.5 V . Hence, I used the voltage divider to bring the voltage down to within 2.5 V... Now all I want it to do is that if the battery voltage is above 2.5 V its displays a battery sign( predefined in LCD_defs.h) on the LCD and if its below 2.5 V it should a low battery sign.

SO see the ADC value you referred to in your last post(used 3047 as an example) . I am right that this value is going to vary with the VCC supply battery voltage...If voltage drops this value will go higher???

Also about reading the ADC more than once....I thought thats what the interrupt will be doing...Everytime a new conversion is done...i.e VCC changes...it will trigger the interrupt and produce a new value for comparison in the WHILE loop...does this make sense?? or I am talking total non sense here...!
!
Was This Post Helpful? 0
  • +
  • -

#8 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 18 February 2012 - 11:11 PM

Quote

SO see the ADC value you referred to in your last post(used 3047 as an example) . I am right that this value is going to vary with the VCC supply battery voltage...If voltage drops this value will go higher???

It will vary with whatever is connected to the ADC pin, if this is the battery voltage then yes it should monitor battery voltage, to a point. if the supply voltage to the microprocessor drops below your reference voltage the reference voltage will also start to drop. When your reference voltage starts dropping then the ADC will not produce accurate results. So choosing the lower voltage reference might be a better option.

Now when the input voltage to the ADC is at or greater than the reference voltage your ADC will report the maximum reading (4095) when your voltage drops below the reference voltage your ADC will report lower readings until it reaches 0.

Quote

Also about reading the ADC more than once....I thought thats what the interrupt will be doing.

No the way you have your program setup the ADC will only take one reading. What you are doing now is initiating a reading before your loop with your call to Single_Measure_REF(), this function sets up the ADC system to take a reading, then starts the conversion. When the conversion is complete the interrupt routine is called, this interrupt routine moves the value in the ADC register into your ADCValue variable, then setts your ADCDone variable to 1. Before this interrupt routine exits it disables any further ADC interrupts with ADC12CTL0 &= ~ENC;.

Meanwhile you are constantly testing ADCDone in your while loop. After the ADC completes and ADCDone is set to 1 the if statement is executed and you can check this value. After you check your value you will then need to call your Single_Measure_REF() function to start a new reading.

Remember when dealing with a ADC the maximum voltage the ADC can resolve is the reference voltage. So if the voltage reference is 1 volt and you supply 1 volt into your ADC you will get the maximum value 4095. If your voltage reference is 2.5 volts an input of 2.5 volts to your ADC will produce the maximum value of 4095.

You have 4096 bits of resolution between the minimum voltage (0) and your voltage reference (vref).

Jim

This post has been edited by jimblumberg: 18 February 2012 - 11:12 PM

Was This Post Helpful? 0
  • +
  • -

#9 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 12:43 PM

Ok.. I have changed the code totally...to make it more simpler... Few notes ....ADC_value defined should be the value i will get after conversion considering the internal voltage divider of the ADC(ADC12MCTL0=SREF_1+INCH_11; )....now when i get that converted value...as you said i can convert that to voltage...and then use it to find the status of the battery... and then make the comparison..... (BAT_VOLT) defines that...Then that can be used for comparison...!However, still the program just jumps to the BAT_LOW..when ISR is called,...not sure what it is doing??thanks for your time


#include  <msp430fg4618.h>
#include <stdint.h>
#include<intrinsics.h> //For add_bcd_short function to be used
#include  "LCD_defs.h" // P7_A1...P1_A0....all defined here
unsigned int ADCValue;
unsigned int BAT_VOLT;
void LCD_all_off(void);

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

  //LCD_A S0-S21 configuration
            LCDAPCTL0 = LCDS24 | LCDS20 | LCDS16 | LCDS12 | LCDS8 | LCDS4;

            // LCD_A configuration
            LCDACTL = LCDFREQ_192 | LCD4MUX | LCDSON | LCDON;   // (ACLK = 32768)/192, 4-mux LCD, LCD_A on, Segments on
            LCDAVCTL0 = LCDCPEN;                                // Charge pump enable
            LCDAVCTL1 = VLCD_3_44;
            LCD_all_off();

 // ADC CONFIGURATION

  P6SEL |= 0x01;                            // Enable A/D channel A0
  //ADC12CTL0 = ADC12ON + SHT0_8 + MSC;       // Turn on ADC12, set sampling time
  ADC12CTL0 = REFON + REF2_5V + ADC12ON + SHT0_8+ MSC;//reference used 2.5 v , MSC= multiple sample and conversion starts another
  	  	  	  	  	  	  	  	  	  	  	  	  	  //conversions as one ends// SHT0_8 ..256 cycles of clock
  ADC12CTL1 = SHP + CONSEQ_2;               // Use sampling timer, set mode//repeat single channel conversions
  ADC12IE = 0x01;                           // Enable ADC12IFG.0
  ADC12CTL0 |= ENC; 						 // Enable conversions
  ADC12MCTL0=SREF_1+INCH_11;                    // selecting reference and channel 11(( Avcc-Avss)/2)
  __enable_interrupt();                     // Enable interrupts
  ADC12CTL0 |= ADC12SC;                     // Start conversion
  __bis_SR_register(LPM0_bits);             // LPM0
}

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
ADCValue= ADC12MEM0;  // Move  conversion result, IFG is cleared
BAT_VOLT= (ADCValue)*(2.5/4095) ;   //coverting the value from ADC into voltage

if (BAT_VOLT>=1.25){        //using voltage divide 2.5/2 =1.25 (not sure abt this bit??)
	BAT_FULL;             // Any battery value above 2.5 gives symbol battery full
}else{
		BAT_50;}              //any battery value below 2.5 gives low battery symbol(BAT_50 or BAT_LOW...same thing defined)

	}


//LCD clear routine
void LCD_all_off(void)
{
 LCDM2 = 0x00;
 LCDM3 = 0x00;
 LCDM4 = 0x00;
 LCDM5 = 0x00;
 LCDM6 = 0x00;
 LCDM7 = 0x00;
 LCDM8 = 0x00;
 LCDM9 = 0x00;
 LCDM10 = 0x00;
 LCDM11 = 0x00;
 LCDM12 = 0x00;
 LCDM13 = 0x00;
}



Was This Post Helpful? 0
  • +
  • -

#10 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 01:05 PM

Quote

Ok.. I have changed the code totally...to make it more simpler.

That is debatable.

Where are you displaying anything on the LCD?

What type of variable is BAT_VOLT?

What happens to your program after __bis_SR_register(LPM0_bits);? And what is this line doing? What is LPM0_bits?

What happens when you try to put a fractional variable in a int?

You need to find an indentation style you like and use it consistantly, your code is very hard to read as presented.
Jim

This post has been edited by jimblumberg: 19 February 2012 - 01:07 PM

Was This Post Helpful? 0
  • +
  • -

#11 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 01:54 PM

Quote

Where are you displaying anything on the LCD?

if (BAT_VOLT>=1.25){
BAT_FULL;
}else{
BAT_50;}
BAT_FULL and BAT_50....these are variables defined in LCD_defs.h for displaying symbols on LCD screen

Quote

What type of variable is BAT_VOLT?

Yes.. just realised that...I will change it to double as it will take a fraction

Quote

What happens to your program after __bis_SR_register(LPM0_bits);? And what is this line doing? What is LPM0_bits?

C compilers do not allow to get access to the CPU control registers. On MSP430 the CPU Register R2 is used as the Status Register (SR).
There are bits within the SR that allows to configure the chip into its Low Power Modes and there is the General Interrupt Enable (GIE) bit.
So if you want to change either the LPM mode or set/clear the GIE bit you use an intrinsic function of the C compiler - that's the __bis_SR_register() function.

This line just configures the system to a low power mode ...definitions are defined in datasheet.. It goes into Low power mode with the interrupt.
code with changes!!

#include  <msp430fg4618.h>
#include <stdint.h>
#include<intrinsics.h> //For add_bcd_short function to be used
#include  "LCD_defs.h" // P7_A1...P1_A0....all defined here
unsigned int ADCValue;
unsigned double BAT_VOLT;
void LCD_all_off(void);

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

  //LCD_A S0-S21 configuration
            LCDAPCTL0 = LCDS24 | LCDS20 | LCDS16 | LCDS12 | LCDS8 | LCDS4;

            // LCD_A configuration
            LCDACTL = LCDFREQ_192 | LCD4MUX | LCDSON | LCDON;   // (ACLK = 32768)/192, 4-mux LCD, LCD_A on, Segments on
            LCDAVCTL0 = LCDCPEN;                                // Charge pump enable
            LCDAVCTL1 = VLCD_3_44;
            LCD_all_off();

 // ADC CONFIGURATION

  P6SEL |= 0x01;                            // Enable A/D channel A0
  //ADC12CTL0 = ADC12ON + SHT0_8 + MSC;       // Turn on ADC12, set sampling time
  ADC12CTL0 = REFON + REF2_5V + ADC12ON + SHT0_8+ MSC;//reference used 2.5 v , MSC= multiple sample and conversion starts another
  	  	  	  	  	  	  	  	  	  	  	  	  	  //conversions as one ends// SHT0_8 ..256 cycles of clock
  ADC12CTL1 = SHP + CONSEQ_2;               // Use sampling timer, set mode//repeat single channel conversions
  ADC12IE = 0x01;                           // Enable ADC12IFG.0
  ADC12CTL0 |= ENC; 						 // Enable conversions
  ADC12MCTL0=SREF_1+INCH_11;                    // selecting reference and channel 11(( Avcc-Avss)/2)
  __enable_interrupt();                     // Enable interrupts
  ADC12CTL0 |= ADC12SC;                     // Start conversion
 for(;;)/>{   
 __bis_SR_register(LPM3_bits + GIE);
 }
}

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
ADCValue= ADC12MEM0;  // Move  conversion result, IFG is cleared
BAT_VOLT= (unsigned double)((ADCValue)*(2.5/4095)) ;   //coverting the value from ADC into voltage

if (BAT_VOLT>=1.25){        //using voltage divide 2.5/2 =1.25 (not sure abt this bit??)
	BAT_FULL;             // Any battery value above 2.5 gives symbol battery full
}else{
		BAT_50;}              //any battery value below 2.5 gives low battery symbol(BAT_50 or BAT_LOW...same thing defined)

	}


//LCD clear routine
void LCD_all_off(void)
{
 LCDM2 = 0x00;
 LCDM3 = 0x00;
 LCDM4 = 0x00;
 LCDM5 = 0x00;
 LCDM6 = 0x00;
 LCDM7 = 0x00;
 LCDM8 = 0x00;
 LCDM9 = 0x00;
 LCDM10 = 0x00;
 LCDM11 = 0x00;
 LCDM12 = 0x00;
 LCDM13 = 0x00;
}





sorry changed it....the type is double not unsigned double...!!
Was This Post Helpful? 0
  • +
  • -

#12 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 02:03 PM

So, did your changes fix your problem?

Don't you still need your while(1) loop to keep the program from ending? And doesn't the interrupt wake up the processor? If it does wake the processor won't you want to place the processor back to low power mode?


Jim
Was This Post Helpful? 0
  • +
  • -

#13 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 02:32 PM

Well it doesnt fix the problem... It displays the full voltage symbol...however..it doesnt respond to the voltage change...i mean when voltage falls below 2.5 v...it should display low battery symbol.

I dont think i need the while loop...because ADC12CTL0 = REFON + REF2_5V + ADC12ON + SHT0_8+ MSC......the MSC command ensures that the next conversion should be done automatically after another...so in case of a new conversion..interrupt routine will be called...is it not??
Was This Post Helpful? 0
  • +
  • -

#14 jimblumberg  Icon User is online

  • member icon


Reputation: 4062
  • View blog
  • Posts: 12,540
  • Joined: 25-December 09

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 03:47 PM

Have you looked at any of the TI example code? There seems to be about 10 or 11 samples using the ADC12. Most of the samples do use the while statement, a couple do not.

Is this the actual Hardware you are using? If it is different please post a link to your actual hardware documentation.


I was not able to find any information on using the LCD that is on the board, if you can supply a link to this information it might help.


Jim
Was This Post Helpful? 0
  • +
  • -

#15 crastonhill  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 29
  • Joined: 21-January 12

Re: MSP430FG4618 experiments board....battery monitor

Posted 19 February 2012 - 03:59 PM

Yes . The hardware is the same one that I m using...

well...I have seen the example codes....But where exactly do u think a while statement is needed??


The LCD information can all be found here..in these two links

http://www.softbaugh...ecification.pdf
http://www.softbaugh...rPartNo=SBLCDA4

http://cnx.org/conte...test/LCD_defs.h
This is the header file I am using....in my code...Thats wher BAT_FULL and all variables comes from

Although I doubt that I have made any mistakes with LCD configuration. I made a whole alarm clock on this
I think the settings should be fine....

cheers

Forgot to tell I use the ADC12_07 example code as reference for this particular code...!
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2