topical media & game development

talk show tell print

lib-of-vs-libs-openFrameworks-communication-ofStandardFirmata.h / h



  /*
   * Copyright 2007-2008 (c) Erik Sjodin, eriksjodin.net
   *
   * Devloped at: The Interactive Institutet / Art and Technology,
   * OF Lab / Ars Electronica
   *
   * Permission is hereby granted, free of charge, to any person
   * obtaining a copy of this software and associated documentation
   * files (the "Software"), to deal in the Software without
   * restriction, including without limitation the rights to use,
   * copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the
   * Software is furnished to do so, subject to the following
   * conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
   * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
   * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
   * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   * OTHER DEALINGS IN THE SOFTWARE.
   */
  
  ifndef OF_STANDARD_FIRMATA_H
  define OF_STANDARD_FIRMATA_H
  
  include <list>
  include <vector>
  include <string>
  include <iostream>
  
  include <ofEvents.h>
  include <ofSerial.h>
  
  using namespace std;
  
  /*
   * Version numbers for the protocol. The protocol is still changing, so these
   * version numbers are important. This number can be queried so that host
   * software can test whether it will be compatible with the currently installed firmware.
   */
  
  define FIRMATA_MAJOR_VERSION                           2 // for non-compatible changes
  define FIRMATA_MINOR_VERSION                           0 // for backwards compatible changes
  define FIRMATA_MAX_DATA_BYTES                          32 // max number of data bytes in non-Sysex messages
  // message command bytes (128-255/0x80-0xFF)
  define FIRMATA_DIGITAL_MESSAGE                         0x90 // send data for a digital pin
  define FIRMATA_ANALOG_MESSAGE                          0xE0 // send data for an analog pin (or PWM)
  define FIRMATA_REPORT_ANALOG                           0xC0 // enable analog input by pin #
  define FIRMATA_REPORT_DIGITAL                          0xD0 // enable digital input by port pair
  //
  define FIRMATA_SET_PIN_MODE                            0xF4 // set a pin to INPUT/OUTPUT/PWM/etc
  //
  define FIRMATA_REPORT_VERSION                          0xF9 // report protocol version
  define FIRMATA_SYSTEM_RESET                            0xFF // reset from MIDI
  //
  define FIRMATA_START_SYSEX                             0xF0 // start a MIDI Sysex message
  define FIRMATA_END_SYSEX                               0xF7 // end a MIDI Sysex message
  // pin modes
  define FIRMATA_INPUT                                   0x00
  define FIRMATA_OUTPUT                                  0x01
  define FIRMATA_ANALOG                                  0x02 // analog pin in analogInput mode
  define FIRMATA_PWM                                     0x03 // digital pin in PWM output mode
  define FIRMATA_SERVO                                   0x04 // digital pin in Servo output mode
  // extended command set using SysEx (0-127/0x00-0x7F)
  /* 0x00-0x0F reserved for custom commands */
  define FIRMATA_SYSEX_SERVO_CONFIG                      0x70
  define FIRMATA_SYSEX_FIRMATA_STRING                                        0x71 // a string message with 14-bits per char
  define FIRMATA_SYSEX_REPORT_FIRMWARE                                        0x79 // report name and version of the firmware
  define FIRMATA_SYSEX_NON_REALTIME                      0x7E // MIDI Reserved for non-realtime messages
  define FIRMATA_SYSEX_REALTIME                          0x7F // MIDI Reserved for realtime messages
  //#define FIRMATA_SYSEX_SHIFTOUT_MESSAGE                                0xB0 // proposed shiftOut message (SysEx)
  
  // ---- arduino constants (for Arduino NG and Diecimila)
  
  // board settings
  define ARD_TOTAL_DIGITAL_PINS                                                        22 // total number of pins currently supported
  define ARD_TOTAL_ANALOG_PINS                                                        8
  define ARD_TOTAL_PORTS                                 3 // total number of ports for the board
  // pin modes
  define ARD_INPUT                                       0x00
  define ARD_OUTPUT                                      0x01
  define ARD_ANALOG                                      0x02 // analog pin in analogInput mode
  define ARD_PWM                                         0x03 // digital pin in PWM output mode
  define ARD_SERVO                                       0x04 // digital pin in Servo output mode
  define ARD_HIGH                                        1
  define ARD_LOW                                         0
  define ARD_ON                                          1
  define ARD_OFF                                         0
  
  /*
   #if defined(__AVR_ATmega168__)  // Arduino NG and Diecimila
   #define ARD_TOTAL_ANALOG_PINS       8
   #define ARD_TOTAL_DIGITAL_PINS      22 // 14 digital + 8 analog
   #define ARD_TOTAL_PORTS             3 // total number of ports for the board
   #define ARD_ANALOG_PORT             2 // port# of analog used as digital
   #elif defined(__AVR_ATmega8__)  // old Arduinos
   #define ARD_TOTAL_ANALOG_PINS       6
   #define ARD_TOTAL_DIGITAL_PINS      20 // 14 digital + 6 analog
   #define ARD_TOTAL_PORTS             3  // total number of ports for the board
   #define ARD_ANALOG_PORT             2  // port# of analog used as digital
   #elif defined(__AVR_ATmega128__)// Wiring
   #define ARD_TOTAL_ANALOG_PINS       8
   #define ARD_TOTAL_DIGITAL_PINS      43
   #define ARD_TOTAL_PORTS             5 // total number of ports for the board
   #define ARD_ANALOG_PORT             2 // port# of analog used as digital
   #else // anything else
   #define ARD_TOTAL_ANALOG_PINS       6
   #define ARD_TOTAL_DIGITAL_PINS      14
   #define ARD_TOTAL_PORTS             3 // total number of ports for the board
   #define ARD_ANALOG_PORT             2 // port# of analog used as digital
   #endif
   */
  
  
