module GrovePi

Constants

A0

Arduino pin mappings.

A1
A2
CMD_4DIG_BRIGHTNESS
CMD_4DIG_CLOCK
CMD_4DIG_DIGIT
CMD_4DIG_INIT
CMD_4DIG_LEDS
CMD_4DIG_ON
CMD_4DIG_VALUE
CMD_4DIG_VALUE_ZEROS
CMD_PIN_MODE
CMD_READ_ANALOG
CMD_READ_DIGITAL

Commands.

CMD_READ_FIRMWARE_VERSION
CMD_READ_TEMP_HUM
CMD_ULTRASONIC_READ
CMD_WRITE_ANALOG
CMD_WRITE_DIGITAL
CONFIG_RETRIES

Configuration settings.

D2
D3
D4
D5
D6
D7
D8
DISPLAY_RGB_ADDRESS
DISPLAY_TEXT_ADDRESS

LCD RGB display - I2C addresses

GROVE_PI_I2C_SLAVE_ADDRESS
LOCK_FILE_PATH

Initialize the lock file path.

LOCK_REQUEST_PATH
PINS_ANALOG
PINS_DIGITAL
PIN_MODE_IN

Pin modes.

PIN_MODE_OUT

Public Class Methods

_ensure_init() click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 190
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
  GrovePi.get_lock
end
_grove_pi_discover() click to toggle source

Internal functions.

These functions are not intended to be used directly by the user but by the functions which are exposed to the user.

# File lib/templates/grove_pi/grove_pi.rb, line 87
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
_grove_pi_init() click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 179
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
_read_analog(pin) click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 206
def self._read_analog(pin)
  self._ensure_init
  @_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_READ_ANALOG, pin, 0, 0
  read_value = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 3)
  GrovePi.release_lock
  if read_value != nil
    bytes = read_value.chars
    return (bytes[1].ord * 256) + bytes[2].ord
  else
    return 65535
  end
end
_read_digital(pin) click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 225
def self._read_digital(pin)
  self._ensure_init
  @_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_READ_DIGITAL, pin, 0, 0
  val = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 2)
  GrovePi.release_lock
  if val != nil
    return val.chars[0].ord
  else
    return 0
  end
end
_set_pin_mode(pin, mode) click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 200
def self._set_pin_mode(pin, mode)
  self._ensure_init
  @_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_PIN_MODE, pin, mode, 0
  GrovePi.release_lock
end
_write_analog(pin, value) click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 219
def self._write_analog(pin, value)
  self._ensure_init
  @_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_WRITE_ANALOG, pin, value, 0
  GrovePi.release_lock
end
_write_digital(pin, value) click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 237
def self._write_digital(pin, value)
  self._ensure_init
  @_i2c_grove_pi.i2cset @_i2c_grove_pi.address, CMD_WRITE_DIGITAL, pin, value, 0
  GrovePi.release_lock
end
fourDigit_displayClock(pin, string) click to toggle source

Display digits and center colon

string can contain digits (0-9)
# File lib/templates/grove_pi/grove_pi.rb, line 543
def self.fourDigit_displayClock(pin, string)
  self._ensure_init
  string.delete! ":"    # make sure there is no colon in the string
  value = string.to_i
  left = value/100
  right = value % 100
  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_CLOCK, pin, left, right)
  self.release_lock
  return left, right
end
fourDigit_displayDec(pin, string) click to toggle source

Display a decimal value without leading zeros

value = 0 - 9999
# File lib/templates/grove_pi/grove_pi.rb, line 487
def self.fourDigit_displayDec(pin, string)
  self._ensure_init
  value = string.to_i

  # split into 2 bytes
  byte1 = value & 255
  byte2 = value >> 8

  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_VALUE, pin, byte1, byte2)
  
  sleep(0.05)
  GrovePi.release_lock
end
fourDigit_displayOn(pin) click to toggle source

Turn on entire display (88:88)

# File lib/templates/grove_pi/grove_pi.rb, line 478
def self.fourDigit_displayOn(pin)
  self._ensure_init
  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_ON, pin, 0, 0)
  sleep(0.05)
  GrovePi.release_lock
end
fourDigit_displayString(pin, string) click to toggle source

Display a string

