CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

sleep mode in 12f683

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mahdihir



Joined: 01 Dec 2013
Posts: 7
Location: Iran

View user's profile Send private message Send e-mail

sleep mode in 12f683
PostPosted: Tue Jan 13, 2015 3:55 am     Reply with quote

Hi
I’m working on project with 12f683, the purpose is to get sample from ADC every 10 sec and if the sample is bigger than X, do something.
The problem is I need to save energy as much as possible for battery life,
Is it possible to put MCU in sleep mode for 10 sec and after that wake up MCU for 10ms to get sample from ADC and go back to sleep?
thanks
40inD



Joined: 30 Jul 2007
Posts: 112
Location: Moscow, Russia

View user's profile Send private message

PostPosted: Tue Jan 13, 2015 10:08 am     Reply with quote

Set WDT to closest round value and do sleep() so much times to get 10 s delay then reset cpu:

Example from my program:
Code:

            setup_wdt(WDT_2304MS);

   ....... 
   {
            sleep();    // 2.3s
            sleep();    // 4.6s
            sleep();    // 6.9s
            sleep();    // 9.2s
           
            reset_cpu();
    }
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jan 13, 2015 10:22 am     Reply with quote

just be aware that the WDT is run from the internal 31KHz osc and is NOT precise !! You'll have to experiment to get reasonable,repeatable operation.
VDD, temperature, initial calibration all affect the timing AND each PIC is different.

For a 'one-off' project , not a big deal , but for a 'commercial' product, you're best to use a proper xtal/caps.
Jay
mahdihir



Joined: 01 Dec 2013
Posts: 7
Location: Iran

View user's profile Send private message Send e-mail

PostPosted: Wed Jan 14, 2015 2:32 am     Reply with quote

thanks a lot
but my problem is the sleep mode is in the middle of program, once WDT reset the MCU and goes to the first line of program and i want to continue after sleep instruction, the rest of program.

Code:
void main()
{ ...
while ()
{ ...

/////////// half of program/////////////

sleep();

///////////the rest of program//////////
...
}
}

thanks
40inD



Joined: 30 Jul 2007
Posts: 112
Location: Moscow, Russia

View user's profile Send private message

PostPosted: Thu Jan 15, 2015 2:13 am     Reply with quote

In SLEEP mode WDT does not reset cpu, just continue program. Read dataheet.
that's why I add reset_cpu() in my program above.
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Thu Jan 15, 2015 3:46 am     Reply with quote

First of all, don't reset the cpu.
It's bad practice. A reset should only happen when there is good cause.

What happens on a watchdog, changes between chips. Some of the very early PIC12's, will always physically restart on a watchdog. However most modern ones won't. Old line _read the data sheet_.....

Section 12.7 on the data sheet for your PIC, says:

"The device can wake-up from Sleep through one of the
following events:
1. External Reset input on MCLR pin.
2. Watchdog Timer wake-up (if WDT was
enabled).
3. Interrupt from GP2/INT pin, GPIO change or a
peripheral interrupt.
The first event will cause a device Reset. The two latter
events are considered a continuation of program
execution. The TO and PD bits in the STATUS register
can be used to determine the cause of a device Reset.
The PD bit, which is set on power-up, is cleared when
Sleep is invoked. TO bit is cleared if WDT wake-up
occurred."

Now, see how an external MCLR causes a reset, but "the two latter events are considered a continuation of program execution". Exactly what you need to know.

So your code structure should be something like:
Code:

#include <12F683.h>
#fuses NOMCLR, NOWDT //wake up without watchdog.
#device ADC=10
#use delay(internal=4000000) //4MHz internal clock
#use rs232 (XMIT=PIN_A2, baud=9600) //minimum RS232 setup for debugging

void main()
{
   int16 adc_val;
   setup_adc(ADC_CLOCK_DIV_8); //correct ADC clock for 4MHz
   setup_adc_ports(sAN0); //sampling on A0, Vss to Vdd as ref
   
   while(TRUE)
   {
      delay_us(10); //ensure ADC has acquired
      adc_val=read_adc(); //read the value
      //Now for debug, just send to RS232 as voltage
      printf("Reading %4.2lw\n\r",(adc_val*49)/100);
      //gives an _integer_ conversion to 0-500 from 0-1023
      //Now we want to sleep
      restart_wdt(); //just ensure the WDT does not occur in the next couple of instructions
      setup_wdt(WDT_2304MS | WDT_ON); //start the watchdog
      sleep();
      delay_cycles(1);
      sleep();
      delay_cycles(1); //each sleep will clear the watchdog when called
      sleep();
      delay_cycles(1);
      //Now approximately 6.9 seconds have passed
      setup_wdt(WDT_OFF); //stop the watchdog
      //and loop back to read the ADC
   }
}

You have to be careful that the watchdog does not trigger when you are not asleep, or the chip will reset. Since you don't know what count is in the watchdog register, I clear it _before_ starting the watchdog.
This is coded to run off the internal 4MHz clock, and send the ADC reading out as a 0 to 5.00 (will actually go to 5.01) value on the RS232, using integer maths for size/speed.

Hopefully gives you an idea of how to do what you want.
mahdihir



Joined: 01 Dec 2013
Posts: 7
Location: Iran

View user's profile Send private message Send e-mail

PostPosted: Sun Jan 25, 2015 3:00 am     Reply with quote

thanks,
its working properly.

my another question is, i setup a ADC to get sample every 2.3 min, and if the value is bigger than MIN, do something,
is my code correct?
Code:

#include <12F683.h>
#device ADC=10
#fuses LP,NOPUT,NOPROTECT,NOCPD,NOMCLR
#FUSES WDT                    //No Watch Dog Timer
#FUSES PUT                      //Power Up Timer
#FUSES PROTECT                  //Code protected from reads
#FUSES CPD                      //Data EEPROM Code Protected
#FUSES NOBROWNOUT               //No brownout reset
#use delay(INTERNAL=31000)
#define GP0 PIN_A0
#define GP1 PIN_A1
#define GP2 PIN_A2
#define GP3 PIN_A3
#define GP4 PIN_A4
#define GP5 PIN_A5
#define BUTTON    PIN_A3
#define BUTTON_PRESSED  input(BUTTON)

int16  i, value, n, m, j, o;
float32 min, max;
void init()
                  {
                  setup_wdt(WDT_2304MS);
                set_tris_a( 0b00000001 ); // set GP0 input, GP1 output, GP2 output, GP3 output GP4 output, GP5 output
                setup_comparator( NC_NC_NC_NC ); // disable comparators
                setup_adc_ports( AN0_ANALOG ); // enable analog inputs
                setup_adc(ADC_CLOCK_INTERNAL);            // Built-in A/D setup function
                set_adc_channel(0); // Built-in A/D setup function
           //     setup_vref(VREF_HIGH | 8);//sets 3.6(vdd * value/32 + vdd/4) if vdd is 5.0V
              //  setup_timer_0(off)
             //   setup_timer_1(T1_DISABLED);
                value = read_adc();
                  }
