Arduino Support for Automate

Introduction

This extension provides interface to Arduino devices via pyFirmata library. You can use either StandardFirmata or preferrably AutomateFirmata, which offers additional features that can be used with Automate. Please use corresponding version of AutomateFirmata from releases -page. I have tested this module with Arduino Pro Mini compatible boards but it should work with others too.

Example application

This example application sets up couple of analog and digital Arduino Sensors and Actuators. It also introduces Servo actuator with ConstantTimeActuator, which functions such a way that if value of a1 changes, the value of servo will change smoothly within given time interval.

from automate import *


class MySystem(System):
    ufloat = UserFloatSensor(value_min=0, value_max=1)

    a1 = ArduinoAnalogSensor(service=0, pin=0)
    d12 = ArduinoDigitalSensor(service=0, pin=12)

    d13 = ArduinoDigitalActuator(service=0, pin=13)  # LED on Arduino board
    pwm = ArduinoPWMActuator(service=0, pin=4, on_update=SetStatus('pwm', 'ufloat'))
    servo = ArduinoServoActuator(min_pulse=200,
                                 max_pulse=8000,
                                 service=0,
                                 pin=3,
                                 default=50,
                                 slave=True)

    interp = ConstantTimeActuator(change_time=2.,
                                  change_frequency=20.,
                                  slave_actuator=servo)

    prog = Program(
        on_update=Run(Log("Value: %s", Value(a1)),
                      SetStatus(d13, d12),
                      SetStatus(interp, Value(180) * Value(a1)))
    )

my_arduino = ArduinoService(
    device="/dev/ttyUSB0",
    sample_rate=500,
)

s = MySystem(services=[my_arduino, WebService()])

VirtualWire wireless communication

VirtualWire enables communication between two Arduinos with very cheap radio frequency (RF) transmitters&receivers. For more information about VirtaualWire, see for example this link. It is possible to make Automate communicate with remote Arduinos via VirtualWire. How to do this:

To configure independent Arduino transmitter module with Automate:

  1. Flash AutomateFirmata to your Arduino
  2. Make simple Automate application to configure Arduino that configures which pin values you are interested in being transmitted via VirtualWire, something like this:
class ArduinoSystem(System):
    digital_sensor1 = ArduinoDigitalSensor(pull_up_resistor=True, pin=2)
    digital_sensor2 = ArduinoDigitalSensor(pull_up_resistor=True, pin=3)
    analog_sensor1= ArduinoAnalogSensor(pin=0)
    analog_sensor2= ArduinoAnalogSensor(pin=1)

s = ArduinoSystem(
    services=[
        ArduinoService(
            device="/dev/ttyUSB0",
            sample_rate=2000,
            home_address=1,
            device_address=1,
            virtualwire_tx_pin=11,
            virtualwire_ptt_pin=12,
        ),
    ],
)

Here you need to connect your RF transmitter device to digital pin 11. With some transmitter devices you might save some power by using push to talk (PTT) pin 12 to power on/off your transmitter device. This will configure your module to transmit values from analog pins 0 and 1, and digital pins 2 and 3. Now you can disconnect Arduino’s serial interface and it will work independently. When running this configuration application, Arduino stores configuration to its EEPROM memory, such that after booting you don’t need any more configuration. AutomateFirmata also saves power when in transmitter mode, so you can implement battery powered sensors that consume very little battery.

To listen these events, you need another Arduino that is connected permanently to your Automate computer:

class ArduinoSystem(System):
    digi1 = ArduinoRemoteDigitalSensor(device=1, pin=2)
    digi2 = ArduinoRemoteDigitalSensor(device=1, pin=3)
    analog1 = ArduinoRemoteAnalogSensor(device=1, pin=0)
    analog2 = ArduinoRemoteAnalogSensor(device=1, pin=1)


s = ArduinoSystem(
    services=[
        ArduinoService(
            device="/dev/ttyUSB0",
            sample_rate=2000,
            home_address=1,
            device_address=2,
            virtualwire_rx_pin=10,
        ),
    ],
)

Notice that here you need to configure device attribute same as device_address that you configured above. Also home_address needs to be same between all Arduino devices that you configure in your system.

You can also configure independent receiver module:

s = System(
    services=[
        ArduinoService(
            device="/dev/ttyUSB0",
            sample_rate=2000,
            home_address=1,
            device_address=3,
            virtualwire_rx_pin=11,
        ),
    ],
)

This is all that is needed for receiver. What this does is sets home_address, device_address and virtualwire_tx_pin in your Arduino receiver device correctly. You must connect your RF receiver device to digital pin 11. Now you can control this device remotely like this:

class ArduinoSystem(System):
    ubool = UserBoolSensor()
    ufloat1 = UserFloatSensor(value_min=0, value_max=1)

    remote_actuator = ArduinoRemoteDigitalActuator(
        device=3, pin=13,
        on_update=SetStatus('remote_actuator', 'ubool'))

    remote_pwm = ArduinoRemotePWMActuator(
        device=3, pin=5,
        on_update=SetStatus('remote_pwm', 'ufloat1'))



