first commit
This commit is contained in:
commit
a5a0434432
1126 changed files with 439481 additions and 0 deletions
270
Software/Ruby/grove_pi.rb
Normal file
270
Software/Ruby/grove_pi.rb
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
module GrovePi
|
||||
require 'i2c'
|
||||
require 'i2c/driver/i2c-dev'
|
||||
|
||||
# Commands.
|
||||
CMD_READ_DIGITAL = 1
|
||||
CMD_WRITE_DIGITAL = 2
|
||||
CMD_READ_ANALOG = 3
|
||||
CMD_WRITE_ANALOG = 4
|
||||
CMD_PIN_MODE = 5
|
||||
CMD_READ_FIRMWARE_VERSION = 8
|
||||
|
||||
# Arduino pin mappings.
|
||||
A0 = 14
|
||||
A1 = 15
|
||||
A2 = 16
|
||||
|
||||
PINS_ANALOG = [A0, A1, A2]
|
||||
|
||||
D2 = 2
|
||||
D3 = 3
|
||||
D4 = 4
|
||||
D5 = 5
|
||||
D6 = 6
|
||||
D7 = 7
|
||||
D8 = 8
|
||||
|
||||
PINS_DIGITAL = [D2, D3, D4, D5, D6, D7, D8]
|
||||
|
||||
# Pin modes.
|
||||
PIN_MODE_IN = 0
|
||||
PIN_MODE_OUT = 1
|
||||
|
||||
# Configuration settings.
|
||||
CONFIG_RETRIES = 10
|
||||
GROVE_PI_I2C_SLAVE_ADDRESS = 4
|
||||
|
||||
# The initialized I2C object.
|
||||
@_i2c_grove_pi = nil
|
||||
|
||||
# Storage for I2C slave addresses present on ports I2C-1, I2C-2 or I2C-3.
|
||||
@_i2c_slave_addresses = Hash.new
|
||||
|
||||
# Internal functions.
|
||||
#
|
||||
# These functions are not intended to be used directly by the user but by the
|
||||
# functions which are exposed to the user.
|
||||
def self._grove_pi_discover()
|
||||
begin
|
||||
i2c_device_files = Dir['/dev/i2c-*']
|
||||
|
||||
if i2c_device_files.length < 1
|
||||
return false, nil
|
||||
end
|
||||
|
||||
# Iterate over I2C device files.
|
||||
for f in i2c_device_files
|
||||
device_file = f
|
||||
f = f.strip
|
||||
f.slice! '/dev/i2c-'
|
||||
lines = %x(#{'i2cdetect -y ' + Integer(f).to_s}).split("\n")
|
||||
|
||||
# Get rid of the first line.
|
||||
lines.shift
|
||||
|
||||
if lines.length < 1
|
||||
next
|
||||
end
|
||||
|
||||
# Process i2cdetect command output for the I2C device file.
|
||||
for i in 0..lines.length - 1
|
||||
line = lines[i].strip
|
||||
line = line.split ':'
|
||||
|
||||
if line.length != 2
|
||||
next
|
||||
end
|
||||
|
||||
for i2c_address in line[1].split(' ')
|
||||
begin
|
||||
if Integer(i2c_address) == GROVE_PI_I2C_SLAVE_ADDRESS
|
||||
return true, device_file.strip
|
||||
end
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
return false, nil
|
||||
end
|
||||
|
||||
return false, nil
|
||||
end
|
||||
|
||||
def self._grove_pi_init()
|
||||
status, i2c_device_file = self._grove_pi_discover
|
||||
|
||||
if status && i2c_device_file != nil
|
||||
return I2CDevice.new address: GROVE_PI_I2C_SLAVE_ADDRESS,
|
||||
driver: I2CDevice::Driver::I2CDev.new(i2c_device_file)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def self._ensure_init()
|
||||
if @_i2c_grove_pi == nil
|
||||
@_i2c_grove_pi = self._grove_pi_init
|
||||
|
||||
if @_i2c_grove_pi == nil
|
||||
raise 'No GrovePi found.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self._set_pin_mode(pin, mode)
|
||||
self._ensure_init
|
||||
@_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_PIN_MODE, pin, mode, 0
|
||||
end
|
||||
|
||||
def self._read_analog(pin)
|
||||
self._ensure_init
|
||||
@_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_READ_ANALOG, pin, 0, 0
|
||||
bytes = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 3).chars
|
||||
return (bytes[1].ord * 256) + bytes[2].ord
|
||||
end
|
||||
|
||||
def self._write_analog(pin, value)
|
||||
self._ensure_init
|
||||
@_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_WRITE_ANALOG, pin, value, 0
|
||||
end
|
||||
|
||||
def self._read_digital(pin)
|
||||
self._ensure_init
|
||||
@_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_READ_DIGITAL, pin, 0, 0
|
||||
return @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 2).chars[0].ord
|
||||
end
|
||||
|
||||
def self._write_digital(pin, value)
|
||||
self._ensure_init
|
||||
@_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_WRITE_DIGITAL, pin, value, 0
|
||||
end
|
||||
|
||||
# Functions exposed to the user.
|
||||
|
||||
# Analog read functions.
|
||||
def self.read_analog(pin)
|
||||
if !PINS_ANALOG.include? pin
|
||||
raise 'Invalid analog pin.'
|
||||
end
|
||||
|
||||
for i in 0..CONFIG_RETRIES - 1
|
||||
begin
|
||||
self._set_pin_mode pin, PIN_MODE_IN
|
||||
return self._read_analog pin
|
||||
rescue Errno::EREMOTEIO
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Analog write functions (PWM on digital pins D3, D5 and D6).
|
||||
def self.write_analog(pin, value)
|
||||
if !PINS_DIGITAL.include? pin
|
||||
raise 'Invalid analog pin. Note: PWM based analog write is applicable on digital ports.'
|
||||
end
|
||||
|
||||
for i in 0..CONFIG_RETRIES - 1
|
||||
begin
|
||||
self._set_pin_mode pin, PIN_MODE_OUT
|
||||
self._write_analog pin, value
|
||||
return
|
||||
rescue Errno::EREMOTEIO
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Digital read function.
|
||||
def self.read_digital(pin)
|
||||
if !PINS_DIGITAL.include? pin
|
||||
raise 'Invalid digital pin.'
|
||||
end
|
||||
|
||||
for i in 0..CONFIG_RETRIES - 1
|
||||
begin
|
||||
self._set_pin_mode pin, PIN_MODE_IN
|
||||
return self._read_digital pin
|
||||
rescue Errno::EREMOTEIO
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Digital write function.
|
||||
def self.write_digital(pin, value)
|
||||
if !PINS_DIGITAL.include? pin
|
||||
raise 'Invalid digital pin.'
|
||||
end
|
||||
|
||||
for i in 0..CONFIG_RETRIES - 1
|
||||
begin
|
||||
self._set_pin_mode pin, PIN_MODE_OUT
|
||||
self._write_digital pin, value
|
||||
return
|
||||
rescue Errno::EREMOTEIO
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Functions for reading and writing I2C slaves connected to
|
||||
# I2C-1, I2C-2 or I2C-3 ports of the GrovePi.
|
||||
def self.read_grove_pi_i2c(i2c_slave_address, length)
|
||||
_ensure_init
|
||||
|
||||
if !@_i2c_slave_addresses.key?(i2c_slave_address)
|
||||
path =
|
||||
@_i2c_grove_pi.instance_variable_get(:@driver)
|
||||
.instance_variable_get(:@path)
|
||||
|
||||
@_i2c_slave_addresses[i2c_slave_address] = I2CDevice.new address: i2c_slave_address,
|
||||
driver: I2CDevice::Driver::I2CDev.new(path)
|
||||
end
|
||||
|
||||
bytes = []
|
||||
_bytes = @_i2c_slave_addresses[i2c_slave_address].i2cget(i2c_slave_address, length).chars
|
||||
|
||||
for b in _bytes
|
||||
bytes << b.ord
|
||||
end
|
||||
|
||||
return bytes
|
||||
end
|
||||
|
||||
def self.write_grove_pi_i2c(i2c_slave_address, *data)
|
||||
_ensure_init
|
||||
|
||||
if !@_i2c_slave_addresses.key?(i2c_slave_address)
|
||||
path =
|
||||
@_i2c_grove_pi.instance_variable_get(:@driver)
|
||||
.instance_variable_get(:@path)
|
||||
|
||||
@_i2c_slave_addresses[i2c_slave_address] = I2CDevice.new address: i2c_slave_address,
|
||||
driver: I2CDevice::Driver::I2CDev.new(path)
|
||||
end
|
||||
|
||||
@_i2c_slave_addresses[i2c_slave_address].i2cset i2c_slave_address, *data
|
||||
end
|
||||
|
||||
# Miscellaneous functions.
|
||||
def self.read_firmware_version()
|
||||
for i in 0..CONFIG_RETRIES - 1
|
||||
begin
|
||||
self._ensure_init
|
||||
@_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_READ_FIRMWARE_VERSION, 0, 0, 0
|
||||
bytes = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 4).chars
|
||||
return [bytes[1].ord, bytes[2].ord, bytes[3].ord]
|
||||
rescue Errno::EREMOTEIO
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Implement rest of the commands that are supported by the firmware.
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue