class YaGPIO
YaGPIO
is a simple module to control GPIO port on a Raspberry Pi. It's based on the Sysfs interface.
@example Open port 22 as output and set it to high
pin = YaGPIO.new(22, YaGPIO::OUTPUT) pin.high
@example Open port 23 as input and read its state
pin = YaGPIO.new(23, YaGPIO::INPUT) pp pin.low?
Constants
- EDGE_BOTH
Interruption on rising and falling edge
- EDGE_FALLING
Interruption on falling edge
- EDGE_NONE
Disable interruption
- EDGE_RISING
Interruption on rising edge
- INPUT
Direction input
- MAX_RETRY
- OUTPUT
Direction output with default low
- OUTPUT_HIGH
Direction output with default high
- VERSION
Attributes
File descriptor to the sysfs entry of the pin. It is not recommended to access the file directly. Use high() lov() helpers instead.
Public Class Methods
Create and configure a new GPIO pin. The pin will be exported via the sysfs interface. The pin will be unexported and released for other use upon garbage collection.
@param pin [Integer] Pin number to configure, using the BCM numbering @param direction [String] The direction if the port. Must be one of INPUT
, OUTPUT
or OUTPUT_HIGH
# File lib/ya_gpio.rb, line 64 def initialize(pin, direction) raise 'direction must be one of INPUT, OUTPUT, OUTPUT_HIGH' unless [INPUT, OUTPUT, OUTPUT_HIGH].include?(direction) @pin = pin @callback = nil @direction = direction export open ObjectSpace.define_finalizer(self, self.class.finalize(@pin)) end
Stop the wait loop, must be run from a callback triggered by YaGPIO::wait()
# File lib/ya_gpio.rb, line 177 def self.resume @@wait = false end
Wait for an interruption to be trigerred and run the associated callback. This method will block until the program exits or YaGPIO::resume()
is called from a callback.
Note that software debounce has not been implemented. You can use a 1µF capacitor in your setup to fix bounce issues.
@param gpios [Array] Array of YaGPIO
to monitor
# File lib/ya_gpio.rb, line 161 def self.wait(gpios) # Initial read to clear interrupt triggered during setup gpios.map{|g| g.high?} @@wait = true while @@wait do rs, ws, es = IO.select(nil, nil, gpios.map{|g| g.file}) es.each do |f| gpio = gpios.select{|g| g.file == f}.first gpio.trigger(gpio.high?) end end end
Private Class Methods
Unexport the port when the program exits
# File lib/ya_gpio.rb, line 234 def self.finalize(pin) proc do File.write('/sys/class/gpio/unexport', pin) end end
Public Instance Methods
Invert all values and settings. After set to true, HIGH means LOW and LOW means HIGH. Be prepared to be confused if you're using this feature.
@param active [Boolean] Feature state
# File lib/ya_gpio.rb, line 106 def active_low=(active) File.write("/sys/class/gpio/gpio#{@pin}/active_low", active ? '1' : '0') end
Return true is active_low feature is enabled
@return [Boolean] Feature state
# File lib/ya_gpio.rb, line 113 def active_low? File.read("/sys/class/gpio/gpio#{@pin}/active_low") != '0' end
Disable a previously set interruption
# File lib/ya_gpio.rb, line 129 def clear_interrupt() set_edge(EDGE_NONE) @callback = nil end
Set the pin to high
# File lib/ya_gpio.rb, line 93 def high write(1) end
Return true if the pin is high
@return [Boolean] State of the pin
# File lib/ya_gpio.rb, line 81 def high? read() != 0 end
Set the pin to low
# File lib/ya_gpio.rb, line 98 def low write(0) end
Return true if the pin is low
@return [Boolean] State of the pin
# File lib/ya_gpio.rb, line 88 def low? read() == 0 end
Define a callback to execute when an interruption will be triggered.
@param edge [String] Edge to trigger interrution. Can be EDGE_RISING
, EDGE_FALLING
or EDGE_BOTH
@param block [Block] Block to execute as callback
# File lib/ya_gpio.rb, line 121 def set_interrupt(edge, &block) raise 'interrupt can only be set on input pin' unless @direction == INPUT set_edge(edge) @callback = block end
Execute the interruption's callback.
@param active [Boolean] Should be true if the pin is high
# File lib/ya_gpio.rb, line 137 def trigger(active) if @callback.nil? puts "No Callback defined for #{@pin}" else @callback.call(active) end end
Release the pin. The object cannot be used after this method is called as the pin will not be configured anymore.
# File lib/ya_gpio.rb, line 147 def unexport() @file.close File.write('/sys/class/gpio/unexport', @pin.to_s) end
Private Instance Methods
# File lib/ya_gpio.rb, line 186 def export() begin File.write('/sys/class/gpio/export', @pin.to_s) rescue Errno::EBUSY puts "WARNING: GPIO #{@pin} is already exported, may be in use." end end
# File lib/ya_gpio.rb, line 194 def open begin retries ||= 0 case @direction when INPUT @file=File.open("/sys/class/gpio/gpio#{@pin}/value", 'r') else @file=File.open("/sys/class/gpio/gpio#{@pin}/value", 'r+') end @file.sync=true # Auto flush File.write("/sys/class/gpio/gpio#{@pin}/direction", @direction) rescue Errno::EACCES if (retries += 1) <= MAX_RETRY puts "Permission on sysfs not ready yet, retrying (#{retries}/#{MAX_RETRY})..." sleep 0.1 retry end raise end end
# File lib/ya_gpio.rb, line 223 def read() @file.seek(0, IO::SEEK_SET) @file.read().to_i end
# File lib/ya_gpio.rb, line 217 def set_edge(edge) raise 'edge must be one of EDGE_RISING, EDGE_FALLING, EDGE_BOTH, EDGE_NONE' unless [EDGE_RISING, EDGE_FALLING, EDGE_BOTH, EDGE_NONE].include?(edge) File.write("/sys/class/gpio/gpio#{@pin}/edge", edge) end
# File lib/ya_gpio.rb, line 228 def write(value) @file.seek(0, IO::SEEK_SET) @file.write(value) end