|
|
View previous topic :: View next topic |
Author |
Message |
Jody
Joined: 08 Sep 2006 Posts: 182
|
PIC10F206 doesn't wake up after sleep |
Posted: Fri Mar 26, 2010 6:45 am |
|
|
Hello,
I have a 10F206 with a Push Button on B0.
A FET (BS170) at B1.
A servo at B2, and a pull-up (100k) at MCLR to VDD.
Let it do some stuff with a servo and put it to sleep.
Have some strange issues:
Sometime after programming it draws 250mA (turning it off and back on solves this....??). At that moment nothing is connected. No servo no switch. Only a pull-up at the MCLR pin.
What happens.... well when I introduced the sleep instruction.. nothing.
I program the chip and let it run it will NOT wake up when I change a pin.
When I remove the sleep instruction and the PinChangeFlag it will control the servo and the FET. It looks like it will not wake up.
Code included.
Code: |
#include <10F206.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES MCLR //Master Clear pin: enable
#FUSES NOPROTECT //No code protected from reads
#use delay(clock=4000000)
#byte STATUS = 0x003
#bit GPWUF = STATUS.7
int1 PinChangeFlag;
int i;
#define SWITCH PIN_B0
#define FET PIN_B1
#define SERVO PIN_B2
main()
{
PinChangeFlag = GPWUF;
setup_comparator(NC_NC_NC_NC);
while(1)
{
SET_TRIS_b(0x01);
if(!PinChangeFlag)
{
output_high(FET); //servo enable
for(i=0; i <40;i++)//linksom
{
output_high(SERVO);
delay_us(500);
output_low(SERVO);
delay_ms(20);
};
for(i=0; i <40;i++)//rechtsom
{
output_high(SERVO);
delay_us(2500);
output_low(SERVO);
delay_ms(20);
}
}
output_low(FET); //servo disable
sleep();
}
}
|
Regards,
Jody |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19511
|
|
Posted: Fri Mar 26, 2010 7:53 am |
|
|
Three separate things:
First, on these chips, 'wake up', triggers a restart of the program. You need to read 'restart_cause' at the start of your program, and according to what this returns, either perform a normal start, or go straight into your program. The resturned values for this function, are defined in the chip's include file. Test for 'PIN_CHANGE_FROM_SLEEP', to know when you have woken this way. You are trying to do this by directly reading the GPWUF bit, but technically, you are meant to test both bit 4, and bit 7. The compiler instruction does this for you.
Then, you should read the input bit you want to wait on, immediately before sleeping.
Finally, wake up on pin change, needs to be enabled.
setup_counters(T0_INTERNAL,PIN_CHANGE_FROM_SLEEP);
What you post would probably work, if this last is done, but in some circumstances could give anomalous results.
Best Wishes |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Fri Mar 26, 2010 8:20 am |
|
|
Hello Ttelmah,
Thanks for you help....!
first thing: Yes I know that the wake up is a reset. And I want to test why we wakes up... But what do you mean by 'PIN_CHANGE_FROM_SLEEP' is it a compiler function?? I thought that I had to test the bit myself...
second: I now read all the bits but no change about waking up (keeps asleep)
third:setup_counters(T0_INTERNAL,PIN_CHANGE_FROM_SLEEP); is this also a compiler function?
Thanks so far,
Jody |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Fri Mar 26, 2010 8:36 am |
|
|
Oke, what I have so far:
Code: |
#include <10F206.h>
#use fast_io(B)
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOMCLR //Master Clear pin: enable
#FUSES NOPROTECT //No code protected from reads
#use delay(clock=4000000)
//#byte STATUS = 0x003
//#bit GPWUF = STATUS.7
int1 PinChangeFlag, read_b0, read_b1, read_b2, read_b3;
int i, RESTART;
#define SWITCH PIN_B0
#define FET PIN_B1
#define SERVO PIN_B2
#define MCLR PIN_B3
main()
{
RESTART = RESTART_CAUSE();
// PinChangeFlag = GPWUF;
setup_counters(RTCC_INTERNAL,PIN_CHANGE_FROM_SLEEP);
setup_comparator(NC_NC_NC_NC);
while(1)
{
SET_TRIS_b(0x01);
if(RESTART == 0x90)
{
output_high(FET); //servo enable
for(i=0; i <40;i++)//linksom
{
output_high(SERVO);
delay_us(500);
output_low(SERVO);
delay_ms(20);
};
for(i=0; i <40;i++)//rechtsom
{
output_high(SERVO);
delay_us(2500);
output_low(SERVO);
delay_ms(20);
}
}
output_low(FET); //servo disable
read_b0 = input(PIN_B0);
sleep();
}
}
|
Is this the correct way??
It is not working at this moment but I am working on it..... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19511
|
|
Posted: Fri Mar 26, 2010 9:05 am |
|
|
The normal way to use the restart_casue, is like this:
Code: |
void main(void) {
int8 demo_value;
int8 restart_val;
restart_val=restart_cause(); //You must move the value into a
//variable, since on some processors, the flags are reset by the
//function.
if (restart_val==PIN_CHANGE_FROM_SLEEP) {
//Do your 'I have woken' code here
demo_value++;
if (demo_value==10) {
//do a demo to show we have woken up ten times
}
}
else {
//Here the 'reset for other reasons' code - normally you would
//do things like initialise variables etc.
demo_val=0;
}
sleep();
}
|
Key point is that a variable is only 'initialised', when declared, if it is given a value. If not, the compiler leaves it unchanged. So here, I test the restart_cause value, and if it is a 'PIN_CHANGE_FROM_SLEEP', don't initialise the demo_value variable. However in all other cases (watchog, MCLR, power_up etc.), I initialise the value. Then after ten 'wake-ups', I can do something.
This is just to show the 'idea', but gives the basis of how to treat a normal, and a 'sleep' wake-up' differently.
A lot of things don't have to be done when you wake. For instance, TRIS remains set as it was. The comparator remains setup, the wake up ability itself remains enabled. They won't do any harm in your code, but waste time, and in some circumstances might matter.
Also use the defined names, not numbers. Somebody looking at the code later (yourself included), is going to have to work out what '0x90' means, whereas 'PIN_CHANGE_FROM_SLEEP', is largely self documenting....
Best Wishes |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Fri Mar 26, 2010 9:25 am |
|
|
mmmh something like this???:
Code: |
#include <10F206.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOMCLR //Master Clear pin: enable
#FUSES NOPROTECT //No code protected from reads
#use delay(clock=4000000)
#define SWITCH PIN_B0
#define FET PIN_B1
#define SERVO PIN_B2
#define MCLR PIN_B3
main()
{
int1 read_b0;
int i, RESTART;
RESTART = RESTART_CAUSE();
setup_counters(RTCC_INTERNAL ,PIN_CHANGE_FROM_SLEEP);
setup_comparator(NC_NC_NC_NC);
SET_TRIS_b(0x01);
while(1)
{
if(RESTART == PIN_CHANGE_FROM_SLEEP)
{
output_high(FET); //servo enable
for(i=0; i <40;i++)//linksom
{
output_high(SERVO);
delay_us(500);
output_low(SERVO);
delay_ms(20);
};
for(i=0; i <40;i++)//rechtsom
{
output_high(SERVO);
delay_us(2500);
output_low(SERVO);
delay_ms(20);
}
}
output_low(FET); //servo disable
output_low(SERVO);
read_b0 = input(PIN_B0);
sleep();
}
} |
but still it is not working...... pulling mine hairs out............. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 26, 2010 5:45 pm |
|
|
The test program shown below works. If I press a switch which connects
pin B0 to ground, the PIC wakes up from sleep and flashes an LED.
Then it goes back to sleep. Internal pull-ups are enabled, so there is
no external pull-up on the switch. This was tested with PCB vs. 4.073
which comes with MPLAB for free. The code was tested in hardware.
If it doesn't work, make sure that you disconnect your ICD2 from the
board before you do the test. That's necessary. Also make sure that
you haven't accidently clobbered the Calibration Memory value at the
end of the PIC's ROM address. If you're using MPLAB, it will warn you
if this happened, and you can re-program the value back again. Also
be aware that when this PIC wakes up from Sleep, it does a reset.
It doesn't start running from where it went to sleep. It resets.
Code: |
#include <10F206.h>
#fuses NOMCLR
#use delay(clock=4000000)
#define SWITCH PIN_B0
#define LED PIN_B2
#define set_options(value) {#ASM \
MOVLW value \
OPTION \
#ENDASM}
//================================
void main()
{
setup_comparator(NC_NC);
// Enable pull-ups, wake-up on change, and Pin B2 for normal i/o.
set_options(0x1F);
output_high(LED); // Flash an LED
delay_ms(500);
output_low(LED);
sleep();
while(1);
}
|
|
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Sat Mar 27, 2010 7:18 am |
|
|
THANK!!!
As soon I get back into the office I will test it..
Keep you informed!!! |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Mon Mar 29, 2010 6:14 am |
|
|
Great it works....
During sleep the uC draws abour 2mA..... is it possible to reduce this??
Regards,
Jody |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19511
|
|
Posted: Mon Mar 29, 2010 8:25 am |
|
|
It depends on a lot of things.
First, and pin that is 'driving' something, will result in the chip drawing what it needs to drive this target. So you must turn all output pins to the state where they are drawing the least power.
Second, you need to be careful, to not to leave input pins 'floating'. They need to be either resistor biased to the supply rails, connected to something else that does this, or switched to being outputs, if this can be safely done.
Third, how is your power being generated?. Regulator IC?. If so, what does _this_ draw. Many draw several mA, even with no output load. You need to be looking at ultra low quiescent consumption regulators. However you then have a 'caveat', that many of these are more prone to oscillation than the traditional designs, meaning great care must be taken with the layout round these.
Then you need to turn off any peripherals in the PIC, that are still left running. Many go 'off' automatically, but some parts like the ADC, if running off it's own RC clock, still run, and will draw power. In your case, are you using the watchdog when asleep?. If not, then this needs to be switched off. Same applies to the comparator.
You should be able to get consumption of a very few uA.
Look at table 12.1.
Best Wishes |
|
|
|
|
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
|