SOLVED: Post #11 - IOC on negative edge sometimes triggers twice on single press


+ Reply to Thread
Results 1 to 13 of 13
  1. #1
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,953

    Default SOLVED: Post #11 - IOC on negative edge sometimes triggers twice on single press

    Any idea what's going on?

    I removed the KHz variable and kept only MHz, but it still does the same thing:

    - sometimes it triggers once,
    - sometimes it triggers twice (IOC on positive edge is OFF),
    - no pattern (that I could see),


    16F18877



    Code:
    @ ERRORLEVEL -306   ; turn off crossing page boundary message
    include     "C:\PBP Includes\DT_INTS-14_16F1885x-7x.bas"
    include     "C:\PBP Includes\ReEnterPBP.bas"
    
    ASM
    INT_LIST  macro      ;IntSource,  Label,     Type, ResetFlag? 
            INT_Handler   IOC_INT,    _IOCinterrupts,    PBP,  yes   ;IOCC.3 
        endm
        INT_CREATE                              ;Creates the interrupt processor
    ENDASM
    
    #CONFIG
        __config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
        __config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
        __config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_ON & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
        __config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
        __config _CONFIG5, _CP_OFF & _CPD_OFF
    #ENDCONFIG
    
    DEFINE OSC 32
    
    '   LCD is used for debugging
        
    DEFINE  LCD_DREG      PORTD                 ' Set LCD data port
    DEFINE  LCD_DBIT      4                     ' Set starting data bit
    DEFINE  LCD_RSREG     PORTD                 ' Set LCD register select port
    DEFINE  LCD_RSBIT     1                     ' Set LCD register select bit
    DEFINE  LCD_EREG      PORTD                 ' Set LCD enable port
    DEFINE  LCD_EBIT      0                     ' Set LCD enable bit
    DEFINE  LCD_BITS      4                     ' Set LCD bus size
    DEFINE  LCD_LINES     4                     ' Set number of lines on LCD
    DEFINE  LCD_COM1MANDUS 1000                 ' Set COM1mand delay time in microseconds
    DEFINE  LCD_DATAUS    50                    ' Set data delay time in microseconds
    
    '   CCPx is used to control Contrast and Blacklight on LCD
    
    define  CCP3_REG     PORTD                  ' PWM Pulse out to LCD contrast
    DEFINE  CCP3_BIT     2                      '   2N2907 PNP with 1K on base
    define  CCP4_REG     PORTD                  ' PWM Pulse out to LCD backlight
    DEFINE  CCP4_BIT     3                      '   2N2222A NPN with 1K on base
    
    IOCBP = %00000000                           ;IOC Interrupt, Positive Edge, low-to-high
    IOCBN = %00000100                           ;IOC Interrupt, Negative Edge, from high-to-low
    
    WPUB = %00000100                            ; Pull-up resistor on pin B2
    
    '   PPS is used to move CCP functions to other pins
    
    PinD2           CON $1A                     '    Datasheet table 13-2
    PinD3           CON $1B
    CCP3PPS = PinD2                             ' CCP3 Peripheral input selection
    CCP4PPS = PinD3                             ' CCP4 Peripheral input selection
    
    PeripheralCCP3  CON $0B                     '    Datasheet table 13-3
    PeripheralCCP4  CON $0C
    RD2PPS = PeripheralCCP3                     ' Pin D2 output source selection
    RD3PPS = PeripheralCCP4                     ' Pin D3 output source selection
    RB0PPS = 0                                  ' Disable CCP3 (moved to D2)
    RB5PPS = 0                                  ' Disable CCP4 (moved to D3)
    
    ANSELA = %00000000                          ' No analog operations
    ANSELB = %00000000
    ANSELC = %00000000
    ANSELD = %00000000
    ANSELE = %00000000
    
    TRISA = %00000000
    TRISB = %00000100                           ' Only pin B2 is Input
    TRISC = %00000000
    TRISD = %00000000
    TRISE = %00000000
    
    IOC_NAV2_Swap_flag      var IOCBF.2         ' IOC flag on pin B2 change
    
    NAV2_Swap_ON            VAR BYTE
    
    NAV2_MHz_Standby        VAr BYTE
    NAV2_MHz_Active         VAr BYTE
    
    SwapFrequency           var WORD            ' Temporary variable used for Swapping frequencies
    
        Pause 500                               ' Let PIC and LCD stabilize
    
        NAV2_MHz_Standby = 111 : NAV2_MHz_Active = 222
            
        HPWM 3,250,1953                         ' Contrast
        HPWM 4,150,1953                         ' Backlight
    
        IOCBF = %00000000                       ' Clear all interrupt flags
        
        NAV2_Swap_ON = 0                        ' Clear Swap button is waiting for processing
                
        goto Start
    
    ;--- Subroutines ---------------------------------------------------------------
    
    IOCinterrupts:
    
    
        if IOC_NAV2_Swap_flag = 1 then          ' Swap frequencies
            NAV2_Swap_ON = 1
            IOC_NAV2_Swap_flag = 0
        endif
    @ INT_RETURN
    
    Start:
        LCDOUT $FE, 1 : Pauseus 1
        LCDOUT $FE, $80, "COM/NAV ENCODER TEST" : Pauseus 1
            
    @ INT_ENABLE IOC_INT
        PAUSE 500
    
    Mainloop:
        if NAV2_Swap_ON = 1 then                ' Swap button has been pressed
            SwapFrequency = NAV2_MHz_Standby    ' Swap MHz frequency
            NAV2_MHz_Standby = NAV2_MHz_Active
            NAV2_MHz_Active = SwapFrequency
    
            NAV2_Swap_ON = 0                    ' Turn OFF swap flag
        endif
     
        LCDOUT $FE, $D4, "NAV2:", dec3 NAV2_MHz_Standby,_
                             "  ", dec3 NAV2_MHz_Active : Pauseus 1
    
        goto mainloop
    end

    Gutted code and left only LCD for my observations.
    Last edited by Demon; - 6th September 2024 at 02:01.
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,563


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    I'm not sure what I'm looking at in the video but inadequate debounce on the input would be my number one guess.

    I believe DT_Ints resets the interrupt request flag on exit of ISR (@ INT_RETURN) so to test you could insert a simple PAUSE 5 or whatever before exiting.

  3. #3
    Join Date
    May 2013
    Location
    australia
    Posts
    2,504


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    catching key presses with isr's is never a good look

    a simple polling debounce is way more effective

    if you are just using plain pwm for mccp ports
    what is this about ?
    'PinD2 CON $1A ' Datasheet table 13-2
    'PinD3 CON $1B
    'CCP3PPS = PinD2 ' CCP3 Peripheral input selection
    'CCP4PPS = PinD3 ' CCP4 Peripheral input selection


    like this (untested)
    Code:
    @ ERRORLEVEL -306   ; turn off crossing page boundary message
    'include     "C:\PBP Includes\DT_INTS-14_16F1885x-7x.bas"
    'include     "C:\PBP Includes\ReEnterPBP.bas"
    
    
    'ASM
    'INT_LIST  macro      ;IntSource,  Label,     Type, ResetFlag? 
    '        INT_Handler   IOC_INT,    _IOCinterrupts,    PBP,  yes   ;IOCC.3 
    '    endm
    '    INT_CREATE                              ;Creates the interrupt processor
    'ENDASM
    
    
    #CONFIG
        __config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_ON
        __config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_ON & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
        __config _CONFIG3, _WDTCPS_WDTCPS_11 & _WDTE_ON & _WDTCWS_WDTCWS_7 & _WDTCCS_LFINTOSC
        __config _CONFIG4, _WRT_OFF & _SCANE_available & _LVP_OFF
        __config _CONFIG5, _CP_OFF & _CPD_OFF
    #ENDCONFIG
    
    
    DEFINE OSC 32
    
    
    '   LCD is used for debugging
        
    DEFINE  LCD_DREG      PORTD                 ' Set LCD data port
    DEFINE  LCD_DBIT      4                     ' Set starting data bit
    DEFINE  LCD_RSREG     PORTD                 ' Set LCD register select port
    DEFINE  LCD_RSBIT     1                     ' Set LCD register select bit
    DEFINE  LCD_EREG      PORTD                 ' Set LCD enable port
    DEFINE  LCD_EBIT      0                     ' Set LCD enable bit
    DEFINE  LCD_BITS      4                     ' Set LCD bus size
    DEFINE  LCD_LINES     4                     ' Set number of lines on LCD
    DEFINE  LCD_COM1MANDUS 1000                 ' Set COM1mand delay time in microseconds
    DEFINE  LCD_DATAUS    50                    ' Set data delay time in microseconds
    
    
    '   CCPx is used to control Contrast and Blacklight on LCD
    
    
    define  CCP3_REG     PORTD                  ' PWM Pulse out to LCD contrast
    DEFINE  CCP3_BIT     2                      '   2N2907 PNP with 1K on base
    define  CCP4_REG     PORTD                  ' PWM Pulse out to LCD backlight
    DEFINE  CCP4_BIT     3                      '   2N2222A NPN with 1K on base
    
    
    'IOCBP = %00000000                           ;IOC Interrupt, Positive Edge, low-to-high
    'IOCBN = %00000100                           ;IOC Interrupt, Negative Edge, from high-to-low
    
    
    WPUB = %00000100                            ; Pull-up resistor on pin B2
    
    
    '   PPS is used to move CCP functions to other pins
    
    
    'PinD2           CON $1A                     '    Datasheet table 13-2
    'PinD3           CON $1B
    'CCP3PPS = PinD2                             ' CCP3 Peripheral input selection
    'CCP4PPS = PinD3                             ' CCP4 Peripheral input selection
    
    
    PeripheralCCP3  CON $0B                     '    Datasheet table 13-3
    PeripheralCCP4  CON $0C
    RD2PPS = PeripheralCCP3                     ' Pin D2 output source selection
    RD3PPS = PeripheralCCP4                     ' Pin D3 output source selection
    RB0PPS = 0                                  ' Disable CCP3 (moved to D2)
    RB5PPS = 0                                  ' Disable CCP4 (moved to D3)
    
    
    ANSELA = %00000000                          ' No analog operations
    ANSELB = %00000000
    ANSELC = %00000000
    ANSELD = %00000000
    ANSELE = %00000000
    
    
    TRISA = %00000000
    TRISB = %00000100                           ' Only pin B2 is Input
    TRISC = %00000000
    TRISD = %00000000
    TRISE = %00000000
    
    
    'IOC_NAV2_Swap_flag      var IOCBF.2         ' IOC flag on pin B2 change
    NAV2_Swap_Pin           var PORT.2 
    NAV2_Swap_ON            VAR BYTE
    NAV2_Swap_Debounce      var WORD
    NAV2_MHz_Standby        VAr BYTE
    NAV2_MHz_Active         VAr BYTE
    
    
    SwapFrequency           var WORD            ' Temporary variable used for Swapping frequencies
    
    
        Pause 500                               ' Let PIC and LCD stabilize
    
    
        NAV2_MHz_Standby = 111 : NAV2_MHz_Active = 222
            
        HPWM 3,250,1953                         ' Contrast
        HPWM 4,150,1953                         ' Backlight
    
    
    '    IOCBF = %00000000                       ' Clear all interrupt flags
        
        NAV2_Swap_ON = 0                        ' Clear Swap button is waiting for processing
        NAV2_Swap_Debounce =0        
        goto Start
    
    
    ;--- Subroutines ---------------------------------------------------------------
    
    
    'IOCinterrupts:
    
    
    
    
    '    if IOC_NAV2_Swap_flag = 1 then          ' Swap frequencies
    '        NAV2_Swap_ON = 1
    '        IOC_NAV2_Swap_flag = 0
    '    endif
    '@ INT_RETURN
    
    
    ProcessEncoder:
    
    
    Start:
          
        LCDOUT $FE, 1 : Pauseus 1
        LCDOUT $FE, $80, "COM/NAV ENCODER TEST" : Pauseus 1
            
    '@ INT_ENABLE IOC_INT
    '    PAUSE 500
    
    
    Mainloop:
        NAV2_Swap_Debounce = (NAV2_Swap_Debounce<<1)   +   NAV2_Swap_Pin 
        if NAV2_Swap_Debounce == $f then                ' Swap button has been debounced and found to have been pressed and now released
            SwapFrequency = NAV2_MHz_Standby    ' Swap MHz frequency
            NAV2_MHz_Standby = NAV2_MHz_Active
            NAV2_MHz_Active = SwapFrequency
    
    
    '        NAV2_Swap_ON = 0                    ' Turn OFF swap flag
        endif
     
        LCDOUT $FE, $D4, "NAV2:", dec3 NAV2_MHz_Standby,_
                             "  ", dec3 NAV2_MHz_Active : Pauseus 1
    
    
        goto mainloop
    end
    Warning I'm not a teacher

  4. #4
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,953


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    Quote Originally Posted by HenrikOlsson View Post
    I'm not sure what I'm looking at in the video but inadequate debounce on the input would be my number one guess....
    The graphs show the signal at the switch and PIC pins; to confirm the absence of bounce on the signal.

    The LCD in the foreground shows the frequencies being swapped back and forth.


    Quote Originally Posted by HenrikOlsson View Post
    ... I believe DT_Ints resets the interrupt request flag on exit of ISR (@ INT_RETURN)...
    - I changed checking IOCBF.2 to checking Port pin; no change, random double-processing.
    - I changed clearing IOCBF.2 = 0 to IOCBF = %00000000; no change, random double-processing.
    - I added an IOC counter, Interrupt is definitely entered TWICE when double-processing.


    Quote Originally Posted by HenrikOlsson View Post
    ... to test you could insert a simple PAUSE 5 or whatever before exiting.
    I'm not sure what this would test. But I still get double-processing with PAUSE 5 in ISR.


    I'm definitely missing proper flag reset out of ISR.
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

  5. #5
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,953


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    Quote Originally Posted by richard View Post
    catching key presses with isr's is never a good look

    a simple polling debounce is way more effective ...
    But isn't IOC specifically designed to handle this? The 16F18877 has IOC across all pins...?


    Quote Originally Posted by richard View Post
    ...what is this about ?
    'PinD2 CON $1A ' Datasheet table 13-2
    'PinD3 CON $1B
    'CCP3PPS = PinD2 ' CCP3 Peripheral input selection
    'CCP4PPS = PinD3 ' CCP4 Peripheral input selection
    ...
    It's PWM on Contrast and Backlight on LCD. I have at least 4 LCDs. That would equate to 8 pots to control contrast and backlight.

    I prefer a HPW solution, that way I can control all LCDs with 1 dual encoder; 1 shaft for contrast, 1 shaft for backlight, and SPST-switch can toggle across each LCD.


    I'm still digesting the code.
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

  6. #6
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,953


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    Look what I just found on p. 208:

    The INLVLB register (Register 12-8) controls the input
    voltage threshold for each of the available PORTB input
    pins. A selection between the Schmitt Trigger CMOS or
    the TTL Compatible thresholds is available. The input
    threshold is important in determining the value of a read
    of the PORTB register and also the level at which an
    interrupt-on-change occurs, if that feature is enabled.
    EDIT: Hmmm, p.212 has 1 as default on port B (ST input).

    Ill try with INLVLB = %00000100, but I doubt it'll make a difference.


    EDIT SOME MORE: Nope, still random double-processing.
    Last edited by Demon; - 6th September 2024 at 09:47.
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

  7. #7
    Join Date
    May 2013
    Location
    australia
    Posts
    2,504


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

    Default Re: IOC on negative edge sometimes triggers twice on single press

    But isn't IOC specifically designed to handle this? The 16F18877 has IOC across all pins...?
    no,
    why would you ever need microsecond responses to a key press ?
    how are you determining the key was held for a reasonable time and not just noise ?
    how are you determining the key was released ?
    how are you determining the key was in fact repressed?

    isr for an emergency stop switch or a limit switch on fast moving machinery that needs protection sure , a human interface device
    i don't think so.


    It's PWM on Contrast and Backlight on LCD. I have at least 4 LCDs. That would equate to 8 pots to control contrast and backlight.
    none of which require an i/p pin

    The graphs show the signal at the switch and PIC pins; to confirm the absence of bounce on the signal.
    if the sample rate of your digital oscilloscope is too low you will never see the bounces, the effective bandwidth is far to low
    what you are viewing is an interpretation not reality. use the highest sample rate/resolution in single channel mode to get the best possible view
    Warning I'm not a teacher

  8. #8
    Join Date
    May 2013
    Location
    australia
    Posts
    2,504


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    Name:  ir-sw4.jpg
Views: 116
Size:  79.9 KB

    see the white negative going spikes that indicate when samples are taken by my routine,

    the spikes are 1 uS in width , on my rigol 100MHz 1Gs/S oscilloscope @ 0.5mS/div they are not accurately rendered nether are all that are in scope always even visible . saleae to the rescue at max res.
    digital tools need to be understood and taken with a pinch of salt

    i should point out @100uS/div all are visible but the display window is too small to see what i was looking for
    Last edited by richard; - 6th September 2024 at 11:28.
    Warning I'm not a teacher

  9. #9
    Join Date
    Aug 2011
    Posts
    438


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

    Default Re: IOC on negative edge sometimes triggers twice on single press

    just a comment...

    If you look at your code in post #1, the only thing the ISR does is set a flag that's read in your mainline code (NAV2_Swap_ON = 1).
    You could drop all the interrupt stuff and just poll the IOCIF flag (or the individual flag bit) in the main loop with the same effect, much as Richard's done.

    The interrupt flag bits get set even if interrupts aren't enabled.

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,563


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    Yes!
    Quite often I see comments like don't do any work in the ISR, just set a flag and do the work in the main loop.

    That's totally fine if what the ISR is doing is, for example, putting UART characters into a buffer and when CR is received sets a flag. When the main loop sees that flag it processes the message.

    But simply setting a flag that there's been an interrupt and then poll that flag in the main loop is...well of not much use and a waste resources. Just poll the interrupt flag (and remember to reset it) instead.

    In general, the ISR should be kepts short and tight (no blocking commands like PAUSE etc (again, in general)) but if you're not actually DOING anytning in the ISR then you might not need an interrupt to begin with.

    Sorry for the rant ;-)

  11. #11
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,953


    Did you find this post helpful? Yes | No

    Default Re: IOC on negative edge sometimes triggers twice on single press

    Quote Originally Posted by HenrikOlsson View Post
    ...But simply setting a flag that there's been an interrupt and then poll that flag in the main loop is...well of not much use and a waste resources. Just poll the interrupt flag (and remember to reset it) instead....
    It's not a rant if you guys help me. I didn't know that about the IOC flag being set regardless (I've done a lot of reading on Interrupt - remembering what I read is something else entirely).

    Richard did find the real problem. I was using 0.01uF for the encoder and the switch. This is what it looked like at higher resolution:




    Then I changed for 0.1uF:



    Just a blip on this one:




    But I have to use 0.01uF on the encoder or else they don't act properly.


    So now I have to decide if I keep the 16F18877 and poll the IOC flag, or go back to the 16F1937 and poll the Port pin. I'm leaning towards the 16F1937 cause it costs a bit less.
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

  12. #12
    Join Date
    Jan 2005
    Location
    Montreal, Quebec, Canada
    Posts
    2,953


    Did you find this post helpful? Yes | No

    Default Re: SOLVED: Post #11 - IOC on negative edge sometimes triggers twice on single press

    Turns out I don't really have a choice to stay with the 16F18877:

    - 16F1937 has TTL General Purpose pins.
    - 16F18877 has TTL and ST General Purpose pins.

    74HC14 only costs $0.09 at JLCPCB, but there's other costs associated with assembly, as well as lost real-estate on the PCB:
    https://jlcpcb.com/parts/componentSe...archTxt=C97666
    My Creality Ender 3 S1 Plus is a giant paperweight that can't even be used as a boat anchor, cause I'd be fined for polluting our waterways with electronic devices.

    Not as dumb as yesterday, but stupider than tomorrow!

  13. #13
    Join Date
    Aug 2011
    Posts
    438


    Did you find this post helpful? Yes | No

    Default Re: SOLVED: Post #11 - IOC on negative edge sometimes triggers twice on single press

    Quote Originally Posted by Demon View Post
    - 16F1937 has TTL General Purpose pins.
    - 16F18877 has TTL and ST General Purpose pins.
    You should be able to set the pin type in the 16F18877 to either ST or TTL to match the 1937 type if that's what you're after.
    I don't think your 'INLVLB = %00000100' statement changed anything for RB2... it's still the default setting.

Similar Threads

  1. Replies: 8
    Last Post: - 30th August 2024, 19:45
  2. calling subroutine triggers interrupt
    By Alexey in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 20th May 2011, 03:50
  3. Replies: 5
    Last Post: - 26th February 2011, 05:51
  4. Button press and press & hold how to ?
    By GrandPa in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 22nd August 2007, 03:37
  5. Best way to find a rising edge?
    By jcsquire in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 31st May 2006, 15:11

Members who have read this thread : 12

You do not have permission to view the list of names.

Posting Permissions

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