void main()
 {

while(TRUE) {

 output_high (PIN_A1); 
           setup_adc_ports(sAN0);
           setup_adc(ADC_CLOCK_DIV_4);
           value=0;

           value = read_adc();
           setup_adc(ADC_OFF);
                 if(value<min)
                  {
                    goto loop1;
         
                  }
           delay_ms(30);

           output_low(PIN_A1);
            restart_wdt();
           sleep();

}
loop1
...
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Sun Jan 25, 2015 4:26 am     Reply with quote

1) Move the setup_adc_ports outside the loop.
There must always be Tacq, between using the setup_adc_ports, and reading the adc. This is what the delay_us at the start of my loop, is there for.
2) Forget float. Unless you absolutely 'have to', FP should not be used when an integer will do. FP, is bulky, slow, and inaccurate. For things like financial calculations they are never used because of the errors. Remember the value from the ADC, is just an integer count. int16 is what you should be using. If you want to work with a 'number' that has some direct relevance to volts, then consider multiplying, so that the integer, gets scaled to represent mV.
3) You have the watchdog enabled in hardware. Again look at how I do it. The watchdog is _not_ enabled, till it is to be used. You have a very high risk now of a watchdog occurring while you are awake. Particularly because of 4 below.
4) You are now using a very slow clock. Slightly 'pointless', since all it does is makes the time spent awake, longer. The effect on consumption, will actually be to make it worse!. At 3v, the chip draws typically 500uA at 4MHz, and 16uA at 31KHz. 31.25* as much, _but_ it executes code 129*faster. So you end up drawing more power running at the slower speed (4* as much to execute the same code....). Use the slower speed, if you are wanting to keep the chip awake. If you are sleeping, look at which processor speed gives the best performance per uA. The slow clock will make things take an age. The FP comparison, will take nearly 1/10th second at 31KHz. If your routine reached after the comparison does anything more than sneeze, you will end up having a watchdog restart in this - since you are leaving the watchdog running. Because you have it enabled in the fuses _it cannot be turned off_. Read the data sheet. Look at what the WDTE bit does.
5) Don't 'goto'. Using goto, in some computer courses is treated as a 'capital' offence. You should really never need to use it (there are a few situations in embedded programming, primarily related to interrupts/recovery, where it may be used), but otherwise treat this instruction as if it doesn't exist. It is _not_ a primary part of C, but is only there for those odd occasions. As it stands, depending on whether you want to get back into the loop, you may well end up with the processor stack becoming unbalanced. It is a very easy way to shoot yourself in the foot.
6) At your slow clock, the ADC will take over 6mSec to perform the conversion. A very long way outside it's recommended operating range (57* slower than the recommended slowest operation). This will degrade it's accuracy appallingly.
guy



Joined: 21 Oct 2005
Posts: 297

View user's profile Send private message Visit poster's website

PostPosted: Sun Jan 25, 2015 2:26 pm     Reply with quote

PIC12F683 also supports Ultra Low Power WakeUp (ULPWU). If you connect in series a 130 ohm resistor from GP0 - to a 10nF capacitor - to GND you can have the PIC charge and discharge the cap to keep track of time while in sleep mode. Power consumption is less than 1uA (much less than the WDT).
GP0 >-----/\/\/\/\----||--- GND
Another thing to look out for - disconnect the cap when programming in-circuit (GP0 is also ICSPDAT).

Let me know if you want me to post the code - I don't think the feature is supported by the compiler. It also requires calibration using the internal oscillator - the code takes care of everything.
mahdihir



Joined: 01 Dec 2013
Posts: 7
Location: Iran

View user's profile Send private message Send e-mail

PostPosted: Mon Jan 26, 2015 5:43 am     Reply with quote

My friend
thanks for your help.
I have done what you said from No 1 to 4.
But for No5 and 6, can you explain more? did you mean I should change [spam] from 31k to 4M?
The battery life is the most important factor in my project.
Thanks
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jan 26, 2015 6:35 am     Reply with quote

re: #5 xtal value.
yes, you should use the 4 MHz xtal instead of the 32KHz xtal. Although the PIC will consume more power at the higher frequency, it gets the program done and back to sleep a LOT faster than the 'slow'(32KHz) PIC will. Overall the 'fast' PIC will SAVE energy.
Microchip has an application note(AN606) you should read. It deals with 'low power design' and is well worth reading.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Mon Jan 26, 2015 8:14 am     Reply with quote

I'll elucidate just a bit.

Consumption, is power*time. Power is volts*current. Assume 3v.

Assume the 'awake' code is 1000 instructions long (the number doesn't matter). At 31KHz, this will take (4428ips), 0.226 seconds. At 4MHz (1mips), it'll take 1mSec. When awake at 4MHz, it'll draw 500uA. When awake at 31Khz, it'll draw 16uA. Total consumption to run the 'awake' code at 31KHz = 3*0.226*16uA = 10.8uW. At 4MHz, = 3*0.001*500uA = 1.5uW. Total battery consumption 7.2* _less_ running the code at 4MHz....

The chip runs less efficiently at the low clock rate. Where the low clock would be used, is if you were keeping the chip awake all the time, so that it could perhaps keep time. Given that the low clock also takes your ADC out of spec, it's a 'no brainer', to use the faster clock.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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