Notes:

   Communication problems could be caused by high baud rates, if you are using ofStandardFirmata then try to turn down the baud rate to 57600.
   I.e. Change Firmata.begin() in setup() in ofStandardFirmata on the Arduino to Firmata.begin(57600) and connect using baud=57600;
  
   ofStandardFirmata on the Arduino will get caught in a while loop if data is sent to it continuosly at high speeds (for example on each update at 100FPS)
   As a consequence data will not be sent from the Arduino to the computer. This is why most of the sender functions only transmit data
   if it has been changed. This behavior can be overriden by setting force=true in the senders.
  
   This version of the Arduino class is intended to be used with the Firmata v2 protocol and the ofStandardFirmata firmware, see http://www.arduino.cc/playground/Interfacing/Firmata.
   It currently supports the Arduino NG and Diecimila boards and other ATmega168 based Arduino compatible boards.
   The class can be extended to accomodate modified versions of ofStandardFirmata.
   **/
  class ofStandardFirmata{
  
          public:
                  ofStandardFirmata();
  
                  virtual ~ofStandardFirmata();
  
                  // --- setup functions
                  int connect(string device, int baud = 115200);
                  // opens a serial port connection to the arduino
  
                  void disconnect();
                  // closes the serial port connection
  
                  void update();
                  // polls data from the serial port, this has to be called periodically
  
                  bool isInitialized();
                  // returns true if a succesfull connection has been established and the Arduino has reported a firmware
  
                  void setDigitalHistoryLength(int length);
                  void setAnalogHistoryLength(int length);
                  void setStringHistoryLength(int length);
                  void setSysExHistoryLength(int nSysEx);
  
                  // --- senders
  
                  void sendDigitalPinMode(int pin, int mode);
                  // pin: 2-13
                  // mode: ARD_INPUT, ARD_OUTPUT, ARD_PWM
                  // setting a pins mode to ARD_INPUT turns on reporting for the port the pin is on
                  // Note: analog pins 0-5 can be used as digitial pins 16-21 but if the mode of _one_ of these pins is set to ARD_INPUT then _all_ analog pin reporting will be turned off
  
                  void sendAnalogPinReporting(int pin, int mode);
                  // pin: 0-5
                  // mode: ARD_ON or ARD_OFF
                  // Note: analog pins 0-5 can be used as digitial pins 16-21 but if reporting for _one_ analog pin is enabled then reporting for _all_ of digital pin 16-21 will be turned off
  
                  void sendDigital(int pin, int value, bool force = false);
                  // pin: 2-13
                  // value: ARD_LOW or ARD_HIGH
                  // the pins mode has to be set to ARD_OUTPUT or ARD_INPUT (in the latter mode pull-up resistors are enabled/disabled)
                  // Note: pin 16-21 can also be used if analog inputs 0-5 are used as digital pins
  
                  void sendPwm(int pin, int value, bool force = false);
                  // pin: 3, 5, 6, 9, 10 and 11
                  // value: 0 (always off) to 255 (always on).
                  // the pins mode has to be set to ARD_PWM
                  // TODO check if the PWM bug still is there causing frequent digital port reporting...
  
                  void sendSysEx(int command, vector<unsigned char> data);
  
                  void sendString(string str);
                  // firmata can not handle strings longer than 12 characters.
  
                  void sendProtocolVersionRequest();
  
                  void sendFirmwareVersionRequest();
  
                  void sendReset();
  
                  // --- senders for SysEx communication
  
                  void sendSysExBegin();
                  // sends the FIRMATA_START_SYSEX command
  
                  void sendSysExEnd();
                  // sends the FIRMATA_END_SYSEX command
  
                  void sendByte(unsigned char byte);
                  // sends a byte without wrapping it in a firmata message, data has to be in the 0-127 range,
                  // values > 127 will be interpreted as commands.
  
                  void sendValueAsTwo7bitBytes(int value);
                  // sends a value as two 7-bit bytes without wrapping it in a firmata message
                  // values in the range 0 - 16384 will be sent as two bytes within the 0-127 data range.
  
                  // --- getters
  
                  int getPwm(int pin);
                  // pin: 3, 5, 6, 9, 10 and 11
                  // returns the last set PWM value (0-255) for the given pin
                  // the pins mode has to be ARD_PWM
                  // Note: pin 16-21 can also be used if analog inputs 0-5 are used as digital pins
  
                  int getDigital(int pin);
                  // pin: 2-13
                  // returns the last received value (if the pin mode is ARD_INPUT) or the last set value (if the pin mode is ARD_OUTPUT) for the given pin
                  // Note: pin 16-21 can also be used if analog inputs 0-5 are used as digital pins
  
                  int getAnalog(int pin);
                  // pin: 0-5
                  // returns the last received analog value (0-1023) for the given pin
  
                  vector<unsigned char> getSysEx();
                  // returns the last received SysEx message
  
                  string getString();
                  // returns the last received string
  
                  int getMajorProtocolVersion();
                  // returns the major firmware version
  
                  int getMinorProtocolVersion();
                  // returns the minor firmware version
  
                  int getMajorFirmwareVersion();
                  // returns the major firmware version
  
                  int getMinorFirmwareVersion();
                  // returns the minor firmware version
  
                  string getFirmwareName();
                  // returns the name of the firmware
  
                  list<int>* getDigitalHistory(int pin);
                  // pin: 2-13
                  // returns a pointer to the digital data history list for the given pin
                  // Note: pin 16-21 can also be used if analog inputs 0-5 are used as digital pins
  
                  list<int>* getAnalogHistory(int pin);
                  // pin: 0-5
                  // returns a pointer to the analog data history list for the given pin
  
                  list<vector<unsigned char> >* getSysExHistory();
                  // returns a pointer to the SysEx history
  
                  list<string>* getStringHistory();
                  // returns a pointer to the string history
  
                  int getDigitalPinMode(int pin);
                  // returns ARD_INPUT, ARD_OUTPUT, ARD_PWM, ARD_SERVO, ARD_ANALOG
  
                  int getAnalogPinReporting(int pin);
                  // returns ARD_ON, ARD_OFF
  
                  int getValueFromTwo7bitBytes(unsigned char lsb, unsigned char msb);
                  // useful for parsing SysEx messages
  
                  // --- events
  
                  ofEvent<const int> EDigitalPinChanged;
                  // triggered when a digital pin changes value, the pin that changed is passed as an argument
  
                  ofEvent<const int> EAnalogPinChanged;
                  // triggered when an analog pin changes value, the pin that changed is passed as an argument
  
                  ofEvent<const vector<unsigned char> > ESysExReceived;
                  // triggered when a SysEx message that isn't in the extended command set is received, the SysEx message is passed as an argument
  
                  ofEvent<const int> EProtocolVersionReceived;
                  // triggered when a protocol version is received, the major version is passed as an argument
  
                  ofEvent<const int> EFirmwareVersionReceived;
                  // triggered when a firmware version is received, the major version is passed as an argument
  
                  ofEvent<const int> EInitialized;
                  // triggered when the firmware version is received upon connect, the major firmware version is passed as an argument
                  // from this point it's safe to send to the Arduino.
  
                  ofEvent<const string> EStringReceived;
                  // triggered when a string is received, the string is passed as an argument
  
          protected:
  
                  bool _initialized;
  
                  void sendDigitalPinReporting(int pin, int mode);
                  // sets pin reporting to ARD_ON or ARD_OFF
                  // enables / disables reporting for the pins port
  
                  void sendDigitalPortReporting(int port, int mode);
                  // sets port reporting to ARD_ON or ARD_OFF
                  // enables / disables reporting for ports 0-2
                  // port 0: pins 2-7  (0,1 are serial RX/TX)
                  // port 1: pins 8-13 (14,15 are disabled for the crystal)
                  // port 2: pins 16-21 analog pins used as digital, all analog reporting will be turned off if this is set to ARD_ON
  
                  void processData(unsigned char inputData);
                  void processDigitalPort(int port, unsigned char value);
                  virtual void processSysExData(vector<unsigned char> data);
  
                  ofSerial _port;
                  int _portStatus;
  
                  // --- history variables
                  int _analogHistoryLength;
                  int _digitalHistoryLength;
                  int _stringHistoryLength;
                  int _sysExHistoryLength;
  
                  // --- data processing variables
                  int _waitForData;
                  int _executeMultiByteCommand;
                  int _multiByteChannel; // indicates which pin data came from
  
                  // --- data holders
                  unsigned char _storedInputData[FIRMATA_MAX_DATA_BYTES];
                  vector<unsigned char> _sysExData;
                  int _majorProtocolVersion;
                  int _minorProtocolVersion;
                  int _majorFirmwareVersion;
                  int _minorFirmwareVersion;
                  string _firmwareName;
  
                  list<vector<unsigned char> > _sysExHistory;
                  // maintains a history of received sysEx messages (excluding SysEx messages in the extended command set)
  
                  list<string> _stringHistory;
                  // maintains a history of received strings
  
                  list<int> _analogHistory[ARD_TOTAL_ANALOG_PINS];
                  // a history of received data for each analog pin
  
                  list<int> _digitalHistory[ARD_TOTAL_DIGITAL_PINS];
                  // a history of received data for each digital pin
  
                  int _digitalPinMode[ARD_TOTAL_DIGITAL_PINS];
                  // the modes for all digital pins
  
                  int _digitalPinValue[ARD_TOTAL_DIGITAL_PINS];
                  // the last set values (DIGITAL/PWM) on all digital pins
  
                  int _digitalPortValue[ARD_TOTAL_PORTS];
                  // the last set values on all ports
  
                  int _digitalPortReporting[ARD_TOTAL_PORTS];
                  // whether pin reporting is enabled / disabled
  
                  int _digitalPinReporting[ARD_TOTAL_DIGITAL_PINS];
                  // whether pin reporting is enabled / disabled
  
                  int _analogPinReporting[ARD_TOTAL_ANALOG_PINS];
                  // whether pin reporting is enabled / disabled
  
  };
  
  endif
  


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.