|
|
View previous topic :: View next topic |
Author |
Message |
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
problem with sleep mode. |
Posted: Mon Jan 27, 2014 9:55 pm |
|
|
Code: | #include <18F4620.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=6144000)
#define LED1 PIN_A0
// global flag to send processor into sleep mode
short sleep_mode;
// external interrupt when button pushed and released
#INT_EXT
void ext_isr() {
static short button_pressed=FALSE;
if(!button_pressed) // if button action and was not pressed
{
button_pressed=TRUE; // the button is now down
sleep_mode=TRUE; // activate sleep
ext_int_edge(L_TO_H); // change so interrupts on release
}
else // if button action and was pressed
{
button_pressed=FALSE; // the button is now up
sleep_mode=FALSE; // reset sleep flag
ext_int_edge(H_TO_L); // change so interrupts on press
}
if(!input(PIN_B0)) // keep button action sychronized wth button flag
button_pressed=TRUE;
delay_ms(100); // debounce button
}
// main program that increments counter every second unless sleeping
void main() {
sleep_mode=FALSE; // init sleep flag
ext_int_edge(H_TO_L); // init interrupt triggering for button press
enable_interrupts(INT_EXT);// turn on interrupts
enable_interrupts(GLOBAL);
while(1)
{
if(sleep_mode) // if sleep flag set
sleep(); // make processor sleep
output_high(LED1); // LED ON
delay_ms(500); // every second
output_low(LED1);
delay_ms(500);
}
} |
measuring current using multimeter. Always shows 7.70mA when i button pressed or not. Why it is not going into sleep mode? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Jan 28, 2014 2:00 am |
|
|
There are several things 'problematical' about this.
Buttons rarely give simple on/off edges. When pressed, you normally get several short make/break pulses over a few uSec. You need to design your hardware, to give clean make/break pulses to have any hope of the current approach working. Now you have a long delay in the interrupt (too long), but the problem is that flags will have been set on the first edge, even if this is not the actual edge the button ends up giving, and worse, this results in interrupts being disabled in the main code during the led on/off delays....
Step back.
Either design the hardware to give clean edges (hardware filtering on the buttons), or rethink, and have the button 'event', trigger an interrupt based delay, and _then_ re-sample. The code needs to only be triggering the sleep, once it _has_ verified that the button is cleanly made.
Then put a 'delay_cycles(1)' after the sleep. The instruction after the sleep is 'pre-fetched' when you go to sleep. ideally it should be a nop (which is what a single cycle delay generates).
Best Wishes |
|
|
jgschmidt
Joined: 03 Dec 2008 Posts: 184 Location: Gresham, OR USA
|
|
Posted: Tue Jan 28, 2014 5:39 pm |
|
|
I'm assuming you are trying to achieve low power sleep. I've had some experience and good results with that and I have several suggestions:
1) To verify that you are truly sleeping, you might just try straight-line code that doesn't require a button press. Do a delay_ms(10000) after main() so you can get a steady reading and then call sleep().
2) You will probably see a reduction in current but less than the spec sheet claims, even if you don't have any other hardware connected. See some suggestions for that below.
3) For detecting button presses I generally use a polled I/O check in my main processing loop. For Inputs held high, I check for an input held low for several consecutive loops. Once that is detected I go and process that button.
4) Once you get your button working you'll need to do several things before calling sleep(). For systems like this I have two functions - HWSetup() to setup the environment for running and HWSleep() to arrange for minimal current sleeping. Depending on what else you have connected to your processor, you need to turn off UARTs, timers, voltage references and ADCs, set the I/O ports so current doesn't flow in or out of the processor, etc. Turn off power to peripherals via relays or pFETs. Set up your conditions for waking up, usually an interrupt and then call sleep().
For my power on/off applications that is followed by interrupt resets and a reset_cpu(), still within the HWSleep() function. The first call in main() is to HWSetup and my application is off and running. You can check to see if you started from a reset or a true cold start with restart_cause().
Microchip publishes some guidance for low power systems and there are posts here and on the Microchip forums related to sleep() which will help you achieve low current sleeping. _________________ Jürgen
www.jgscraft.com |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|