Cant get to sleep

Discuss PIC and electronic related things

Moderators: David Barker, Jerry Messina

Post Reply
Overclocked
Posts: 21
Joined: Mon Oct 13, 2008 9:53 pm
Location: CT

Cant get to sleep

Post by Overclocked » Wed Jul 29, 2015 12:34 am

Im using a PIC18F13K22 for data logging purposes. I have a 32kHz crystal on timer one with 2 10pf caps. It interrupts once per second and counts how many seconds go by, until it reaches a if statement so it can do more things. I want it to sleep while its waiting for the interrupt, but cant figure out how to do it. The datasheet says to clear OSCCON bit 7 to 0 and then issue the sleep command. I do that and nothing happens. I dont have anything planned for my main loop because everything is done in the interrupt routine. . Current consumed doesn't go down. Without sleep its consuming 910uA. Everything else works, except sleep.

Here is my Code.

Code: Select all

{
*****************************************************************************
*  Name    : Dataloger_C.BAS                                                *
*  Author  : Chris S                                                        *
*  Notice  : Copyright (c) 2015 Open Source                                 *
*          : All Rights Reserved                                            *
*  Date    : 7/22/2015                                                      *
*  Version : 1.0                                                            *
*  Notes   :    TX on Micro goes to RX on transmitter                       *
*          :   AN2, AN4 and AN5 Are Available ports                         *
*          : TO DO: FVR (2.048v) on All channels.                           *
*          : FVR Varies. Check against theoretical (2.048) value and then   *
*          : Subtract the measured value to get the difference.             *
*          : Call this Var "MeasuredFVR" and "TheoreticalFVR"               *
*          : DeltaFVR=Theoretical-Measured                                  *
*          :RealFVF=Theoretical-Delta if less than Theo                     *
*          :RealFVR=Theoretical+Delta if More than Theo  
*^^^ This wont work                                                                *
*          : Check battery voltage once per hour. Same with Solar Cell      *
*****************************************************************************
}

//Relavent settings
// ADCON0 Settings
// ADCON0= %00001000 = Channel 2
// ADCON0= %00010000 = Channel 4
// ADCON0= %00101000 = Channel 5
//
//ANSEL Settings
//ANSEL.3 = 1 For channel 4
//ANSEL.5 = 1 For Channel 5
//
//TRISA Settings
//TRISA.5 = 1 For Channel 5

Device = 18F13K22
Clock = 4
Include "IntOSC.bas"
Include "USART.bas"
Include "utils.bas"
Include "convert.bas"
Include "ADC.bas"
Config FOSC = IRC

Dim
    Channel2 As Integer, //changed datatypes from word to avoid negative number errors
    Channel4 As Integer,
    Channel5 As Integer,
    TMR1IE As PIE1.0, // TMR1 Interrupt Enable
    TMR1IF As PIR1.0, // TMR1 Interrupt Flag
    Timer1 As TMR1L.AsWord, // A quick way of creating a Word Alias
    Seconds As Byte,
    Minutes As Byte,
    Hours As Byte,
    Days As Word, //179 Years before this fills up...
    Years As Byte
   

 
//Const 
// TMR1StartVal = $80, // User defined TMR1 starting value
// TMR1ReloadVal = TMR1StartVal + 5
 
 
 
