Closed EdgarSun closed 7 years ago
Thank you for reporting. We will set up the repro and see what's going on. (looks like the handshake process has changed)
Below are some codes for initializing the connections:
public const int CONN_BAUD = 115200;
... ...
...
DeviceStream.begin(CONN_BAUD, SerialConfig.SERIAL_8N1);
Firmata = new UwpFirmata();
Arduino = new RemoteDevice(Firmata);
Firmata.begin(DeviceStream);
Firmata.startListening();
Below are the sample codes for processing sysex command in arduino:
void sysexCallback(byte command, byte argc, byte *argv)
{
byte mode;
byte slaveAddress;
byte data;
int slaveRegister;
unsigned int delayTime;
switch (command) {
case ALL_PINS_COMMAND:
if( argc == 1 ) //verify we received the whole message
{
//the MSB is always sent in the LSB position 2nd byte
byte val;
if( argv[0] == 1 )
{
val = HIGH;
}
else
{
val = LOW;
}
//set the pins! On many Arduino devices (Uno, Leo, Yun, etc) there are 14 digital pins from 0 to 13.
for( byte i = 0; i < 14; ++i )
{
digitalWrite( i, val );
}
}
break;
... ...
The error you are getting actually isn't from the sysex functionality you're trying, it's from the handshaking procedure that occurs when the initial connection is established. I can confirm that in StandardFirmata
version 2.5 the author added a new pin mode which will break the current handshaking procedure. I am implementing a more foolproof fix for this now, but you can make a one line change to the file RemoteDevice.cpp
(or revert to using StandardFirmata
version 2.4.4 or 2.4.3).
In file RemoteDevice.cpp
line 522:
i += 4;
change to:
i += 6;
I've added the support for this new pin mode (and one other), but as I did so I realized that my original implementation allowed for additional data to be present without causing an error. This means that your handshaking failures are not due to the version change (I verified this). Therefore, I wonder if you are using USB, Bluetooth, or networking to establish your connection? Have you validated your baud rate in StandardFirmata matches the value you are using above (115200
)?
I am using bluetooth to establish connection between windows phone 8.1 and arduino.
Bluetooth Device: SparkFun Bluetooth Mate Silver.
And I test the connections on three different arduino board, all of them have the same error messages:
Arduino Failed: A device connection was established, but the device failed handshaking procedures. Verify that your device is configured with StandardFirmata. Message: Catastrophic failure
Pin configuration not received.
1) Arduino UNO 2) DFRobot Bluno v2.0 3) DFRobot Romeo v2.2 R3
And I tried to revert to firmata 2.4.4 and involved the changes (i += 6;) in RemoteDevice.cpp, but the error messages still exist.
Yes, I am using the same baud rate (115200) on both side
Below are the complete codes for setting up connections:
Arduino
Firmata.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Only needed for ATmega32u4-based boards (Leonardo, etc).
}
C#
var deviceStream = new BluetoothSerial(device); //device -> DeviceInformation
deviceStream.begin(115200, SerialConfig.SERIAL_8N1);
var firmata = new UwpFirmata();
var arduino = new RemoteDevice(firmata);
firmata.begin(DeviceStream);
firmata.startListening();
I've tested using your code & the same configuration and having no trouble. I also tested using Firmata 2.5 and the current (unchanged) version of WRA. The error means that despite getting a connecting to the Bluetooth Mate Silver, it doesn't seem like any of the data is being sent/received properly between the two devices, or what is being sent/received is not understood.
How are you connecting the Bluetooth Mate Silver to the Arduino?
Will you also try this? I've rearranged your function calls a bit. The library is written so that the way you are doing it shouldn't cause a problem (and it didn't for me), but if it does for you I'd like to know about it. I've moved the IStream begin
to be the last thing invoked, and I've removed startListening
. startListening
is automatically invoked by the RemoteDevice class when the device connection is established.
var deviceStream = new BluetoothSerial(device); //device -> DeviceInformation
var firmata = new UwpFirmata();
var arduino = new RemoteDevice(firmata);
firmata.begin(DeviceStream);
deviceStream.begin(CONN_BAUD, SerialConfig.SERIAL_8N1);
The events of deviceStream (IStream) were hooked up with handlers in my original codes, the handshaking issues was resolved and the "DeviceReady" event of arduino also was triggered successfully after removing below three event handlers.
deviceStream.ConnectionEstablished += DeviceStream_ConnectionEstablished;
deviceStream.ConnectionFailed += DeviceStream_ConnectionFailed;
deviceStream.ConnectionLost += DeviceStream_ConnectionLost;
Currently, I have another issue the LED will not be turned on/off when executing "sendSysex" function with below codes, it looks like the sysexCallback did not recevice command in arduino. Is there any way I can debug if the connection of firmata is available?
[CommandHandle]
public void ToggleLED()
{
byte ALL_PINS_COMMAND = 0x42;
//we're defining our own command, so we're free to encode it how we want.
//let's send a '1' if we want the pins HIGH, and a 0 for LOW
byte b;
if (_LEDState==false)
{
b = 1;
}
else
{
b = 0;
}
_LEDState = !_LEDState;
//invoke the sendSysex command with ALL_PINS_COMMAND and our data payload as an IBuffer
BluetoothHelper.Instance.FirstDevice.Firmata.sendSysex(ALL_PINS_COMMAND, new byte[] { b }.AsBuffer());
}
Below is a picture for demonstrating the device connections:
I made another test to see whether the sysexCallback was called properly with below temporary codes:
bool ledState=false;
void sysexCallback(byte command, byte argc, byte *argv)
{
byte mode;
byte slaveAddress;
byte data;
int slaveRegister;
unsigned int delayTime;
//-----------------------------------------------------
if(ledState){
digitalWrite( 13, LOW);
}
else{
digitalWrite( 13, HIGH);
}
ledState = !ledState;
//-----------------------------------------------------
switch (command) {
case ALL_PINS_COMMAND:**
... ...
The testing result is LED was lighted on when establishing the connection, it means "sysexCallback" was called at least one time. But when executing "sendSysex" to send command to arduino, there was nothing happened with the LED. I assume "sysexCallback" was no longer to response the Sysex command.
Hey @EdgarSun , I replied to your other issue thread on sendSysex
issues. I'll leave this issue open for now as our conversation continues, but I believe we are now discussing the same issue on both threads, correct?
@turkycat, Yes, you are right. the original issue of this thread has been resolved. my last reply is a same issue I reported in another thread Duplicate Issue. the only tiny difference is I was testing "sendSysex" with USB connection between raspberry pi 2 and arduino a few weeks ago. and I meet a same issue when testing with bluetooth connection between windows phone 8.1 and arduino.
I have Arduino Mega 2560 and still the same error:
Arduino Failed: A device connection was established, but the device failed handshaking procedures. Verify that your device is configured with StandardFirmata. Message: Catastrophic failure Pin configuration not received.
Configuration: Windows 10, connection via USB, baud rate set on 115200 (device drivers) Firmata 2.4.4 Repo cloned from this tutorial I tried all below configurations:
Serial1.begin(115200);
Firmata.begin(Serial1);
Firmata.begin(115200);
while (!Serial) {
/ ; // wait for serial port to connect. Only needed for ATmega32u4-based boards (Leonardo, etc).
}
Serial1.begin(115200); //or your baud rate here, it will be 115200 if using the Bluetooth Mate Silver or Gold
while( !Serial1 );
Firmata.begin( Serial1 );
Could you help me with this issue ? Thanks !
Hello. Same exact issue as pbalut above. Mega 2560 with standard firmata sketch. Pin configuration not received and it says it's failing the handshaking procedures.
Can somebody please help?
I bought Arduino Uno and now everything works great...
From what I can gather the Mega isn not replying back after the initial request. Either the sketch needs updating or the request is wrong.
I do not wish to switch to Uno :\
Coming back to this issue, I had a bit of time to debug it on the mega and partially solved the problem. From what I can tell, the mega has a lot more pins than the Uno and as such, takes a bit longer to count them all and build the capabilities. Thus, it would send a new request before giving the board time to complete the request which was sent before and never giving it time to actually respond.
In RemoteDevice.cpp, around line 497, I changed Sleep( delay_ms ); to Sleep( 1000 ); Obviosuly it is a temporary solution but at least it works.
Hi,
I am getting this same issue intermittently with the Arduino Nano cat feeder I've built. To test the connection I've tried using the remote Arduino experience app from either my laptop or phone (both win 10). The only way I've found to resolve the issue is to restart my device. Sometime this works straight away other times a couple of restarts fixes it. I've had it running reliably for about a week, but then it bombed out again. I'm running my own dhcp server from my physical server, but as I haven't setup a secondary dhcp server sometimes I get issues. I wonder if this issue could be related to a network problem?
I haven't tried the timeout idea but I can give that a go to try to rule that out.
Out of interest does the standard firmata ethernet image retry to connect if it fails for something like a dhcp issue?
Many thanks
Andy
Hi,
To add more to this, I am seeing this issue repeatedly now in a number of situations.
I've seen the problem intermittently with my cat feeder using a nano and W5100 ethernet module with standard firmata ethernet.
I've tried 4 different nanos, and a mega 2560 with 2 different bluetooth modules (HC-06), these never seem to connect and always result in the pin configuration not received error.
I've tested from my phone, tablet and laptop using both the remote arduino experience app and a custom remote blinky app.
I had noticed a few errors about the capabilities on the remote arduino experience, so I tried deploying the remote blinky app ensuring the bluetooth capability was selected.
All result in the same error.
I also tried this to no avail:
In file RemoteDevice.cpp line 522:
i += 4;
change to:
i += 6;
And I tried this:
In RemoteDevice.cpp, around line 497, I changed Sleep( delay_ms ); to Sleep( 1000 );
This last one creates the error:
Connection attempt timed out
I've also tried connecting with USB with standard firmata and standard firmata ethernet and neither will connect.
Can anyone help?
Cheers,
Andy
Hi
For anyone else experiencing this issue, I've increased the sampling interval and it seems to have resolved the problem with a nano using usb:
Line 67: unsigned int samplingInterval = 99;
Still getting the same error on bluetooth unfortunately. which I can't understand why?
I can see the arduino is doing stuff, but it never seems to manage to send the pin configuration through.
Andy
Hi,
Ok a little more investigating and I've got something working...
As I've said previously, I've got my cat feeder running on this with wifi, with all but the occasional disconnection that requires a manual reset. This is running an old version of standard firmata ethernet.
Using the arduino ide and its package manager I've removed and reinstalled the latest version of firmata: 2.5.2
With the and the standard or ethernet firmata example sketches, I get the problem described above.
However with the following sketch, it all runs fine. (This sketch is pretty standard but has a distance sensor sysex command added).
`/* 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-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.
Last updated by Jeff Hoefs: April 11, 2015 */
// the minimum interval for sampling analog input
/*==============================================================================
/* 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];
byte i2cRxData[32]; boolean isI2CEnabled = false; signed char queryIndex = -1; // default delay time between i2c read request and Wire.requestFrom() unsigned int i2cReadDelayTime = 0;
Servo servos[MAX_SERVOS]; byte servoPinMap[TOTAL_PINS]; byte detachedServos[MAX_SERVOS]; byte detachedServoCount = 0; byte servoCount = 0;
boolean isResetting = false;
/* utility functions */ void wireWrite(byte data) {
Wire.write((byte)data);
Wire.send(data);
}
byte wireRead(void) {
return Wire.read();
return Wire.receive();
}
/*==============================================================================
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); 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 { 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: 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++) {
i2cRxData[2 + i] = wireRead();
}
// 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; } }
/* -----------------------------------------------------------------------------
// ----------------------------------------------------------------------------- /* 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 }
int ultrasonicTriggerPin = 12; int ultrasonicEchoPin = 3;
/*==============================================================================
void sysexCallback(byte command, byte argc, byte *argv) { byte mode; byte slaveAddress; byte data; int slaveRegister; unsigned int delayTime; long duration; long distance; String distanceAsString;
switch (command) {
case ULTRASONIC_DISTANCE_QUERY:
pinMode(ultrasonicTriggerPin, OUTPUT);
digitalWrite(ultrasonicTriggerPin, LOW);
pinMode(ultrasonicEchoPin, INPUT);
while (true) {
digitalWrite(ultrasonicTriggerPin, LOW);
delayMicroseconds(2);
digitalWrite(ultrasonicTriggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(ultrasonicTriggerPin, LOW);
duration = pulseIn(ultrasonicEchoPin, HIGH);
distance = duration / 52.2;
distanceAsString = String(distance);
Firmata.sendString(distanceAsString.c_str());
delay(1000);
}
break;
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);
wireWrite(data);
}
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); // 10 = 10-bit resolution
}
if (IS_PIN_PWM(pin)) {
Firmata.write(PWM);
Firmata.write(8); // 8 = 8-bit resolution
}
if (IS_PIN_DIGITAL(pin)) {
Firmata.write(SERVO);
Firmata.write(14);
}
if (IS_PIN_I2C(pin)) {
Firmata.write(I2C);
Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
}
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;
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; }
/*==============================================================================
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() { 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);
Firmata.begin(9600);
systemResetCallback(); // reset to default config
}
/*==============================================================================
LOOP() ============================================================================/ void loop() { byte pin, analogPin;
/* DIGITALREAD - as fast as possible, check for changes and output them to the
/* STREAMREAD - processing incoming messagse as soon as possible, while still
// TODO - ensure that Stream buffer doesn't go over 60 bytes
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); } } } }`
The main thing I notice is the min sampling interval used to be 10, but this is now 1. Also the baud rate used to be 9600 and is now 57600.
Hope this helps someone else
Andy
hi, i am trying to implement simple standard firmata wifi between arduino mkr 1000 and windows remote arduino, but when i am trying to connect from windows remote arduino experience it is giving an "error"
while simple standard firmata is working fine on usb port . any one can help me regarding this issue.
Hi I had the same problem and I tried everything during hours, but finally I solved my problem. My problem was the most stupid problem in world, I had connected the bluetooth TX-TX, RX-RX instead of TX-RX, RX-TX. :-( TIP: check the connections, please don't be like me
Closing based on solution to verify pin connections
@IoTGirl This issue should not be closed. The main issue is the failed handshaking with Arduino Mega and it still persists.
Hi,
I am testing "sendSysex" function between windows phone 8.1 and arduino (with SparkFun Bluetooth Mate Silver). the connection can be established successfully, but I got below error message when executing "sendSysex" to turn on/off LED (https://github.com/ms-iot/remote-wiring/blob/develop/advanced.md).
(StandardFirmata version: 2.5)