Jump to content
43oh

Is there a way in Energia to access the LPM's?


Recommended Posts

I was wondering if anyone might be able to give me direction on how to use the LPM's? I have seen a bunch of stuff like this:

 

 

//******************************************************************************

// MSP430G2xxx Demo - Software Port Interrupt Service on P1.3 from LPM4

//

// Description: A hi/low transition on P1.3 will trigger P1_ISR which,

// toggles P1.0. Normal mode is LPM3 ~ 0.1uA. LPM4 current can be measured

// with the LED removed, all unused P1.x/P2.x configured as output or inputs

// pulled high or low, and ensure the P1.3 interrupt input does not float.

// ACLK = n/a, MCLK = SMCLK = default DCO

//

// MSP430F20xx

// -----------------

// /|\| XIN|-

// | | |

// --|RST XOUT|-

// /|\ | |

// --o--|P1.3 P1.0|-->LED

// \|/

//

// M.Buccini / L. Westlund

// Texas Instruments, Inc

// October 2005

// Built with CCE Version: 4

//******************************************************************************

#include <msp430g2231.h>

 

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

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

P1IE |= BIT3; // P1.3 interrupt enabled

P1IES |= BIT3; // P1.3 Hi/lo edge

P1IFG &= ~BIT3; // P1.3 IFG cleared

 

_BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt

}

 

// Port 1 interrupt service routine

#pragma vector=PORT1_VECTOR

__interrupt void Port_1(void)

{

P1OUT ^= 0x01; // P1.0 = toggle

P1IES ^= BIT3;

P1IFG &= ~BIT3; // P1.3 IFG cleared

}

 

 

Not really too tough to follow considering it has been commented every step of the way. I guess my question is:

 

Is there already some functionality that I am not aware of within Energia to utilize the LPM's? Is there a library available to allow people using Energia to use the various LPM's available?

 

Regardless of the answers to those two questions...if I wanted to take the above code, and use it in Energia would that be possible? I assume there is some sort of syntax for allowing a code block like the one above to pass information to the C code or am I way off here?

 

As usual, I come with more questions than answers :-)

Link to post
Share on other sites

Enabling easy access to LMP's has been on my list for a long time but just hadn't had the time..

I have done some sketching to get a rough idea of what it would take. The below Sketch should help you to get on your way.

 

void setup() {
 /* Watchdog runs in interval.
  * Disable it so we don't wake up at 6 am when our alarm is set for 10 am.
  * After this call delay(...) will not work */
 disableWatchDog();
 attachInterrupt(P1_3, awake, FALLING);
}

void loop() {
 __bis_status_register(LPM4_bits + GIE);
 /* Code after this will never be reached */
}

void awake(){
 /* You are in the ISR.
  * Do something useful while you are awake!
  * But don't call any functions that rely on interrupt */
}

 

Note that after awake() is called, system will go back to LPM4. Clearing the LPM4 bits here will not work since the SR register is on the stack and will be popped off resetting the LPM bits. Only place you can do this right now is inside WInterrupt.c in the port interrupt ISR. You will have to call __bic_status_register_on_exit(LPM4_bits);

 

Using the above you should see current consumption go down to the nA's :-)

 

Robert

Link to post
Share on other sites

I didn't answer your last question. Yes, the code is totally portable to Energia.

 

void setup(void)
{
 disableWatchDog();
 P1DIR |= 0x01; // Set P1.0 to output direction
 P1IE |= BIT3; // P1.3 interrupt enabled
 P1IES |= BIT3; // P1.3 Hi/lo edge
 P1IFG &= ~BIT3; // P1.3 IFG cleared
 _BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt
}
void loop() {
}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
 P1OUT ^= 0x01; // P1.0 = toggle
 P1IES ^= BIT3;
 P1IFG &= ~BIT3; // P1.3 IFG cleared
}

Link to post
Share on other sites

Ok, so one more question. In your response you have the ISR section:

 

void awake(){

/* You are in the ISR.

* Do something useful while you are awake!

* But don't call any functions that rely on interrupt */

}

 

You say don't call any functions that rely on interrupts. Why? I still think I need a bit of help understanding how to impliment this. Basically I have this code:

 

// Example testing sketch for various DHT humidity/temperature sensors

// Written by ladyada, public domain

 

#include "DHT.h"

 

#include <LiquidCrystal.h>

 

#define DHTPIN 15 // what pin we're connected to

 

const int buttonPin = 2;

const int ledPin = 12;

int ledState = LOW;

int buttonState;

int lastButtonState = LOW;

 

long lastDebounceTime = 0;

long debounceDelay = 50;

 

 

// Uncomment whatever type you're using!

#define DHTTYPE DHT11 // DHT 11

//#define DHTTYPE DHT22 // DHT 22 (AM2302)

//#define DHTTYPE DHT21 // DHT 21 (AM2301)

 

// Connect pin 1 (on the left) of the sensor to +5V

// Connect pin 2 of the sensor to whatever your DHTPIN is

// Connect pin 4 (on the right) of the sensor to GROUND

// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

 

LiquidCrystal lcd(3,4,5,6,7,8);

 

DHT dht(DHTPIN, DHTTYPE);

 

 

 