Interrupt TMR1_Interrupt()
 Save(0) // Back up system variables
 If TMR1IF = 1 Then
    TMR1IF = 0 // Clear the TMR1 Interrupt
    T1CON.0 = 0 //Turn timer 1 off
    TMR1H = $80 //Preload high byte with 128
    TMR1L = 0   // Preload Low byte with 0
    T1CON.0 = 1 // timer 1 on
    Seconds= Seconds +1
    //USART.Write (DecToStr(Seconds,2),13,10)      //Just a test string. Can be deleted in final version.
    If Seconds = 10 Then   //count to 59. Take ADC reading
        TRISA.2 = 1 //set channel 2 as a input
       //read channel 2 
        ADCON0= %00001000  //channel 2 as ADC input
        ANSEL.2 = 1 // Channel 2
        ADCON0.0 = 1  //enable ADC                
        ADCON0.1 = 1 //GOGOGOGO
        While ADCON0.1 = 1
            ADResult = (ADRESL)
        Wend
        
        Channel2 = ((ADResult+ 1) * 500) / 1024    //MATHMATICAL!
        Channel2 = Channel2 - 50 //Subtract 50 to get the current temp in C
        
        //Next Channel
        TRISA.4 = 1 //set channel 4 as input
        ADCON0= %00010000 //Channel 4
        ANSEL.3 = 1 //Channel 4
        ADCON0.0 = 1  //enable ADC                
        ADCON0.1 = 1 //GOGOGOGO
        While ADCON0.1 = 1
            ADResult = (ADRESL)
        Wend
        
        Channel4 = ((ADResult+ 1) * 500) / 1024    //MATHMATICAL!
            //Place holder for Math for Battery.
                         
        //USART.Write ("Channel 2: ",DecToStr(Channel2 / 100), ".", DecToStr(Channel2, 2), " ",13,10)
        USART.Write ("Current Temp: ", DecToStr(Channel2), " ",13,10)
        USART.Write ("Battery Voltage: ", DecToStr(Channel4), " ",13,10)
        Seconds = 0
        Minutes = Minutes + 1  
        USART.Write ("Minutes:",DecToStr(Minutes,2),13,10)
    End If 
    
    If Minutes = 59 Then  //Count up hours
        Hours = Hours + 1
        Minutes = 0
        USART.Write ("Hours:",DecToStr(Hours,2),13,10)
    End If   
    
    If Hours = 24 Then
        Days = Days + 1
        Hours = 0
        USART.Write ("Days:",DecToStr(Days,3),13,10)
    End If  
    
    If Days = 365 Then
        Years = Years +1
        Days = 0
        USART.Write ("Years:",DecToStr(Years,2),13,10)
    End If  
    
 EndIf 
 Restore // Restore system variables
 

End Interrupt 
 
  
Sub TMR1_Initialize()
 TRISC.0 = 1 // If External clock, then set clock as an input
 T1CON.0 = 0 // Timer 1 off
 TMR1H = $80 //Preload with 128
 TMR1L = 0   // 
 T1CON.0 = 1 // timer 1 on
 T1CON.1 = 1 // 1 = External clock from pin RC0/T1OSO/T1CKI (on the rising edge)
             // 0 = Internal clock (FOSC/4)
    
 T1CON.2 = 0 // 1 = Do not synchronize external clock input   
 // 0 = Synchronize external clock input
 // When T1CON.1 = 0;
 // this bit is ignored.
 T1CON.3 = 1
 T1CON.4 = 0 
 T1CON.5 = 0 
 T1CON.6 = 0 
 T1CON.7 = 0 
 TMR1IE = 1 // Enable TMR1 Interrupts

 Enable(TMR1_Interrupt) // Enable TMR1 Interrupt Handle
End Sub 

 
// Start Of Main Program...

Seconds = 0
Minutes = 0
Hours = 0
Days = 0
Years = 0 
Channel2 = 0
Channel4 = 0
TMR1_Initialize // Setup and enable TMR1
USART.SetBaudrate(br9600) 
//TRISA.2 = 1 //set channel 2 as a input
//TRISA.4 = 1 //set channel 4 as input
ADCON2 =%10110001 //12 TAD, FOSC/8

While True
OSCCON.7 = 0
  
    Asm
        
        sleep
        Nop
         Nop
    End Asm 
Wend
The intOC just contains this:

Code: Select all

Config fosc = IRC
OSCCON = %11010011

Jerry Messina
Swordfish Developer
Posts: 1245
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Cant get to sleep

Post by Jerry Messina » Wed Jul 29, 2015 11:43 am

