Skip to content

0.12.0

Latest
Compare
Choose a tag to compare
@vickash vickash released this 03 Mar 16:14

0.12.0

New Boards

  • The dino sketch shell command now accepts a --target argument. It includes/excludes features to tailor the sketch for different boards/chips. Run dino targets for more info.

  • ATmega Based Boards (default) (--target mega):

    • This is the default sketch if --target isn't specified, and works for Arduino (and other) products based on the ATmega AVR chips, like the Uno, Nano, Leonardo and Mega.
  • ESP8266 (--target esp8266):

    • Works with either built in WiFi or Serial.
    • WiFi version supports OTA (over-the-air) update in the Arduino IDE. Initial flash must still be done via serial.
    • Dev boards can map GPIOs to physical pins differently. Always look up the GPIO numbers and use those for pin numbers.
    • Note: SoftwareSerial and LiquidCrystal (LCD) both do not work on the ESP8266, and are excluded from the sketch.
  • ESP32 (--target esp32):

    • Works with either built in WiFi or Serial.
    • WiFi version does NOT support OTA (over-the-air) updates yet.
    • Only tested with the original ESP32 module so far, not the later revisions with slightly different hardware.
    • Dev boards can map GPIOs to physical pins differently. Always look up the GPIO numbers and use those for pin numbers.
    • Note: Servos and analog outputs share the LEDC channels on the board. Maximum of 16 combined.
    • Note: SoftwareSerial and LiquidCrystal (LCD) both do not work on the ESP32, and are excluded from the sketch.
    • Note: SPI bug exists where input modes don't match other platforms. Eg. For a register using mode 0 on AVR, mode 2 needs to be set on ESP32 for it to work. Using mode 0 misses a bit.
  • Arduino Due (--target sam3x) :

    • Up to 12-bit analog in/out. Pass a bits: option to Board#new to set resolution for both.
    • DAC support. Refer to DAC pins as 'DAC0', 'DAC1', just as labeled on the board. Call #analog_write or just #write on an AnalogOutput component that uses the pin.
    • Uses the native ARM serial port by default. Configurable in sketch to use programming port.
    • Note: SoftwareSerial, Infrared, and Tone are incompatible with the Arduino Due, and excluded from the sketch.
  • ATmega168 (--target mega168):

    • By excluding a lot of features, we can still fit the memory constraints of the ATmega168 chips found in older Arduinos.
    • SoftwareSerial, LCD, OneWire and IROut are compatible, but left out to keep memory usage down.
    • Included libraries can be toggled in DinoDefines.h to suit your needs.
    • Note: Aux message is limited to 264 bytes on the mega168, or less depending on included libraries. The only feature currently affected by this is sending long infrared signals, like for an air conditioner.

New Components

  • TxRx::TCP allows communication with the board over an IP network, instead of serial connection. Tested on Arduino Uno Ethernet Shield (Wiznet W5100), and ESP8266 native WiFi. Should work on Uno WiFi shield, but is untested. WiFi must be configured before flashing. Instad of dino sketch serial, use dino sketch wifi.

  • Hitachi HD44780 LCD support. Uses Arduino LiquidCrystal library.

  • Seven Segment Display support. Ruby implementation as multiple LEDs.

  • Infrared Emitter support. Uses Arduino-IRremote, and the ESP8266 fork where applicable.

  • Tone (piezo) support. Uses Arduino tone,noTone functions.

  • SoftwareSerial (write only). Uses Arduino SoftSerial library. Only tested on ATmega chips.

  • Potentiometer class, based on AnalogInput, but enables moving average smoothing by default, and adds #on_change callback method.

  • Rotary encoder support. Polls @ 1ms interval. WARNING: Not suitable for high speed or precise position needs. It will definitely miss steps. Sufficient for rotary knobs as user input.

  • DHT11 / DHT 21 (AM2301) / DHT22 temperature and relative humidity sensor support. Custom implementation where input pulses are measured on the board, then decoded in Ruby.

  • DS3231 RTC (real time clock) over I2C (Ruby implementation)

  • DS18B20 temperature sensor. Uses custom implementation of Dallas/Maxim 1-Wire bus below.

  • Dallas/Maxim 1-Wire bus support. Low level timing functions run on the board. High level logic in Ruby.

    • Most bus features are implemented: reset/presence detect, parasite power handling, bus search and slave device identification, CRC. No overdrive support.
    • Based on Kevin Darrah's video explaining the DS18B20 datasheet.
  • I2C bus support. Uses Arduino Wire library.

  • Shift Register support. Uses Arduino ShiftOut and ShiftIn functions.

  • SPI bus support (uses Arduino SPI library) :

    • Read/Write Transfers
    • Read-Only Listeners (like digital/analog listeners, but reads n bytes from MISO)
  • Generic input and output register classes for the above 2: Register::ShiftIn, Register::ShiftOut, Register::SPIIn, Register::SPIOut.

  • Board EEPROM support. Uses Arduino EEPROM library.

