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() and watchdog timer
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Can



Joined: 26 Feb 2012
Posts: 23

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

sleep() and watchdog timer
PostPosted: Tue Mar 06, 2012 2:08 am     Reply with quote

Hello all,

I am trying to put the PIC to sleep under certain conditions and wake it up every once in a while. WDT seems to be a good choice to wake the PIC up from sleep however when it is not sleeping, it keeps resetting the PIC. I am using delays longer than the WDT overflow time so I need to disable the WDT when I don't want it to reset the PIC. For example when the USB is enumerated it should stay awake.

Here is my code:

Code:

void main(){
 
SETUP_ADC(0x07); //internal clock
SETUP_ADC_PORTS(0x0B); //AN0->AN3

  delay_ms(100);
  ds1307_init();
 
  init_ext_eeprom();

   // Initialize USB CDC (this sets line coding and clears buffers).

   usb_cdc_init();

   // Initialize USB subsystem.
   // Since we are not using sense pin, this will not wait indefinitely.
   usb_init_cs(); //I've also tried usb_init() but no luck

   delay_ms(1000);

output_high(PIN_B5); //Power up the RTC
output_high(PIN_B4); //Power up the EEPROM

   while(true){   

      // Sense USB status.
      usb_task();
      //delay_ms(100);
setup_wdt(wdt_off);
     if(usb_enumerated()){
       setup_wdt(wdt_off);
       output_low(pin_B6);
        output_high(pin_B5);
       // Get_Data();
         if(usb_cdc_kbhit()){
            getItem();
            showSub();
         }
     } else{

      output_low(pin_B5);   
      output_high(pin_B6);
      //Put the PIC to sleep if no USB connection
      setup_wdt(wdt_on);
      restart_wdt();
      sleep();
      delay_cycles(1);
     
     }
 
   }
}


In my fuses I tried different things like WDT128, WDT, and since I read somewhere that setup_wdt(wdt_on) can only be used while #NOWDT is set (I can not remember where I've read it), I even tried the #NOWDT.

What I want the code to do is: If there is no USB connection do some stuff (which is going to be to read the adc and timestamp it and write it to EEPROM, yet to be implemented)-> go to sleep -> wake up -> check the USB connection -> if there is a connection, don't go to sleep...

I can't figure out what i am doing wrong.
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 2:33 am     Reply with quote

What PIC.....
The abilities of both the fuses and setup_wdt, vary with the PIC.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 2:46 am     Reply with quote

Watchdogs are intended to reset processors in the event that something goes wrong and normal processing stops. Its not a general purpose timer. Its a watch dog timer. If enabled, it resets the processor when it times out. You MUST keep resetting (kicking) during normal processing to keep the watchdog alive.

So, the watchdog is not an appropriate resource to use while the processor is sleeping.

What is? Any event that would generate an interrupt will bring the processor out of sleep. Apparently, interrupts don't even have to be enabled, but the cause of interrupt shuld be dealt with in the normal way (e.g. read port b if it was an "interrupt on change". It makes more sense if you think of an interrupt as a request for action, thereby forcing the processor out of sleep so that it can take the relevant action.

Its generally counter productive to consider sleep as sleeping for some particular time. Timers ARE useful for bringing the processor out of sleep, but because they produce known time intervals, but because they can bring the processor out of sleep periodically to poll for some state in case action is required. If it isn't you can aimply go back to sleep.

"I am trying to put the PIC to sleep under certain conditions and wake it up every once in a while. "

Instead of this, its probably better better to think of putting the PIC to sleep if there's nothing useful to do and wake it up when there is something (as indicated by an interrupt), or once in a while in case there's something to do (on a timer). In your case you need it to wake up any any USB activity.

One question: Do you really need it to sleep? Is this USB powered? What is your power source? Do you really need the power savings of sleep? If not, try to make things simpler: don't sleep.

RF Developer.
Can



Joined: 26 Feb 2012
Posts: 23

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

PostPosted: Tue Mar 06, 2012 3:10 am     Reply with quote

RF_Developer and Ttelmah thank you for your replies.

I am using an 18F2550.

My intention is to realize a datalogger. It is going to run on batteries so I need it to be power efficient. I want to gather data like every minute or every 5 minutes whatever.. So i need to get the PIC to sleep.

However I don't want it to go to sleep when I attach the USB for dumping the data to PC.

Thank you
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 3:26 am     Reply with quote

Have you got a USB connection sense pin?.
If not, it is not going to work.

Problem is that USB _requires_ it's responses in a very limited time scale. Now if your system is asleep, and you then attach it to a PC, it'll probably still be asleep when the PC tries to enumerate. Problem.

However what you want can be done, with the connection sense pin. If this is connected to B0, you can program an interrupt on the rising edge of this to 'wake' you up, ready to service the enumeration request. The loop can then test for 'usb_is_attached', and remain awake so long as this is so.

If you need intermittent wake up while asleep, this should be available using the watchdog, but details will depend on your chip, so same comment at before 'what chip'.

Best Wishes
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 3:27 am     Reply with quote

OK 18F2550. Will look up the details for this.

Best Wishes
Can