First off, I'd make sure any unused IO pins are set for digital mode and output low.
If you leave any of them as floating inputs that can cause current to go up.

Here's a routine with some of the pins setup to show what I mean... add any others you might need

Code: Select all

sub iopin_setup()

// set pin mode
// 0=digital, 1=analog (default)
ANSEL.0 = 0 		// RA0
ANSEL.1 = 0 		// RA1
ANSEL.2 = 1 		// RA2 (analog input ch2)
ANSEL.3 = 1 		// RA4 (analog input ch4)
ANSEL.4 = 0 		// RC0
ANSEL.5 = 0 		// RC1
ANSEL.6 = 0 		// RC2
ANSEL.7 = 0 		// RC3

ANSELH.0 = 0		// ANS8 RC6
ANSELH.1 = 0		// ANS9 RC7
ANSELH.2 = 0		// ANS10 RB4
ANSELH.3 = 0		// ANS11 RB5


// set unused pins as outputs
// RA2 input, RA4 input
TRISA = %00010100
TRISB = %00000000
TRISC = %00000000

// set unused output pins low
PORTA = 0
PORTB = 0
PORTC = 0

end sub
Also, you don't have to actually use the interrupts with sleep mode, you can just use the TMR1IF to wake you up.
That may make it easier to see if you're actually sleeping or not. It'll also save you a few instructions, so less power.

change the timer code in the existing interrupt routine to a normal sub...
from

Code: Select all

Interrupt TMR1_Interrupt()
 Save(0) // Back up system variables
 
 // ********** keep all the existing code 
 If TMR1IF = 1 Then
   <snip>
 EndIf
 // ********** keep all the existing code 

 Restore // Restore system variables

End Interrupt
to

Code: Select all

Sub TMR1_Seconds()
 
 // <<paste existing code here>>
 If TMR1IF = 1 Then
   <snip>
 Else  // could add a message here to make sure it was TMR1IF
   UART.Write("**unknown wakeup event**")
 EndIf

End Sub
Get rid of the interrupt enable in the TMR1_Initialize() routine...

Code: Select all

 'Enable(TMR1_Interrupt) // Enable TMR1 Interrupt Handle
and change the main loop to call the new sub when you wake up. I added toggling an IO pin so you can monitor it
with a scope. Remove them if you like.

Code: Select all

OSCCON.7 = 0	// set IDLEN bit to SLEEP mode
INTCON = 0		// make sure all intrs are disabled
While True
    PORTB.0 = 1		// set IO bit to show we're going to sleep...
    Asm
       SLEEP
       NOP
       NOP
    End Asm
    PORTB.0 = 0		// awake now...

    TMR1_Seconds()
Wend
Try that and see if the output is what you expect.
PORTB.0 should be high for 1 second and go low for a short time while it does the TMR1_Seconds() routine. If it constantly just toggles high/low you know you're not sleeping.

Overclocked
Posts: 21
Joined: Mon Oct 13, 2008 9:53 pm
Location: CT

Re: Cant get to sleep

Post by Overclocked » Wed Jul 29, 2015 10:37 pm

Hmm. Pin Sits high. Ive kept most of the code the same, but I plan on using the sub for the pins at some point. Just wanted to get the sleep working before moving on to other power saving techniques.

Code: Select all


{
*****************************************************************************
*  Name    : Dataloger_D.BAS                                                *
*  Author  : Chris S                                                        *
*  Notice  : Copyright (c) 2015 Open Source                                 *
*          : All Rights Reserved                                            *
*  Date    : 7/29/2015                                                      *
*  Version : 1.0                                                            *
*  Notes   :    TX on Micro goes to RX on transmitter                       *
*          :   AN2, AN4 and AN5 Are Available ports                         *
*          : TO DO: FVR (2.048v) on All channels.                           *
*          : FVR Varies. Check against theoretical (2.048) value and then   *
*          : Subtract the measured value to get the difference.             *
*          : Call this Var "MeasuredFVR" and "TheoreticalFVR"               *
*          : DeltaFVR=Theoretical-Measured                                  *
*          :RealFVF=Theoretical-Delta if less than Theo                     *
*          :RealFVR=Theoretical+Delta if More than Theo                     *
*          : Check battery voltage once per hour. Same with Solar Cell      *
*****************************************************************************
}

//Relavent settings
// ADCON0 Settings
// ADCON0= %00001000 = Channel 2
// ADCON0= %00010000 = Channel 4
// ADCON0= %00101000 = Channel 5
//
//ANSEL Settings
//ANSEL.3 = 1 For channel 4
//ANSEL.5 = 1 For Channel 5
//
//TRISA Settings
//TRISA.5 = 1 For Channel 5

Device = 18F13K22
Clock = 4
Include "IntOSC.bas"
Include "USART.bas"
Include "utils.bas"
Include "convert.bas"
Include "ADC.bas"
Config FOSC = IRC

Dim
    Channel2 As Integer, //changed datatypes from word to avoid negative number errors
    Channel4 As Integer,
    Channel5 As Integer,
    TMR1IE As PIE1.0, // TMR1 Interrupt Enable
    TMR1IF As PIR1.0, // TMR1 Interrupt Flag
    Timer1 As TMR1L.AsWord, // A quick way of creating a Word Alias
    Seconds As Byte,
    Minutes As Byte,
    Hours As Byte,
    Days As Word, //179 Years before this fills up...
    Years As Byte
   

 
//Const 
// TMR1StartVal = $80, // User defined TMR1 starting value
// TMR1ReloadVal = TMR1StartVal + 5
 
 
 
Sub TMR1_Seconds()
 If TMR1IF = 1 Then
    TMR1IF = 0 // Clear the TMR1 Interrupt
    T1CON.0 = 0 //Turn timer 1 off
    TMR1H = $80 //Preload high byte with 128
    TMR1L = 0   // Preload Low byte with 0
    T1CON.0 = 1 // timer 1 on
    Seconds= Seconds +1
    //USART.Write (DecToStr(Seconds,2),13,10)      //Just a test string. Can be deleted in final version.
    If Seconds = 10 Then   //count to 59. Take ADC reading
        TRISA.2 = 1 //set channel 2 as a input
       //read channel 2 
        ADCON0= %00001000  //channel 2 as ADC input
        ANSEL.2 = 1 // Channel 2
        ADCON0.0 = 1  //enable ADC                
        ADCON0.1 = 1 //GOGOGOGO
        While ADCON0.1 = 1
            ADResult = (ADRESL)
        Wend
        
        Channel2 = ((ADResult+ 1) * 500) / 1024    //MATHMATICAL!
        Channel2 = Channel2 - 50 //Subtract 50 to get the current temp in C
        
        //Next Channel
        TRISA.4 = 1 //set channel 4 as input
        ADCON0= %00010000 //Channel 4
        ANSEL.3 = 1 //Channel 4
        ADCON0.0 = 1  //enable ADC                
        ADCON0.1 = 1 //GOGOGOGO
        While ADCON0.1 = 1
            ADResult = (ADRESL)
        Wend
        
        Channel4 = ((ADResult+ 1) * 500) / 1024    //MATHMATICAL!
            //Place holder for Math for Battery.
                         
        //USART.Write ("Channel 2: ",DecToStr(Channel2 / 100), ".", DecToStr(Channel2, 2), " ",13,10)
        USART.Write ("Current Temp: ", DecToStr(Channel2), " ",13,10)
        USART.Write ("Battery Voltage: ", DecToStr(Channel4), " ",13,10)
        Seconds = 0
        Minutes = Minutes + 1  
        USART.Write ("Minutes:",DecToStr(Minutes,2),13,10)
    End If 
    
    If Minutes = 59 Then  //Count up hours
        Hours = Hours + 1
        Minutes = 0
        USART.Write ("Hours:",DecToStr(Hours,2),13,10)
    End If   
    
    If Hours = 24 Then
        Days = Days + 1
        Hours = 0
        USART.Write ("Days:",DecToStr(Days,3),13,10)
    End If  
    
    If Days = 365 Then
        Years = Years +1
        Days = 0
        USART.Write ("Years:",DecToStr(Years,2),13,10)
    End If  
    
 EndIf 
 
