Sleep does not really sleep...


+ Reply to Thread
Results 1 to 9 of 9
  1. #1
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,260

    Default Sleep does not really sleep...

    On a 16F886 the following code initially is in sleep mode having almost 0 current through PIC.

    But after first interrupt-on-change (port B), the sleep does not zero current. It stays rather high at 1,8 mA.

    Something is still on and cannot see what.

    Code:
    #config
    Line1 = _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF
    Line2 = _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
        __CONFIG _CONFIG1, Line1 & Line2
        __CONFIG _CONFIG2, _WRT_OFF; & _BOR40V
    #endconfig
    
    OSCCON = %01110001 '8MHz Clock
    
    DEFINE OSC 8
    
    OPTION_REG.0=1		'PSA0 PRESCALER SELECT 1:1 TO 1:256
    OPTION_REG.1=1		'PSA1
    OPTION_REG.2=1		'PSA2
    OPTION_REG.3=1		'PRESCALER TO: 1->WDT, 0->TMR0
    OPTION_REG.4=0		'T0SE SOURCE EDGE 1->H TO L, 0->L TO H
    OPTION_REG.5=0		'T0CS 1->FROM RA4, 0->FROM INT. CLOCK
    OPTION_REG.6=0		'INT EDGE SELECT 0->H TO L, 1->L TO H
    OPTION_REG.7=0		'PULL UP 1->DISABLE, 0->ENABLE
    
    adcon0=%10111101    'ADC on, input set at Fixed Ref 0.6 Volts,adc clk @ Fosc/32
    adcon1=%10000000    'right justified
    ansel=$00
    anselh=$00
    
    DEFINE ADC_BITS 10          ; Set-up ADC for fast 10-bit results
    DEFINE ADC_SAMPLEUS 5
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 20h
    DEFINE HSER_BAUD 9600
    DEFINE HSER_SPBRG 12  ' 9600 Baud @ 8MHz, 0,16%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    
    ccp1con=0
    
    PORTA=%00000000
    PORTB=%01111000
    PORTC=%11000000'%10000001
    
    TRISC = %10000000
    
    TRISA = %00000000			'PA0: buzzer out
    							'PA1:
    							'PA2:
    							'PA3:
    							'PA4:
    							'PA5:
    							'RA6:
    
    TRISB = %01111000			'PB0: col3 out
    							'PB1: col2 out
    							'PB2: col1 out
    							'PB3: line4 in
    							'PB4: line3 in
    							'PB5: line2 in
    							'PB6: line1 in
    							'PB7: N.C.
    
    clear
    
    'baudctl=%00010000    'Transmit inverted data (with no MAX232/USB2Serial needed)
    BAUDCTL = %00000000   'Transmit true data (with MAX232/USB2Serial needed)
    WPUB = %01111000
    IOCB = %01111000
    INTCON = %10001000
    
    wsave    var byte $70 system
    wsave1   var byte $a0 system
    wsave2   var byte $120 system
    wsave3   var byte $1a0 system
    
    a       var word
    pressed var byte
    buzzer  var portc.0
    
    char    var byte
    idx     var byte
    array   var byte[5]
    
    keyin   var byte
    ix      var byte
     
    '-------------   INTERRUPTS SETUP   ---------------------
    INCLUDE "DT_INTS-14.bas"
    INCLUDE "ReEnterPBP.bas"
    
    '-------------   INTERRUPTS SETUP   ---------------------
    ASM
    INT_LIST  macro;    IntSource,  Label,      Type,  ResetFlag?
        INT_Handler     RBC_INT,    _IOC2,      PBP,    yes
        ;INT_Handler     TMR1_INT,   _timer,     PBP,    yes
        endm
        INT_CREATE            ; Creates the interrupt processor
    ENDASM
    
    @   INT_ENABLE  RBC_INT      ; Enable Port B on change
    ;@   INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts  
    
    
    goto main
    
    '-------------   INTERRUPTS SETUP   ---------------------
    
    '***********************************************************************
    '*
    '*             Interrupt on Change
    '*
    '***********************************************************************
    
    IOC2:
        adcon0=%10111101    'ADC on, input set at Fixed Ref 0.6 Volts,adc clk @ Fosc/32
        adcon1=%10000000    'right justified
        txsta=$20  'Enable USART
        rcsta=$90
        keyin=portb & %01111000     'End mismatch on port B interrupt
        'hserout [bin8 keyin,13,10]'check keyin
        if keyin<>120 then
            adcon0.0=1:adcon0.1=1 'Start adc for bat level check
            pressed=1  'Flag key press
            toggle buzzer
        else
            pressed=0
        endif
    @ INT_RETURN
    
    main:
    portb=$78   'set port to 01111000
    txsta=0     'Turn off all peripherals
    rcsta=0     'before sleeping
    adcon0.0=0  'Disable ADC
    pressed=0   'reset flag pressed
    intcon.0=0  'reset RBIF flag
    t1con.0=0   'turn off timmer 1
    buzzer=0
    @ sleep
    @ nop
    hserout ["Alive",13,10]
    
    while adcon0.1:wend
    a.byte0=adresl:a.byte1=adresh
    if a>192 then
        hserout ["Bat low",dec3 a,13,10]
    else
        hserout ["Bat ok",dec3 a,13,10]
    endif
    
    keyscan:
    while 1
        for ix=0 to 2     'scan columns
            portb=~dcd ix 'invert polarity
            keyin=portb & %01111000
            if keyin<>120 then keycheck  'no key press,scan again
        next ix
    wend
            
    keycheck:
    ' 0,   1, 2, 3, 4, 5, 6,  7,  8,  9,  *,  #
    ' 117,59,61,62,91,93,94,107,109,110,115,118
        keyin=portb & 127
        lookdown keyin,[117,59,61,62,91,93,94,107,109,110,115,118],char
        if char>11 then keyscan 'wrong key,noise etc
        char=char+48
        hserout [char,13,10]
        array[idx]=char
        idx=idx+1
        if idx=5 then
            hserout [str array\5,13,10]
            idx=0
        endif 
        pause 200
        goto main
    
    End
    Thanks,
    Ioannis
    Last edited by Ioannis; - 18th June 2022 at 22:50.

  2. #2
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,260


    Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    Additional info:

    The ADC uses internal Vref of 0.6 volts to check the battery power supply. Before sleep the ADC is switched off.

    Also UART is switched off, along with Tmr1 and some ports setting.

    The only one that stays as input, is the Portb.7 the Rx pin but even if it is grounded the current stays at 1.8mA.

    WDT is disabled.

    BOR is disabled.

    /MCLR is set as internal and as the data sheet states, there is an internal pull up.

    Ioannis
    Last edited by Ioannis; - 18th June 2022 at 22:39.

  3. #3
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,260


    Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    The interrupt on change is created by a matrix keyboard connected on portB (0-6).

    I noticed that a short keypress allows PIC go to sleep, while a longer press keeps it semi awake.

    Then I added this while-wend check just before pressed=0 in the main routine and now works OK:

    Code:
    main:
    portb=$78   'set port to 01111000
    txsta=0     'Turn off all peripherals
    rcsta=0     'before sleeping
    adcon0.0=0  'Disable ADC
    while pressed:pause 10:wend
    pressed=0   'reset flag pressed
    intcon.0=0  'reset RBIF flag
    t1con.0=0   'turn off timmer 1
    buzzer=0
    @ sleep
    @ nop
    Though not elegant nor explains why this happens, it kinda fixed the problem.

    Ioannis

  4. #4
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,260


    Did you find this post helpful? Yes | No

    Default Wait for key release

    Any idea how can the keyboard matrix scan routine check for key release, before jumps to the keycheck subroutine please?

    Code:
    keyscan:
    while 1
        for ix=0 to 2     'scan columns
            portb=~dcd ix 'invert polarity
            keyin=portb & %01111000
            if keyin<>120 then keycheck  'if key is pressed then check it
        next ix
    wend
    Ioannis

  5. #5
    Join Date
    May 2013
    Location
    australia
    Posts
    2,102


    Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    from the data sheet, my best guess . i see no attempt to read portb before sleep

    For enabled interrupt-on-change pins, the present valueis compared with the old value latched on the last read
    of PORTB to determine which bits have changed or
    mismatched the old value. The ‘mismatch’ outputs of
    the last read are OR’d together to set the PORTB
    Change Interrupt flag bit (RBIF) in the INTCON register.
    This interrupt can wake the device from Sleep. The user,
    in the Interrupt Service Routine, clears the interrupt by:
    a) Any read or write of PORTB. This will end the
    mismatch condition.
    b) Clear the flag bit RBIF.
    A mismatch condition will continue to set flag bit RBIF.
    Reading or writing PORTB will end the mismatch
    condition and allow flag bit RBIF to be cleared. The latch
    holding the last read value is not affected by a MCLR nor
    Brown-out Reset. After these Resets, the RBIF flag will
    continue to be set if a mismatch is present.
    Warning I'm not a teacher , prose like a gushing embroilment is not my style

  6. #6
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,260


    Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    Mismatch is taken care in the ISR (5th command in the IOC2 routine) and the then interrupt flag bit is reset.

    My problem is that it does interrupt continuously as the user keeps pressing the button.

    But since it is a matrix scanned keyboard, I want to check for key release and then take action, not on key press.

    Ioannis

  7. #7
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    908


    1 out of 1 members found this post helpful. Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    Couple of things that caught my attention

    1 - in keyscan, this lne should ensure the rows are high
    portb=~dcd ix 'invert polarity
    So, I guess, you should add
    portb=~(dcd ix) + $78 'invert polarity

    2. I infer, the keypress interrupt is just to wake the processor out of sleep. So, the interrupt routine needs to do nothing other than just return when the interrupt occurs. After that, the processor will be awake and the scan, beep, transmit routine can work like normal in the foreground. No need of any flags. If no key is found, the processor can go back to sleep.

    This line need not re-scan till it finds a key. If no valid key is found, the processor can just go back to sleep.
    if char>11 then keyscan 'wrong key,noise etc

  8. #8
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,260


    Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    Hi Jerson.

    Thanks for the good points. Yes I will change the ISR to what you suggested. But in any case as it is now, it works very good. With your suggestion will be more efficient and fast in regards of ISR view.

    The PortB has Pull-Ups enabled so the line is correct as it is in the program.

    My only problem is how to check for key release instead of key press.

    Ioannis

  9. #9
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    908


    Did you find this post helpful? Yes | No

    Default Re: Sleep does not really sleep...

    Not too difficult to check for key release to act on.

    Right now you are checking a keypress when the portb value is different from $78

    Key release is simply getting the transition from (Not $78) to $78

    What caused it to be Not $78 is the key that got released.

    For easy implementation in case of short keypresses, a tight blocking loop doing the above test is fine. In case you anticipate the user will have a button down for a long while, then a different approach using a software timer may give better results.

    Just a short pseudo code as I am not well oiled in PBP these days

    Code:
    while 1
        key = ~portb & $78
        if (key <> $78) then
             savedkey = key
        else
             if savedkey <> $78 then
                  ' saved key is the one that was released
                  ' act on saved key
             endif
        endif
    wend
    If you wish to have a keyboard that has buttons that give pressed, hold, repeat and release states, I suggest you look at some arduino code that shows such an implementation using a finite state machine

Similar Threads

  1. Asm sleep - pbp sleep
    By MOUNTAIN747 in forum mel PIC BASIC Pro
    Replies: 31
    Last Post: - 18th May 2020, 21:13
  2. Can't @sleep
    By MOUNTAIN747 in forum General
    Replies: 3
    Last Post: - 30th December 2010, 17:29
  3. Trying to add a sleep function or pretend to sleep
    By lilimike in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 9th May 2010, 19:10
  4. How to go to sleep
    By savnik in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 22nd September 2006, 18:38
  5. @sleep
    By jheissjr in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 5th March 2006, 22:42

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts