View previous topic :: View next topic |
Author |
Message |
starfire151
Joined: 01 Apr 2007 Posts: 195
|
remaining problem with wdt / sleep |
Posted: Sun Jun 03, 2007 3:34 pm |
|
|
I'm using a PIC18LF2525 at 10MHz with the internal X4 PLL for 40MHz op.
CCS compiler version 3.249
I created a testbed program to examine the interactions with different parameters of the #fuses WDTxxxxx, where xxxxx was 32768, 16384, and 8192. I initially had the #fuses NOWDT set, also.
The program was the following simple loop (used #fuses WDT8192):
Code: |
...
printf("Init completed successfully\r\n");
printf("delay_ms(200)\r\n");
printf("#fuses WDT8192\r\n");
printf("watchdog enabled...\r\n");
setup_wdt(WDT_ON);
while(TRUE)
{
printf("doing 1 second delay...\r\n");
delay_ms(1000);
printf("going to sleep...\r\n");
sleep();
delay_ms(100);
printf("waking from sleep... %u\r\n", i++);
}
}
|
The output looked like this:
Init completed successfully
delay_ms(200)
#fuses WDT8192
watchdog enabled...
doing 1 second delay...
Cáwaking from sleep... 0
doing 1 second delay...
Cáwaking from sleep... 1
doing 1 second delay...
Cáwaking from sleep... 2
doing 1 second delay...
Cáwaking from sleep... 3
doing 1 second delay...
Cáwaking from sleep... 4
doing 1 second delay...
Why is the printf() after the delay_ms(1000) not being printed?
Would someone please post a code example of how to set up and use the WDT this way? I would like to have an executing backgorund loop, put the system to sleep for a period of time, have the system wake back up, and resume where it left off. I can't use any external stimulus to wake it (like EXT0) and I can't modify the circuit to include an external 32768 crystal for Timer1.
With this set up, #fuses WDT8192 gave about a 34 second delay, #fuses WDT16384 gave about a 68 second delay, and #fuses WDT32768 gave about a 136 second delay. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 03, 2007 4:10 pm |
|
|
Post the missing lines of the test program. Post the #include, #fuses
and #use statements. Post the main() and the variable declarations.
The program should be able to be copied and pasted into MPLAB and
then compile without errors. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Sun Jun 03, 2007 8:00 pm |
|
|
complete .c file: Code: |
#include <sleep_wdt.h>
// ---- variable definitions ----
int i;
#zero_ram
void main(void)
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
port_b_pullups(TRUE);
set_rtcc(0);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED, 0, 1);
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
delay_ms(200); // system stability time
i = 0;
printf("Init completed successfully\r\n");
printf("delay_ms(200)\r\n");
printf("#fuses WDT8192\r\n");
printf("watchdog enabled...\r\n");
setup_wdt(WDT_ON);
while(TRUE)
{
printf("doing 1 second delay...\r\n");
delay_ms(1000);
printf("going to sleep...\r\n");
sleep();
delay_ms(100);
printf("waking from sleep... %u\r\n", i++);
}
}
|
complete sleep_wdt.h file: Code: |
#include <18F2525.h>
//#include <18F2620.h>
#device *=16
#device ICD=TRUE
#device adc=10
#FUSES NOWDT // No Watch Dog Timer
//#FUSES WDT // Watch Dog Timer
#FUSES WDT8192 // Watch Dog Timer uses 1:8192 Postscale
#FUSES H4 // High speed osc with 40MHz osc
#FUSES NOPROTECT // Code not protected from reading
#FUSES IESO // Internal External Switch Over mode enabled
#FUSES NOBROWNOUT // No brownout reset
#FUSES BORV20 // 18F2525 Brownout reset at 2.0V
//#FUSES BORV21 // 18F2620 Brownout reset at 2.1V
#FUSES PUT // Power Up Timer <<< COMMENT OUT FOR DEBUGGING >>>
//#FUSES NOPUT // No Power Up Timer <<< COMMENT OUT FOR NORMAL OP >>>
#FUSES NOCPD // No EE protection
#FUSES STVREN // Stack full/underflow will cause reset
#FUSES NODEBUG // No Debug mode for ICD <<< COMMENT OUT FOR DEBUGGING >>>
//#FUSES DEBUG // Debug mode for ICD <<< COMMENT OUT FOR NORMAL OP >>>
#FUSES NOLVP // No low volt prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT // Program memory not write protected
#FUSES NOWRTD // Data EEPROM not write protected
#FUSES NOEBTR // Memory not protected from table reads
#FUSES NOCPB // No Boot Block code protection
#FUSES NOEBTRB // Boot block not protected from table reads
#FUSES NOWRTC // configuration not registers write protected
#FUSES NOWRTB // Boot block not write protected
#FUSES FCMEN // Fail-safe clock monitor enabled
#FUSES NOXINST // Ext set exten and Index Addr mode disabled (Legacy mode)
#FUSES MCLR // Master Clear pin enabled
#use delay(clock=40000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
|
thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 03, 2007 9:18 pm |
|
|
Quote: | #include <18F2525.h>
//#include <18F2620.h>
#device *=16
#device ICD=TRUE
#device adc=10
#FUSES NOWDT // No Watch Dog Timer
//#FUSES WDT // Watch Dog Timer
#FUSES WDT8192
|
You have a "#device ICD=TRUE" line above. According to the MPLAB
help file for the ICD2:
Quote: | The Watchdog Timer (WDT) cannot be used when debugging. |
Comment out or delete that line.
Also you have a "#device *=16" line. That option doesn't apply to 18F
PICs. It's for 16F PICs. Delete that line.
I don't have your PIC to test. I tested the program with an 18F4550,
and it works. Though, I ran it at 4 MHz, and without the PLL.
The WDT8192 period is rather long. I timed it at about 38 seconds.
I'm stating that in case you weren't aware of it. |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Sun Jun 03, 2007 10:30 pm |
|
|
I made the modifications, per your suggestion. I get the following output:
Init completed successfully
delay_ms(200)
#fuses WDT8192
watchdog enabled...
doing 1 second delay...
Cáwaking from sleep... 0
doing 1 second delay...
going toCáwaking from sleep... 1
doing 1 second delay...
going toCáwaking from sleep... 2
doing 1 second delay...
going toCáwaking from sleep... 3
doing 1 second delay...
Cáwaking from sleep... 4
doing 1 second delay...
going to sleep..Cáwaking from sleep... 5
doing 1 second delay...
going to sleep..Cáwaking from sleep... 6
doing 1 second delay...
going to sleep..Cáwaking from sleep... 7
doing 1 second delay...
Notice the inconsistency in output and the bogus characters with partial lines being printed.
Is there something else besides just placing a sleep() statement in the code and having the watchdog wake it up? It seems the program continues from where it left off but some data is getting corrupted. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 03, 2007 11:57 pm |
|
|
I was able to get rid of the extra characters "Cá" by adding a short
delay before going to sleep. Add the line shown in bold below.
Quote: |
while(TRUE)
{
printf("doing 1 second delay...\r\n");
delay_ms(1000);
printf("going to sleep...\r\n");
delay_ms(5); // Allow time to xmit last two chars
sleep();
delay_ms(100);
printf("waking from sleep... %u\r\n", i++);
} |
|
|
|
Ttelmah Guest
|
|
Posted: Mon Jun 04, 2007 2:28 am |
|
|
It is perhaps worth explaining 'why' PCM Programmer added the delay.
His 'remark', explains why, but this may not be clear unless you understand the hardware.
The RS232 stops when the chip goes to sleep. There can be up to 1.999... untransmitted characters in the hardware, when a 'printf' returns. (basically, the chips has one character of buffering, plus the 'output shift register', containing the character currently being transmitted - this should have only just started being transmitted, so fractionally 'under' a second character in the hardware). At 9600bps, these could need up to 2.083mSec to send. Hence PCM, is delaying to _ensure_ that these characters are sent, before triggering the sleep. '5mSec', is a safe 'overkill'.
An alternative, if you wanted to just delay 'as long as necessary', rather than erring on the side of safety, would be:
Code: |
#byte TXSTA=0xFAC //Address of the UART transmit status register
#bit TRMT=TXSTA.1 //Bit reflecting transmit shift register status
#define wait_for_RS232_to_complete() while(TRMT==0)
|
Called as the line:
wait_forRS232_to_complete();
Will wait till the UART's buffers _are_ empty, and no longer.
Best Wishes |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
|
Posted: Mon Jun 04, 2007 8:44 am |
|
|
Excellent! Thanks, I will try that tonight.
Thanks very much for taking the time to address the issue and, more importantly, to address the reason for the issue...
So is the small time delay I've added after the sleep() (the 100ms time delay) necessary? I inserted it to allow the system enough time to have the internal clocks stabilize before attempting a print out. Was this incorrect? |
|
|
Ttelmah Guest
|
|
Posted: Mon Jun 04, 2007 9:07 am |
|
|
The 'PUT' fuse already gives a delay.
This makes the system wait for typically 65mSec, after the oscillator is stable.
Best Wishes |
|
|
starfire151
Joined: 01 Apr 2007 Posts: 195
|
watchdog / sleep problem solved... |
Posted: Mon Jun 04, 2007 5:47 pm |
|
|
I tried the suggestion of inserting the 5 ms delay before the sleep() and I removed the 100 ms delay after the sleep(). I worked perfectly! I got the following results:
delay_ms(200)
#fuses WDT8192
watchdog enabled...
doing 1 second delay...
going to sleep...
waking from sleep... 0
doing 1 second delay...
going to sleep...
waking from sleep... 1
doing 1 second delay...
going to sleep...
waking from sleep... 2
doing 1 second delay...
going to sleep...
waking from sleep... 3
doing 1 second delay...
going to sleep...
waking from sleep... 4
doing 1 second delay...
going to sleep...
waking from sleep... 5
doing 1 second delay...
going to sleep...
I will additionally try it with the #define wait_for_RS232_to_complete() (as suggested by Ttelmah), as this looks to be a little more efficient and I wouldn't have to change the delay value dependant on the baud rate.
Thanks, again, for the help! |
|
|
|