End Sub
  
Sub TMR1_Initialize()
 TRISC.0 = 1 // If External clock, then set clock as an input
 T1CON.0 = 0 // Timer 1 off
 TMR1H = $80 //Preload with 128
 TMR1L = 0   // 
 T1CON.0 = 1 // timer 1 on
 T1CON.1 = 1 // 1 = External clock from pin RC0/T1OSO/T1CKI (on the rising edge)
             // 0 = Internal clock (FOSC/4)
    
 T1CON.2 = 0 // 1 = Do not synchronize external clock input   
 // 0 = Synchronize external clock input
 // When T1CON.1 = 0;
 // this bit is ignored.
 T1CON.3 = 1
 T1CON.4 = 0 
 T1CON.5 = 0 
 T1CON.6 = 0 
 T1CON.7 = 0 
 TMR1IE = 1 // Enable TMR1 Interrupts

// Enable(TMR1_Interrupt) // Enable TMR1 Interrupt Handle
End Sub 

 
// Start Of Main Program...

Seconds = 0
Minutes = 0
Hours = 0
Days = 0
Years = 0 
Channel2 = 0
Channel4 = 0
TMR1_Initialize // Setup and enable TMR1
USART.SetBaudrate(br9600) 
//TRISA.2 = 1 //set channel 2 as a input
//TRISA.4 = 1 //set channel 4 as input
ADCON2 =%10110001 //12 TAD, FOSC/8

OSCCON.7 = 0   // set IDLEN bit to SLEEP mode
INTCON = 0      // make sure all intrs are disabled
TRISB.6=0 
While True
    PORTB.6 = 1      // set IO bit to show we're going to sleep...
    Asm
       SLEEP
       NOP
       NOP
    End Asm
    PORTB.6 = 0      // awake now...

TMR1_Seconds()
Wend


Jerry Messina
Swordfish Developer
Posts: 1245
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Cant get to sleep

Post by Jerry Messina » Thu Jul 30, 2015 6:16 pm

I had a chance to try it out, and if the pin just goes high and stays there it's not coming out of sleep, probably because the 32kHz xtal for TMR1 OSC isn't running.

I made some modifications and cleaned up things a bit. I don't have an 18F13K22 around, so I had to run a slightly modified version on a different K22 chip and it worked, but I had to setup TMR1 differently. See if this works for you...

Code: Select all

{
*****************************************************************************
*  Name    : Dataloger_D.BAS                                                *
*  Author  : Chris S                                                        *
*  Notice  : Copyright (c) 2015 Open Source                                 *
*          : All Rights Reserved                                            *
*  Date    : 7/29/2015                                                      *
*  Version : 1.0                                                            *
*  Notes   :    TX on Micro goes to RX on transmitter                       *
*          :   AN2, AN4 and AN5 Are Available ports                         *
*          : TO DO: FVR (2.048v) on All channels.                           *
*          : FVR Varies. Check against theoretical (2.048) value and then   *
*          : Subtract the measured value to get the difference.             *
*          : Call this Var "MeasuredFVR" and "TheoreticalFVR"               *
*          : DeltaFVR=Theoretical-Measured                                  *
*          :RealFVF=Theoretical-Delta if less than Theo                     *
*          :RealFVR=Theoretical+Delta if More than Theo                     *
*          : Check battery voltage once per hour. Same with Solar Cell      *
*****************************************************************************
}

Device = 18F13K22
Clock = 4

Include "IntOSC.bas"    // assumes 4MHz int RC osc
Include "USART.bas"
Include "utils.bas"
Include "convert.bas"

