I apologize if this topic has been previously covered but I could not find after searching for alitte while.
I am using a PIC 16F676, ICD2, PICBASIC Pro, internal 4Mhz RC osc.
Basically I am using the PIC to measure temperature and pressure, display them to an Optrex LCD and then place the PIC in sleep mode to conserve battery power.
The problem is the first pass through the code the sleep command is either skipped (highly unlikely) or somehow times out instantly prior to one of the two wake-up methods and continues on to the next pass. The two methods are 1) WTD based on the PBP sleep command or 2) an external interrupt which can wake up the PIC before the WDT exits the sleep command. After the first pass it works fine, i.e. it goes to sleep, if I only allow the wake-up to be WDT based. If I wake it up with the ext int it exhibits the same behavior as the first pass and will then work on the next pass. This is very strange.
I have also tried using only the ext int, turning off the WDT and using @sleep only to get the same results: does not go to sleep in the first pass but will after the second pass. Code is below. Any assistance will be greatly appreciated.
' Set LCD data port to PORTC
DEFINE LCD_DREG PORTC
'Set starting data bit to 4
DEFINE LCD_DBIT 0
'Set LCD register select bit to PORTC
DEFINE LCD_RSREG PORTC
'Set LCD register select bit to bit 4
DEFINE LCD_RSBIT 4
'Set LCD enable port
DEFINE LCD_EREG PORTC
'Set enable bit
DEFINE LCD_EBIT 5
TRISA.5 = 0 'Set PORTA BIT 5 to output, Voltage reg enable/disable
PORTA.5 = 0
TRISA.4 = 0 'Set PORTA BIT 4 to output to be on/off for LCD and temp sensor power
PORTA.4 = 1
'Set clock speed
'DEFINE OSC 4
TEMP VAR word
t0 VAR TEMP.byte0
t1 VAR TEMP.byte1
w0 VAR word
w1 VAR word
w2 var word
DEPTH VAR word
d0 VAR DEPTH.byte0
d1 VAR DEPTH.byte1
RA2 var bit
i var byte
TRISA.1 = 1 'Set PORTA BIT 1 to input
ANSEL.1 = 1 'Select PORTA bit 1 to analog input for Temp Sensor
TRISA.0 = 1 'Set PORTA BIT 0 to input
ANSEL.0 = 1 'Select PORTA bit 0 to analog input for Pressure Sensor
TRISA.2 = 1 'Set PORTA BIT 2 to input
ANSEL.2 = 0 'Be sure PORTA BIT 2 is a digital input for Ext Int Wake Up
option_reg.6 = 0 ' set interrupt to occur on falling edge
intcon.4 = 1 ' enable external interrupt
ADCON1 = %01010000 'Set A/D clock source to 16Tosc
'to ensure sufficient conversion time
MAIN:
for i = 1 to 20
pause 1000
' Temperature measurement
ADCON0 = %10000101 'result is right justified, Vref = external (using 1.024V at present)
'select RA1, enable but not start A/D.
PAUSEUS 25 'A/D acquisition time for sample and hold circuit
ADCON0.1 = 1 'Start A/D conversion
WHILE PIR1.6 == 0 'wait for A/D conversion to finish
WEND
ADCON0.0 = 0 'disable A/D converter to save power
PIR1.6 = 0 'reset interrupt flag
' Place results into TEMP variable
t0 = ADRESL
t1 = ADRESH
' approximate resolution is 4.86mV/ct. Since no floating point
' routines in PBP use fixed point math and keep track of decimal
TEMP = TEMP *54 ' Want to multiply by 486 but too many issues arrise from PBP inability to have variables longer than 16-bits
w0 = TEMP / 10000
w1 = TEMP // 10000
w0 = w0 * 9
w1 = (w1 / 10) * 9 'Remainder seems to be 4 places so divide by 10 first to keep the *9 confined to a 16-bit number
w0 = w0 + w1 DIG 3 ' Whole number plus most significant digit of remainder hand waving
w1 = w1 DIG 2 ' Next significant digit of remainder as the temths decimal place
Lcdout $fe, 1 'Clear LCD screen
Lcdout "T= ", DEC w0,".",DEC w1,"C"
' Pressure or Depth measurement
ADCON0 = %10000001 'result is right justified, Vref = Vdd
'select RA0, enable but not start A/D.
PAUSEUS 25 'A/D acquisition time for sample and hold circuit
ADCON0.1 = 1 'Start A/D conversion
WHILE PIR1.6 == 0 'wait for A/D conversion to finish
WEND
ADCON0.0 = 0 'disable A/D converter to save power
PIR1.6 = 0 'reset interrupt flag
d0 = ADRESL
d1 = ADRESH
'DEPTH = DEPTH - 38 'Subtract offset ~0.183v = ~38 counts
'DEPTH = DEPTH * 44
'DEPTH = DEPTH / 128
'DEPTH = DEPTH *110
'w0 = DEPTH / 169
'w1 = DEPTH // 169
Lcdout $fe, $C0 'Clear LCD screen
Lcdout "D= ", DEC d0 ',".",DEC w1
next i
Lcdout $fe, 1 'Clear LCD screen
Lcdout "ENTERING"
Lcdout $fe, $C0 'Clear LCD screen
Lcdout "SLEEP"
PAUSE 500
' PORTA.5 = 0 'Turn off power to pressure sensor
PORTA.4 = 0 'Turn off power to temp sensor and LCD
TRISC = %000000
PORTC = 0 'Place all output to zero for zero current draw
sleep 300
intcon.1 = 0
PORTA.4 = 1
' PORTA.5 = 1
CLEAR 'Clear all RAM including system RAM. This is important
'because it clears the FLAGS register that includes the
'LCDINITFLAG. The LCDINITFLAG is SET to indicate that
'the LCD has been initialized by the LCDOUT command. But since exiting SLEEP is a
'WatchDog timeout reset which just resumes normal operation
'the LCDINITFLAG is still SET so that when power is restored
'to the LCD the program thinks its initialized and LCDOUT does
'not attempt to re-initialize, which is not good!
asm
clrf 32h
endasm
pause 1000
Lcdout $fe, 1 'Clear LCD screen
Lcdout "End Loop"
GOTO MAIN
Bookmarks