Jump to content
43oh

Low Power Modes with an ISR


Recommended Posts

Please help, I am trying without success to write a program which uses the low power modes. My objective is to use an ISR to turn an led on for one second, then turn it off.

I have looked at several tutorials for the low power modes and copied the following very

Basic program which works okay by toggling an led every time the button is pushed. I

Modified the ISR to turn the green led on for a second, then  off, it does not work. I did a lot of trial and error programming on this and cannot come up with a solution  I am using an MSPG2553On a launchpad

Thank you for any help

Link to post
Share on other sites

Yep what @@cubeberg said - ask me anything about the sleep(), sleepSeconds(), suspend() and wakeup() functions (it was @@energia and myself who wrote them).

 

In your main loop, you use suspend() to enact LPM4.  sleep() and sleepSeconds() allow you to enter LPM3 with a timeout.

 

When your ISR fires at some point, if you need to wake the chip up completely you can run wakeup() inside your ISR to make that happen.  The chip will wake up, resuming the main loop just after your suspend()/sleep()/sleepSeconds() call.  Otherwise it will perpetually go back to sleep when the ISR ends (or in the case of LPM3, i.e. sleep/sleepSeconds, go back to sleep until the intended sleep time has elapsed).

Link to post
Share on other sites

Also, using delay() inside your ISR is sketchy and not recommended.  That might actually be what's screwing you up here.  Save delays for the main loop.  You might be able to get by with a simple ISR that just issues wakeup() and then does the LED toggle crap inside the main loop... example:

const int  led1         = P1_0;       // the pin that the red LED is attached to
const int  led2         = P1_6;       // the pin that the green LED is attached to

void setup()
{
  pinMode        (led2,OUTPUT);                     //Enable output on P1_6 (onboard green LED)
  pinMode        (P1_3,INPUT_PULLUP);       //Enable inputs on P1_3 (onboard button)
  pinMode        (led1,OUTPUT);                     //Enable output on P1_0 (onboard red LED)
  attachInterrupt(P1_3,Interrupt, FALLING); //attach interrupt routine to P1_3
}

void loop() {
  suspend();
  // chip woke up; toggle LED then go back to sleep
  digitalWrite(led1, !digitalRead(led1));  // toggle red LED
  digitalWrite(led2, HIGH);  // turn the green LED on
  sleep(999);  // wait for a second (using LPM3 sleep)
  digitalWrite(led2, LOW);   // turn the green LED off
  // end loop, loop() will run again putting the chip in LPM4 via suspend()
}

void Interrupt(void)
{
  wakeup();
}

The sleep(999) stuff may look weird, trust me on that though.  When sleep(1000) or above is called it converts to sleepSeconds(), which may sleep for a longer period of time than you intend (due to its low granularity of WDT timer ISR firing).  You can use delay(1000) instead if you'd like, sleep() just uses less power.

Link to post
Share on other sites

Thanks spirilis:

 

I've been watching the development of sleep, sleepSeconds, wake, and suspend with great interest because of a project I am working on that demands low power. I appreciate your contributions.

 

Unfortunately, I am not realizing the manufacture's stated current draw on a MSP430FR5969 LaunchPad Rev. 2.0 (modified the Energia boards.txt to make it run at 16 MHz) using the functions. For example, slight modifications to the code you provide above:

void setInputLow(uint8_t port, uint8_t pins) {  volatile uint8_t *out;
  volatile uint8_t *ren;


  /* Get the output register */
  out = portOutputRegister(port);
  /* Get the internal resistor pull up/down register */
  ren = portRenRegister(port);
  
  /* If the port is not a port then return */
  if(out == NOT_A_PORT || ren == NOT_A_PORT) return;
  
  /* Enable the internal pull up/down resistors */
  *ren |= pins;
  /* Clear output register bits to select pull down */
  *out &= ~pins;  
}