Dim
    Channel2 As Integer, //changed datatypes from word to avoid negative number errors
    Channel4 As Integer,
    Channel5 As Integer,
    TMR1IE As PIE1.0, // TMR1 Interrupt Enable
    TMR1IF As PIR1.0, // TMR1 Interrupt Flag
    Seconds As Byte,
    Minutes As Byte,
    Hours As Byte,
    Days As Word, //179 Years before this fills up...
    Years As Byte

Dim
   ADRESULT as ADRESL.AsWord            // ADC result registers as a 16-bit word
 
Dim SLEEP_LED as PORTB.6            // set IO bit to show we're going to sleep...

Sub TMR1_Seconds()
  If TMR1IF = 1 Then
    TMR1IF = 0 // Clear the TMR1 Interrupt

    // reload TMR1 for 1 sec (32768 counts at 32KHz)
    // do not turn off the tmr or touch TMR1L so that it doesn't accumulate error
    TMR1H = $80 //reload high byte with 128

    Seconds= Seconds +1

    USART.Write (DecToStr(Seconds,2),13,10)      //Just a test string. Can be deleted in final version.

    If Seconds = 60 Then
        Seconds = 0
        Minutes = Minutes + 1 
        USART.Write ("Minutes:",DecToStr(Minutes,2),13,10)
    End If
   
    // take an ADC reading every 10 seconds
    If ((Seconds mod 10) = 0) Then
        ADCON0.0 = 1            // turn on ADC (if it was off)
        // may have to wait a bit for ADC to stabilize if it was turned off
        'delayus(10)

        //read channel 2
        ADCON0= (%0010 << 2) or $01     // set AN2 as ADC input, ADC ON
        ADCON0.1 = 1            //GOGOGOGO
        While ADCON0.1 = 1      // wait for ADC conversion to complete
        Wend
        // ADRESULT holds the 10-bit ADC result
        Channel2 = ((ADRESULT+ 1) * 500) / 1024    //MATHMATICAL!
        Channel2 = Channel2 - 50 //Subtract 50 to get the current temp in C
       
        //read channel 4
        ADCON0= (%0100 << 2) or $01     // set AN4 as ADC input, ADC ON
        ADCON0.1 = 1            //GOGOGOGO
        While ADCON0.1 = 1      // wait for ADC conversion to complete
        Wend
        // ADRESULT holds the 10-bit ADC result
        Channel4 = ((ADRESULT+ 1) * 500) / 1024    //MATHMATICAL!
            //Place holder for Math for Battery.
                         
        //USART.Write ("Channel 2: ",DecToStr(Channel2 / 100), ".", DecToStr(Channel2, 2), " ",13,10)
        USART.Write ("Current Temp: ", DecToStr(Channel2), " ",13,10)
        USART.Write ("Battery Voltage: ", DecToStr(Channel4), " ",13,10)
    End If

    If Minutes = 60 Then  //Count up hours
        Minutes = 0
        Hours = Hours + 1
        USART.Write ("Hours:",DecToStr(Hours,2),13,10)
    End If   
   
    If Hours = 24 Then
        Hours = 0
        Days = Days + 1
        USART.Write ("Days:",DecToStr(Days,3),13,10)
    End If 
   
    If Days = 365 Then
        Days = 0
        Years = Years +1
        USART.Write ("Years:",DecToStr(Years,2),13,10)
    End If
  EndIf      // TMR1IF
End Sub
 