Changed Components

  • Servos can now be connected to arbitrary pins as long as they are supported by the board.

  • Digital and analog listeners now have dividers on a per-pin basis.

    • Timing is based on a 1000 microsecond tick being counted by the board.
    • Call #listen with a value as the first argument. Eg. analog_sensor.listen(64) will tell the board to send us that specific sensor's state every 64 ticks (~64ms) or around 16 times per second, without affecting other components' rates.
    • Valid dividers are: 1, 2, 4, 8, 16, 32, 64, 128.
    • Defaults are same as before: 4 for digital, 16 for analog.

Hardware Abstraction

  • MultiPin abstraction for components using more than one pin:

    • Components connecting to more than 1 pin, like an RGB LED or rotary encoder, are now modeled as MultiPin and contain multiple SinglePin proxies. An RGBLed is built from 3 AnalogOutputs, for example, one for each color, connected to a separate pin.
    • MultiPin implements a shortcut class method proxy_pins. Proxying a pin allows subcomponent pin numbers to be given as a hash when initializing an instance of a MultiPin component. Eg: {red: 9, green: 10, blue: 11} given as the pins: option for RGBLed#new.
    • When initialized, subcomponents corresponding to the proxied pins are automatically created. They're stored in #proxies and attr_reader methods are created for each, corresponding to their key in the pins: hash. Eg: RGBLed#green and RGBLed#proxies[:green] both give the AnalogOutput component that represents the green LED inside the RGB LED, connected to pin 10.
  • BoardProxy abstraction for shift/SPI registers:

    • The Register classes implement enough of the Board interface to satisfy components based on DigitalInput and DigitalOutput, such as Led or Button.
    • This lets you call methods on components directly, rather than manipulating the register data to control components indirectly.
    • Initialize the appropriate Register object for the type of register. To initialize a component connected to the register, use the register as the board:, and give the parallel I/O pin on the register that the component is connected to. Pin 0 maps to the lowest bit.
    • This also works for MultiPin components built out of only DigitalInput or DigitalOutput, eg. SSD - seven segment display or RGBLed. See examples/register for more.

Input Components, Callbacks and State

  • @value has been renamed to @state.

    • By default, all components define #state and #state=, which access @state through @state_mutex. This way we don't try to read with #state while a callback is updating it with #state=.
    • @state can be any Ruby object representing the state of the component.
  • Callback functionality for components has been extracted into a mixin module, Mixins::Callbacks.

    • Like before, callbacks for all components on a board run sequentially, in a single "update" thread, separate from the main thread. This is the same thread reading from TxRx.
    • #add_callback and #remove_callback methods are available, and take an optional key as argument.
    • Blocks given to #add_callback are stored in @callbacks[key], to be called later, when the "update" thread receives data for the component. The default key is :persistent.
    • Each key represents an array of callbacks, so multiple callbacks can share the same key.
    • Calling #remove_callbacks with a key empties that array. Calling with no key removes all callbacks for the component.
    • #pre_callback_filter is defined in the Callbacks module. The return value of this method is what is given to the component's callbacks and to update its @state. By default, it returns whatever was given from the board.
    • Override #pre_callback_filter to process data before giving it to callbacks and @state. Eg: given raw bytes from a DHT sensor, process them into a hash containing :celsius, : fahrenheit and :humidity values. That hash is given to to callbacks and #update_state instead of the original string of raw bytes.
    • #update_state is defined in the Callbacks module. It is called after all callbacks are run and given the return value of #pre_callback_filter. By default, it sets @state= to the value given.
    • Override it if updating @state is more complex than this, but be sure to either use #state= only once, or wrap the operation in @state_mutex.synchronize.
  • Input components no longer automatically start listening when created, since there are more options for reading inputs.

    • DigitalInput and its subclasses are the exception to this. They automatically listen, since there is little advantage to other modes.
  • Input components can have any combination of #read, #poll and #listen methods now, coming from Reader, Poller, and Listener respectively, inside Mixins.

    • #read sends a single read command by calling #_read, and blocks the main thread, until data is received from #pre_callback_filter. When received, any block that was given to #read will run once as a callback and be removed immediately. #read then stops blocking the main thread and returns data.
    • #poll requires an interval (in seconds) as its first argument. It starts a new thread, and keeps calling #_read in it, at the given interval. #poll does not block the main thread, and does not return a value. A block given will be added as a callback inside the :poll key.
    • #listen adds its block as a callback inside the :listen key, calls #_listen and returns immediately.
    • #stop stops polling and listening. It also removes all callbacks in the :poll and :listen keys (callbacks added as blocks when polling or listening).

Minor Changes

  • Serial communication now uses the rubyserial gem instead of serialport.
  • Switched from rspec to minitest for testing.
  • Added more useful information and errors during the connect & handshake process.
  • Extended message syntax so the Arduino can receive arbitrary length messages, including binary.
  • Created Dino::Message class to handle message construction.
  • Moved CLI into it's own class, Dino::CLI.
  • Added simple flow control to avoid overrunning the 64 byte input buffer in the Arduino Serial library. No flow control for Ruby receiving data.