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. Rundino 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.
- This is the default sketch if
-
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 toBoard#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 anAnalogOutput
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.
- Up to 12-bit analog in/out. Pass a
-
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 ofdino sketch serial
, usedino 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
andShiftIn
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 multipleSinglePin
proxies
. AnRGBLed
is built from 3AnalogOutput
s, for example, one for each color, connected to a separate pin. MultiPin
implements a shortcut class methodproxy_pins
. Proxying a pin allows subcomponent pin numbers to be given as a hash when initializing an instance of aMultiPin
component. Eg:{red: 9, green: 10, blue: 11}
given as thepins:
option forRGBLed#new
.- When initialized, subcomponents corresponding to the proxied pins are automatically created. They're stored in
#proxies
andattr_reader
methods are created for each, corresponding to their key in thepins:
hash. Eg:RGBLed#green
andRGBLed#proxies[:green]
both give theAnalogOutput
component that represents the green LED inside the RGB LED, connected to pin 10.
- Components connecting to more than 1 pin, like an RGB LED or rotary encoder, are now modeled as
-
BoardProxy
abstraction for shift/SPI registers:- The
Register
classes implement enough of theBoard
interface to satisfy components based onDigitalInput
andDigitalOutput
, such asLed
orButton
. - 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 theboard:
, 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 onlyDigitalInput
orDigitalOutput
, eg.SSD
- seven segment display orRGBLed
. Seeexamples/register
for more.
- The
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.
- By default, all components define
-
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 optionalkey
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 theCallbacks
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 theCallbacks
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 fromReader
,Poller
, andListener
respectively, insideMixins
.#read
sends a single read command by calling#_read
, and blocks the main thread, untildata
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 returnsdata
.#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 ofserialport
. - Switched from
rspec
tominitest
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.