Menu

Not sure I completely understand the demo code for button presses

2017-11-26
2019-12-27
  • George Alvarez

    George Alvarez - 2017-11-26

    Hi, let me just start out by saying I'm very new at this and some of the questions I ask might be a little "basic"

    Long story short, the results I get from the example code are wildly inaccurate. When left alone, the button shows pressed ALMOST ALL THE TIME. This occurs whether I have the state_switch set to off or on.

    I'll include everything down below:
    a) the slightly modified code
    b) the terminal output
    c) breadboard setup

    All I want to do is know how to reliably detect a button push so that I can execute some other code I've got.

    Here are the questions I have:

    1) Should the state_switch be OFF or ON?
    2) What is the input_event function for?
    3) Where would I use input_switch function to debounce?
    4) What could be causing the phantom button presses?
    5) How can I prevent them?
    6) Do I have everything wired ok?

    Thanks

    ----- the code

    '''A demonstration program for GCGB and GCB.
    ''' Interrupt - OnChange event example - Interrupt Switch Counter for mega328p
    '''--------------------------------------------------------------------------------------------------------------------------------
    '''This program demonstrates Interrupt upon the button press on portb.0
    '''Each microprocessor will have different commands to setup the Interrupt. Refer to datasheet.
    '''When each interrupt event occurs a counter is incremented.
    '''Afer each event the counter is shown on the terminal.
    '''The demonstration also show the four states a button can be in UP, PRESSED, DOWN and RELEASED.
    '''Enjoy
    '''@author  EvanV
    '''@licence GPL
    '''@version 1.1a
    '''@date    20.02.2015
    '''********************************************************************************
    
     #chip mega328p, 16
     #option explicit
    
    ; ----- Define Hardware settings
      'Config hardware UART
      #define USART_BLOCKING
      #define USART_BAUD_RATE 9600
      #define USART_DELAY 10 ms
    
      'Required for switch_event method
      Dir SwitchIn1 In
    
    ; ----- Constants
      'Required for switch_event method
      #Define BUTTON_UP 0
      #Define BUTTON_PRESSED 1
      #Define BUTTON_DOWN 2
      #Define BUTTON_RELEASED 3
      #Define BUTTON_UNKNOWN 4
    
      'Required for switch_event method
      #define SwitchIn1 PORTb.0
      #define check_switch PORTb.0
      #define state_switch OFF
    
    ;----- Variables
      Dim CURRENT_STATE, OLD_STATE, BTN as Byte
      Dim ButtonPressCount as BYTE
      ButtonPressCount = 0
    
      'Required for switch_event method
      Dim btn_pv
    
    ; ----- Main body of program commences here.
    
      'Enable portb.0 as the source of the interrupt. See the datasheet for more information.
      'Trigger on change of PB0
      PCINT0 = 1
      On Interrupt PinChange0  Call ButtonPressed
    
      Wait 5 s
      HSerPrintCRLF 2
      HSerPrint "Started"
      HSerPrintCRLF
    
      'track button presses - required to manage serial display only
      old_state = 0
    
      do forever
         'determine the state of the switch
         current_state = switch_event
    
         'if the current state is not the same as the saved state then print current state
         if current_state <> old_state then
            HSerPrint "Changed State: "
            HSerPrint current_state
            HSerPrintCRLF
            'save state
            old_state = current_state
         else
            HSerPrint "Stable State: "
            HSerPrint current_state
            HSerPrintCRLF
         end if
         'if the current state is Released then show the count.
         'count is incremented in the Interrupt routine.
         if current_state = BUTTON_RELEASED then
            HSerPrint "Button Press Count: ("
            HserPrint ButtonPressCount
            HSerPrint ")"
            HSerPrintCRLF
            ' Restore intterupt
            On Interrupt PinChange0  Call ButtonPressed
         end if
         'print only if the button is Pressed. Formatting display only.
         if current_state = BUTTON_PRESSED then
            HSerPrintCRLF
            HSerPrint "PRESS!"
            HSerPrintCRLF
         end if
    
      loop
      end
    
    ; ----- Support methods.  Subroutines and Functions
     sub ButtonPressed
    
         'Check port is depressed/down? If yes, then increment counter
         if check_switch = 1 then
             ButtonPressCount++
             On Interrupt PinChange0  Ignore
         end if
    
     end sub
    
    '/****************************************************************************
    '  Function:
    '    input_event(void)
    '
    '  Summary:
    '    Processes the single button into the states UP, DOWN, PRESSED & RELEASED.
    '
    '  Description:
    '    This function helps write user interface state machines by determining when
    '    the button was pressed, released
    '
    '  Precondition:
    '    None
    '
    '  Parameters:
    '    None
    '
    '  Returns:
    '    event_t value of the current button events.
    '    Valid responses are BUTTON_UP, BUTTON_DOWN, BUTTON_PRESSED, BUTTON_RELEASED
    '
    '  Remarks:
    ' state_switch inverts the port. If high then use state_switch=off
    
    ' #define SwitchIn1 PORTD.2
    ' Dir SwitchIn1 In
    ' #define check_switch RD2
    ' #define state_switch OFF
    '
    ' ***************************************************************************/
    
      function switch_event()
          dim ret As byte
          Dim btn as Byte
    
          btn = check_switch = state_switch
    
         if !btn & !btn_pv then
                    ' button is not pressed now nor was it pressed previously
              ret = BUTTON_UP
    
          END if
          if btn & !btn_pv then
                    ' button is pressed now but it wasn't previously
              ret = BUTTON_PRESSED
    
          End if
          if btn & btn_pv  then
                    ' button was pressed previously and is still pressed
              ret = BUTTON_DOWN
    
          end if
          if !btn & btn_pv    then
                    ' button is not pressed now but it was previously
              ret = BUTTON_RELEASED
          End If
    
          btn_pv = btn
          switch_event = ret
      End Function
    
      ' Debounce button, Debounce switch
      Function input_switch (  )
    
          input_switch  = false
          If check_switch = state_switch Then
              ButtonCount = 0
              Do While check_switch = state_switch and ButtonCount < 4
                  wait 5 ms
                  ButtonCount = ButtonCount + 1
              Loop
          end if
          If ButtonCount > 3 then
              input_switch  = true
              ButtonCount = 0
          end if
      End Function
    

    ----- terminal output

    'Required for switch_event method
    Define BUTTON_UP 0
    Define BUTTON_PRESSED 1
    Define BUTTON_DOWN 2
    Define BUTTON_RELEASED 3
    Define BUTTON_UNKNOWN 4

    Started
    Changed State: 2
    Changed State: 3
    Button Press Count: (1)
    Changed State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Changed State: 1

    PRESS!
    Changed State: 3
    Button Press Count: (2)
    Changed State: 0
    Stable State: 0
    Stable State: 0
    Changed State: 1

    PRESS!
    Changed State: 3
    Button Press Count: (3)
    Changed State: 0
    Changed State: 1

    PRESS!
    Changed State: 2
    Stable State: 2
    Stable State: 2
    Changed State: 3
    Button Press Count: (4)
    Changed State: 1

    PRESS!
    Changed State: 2
    Changed State: 3
    Button Press Count: (5)
    Changed State: 0
    Stable State: 0
    Stable State: 0
    Changed State: 1

    PRESS!
    Changed State: 3
    Button Press Count: (6)
    Changed State: 0
    Changed State: 1

    PRESS!
    Changed State: 2
    Stable State: 2
    Stable State: 2
    Stable State: 2
    Changed State: 3
    Button Press Count: (7)
    Changed State: 0
    Changed State: 1

    PRESS!
    Changed State: 2
    Changed State: 3
    Button Press Count: (8)
    Changed State: 0
    Stable State: 0
    Stable State: 0
    Changed State: 1

    PRESS!
    Changed State: 3
    Button Press Count: (9)
    Changed State: 0
    Changed State: 1

    PRESS!
    Changed State: 2
    Stable State: 2
    Stable State: 2
    Changed State: 3
    Button Press Count: (10)

    ----- breadboard setup

    Arduino Nano clone w/ ATMega328P

    Nano pin color wire to ...

    A4 Green to SDA display 1 to Orange SDA display 2
    A5 Yellow to SCL display 1 to Yellow SDA display 2
    5V Orange to VCC display 1
    5V Orange to VCC display 2
    A pins side GND Black to GND display 1
    A pins side GND Black to GND display 2
    D pins side GND to switch
    D8 to switch

    not that it's much help, but I've included a couple of pictures as well:

     

    Last edit: George Alvarez 2017-11-26
  • George Alvarez

    George Alvarez - 2017-11-26

    oops!

     

    Last edit: George Alvarez 2017-11-26
    • Anobium

      Anobium - 2017-11-26

      Welcome.

      A good post!

      This is probably my fault. In the header of the example is does not provide one important statement.... add a suitable resistor to pull up the port to which the switch is attached.

      So, do you have a pull-up (or, pull-down) resistor fitted? https://en.wikipedia.org/wiki/Pull-up_resistor

       
  • George Alvarez

    George Alvarez - 2017-11-26

    Hi, thanks for responding. A great product/project you have here.

    I was hoping to get away with the internal resistor only, but I guess you're saying that doesn't work. OK, I'll hook it up and report back. I think I understand what it does.

    What about that debouncing code? As far as I can tell, it's not actually used. Maybe I missed the call to the function, but I don't see it anywhere.

    Thanks again.

     
  • George Alvarez

    George Alvarez - 2017-11-26

    Anobium, here's my report:

    First I tried a pull-down resistor,10K ohm between ground pin on the Nano and the switch. This did not behave much differently. Then I tried 2.2K, that didn't work either. Then I kept going down, my next value without having to go to the store was 680 Ohms. They all acted pretty much the same, where at first, BUTTON_UP (0) was the usual state. But by the 10th false positive button press, I never saw a 0 again.

    The 10K pull-up resistor, on the other hand, works flawlessly. No false positives in 1500 cycles, and always responsive to a button click, even on the quickest clicks using my cheapest (i.e. electronically noisiest) button!

    Like this:

    Started
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0

    then I click my button:

    Changed State: 1

    PRESS!
    Changed State: 2
    Changed State: 3
    Button Press Count: (8)
    Changed State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0
    Stable State: 0

    So, I'm very happy with this, as I can now proceed with the rest of my project. Thank you for your help with this, and for all the work you do on this too.

    However, I'm still left with some of my original questions:

    1) Why would I use state_switch ON vs. OFF? Can you provide a practical example?

    2) What is the input_event function for? Is this merely the old comments for new and improved switch_event function that performs the same function?

    3) Where would I use input_switch function to debounce? In other words, where would I call this function in the code? I still don't see where it is ever called.

    4) What could be causing the phantom button presses? Never mind. I think I have a sense of this.

    5) How can I prevent them? Totally answered! Thank you.

    6) Do I have everything wired ok? It seems like I do.

    Thanks again!

    George

     
  • Anobium

    Anobium - 2017-11-27

    1) Why would I use state_switch ON vs. OFF? Can you provide a practical example?
    Some boards, like the Microchip boards have the switch pulled low. So, you can invert.
    2) What is the input_event function for? Is this merely the old comments for new and improved switch_event function that performs the same function?
    Old comments... when this was ported this was left iin. Delete.
    3) Where would I use input_switch function to debounce? In other words, where would I call this function in the code? I still don't see where it is ever called.
    This can be used, optional
    4) What could be causing the phantom button presses? Never mind. I think I have a sense of this.
    5) How can I prevent them? Totally answered! Thank you.
    6) Do I have everything wired ok? It seems like I do.

    Welcome.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.