Joined: 26 Feb 2012
Posts: 23

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

PostPosted: Tue Mar 06, 2012 3:32 am     Reply with quote

Ttelmah, I wasn't using a USB connection sense pin. I will try to arrange it in the hardware and see if it works. So I suppose I have to program an external interrupt on pinB0. I have to figure out how to do it. I am a total stranger to the interrupts Embarassed

Edit: The problem with using the pinB0 is that it is already utilized for i2c communications.. Is it possible to program another pin for the external interrupt?

Thank you,
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 3:56 am     Reply with quote

OK. 2550.

From the fuses in the data sheet:

"WDTEN: Watchdog Timer Enable bit
1 = WDT enabled
0 = WDT disabled (control is placed on the SWDTEN bit)"

So the watchdog has to be disabled, for control in software.
However prescaler is in the fuses.

So:

Code:

#include <18F2550.h>
#fuses NOWDT, WDT128 //Plus your clock settings etc..
//clock definitions etc here
#define USB_CON_SENSE_PIN PIN_B0

//Then the USB includes
#include <stdlib.h>
#define __USB_PIC_PERIF__ 1
#include <usb_cdc.h>

void main(void) {
   SETUP_ADC(ADC_CLOCK_INTERNAL); //internal clock
   //Are you really using this - are you aware of the accuracy limitations
   //DATA sheet table 21-1 Note 3
   SETUP_ADC_PORTS(AN0_TO_AN3); //AN0->AN3

   delay_ms(100);
   ds1307_init();
 
   init_ext_eeprom();

   // Initialize USB CDC (this sets line coding and clears buffers).

   usb_cdc_init();

   usb_init_cs(); //I've also tried usb_init() but no luck

   delay_ms(1000);

   output_high(PIN_B5); //Power up the RTC
   output_high(PIN_B4); //Power up the EEPROM

   while(true){   

      // Sense USB status.
      if (usb_attached) {
         usb_task();
         if (usb_enumerated()) {
            output_low(pin_B6);
            output_high(pin_B5);
            // Get_Data();
            if(usb_cdc_kbhit()){
               getItem();
               showSub();
               //Question at this point. Do these routines take longer than
               //about 10mSec total?. usb_task _must_ be called regularly
            }
         }
      }
      else {
          //Suspend code 
          output_low(pin_B5);   
          output_high(pin_B6);
          //Put the PIC to sleep if no USB connection
          restart_wdt();
          setup_wdt(wdt_on);
          disable_interrupts(global);
          enable_interrupts(INT_EXT);
          ext_int_edge(L_TO_H);
          clear_interrupt(INT_EXT);
          //Final check USB is not attached
          if (!usb_attached()) {
               sleep();
               delay_cycles(1);
          }
          disable_interrupts(INT_EXT);
          setup_wdt(WDT_OFF);
          enable_interrupts(GLOBAL);
      }
   }
}


The key problem is that you need to wake ASAP if USB is attached. You _need_ the sense pin, and to generate a hardware interrupt when this goes true.

Best Wishes
temtronic



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

View user's profile Send private message

PostPosted: Tue Mar 06, 2012 6:28 am     Reply with quote

Hmm. Battery powered datalogger with USB...ok..

1) How much power are you actually using ? My 4550 version draws next to nothing on the 'reality scale' except when flashdrive is writing. Microchip has a great appnote about battey powered loggers (old but valid today). I use 4 high capacity Li-I batteries and should get years of continuous use.
You may not actually 'need' the make the PIC go to sleep.

2) "output_high(PIN_B5); //Power up the RTC "
I have to ask why ? Can we infer the RTC doesn't have battery backup and that the RTC doesn't really keep real time ?

3) Are you running 5 volt or 3 volt. Going 3 reduces power consumed but you can't go as fast. Clock speed ? Slower saves power.
Can



Joined: 26 Feb 2012
Posts: 23

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

PostPosted: Wed Mar 07, 2012 2:06 pm     Reply with quote

I am really sorry about the late reply, I forgot my codes at my workplace so I couldn't try anything Embarassed

After your heads up, I measured the current consumption and it is like 50 mA. So i suppose with 3000 mAH batteries I can run 60 hours approximately?

"output_high(PIN_B5); //Power up the RTC " was a setup for reducing power consumption. Because the EEPROM, RTC and PIC is going to be running on the same power source. So there is no need for the EEPROM and RTC to be powered if the PIC is sleeping.

I am using 4x1,5 batteries passing through a 5 V regulator for the PIC. So it can run on batteries as well as USB power.

As for the clock speed I use
#use delay(clock=48000000).

As the Murphy laws kicked in in every single opportunity, I am not tampering with the code that is running too much.

I haven't tried the putting to sleep and waking up the PIC yet. I will inform as soon as I try.

Thank you.
Can



Joined: 26 Feb 2012
Posts: 23

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

PostPosted: Wed Mar 07, 2012 3:18 pm     Reply with quote

Well I mostly tried the sleep and wake up part.

My final code is like the following:

Code:

