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

Long delay using watchdog timer

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



Joined: 26 Jan 2008
Posts: 11

View user's profile Send private message

Long delay using watchdog timer
PostPosted: Sat Jan 26, 2008 12:40 pm     Reply with quote

Hi all.

I have a PIC16f690 that must use the lowest possible power for as long periods of time (up to an hour). I would like to utilise the watchdog timer, which has a max time of 268 seconds, in the following way -

initially set timing variable = 6

device is asleep

WDT wake from sleep (268 sec)

decrement timing variable

is timing variable == 0?
if yes, perform_function()
else, sleep (for another 268 sec)

repeat.

Would this be possible? I would like to change the timing variable in "perform_function()" so that the duration my "pseudo-sleep" can be dynamically changed.

Cheers.
Ttelmah
Guest







PostPosted: Sun Jan 27, 2008 10:36 am     Reply with quote

Yes, totally possible, and a common solution.
Big caveat though, is that the times will _not_ be accurate. The WDT on your chip, runs from the LFINTOSC, which is an uncalibrated oscillator, and varies massively between chips, and with temperature/voltage. The range quoted in the data sheet, is 15KHz, to 45KHz, for the 'nominally' 31KHz oscillator. As such the '268' second selection, may vary to as little as 184 seconds, and up to 553 seconds.....
If you want accurate times, then I'm afraid you need to use timer1, and add an external crystal, or use an external RTC module.

Best Wishes
peter-storm



Joined: 26 Jan 2008
Posts: 11

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 4:51 pm     Reply with quote

Thanks, Ttelmah.

The precision isn't particularly important to me, so I have gone ahead and written the following:

Code:

#include <16f690.h>
#fuses HS, WDT, NOPROTECT, BROWNOUT

#use delay(clock=8000000)
#use rs232(baud=19200,parity=N,xmit=PIN_B7,rcv=PIN_B5,bits=8)

#include <vl1001.c>


int timer = 5;
int delay = 500;

void main(){

setup_adc_ports(NO_ANALOGS|VSS_VDD);// This is because by default
                                      //the AD inputs are analogs
setup_adc(ADC_OFF);// switch off the internal ADC module
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_2304MS|WDT_TIMES_8);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);
setup_uart(UART_WAKEUP_ON_RDA);
   


set_tris_c(0x00); // set portC as output




output_toggle(PIN_C0);


if (timer == 1){
output_toggle(PIN_C1);
timer = 5;
}
else
timer--

}


However, C1 doesn't toggle every 5 toggles of C0, and I fear that the variable timer is being reset to 5 every time the PIC's WDT kicks in.

How would I make it not reset the value every time?

Cheers
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 5:03 pm     Reply with quote

Quote:
int delay = 500;

In CCS, an 'int' is an unsigned 8-bit integer. Use 'long' or 'int16' instead.
Both are 16-bit unsigned integers in CCS.
peter-storm



Joined: 26 Jan 2008
Posts: 11

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 5:24 pm     Reply with quote

PCM programmer wrote:
Quote:
int delay = 500;

In CCS, an 'int' is an unsigned 8-bit integer. Use 'long' or 'int16' instead.
Both are 16-bit unsigned integers in CCS.


Oh ok, thanks for the info. The delay variable isn't used in this example, but I'll use int16 for future code.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 5:49 pm     Reply with quote

Code:
if (timer == 1){
output_toggle(PIN_C1);
timer = 5;
}
else
timer--
Your code now loops 4 times. If you want to loop 5 times, than change to
Code:
if (timer == 0){
...
An additional advantage of this change is shorter code. Comparing with 0 takes fewer instructions than comparing to any other value.
peter-storm



Joined: 26 Jan 2008
Posts: 11

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 6:02 pm     Reply with quote

ckielstra wrote:
Code:
if (timer == 1){
output_toggle(PIN_C1);
timer = 5;
}
else
timer--
Your code now loops 4 times. If you want to loop 5 times, than change to
Code:
if (timer == 0){
...
An additional advantage of this change is shorter code. Comparing with 0 takes fewer instructions than comparing to any other value.

Thanks for the info, but the main issue I have is that PIN_C1 is not changing - the "if" statement is never satisfied, and I cannot work out why.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 6:04 pm     Reply with quote

Quote:
How would I make it not reset the value every time?

Don't initialize 'timer' above main(). Just declare it.
Example:
Code:
int8 timer;

Initialize it at the start of main(). But, qualify the init with
a call to the restart_cause() function. If it's a normal power-on
reset, then set 'timer' to 5. If not, then don't touch it. Use an 'if'
statement to do this test. So when a WDT reset occurs, 'timer'
will not be set to 5.
See this file for an example of using restart_cause():
Quote:
c:\program files\picc\examples\ex_wdt.c
peter-storm



Joined: 26 Jan 2008
Posts: 11

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 6:10 pm     Reply with quote

PCM programmer wrote:
Quote:
How would I make it not reset the value every time?

Don't initialize 'timer' above main(). Just declare it.
Example:
Code:
int8 timer;

Initialize it at the start of main(). But, qualify the init with
a call to the restart_cause() function. If it's a normal power-on
reset, then set 'timer' to 5. If not, then don't touch it. Use an 'if'
statement to do this test. So when a WDT reset occurs, 'timer'
will not be set to 5.
See this file for an example of using restart_cause():
Quote:
c:\program files\picc\examples\ex_wdt.c


Thank you very much, this has worked!

Thanks again to all that have contributed.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 6:16 pm     Reply with quote

Actually, since you could have a Brownout reset, you should probably
change the test to look specifically for a WDT reset. Skip the init only
in that case. Do the init for all other types of reset. That would be
a more complete way to do it. (After thinking a little more about it).
peter-storm



Joined: 26 Jan 2008
Posts: 11

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 6:24 pm     Reply with quote

You have a good point, so I have replaced the NORMAL_POWER_UP: with default:, that should do the trick?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 27, 2008 6:44 pm     Reply with quote

I think that will do it. Don't do anything in the WDT case. Just break.
In the default case, set timer to 5, then break. Only the WDT and default
cases should be in the switch statement.
n-squared



Joined: 03 Oct 2006
Posts: 99

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Sun Jan 27, 2008 11:34 pm     Reply with quote

Hi,
If I may add my two cents worth:
It is good practice to check for boundaries in real time systems.
That means that if the timer variable is not 1 to 5, you want to "bring it back home".
The way I implement such a timer is to start at zero and upcount and test for value 5 or greater:
Code:

  if (++timer >= 5)
    {
    timer = 0;
    output_toggle(PIN_C1);
    }

This method will prevent counting 100 or 200 cycles if noise caused the variable to go wild.
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