Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Firmata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,17 @@ void FirmataClass::sendDigitalPort(byte portNumber, int portData)
FirmataStream->write(portData >> 7); // Tx bits 7-13
}

// send an error code (0-127) to the client application
// the client application should provide a string message corresponding to the
// error code or otherwise handle the error as necessary
void FirmataClass::sendErrorCode(byte errorCode)
{
startSysex();
FirmataStream->write(ERROR_CODE);
FirmataStream->write(errorCode & 0x7F);
endSysex();
}


void FirmataClass::sendSysex(byte command, byte bytec, byte* bytev)
{
Expand All @@ -352,6 +363,7 @@ void FirmataClass::sendString(const char* string)
sendString(STRING_DATA, string);
}


// expose the write method
void FirmataClass::write(byte c)
{
Expand Down
2 changes: 2 additions & 0 deletions Firmata.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

// extended command set using sysex (0-127/0x00-0x7F)
/* 0x00-0x0F reserved for user-defined commands */
#define ERROR_CODE 0x68 // send an error code (0-127)
#define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq
#define STRING_DATA 0x71 // a string message with 14-bits per char
#define STEPPER_DATA 0x72 // control a stepper motor
Expand Down Expand Up @@ -111,6 +112,7 @@ class FirmataClass
void sendAnalog(byte pin, int value);
void sendDigital(byte pin, int value); // TODO implement this
void sendDigitalPort(byte portNumber, int portData);
void sendErrorCode(byte errorCode);
void sendString(const char* string);
void sendString(byte command, const char* string);
void sendSysex(byte command, byte bytec, byte* bytev);
Expand Down
35 changes: 23 additions & 12 deletions examples/StandardFirmata/StandardFirmata.ino
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include <Wire.h>
#include <Firmata.h>

// move the following defines to Firmata.h?
#define I2C_WRITE B00000000
#define I2C_READ B00001000
#define I2C_READ_CONTINUOUSLY B00010000
Expand All @@ -46,6 +45,15 @@

#define REGISTER_NOT_SPECIFIED -1

// error codes (see ERROR_CODE sysex message)
// in your client appliaction, add a lookup to the corresponding strings in the comments below
#define UNKNOWN_PIN_MODE 0 // "Unknown pin mode."
#define I2C_TOO_MANY_BYTES 1 // "I2C Read Error: Too many bytes received."
#define I2C_TOO_FEW_BYTES 2 // "I2C Read Error: Too few bytes received."
#define I2C_10BIT_ADDR 3 // "I2C Error: 10-bit addressing mode is not supported."
#define I2C_TOO_MANY_QUERIES 4 // "I2C Error: Too many queries."
#define SAMPINT_TOO_FEW_BYTES 5 // "Sampling Interval: Too few bytes received."

/*==============================================================================
* GLOBAL VARIABLES
*============================================================================*/
Expand Down Expand Up @@ -83,6 +91,7 @@ signed char queryIndex = -1;
unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom()

Servo servos[MAX_SERVOS];

/*==============================================================================
* FUNCTIONS
*============================================================================*/
Expand Down Expand Up @@ -124,9 +133,9 @@ void readAndReportData(byte address, int theRegister, byte numBytes) {
}
else {
if(numBytes > Wire.available()) {
Firmata.sendString("I2C: Too many bytes received");
Firmata.sendErrorCode(I2C_TOO_MANY_BYTES);
} else {
Firmata.sendString("I2C: Too few bytes received");
Firmata.sendErrorCode(I2C_TOO_FEW_BYTES);
}
}

Expand Down Expand Up @@ -243,7 +252,7 @@ void setPinModeCallback(byte pin, int mode)
}
break;
default:
Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
Firmata.sendErrorCode(UNKNOWN_PIN_MODE);
}
// TODO: save status to EEPROM here, if changed
}
Expand Down Expand Up @@ -337,7 +346,7 @@ void sysexCallback(byte command, byte argc, byte *argv)
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");
Firmata.sendErrorCode(I2C_10BIT_ADDR);
return;
}
else {
Expand Down Expand Up @@ -374,7 +383,7 @@ void sysexCallback(byte command, byte argc, byte *argv)
case I2C_READ_CONTINUOUSLY:
if ((queryIndex + 1) >= MAX_QUERIES) {
// too many queries, just ignore
Firmata.sendString("too many queries");
Firmata.sendErrorCode(I2C_TOO_MANY_QUERIES);
break;
}
queryIndex++;
Expand Down Expand Up @@ -433,8 +442,9 @@ void sysexCallback(byte command, byte argc, byte *argv)
int maxPulse = argv[3] + (argv[4] << 7);

if (IS_PIN_SERVO(pin)) {
if (servos[PIN_TO_SERVO(pin)].attached())
if (servos[PIN_TO_SERVO(pin)].attached()) {
servos[PIN_TO_SERVO(pin)].detach();
}
servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
setPinModeCallback(pin, SERVO);
}
Expand All @@ -447,7 +457,7 @@ void sysexCallback(byte command, byte argc, byte *argv)
samplingInterval = MINIMUM_SAMPLING_INTERVAL;
}
} else {
//Firmata.sendString("Not enough data");
Firmata.sendErrorCode(SAMPINT_TOO_FEW_BYTES);
}
break;
case EXTENDED_ANALOG:
Expand Down Expand Up @@ -496,9 +506,9 @@ void sysexCallback(byte command, byte argc, byte *argv)
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((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);
}
Expand Down Expand Up @@ -611,8 +621,9 @@ void loop()

/* SERIALREAD - processing incoming messagse as soon as possible, while still
* checking digital inputs. */
while(Firmata.available())
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
Expand Down