// set TMR1 SOSC for external 32KHz xtal on the OSC1/T13CKI(RA5) and OSC2(RA4) pins
Sub TMR1_Initialize()
    T1CON.0 = 0     // Timer 1 off

    TMR1H = $80     // Preload with $8000 (32768 counts at 32KHz = 1 sec)
    TMR1L = 00

    T1CON.7 = 0     // RD16 = 0 - 8bit mode ok
    T1CON.6 = 0     // T1RUN = 0 - main system clock from another source
    T1CON.5 = 0     // T1CKPS1 = %00 - no prescaler
    T1CON.4 = 0     // T1CKPS0
    T1CON.3 = 1     // T1OSCEN = 1 - TMR1 osc enabled
    T1CON.2 = 1     // T1SYNCn = 1 - do not sync external clock
    T1CON.1 = 1     // TMR1CS = 1 - external clock from the T13CKI pin
    T1CON.0 = 1     // TMR1ON

    TMR1IE = 1      // Enable TMR1 Interrupts
    TMR1IF = 0      // clear flag
End Sub

sub iopin_setup()
    // set pin mode
    // 0=digital, 1=analog (default)
    ANSEL.0 = 0       // RA0 AN0
    ANSEL.1 = 0       // RA1 AN1
    ANSEL.2 = 1       // RA2 AN2 (analog input ch2)
    ANSEL.3 = 0       // RA4 AN3
    ANSEL.4 = 1       // RC0 AN4 (analog input ch4)
    ANSEL.5 = 1       // RC1 AN5 (analog input ch5)
    ANSEL.6 = 0       // RC2 AN6
    ANSEL.7 = 0       // RC3 AN7
    
    ANSELH.0 = 0      // RC6 AN8
    ANSELH.1 = 0      // RC7 AN9
    ANSELH.2 = 0      // RB4 AN10
    ANSELH.3 = 0      // RB5 AN11
    
    // set RA2, RC0, RC1 inputs (analog)
    // set unused pins as outputs
    TRISA = %00000100
    TRISB = %00000000
    TRISC = %00000011
    
    // set unused pins output low
    PORTA = 0
    PORTB = 0
    PORTC = 0
end sub 

// Start Of Main Program...
iopin_setup()

Seconds = 0
Minutes = 0
Hours = 0
Days = 0
Years = 0
Channel2 = 0
Channel4 = 0

// Setup and enable TMR1
TMR1_Initialize()

// setup ADC
// ADFM=1 (right-justify), ACQT=110 (16 TAD), ADCS=001 (FOSC/8)
ADCON2 =%10110001

USART.SetBaudrate(br9600)
USART.write("Datalogger", 13, 10)

OSCCON.7 = 0   // set IDLEN bit to SLEEP mode
INTCON = 0      // make sure all intrs are disabled

While True
    // wait for any serial message to finish transmitting before we go to sleep
    while (USART.TRMT = 0)
    wend

    high(SLEEP_LED)      // set IO bit to show we're going to sleep...
    Asm
       SLEEP
       NOP
       NOP
    End Asm
    low(SLEEP_LED)      // awake now...

    // toggle uart enable since we're coming out of sleep (clears baudrate)
    USART.SPEN = 0
    USART.SPEN = 1

    TMR1_Seconds()
Wend
Last edited by Jerry Messina on Tue Aug 04, 2015 11:43 am, edited 1 time in total.
Reason: correct T1SYNC bit setting

Overclocked
Posts: 21
Joined: Mon Oct 13, 2008 9:53 pm
Location: CT

Re: Cant get to sleep

Post by Overclocked » Sun Aug 02, 2015 11:36 pm

Hmm. Gave it a shot tonight. Not much time in the coming week (vacation next week). I want to get a laptop up and working so I can atleast give it a shot during my downtime. Anyway. I looked on my scope and OSC1 and OSC2 are oscillating at 32kHz. RB6 just sits low.

Jerry Messina
Swordfish Developer
Posts: 1245
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Cant get to sleep

Post by Jerry Messina » Mon Aug 03, 2015 9:37 am

Try commenting out the asm block with the sleep instruction for the time being.

You should get a serial message every second as it counts, and a set of ADC readings every 10 seconds.

As I said, that code worked for me on an 87K22 (with a slightly different TMR1 setup)

Overclocked
Posts: 21
Joined: Mon Oct 13, 2008 9:53 pm
Location: CT

Re: Cant get to sleep

Post by Overclocked » Mon Aug 03, 2015 11:39 pm

Hmm. Works if I comment out the sleep command. What did you have to do to get it to work on your PIC?

Jerry Messina
Swordfish Developer
Posts: 1245
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Cant get to sleep

Post by Jerry Messina » Tue Aug 04, 2015 11:42 am

Oops! Looks like when I changed the timer init code for the 13K22 I set the SYNC bit the wrong way around.

In the TMR1_Initialize() routine change:

Code: Select all

    T1CON.2 = 0     // T1SYNCn = 0 - do not sync external clock (OSCEN overrides this anyway)
to:

Code: Select all

    T1CON.2 = 1     // T1SYNCn = 1 - do not sync external clock
On the 87K22 this is a don't care when enabling the ext osc, but I bet it needs to be set correctly for the 13K22.

Sorry about that. I'll edit the post above to reflect the change.

Overclocked
Posts: 21
Joined: Mon Oct 13, 2008 9:53 pm
Location: CT

Re: Cant get to sleep

Post by Overclocked » Wed Aug 05, 2015 12:19 am

Jerry Messina wrote:Oops! Looks like when I changed the timer init code for the 13K22 I set the SYNC bit the wrong way around.

In the TMR1_Initialize() routine change:

Code: Select all

    T1CON.2 = 0     // T1SYNCn = 0 - do not sync external clock (OSCEN overrides this anyway)
to:

Code: Select all

    T1CON.2 = 1     // T1SYNCn = 1 - do not sync external clock
On the 87K22 this is a don't care when enabling the ext osc, but I bet it needs to be set correctly for the 13K22.

Sorry about that. I'll edit the post above to reflect the change.

Woops! I overlooked it myself. We must have assumed that 0 = no sync. From my scope it looks like it works, PortB.6 stays on for about 10 seconds, and goes off very shortly. Power usage is a whopping 26uA. I was measuring 2mA But I realized a stupid mistake-I left the UART to USB chip connected I was using for debug. UART is sending the correct code (no sensors hooked up yet though)! OK Sweet. Now the real program actually wont take measurements every 10 seconds, it will probably be once every 5 minutes or so. 10 second intervals is easy enough that I know its sleeping and my code works. Its also worth noting that my memory use has decreased quite a bit without the use of a ISR. I really appreciate your help, I wouldnt have thought of using no ISR and just looking at the bit itself.

Jerry, could you explain this line of Code?

Code: Select all

If ((Seconds Mod 10) = 0) Then
Why do it that way? Wouldnt:

Code: Select all

If Seconds = 10 then
do the same thing? Unless its the same way of writing it, just personal preference.

Jerry Messina
Swordfish Developer
Posts: 1245
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Cant get to sleep

Post by Jerry Messina » Wed Aug 05, 2015 9:46 am

The MOD operator gives you the remainder after a division, so 'x MOD 10' is 0 when x is evenly divisible by 10... 10, 20, 30, 40, etc.
That way you get a measurement every 10 seconds.

'If (seconds = 10)' would only give you a measurement once a minute at the 10 seconds mark.

If you want to sample at different intervals then you'll have to move the measurement block into the timekeeping tests that change the interval you're interested in, something like

Code: Select all

    If Seconds = 60 Then
        Seconds = 0
        Minutes = Minutes + 1
        // take an ADC reading every 5 minutes
        If ((Minutes mod 5) = 0) Then
          <SNIP>
        End If
    End If
   
    If Minutes = 60 Then
        Minutes = 0
        Hours = Hours + 1
        // take an ADC reading every 2 hours
        If ((Hours mod 2) = 0) Then
          <SNIP>
        End If
      <SNIP>
    End If   
   
    If Hours = 24 Then
      <SNIP>
    End If
   
    If Days = 365 Then
      <SNIP>
    End If

Last edited by Jerry Messina on Wed Aug 05, 2015 10:15 am, edited 3 times in total.
Reason: change faulty logic

Post Reply