Pages: [1] 2   Go Down
Author Topic: Help with Programming Arduino Uno to sleep and wakeup with FSR sensor  (Read 2601 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello Everyone, I m a newbie, and i m working on a small project using arduino Uno. I want my arduino to be on Idle mode to save power since i will be recharging my battery from time to time. I would also want to write a program that will put my arduino to sleep and then activate it with FSR sensor. Based on all my readings and research from this site, i came across with the code at below, but i did not fully understand the code and i hopping that someone will take a look at the code and tell me if the code is what i needed or if i need more code to add into it for it serve my purpose. I would also like to use LED to show the interrupt . For example; i would like my code to show LED red light on when it is on IDLE mode and when FSR sensor is pressed, the green LED will be on showing that arduino is fully active. I also understand that the code uses Interrupt on Pin 2 to wake up.

#include <avr/sleep.h>      // powerdown library
#include <avr/interrupt.h>  // interrupts library

//***************************************************
// *  Name:        pin2Interrupt, "ISR" to run when interrupted in Sleep Mode
void pin2Interrupt()
{
  /* This brings us back from sleep. */
}
//***************************************************

//***************************************************
// *  Name:        enterSleep
void enterSleep()
{
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(0, pin2Interrupt, LOW);  // << LOW, HIGH, FALLING, RISING I think are valid
  delay(50); // need this?
  /* the sleep modes
   SLEEP_MODE_IDLE - the least power savings
   SLEEP_MODE_ADC
   SLEEP_MODE_PWR_SAVE
   SLEEP_MODE_STANDBY
   SLEEP_MODE_PWR_DOWN - the most power savings
   */
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // setting up for sleep ...
  sleep_enable();                       // setting up for sleep ...
  sleep_mode();                         // now goes to Sleep and waits for the interrupt

  /* The program will continue from here after the interrupt. */
  detachInterrupt(0);                 //disable interrupts while we get ready to read the keypad

  /* First thing to do is disable sleep. */
  sleep_disable();

  // then go to the void Loop()
}
//***************************************************


//***************************************************
// within void loop() call this ...

    enterSleep();                         // call Sleep function to put us out
                                                  //  THE PROGRAM CONTINUEs FROM HERE after waking up in enterSleep()
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can't use an analog device, like an FSR, to generate an input that wakes the Arduino. A digital device, yes.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can't use an analog device, like an FSR, to generate an input that wakes the Arduino. A digital device, yes.

Thanks for your input, but how can generate an input that wakes the Arduino through digital device?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Exactly how depends on a number of factors. Generating a RISING, FALLING, or LOW interrupt all can be done, depending on how the switch is wired. Which type(s) of interrupt wake the Arduino is the question.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi zajebiscie,

That's a cool project you got there. Well first I agree with PaulS, you should first convert the analog signal into a digital one,a simple comparator with a defined threshold may be used. If you want to avoid debouncing  a Schmidt trigger or a latch are very useful. Regarding to your code it seems so be very complete, but I would rather prefer to call sleep_disable() before detachInterrupt(0). This way you can assure that your system will be awake and the CPU clock cycles will be running, and after the processor is awake then you call the detachinterrupt(0). Detaching the interrupt after it awakes is a good idea, this way the interrupt won't be called until your Arduino is sleeping. Nowtalking about you LED indicator you can set it as an output and modify it in your enterSleep() function. Set it LOW before it goes to sleep and set it HIGH when it wakes up. By the way,you can also use CHANGE for generating the interrupt. Here below I add the modificationes I would recommend for your code:

#include <avr/sleep.h>      // powerdown library
#include <avr/interrupt.h>  // interrupts library

//***************************************************
void setup(){
pinMode(13,OUTPUT); //The LED indicator is in pin 13, change it to your needs
}

// *  Name:        pin2Interrupt, "ISR" to run when interrupted in Sleep Mode
void pin2Interrupt()
{
  /* This brings us back from sleep. */
}
//***************************************************

//***************************************************
// *  Name:        enterSleep
void enterSleep()
{
  /* Setup pin2 as an interrupt and attach handler. */
  attachInterrupt(0, pin2Interrupt, LOW);  // << LOW, HIGH, FALLING, RISING I think are valid. Here you can also use GHANGE that it is a
                                                          //combination of FALLING OR RISING (activated in both cases)
  delay(50); // need this? This depends how you want to deal with your sleep times
  /* the sleep modes
   SLEEP_MODE_IDLE - the least power savings
   SLEEP_MODE_ADC
   SLEEP_MODE_PWR_SAVE
   SLEEP_MODE_STANDBY
   SLEEP_MODE_PWR_DOWN - the most power savings
   */
  digitalWrite(13,LOW); // LED is turned off when it goes to sleep
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // setting up for sleep ...
  sleep_enable();                       // setting up for sleep ...
  sleep_mode();                         // now goes to Sleep and waits for the interrupt

  /* First thing to do is disable sleep. */
  sleep_disable();

/* The program will continue from here after the interrupt. */
  detachInterrupt(0);                 //disable interrupts while we get ready to read the keypad

  digitalWrite(13,HIGH); //LED is turned off when it wakes up and it's fully active

  // then go to the void Loop()
}
//***************************************************


//***************************************************
// within void loop() call this ...

    enterSleep();                         // call Sleep function to put us out
                                                  //  THE PROGRAM CONTINUES FROM HERE after waking up in enterSleep()

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Exactly how depends on a number of factors. Generating a RISING, FALLING, or LOW interrupt all can be done, depending on how the switch is wired. Which type(s) of interrupt wake the Arduino is the question.

Thanks for your help. There is no clock associated with the project, but all i wanted my arduino to do is to go to sleep (idle) when not in use, and i want to use FSR sensor to interrupt by waking up the arduino while pressing the FSR sensor, and as soon as FSR sensor is release, it will go back to sleep(idle) and move a motor to clockwise. Below is a code i have been working on for the past two days, please could you take a look at it and see if i m missing anything. thanks

Code:
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/io.h>
//
void setup(void)
{
DDRD &= B00000011; // set Arduino pins 2 to 7 as inputs, leaves 0 & 1 (RX & TX) as is
DDRB = B00000000; // set pins 8 to 13 as inputs
PORTD |= B11111100; // enable pullups on pins 2 to 7
PORTB |= B11111111; // enable pullups on pins 8 to 13
pinMode(13,OUTPUT); // set pin 13 as an output so we can use LED to monitor
digitalWrite(13,HIGH); // turn pin 13 LED on

}
//
void loop(void)
{
// Stay awake for 1 second, then sleep.
// LED turns off when sleeping, then back on upon wake.
delay(100);
sleepNow();
}
//
void sleepNow(void)
{

/* Now is the time to set the sleep mode. In the Atmega8 datasheet
* http://www.atmel.com/dyn/resources/prod ... oc2486.pdf on page 35
* there is a list of sleep modes which explains which clocks and
* wake up sources are available in which sleep modus.
*
* In the avr/sleep.h file, the call names of these sleep modus are to be found:
*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*
* the power reduction management <avr/power.h> is described in
* http://www.nongnu.org/avr-libc/user-man ... power.html
*/
// Set pin 2 as interrupt and attach handler:
attachInterrupt(0, pinInterrupt, LOW);
delay(100);
//
// Choose our preferred sleep mode:
set_sleep_mode(SLEEP_MODE_IDLE);
//
// Set sleep enable (SE) bit:
sleep_enable();
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
//
// Put the device to sleep:
digitalWrite(13,LOW); // turn LED off to indicate sleep

sleep_mode();
//
// Upon waking up, sketch continues from this point.
sleep_disable();
digitalWrite(13,HIGH); // turn LED on to indicate awake

}
//
void pinInterrupt(void)
{
detachInterrupt(0);
}

« Last Edit: December 14, 2012, 02:02:57 am by Nick Gammon » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Stuff about sleep:

http://gammon.com.au/power


And interrupts:

http://gammon.com.au/interrupts

Quote
... could you take a look at it ...

Can you use the auto-format tool to indent things please?

Next time please post your code inside code tags. Select the code and hit the # button above the posting area.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
// Stay awake for 1 second, then sleep.
// LED turns off when sleeping, then back on upon wake.
delay(100);

One second is 1000 mS not 100.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
// Stay awake for 1 second, then sleep.
// LED turns off when sleeping, then back on upon wake.
delay(100);

One second is 1000 mS not 100.

Thanks very much for the correction. I posted my code as you said. So, please can you or another person take look and see if i m on right track with the code at the below...thanks.

Code:
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/io.h>
//
void setup(void)
{
DDRD &= B00000011; // set Arduino pins 2 to 7 as inputs, leaves 0 & 1 (RX & TX) as is
DDRB = B00000000; // set pins 8 to 13 as inputs
PORTD |= B11111100; // enable pullups on pins 2 to 7
PORTB |= B11111111; // enable pullups on pins 8 to 13
pinMode(13,OUTPUT); // set pin 13 as an output so we can use LED to monitor
digitalWrite(13,HIGH); // turn pin 13 LED on

}
//
void loop(void)
{
// Stay awake for 1 second, then sleep.
// LED turns off when sleeping, then back on upon wake.
delay(100);
sleepNow();
}
//
void sleepNow(void)
{

/* Now is the time to set the sleep mode. In the Atmega8 datasheet
* http://www.atmel.com/dyn/resources/prod ... oc2486.pdf on page 35
* there is a list of sleep modes which explains which clocks and
* wake up sources are available in which sleep modus.
*
* In the avr/sleep.h file, the call names of these sleep modus are to be found:
*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*
* the power reduction management <avr/power.h> is described in
* http://www.nongnu.org/avr-libc/user-man ... power.html
*/
// Set pin 2 as interrupt and attach handler:
attachInterrupt(0, pinInterrupt, LOW);
delay(100);
//
// Choose our preferred sleep mode:
set_sleep_mode(SLEEP_MODE_IDLE);
//
// Set sleep enable (SE) bit:
sleep_enable();
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
//
// Put the device to sleep:
digitalWrite(13,LOW); // turn LED off to indicate sleep

sleep_mode();
//
// Upon waking up, sketch continues from this point.
sleep_disable();
digitalWrite(13,HIGH); // turn LED on to indicate awake

}
//
void pinInterrupt(void)
{
detachInterrupt(0);
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What is attached to the interrupt pin? What is generating the interrupt? Your not still trying to use an FSR, are you?

Quote
I posted my code as you said.
No
you
did
not!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Stuff about sleep:

http://gammon.com.au/power


And interrupts:

http://gammon.com.au/interrupts

Quote
... could you take a look at it ...

Can you use the auto-format tool to indent things please?

Next time please post your code inside code tags. Select the code and hit the # button above the posting area.

Thank you very much for the site. Based on the example code from that site, i put together a code that will work for my small project, but i m not sure if i m on the right track. Please could you take a look at the code and see if i m doing it correct way. I m planning to use FSR sensor to interrupt from pin2 and it will stays on while someone is holding the sensor, and then arduino will go back to idle as soon as the FSR sensor is realeas.

Code:
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/io.h>

const byte LED = 9;
  
void wake ()
{
  // cancel sleep as a precaution
  sleep_disable();
}  // end of wake

void setup ()
  {
  digitalWrite (2, HIGH);  // enable pull-up
  }  // end of setup

void loop ()
{
 
  pinMode (LED, OUTPUT);
  digitalWrite (LED, HIGH);
  delay (50);
  digitalWrite (LED, LOW);
  delay (50);
  pinMode (LED, INPUT);
  
  // disable ADC
  ADCSRA = 0;  

  // turn off various modules
  PRR = 0xFF;
  
  set_sleep_mode (SLEEP_MODE_IDLE);  
  sleep_enable();

  // will be called when pin D2 goes low  
  attachInterrupt (0, wake, LOW);
 
  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);
  MCUCR = _BV (BODS);
  sleep_cpu ();  
  
  // must do this as the pin will probably stay low for a while
  detachInterrupt (0);
  
  } // end of loop

« Last Edit: December 15, 2012, 03:15:35 pm by Nick Gammon » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Isn't an FSR a force sensitive resistor? Which is an analog device? Interrupts only work on digital changes (eg. high to low) so I wouldn't think an FSR is suitable, unless you hook it up to a comparator before the interrupt pin.

Quote
Please could you take a look at the code and see if i m doing it correct way.

Try it and see ...
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Isn't an FSR a force sensitive resistor? Which is an analog device? Interrupts only work on digital changes (eg. high to low) so I wouldn't think an FSR is suitable, unless you hook it up to a comparator before the interrupt pin.

Quote
Please could you take a look at the code and see if i m doing it correct way.

Try it and see ...

Thanks Nick Gammon for your quick reply. Yes FSR is a force sensitve resistor. Please Nick Gammon, do you know or have a direction on how to connect FSR to comarator and then before connecting it to interrupt pin?
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 93
Posts: 3968
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can't use an analog device, like an FSR, to generate an input that wakes the Arduino. A digital device, yes.

Very much to my surprise, this can be done and it works exceedingly well! I have a project with several tactile button switches and an FSR. It sleeps in power down mode; I wanted any button or the FSR to wake it. I treat the FSR identically to the buttons, I have the internal pullups enabled and use pin change interrupts to wake the µC. I use the same library for debouncing and sensing the FSR and the buttons. Actually, for this project I never use the FSR as an analog device, since I just want to know if it's "pressed" or not.

Going in to the project, I of course assumed that I would have to treat the FSR as an analog device. But in a moment of weakness (and temporary insanity), I thought I'd try just treating it the same as the switches, nothing to lose really. I was amazed when it worked perfectly. Maybe I got lucky, maybe the characteristics of the FSR I chose, the way it's being loaded, and the hysteresis provided by the AVR all just lined up perfectly, so YMMV, but it works just great for me.
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, Jack. I'm not totally surprised. If the voltage from the FSR when not pressed is quite high (eg. 4V) and when pressed is quite low (eg. 2V) then that effectively could be treated as a digital signal, because the digital inputs would have a "transition" zone (around 2.5V) where above that is considered high, and below is considered low.
Logged

Pages: [1] 2   Go Up
Jump to: