Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Embedding Ruby into your Daily Life

Embedding Ruby into your Daily Life

Many Rubyists know Ruby for its ease of use as a web scripting language. Many sysadmins know Ruby for its server provisioning capacity and as a glue language to the shell. Many Rubyists don't know about how Ruby can be used in the world of embedded computing and microcontrollers to assist your daily life. Mruby expands the capabilities to robotics and hobby electronics, as well as small-scale automation. Learn about ways to embed ruby into your daily life with heat control, plant watering, helpful robots, and more.

Andrew Nordman

August 03, 2013
Tweet

More Decks by Andrew Nordman

Other Decks in Programming

Transcript

  1. • eLearning Technology Company • Work Training, Compliance, Learning •

    Software Engineer • We’re Hiring Saturday, August 3, 13
  2. • Nanobrewery • Small-batch, Diverse Beer • Co-Founder / Brewer

    • We’re Not Hiring Saturday, August 3, 13
  3. • Father of Two • Sleep Deprivation Tool • I

    Wish We Were Hiring Saturday, August 3, 13
  4. Voltage Logic Component CPU Here’s 3.3V @ 40mA! Oh? Then,

    here’s 5V @ 40mA! Why so LOW? Not enough to trigger me to HIGH state. Much better, setting to HIGH state. Saturday, August 3, 13
  5. General Purpose I/O • Expansion pins on a development board

    • Programmable voltage control • Accessible via UNIX file handles echo “17” > /sys/class/gpio/export echo “out” > /sys/class/gpio/gpio17/direction echo 1 > /sys/class/gpio/gpio17/value Saturday, August 3, 13
  6. Arduino • Atmel Virtual Runtime • Small SRAM • Too

    small for CRuby :( Saturday, August 3, 13
  7. Raspberry Pi • Low-Cost Computer ($25-35) • Runs Custom Debian

    Installation • Aimed at Education • 26 available GPIO pins Saturday, August 3, 13
  8. BeagleBone Black • $45 Development Board • Custom Linux Distribution

    • 92 GPIO pins • Built-in Cloud9 IDE Saturday, August 3, 13
  9. WiringPi-Ruby https://github.com/WiringPi/WiringPi-Ruby require ‘WiringPi’ IO = WiringPi.new inputPin = 1

    outputPin = 2 IO.mode(inputPin, INPUT) # YUNO NAMESPACE GLOBALS IO.mode(outputPin, OUTPUT) # SRSLY value = IO.read(inputPin) IO.write(outputPin, value) Saturday, August 3, 13
  10. Brewby + • Brewery Automation System • Useful for Commercial

    & Homebrewers • Rack app monitors and triggers events • Client app interfaces with GPIO • Logs Saturday, August 3, 13
  11. KeepMeAlive • Plants die at our house • Tired of

    killing plants • Monitors plant moisture level • Sends SMS at certain threshold Saturday, August 3, 13
  12. KeepMeAlive.Animal • Modified Cereal Dispenser • Controls dispensing with Servo

    Motor • Uses Rails app to Schedule Feeding • Possible Improvements? Saturday, August 3, 13
  13. Drawbacks to Ruby • CRuby relies on “full” operating system

    • CRuby memory usage is large* • CRuby is slow* * compared to microcontroller RTOS Saturday, August 3, 13
  14. Delegate to MCUs • Ruby controls the main state machine

    • MCU controls an isolated subsystem • Use I2C communication protocol • Arduino!!! :D :D :D Saturday, August 3, 13
  15. ATMega328P • MCU behind the Arduino Uno dev board •

    14 Digital IO pins, 6 Analog Pins • Arduino Uno - $30 • ATMega328P - $2 + $3 in parts to run Saturday, August 3, 13
  16. • Subset of Ruby API • Built with embedded appliances

    • No assumption of threaded OS or FS • Cross-build to specific targets • Very small footprint (~80KB RAM usage) • Code dependencies compiled into bin Saturday, August 3, 13
  17. Mruby’s small footprint is because it cut out a lot.

    CRuby Mruby File/IO, require, multithreading, readline, RubyGems support... Saturday, August 3, 13
  18. MGem • Mruby answer to code packaging • Library can

    contain ruby or C code • Many authors have implemented the missing Ruby components for mruby in mgems • STDLIB is a series of mgems • https://www.github.com/bovi/mgem-list Saturday, August 3, 13
  19. Adding an mgem to mruby MRuby::Build.new do |conf| conf.gem ‘mruby-pid’,

    :github => ‘cadwallion/mruby-pid’ conf.gem ‘/home/cadwallion/code/mruby_example_gem’ end build_config.rb mirb - Embeddable Interactive Ruby Shell This is a very early version, please test and report errors. Thanks :) > PID => PID > mruby/bin/mirb Saturday, August 3, 13
  20. Cross-Build Mruby to Targets • Builds mruby on a target

    toolchain for deployment • Opens up opportunity to build for new runtimes • Which means.... Saturday, August 3, 13
  21. ARDUINO?!? MRuby::CrossBuild.new do |conf| # A LOT OF SETUP conf.cc

    do |cc| # CC compilation options for Arduino end conf.cxx do |cxx| # CXX compilation options for Arduino end conf.archiver do |ar| # Archiver options for Arduino end conf.gem :github => ‘kyab/mruby-arduino’, :branch => ‘master’ end For more full version, https://github.com/mruby/mruby/blob/master/examples/targets/ArduinoDue.rb build_config.rb Saturday, August 3, 13
  22. Steps to push Ruby code to Arduino • Write ruby

    code • Use `bin/mrbc` to compile to bytecode • Write C to kickoff bytecode in mruby VM • Upload C code to Arduino Saturday, August 3, 13
  23. #include <stdio.h> #include “mruby.h” #include “mruby/class.h” #include “mruby/value.h” #include “mruby/irep.h”

    mrb_state *mrb; mrb_value rover_obj; extern const uint8_t rover[]; // ruby bytecode void setup() { mrb_load_irep(rover); // eval bytecode RClass *rover_class = mrb_class_get(mrb, “Rover”); mrb_value args[6]; args[0] = mrb_fixnum_value(2); // Motor1Pin1 args[1] = mrb_fixnum_value(3); // Motor1Pin2 args[2] = mrb_fixnum_value(4); // Motor1PwmPin args[3] = mrb_fixnum_value(5); // Motor2Pin1 args[3] = mrb_fixnum_value(6); // Motor2Pin2 args[3] = mrb_fixnum_value(7); // Motor2PwmPin rover_obj = mrb_class_new_instance(mrb, 6, args, rover_class); mrb_funcall(mrb, rover_obj, ‘run’, 0); } void loop() { // no-op, Ruby handles all the fun here } class Rover def initialize(m1p1, m1p2, m1pwm, m2p1, m2pwm) @left_wheel = Wheel.new(m1p1, m1p2, m1pwm) @right_wheel = Wheel.new(m2p1, m2p2, m2pwm) end def run @goForward() end def goForward() @left_wheel.setMotor(:forward) @right_wheel.setMotor(:forward) end end class Wheel def initialize(pin1, pin2, pwmPin) @forwardPin = pin1 @backwardPin = pin2 @speedPin = pin3 end def setMotor(direction) if direction == :forward Arduino.analogWrite(@speedPin, 255) Arduino.digitalWrite(@forwardPin, Arduino::LOW) Arduino.digitalWrite(@backwardPin, Arduino::HIGH) end end end Rover Example Saturday, August 3, 13
  24. Always Be Coding... ...Robots*. * I am not to be

    held responsible for the birth of SkyNet by following this advice. Saturday, August 3, 13