void setup()
{
  // Drive all pins low, and set as outputs.
  setInputLow(1, 0xF);
  setInputLow(2, 0xF);
  setInputLow(3, 0xF);
  
  pinMode        (GREEN_LED,OUTPUT);                     //Enable output on P1_6 (onboard green LED)
  pinMode        (PUSH1,INPUT_PULLUP);       //Enable inputs on P1_3 (onboard button)
  pinMode        (RED_LED,OUTPUT);                     //Enable output on P1_0 (onboard red LED)
  attachInterrupt(PUSH1,Interrupt, FALLING); //attach interrupt routine to P1_3
}


void loop() {
  suspend();
  // chip woke up; toggle LED then go back to sleep
  digitalWrite(RED_LED, !digitalRead(RED_LED));  // toggle red LED
  digitalWrite(GREEN_LED, HIGH);  // turn the green LED on
  sleep(999);  // wait for a second (using LPM3 sleep)
  digitalWrite(GREEN_LED, LOW);   // turn the green LED off
  // end loop, loop() will run again putting the chip in LPM4 via suspend()
}


void Interrupt(void)
{
  wakeup();
}

In LPM4 is drawing ~100-200 microamps. It does bounce around. The manufacture states that it should draw about .5 microamps.

 

To make this assessment I've:

  1. Moved to an external 3.3V power source on J12.
  2. Removed all jumpers from J13 (to prevent flow to the debugger).
  3. Specified external power on J10,
  4. and am measuring current on J9

I know that I should be making all unused ports grounded inputs, hence the additional function and the calls to it in setup.

 

Finally, I've run "MSP430FR59xx Demo - RTC_B in LPM3.5 with 2 second wake-up interval" from CSS examples, and do get the expected current draw, using the current measurement technique specified above. 

 

Any idea how to bring that consumption down? 

 

Thanks a lot!

 

Link to post
Share on other sites

 

Thanks spirilis:

 

I've been watching the development of sleep, sleepSeconds, wake, and suspend with great interest because of a project I am working on that demands low power. I appreciate your contributions.

 

Unfortunately, I am not realizing the manufacture's stated current draw on a MSP430FR5969 LaunchPad Rev. 2.0 (modified the Energia boards.txt to make it run at 16 MHz) using the functions. For example, slight modifications to the code you provide above:

void setInputLow(uint8_t port, uint8_t pins) {  volatile uint8_t *out;
  volatile uint8_t *ren;


  /* Get the output register */
  out = portOutputRegister(port);
  /* Get the internal resistor pull up/down register */
  ren = portRenRegister(port);
  
  /* If the port is not a port then return */
  if(out == NOT_A_PORT || ren == NOT_A_PORT) return;
  
  /* Enable the internal pull up/down resistors */
  *ren |= pins;
  /* Clear output register bits to select pull down */
  *out &= ~pins;  
}


void setup()
{
  // Drive all pins low, and set as outputs.
  setInputLow(1, 0xF);
  setInputLow(2, 0xF);
  setInputLow(3, 0xF);
  
  pinMode        (GREEN_LED,OUTPUT);                     //Enable output on P1_6 (onboard green LED)
  pinMode        (PUSH1,INPUT_PULLUP);       //Enable inputs on P1_3 (onboard button)
  pinMode        (RED_LED,OUTPUT);                     //Enable output on P1_0 (onboard red LED)
  attachInterrupt(PUSH1,Interrupt, FALLING); //attach interrupt routine to P1_3
}


void loop() {
  suspend();
  // chip woke up; toggle LED then go back to sleep
  digitalWrite(RED_LED, !digitalRead(RED_LED));  // toggle red LED
  digitalWrite(GREEN_LED, HIGH);  // turn the green LED on
  sleep(999);  // wait for a second (using LPM3 sleep)
  digitalWrite(GREEN_LED, LOW);   // turn the green LED off
  // end loop, loop() will run again putting the chip in LPM4 via suspend()
}


void Interrupt(void)
{
  wakeup();
}

In LPM4 is drawing ~100-200 microamps. It does bounce around. The manufacture states that it should draw about .5 microamps.

 

To make this assessment I've:

  1. Moved to an external 3.3V power source on J12.
  2. Removed all jumpers from J13 (to prevent flow to the debugger).
  3. Specified external power on J10,
  4. and am measuring current on J9

I know that I should be making all unused ports grounded inputs, hence the additional function and the calls to it in setup.

 

