Skip to content

initial implementation of analog config protocol #143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
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
1 change: 1 addition & 0 deletions Firmata.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#define I2C_REQUEST 0x76 // send an I2C read/write request
#define I2C_REPLY 0x77 // a reply to an I2C read request
#define I2C_CONFIG 0x78 // config I2C settings such as delay times and power pins
#define ANALOG_CONFIG 0x7C // configure analog read and write resolution and reference voltage
#define EXTENDED_ANALOG 0x6F // analog write (PWM, Servo, etc) to any pin
#define PIN_STATE_QUERY 0x6D // ask for a pin's current mode and value
#define PIN_STATE_RESPONSE 0x6E // reply with pin's current mode and value
Expand Down
80 changes: 78 additions & 2 deletions examples/StandardFirmata/StandardFirmata.ino
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ boolean isI2CEnabled = false;
signed char queryIndex = -1;
unsigned int i2cReadDelayTime = 0; // default delay time between i2c read request and Wire.requestFrom()

byte analogReadRes = 10; // default - better to define in Boards.h?
byte analogWriteRes = 8; // default - better to define in Boards.h?
byte analogReferenceVoltage = DEFAULT; // defined in Arduio core for AVRs only

Servo servos[MAX_SERVOS];
/*==============================================================================
* FUNCTIONS
Expand Down Expand Up @@ -448,6 +452,78 @@ void sysexCallback(byte command, byte argc, byte *argv)
//Firmata.sendString("Not enough data");
}
break;
case ANALOG_CONFIG:
if (argc > 1) {
switch (argv[0]) {
case 0: // set analog reference voltage
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SAM-based variants would need to skip this entire case.

// currently analogReference is only definved for AVR boards
// see: http://arduino.cc/en/Reference/AnalogReference
switch (argv[1]) {
// note that the following 5 case values do not equal the actual
// value of the corresponding constant. The constant value may change
// by board type (Mega vs Uno, etc)
case 0: // DEFAULT (5v on 5v boards, 3.3v on 3.3v boards)
analogReference(DEFAULT);
analogReferenceVoltage = DEFAULT;
break;
#ifdef INTERNAL
case 1: // INTERNAL
analogReference(INTERNAL);
analogReferenceVoltage = INTERNAL;
break;
#endif
#ifdef INTERNAL1V1
case 2: // INTERNAL1V1
analogReference(INTERNAL1V1);
analogReferenceVoltage = INTERNAL1V1;
break;
#endif
#ifdef INTERNAL2V56
case 3: // INTERNAL_2V56
analogReference(INTERNAL2V56);
analogReferenceVoltage = INTERNAL2V56;
break;
#endif
case 4: // EXTERNAL (0 to 5V applied to AREF pin)
analogReference(EXTERNAL);
analogReferenceVoltage = EXTERNAL;
break;
}

break;
case 1: // query analog reference voltage
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that this has to be separate from the configuration query but I'm not sure how else to do it since adding a second value to analog read and analog write (pwm) for the respective values in the configuration query response would likely break existing Firmata client implementations (since currently the response is pinType: value for each pin type).

Firmata.write(START_SYSEX);
Firmata.write(ANALOG_CONFIG);
Firmata.write(1); // analog reference response
Firmata.write(analogReferenceVoltage);
Firmata.write(END_SYSEX);
break;
#if ARDUINO >= 150
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would really need to determine not only if the version is 1.5 or higher, but whether or not the board is a SAM or AVR architecture. AVR boards don't include the analogReadResolution and analogWriteResolution methods.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After looking into this further I've determined that I could use the existing constants ARDUINO_ARCH_AVR and ARDUINO_ARCH_SAM. However that would likely leave out compatible 3rd party boards such as Teensy.

// to do: need to exclude AVRs
// only available for SAM core boards
// not available for all boards, but will safely default to proper
// resolution for unsupported boards
case 2: // set analog read resolution (defaults to 10 bits for AVR boards)
if (argv[1] > 0 && argv[1] < 33) {
// see: http://arduino.cc/en/Reference/analogReadResolution
// values above the boards capability are truncated
// values below the min supported resolution will be zero padded
analogReadResolution(argv[1]);
analogReadRes = argv[1];
}
break;
case 3: // set analog write (pwm) resolution (defaults to 8 bits for AVR boards)
if (argv[1] > 0 && argv[1] < 33) {
// see: http://arduino.cc/en/Reference/analogWriteResolution
// values above the boards capability are truncated
// values below the min supported resolution will be zero padded
analogWriteResolution(argv[1]);
analogWriteRes = argv[1];
}
break;
#endif
}
}
case EXTENDED_ANALOG:
if (argc > 1) {
int val = argv[1];
Expand All @@ -468,11 +544,11 @@ void sysexCallback(byte command, byte argc, byte *argv)
}
if (IS_PIN_ANALOG(pin)) {
Firmata.write(ANALOG);
Firmata.write(10);
Firmata.write(analogReadRes);
}
if (IS_PIN_PWM(pin)) {
Firmata.write(PWM);
Firmata.write(8);
Firmata.write(analogWriteRes);
}
if (IS_PIN_SERVO(pin)) {
Firmata.write(SERVO);
Expand Down