From 3dca3653690f6aeec0d1df158913e59580addea4 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sun, 22 Feb 2015 15:47:50 -0800 Subject: [PATCH 01/12] added experimental StandardFirmataEthernet example --- .../EthernetClientStream.cpp | 105 +++ .../EthernetClientStream.h | 52 ++ .../StandardFirmataEthernet.ino | 798 ++++++++++++++++++ 3 files changed, 955 insertions(+) create mode 100644 examples/StandardFirmataEthernet/EthernetClientStream.cpp create mode 100644 examples/StandardFirmataEthernet/EthernetClientStream.h create mode 100644 examples/StandardFirmataEthernet/StandardFirmataEthernet.ino diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.cpp b/examples/StandardFirmataEthernet/EthernetClientStream.cpp new file mode 100644 index 00000000..e010a083 --- /dev/null +++ b/examples/StandardFirmataEthernet/EthernetClientStream.cpp @@ -0,0 +1,105 @@ +/* + EthernetClientStream.cpp + An Arduino-Stream that wraps an instance of Client reconnecting to + the remote-ip in a transparent way. A disconnected client may be + recognized by the returnvalues -1 from calls to peek or read and + a 0 from calls to write. + + Copyright (C) 2013 Norbert Truchsess. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See file LICENSE.txt for further informations on licensing terms. + + formatted using the GNU C formatting and indenting + */ + +#include "EthernetClientStream.h" +#include + +#define MILLIS_RECONNECT 5000 + +EthernetClientStream::EthernetClientStream(Client &client, IPAddress localip, IPAddress ip, const char* host, uint16_t port) +: ip(ip), + host(host), + port(port), + connected(false), + client(client), + localip(localip) +{ +} + +int +EthernetClientStream::available() +{ + return maintain() ? client.available() : 0; +} + +int +EthernetClientStream::read() +{ + return maintain() ? client.read() : -1; +} + +int +EthernetClientStream::peek() +{ + return maintain() ? client.peek() : -1; +} + +void EthernetClientStream::flush() +{ + if (maintain()) + client.flush(); +} + +size_t +EthernetClientStream::write(uint8_t c) +{ + return maintain() ? client.write(c) : 0; +} + +void +EthernetClientStream::maintain(IPAddress localip) +{ + if (this->localip!=localip) + { + this->localip = localip; + if (connected) + stop(); + } +} + +void +EthernetClientStream::stop() +{ + client.stop(); + connected = false; + time_connect = millis(); +} + +bool +EthernetClientStream::maintain() +{ + if (client && client.connected()) + return true; + + if (connected) + { + stop(); + } + else if (millis()-time_connect >= MILLIS_RECONNECT) + { + connected = host ? client.connect(host,port) : client.connect(ip,port); + if (!connected) { + time_connect = millis(); + Serial.println("connection failed"); + } else { + Serial.println("connected"); + } + } + return connected; +} diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.h b/examples/StandardFirmataEthernet/EthernetClientStream.h new file mode 100644 index 00000000..ab12e888 --- /dev/null +++ b/examples/StandardFirmataEthernet/EthernetClientStream.h @@ -0,0 +1,52 @@ +/* + EthernetClientStream.h + An Arduino-Stream that wraps an instance of Client reconnecting to + the remote-ip in a transparent way. A disconnected client may be + recognized by the returnvalues -1 from calls to peek or read and + a 0 from calls to write. + + Copyright (C) 2013 Norbert Truchsess. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See file LICENSE.txt for further informations on licensing terms. + + formatted using the GNU C formatting and indenting + */ + +#ifndef ETHERNETCLIENTSTREAM_H +#define ETHERNETCLIENTSTREAM_H + +#include +#include +#include +#include +#include + +class EthernetClientStream : public Stream +{ +public: + EthernetClientStream(Client &client, IPAddress localip, IPAddress ip, const char* host, uint16_t port); + int available(); + int read(); + int peek(); + void flush(); + size_t write(uint8_t); + void maintain(IPAddress localip); + +private: + IPAddress localip; + IPAddress ip; + const char* host; + uint16_t port; + Client &client; + bool connected; + uint32_t time_connect; + bool maintain(); + void stop(); +}; + +#endif \ No newline at end of file diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino new file mode 100644 index 00000000..8ddd861d --- /dev/null +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -0,0 +1,798 @@ +/* + * Firmata is a generic protocol for communicating with microcontrollers + * from software on a host computer. It is intended to work with + * any host computer software package. + * + * To download a host software package, please clink on the following link + * to open the download page in your default browser. + * + * http://firmata.org/wiki/Download + */ + +/* + Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. + Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. + Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. + Copyright (C) 2009-2015 Jeff Hoefs. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See file LICENSE.txt for further informations on licensing terms. + + formatted using the GNU C formatting and indenting +*/ + +#include +#include +#include +#include +#include +#include "EthernetClientStream.h" + +/* + * network configuration + */ +// replace with IP of the server you want to connect to, comment out if using 'remote_host' +#define remote_ip IPAddress(10, 0, 0, 3) + +// *** REMOTE HOST IS NOT YET WORKING *** +// replace with hostname of server you want to connect to, comment out if using 'remote_ip' +// #define remote_host "server.local" + +// replace with the port that your server is listening on +#define remote_port 3030 +// replace with the Arduino's IP address. Comment out if Ethernet-startup should use dhcp. +#define local_ip IPAddress(10, 0, 0, 15) +// replace with ethernet shield mac. It's mandatory every devices is assigned a unique mac address +const byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x53, 0xE5}; + +#if defined remote_ip && defined remote_host +#error "cannot define both remote_ip and remote_host at the same time!" +#endif + +// move the following defines to Firmata.h? +#define I2C_WRITE B00000000 +#define I2C_READ B00001000 +#define I2C_READ_CONTINUOUSLY B00010000 +#define I2C_STOP_READING B00011000 +#define I2C_READ_WRITE_MODE_MASK B00011000 +#define I2C_10BIT_ADDRESS_MODE_MASK B00100000 + +#define MAX_QUERIES 8 +#define MINIMUM_SAMPLING_INTERVAL 10 + +#define REGISTER_NOT_SPECIFIED -1 + +/*============================================================================== + * GLOBAL VARIABLES + *============================================================================*/ + +/* network */ +EthernetClient client; +#if defined remote_ip && !defined remote_host +#ifdef local_ip +EthernetClientStream stream(client, local_ip, remote_ip, NULL, remote_port); +#else +EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), remote_ip, NULL, remote_port); +#endif +#endif +#if !defined remote_ip && defined remote_host +#ifdef local_ip +EthernetClientStream stream(client, local_ip, IPAddress(0, 0, 0, 0), remote_host, remote_port); +#else +EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0), remote_host, remote_port); +#endif +#endif + +/* analog inputs */ +int analogInputsToReport = 0; // bitwise array to store pin reporting + +/* digital input ports */ +byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence +byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent + +/* pins configuration */ +byte pinConfig[TOTAL_PINS]; // configuration of every pin +byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else +int pinState[TOTAL_PINS]; // any value that has been written + +/* timer variables */ +unsigned long currentMillis; // store the current value from millis() +unsigned long previousMillis; // for comparison with currentMillis +unsigned int samplingInterval = 19; // how often to run the main loop (in ms) + +/* i2c data */ +struct i2c_device_info { + byte addr; + int reg; + byte bytes; +}; + +/* for i2c read continuous more */ +i2c_device_info query[MAX_QUERIES]; + +boolean isResetting = false; + +byte i2cRxData[32]; +boolean isI2CEnabled = false; +signed char queryIndex = -1; +unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom() + +Servo servos[MAX_SERVOS]; +byte servoPinMap[TOTAL_PINS]; +byte detachedServos[MAX_SERVOS]; +byte detachedServoCount = 0; +byte servoCount = 0; + + +/*============================================================================== + * FUNCTIONS + *============================================================================*/ + +void attachServo(byte pin, int minPulse, int maxPulse) +{ + if (servoCount < MAX_SERVOS) { + // reuse indexes of detached servos until all have been reallocated + if (detachedServoCount > 0) { + servoPinMap[pin] = detachedServos[detachedServoCount - 1]; + if (detachedServoCount > 0) detachedServoCount--; + } else { + servoPinMap[pin] = servoCount; + servoCount++; + } + if (minPulse > 0 && maxPulse > 0) { + servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse); + } else { + servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin)); + } + } else { + Firmata.sendString("Max servos attached"); + } +} + +void detachServo(byte pin) +{ + servos[servoPinMap[pin]].detach(); + // if we're detaching the last servo, decrement the count + // otherwise store the index of the detached servo + if (servoPinMap[pin] == servoCount && servoCount > 0) { + servoCount--; + } else if (servoCount > 0) { + // keep track of detached servos because we want to reuse their indexes + // before incrementing the count of attached servos + detachedServoCount++; + detachedServos[detachedServoCount - 1] = servoPinMap[pin]; + } + + servoPinMap[pin] = 255; +} + +void readAndReportData(byte address, int theRegister, byte numBytes) { + // allow I2C requests that don't require a register read + // for example, some devices using an interrupt pin to signify new data available + // do not always require the register read so upon interrupt you call Wire.requestFrom() + if (theRegister != REGISTER_NOT_SPECIFIED) { + Wire.beginTransmission(address); +#if ARDUINO >= 100 + Wire.write((byte)theRegister); +#else + Wire.send((byte)theRegister); +#endif + Wire.endTransmission(); + // do not set a value of 0 + if (i2cReadDelayTime > 0) { + // delay is necessary for some devices such as WiiNunchuck + delayMicroseconds(i2cReadDelayTime); + } + } else { + theRegister = 0; // fill the register with a dummy value + } + + Wire.requestFrom(address, numBytes); // all bytes are returned in requestFrom + + // check to be sure correct number of bytes were returned by slave + if (numBytes < Wire.available()) { + Firmata.sendString("I2C Read Error: Too many bytes received"); + } else if (numBytes > Wire.available()) { + Firmata.sendString("I2C Read Error: Too few bytes received"); + } + + i2cRxData[0] = address; + i2cRxData[1] = theRegister; + + for (int i = 0; i < numBytes && Wire.available(); i++) { +#if ARDUINO >= 100 + i2cRxData[2 + i] = Wire.read(); +#else + i2cRxData[2 + i] = Wire.receive(); +#endif + } + + // send slave address, register and received bytes + Firmata.sendSysex(SYSEX_I2C_REPLY, numBytes + 2, i2cRxData); +} + +void outputPort(byte portNumber, byte portValue, byte forceSend) +{ + // pins not configured as INPUT are cleared to zeros + portValue = portValue & portConfigInputs[portNumber]; + // only send if the value is different than previously sent + if (forceSend || previousPINs[portNumber] != portValue) { + Firmata.sendDigitalPort(portNumber, portValue); + previousPINs[portNumber] = portValue; + } +} + +/* ----------------------------------------------------------------------------- + * check all the active digital inputs for change of state, then add any events + * to the Serial output queue using Serial.print() */ +void checkDigitalInputs(void) +{ + /* Using non-looping code allows constants to be given to readPort(). + * The compiler will apply substantial optimizations if the inputs + * to readPort() are compile-time constants. */ + if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false); + if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false); + if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false); + if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false); + if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false); + if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false); + if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false); + if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false); + if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false); + if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false); + if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false); + if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false); + if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false); + if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false); + if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false); + if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false); +} + +// ----------------------------------------------------------------------------- +/* sets the pin mode to the correct state and sets the relevant bits in the + * two bit-arrays that track Digital I/O and PWM status + */ +void setPinModeCallback(byte pin, int mode) +{ + if (pinConfig[pin] == IGNORE) + return; + + if (pinConfig[pin] == I2C && isI2CEnabled && mode != I2C) { + // disable i2c so pins can be used for other functions + // the following if statements should reconfigure the pins properly + disableI2CPins(); + } + if (IS_PIN_DIGITAL(pin) && mode != SERVO) { + if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) { + detachServo(pin); + } + } + if (IS_PIN_ANALOG(pin)) { + reportAnalogCallback(PIN_TO_ANALOG(pin), mode == ANALOG ? 1 : 0); // turn on/off reporting + } + if (IS_PIN_DIGITAL(pin)) { + if (mode == INPUT) { + portConfigInputs[pin / 8] |= (1 << (pin & 7)); + } else { + portConfigInputs[pin / 8] &= ~(1 << (pin & 7)); + } + } + pinState[pin] = 0; + switch (mode) { + case ANALOG: + if (IS_PIN_ANALOG(pin)) { + if (IS_PIN_DIGITAL(pin)) { + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups + } + pinConfig[pin] = ANALOG; + } + break; + case INPUT: + if (IS_PIN_DIGITAL(pin)) { + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups + pinConfig[pin] = INPUT; + } + break; + case OUTPUT: + if (IS_PIN_DIGITAL(pin)) { + digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM + pinMode(PIN_TO_DIGITAL(pin), OUTPUT); + pinConfig[pin] = OUTPUT; + } + break; + case PWM: + if (IS_PIN_PWM(pin)) { + pinMode(PIN_TO_PWM(pin), OUTPUT); + analogWrite(PIN_TO_PWM(pin), 0); + pinConfig[pin] = PWM; + } + break; + case SERVO: + if (IS_PIN_DIGITAL(pin)) { + pinConfig[pin] = SERVO; + if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) { + // pass -1 for min and max pulse values to use default values set + // by Servo library + attachServo(pin, -1, -1); + } + } + break; + case I2C: + if (IS_PIN_I2C(pin)) { + // mark the pin as i2c + // the user must call I2C_CONFIG to enable I2C for a device + pinConfig[pin] = I2C; + } + break; + default: + Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM + } + // TODO: save status to EEPROM here, if changed +} + +void analogWriteCallback(byte pin, int value) +{ + if (pin < TOTAL_PINS) { + switch (pinConfig[pin]) { + case SERVO: + if (IS_PIN_DIGITAL(pin)) + servos[servoPinMap[pin]].write(value); + pinState[pin] = value; + break; + case PWM: + if (IS_PIN_PWM(pin)) + analogWrite(PIN_TO_PWM(pin), value); + pinState[pin] = value; + break; + } + } +} + +void digitalWriteCallback(byte port, int value) +{ + byte pin, lastPin, mask = 1, pinWriteMask = 0; + + if (port < TOTAL_PORTS) { + // create a mask of the pins on this port that are writable. + lastPin = port * 8 + 8; + if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS; + for (pin = port * 8; pin < lastPin; pin++) { + // do not disturb non-digital pins (eg, Rx & Tx) + if (IS_PIN_DIGITAL(pin)) { + // only write to OUTPUT and INPUT (enables pullup) + // do not touch pins in PWM, ANALOG, SERVO or other modes + if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) { + pinWriteMask |= mask; + pinState[pin] = ((byte)value & mask) ? 1 : 0; + } + } + mask = mask << 1; + } + writePort(port, (byte)value, pinWriteMask); + } +} + + +// ----------------------------------------------------------------------------- +/* sets bits in a bit array (int) to toggle the reporting of the analogIns + */ +//void FirmataClass::setAnalogPinReporting(byte pin, byte state) { +//} +void reportAnalogCallback(byte analogPin, int value) +{ + if (analogPin < TOTAL_ANALOG_PINS) { + if (value == 0) { + analogInputsToReport = analogInputsToReport & ~ (1 << analogPin); + } else { + analogInputsToReport = analogInputsToReport | (1 << analogPin); + // prevent during system reset or all analog pin values will be reported + // which may report noise for unconnected analog pins + if (!isResetting) { + // Send pin value immediately. This is helpful when connected via + // ethernet, wi-fi or bluetooth so pin states can be known upon + // reconnecting. + Firmata.sendAnalog(analogPin, analogRead(analogPin)); + } + } + } + // TODO: save status to EEPROM here, if changed +} + +void reportDigitalCallback(byte port, int value) +{ + if (port < TOTAL_PORTS) { + reportPINs[port] = (byte)value; + // Send port value immediately. This is helpful when connected via + // ethernet, wi-fi or bluetooth so pin states can be known upon + // reconnecting. + if (value) outputPort(port, readPort(port, portConfigInputs[port]), true); + } + // do not disable analog reporting on these 8 pins, to allow some + // pins used for digital, others analog. Instead, allow both types + // of reporting to be enabled, but check if the pin is configured + // as analog when sampling the analog inputs. Likewise, while + // scanning digital pins, portConfigInputs will mask off values from any + // pins configured as analog +} + +/*============================================================================== + * SYSEX-BASED commands + *============================================================================*/ + +void sysexCallback(byte command, byte argc, byte *argv) +{ + byte mode; + byte slaveAddress; + byte data; + int slaveRegister; + unsigned int delayTime; + + switch (command) { + case I2C_REQUEST: + mode = argv[1] & I2C_READ_WRITE_MODE_MASK; + if (argv[1] & I2C_10BIT_ADDRESS_MODE_MASK) { + Firmata.sendString("10-bit addressing not supported"); + return; + } + else { + slaveAddress = argv[0]; + } + + switch (mode) { + case I2C_WRITE: + Wire.beginTransmission(slaveAddress); + for (byte i = 2; i < argc; i += 2) { + data = argv[i] + (argv[i + 1] << 7); +#if ARDUINO >= 100 + Wire.write(data); +#else + Wire.send(data); +#endif + } + Wire.endTransmission(); + delayMicroseconds(70); + break; + case I2C_READ: + if (argc == 6) { + // a slave register is specified + slaveRegister = argv[2] + (argv[3] << 7); + data = argv[4] + (argv[5] << 7); // bytes to read + } + else { + // a slave register is NOT specified + slaveRegister = REGISTER_NOT_SPECIFIED; + data = argv[2] + (argv[3] << 7); // bytes to read + } + readAndReportData(slaveAddress, (int)slaveRegister, data); + break; + case I2C_READ_CONTINUOUSLY: + if ((queryIndex + 1) >= MAX_QUERIES) { + // too many queries, just ignore + Firmata.sendString("too many queries"); + break; + } + if (argc == 6) { + // a slave register is specified + slaveRegister = argv[2] + (argv[3] << 7); + data = argv[4] + (argv[5] << 7); // bytes to read + } + else { + // a slave register is NOT specified + slaveRegister = (int)REGISTER_NOT_SPECIFIED; + data = argv[2] + (argv[3] << 7); // bytes to read + } + queryIndex++; + query[queryIndex].addr = slaveAddress; + query[queryIndex].reg = slaveRegister; + query[queryIndex].bytes = data; + break; + case I2C_STOP_READING: + byte queryIndexToSkip; + // if read continuous mode is enabled for only 1 i2c device, disable + // read continuous reporting for that device + if (queryIndex <= 0) { + queryIndex = -1; + } else { + // if read continuous mode is enabled for multiple devices, + // determine which device to stop reading and remove it's data from + // the array, shifiting other array data to fill the space + for (byte i = 0; i < queryIndex + 1; i++) { + if (query[i].addr == slaveAddress) { + queryIndexToSkip = i; + break; + } + } + + for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) { + if (i < MAX_QUERIES) { + query[i].addr = query[i + 1].addr; + query[i].reg = query[i + 1].reg; + query[i].bytes = query[i + 1].bytes; + } + } + queryIndex--; + } + break; + default: + break; + } + break; + case I2C_CONFIG: + delayTime = (argv[0] + (argv[1] << 7)); + + if (delayTime > 0) { + i2cReadDelayTime = delayTime; + } + + if (!isI2CEnabled) { + enableI2CPins(); + } + + break; + case SERVO_CONFIG: + if (argc > 4) { + // these vars are here for clarity, they'll optimized away by the compiler + byte pin = argv[0]; + int minPulse = argv[1] + (argv[2] << 7); + int maxPulse = argv[3] + (argv[4] << 7); + + if (IS_PIN_DIGITAL(pin)) { + if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached()) { + detachServo(pin); + } + attachServo(pin, minPulse, maxPulse); + setPinModeCallback(pin, SERVO); + } + } + break; + case SAMPLING_INTERVAL: + if (argc > 1) { + samplingInterval = argv[0] + (argv[1] << 7); + if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) { + samplingInterval = MINIMUM_SAMPLING_INTERVAL; + } + } else { + //Firmata.sendString("Not enough data"); + } + break; + case EXTENDED_ANALOG: + if (argc > 1) { + int val = argv[1]; + if (argc > 2) val |= (argv[2] << 7); + if (argc > 3) val |= (argv[3] << 14); + analogWriteCallback(argv[0], val); + } + break; + case CAPABILITY_QUERY: + Firmata.write(START_SYSEX); + Firmata.write(CAPABILITY_RESPONSE); + for (byte pin = 0; pin < TOTAL_PINS; pin++) { + if (IS_PIN_DIGITAL(pin)) { + Firmata.write((byte)INPUT); + Firmata.write(1); + Firmata.write((byte)OUTPUT); + Firmata.write(1); + } + if (IS_PIN_ANALOG(pin)) { + Firmata.write(ANALOG); + Firmata.write(10); + } + if (IS_PIN_PWM(pin)) { + Firmata.write(PWM); + Firmata.write(8); + } + if (IS_PIN_DIGITAL(pin)) { + Firmata.write(SERVO); + Firmata.write(14); + } + if (IS_PIN_I2C(pin)) { + Firmata.write(I2C); + Firmata.write(1); // to do: determine appropriate value + } + Firmata.write(127); + } + Firmata.write(END_SYSEX); + break; + case PIN_STATE_QUERY: + if (argc > 0) { + byte pin = argv[0]; + Firmata.write(START_SYSEX); + Firmata.write(PIN_STATE_RESPONSE); + Firmata.write(pin); + if (pin < TOTAL_PINS) { + Firmata.write((byte)pinConfig[pin]); + Firmata.write((byte)pinState[pin] & 0x7F); + if (pinState[pin] & 0xFF80) Firmata.write((byte)(pinState[pin] >> 7) & 0x7F); + if (pinState[pin] & 0xC000) Firmata.write((byte)(pinState[pin] >> 14) & 0x7F); + } + Firmata.write(END_SYSEX); + } + break; + case ANALOG_MAPPING_QUERY: + Firmata.write(START_SYSEX); + Firmata.write(ANALOG_MAPPING_RESPONSE); + for (byte pin = 0; pin < TOTAL_PINS; pin++) { + Firmata.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127); + } + Firmata.write(END_SYSEX); + break; + } +} + +void enableI2CPins() +{ + byte i; + // is there a faster way to do this? would probaby require importing + // Arduino.h to get SCL and SDA pins + for (i = 0; i < TOTAL_PINS; i++) { + if (IS_PIN_I2C(i)) { + // mark pins as i2c so they are ignore in non i2c data requests + setPinModeCallback(i, I2C); + } + } + + isI2CEnabled = true; + + // is there enough time before the first I2C request to call this here? + Wire.begin(); +} + +/* disable the i2c pins so they can be used for other functions */ +void disableI2CPins() { + isI2CEnabled = false; + // disable read continuous mode for all devices + queryIndex = -1; +} + +/*============================================================================== + * SETUP() + *============================================================================*/ + +void systemResetCallback() +{ + isResetting = true; + // initialize a defalt state + // TODO: option to load config from EEPROM instead of default + if (isI2CEnabled) { + disableI2CPins(); + } + + for (byte i = 0; i < TOTAL_PORTS; i++) { + reportPINs[i] = false; // by default, reporting off + portConfigInputs[i] = 0; // until activated + previousPINs[i] = 0; + } + + for (byte i = 0; i < TOTAL_PINS; i++) { + // pins with analog capability default to analog input + // otherwise, pins default to digital output + if (IS_PIN_ANALOG(i)) { + // turns off pullup, configures everything + setPinModeCallback(i, ANALOG); + } else { + // sets the output to 0, configures portConfigInputs + setPinModeCallback(i, OUTPUT); + } + + servoPinMap[i] = 255; + } + // by default, do not report any analog inputs + analogInputsToReport = 0; + + detachedServoCount = 0; + servoCount = 0; + + /* send digital inputs to set the initial state on the host computer, + * since once in the loop(), this firmware will only send on change */ + /* + TODO: this can never execute, since no pins default to digital input + but it will be needed when/if we support EEPROM stored config + for (byte i=0; i < TOTAL_PORTS; i++) { + outputPort(i, readPort(i, portConfigInputs[i]), true); + } + */ + isResetting = false; +} + +void setup() +{ + Serial.begin(9600); + +#ifdef local_ip + Ethernet.begin((uint8_t *)mac, local_ip); //start ethernet +#else + Ethernet.begin((uint8_t *)mac); //start ethernet using dhcp +#endif + + delay(1000); // this delay may impact some Firmata clients + Serial.println("connecting..."); + + Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION); + + Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); + Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback); + Firmata.attach(REPORT_ANALOG, reportAnalogCallback); + Firmata.attach(REPORT_DIGITAL, reportDigitalCallback); + Firmata.attach(SET_PIN_MODE, setPinModeCallback); + Firmata.attach(START_SYSEX, sysexCallback); + Firmata.attach(SYSTEM_RESET, systemResetCallback); + + // Network Firmata communicates with Ethernet-shields over SPI. Therefor all + // SPI-pins must be set to IGNORE. Otherwise Firmata would break SPI-communication. + // add Pin 10 and configure pin 53 as output if using a MEGA with Ethernetshield. + + // ignore SPI and pin 4 that is SS for SD-Card on Ethernet-shield + for (byte i = 0; i < TOTAL_PINS; i++) { + if (IS_PIN_SPI(i) + || 4 == i // SD-Card on Ethernet-shiedl uses pin 4 for SS + || 10 == i // Ethernet-shield uses pin 10 for SS + ) { + pinConfig[i] = IGNORE; + } + } +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + setPinModeCallback(53, IGNORE); // on MEGA as 53 is hardware-SS + pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware-SS as output on MEGA +#endif + pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD-card bypassing Firmata + digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low; + + // start up Network Firmata: + Firmata.begin(stream); + systemResetCallback(); // reset to default config +} + +/*============================================================================== + * LOOP() + *============================================================================*/ +void loop() +{ + byte pin, analogPin; + + /* DIGITALREAD - as fast as possible, check for changes and output them to the + * FTDI buffer using Serial.print() */ + checkDigitalInputs(); + + /* SERIALREAD - processing incoming messagse as soon as possible, while still + * checking digital inputs. */ + while (Firmata.available()) + Firmata.processInput(); + + /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over + * 60 bytes. use a timer to sending an event character every 4 ms to + * trigger the buffer to dump. */ + + currentMillis = millis(); + if (currentMillis - previousMillis > samplingInterval) { + previousMillis += samplingInterval; + /* ANALOGREAD - do all analogReads() at the configured sampling interval */ + for (pin = 0; pin < TOTAL_PINS; pin++) { + if (IS_PIN_ANALOG(pin) && pinConfig[pin] == ANALOG) { + analogPin = PIN_TO_ANALOG(pin); + if (analogInputsToReport & (1 << analogPin)) { + Firmata.sendAnalog(analogPin, analogRead(analogPin)); + } + } + } + // report i2c data for all device with read continuous mode enabled + if (queryIndex > -1) { + for (byte i = 0; i < queryIndex + 1; i++) { + readAndReportData(query[i].addr, query[i].reg, query[i].bytes); + } + } + } + +#if !defined local_ip + if (Ethernet.maintain()) + { + stream.maintain(Ethernet.localIP()); + } +#endif + +} From 8b57a1d84a0763b04d7e061719aeb94e98931a0d Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sun, 8 Mar 2015 17:03:02 -0700 Subject: [PATCH 02/12] add ability to use Arduino Yun and ENC28J60-based shields. cleaned up file --- .../EthernetClientStream.cpp | 13 +- .../EthernetClientStream.h | 2 +- .../StandardFirmataEthernet.ino | 267 ++++++++++++------ 3 files changed, 195 insertions(+), 87 deletions(-) diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.cpp b/examples/StandardFirmataEthernet/EthernetClientStream.cpp index e010a083..2556f682 100644 --- a/examples/StandardFirmataEthernet/EthernetClientStream.cpp +++ b/examples/StandardFirmataEthernet/EthernetClientStream.cpp @@ -22,6 +22,15 @@ #define MILLIS_RECONNECT 5000 +#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINTLN(x) Serial.println (x) + #define DEBUG_PRINT(x) Serial.print (x) +#else + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINT(x) +#endif + EthernetClientStream::EthernetClientStream(Client &client, IPAddress localip, IPAddress ip, const char* host, uint16_t port) : ip(ip), host(host), @@ -96,9 +105,9 @@ EthernetClientStream::maintain() connected = host ? client.connect(host,port) : client.connect(ip,port); if (!connected) { time_connect = millis(); - Serial.println("connection failed"); + DEBUG_PRINTLN("connection failed"); } else { - Serial.println("connected"); + DEBUG_PRINTLN("connected"); } } return connected; diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.h b/examples/StandardFirmataEthernet/EthernetClientStream.h index ab12e888..c0d34e54 100644 --- a/examples/StandardFirmataEthernet/EthernetClientStream.h +++ b/examples/StandardFirmataEthernet/EthernetClientStream.h @@ -49,4 +49,4 @@ class EthernetClientStream : public Stream void stop(); }; -#endif \ No newline at end of file +#endif diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index 8ddd861d..09d64002 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -1,15 +1,13 @@ /* - * Firmata is a generic protocol for communicating with microcontrollers - * from software on a host computer. It is intended to work with - * any host computer software package. - * - * To download a host software package, please clink on the following link - * to open the download page in your default browser. - * - * http://firmata.org/wiki/Download - */ + Firmata is a generic protocol for communicating with microcontrollers + from software on a host computer. It is intended to work with + any host computer software package. + + To download a host software package, please clink on the following link + to open the list of Firmata client libraries your default browser. + + https://github.com/firmata/arduino#firmata-client-libraries -/* Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. @@ -22,56 +20,134 @@ See file LICENSE.txt for further informations on licensing terms. - formatted using the GNU C formatting and indenting + Last updated by Jeff Hoefs: March 8, 2015 +*/ + +/* + README + + To use StandardFirmataEthernet you will need to have one of the following + boards or shields: + + - Arduino Ethernet shield (or clone) + - Arduino Ethernet board (or clone) + - Arduino Yun + - An ENC28J60-based ethernet shield or board + + Follow the instructions in the NETWORK CONFIGURATION section below to + configure your particular hardware. */ #include #include #include -#include -#include -#include "EthernetClientStream.h" + +#define DEBUG +#ifdef DEBUG + #define DEBUG_PRINTLN(x) Serial.println (x) + #define DEBUG_PRINT(x) Serial.print (x) +#else + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINT(x) +#endif + +#define I2C_WRITE B00000000 +#define I2C_READ B00001000 +#define I2C_READ_CONTINUOUSLY B00010000 +#define I2C_STOP_READING B00011000 +#define I2C_READ_WRITE_MODE_MASK B00011000 +#define I2C_10BIT_ADDRESS_MODE_MASK B00100000 +#define I2C_MAX_QUERIES 8 +#define I2C_REGISTER_NOT_SPECIFIED -1 + +// the minimum interval for sampling analog input +#define MINIMUM_SAMPLING_INTERVAL 10 + + +/*============================================================================== + * NETWORK CONFIGURATION + * + * You must configure your particular hardware. Follow the steps below. + *============================================================================*/ + +// STEP 1 [REQUIRED] +// Uncomment the appropriate set of includes for your hardware (OPTION A, B or C) + +/* + * OPTION A: Configure for Arduino Ethernet board or shield + * + * To configure StandardFirmataEthernet to use the original WIZ5100-based + * ethernet shield or Arduino Ethernet uncomment the includes of 'SPI.h' and 'Ethernet.h': + */ + +// #include +// #include + +/* + * OPTION B: Configure for Arduin Yun + * + * To execute StandardFirmataEthernet on Yun uncomment Bridge.h and YunClient.h. + * Do not include Ethernet.h or SPI.h above in this case. + * On Yun there's no need to configure local_ip and mac in the sketch + * as this is configured on the linux-side of Yun. + */ + +// #include +// #include /* - * network configuration + * OPTION C: Configure for ENC28J60-based Ethernt boards or shields + * + * To configure StandardFirmataEthernet to use an ENC28J60 based board include + * 'UIPEthernet.h' (no SPI.h or Ethernet.h required). + * The UIPEthernet-library can be downloaded from: https://github.com/ntruchsess/arduino_uip */ + +// #include + +// STEP 2 [REQUIRED for all boards and shields] // replace with IP of the server you want to connect to, comment out if using 'remote_host' #define remote_ip IPAddress(10, 0, 0, 3) - // *** REMOTE HOST IS NOT YET WORKING *** // replace with hostname of server you want to connect to, comment out if using 'remote_ip' // #define remote_host "server.local" -// replace with the port that your server is listening on +// STEP 3 [REQUIRED unless using Arduin Yun] +// Replace with the port that your server is listening on #define remote_port 3030 -// replace with the Arduino's IP address. Comment out if Ethernet-startup should use dhcp. + +// STEP 4 [REQUIRED unless using Arduino Yun OR if not using DHCP] +// Replace with your board or ethernet shield's IP address +// Comment out if you want to use DHCP #define local_ip IPAddress(10, 0, 0, 15) + +// STEP 5 [REQUIRED unless using Arduino Yun] // replace with ethernet shield mac. It's mandatory every devices is assigned a unique mac address const byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x53, 0xE5}; +#if !defined ethernet_h && !defined _YUN_CLIENT_H_ && !defined UIPEthernet_H +#error "you must uncomment the includes for your board configuration. See OPTIONS A, B and C in the NETWORK CONFIGURATION SECTION" +#endif + #if defined remote_ip && defined remote_host #error "cannot define both remote_ip and remote_host at the same time!" #endif -// move the following defines to Firmata.h? -#define I2C_WRITE B00000000 -#define I2C_READ B00001000 -#define I2C_READ_CONTINUOUSLY B00010000 -#define I2C_STOP_READING B00011000 -#define I2C_READ_WRITE_MODE_MASK B00011000 -#define I2C_10BIT_ADDRESS_MODE_MASK B00100000 - -#define MAX_QUERIES 8 -#define MINIMUM_SAMPLING_INTERVAL 10 - -#define REGISTER_NOT_SPECIFIED -1 /*============================================================================== * GLOBAL VARIABLES *============================================================================*/ /* network */ + +#include "EthernetClientStream.h" + +#ifdef _YUN_CLIENT_H_ +YunClient client; +#else EthernetClient client; +#endif + #if defined remote_ip && !defined remote_host #ifdef local_ip EthernetClientStream stream(client, local_ip, remote_ip, NULL, remote_port); @@ -79,6 +155,7 @@ EthernetClientStream stream(client, local_ip, remote_ip, NULL, remote_port); EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), remote_ip, NULL, remote_port); #endif #endif + #if !defined remote_ip && defined remote_host #ifdef local_ip EthernetClientStream stream(client, local_ip, IPAddress(0, 0, 0, 0), remote_host, remote_port); @@ -88,7 +165,7 @@ EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0) #endif /* analog inputs */ -int analogInputsToReport = 0; // bitwise array to store pin reporting +int analogInputsToReport = 0; // bitwise array to store pin reporting /* digital input ports */ byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence @@ -102,7 +179,7 @@ int pinState[TOTAL_PINS]; // any value that has been written /* timer variables */ unsigned long currentMillis; // store the current value from millis() unsigned long previousMillis; // for comparison with currentMillis -unsigned int samplingInterval = 19; // how often to run the main loop (in ms) +unsigned int samplingInterval = 19; // how often to sample analog inputs (in ms) /* i2c data */ struct i2c_device_info { @@ -111,15 +188,14 @@ struct i2c_device_info { byte bytes; }; -/* for i2c read continuous more */ -i2c_device_info query[MAX_QUERIES]; - -boolean isResetting = false; +/* for i2c read continuous mode */ +i2c_device_info query[I2C_MAX_QUERIES]; byte i2cRxData[32]; boolean isI2CEnabled = false; signed char queryIndex = -1; -unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom() +// default delay time between i2c read request and Wire.requestFrom() +unsigned int i2cReadDelayTime = 0; Servo servos[MAX_SERVOS]; byte servoPinMap[TOTAL_PINS]; @@ -127,6 +203,26 @@ byte detachedServos[MAX_SERVOS]; byte detachedServoCount = 0; byte servoCount = 0; +boolean isResetting = false; + +/* utility functions */ +void wireWrite(byte data) +{ +#if ARDUINO >= 100 + Wire.write((byte)data); +#else + Wire.send(data); +#endif +} + +byte wireRead(void) +{ +#if ARDUINO >= 100 + return Wire.read(); +#else + return Wire.receive(); +#endif +} /*============================================================================== * FUNCTIONS @@ -174,13 +270,9 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // allow I2C requests that don't require a register read // for example, some devices using an interrupt pin to signify new data available // do not always require the register read so upon interrupt you call Wire.requestFrom() - if (theRegister != REGISTER_NOT_SPECIFIED) { + if (theRegister != I2C_REGISTER_NOT_SPECIFIED) { Wire.beginTransmission(address); -#if ARDUINO >= 100 - Wire.write((byte)theRegister); -#else - Wire.send((byte)theRegister); -#endif + wireWrite((byte)theRegister); Wire.endTransmission(); // do not set a value of 0 if (i2cReadDelayTime > 0) { @@ -195,20 +287,16 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // check to be sure correct number of bytes were returned by slave if (numBytes < Wire.available()) { - Firmata.sendString("I2C Read Error: Too many bytes received"); + Firmata.sendString("I2C: Too many bytes received"); } else if (numBytes > Wire.available()) { - Firmata.sendString("I2C Read Error: Too few bytes received"); + Firmata.sendString("I2C: Too few bytes received"); } i2cRxData[0] = address; i2cRxData[1] = theRegister; for (int i = 0; i < numBytes && Wire.available(); i++) { -#if ARDUINO >= 100 - i2cRxData[2 + i] = Wire.read(); -#else - i2cRxData[2 + i] = Wire.receive(); -#endif + i2cRxData[2 + i] = wireRead(); } // send slave address, register and received bytes @@ -228,7 +316,7 @@ void outputPort(byte portNumber, byte portValue, byte forceSend) /* ----------------------------------------------------------------------------- * check all the active digital inputs for change of state, then add any events - * to the Serial output queue using Serial.print() */ + * to the Stream output queue using Stream.write() */ void checkDigitalInputs(void) { /* Using non-looping code allows constants to be given to readPort(). @@ -286,7 +374,7 @@ void setPinModeCallback(byte pin, int mode) case ANALOG: if (IS_PIN_ANALOG(pin)) { if (IS_PIN_DIGITAL(pin)) { - pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups } pinConfig[pin] = ANALOG; @@ -294,7 +382,7 @@ void setPinModeCallback(byte pin, int mode) break; case INPUT: if (IS_PIN_DIGITAL(pin)) { - pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups pinConfig[pin] = INPUT; } @@ -449,11 +537,7 @@ void sysexCallback(byte command, byte argc, byte *argv) Wire.beginTransmission(slaveAddress); for (byte i = 2; i < argc; i += 2) { data = argv[i] + (argv[i + 1] << 7); -#if ARDUINO >= 100 - Wire.write(data); -#else - Wire.send(data); -#endif + wireWrite(data); } Wire.endTransmission(); delayMicroseconds(70); @@ -466,15 +550,15 @@ void sysexCallback(byte command, byte argc, byte *argv) } else { // a slave register is NOT specified - slaveRegister = REGISTER_NOT_SPECIFIED; + slaveRegister = I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7); // bytes to read } readAndReportData(slaveAddress, (int)slaveRegister, data); break; case I2C_READ_CONTINUOUSLY: - if ((queryIndex + 1) >= MAX_QUERIES) { + if ((queryIndex + 1) >= I2C_MAX_QUERIES) { // too many queries, just ignore - Firmata.sendString("too many queries"); + Firmata.sendString("too many I2C queries"); break; } if (argc == 6) { @@ -484,7 +568,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } else { // a slave register is NOT specified - slaveRegister = (int)REGISTER_NOT_SPECIFIED; + slaveRegister = (int)I2C_REGISTER_NOT_SPECIFIED; data = argv[2] + (argv[3] << 7); // bytes to read } queryIndex++; @@ -510,7 +594,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } for (byte i = queryIndexToSkip; i < queryIndex + 1; i++) { - if (i < MAX_QUERIES) { + if (i < I2C_MAX_QUERIES) { query[i].addr = query[i + 1].addr; query[i].reg = query[i + 1].reg; query[i].bytes = query[i + 1].bytes; @@ -593,7 +677,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } if (IS_PIN_I2C(pin)) { Firmata.write(I2C); - Firmata.write(1); // to do: determine appropriate value + Firmata.write(1); // TODO: could assign a number to map to SCL or SDA } Firmata.write(127); } @@ -639,7 +723,6 @@ void enableI2CPins() isI2CEnabled = true; - // is there enough time before the first I2C request to call this here? Wire.begin(); } @@ -657,14 +740,16 @@ void disableI2CPins() { void systemResetCallback() { isResetting = true; + // initialize a defalt state // TODO: option to load config from EEPROM instead of default + if (isI2CEnabled) { disableI2CPins(); } for (byte i = 0; i < TOTAL_PORTS; i++) { - reportPINs[i] = false; // by default, reporting off + reportPINs[i] = false; // by default, reporting off portConfigInputs[i] = 0; // until activated previousPINs[i] = 0; } @@ -702,16 +787,25 @@ void systemResetCallback() void setup() { +#ifdef DEBUG Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Need only for ATmega32u4-based boards (Leonardo) + } +#endif +#ifdef _YUN_CLIENT_H_ + Bridge.begin(); +#else #ifdef local_ip Ethernet.begin((uint8_t *)mac, local_ip); //start ethernet #else - Ethernet.begin((uint8_t *)mac); //start ethernet using dhcp + Ethernet.begin((uint8_t *)mac); //start ethernet using dhcp +#endif #endif - delay(1000); // this delay may impact some Firmata clients - Serial.println("connecting..."); + delay(1000); // TODO: determine if this delay is necessary and if so how short it can be + DEBUG_PRINTLN("connecting..."); Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION); @@ -723,25 +817,32 @@ void setup() Firmata.attach(START_SYSEX, sysexCallback); Firmata.attach(SYSTEM_RESET, systemResetCallback); - // Network Firmata communicates with Ethernet-shields over SPI. Therefor all - // SPI-pins must be set to IGNORE. Otherwise Firmata would break SPI-communication. - // add Pin 10 and configure pin 53 as output if using a MEGA with Ethernetshield. + // StandardFirmataEthernet communicates with Ethernet shields over SPI. Therefor all + // SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication. + // add Pin 10 and configure pin 53 as output if using a MEGA with an Ethernet shield. + // No need to ignore pin 10 on MEGA with ENC28J60, as here pin 53 should be connected to SS: +#if !defined UIPEthernet_H // ignore SPI and pin 4 that is SS for SD-Card on Ethernet-shield for (byte i = 0; i < TOTAL_PINS; i++) { if (IS_PIN_SPI(i) - || 4 == i // SD-Card on Ethernet-shiedl uses pin 4 for SS - || 10 == i // Ethernet-shield uses pin 10 for SS + || 4 == i // SD-Card on Ethernet-shiedl uses pin 4 for SS + || 10 == i // Ethernet-shield uses pin 10 for SS ) { pinConfig[i] = IGNORE; } } + + // Arduino Ethernet, Arduino EthernetShield and Arduino Yun all have SD SS wired to D4 + pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD card bypassing Firmata + digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low; + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - setPinModeCallback(53, IGNORE); // on MEGA as 53 is hardware-SS - pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware-SS as output on MEGA + setPinModeCallback(53, IGNORE); // on MEGA as 53 is hardware SS + pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA +#endif + #endif - pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD-card bypassing Firmata - digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low; // start up Network Firmata: Firmata.begin(stream); @@ -756,17 +857,15 @@ void loop() byte pin, analogPin; /* DIGITALREAD - as fast as possible, check for changes and output them to the - * FTDI buffer using Serial.print() */ + * Stream buffer using Stream.write() */ checkDigitalInputs(); - /* SERIALREAD - processing incoming messagse as soon as possible, while still + /* STREAMREAD - processing incoming messagse as soon as possible, while still * checking digital inputs. */ while (Firmata.available()) Firmata.processInput(); - /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over - * 60 bytes. use a timer to sending an event character every 4 ms to - * trigger the buffer to dump. */ + // TODO - ensure that Stream buffer doesn't go over 60 bytes currentMillis = millis(); if (currentMillis - previousMillis > samplingInterval) { @@ -788,7 +887,7 @@ void loop() } } -#if !defined local_ip +#if !defined local_ip && !defined _YUN_CLIENT_H_ if (Ethernet.maintain()) { stream.maintain(Ethernet.localIP()); From aedabfc399d65911c28106230d8a6bb832e375a8 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Tue, 10 Mar 2015 21:26:44 -0700 Subject: [PATCH 03/12] fix UIPEthernet guard constant. add note about needing at least 4 KB of SRAM to use UIPEthernt --- .../StandardFirmataEthernet/StandardFirmataEthernet.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index 09d64002..a2795374 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -101,6 +101,10 @@ * To configure StandardFirmataEthernet to use an ENC28J60 based board include * 'UIPEthernet.h' (no SPI.h or Ethernet.h required). * The UIPEthernet-library can be downloaded from: https://github.com/ntruchsess/arduino_uip + * + * NOTE there is not enough memory to use UIPEthenet with an Arduino Uno or Leonardo + * (or other ATmega328 or ATmega32u4 based board). Use an Arduino Mega or other board + * that has at least 4 KB of SRAM. */ // #include @@ -125,7 +129,7 @@ // replace with ethernet shield mac. It's mandatory every devices is assigned a unique mac address const byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x53, 0xE5}; -#if !defined ethernet_h && !defined _YUN_CLIENT_H_ && !defined UIPEthernet_H +#if !defined ethernet_h && !defined _YUN_CLIENT_H_ && !defined UIPETHERNET_H #error "you must uncomment the includes for your board configuration. See OPTIONS A, B and C in the NETWORK CONFIGURATION SECTION" #endif From 8b0200855da032c930a398d845cd520cbde7e616 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Fri, 10 Apr 2015 20:40:28 -0700 Subject: [PATCH 04/12] removed UIPEthernet option and included Arduino Ethernet by default --- .../StandardFirmataEthernet.ino | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index a2795374..7e416cec 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -20,7 +20,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated by Jeff Hoefs: March 8, 2015 + Last updated by Jeff Hoefs: April 10, 2015 */ /* @@ -32,7 +32,6 @@ - Arduino Ethernet shield (or clone) - Arduino Ethernet board (or clone) - Arduino Yun - - An ENC28J60-based ethernet shield or board Follow the instructions in the NETWORK CONFIGURATION section below to configure your particular hardware. @@ -42,7 +41,7 @@ #include #include -#define DEBUG +//#define DEBUG #ifdef DEBUG #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINT(x) Serial.print (x) @@ -71,7 +70,8 @@ *============================================================================*/ // STEP 1 [REQUIRED] -// Uncomment the appropriate set of includes for your hardware (OPTION A, B or C) +// Uncomment / comment the appropriate set of includes for your hardware (OPTION A or B) +// Option A is enabled by default. /* * OPTION A: Configure for Arduino Ethernet board or shield @@ -80,8 +80,8 @@ * ethernet shield or Arduino Ethernet uncomment the includes of 'SPI.h' and 'Ethernet.h': */ -// #include -// #include +#include +#include /* * OPTION B: Configure for Arduin Yun @@ -95,19 +95,6 @@ // #include // #include -/* - * OPTION C: Configure for ENC28J60-based Ethernt boards or shields - * - * To configure StandardFirmataEthernet to use an ENC28J60 based board include - * 'UIPEthernet.h' (no SPI.h or Ethernet.h required). - * The UIPEthernet-library can be downloaded from: https://github.com/ntruchsess/arduino_uip - * - * NOTE there is not enough memory to use UIPEthenet with an Arduino Uno or Leonardo - * (or other ATmega328 or ATmega32u4 based board). Use an Arduino Mega or other board - * that has at least 4 KB of SRAM. - */ - -// #include // STEP 2 [REQUIRED for all boards and shields] // replace with IP of the server you want to connect to, comment out if using 'remote_host' @@ -126,11 +113,11 @@ #define local_ip IPAddress(10, 0, 0, 15) // STEP 5 [REQUIRED unless using Arduino Yun] -// replace with ethernet shield mac. It's mandatory every devices is assigned a unique mac address +// replace with ethernet shield mac. Must be unique for your network const byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x53, 0xE5}; -#if !defined ethernet_h && !defined _YUN_CLIENT_H_ && !defined UIPETHERNET_H -#error "you must uncomment the includes for your board configuration. See OPTIONS A, B and C in the NETWORK CONFIGURATION SECTION" +#if !defined ethernet_h && !defined _YUN_CLIENT_H_ +#error "you must uncomment the includes for your board configuration. See OPTIONS A and B in the NETWORK CONFIGURATION SECTION" #endif #if defined remote_ip && defined remote_host @@ -824,9 +811,7 @@ void setup() // StandardFirmataEthernet communicates with Ethernet shields over SPI. Therefor all // SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication. // add Pin 10 and configure pin 53 as output if using a MEGA with an Ethernet shield. - // No need to ignore pin 10 on MEGA with ENC28J60, as here pin 53 should be connected to SS: -#if !defined UIPEthernet_H // ignore SPI and pin 4 that is SS for SD-Card on Ethernet-shield for (byte i = 0; i < TOTAL_PINS; i++) { if (IS_PIN_SPI(i) @@ -844,8 +829,6 @@ void setup() #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) setPinModeCallback(53, IGNORE); // on MEGA as 53 is hardware SS pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA -#endif - #endif // start up Network Firmata: From 2ada71b558d64123900ea4374b68e795e7d1d7c7 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Fri, 10 Apr 2015 20:45:57 -0700 Subject: [PATCH 05/12] no debugging by default --- examples/StandardFirmataEthernet/EthernetClientStream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.cpp b/examples/StandardFirmataEthernet/EthernetClientStream.cpp index 2556f682..0d46f7c8 100644 --- a/examples/StandardFirmataEthernet/EthernetClientStream.cpp +++ b/examples/StandardFirmataEthernet/EthernetClientStream.cpp @@ -22,7 +22,7 @@ #define MILLIS_RECONNECT 5000 -#define DEBUG +//#define DEBUG #ifdef DEBUG #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINT(x) Serial.print (x) From 08758cbf1ba1544a8bb42f5832531c104d9ae9fa Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 12:58:01 -0700 Subject: [PATCH 06/12] fixed Leonardo issue --- examples/StandardFirmataEthernet/StandardFirmataEthernet.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index 7e416cec..2df357db 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -817,6 +817,9 @@ void setup() if (IS_PIN_SPI(i) || 4 == i // SD-Card on Ethernet-shiedl uses pin 4 for SS || 10 == i // Ethernet-shield uses pin 10 for SS +#if defined(__AVR_ATmega32U4__) + || 28 == i // On Leonardo, pin 28 is A10 which maps to D10 +#endif ) { pinConfig[i] = IGNORE; } From 979d46f944f30b1ee867b45236139f3ff0bcd7e9 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 18:24:15 -0700 Subject: [PATCH 07/12] moved debug macro to separate file --- .../EthernetClientStream.cpp | 12 +++--------- .../StandardFirmataEthernet.ino | 17 +++-------------- examples/StandardFirmataEthernet/debug.h | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 23 deletions(-) create mode 100644 examples/StandardFirmataEthernet/debug.h diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.cpp b/examples/StandardFirmataEthernet/EthernetClientStream.cpp index 0d46f7c8..74344096 100644 --- a/examples/StandardFirmataEthernet/EthernetClientStream.cpp +++ b/examples/StandardFirmataEthernet/EthernetClientStream.cpp @@ -20,16 +20,10 @@ #include "EthernetClientStream.h" #include -#define MILLIS_RECONNECT 5000 - //#define DEBUG -#ifdef DEBUG - #define DEBUG_PRINTLN(x) Serial.println (x) - #define DEBUG_PRINT(x) Serial.print (x) -#else - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINT(x) -#endif +#include "debug.h" + +#define MILLIS_RECONNECT 5000 EthernetClientStream::EthernetClientStream(Client &client, IPAddress localip, IPAddress ip, const char* host, uint16_t port) : ip(ip), diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index 2df357db..2832063e 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -20,7 +20,7 @@ See file LICENSE.txt for further informations on licensing terms. - Last updated by Jeff Hoefs: April 10, 2015 + Last updated by Jeff Hoefs: April 11, 2015 */ /* @@ -42,13 +42,7 @@ #include //#define DEBUG -#ifdef DEBUG - #define DEBUG_PRINTLN(x) Serial.println (x) - #define DEBUG_PRINT(x) Serial.print (x) -#else - #define DEBUG_PRINTLN(x) - #define DEBUG_PRINT(x) -#endif +#include "debug.h" #define I2C_WRITE B00000000 #define I2C_READ B00001000 @@ -778,12 +772,7 @@ void systemResetCallback() void setup() { -#ifdef DEBUG - Serial.begin(9600); - while (!Serial) { - ; // wait for serial port to connect. Need only for ATmega32u4-based boards (Leonardo) - } -#endif + DEBUG_BEGIN(9600); #ifdef _YUN_CLIENT_H_ Bridge.begin(); diff --git a/examples/StandardFirmataEthernet/debug.h b/examples/StandardFirmataEthernet/debug.h new file mode 100644 index 00000000..d894c9f7 --- /dev/null +++ b/examples/StandardFirmataEthernet/debug.h @@ -0,0 +1,14 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef DEBUG + #define DEBUG_BEGIN(baud) Serial.begin(baud); while(!Serial) {;} + #define DEBUG_PRINTLN(x) Serial.println (x) + #define DEBUG_PRINT(x) Serial.print (x) +#else + #define DEBUG_BEGIN(baud) + #define DEBUG_PRINTLN(x) + #define DEBUG_PRINT(x) +#endif + +#endif /* DEBUG_H */ From a0dc3e0252cea89c29797f27c84c30e5e2e8f8d5 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 18:54:03 -0700 Subject: [PATCH 08/12] apply some changes from StandardFirmataEthernet to StandardFirmata --- examples/StandardFirmata/StandardFirmata.ino | 114 +++++++++--------- .../StandardFirmataEthernet.ino | 4 +- 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/examples/StandardFirmata/StandardFirmata.ino b/examples/StandardFirmata/StandardFirmata.ino index 49da4abb..bc044dcd 100644 --- a/examples/StandardFirmata/StandardFirmata.ino +++ b/examples/StandardFirmata/StandardFirmata.ino @@ -1,19 +1,17 @@ /* - * Firmata is a generic protocol for communicating with microcontrollers - * from software on a host computer. It is intended to work with - * any host computer software package. - * - * To download a host software package, please clink on the following link - * to open the download page in your default browser. - * - * http://firmata.org/wiki/Download - */ + Firmata is a generic protocol for communicating with microcontrollers + from software on a host computer. It is intended to work with + any host computer software package. + + To download a host software package, please clink on the following link + to open the download page in your default browser. + + https://github.com/firmata/arduino#firmata-client-libraries -/* Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. - Copyright (C) 2009-2014 Jeff Hoefs. All rights reserved. + Copyright (C) 2009-2015 Jeff Hoefs. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -22,29 +20,26 @@ See file LICENSE.txt for further informations on licensing terms. - formatted using the GNU C formatting and indenting + Last updated by Jeff Hoefs: April 11, 2015 */ -/* - * TODO: use Program Control to load stored profiles from EEPROM - */ - #include #include #include // move the following defines to Firmata.h? -#define I2C_WRITE B00000000 -#define I2C_READ B00001000 -#define I2C_READ_CONTINUOUSLY B00010000 -#define I2C_STOP_READING B00011000 -#define I2C_READ_WRITE_MODE_MASK B00011000 +#define I2C_WRITE B00000000 +#define I2C_READ B00001000 +#define I2C_READ_CONTINUOUSLY B00010000 +#define I2C_STOP_READING B00011000 +#define I2C_READ_WRITE_MODE_MASK B00011000 #define I2C_10BIT_ADDRESS_MODE_MASK B00100000 +#define MAX_QUERIES 8 +#define REGISTER_NOT_SPECIFIED -1 -#define MAX_QUERIES 8 +// the minimum interval for sampling analog input #define MINIMUM_SAMPLING_INTERVAL 10 -#define REGISTER_NOT_SPECIFIED -1 /*============================================================================== * GLOBAL VARIABLES @@ -65,7 +60,7 @@ int pinState[TOTAL_PINS]; // any value that has been written /* timer variables */ unsigned long currentMillis; // store the current value from millis() unsigned long previousMillis; // for comparison with currentMillis -unsigned int samplingInterval = 19; // how often to run the main loop (in ms) +unsigned int samplingInterval = 19; // how often to run the main loop (in ms) /* i2c data */ struct i2c_device_info { @@ -77,12 +72,11 @@ struct i2c_device_info { /* for i2c read continuous more */ i2c_device_info query[MAX_QUERIES]; -boolean isResetting = false; - byte i2cRxData[32]; boolean isI2CEnabled = false; signed char queryIndex = -1; -unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom() +// default delay time between i2c read request and Wire.requestFrom() +unsigned int i2cReadDelayTime = 0; Servo servos[MAX_SERVOS]; byte servoPinMap[TOTAL_PINS]; @@ -90,6 +84,26 @@ byte detachedServos[MAX_SERVOS]; byte detachedServoCount = 0; byte servoCount = 0; +boolean isResetting = false; + +/* utility functions */ +void wireWrite(byte data) +{ +#if ARDUINO >= 100 + Wire.write((byte)data); +#else + Wire.send(data); +#endif +} + +byte wireRead(void) +{ +#if ARDUINO >= 100 + return Wire.read(); +#else + return Wire.receive(); +#endif +} /*============================================================================== * FUNCTIONS @@ -139,11 +153,7 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // do not always require the register read so upon interrupt you call Wire.requestFrom() if (theRegister != REGISTER_NOT_SPECIFIED) { Wire.beginTransmission(address); -#if ARDUINO >= 100 - Wire.write((byte)theRegister); -#else - Wire.send((byte)theRegister); -#endif + wireWrite((byte)theRegister); Wire.endTransmission(); // do not set a value of 0 if (i2cReadDelayTime > 0) { @@ -158,20 +168,16 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // check to be sure correct number of bytes were returned by slave if (numBytes < Wire.available()) { - Firmata.sendString("I2C Read Error: Too many bytes received"); + Firmata.sendString("I2C: Too many bytes received"); } else if (numBytes > Wire.available()) { - Firmata.sendString("I2C Read Error: Too few bytes received"); + Firmata.sendString("I2C: Too few bytes received"); } i2cRxData[0] = address; i2cRxData[1] = theRegister; for (int i = 0; i < numBytes && Wire.available(); i++) { -#if ARDUINO >= 100 - i2cRxData[2 + i] = Wire.read(); -#else - i2cRxData[2 + i] = Wire.receive(); -#endif + i2cRxData[2 + i] = wireRead(); } // send slave address, register and received bytes @@ -221,6 +227,9 @@ void checkDigitalInputs(void) */ void setPinModeCallback(byte pin, int mode) { + if (pinConfig[pin] == IGNORE) + return; + if (pinConfig[pin] == I2C && isI2CEnabled && mode != I2C) { // disable i2c so pins can be used for other functions // the following if statements should reconfigure the pins properly @@ -246,7 +255,7 @@ void setPinModeCallback(byte pin, int mode) case ANALOG: if (IS_PIN_ANALOG(pin)) { if (IS_PIN_DIGITAL(pin)) { - pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups } pinConfig[pin] = ANALOG; @@ -254,7 +263,7 @@ void setPinModeCallback(byte pin, int mode) break; case INPUT: if (IS_PIN_DIGITAL(pin)) { - pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups pinConfig[pin] = INPUT; } @@ -409,11 +418,7 @@ void sysexCallback(byte command, byte argc, byte *argv) Wire.beginTransmission(slaveAddress); for (byte i = 2; i < argc; i += 2) { data = argv[i] + (argv[i + 1] << 7); -#if ARDUINO >= 100 - Wire.write(data); -#else - Wire.send(data); -#endif + wireWrite(data); } Wire.endTransmission(); delayMicroseconds(70); @@ -541,11 +546,11 @@ void sysexCallback(byte command, byte argc, byte *argv) } if (IS_PIN_ANALOG(pin)) { Firmata.write(ANALOG); - Firmata.write(10); + Firmata.write(10); // 10 = 10-bit resolution } if (IS_PIN_PWM(pin)) { Firmata.write(PWM); - Firmata.write(8); + Firmata.write(8); // 8 = 8-bit resolution } if (IS_PIN_DIGITAL(pin)) { Firmata.write(SERVO); @@ -553,7 +558,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } if (IS_PIN_I2C(pin)) { Firmata.write(I2C); - Firmata.write(1); // to do: determine appropriate value + Firmata.write(1); // TODO: could assign a number to map to SCL or SDA } Firmata.write(127); } @@ -599,7 +604,6 @@ void enableI2CPins() isI2CEnabled = true; - // is there enough time before the first I2C request to call this here? Wire.begin(); } @@ -617,14 +621,16 @@ void disableI2CPins() { void systemResetCallback() { isResetting = true; + // initialize a defalt state // TODO: option to load config from EEPROM instead of default + if (isI2CEnabled) { disableI2CPins(); } for (byte i = 0; i < TOTAL_PORTS; i++) { - reportPINs[i] = false; // by default, reporting off + reportPINs[i] = false; // by default, reporting off portConfigInputs[i] = 0; // until activated previousPINs[i] = 0; } @@ -687,14 +693,12 @@ void loop() * FTDI buffer using Serial.print() */ checkDigitalInputs(); - /* SERIALREAD - processing incoming messagse as soon as possible, while still + /* STREAMREAD - processing incoming messagse as soon as possible, while still * checking digital inputs. */ while (Firmata.available()) Firmata.processInput(); - /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over - * 60 bytes. use a timer to sending an event character every 4 ms to - * trigger the buffer to dump. */ + // TODO - ensure that Stream buffer doesn't go over 60 bytes currentMillis = millis(); if (currentMillis - previousMillis > samplingInterval) { diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index 2832063e..ec7e353c 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -650,11 +650,11 @@ void sysexCallback(byte command, byte argc, byte *argv) } if (IS_PIN_ANALOG(pin)) { Firmata.write(ANALOG); - Firmata.write(10); + Firmata.write(10); // 10 = 10-bit resolution } if (IS_PIN_PWM(pin)) { Firmata.write(PWM); - Firmata.write(8); + Firmata.write(8); // 8 = 8-bit resolution } if (IS_PIN_DIGITAL(pin)) { Firmata.write(SERVO); From ebc77f97694b361cd3e2a594dbafb6827b207d61 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 21:40:09 -0700 Subject: [PATCH 09/12] removed unnecessary code and added D24 to Leonardo ignore list --- .../StandardFirmataEthernet.ino | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index ec7e353c..4843fda0 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -35,6 +35,14 @@ Follow the instructions in the NETWORK CONFIGURATION section below to configure your particular hardware. + + NOTE: If you are using an Arduino Ethernet shield you cannot use the following pins on + the following boards. Firmata will ignore any requests to use these pins: + + - Arduino Uno or other ATMega328 boards: (D4, D10, D11, D12, D13) + - Arduino Mega: (D4, D10, D50, D51, D52, D53) + - Arduino Leonardo: (D4, D10) + - Arduino Due: (D4, D10) */ #include @@ -784,7 +792,6 @@ void setup() #endif #endif - delay(1000); // TODO: determine if this delay is necessary and if so how short it can be DEBUG_PRINTLN("connecting..."); Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION); @@ -807,7 +814,8 @@ void setup() || 4 == i // SD-Card on Ethernet-shiedl uses pin 4 for SS || 10 == i // Ethernet-shield uses pin 10 for SS #if defined(__AVR_ATmega32U4__) - || 28 == i // On Leonardo, pin 28 is A10 which maps to D10 + || 24 == i // On Leonardo, pin 24 maps to D4 and pin 28 maps to D10 + || 28 == i #endif ) { pinConfig[i] = IGNORE; @@ -819,7 +827,6 @@ void setup() digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low; #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - setPinModeCallback(53, IGNORE); // on MEGA as 53 is hardware SS pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA #endif From 407971be75a8c72c24929b48f9417754dbb0bf9b Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 22:26:02 -0700 Subject: [PATCH 10/12] moved debug lib and EthernetClientStream to utility folder --- .../StandardFirmataEthernet/StandardFirmataEthernet.ino | 6 +++--- release.sh | 2 ++ .../EthernetClientStream.cpp | 4 ++-- .../EthernetClientStream.h | 0 .../debug.h => utility/firmataDebug.h | 8 ++++---- 5 files changed, 11 insertions(+), 9 deletions(-) rename {examples/StandardFirmataEthernet => utility}/EthernetClientStream.cpp (97%) rename {examples/StandardFirmataEthernet => utility}/EthernetClientStream.h (100%) rename examples/StandardFirmataEthernet/debug.h => utility/firmataDebug.h (72%) diff --git a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino index 4843fda0..cc5fdb0f 100644 --- a/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino +++ b/examples/StandardFirmataEthernet/StandardFirmataEthernet.ino @@ -49,8 +49,8 @@ #include #include -//#define DEBUG -#include "debug.h" +//#define SERIAL_DEBUG +#include "utility/firmataDebug.h" #define I2C_WRITE B00000000 #define I2C_READ B00001000 @@ -133,7 +133,7 @@ const byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x53, 0xE5}; /* network */ -#include "EthernetClientStream.h" +#include "utility/EthernetClientStream.h" #ifdef _YUN_CLIENT_H_ YunClient client; diff --git a/release.sh b/release.sh index 9d5cc146..00db3cb6 100644 --- a/release.sh +++ b/release.sh @@ -6,6 +6,7 @@ mkdir -p temp/Firmata cp -r examples temp/Firmata cp -r extras temp/Firmata +cp -r utility temp/Firmata cp Boards.h temp/Firmata cp Firmata.cpp temp/Firmata cp Firmata.h temp/Firmata @@ -25,6 +26,7 @@ mkdir src mv Boards.h ./src/ mv Firmata.cpp ./src/ mv Firmata.h ./src/ +mv utility ./src/ cd .. find . -name "*.DS_Store" -type f -delete zip -r Firmata.zip ./Firmata/ diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.cpp b/utility/EthernetClientStream.cpp similarity index 97% rename from examples/StandardFirmataEthernet/EthernetClientStream.cpp rename to utility/EthernetClientStream.cpp index 74344096..81ccf839 100644 --- a/examples/StandardFirmataEthernet/EthernetClientStream.cpp +++ b/utility/EthernetClientStream.cpp @@ -20,8 +20,8 @@ #include "EthernetClientStream.h" #include -//#define DEBUG -#include "debug.h" +//#define SERIAL_DEBUG +#include "firmataDebug.h" #define MILLIS_RECONNECT 5000 diff --git a/examples/StandardFirmataEthernet/EthernetClientStream.h b/utility/EthernetClientStream.h similarity index 100% rename from examples/StandardFirmataEthernet/EthernetClientStream.h rename to utility/EthernetClientStream.h diff --git a/examples/StandardFirmataEthernet/debug.h b/utility/firmataDebug.h similarity index 72% rename from examples/StandardFirmataEthernet/debug.h rename to utility/firmataDebug.h index d894c9f7..6e364b0c 100644 --- a/examples/StandardFirmataEthernet/debug.h +++ b/utility/firmataDebug.h @@ -1,7 +1,7 @@ -#ifndef DEBUG_H -#define DEBUG_H +#ifndef FIRMATA_DEBUG_H +#define FIRMATA_DEBUG_H -#ifdef DEBUG +#ifdef SERIAL_DEBUG #define DEBUG_BEGIN(baud) Serial.begin(baud); while(!Serial) {;} #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINT(x) Serial.print (x) @@ -11,4 +11,4 @@ #define DEBUG_PRINT(x) #endif -#endif /* DEBUG_H */ +#endif /* FIRMATA_DEBUG_H */ From e2cede35460333ed97c27f271dadbf7349b11c0e Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 22:43:15 -0700 Subject: [PATCH 11/12] brought StandardFirmataYun up to date with StandardFirmata and added explanation of sketch purpose --- examples/StandardFirmata/StandardFirmata.ino | 1 - .../StandardFirmataYun/StandardFirmataYun.ino | 161 +++++++++--------- 2 files changed, 82 insertions(+), 80 deletions(-) diff --git a/examples/StandardFirmata/StandardFirmata.ino b/examples/StandardFirmata/StandardFirmata.ino index bc044dcd..9dfb8c4f 100644 --- a/examples/StandardFirmata/StandardFirmata.ino +++ b/examples/StandardFirmata/StandardFirmata.ino @@ -27,7 +27,6 @@ #include #include -// move the following defines to Firmata.h? #define I2C_WRITE B00000000 #define I2C_READ B00001000 #define I2C_READ_CONTINUOUSLY B00010000 diff --git a/examples/StandardFirmataYun/StandardFirmataYun.ino b/examples/StandardFirmataYun/StandardFirmataYun.ino index b2e671f0..9391fb93 100644 --- a/examples/StandardFirmataYun/StandardFirmataYun.ino +++ b/examples/StandardFirmataYun/StandardFirmataYun.ino @@ -1,15 +1,13 @@ /* - * Firmata is a generic protocol for communicating with microcontrollers - * from software on a host computer. It is intended to work with - * any host computer software package. - * - * To download a host software package, please clink on the following link - * to open the download page in your default browser. - * - * http://firmata.org/wiki/Download - */ + Firmata is a generic protocol for communicating with microcontrollers + from software on a host computer. It is intended to work with + any host computer software package. + + To download a host software package, please clink on the following link + to open the download page in your default browser. + + https://github.com/firmata/arduino#firmata-client-libraries -/* Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. @@ -23,29 +21,36 @@ See file LICENSE.txt for further informations on licensing terms. - formatted using the GNU C formatting and indenting + Last updated by Jeff Hoefs: April 11, 2015 */ /* - * TODO: use Program Control to load stored profiles from EEPROM - */ + README + + The Arduino Yun has both an Arduino (Atmega32u4) environment and a + Linux (Linino) environment. + + StandardFirmataYun enables Firmata running on the Arduino environment + to communicate with a Firmata client application running on the Linux + environment. +*/ #include #include #include -// move the following defines to Firmata.h? -#define I2C_WRITE B00000000 -#define I2C_READ B00001000 -#define I2C_READ_CONTINUOUSLY B00010000 -#define I2C_STOP_READING B00011000 -#define I2C_READ_WRITE_MODE_MASK B00011000 +#define I2C_WRITE B00000000 +#define I2C_READ B00001000 +#define I2C_READ_CONTINUOUSLY B00010000 +#define I2C_STOP_READING B00011000 +#define I2C_READ_WRITE_MODE_MASK B00011000 #define I2C_10BIT_ADDRESS_MODE_MASK B00100000 +#define MAX_QUERIES 8 +#define REGISTER_NOT_SPECIFIED -1 -#define MAX_QUERIES 8 +// the minimum interval for sampling analog input #define MINIMUM_SAMPLING_INTERVAL 10 -#define REGISTER_NOT_SPECIFIED -1 /*============================================================================== * GLOBAL VARIABLES @@ -66,7 +71,7 @@ int pinState[TOTAL_PINS]; // any value that has been written /* timer variables */ unsigned long currentMillis; // store the current value from millis() unsigned long previousMillis; // for comparison with currentMillis -unsigned int samplingInterval = 19; // how often to run the main loop (in ms) +unsigned int samplingInterval = 19; // how often to run the main loop (in ms) /* i2c data */ struct i2c_device_info { @@ -78,12 +83,11 @@ struct i2c_device_info { /* for i2c read continuous more */ i2c_device_info query[MAX_QUERIES]; -boolean isResetting = false; - byte i2cRxData[32]; boolean isI2CEnabled = false; signed char queryIndex = -1; -unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom() +// default delay time between i2c read request and Wire.requestFrom() +unsigned int i2cReadDelayTime = 0; Servo servos[MAX_SERVOS]; byte servoPinMap[TOTAL_PINS]; @@ -91,6 +95,26 @@ byte detachedServos[MAX_SERVOS]; byte detachedServoCount = 0; byte servoCount = 0; +boolean isResetting = false; + +/* utility functions */ +void wireWrite(byte data) +{ +#if ARDUINO >= 100 + Wire.write((byte)data); +#else + Wire.send(data); +#endif +} + +byte wireRead(void) +{ +#if ARDUINO >= 100 + return Wire.read(); +#else + return Wire.receive(); +#endif +} /*============================================================================== * FUNCTIONS @@ -103,19 +127,16 @@ void attachServo(byte pin, int minPulse, int maxPulse) if (detachedServoCount > 0) { servoPinMap[pin] = detachedServos[detachedServoCount - 1]; if (detachedServoCount > 0) detachedServoCount--; - } - else { + } else { servoPinMap[pin] = servoCount; servoCount++; } if (minPulse > 0 && maxPulse > 0) { servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse); - } - else { + } else { servos[servoPinMap[pin]].attach(PIN_TO_DIGITAL(pin)); } - } - else { + } else { Firmata.sendString("Max servos attached"); } } @@ -127,8 +148,7 @@ void detachServo(byte pin) // otherwise store the index of the detached servo if (servoPinMap[pin] == servoCount && servoCount > 0) { servoCount--; - } - else if (servoCount > 0) { + } else if (servoCount > 0) { // keep track of detached servos because we want to reuse their indexes // before incrementing the count of attached servos detachedServoCount++; @@ -144,19 +164,14 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // do not always require the register read so upon interrupt you call Wire.requestFrom() if (theRegister != REGISTER_NOT_SPECIFIED) { Wire.beginTransmission(address); -#if ARDUINO >= 100 - Wire.write((byte)theRegister); -#else - Wire.send((byte)theRegister); -#endif + wireWrite((byte)theRegister); Wire.endTransmission(); // do not set a value of 0 if (i2cReadDelayTime > 0) { // delay is necessary for some devices such as WiiNunchuck delayMicroseconds(i2cReadDelayTime); } - } - else { + } else { theRegister = 0; // fill the register with a dummy value } @@ -164,21 +179,16 @@ void readAndReportData(byte address, int theRegister, byte numBytes) { // check to be sure correct number of bytes were returned by slave if (numBytes < Wire.available()) { - Firmata.sendString("I2C Read Error: Too many bytes received"); - } - else if (numBytes > Wire.available()) { - Firmata.sendString("I2C Read Error: Too few bytes received"); + Firmata.sendString("I2C: Too many bytes received"); + } else if (numBytes > Wire.available()) { + Firmata.sendString("I2C: Too few bytes received"); } i2cRxData[0] = address; i2cRxData[1] = theRegister; for (int i = 0; i < numBytes && Wire.available(); i++) { -#if ARDUINO >= 100 - i2cRxData[2 + i] = Wire.read(); -#else - i2cRxData[2 + i] = Wire.receive(); -#endif + i2cRxData[2 + i] = wireRead(); } // send slave address, register and received bytes @@ -228,6 +238,9 @@ void checkDigitalInputs(void) */ void setPinModeCallback(byte pin, int mode) { + if (pinConfig[pin] == IGNORE) + return; + if (pinConfig[pin] == I2C && isI2CEnabled && mode != I2C) { // disable i2c so pins can be used for other functions // the following if statements should reconfigure the pins properly @@ -244,8 +257,7 @@ void setPinModeCallback(byte pin, int mode) if (IS_PIN_DIGITAL(pin)) { if (mode == INPUT) { portConfigInputs[pin / 8] |= (1 << (pin & 7)); - } - else { + } else { portConfigInputs[pin / 8] &= ~(1 << (pin & 7)); } } @@ -254,7 +266,7 @@ void setPinModeCallback(byte pin, int mode) case ANALOG: if (IS_PIN_ANALOG(pin)) { if (IS_PIN_DIGITAL(pin)) { - pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups } pinConfig[pin] = ANALOG; @@ -262,7 +274,7 @@ void setPinModeCallback(byte pin, int mode) break; case INPUT: if (IS_PIN_DIGITAL(pin)) { - pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver + pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups pinConfig[pin] = INPUT; } @@ -417,11 +429,7 @@ void sysexCallback(byte command, byte argc, byte *argv) Wire.beginTransmission(slaveAddress); for (byte i = 2; i < argc; i += 2) { data = argv[i] + (argv[i + 1] << 7); -#if ARDUINO >= 100 - Wire.write(data); -#else - Wire.send(data); -#endif + wireWrite(data); } Wire.endTransmission(); delayMicroseconds(70); @@ -466,8 +474,7 @@ void sysexCallback(byte command, byte argc, byte *argv) // read continuous reporting for that device if (queryIndex <= 0) { queryIndex = -1; - } - else { + } else { // if read continuous mode is enabled for multiple devices, // determine which device to stop reading and remove it's data from // the array, shifiting other array data to fill the space @@ -526,8 +533,7 @@ void sysexCallback(byte command, byte argc, byte *argv) if (samplingInterval < MINIMUM_SAMPLING_INTERVAL) { samplingInterval = MINIMUM_SAMPLING_INTERVAL; } - } - else { + } else { //Firmata.sendString("Not enough data"); } break; @@ -551,11 +557,11 @@ void sysexCallback(byte command, byte argc, byte *argv) } if (IS_PIN_ANALOG(pin)) { Firmata.write(ANALOG); - Firmata.write(10); + Firmata.write(10); // 10 = 10-bit resolution } if (IS_PIN_PWM(pin)) { Firmata.write(PWM); - Firmata.write(8); + Firmata.write(8); // 8 = 8-bit resolution } if (IS_PIN_DIGITAL(pin)) { Firmata.write(SERVO); @@ -563,7 +569,7 @@ void sysexCallback(byte command, byte argc, byte *argv) } if (IS_PIN_I2C(pin)) { Firmata.write(I2C); - Firmata.write(1); // to do: determine appropriate value + Firmata.write(1); // TODO: could assign a number to map to SCL or SDA } Firmata.write(127); } @@ -609,7 +615,6 @@ void enableI2CPins() isI2CEnabled = true; - // is there enough time before the first I2C request to call this here? Wire.begin(); } @@ -627,14 +632,16 @@ void disableI2CPins() { void systemResetCallback() { isResetting = true; + // initialize a defalt state // TODO: option to load config from EEPROM instead of default + if (isI2CEnabled) { disableI2CPins(); } for (byte i = 0; i < TOTAL_PORTS; i++) { - reportPINs[i] = false; // by default, reporting off + reportPINs[i] = false; // by default, reporting off portConfigInputs[i] = 0; // until activated previousPINs[i] = 0; } @@ -645,8 +652,7 @@ void systemResetCallback() if (IS_PIN_ANALOG(i)) { // turns off pullup, configures everything setPinModeCallback(i, ANALOG); - } - else { + } else { // sets the output to 0, configures portConfigInputs setPinModeCallback(i, OUTPUT); } @@ -663,11 +669,11 @@ void systemResetCallback() * since once in the loop(), this firmware will only send on change */ /* TODO: this can never execute, since no pins default to digital input - but it will be needed when/if we support EEPROM stored config - for (byte i=0; i < TOTAL_PORTS; i++) { - outputPort(i, readPort(i, portConfigInputs[i]), true); - } - */ + but it will be needed when/if we support EEPROM stored config + for (byte i=0; i < TOTAL_PORTS; i++) { + outputPort(i, readPort(i, portConfigInputs[i]), true); + } + */ isResetting = false; } @@ -710,14 +716,12 @@ void loop() * FTDI buffer using Serial.print() */ checkDigitalInputs(); - /* SERIALREAD - processing incoming messagse as soon as possible, while still + /* STREAMREAD - processing incoming messagse as soon as possible, while still * checking digital inputs. */ while (Firmata.available()) Firmata.processInput(); - /* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over - * 60 bytes. use a timer to sending an event character every 4 ms to - * trigger the buffer to dump. */ + // TODO - ensure that Stream buffer doesn't go over 60 bytes currentMillis = millis(); if (currentMillis - previousMillis > samplingInterval) { @@ -739,4 +743,3 @@ void loop() } } } - From 45345701da6bae45b2da7eca20658ef25a705382 Mon Sep 17 00:00:00 2001 From: Jeff Hoefs Date: Sat, 11 Apr 2015 23:03:31 -0700 Subject: [PATCH 12/12] bump version. update readme and revisions log --- Firmata.cpp | 2 +- Firmata.h | 4 ++-- extras/revisions.txt | 10 ++++++++++ library.properties | 2 +- readme.md | 18 +++++++++--------- release.sh | 4 ++-- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Firmata.cpp b/Firmata.cpp index 99d04f4a..20cee89a 100644 --- a/Firmata.cpp +++ b/Firmata.cpp @@ -1,5 +1,5 @@ /* - Firmata.cpp - Firmata library v2.4.2 - 2015-3-16 + Firmata.cpp - Firmata library v2.4.3 - 2015-4-11 Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. This library is free software; you can redistribute it and/or diff --git a/Firmata.h b/Firmata.h index e286b3c6..9c788e13 100644 --- a/Firmata.h +++ b/Firmata.h @@ -1,5 +1,5 @@ /* - Firmata.h - Firmata library v2.4.2 - 2015-3-16 + Firmata.h - Firmata library v2.4.3 - 2015-4-11 Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. This library is free software; you can redistribute it and/or @@ -21,7 +21,7 @@ * installed firmware. */ #define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes #define FIRMATA_MINOR_VERSION 4 // for backwards compatible changes -#define FIRMATA_BUGFIX_VERSION 2 // for bugfix releases +#define FIRMATA_BUGFIX_VERSION 3 // for bugfix releases #define MAX_DATA_BYTES 64 // max number of data bytes in incoming messages diff --git a/extras/revisions.txt b/extras/revisions.txt index 66f77da3..9a933d24 100644 --- a/extras/revisions.txt +++ b/extras/revisions.txt @@ -1,3 +1,13 @@ +FIRMATA 2.4.3 - Apr 11, 2015 + +[core library] +* Added debug macros (utility/firmataDebug.h) +* Added Norbert Truchsess' EthernetClientStream lib from the configurable branch + +[examples] +* Added StandardFirmataEthernet to enable Firmata over Ethernet +* Minor updates to StandardFirmata and StandardFirmataYun + FIRMATA 2.4.2 - Mar 16, 2015 [core library] diff --git a/library.properties b/library.properties index d9205c12..fd9eea05 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Firmata -version=2.4.2 +version=2.4.3 author=Firmata Developers maintainer=https://github.com/firmata/arduino sentence=Enables the communication with computer apps using a standard serial protocol. For all Arduino boards. diff --git a/readme.md b/readme.md index a7388662..22e0c171 100644 --- a/readme.md +++ b/readme.md @@ -58,7 +58,7 @@ Most of the time you will be interacting with arduino with a client library on t Note: The above libraries may support various versions of the Firmata protocol and therefore may not support all features of the latest Firmata spec nor all arduino and arduino-compatible boards. Refer to the respective projects for details. ##Updating Firmata in the Arduino IDE -The version of firmata in the Arduino IDE contains an outdated version of Firmata. To update Firmata, download the latest [release](https://github.com/firmata/arduino/releases/tag/v2.4.2) (for Arduino 1.0.x or Arduino 1.5.6 or higher) and replace the existing Firmata folder in your Arduino application. See the instructions below for your platform. +The version of firmata in the Arduino IDE contains an outdated version of Firmata. To update Firmata, download the latest [release](https://github.com/firmata/arduino/releases/tag/v2.4.3) (for Arduino 1.0.x or Arduino 1.5.6 or higher) and replace the existing Firmata folder in your Arduino application. See the instructions below for your platform. *Note that Arduino 1.5.0 - 1.5.5 are not supported. Please use Arduino 1.5.6 or higher (or Arduino 1.0.5 or 1.0.6).* @@ -69,8 +69,8 @@ The Firmata library is contained within the Arduino package. 1. Navigate to the Arduino application 2. Right click on the application icon and select `Show Package Contents` 3. Navigate to: `/Contents/Resources/Java/libraries/` and replace the existing -`Firmata` folder with latest [Firmata release](https://github.com/firmata/arduino/releases/tag/v2.4.2) (note there is a different download -for Arduino 1.0.x vs 1.5.x) +`Firmata` folder with latest [Firmata release](https://github.com/firmata/arduino/releases/tag/v2.4.3) (note there is a different download +for Arduino 1.0.x vs 1.6.x) 4. Restart the Arduino application and the latest version of Firmata will be available. If you are using the Java 7 version of Arduino 1.5.7 or higher, the file path @@ -79,8 +79,8 @@ will differ slightly: `Contents/Java/libraries/Firmata` (no Resources directory) ###Windows: 1. Navigate to `c:/Program\ Files/arduino-1.x/libraries/` and replace the existing -`Firmata` folder with the latest [Firmata release](https://github.com/firmata/arduino/releases/tag/v2.4.2) (note there is a different download -for Arduino 1.0.x vs 1.5.x). +`Firmata` folder with the latest [Firmata release](https://github.com/firmata/arduino/releases/tag/v2.4.3) (note there is a different download +for Arduino 1.0.x vs 1.6.x). 2. Restart the Arduino application and the latest version of Firmata will be available. *Update the path and arduino version as necessary* @@ -88,8 +88,8 @@ for Arduino 1.0.x vs 1.5.x). ###Linux: 1. Navigate to `~/arduino-1.x/libraries/` and replace the existing -`Firmata` folder with the latest [Firmata release](https://github.com/firmata/arduino/releases/tag/v2.4.2) (note there is a different download -for Arduino 1.0.x vs 1.5.x). +`Firmata` folder with the latest [Firmata release](https://github.com/firmata/arduino/releases/tag/v2.4.3) (note there is a different download +for Arduino 1.0.x vs 1.6.x). 2. Restart the Arduino application and the latest version of Firmata will be available. *Update the path and arduino version as necessary* @@ -97,7 +97,7 @@ for Arduino 1.0.x vs 1.5.x). ###Using the Source code rather than release archive Clone this repo directly into the core Arduino libraries directory. If you are using -Arduino 1.5.x, the repo directory structure will not match the Arduino +Arduino 1.5.x or 1.6.x, the repo directory structure will not match the Arduino library format, however it should still compile as long as you are using Arduino 1.5.7 or higher. @@ -111,7 +111,7 @@ $ git clone git@github.com:firmata/arduino.git /Applications/Arduino.app/Content *Update paths if you're using Windows or Linux* -To generate properly formatted versions of Firmata (for Arduino 1.0.x and Arduino 1.5.x), run the +To generate properly formatted versions of Firmata (for Arduino 1.0.x and Arduino 1.6.x), run the `release.sh` script. diff --git a/release.sh b/release.sh index 00db3cb6..49c43802 100644 --- a/release.sh +++ b/release.sh @@ -16,7 +16,7 @@ cd temp find . -name "*.DS_Store" -type f -delete zip -r Firmata.zip ./Firmata/ cd .. -mv ./temp/Firmata.zip Firmata-2.4.2.zip +mv ./temp/Firmata.zip Firmata-2.4.3.zip #package for Arduino 1.6.x cp library.properties temp/Firmata @@ -31,5 +31,5 @@ cd .. find . -name "*.DS_Store" -type f -delete zip -r Firmata.zip ./Firmata/ cd .. -mv ./temp/Firmata.zip Arduino-1.6.x-Firmata-2.4.2.zip +mv ./temp/Firmata.zip Arduino-1.6.x-Firmata-2.4.3.zip rm -r ./temp