Finally, I've run "MSP430FR59xx Demo - RTC_B in LPM3.5 with 2 second wake-up interval" from CSS examples, and do get the expected current draw, using the current measurement technique specified above. 

 

Any idea how to bring that consumption down? 

 

Thanks a lot!

 

 

setInputLow(1, 0xF);

 

Why 0xF?  Wouldn't that just set the lower 4 pins of each port and ignore the upper 4?  e.g. P1.0-P1.3, but not P1.4-P1.7, etc...

 

Also be aware the FR5969 has Port 4 and Port J, be sure to set their pins appropriately.

Link to post
Share on other sites

Much appreciated spirilis!

 

Changing to 0xFF, and setting the 4 and J ports brought the current consumption down to 0.6-0.7 micro amps.

  // Drive all pins low, and set as outputs.
  setInputLow(1, 0xFF);
  setInputLow(2, 0xFF);
  setInputLow(3, 0xFF);
  setInputLow(4, 0xFF);
  // J pins, has to be a cleaner way of doing this...
  pinMode (PJ_0,OUTPUT);
  digitalWrite(PJ_0,LOW);
  pinMode (PJ_1,OUTPUT);
  digitalWrite(PJ_1,LOW);
  pinMode (PJ_2,OUTPUT);
  digitalWrite(PJ_2,LOW); 
  pinMode (PJ_3,OUTPUT);
  digitalWrite(PJ_3,LOW);
Link to post
Share on other sites

Thanks again for the responses to my original question. My program now compiles

and runs correctly. After reading the responses, I would like to measure the amount of

Microamps that are actually being used by the low power modes.  I purchased a

500 ua analog  meter and an 200 ua digital meter. I could not get the digital meter

To work at all. The analog meter appears to work, showing about 200ua of current

When the battery is connected to the breadboarded mspg2553, but the program ceases

To function when the meter is in series. When I remove the meter from the circuit

The program starts running correctly.  If you have a setup that is correctly measuring

Current, please share it. Thanks in advance for any help.      

Link to post
Share on other sites

Yeah often times a current meter that measures small amounts of current use a fairly high-value inline resistor, which will add voltage drop to the circuit which can screw up your circuit's operation depending on how "high" the power consumption can get relative to the amount of capacitance inside the circuit.

 

Good meters use a lower-value inline resistor and have well-designed analog frontends for extracting the infinitessimally small voltage drop that exists across such a resistor and amplifying it into something useful for measuring purposes.  See the "uCurrent" for example - http://www.eevblog.com/projects/ucurrent/ (sorry, link seems a little slow/flaky giving random 503 errors atm)

 

My own meter seems to register around 1uA or sub-1uA with ease, though I can't vouch for its accuracy and I haven't tried it on too many circuits that alternate between ULP and higher-power consumption: EXTECH 420 - http://www.extech.com/instruments/product.asp?catid=48&prodid=271

Link to post
Share on other sites

I've broken down the uCurrent for fun a while ago, it's really simple in design:

there is one opamp to break the supply power into two halves (making a symmetrical supply).

then there is an instrumentation amplifier (a low distortion double opamp essentially) which simply amplifies the voltage over the resistor in the input path.

so it surprises me that it costs $60, because there couldn't be more than $10 in components in there...

Link to post
Share on other sites
so it surprises me that it costs $60, because there couldn't be more than $10 in components in there...

 

Dave actually does a video on how he picked his target price. The video makes alot of sense.

There were a few main points,

  • It's a neice product. Volume isn't particularly high, esspecially compared to typical "consumer" electronics
  • A markup of atleast 2x over the raw cost for him, I believe he actually made the price a tad higher to account for point 1. This allows him to actually make a profit (keep in mind Dave makes a living from youtube)
  • PCB/case/assembly was all done here in Australia, (actually PCBs were possibly from Tasmania I believe) It's always good to support local buisness, and while china might be cheaper, because there isn't any directly competing product he doesn't have to attempt to undercut other market players.

You could run the numbes to get an exact cost for the BOM, but making your own single qty would likely cost more than $60.

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...