#include <18F2550.h>
#DEVICE ADC=8
#fuses HSPLL,NOWDT,WDT4096,MCLR,NOPROTECT,NOLVP,NODEBUG,NOBROWNOUT,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#define USB_CON_SENSE_PIN PIN_B2 //Because B0 and B1 are for SDA and SCL

#include "usb_cdc.h"

void main(){

SETUP_ADC(0x07); //Seems like I am using this and I couldn't figure out the accuracy limitation?! Man I suck at reading datasheet, my table 21-1 only has 2 notes.. Tad vs. device operating frequencies
SETUP_ADC_PORTS(0x0B); //AN0->AN3
   delay_ms(100);
  ds1307_init();
 
init_ext_eeprom();
   // Initialize USB CDC (this sets line coding and clears buffers).
   usb_cdc_init();

   // Initialize USB subsystem.
   // Since we are not using sense pin, this will not wait indefinitely.
   usb_init_cs();

   delay_ms(1000);


 
   while(true){
      usb_task();
 
  if(usb_attached()){
     if(usb_enumerated()){
     // Get_Data();
      if(usb_cdc_kbhit()){
      getItem();  //Actually getItem receives an input from the user via the terminal but I don't have problems while using it
         showSub();
      }
     }
     
     output_high(pin_B6);
     } else {
     output_low(pin_B6);
               //Suspend code
          //Put the PIC to sleep if no USB connection
          restart_wdt();
          setup_wdt(wdt_on);
          disable_interrupts(global);
          enable_interrupts(INT_EXT);
          ext_int_edge(L_TO_H);
          clear_interrupt(INT_EXT);
          //Final check USB is not attached
          if (!usb_attached()) {
          output_low(pin_b5);
               sleep();
               delay_cycles(1);
          }
          usb_task();
          output_high(pin_b5);
          disable_interrupts(INT_EXT);
          setup_wdt(WDT_OFF);
          enable_interrupts(GLOBAL);
      }
         
   }
}


The code puts PIC to sleep (with 4.5 mA of power consumption) and wakes it up every once in a while. However I couldn't figure out how to wake the PIC up on USB connect. I had to put the usb sense pin to B2 because B0 and B1 are already occupied. With this code I have to wait for PIC to wake up in order to have a usb connection.
Can



Joined: 26 Feb 2012
Posts: 23

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

PostPosted: Fri Mar 09, 2012 1:46 am     Reply with quote

I've managed to write data to the EEPROM after sleeping through WDT128. Data seems ok and there is no problem. When I try WDT32768, the PIC wakes up like every minute, writes some data and goes back to sleep, however when I look at the data, it is all nonsense gibberish. The readings from the RTC gets messed up, they are giving data like 197/89/52;12:06:53; 02/56/89;09:03:12; and 02/34/89;07:25:04.

I tried putting a ds1307_init(); after the sleep but no luck. Also I saw that there was data missing in my all-night test. So I thought after a sleep that long, the EEPROM and RTC needs to be initialized again. I put initialize commands after sleep but they caused more problems...What am I missing here?
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Fri Mar 09, 2012 2:27 am     Reply with quote

To wake on B2, you need to use INT_EXT2_L2H, instead of INT_EXT.
Also get rid of the int edge setting.

How is the 1307 connected and powered?.
You show power being disconnected from the DS1307 - "Power up the RTC ".
What battery voltage are you using on the sustain battery (there can be problems if this is not in the range the chips requires).
4.5mA!... That is foul, Seriously I'd be expecting _uA_ sleep currents. You have something in your circuitry drawing power that should not be drawn. Key things are:
1) Ensure every line on the PIC is driven to the state which draws least power. Either by the chip itself (driving them as outputs), or by external circuitry (chips or resistors). Lines that float _will_ cause excess power to be drawn.
2) Make sure you are genuinely switching off the external parts when you sleep.
3) How is your supply generated?. A lot of traditional 5v regulators, have minimum consumptions that are very significant when asleep. Even worse, some can start oscillating when loads are low.

Best Wishes
Can



Joined: 26 Feb 2012
Posts: 23

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

PostPosted: Fri Mar 09, 2012 2:57 am     Reply with quote

I tried the configuration disconnecting the RTC and EEPROM but the power consumption was almost the same, so the RTC and EEPROM are connected to the regulator directly. I am using a 7805 as a regulator, I suppose some of the consumption is caused by that.
I suppose the pins for which I haven't defined the tris register stay floating. I will set them as outputs and see how it affects the consumption.
Best,
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Fri Mar 09, 2012 3:14 am     Reply with quote

Seriously, _most_ of your consumption is from the 7805. This is not the regulator to use for low power applications. You want something like the LM2936 as a 'drop in' replacement for this (assuming 100mA is OK). The consumption of a 7805, with an output load under 5mA, is quoted as 6mA typical. It has 0.5mA quiescent, _once the load rises over 5mA_, but below this the current does not significantly drop. The 78L05 (100mA version), has 3 to 5mA typical quiescent as well....).
On the RTC, what battery are you using?. This _needs_ to be present, and the chip needs to have it's supply removed. It draws typically 1.5mA if left running, with the I2C bus still active (which means data could be corrupted), while switched off, the consumption drops to under 1uA.....

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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