ms-iot / remote-wiring

A remote "Arduino Wiring" interface to control an Arduino compatible device from a Windows 10 Universal Windows Application. NOTE: The projects for Windows 8.1 and Windows Phone 8.1 are no longer maintained, but have been left in place to facilitate makers using those platforms.
https://microsoft.hackster.io/windowsiot/basic-windows-remote-arduino
MIT License
196 stars 123 forks source link

Pin configuration not received #80

Closed EdgarSun closed 7 years ago

EdgarSun commented 8 years ago

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).

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.

(StandardFirmata version: 2.5)

ooeygui commented 8 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)

EdgarSun commented 8 years ago

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;
... ...
turkycat commented 8 years ago

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;
turkycat commented 8 years ago

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)?

EdgarSun commented 8 years ago

I wonder if you are using USB, Bluetooth, or networking to establish your connection?

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.

Have you validated your baud rate in StandardFirmata matches the value you are using above (115200)?

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();
turkycat commented 8 years ago

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);
EdgarSun commented 8 years ago

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:

img_5367

EdgarSun commented 8 years ago

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.

turkycat commented 8 years ago

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?

EdgarSun commented 8 years ago

@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.

piotrbalut commented 8 years ago

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 !

Adrian915 commented 8 years ago

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?

piotrbalut commented 8 years ago

I bought Arduino Uno and now everything works great...

Adrian915 commented 8 years ago

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 :\

Adrian915 commented 8 years ago

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.

mcinnes01 commented 8 years ago

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

mcinnes01 commented 8 years ago

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

mcinnes01 commented 8 years ago

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

mcinnes01 commented 8 years ago

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 */

include

include

include

define ULTRASONIC_DISTANCE_QUERY 0x42

define ULTRASONIC_DISTANCE_RESPONSE 0x43

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

// the minimum interval for sampling analog input

define MINIMUM_SAMPLING_INTERVAL 10

/*==============================================================================

/* 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) {

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

}

/*==============================================================================

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

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

}

/*==============================================================================

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

codehArt commented 8 years ago

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"

connection attempt failed : adevice connection was established, but the device failed handshaking procedures.

verify that your device is configured with standard firmata.

message: catastrophic failure

pin configuration not received.

while simple standard firmata is working fine on usb port . any one can help me regarding this issue.

carlosramajo commented 7 years ago

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

IoTGirl commented 7 years ago

Closing based on solution to verify pin connections

kulbhushanchand commented 5 years ago

@IoTGirl This issue should not be closed. The main issue is the failed handshaking with Arduino Mega and it still persists.