s = ArduinoSystem(
    services=[
        ArduinoService(
            device="/dev/ttyUSB0",
            sample_rate=2000,
            home_address=1,
            device_address=4,
            virtualwire_tx_pin=11,
            virtualwire_ptt_pin=12,
        ),
        WebService(read_only=False),
    ],
)

Here, you must configure your RF transmitter to digital pin 11.

Class definitions

Service

class automate.extensions.arduino.ArduinoService(*args, **kwargs)[source]

Service that provides interface to Arduino devices via pyFirmata library.

device = None

Arduino devices to use, as a list

device_type = None

Arduino device board type, choices: ‘arduino’, ‘arduino_mega’, ‘arduino_due’.

sample_rate = None

Arduino sample rate in milliseconds (i.e. how often to send data to host)

home_address = None

Device home address (0-255) in VirtualWire network. This should be same for all devices in a network.

device_address = None

Device address (0-255) in VirtualWire network. Unique for each device.

virtualwire_tx_pin = None

VirtualWire transfer pin

virtualwire_rx_pin = None

VirtualWire receiver pin

virtualwire_ptt_pin = None

VirtualWire PTT (push to talk) pin

lcd_port = None

LCD Port

lcd_columns = 16

LCD Columns

lcd_rows = 2

LCD Rows

wakeup_pin = None

Wakeup pin (0 to disable) that wakes Arduino from sleep mode. On Atmega328 based boards, possible values are 2 and 3

virtualwire_speed = None

VirtualWire speed, (bit rate = speed * 1000 bps). Values 1-9 are allowed. Values up to 7 should be working, but your mileage may vary.

keep_alive = None

Send keep-alive messages periodically over serial port to prevent Arduino device from falling to power save mode.

change_digital(pin_nr, value)[source]

Change digital Pin value (boolean). Also PWM supported(float)

Sensors

class automate.extensions.arduino.arduino_sensors.AbstractArduinoSensor(*args, **kwargs)[source]

Abstract base class for Arduino sensors

service = None

Arduino service number (specify, if more than 1 ArduinoServices are configured in system)

pin = None

Arduino pin number

class automate.extensions.arduino.arduino_sensors.ArduinoDigitalSensor(*args, **kwargs)[source]

Boolean-valued sensor object for digital Arduino input pins

pull_up_resistor = None

Enable built-in pull-up resistor

inverted = None

Set to True to have inversed status value

class automate.extensions.arduino.arduino_sensors.ArduinoAnalogSensor(*args, **kwargs)[source]

Float-valued sensor object for analog Arduino input pins

class automate.extensions.arduino.arduino_sensors.ArduinoRemoteDigitalSensor(*args, **kwargs)[source]

Sensor which listens to status changes of remote digital input pin (transmission via VirtualWire).

Needs AutomateFirmata

device = None

Source device number

inverted = None

Set to True to have inversed status value

class automate.extensions.arduino.arduino_sensors.ArduinoRemoteAnalogSensor(*args, **kwargs)[source]

Sensor which listens to status changes of remote analog input pin (transmission via VirtualWire)

Needs AutomateFirmata

device = None

Source device number

Actuators

class automate.extensions.arduino.arduino_actuators.AbstractArduinoActuator(*args, **kwargs)[source]

Abstract base class for Arduino actuators

service = None

Arduino service number (specify, if more than 1 ArduinoService are configured in the system)

pin = None

Arduino pin number

class automate.extensions.arduino.arduino_actuators.ArduinoDigitalActuator(*args, **kwargs)[source]

Boolean-valued actuator object for digital Arduino output pins

class automate.extensions.arduino.arduino_actuators.ArduinoLCDActuator(*args, **kwargs)[source]

Actuator that sends target device digital output pin status change requests

Needs AutomateFirmata

device = None

Target device number

class automate.extensions.arduino.arduino_actuators.ArduinoRemoteDigitalActuator(*args, **kwargs)[source]

Actuator that sends target device digital output pin status change requests

Needs AutomateFirmata

device = None

Target device number

class automate.extensions.arduino.arduino_actuators.ArduinoRemotePWMActuator(*args, **kwargs)[source]

Actuator that sends target device analog (PWM) output pin status change requests

Needs AutomateFirmata

device = None

Target device number

class automate.extensions.arduino.arduino_actuators.ArduinoServoActuator(*args, **kwargs)[source]

Float-valued actuator object for Arduino output pins that can be configured in Servo mode Status is servo angle (0-360).

min_pulse = None

Minimum pulse time (in microseconds)

max_pulse = None

Maximum pulse time (in microseconds)

class automate.extensions.arduino.arduino_actuators.ArduinoPWMActuator(*args, **kwargs)[source]

Float-valued actuator object for Arduino output pins that can be configured in PWM mode Status is float between 0.0 and 1.0.