void setup() {

 

pinMode(buttonPin, INPUT);

pinMode(ledPin, OUTPUT);

pinMode(14, OUTPUT);

lcd.begin(16, 2);

 

dht.begin();

}

 

void loop() {

 

int reading = digitalRead(buttonPin);

 

if (reading != lastButtonState) {

// reset the debouncing timer

lastDebounceTime = millis();

}

 

if ((millis() - lastDebounceTime) > debounceDelay) {

// whatever the reading is at, it's been there for longer

// than the debounce delay, so take it as the actual current state:

buttonState = reading;

}

if(buttonState == HIGH) {

analogWrite(14, 90);

lcd.display();

digitalWrite(12, HIGH);

}

else if(buttonState == LOW){

analogWrite(14, 0);

digitalWrite(12, LOW);

lcd.noDisplay();

}

lastButtonState = reading;

// Reading temperature or humidity takes about 250 milliseconds!

// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)

float h = dht.readHumidity();

float t = dht.readTemperature();

 

 

// check if returns are valid, if they are NaN (not a number) then something went wrong!

 

 

lcd.setCursor(0,0);

lcd.print("RH: ");

lcd.print(h);

lcd.print(" %");

lcd.setCursor(0,1);

lcd.print("Temp: ");

lcd.print(Fahrenheit(t));

lcd.print(" *F");

 

delay(100);

}

 

double Fahrenheit(double celsius)

{

return 1.8 * celsius + 32;

}

 

 

When the button is pressed, the backlight turns on, analogWrite adjusts the contrast, and the readings are displayed. What I want is for this little gadget to hang out in LPM4 until the button is pressed...then run the code above when it is pressed..then go back to LPM4.

 

Is this as simple as perhaps setting a variable = to 1 in the ISR, and then checking in the loop if the variable = 1 to execute the code, else set the variable to 0 and go back to sleep? So perhaps a "do while button is pressed" control structure in the main loop, and then when the while loop exits it goes back to sleep?

 

Just wondering if I am on the right track.

 

I just want to say again...thank you so much for all of your help.

Link to post
Share on other sites

Ok, after doing a bunch more research I think I am getting a handle on this.

 

I would like if someone would explain this (in the reply from energia):

 

Note that after awake() is called, system will go back to LPM4. Clearing the LPM4 bits here will not work since the SR register is on the stack and will be popped off resetting the LPM bits. Only place you can do this right now is inside WInterrupt.c in the port interrupt ISR. You will have to call __bic_status_register_on_exit(LPM4_bits);

END QUOTE

 

So if I wrote, for instance, something in the loop to blink an LED 10 times, and then put the line at the end to put it into LPM0 or even LPM4. What do I need to put in the ISR to wake it back up and start at the top of the loop again? If I can get answer to that, I think I am set.

Link to post
Share on other sites

Sorry if this is a silly questions...but how do I use the functions in WInterrupts2.ino ? I even tried replacing the WInterrupts.c in the core folder with yours and that didn't work.

 

I tried including it, etc so that I could use the attachInterrupt2 function...no go.

 

What am I doing wrong?

Link to post
Share on other sites
  • 6 months later...

Rick, 

 

Thank you for the codes, it definitely is a tremendous help for me. However, I notice that the current draw (@3.7V) by the M430G2553 on the TI Launchpad is 39.2mA on LPM4 and 40.5mA on LPM3. Surely, something is not quite right here. I used both your editions of WInterrupt and LPM Button codes. Please advise me on this matter, thank you.

 

Regards,

Elmo

Link to post
Share on other sites

Guys, some update on my matter. I pulled out the jumpers on J5 and J3 each time I do the power tests. I found that at LPM3 and LPM4, it draws 0.063mA @ 1.5V. This shows that there is no significant difference between LPM3 and LPM4, which theoretically is not correct. I will keep investigating why doesn't it work for LPM4. In the meanwhile, please share an insight on what you think on my basic power tests code

 

void setup() {

}
 
void loop() {
  _BIS_SR(LPM4_bits | GIE); 
}
Link to post
Share on other sites
  • 2 years later...

Enabling easy access to LMP's has been on my list for a long time but just hadn't had the time..

I have done some sketching to get a rough idea of what it would take. The below Sketch should help you to get on your way.

 

void setup() {
  /* Watchdog runs in interval.
   * Disable it so we don't wake up at 6 am when our alarm is set for 10 am.
   * After this call delay(...) will not work */
  disableWatchDog();
  attachInterrupt(P1_3, awake, FALLING);
}

void loop() {
  __bis_status_register(LPM4_bits + GIE);
  /* Code after this will never be reached */
}

void awake(){
  /* You are in the ISR.
   * Do something useful while you are awake!
   * But don't call any functions that rely on interrupt */
}
Note that after awake() is called, system will go back to LPM4. Clearing the LPM4 bits here will not work since the SR register is on the stack and will be popped off resetting the LPM bits. Only place you can do this right now is inside WInterrupt.c in the port interrupt ISR. You will have to call __bic_status_register_on_exit(LPM4_bits);

 

Using the above you should see current consumption go down to the nA's icon_e_smile.gif

 

Robert

 

Hi Robert

 

I am using the MSP430FR5969 and can't seam to get the current down below 270uA is there something extra needed ?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...