Connecting Button with GPIO and using interupts

In this example we are going to connect the Raspberry PI with a button, and then make  Xojo programs where the first one will read from the button without interrupts and the second will be doing the same using interrupts.

Disclaimer:
We do not take any responsibility for possible errors in the guide or errors that you might do wiring it up. Incorrect wiring can result in damaged sensor or damaged Raspberry PI.

Pieces we use are:

If you are not familiar with working with a breadboard or on how to place a cobbler on the breadboard then click here bellow

If you don’t know resistor color codings to find correct resistors then you can click the link bellow

 

First thing is understanding the wiring of the button:

My button looked like this:

Button

The button had 4 pins, 2 and 2 are same. At first I was not sure how its internal wiring was, as in which two poles were the same and which were the opposite. So I used digital multimeter to get to know its internal wiring.

Do not worry if you don’t know which pins are what on your button, if you get it wrong then worst thing that can happen is the reading of your application will just be always pressed down.

You will want to protect the GPIO pin from mistakes, like if you were to program it as output instead of input then without protection you likely would damage the Raspberry PI. So we use 1K resistor to protect the pin.

1 KOhm resistor in 4 stripe system =  Brown – Black – Red (Read towards the golden stripe)

If you have 5 or 6 stipe system on your resistors then you can 5 and 6 stripe resistors to get help on reading their values if you do not know how.

Now once the resistor is in place then if doing programming error it should not damage the pin.

On the breadboard it looked like this:

ButtonWiring

GPIO Header

So basically red is connected to 3,3 V on the Cobbler, and the other end to the button. From the output of the button we connect the 1K resistor, and from the other end of the button we connect Green which goes from the resistor to the GPIO 6 (which is pin 31) which we choose to use for this example.

The Xojo code without interupts:

An input gpio will float between 0 and 1 if it’s not connected to a voltage. So we will need to take care of that by giving it determined state. We do that by using the GPIO.PullUpDnControl function.

The open event of a window:

Sub Open()
Const kPin = 6
 
GPIO.SetupGPIO
GPIO.PinMode(kPin,GPIO.INPUT)
GPIO.PullUpDnControl(kPin,GPIO.PUD_DOWN)
 
Timer1.Mode = Timer.ModeMultiple
Timer1.Enabled = true
 
End Sub

The timer action event:

Sub Action()
Const kPin = 6
 
for n as Integer = 1 to 10
if GPIO.DigitalRead(kPin) <> 0 then
Listbox1.AddRow "Button was clicked"
end if
App.DoEvents(1)
next
End Sub

This works…… and completes the example without interrupts……

But this is not really great since no matter how tight your timer or loop runs then you will be able to miss clicks.

So here is how we do it with interrupts:

When using interrupts then we must be really careful to not call anything from within the interrupt since Xojo does not support that. So the idea is we have a safe function that only logs the interrupt then we poll the log. That way event is never lost and timer or whatever method you use to poll does not need to be very intensive.

First thing is we need to patch Paul’s GPIO module, adding the following to the module (the function we are adding likely already exists but is not fully implemented so verify that or just blindly override it)  and remember to add the four constants also:

Protected Const EDGE_FALLING = 1
Protected Const EDGE_BOTH = 3
Protected Const EDGE_RISING = 2
Protected Const EDGE_SETUP = 0
 
Protected Function WIringPiISR(pin as integer,edgeType as integer, p as ptr) As Integer
 //This function registers a function to received interrupts on the specified pin.
 // The edgeType parameter is either INT_EDGE_FALLING, INT_EDGE_RISING,
 // INT_EDGE_BOTH or INT_EDGE_SETUP. If it is INT_EDGE_SETUP then no
 // initialisation of the pin will happen – it’s assumed that you have already
 // setup the pin elsewhere (e.g. with the gpio program), but if you specify one
 // of the other types, then the pin will be exported and initialised as specified.
 // This is accomplished via a suitable call to the gpio utility program,
 // so it need to be available.
 //
 // The pin number is supplied in the current mode – native wiringPi, BCM_GPIO,
 // physical or Sys modes.
 //
 // This function will work in any mode, and does not need root privileges to work.
 //
 // The function will be called when the interrupt triggers.
 // When it is triggered, it’s cleared in the dispatcher before calling your
 // function, so if a subsequent interrupt fires before you finish your handler,
 // then it won’t be missed. (However it can only track one more interrupt,
 // if more than one interrupt fires while one is being handled then they will be ignored)
 //
 // This function is run at a high priority (if the program is run
 // using sudo, or as root) and executes concurrently with the main program.
 // It has full access to all the global variables, open file handles and so on.
 //
 // See the isr.c example program for more details on how to use this feature.
 
 
 #If TargetARM And TargetLinux Then
 Soft Declare Function wpISR Lib "libwiringPi.so" Alias "wiringPiISR" (pin As Integer, mode As Integer, p as ptr) as Integer
 return wpISR(pin, edgeType,p)
 #Endif
 
End Function

Next we create a module which we will call InteruptModule and this module will contain the following things:

Private DownEventCount As Integer
 
Protected Sub ButtonDownInterupt()
 // We need some pragmas here to make this safe since this is called from interupt.
 #Pragma StackOverflowChecking False
 #Pragma DisableBackgroundTasks
 
 // NOTE since we are in interupt then we may not call any methods here it is not safe
 // however we can count the number of occurances and poll this module with a timer or by other means, and by doing that we can be sure that no clicks were missed.
 DownEventCount = DownEventCount + 1
End Sub
 
Protected Function GetDetectedClicks() As Integer
 Dim tmp as Integer = DownEventCount
 
 DownEventCount = 0
 return tmp
End Function

Then the Window open event will look like this:

Sub Open()
 
 Const kPin = 6
 
 GPIO.SetupGPIO
 GPIO.PinMode(kPin,GPIO.INPUT)
 GPIO.PullUpDnControl(kPin,GPIO.PUD_DOWN)
 
 if GPIO.WIringPiISR(kPin,GPIO.EDGE_RISING,Addressof InteruptModule.ButtonDownInterupt) = -1 then
 MsgBox "Could not register interupt for pin number " + Str(kPin)
 end if
 
 Timer1.Mode = Timer.ModeMultiple
 Timer1.Enabled = true
 
End Sub

And the timer action event will look like this:

Sub Action()
  Dim clicks as Integer
 
 clicks = InteruptModule.GetDetectedClicks()
 
 if clicks > 0 then
 Listbox1.AddRow "Button was clicked"
 end if
End Sub

No button clicks should ever get missed now.

Thats it for now !


AliExpress.com Product - Electronic Fans Kit Breadboard Cable Resistor Capacitor LED Potentiometer for Arduino FZ0869

Leave a Reply

Einhugur technical blog that involves Xojo and Einhugur Xojo plugin related topics

%d bloggers like this: