C
C#2y ago
dvd

❔ GPIO listening to button events (Raspbery Pi w breakout board)

Im using GpioController to control the GPIO pins on my Raspberry pi, i have a breakout board with some LEDs on it and a couple of buttons. Controlling the leds has been pretty easy so far, as they are not something I have to actively listen to but I'm trying to make a method that will listen to all connected buttons (there are total of 6 of them) and do something based on when they are pressed (For testing im simply trying to print to console with their respective button number) I've tried a couple of things, but Im having issues in their behavior (you press once, it keeps going off for eternity) and in general I think I'm doing it in a convoluted way. Does anyone know the best method to listen for button presses (on the background) and then upon button press allow them to execute a piece of code? the extent of what I have tried so far mainly revolves around opening all pins that are buttons
public static async Task ButtonWatcher(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
List<int> buttonList = new List<int>() {22,27,17,4,3,6};
foreach (int pin in buttonList)
{
_controller.OpenPin(pin);
}
// Logic here to listen to them
}
}
public static async Task ButtonWatcher(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
List<int> buttonList = new List<int>() {22,27,17,4,3,6};
foreach (int pin in buttonList)
{
_controller.OpenPin(pin);
}
// Logic here to listen to them
}
}
I have no idea if this is the right approach and any pointers would be greatly appreciated
38 Replies
dvd
dvdOP2y ago
Oh and the _controller is just an instance of gpiocontroller GpioController _controller = new GpioController();
canton7
canton72y ago
Are you sure you've set the pull-ups/pull-downs on the button inputs as appropriate? Or do you have external pull-up/pull-down resistors?
dvd
dvdOP2y ago
They are setup yeah
canton7
canton72y ago
Where? Are they external? Your code doesn't enable the internal pull-ups/pull-downs?
dvd
dvdOP2y ago
Its a breakout board that is wired to another one that has resistors on them It functions properly in a python project it came with, not sure how they handle it
canton7
canton72y ago
I'd also avoid calling OpenPin on every loop iteration Also try specifying the PinMode when you call OpenPin?
dvd
dvdOP2y ago
Good points Is there a more elegant way to open all these pins in 1 go?
canton7
canton72y ago
Also, what's the logic in // Logic here to listen to them? Maybe that has a problem Doesn't look like it, from the docs Although I'm not familiar with GpioController itself
dvd
dvdOP2y ago
They are are a bunch of tasks that refer to a corresponding method based on the pin number
static async Task PinEvent4(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
WaitForEventResult waitResult;
waitResult = await _controller.WaitForEventAsync(4, PinEventTypes.Falling, token);
int count = 0;
do
{
if (!waitResult.TimedOut)
{
Console.WriteLine(
$"[{count++}] Button was pressed: GPIO pin number 4, ChangeType={waitResult.EventTypes}");
Thread.Sleep(1000);
}
} while (waitResult.EventTypes != PinEventTypes.Rising);

await Task.Delay(Timeout.Infinite, token);
}
}
static async Task PinEvent4(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
WaitForEventResult waitResult;
waitResult = await _controller.WaitForEventAsync(4, PinEventTypes.Falling, token);
int count = 0;
do
{
if (!waitResult.TimedOut)
{
Console.WriteLine(
$"[{count++}] Button was pressed: GPIO pin number 4, ChangeType={waitResult.EventTypes}");
Thread.Sleep(1000);
}
} while (waitResult.EventTypes != PinEventTypes.Rising);

await Task.Delay(Timeout.Infinite, token);
}
}
This is pin 4 for example, mainly trying to get one button working properly before moving on to all
dvd
dvdOP2y ago
Which after pressing the button once results in this
canton7
canton72y ago
Wait, that means the pin is constantly rising/falling, rather than just being stuck low?
dvd
dvdOP2y ago
It seems so, but only after the initial press If i do rising, it will always be going off Ill give it a quick try though with pinmode as input
canton7
canton72y ago
Ah, d'oh
do
{
if (!waitResult.TimedOut)
{
Console.WriteLine(
$"[{count++}] Button was pressed: GPIO pin number 4, ChangeType={waitResult.EventTypes}");
Thread.Sleep(1000);
}
} while (waitResult.EventTypes != PinEventTypes.Rising);
do
{
if (!waitResult.TimedOut)
{
Console.WriteLine(
$"[{count++}] Button was pressed: GPIO pin number 4, ChangeType={waitResult.EventTypes}");
Thread.Sleep(1000);
}
} while (waitResult.EventTypes != PinEventTypes.Rising);
There's no code to re-read waitResult in there So yeah, of course it keeps printing the waitResult -- because it's Falling when you enter that loop, and it's never re-assigned so it never becomes something other than Falling
dvd
dvdOP2y ago
ahh
canton7
canton72y ago
Also don't use Thread.Sleep in async code. If you need to delay, use await Task.Delay(...)
dvd
dvdOP2y ago
Alright, ill give it a quick test, ill reassign waitResult.EvenTypes to rising and ive set the pin type to input Yeah that stopped it from repeating I think i should flip them actually, i only picked falling because it was spamming on rising
canton7
canton72y ago
What's the point of that loop anyway? Just print all edges?
dvd
dvdOP2y ago
Im not sure what you mean with print all edges
canton7
canton72y ago
What are you trying to achieve with that loop?
dvd
dvdOP2y ago
But my basic goal is to have a press of 'button 1' result in 'Button 1 was pressed' to show up in console (I mean later there will be logic tied to what it needs to execute but thats not important for now) And only do that once, for every time i press a button
dvd
dvdOP2y ago
It sort of works now i think, it just prints it out 4 times each time i press it assuming I want the 500ms task delay i put in
canton7
canton72y ago
Ah, so:
static async Task PinEvent4(CancellationToken token)
{
int count = 0;
while (!token.IsCancellationRequested)
{
var waitResult = await _controller.WaitForEventAsync(4, PinEventTypes.Falling, token);
if (waitResult.EventTypes.HasFlag(PinEventTypes.Falling))
{
Console.WriteLine(
$"[{count++}] Button was pressed: GPIO pin number 4, ChangeType={waitResult.EventTypes}");
}
}
}
static async Task PinEvent4(CancellationToken token)
{
int count = 0;
while (!token.IsCancellationRequested)
{
var waitResult = await _controller.WaitForEventAsync(4, PinEventTypes.Falling, token);
if (waitResult.EventTypes.HasFlag(PinEventTypes.Falling))
{
Console.WriteLine(
$"[{count++}] Button was pressed: GPIO pin number 4, ChangeType={waitResult.EventTypes}");
}
}
}
?
dvd
dvdOP2y ago
I will say this current code is the result of just throwing shit at the wall and seeing what sticks, i think i overcomplicated it for no reason Yeah
static async Task PinEvent4(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
WaitForEventResult waitResult;
waitResult = await _controller.WaitForEventAsync(4, PinEventTypes.Falling, token);
do
{
if (!waitResult.TimedOut)
{
Console.WriteLine(
$"[Button 4, ChangeType={waitResult.EventTypes}");
await Task.Delay(100);
waitResult.EventTypes = PinEventTypes.Rising;
}
} while (waitResult.EventTypes != PinEventTypes.Rising);
await Task.Delay(500, token);
}
}
static async Task PinEvent4(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
WaitForEventResult waitResult;
waitResult = await _controller.WaitForEventAsync(4, PinEventTypes.Falling, token);
do
{
if (!waitResult.TimedOut)
{
Console.WriteLine(
$"[Button 4, ChangeType={waitResult.EventTypes}");
await Task.Delay(100);
waitResult.EventTypes = PinEventTypes.Rising;
}
} while (waitResult.EventTypes != PinEventTypes.Rising);
await Task.Delay(500, token);
}
}
This is what i have now, made it a bit shorter since that Console.WriteLine doesnt need to be very detailed anyway
canton7
canton72y ago
That do...while and waitResult.EventTypes = PinEventTypes.Rising; just cancel each other out It means you'll never loop around that loop more than once And once you strip that out, it starts looking like my code
dvd
dvdOP2y ago
thats true
canton7
canton72y ago
Oh, unless it's TimedOut, but that won't happen anyway? And besides you've got the outer loop for that
dvd
dvdOP2y ago
Yeah good point Im gonna try yours now, one slight edit because I just did the order wrong for Rising and Falling; it was spamming falling over and over until i would press and hold the button
canton7
canton72y ago
Also it's racey: if you get an edge after WaitForEventAsync returns before you call it again, you'll miss that event
dvd
dvdOP2y ago
Yeah, im not sure how to best approach that ideally it wouldnt matter how quickly you spam the button
dvd
dvdOP2y ago
Could you give me pointers on how to implement that? I'm not really certain how to do it if not thats fine too, I think this was in one of my open tabs but i couldnt figure it out or find a guide online
canton7
canton72y ago
Looking at the docs,
_controller.RegisterCallbackForPinValueChangedEvent(4, PinEventTypes.Falling, PinChangedHandler);

void PinChangedHandler(object sender, PinValueChangedEventArgs args)
{
Console.WriteLine($"Pin {args.PinNumber}: {args.ChangeType}");
}
_controller.RegisterCallbackForPinValueChangedEvent(4, PinEventTypes.Falling, PinChangedHandler);

void PinChangedHandler(object sender, PinValueChangedEventArgs args)
{
Console.WriteLine($"Pin {args.PinNumber}: {args.ChangeType}");
}
Or whatever PinEventTypes you care about -- PinEventTypes.Rising | PinEventTypes.Falling for both
dvd
dvdOP2y ago
Alright, thanks! Ill give this a try, thanks for all the help Canton
canton7
canton72y ago
Sweet! No worries
dvd
dvdOP2y ago
Also fun little problem, i noticed if i hover my finger like a half an inch / few mm above the button it is already activating lol
canton7
canton72y ago
Hah That strongly suggests that you don't have those pull-up resistors working right?
dvd
dvdOP2y ago
Yep, I think something got disconnected
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server