Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement event-driven input #4

Open
ClockVapor opened this issue Jul 24, 2016 · 17 comments
Open

Implement event-driven input #4

ClockVapor opened this issue Jul 24, 2016 · 17 comments
Assignees
Labels

Comments

@ClockVapor
Copy link
Owner

@ClockVapor ClockVapor commented Jul 24, 2016

No description provided.

@ClockVapor ClockVapor added task and removed enhancement labels Aug 4, 2016
@asachs01
Copy link

@asachs01 asachs01 commented Aug 29, 2017

Howdy! Any news on implementing the event-driven input?

@codenamev
Copy link
Contributor

@codenamev codenamev commented Jun 12, 2018

I am working on this in my spare time 😄 So far I nearly have the Python equivalent of add_event_detect. If anyone else is working on this, or wants to, feel free to reach out (if I haven't already submitted a PR) and we can sync up.

@ClockVapor
Copy link
Owner Author

@ClockVapor ClockVapor commented Jun 12, 2018

Thanks for helping out, @codenamev. I've put this off for so long now...

@jtoy
Copy link

@jtoy jtoy commented Sep 14, 2019

dead?

@codenamev
Copy link
Contributor

@codenamev codenamev commented Sep 20, 2019

@jtoy I have this about 90% there (got stuck on some GIL issues). Hoping to pick this back up in the next couple weeks. I'll push up my branch shortly if you'd like to see where I'm at?

@jtoy
Copy link

@jtoy jtoy commented Sep 22, 2019

Yes I will test it when you are ready!

@juliancheal
Copy link

@juliancheal juliancheal commented Nov 28, 2019

@codenamev is your event code on a branch? I couldn't seem to find it on your fork. I would love to start looking at this, as I am wanting to port my home automation code over from the python library to ruby. :)

@jezcaudle
Copy link

@jezcaudle jezcaudle commented May 14, 2020

I would love to test this feature too please. I have a JuiceBox that uses BCM 16. Plus I'd like to detect when a button is pushed etc.

@codenamev
Copy link
Contributor

@codenamev codenamev commented May 14, 2020

Hey y'all! Sorry about the silence. I pushed up a WIP of where I got with this. I hit a GIL wall while not correctly executing the ruby blocks during the event setup, but it's getting there. My next move was to just duplicate functionality from the epoll gem. If anyone cares to help out, feel free to ping me.

@tenderlove
Copy link

@tenderlove tenderlove commented Jun 3, 2020

My next move was to just duplicate functionality from the epoll gem. If anyone cares to help out, feel free to ping me.

Any reason to not just add a dependency on the epoll gem and then write the functionality in Ruby? The main advantage is that we don't need to copy / paste from the epoll gem or fight with GVL issues.

I was able to get evented input working with just the epoll gem and a Ruby script.

Here is the code I used:

require 'epoll'

def watch pin, on:
  # Export the pin we want to watch
  File.binwrite "/sys/class/gpio/export", pin.to_s

  # It takes time for the pin support files to appear, so retry a few times
  retries = 0
  begin
    # `on` should be "none", "rising", "falling", or "both"
    File.binwrite "/sys/class/gpio/gpio#{pin}/edge", on
  rescue
    raise if retries > 3
    sleep 0.1
    retries += 1
    retry
  end

  # Read the initial pin value and yield it to the block
  fd = File.open "/sys/class/gpio/gpio#{pin}/value", 'r'
  yield fd.read.chomp

  epoll = Epoll.create
  epoll.add fd, Epoll::PRI

  loop do
    fd.seek 0, IO::SEEK_SET
    epoll.wait # put the program to sleep until the status changes
    yield fd.read.chomp
  end
ensure
  # Unexport the pin when we're done
  File.binwrite "/sys/class/gpio/unexport", pin.to_s
end

pin = 5

watch pin, on: 'both' do |value|
  p value
end

The motion sensor is mounted on top of the Raspberry Pi, and it's connected to pin 5.

Here is a video demo:

event

(Better quality version here).

@codenamev
Copy link
Contributor

@codenamev codenamev commented Jun 4, 2020

Any reason to not just add a dependency on the epoll gem and then write the functionality in Ruby? The main advantage is that we don't need to copy / paste from the epoll gem or fight with GVL issues.

At first, event detection was appearing to be a relatively straightforward port from the python library. I think it's safe to say, it is not 😆 Also, there are some internal pin registration and validation mechanisms in place that would be easier to tie into from the C-side 🌊.

Ultimately it's up to @ClockVapor on adding the epoll dependency. I'm all for it 👍 Your solution is way more elegant than my poorly written C 😄

@tenderlove
Copy link

@tenderlove tenderlove commented Jun 4, 2020

Also, there are some internal pin registration and validation mechanisms in place that would be easier to tie into from the C-side

Can you point me to that code? Maybe we can expose it to Ruby, then use more pure-Ruby solutions.

I could turn my code in to a patch for this library, but a) I don't know how the Python version behaves (like what the API is like) and b) I'm not sure the goals of this library (like is this library supposed to be a 1:1 port of the Python version? Or a more Ruby centric version? Or..?)

@codenamev
Copy link
Contributor

@codenamev codenamev commented Jun 4, 2020

Can you point me to that code? Maybe we can expose it to Ruby, then use more pure-Ruby solutions.

  • get_gpio_number does some channel/pin validation based on the GPIO mode and board configuration
  • check_gpio_priv does some checks for GPIO and system stability. Namely checking that GPIO registers are available and the system has enough available memory.
  • is_gpio_output validates the GPIO directionality configuration (input or output). I also added is_gpio_input as a you should be able to watch either direction.

a) I don't know how the Python version behaves (like what the API is like)

I originally started with the Python library when working through a starter kit, and the process seems to be very heavy handed in setup and tear-down. The methods in place are catered more to introspecting what pins are being watched, and allows for mutating the internal state of what's being watched.

b) I'm not sure the goals of this library (like is this library supposed to be a 1:1 port of the Python version? Or a more Ruby centric version? Or..?)

I'm no maintainer of this (although wouldn't mind 😄 joining), but as a beginner it was much easier to follow along with tutorials where this library's signature matched up with the Python one. When I first dove into this, I went along with that mentality trying to provide as much in parallel whenever possible while also providing more Ruby-centric aliases.

@ClockVapor
Copy link
Owner Author

@ClockVapor ClockVapor commented Jul 23, 2020

@codenamev @tenderlove Finally working on adding this 😃 I'll try going the epoll gem route and leverage @tenderlove's code.

@ClockVapor ClockVapor self-assigned this Jul 24, 2020
@ClockVapor ClockVapor pinned this issue Jul 26, 2020
@ClockVapor
Copy link
Owner Author

@ClockVapor ClockVapor commented Jul 29, 2020

I believe I'm all done implementing this on the develop branch. I've done a little bit of testing so far and I'll do some more, but everyone else feel free to test it out and let me know if you find any issues!

@juliancheal
Copy link

@juliancheal juliancheal commented Jul 29, 2020

Awesome work @ClockVapor I'll check it, thanks for all your work.

@codenamev
Copy link
Contributor

@codenamev codenamev commented Jul 29, 2020

I only did a small test (hooked a button up to an LED, but this worked really well! The bounce rate adjustment worked perfectly and I was able to verify both falling and rising edge detection 😄 I'll test this more heavily over the coming weeks.

Thank you for your excellent work on this 🥇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.