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[R]

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

new(pin, direction) click to toggle source

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
resume() click to toggle source

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(gpios) click to toggle source

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

finalize(pin) click to toggle source

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

active_low=(active) click to toggle source

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
active_low?() click to toggle source

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
clear_interrupt() click to toggle source

Disable a previously set interruption

# File lib/ya_gpio.rb, line 129
def clear_interrupt()
        set_edge(EDGE_NONE)   
        @callback = nil
end
close()
Alias for: unexport
high() click to toggle source

Set the pin to high

# File lib/ya_gpio.rb, line 93
def high
        write(1)
end
high?() click to toggle source

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
low() click to toggle source

Set the pin to low

# File lib/ya_gpio.rb, line 98
def low
        write(0)
end
low?() click to toggle source

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
set_interrupt(edge, &block) click to toggle source

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
trigger(active) click to toggle source

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
unexport() click to toggle source

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
Also aliased as: close

Private Instance Methods

export() click to toggle source
# 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
open() click to toggle source
# 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
read() click to toggle source
# File lib/ya_gpio.rb, line 223
def read()
        @file.seek(0, IO::SEEK_SET)
        @file.read().to_i
end
set_edge(edge) click to toggle source
# 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
write(value) click to toggle source
# File lib/ya_gpio.rb, line 228
def write(value)
        @file.seek(0, IO::SEEK_SET)
        @file.write(value)
end