string can consist of 0-9
# File lib/templates/grove_pi/grove_pi.rb, line 503
def self.fourDigit_displayString(pin, string)
  self._ensure_init

  if string.include? ":"
    string.delete ":"
  end

  digits = string.chars
  i = 0
  
  while (digits.length < 4)
    digits.unshift(" ")
  end

  #for each space added or each unaccepted character, display an empty space
  #otherwise display the character
  digits.each do |digit|
    if (digit == " ") | ((digit.to_i(16) == 0) & (digit != "0"))
      @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_LEDS, pin, i, 0)
    else
      @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_DIGIT, pin, i, digit.to_i(16))
    end
    i += 1
    sleep(0.05)
  end
  GrovePi.release_lock
end
fourDigit_init(pin) click to toggle source

Initialize four-digit display

# File lib/templates/grove_pi/grove_pi.rb, line 460
def self.fourDigit_init(pin)
  self._ensure_init
  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_INIT, pin, 0, 0)
  GrovePi.release_lock
end
fourDigit_setBrightness(pin, brightness) click to toggle source

Set brightness of display

brightness = 0-7
# File lib/templates/grove_pi/grove_pi.rb, line 533
def self.fourDigit_setBrightness(pin, brightness)
  self._ensure_init
  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_BRIGHTNESS, pin, brightness.to_i, 0)
  sleep(0.05)
  GrovePi.release_lock
end
fourDigit_writeDigit(pin, segment, value) click to toggle source

Set individual digit

segment = 0-3
value = 0-15 or 0-F
# File lib/templates/grove_pi/grove_pi.rb, line 470
def self.fourDigit_writeDigit(pin, segment, value)
  self._ensure_init
  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_4DIG_DIGIT, pin, segment, value)
  sleep(0.05)
  GrovePi.release_lock
end
get_lock() click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 136
def self.get_lock
  cycle = true
  wait = false
  while cycle == true
    begin
      #puts "Getting lock."
      unless @@_lock_request == false && File.exist?(LOCK_REQUEST_PATH)
        @@_i2c_device_file = File.open(LOCK_FILE_PATH, File::WRONLY|File::CREAT|File::EXCL)
        if @@_lock_request == true
          File.delete(LOCK_REQUEST_PATH)
        end
        @@_lock_request = false
      end
      if wait == true
        i = 0
        while i < 1000000
          i += 1
        end
        wait = false
      end
      cycle = false
      #puts "Lock acquired."
    rescue
      #puts "Could not get lock."
      unless File.exist?(LOCK_REQUEST_PATH)
        File.open(LOCK_REQUEST_PATH, File::WRONLY|File::CREAT)
      end
      @@_lock_request = true
      wait = true
    end
  end
end
read_analog(pin) click to toggle source

Analog read functions.

# File lib/templates/grove_pi/grove_pi.rb, line 246
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
read_digital(pin) click to toggle source

Digital read function.

# File lib/templates/grove_pi/grove_pi.rb, line 279
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 => e
      puts e.message
      next
    end
  end
end
read_firmware_version() click to toggle source

Miscellaneous functions.

# File lib/templates/grove_pi/grove_pi.rb, line 359
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
      read_value = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 4)
      GrovePi.release_lock
      if read_value != nil
        bytes = read_value.chars
        return [bytes[1].ord, bytes[2].ord, bytes[3].ord]
      else
        raise "Firmware version could not be read."
      end
    rescue Errno::EREMOTEIO
      next
    end
  end
end
read_grove_pi_i2c(i2c_slave_address, length) click to toggle source

Functions for reading and writing I2C slaves connected to I2C-1, I2C-2 or I2C-3 ports of the GrovePi.

# File lib/templates/grove_pi/grove_pi.rb, line 314
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 = []
  read_value = @_i2c_slave_addresses[i2c_slave_address].i2cget(i2c_slave_address, length)
  GrovePi.release_lock
  
  if read_value != nil
    _bytes = read_value.chars
    for b in _bytes
      bytes << b.ord
    end
    return bytes
  else
    return ["0".ord]
  end
  
end
read_temp_humidity(pin, sensor_version) click to toggle source

Read temperature and humidity values from sensor

# File lib/templates/grove_pi/grove_pi.rb, line 410
def self.read_temp_humidity(pin, sensor_version)
  self._ensure_init
  
  # if sensor is white: module_type = 1, if sensor is blue: module_type = 0
  if sensor_version == "white"
    module_type = 1 
  else 
    module_type = 0
  end

  error = false
  begin
    @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_READ_TEMP_HUM, pin, module_type, 0)   
  rescue => e
    puts e.message
    error = true
  end


  if error == false
    for i in 0..CONFIG_RETRIES - 1
      begin
        # read one byte
        @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 1)

        # read 10 more bytes
        number = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 9)
        GrovePi.release_lock
        if !number.nil?
          temp_value = number[1..4].unpack('f')[0].round(2) * 9/5 + 32 #convert to F
          humidity_value = number[5..8].unpack('f')[0].round(2)
          return temp_value, humidity_value
        else
          return 0.0, -100.0
        end
      rescue Errno::EREMOTEIO
        next
      end
    end
  end
  
  
end
release_lock() click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 169
def self.release_lock
  #puts "Releasing lock."
  if @@_i2c_device_file.is_a?(File)
    @@_i2c_device_file.close
    File.delete(LOCK_FILE_PATH)
    @@_i2c_device_file = nil
    #puts "Lock released."
  end
end
setRGB(red,green,blue) click to toggle source

Set the color of the LCD RGB display

red = 0-255
green = 0-255
blue = 0-255
# File lib/templates/grove_pi/grove_pi.rb, line 579
def self.setRGB(red,green,blue)
  write_lcd_rgb_i2c(DISPLAY_RGB_ADDRESS, 0, 0)
  write_lcd_rgb_i2c(DISPLAY_RGB_ADDRESS, 1, 0)
  write_lcd_rgb_i2c(DISPLAY_RGB_ADDRESS, 0x08, 0xaa)
  write_lcd_rgb_i2c(DISPLAY_RGB_ADDRESS, 4, red.to_i)
  write_lcd_rgb_i2c(DISPLAY_RGB_ADDRESS, 3, green.to_i)
  write_lcd_rgb_i2c(DISPLAY_RGB_ADDRESS, 2, blue.to_i)
end
setText(text) click to toggle source

Set the text on the LCD RGB display

# File lib/templates/grove_pi/grove_pi.rb, line 589
def self.setText(text)
  write_lcd_rgb_i2c(DISPLAY_TEXT_ADDRESS, 0x80, 0x01)
  sleep(0.05)
  write_lcd_rgb_i2c(DISPLAY_TEXT_ADDRESS, 0x80, 0x08 | 0x04)
  write_lcd_rgb_i2c(DISPLAY_TEXT_ADDRESS, 0x80, 0x28)
  sleep(0.05)
  count = 0
  row = 0
  text.chars.each do |c|
    if c == '\n' or count == 16
      count = 0
      row += 1
      if row == 2
        break
      end
      write_lcd_rgb_i2c(DISPLAY_TEXT_ADDRESS, 0x80, 0xc0)
      if c == '\n'
        next
      end
    end
    count += 1
    write_lcd_rgb_i2c(DISPLAY_TEXT_ADDRESS, 0x40, c.ord)
  end
end
ultrasonic_read(pin) click to toggle source

Read distance from ultrasonic ranger

# File lib/templates/grove_pi/grove_pi.rb, line 387
def self.ultrasonic_read(pin)
  self._ensure_init
  @_i2c_grove_pi.i2cset(@_i2c_grove_pi.address, CMD_ULTRASONIC_READ, pin, 0, 0)
  
  sleep(0.06) #firmware has a time of 50ms so wait for more than that

  @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 1)
  GrovePi.release_lock
  
  read_value = @_i2c_grove_pi.i2cget(@_i2c_grove_pi.address, 3)
  
  if read_value != nil
    numbers = read_value.chars
    return (numbers[1].ord) * 256 + (numbers[2].ord)
  else
    return 0
  end
end
write_analog(pin, value) click to toggle source

Analog write functions (PWM on digital pins D3, D5 and D6).

# File lib/templates/grove_pi/grove_pi.rb, line 262
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
write_digital(pin, value) click to toggle source

Digital write function.

# File lib/templates/grove_pi/grove_pi.rb, line 296
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
write_grove_pi_i2c(i2c_slave_address, *data) click to toggle source
# File lib/templates/grove_pi/grove_pi.rb, line 342
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
  GrovePi.release_lock
end
write_lcd_rgb_i2c(i2c_slave_address, *data) click to toggle source

Helper function for communicating with LCD RGB display

# File lib/templates/grove_pi/grove_pi.rb, line 559
def self.write_lcd_rgb_i2c(i2c_slave_address, *data)
  self._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 *data
  GrovePi.release_lock
end