firmata / firmata.js

JavaScript implementation of the Firmata protocol
711 stars 147 forks source link

Timeout to first write #121

Closed ericogr closed 8 years ago

ericogr commented 8 years ago

Sometimes, after open and before ready, the board does not respond to command queryCapabilities (settings.skipCapabilities is false). Adding a timeout before execute any write can prevent this issue. I don't know the exact time but PyMata3 uses 2 seconds (by default) after connected.

I created a new option firstWriteTimeout to control timeout (default is 2000ms)

soundanalogous commented 8 years ago

There was a change to node-serialport recently that prevents a hard reset of the board when the serial connection is established. If you are using the very latest version of node-serialport I wonder if that is the reason you are needing to add these timeouts. Can you verify which version you are using?

@reconbot FYI

reconbot commented 8 years ago

There sure wasn't an intentional change. It's still resetting my uno on connection, but I think it deserves some attention. Not sending the hup would be a regression.

soundanalogous commented 8 years ago

Also, as an experiment try StandardFirmataPlus rather than StandardFirmata. Make sure you have at least Firmata v2.5.2 before you try this. StandardFirmataPlus removes the version blink sequence which makes startup over 2 seconds faster. I'm curious if this makes any difference.

ericogr commented 8 years ago

with serialport 2.0.6

with serialport 2.1.0

Using Firmata (standard/plus) 2.5.2 and arduino mega

ericogr commented 8 years ago

More details:

1460980402555 'open' 1460980402557 Buffer f9 02 05 f0 79 02 00 75 00 73 00 2e 00 69 00 6e 00 6f 00 f7 1460980402558 'queryCapabilities' (but arduino still writing) 1460980403464 Buffer f9 02 05 f0 79 02 05 53 00 74 00 61 00 6e 00 64 00 61 00 72 00 1460980403469 Buffer 64 00 46 00 69 00 72 00 6d 00 61 00 74 00 61 00 50 00 6c 00 75 00 73 00 1460980403473 Buffer 2e 00 69 00 6e 00 6f 00 f7

...
this.queryCapabilities(function() { //>>> executed but arduino still writing "dirty data" (arduino ignored)
  this.queryAnalogMapping(ready); //>>> never executed (firmata hangs)
});
...

StandardFirmataPlus 2.5.2 serialport 2.1.0 firmata.js 0.11.3

soundanalogous commented 8 years ago

What this data shows is on boot (of the Arduino) it sends REPORT_VERSION (0xF9) followed by REPORT_FIRMWARE (0xF0, 0x79... 0xF7). However REPORT_FIRMWARE is ended abruptly (the 0xF7) which is really strange and may indicate an error on the Arduino on startup - maybe junk in the buffer. Then queryCapabilities is sent by the host application. Prior to queryCapabilities, a request for the version and firmware is sent by Firmata.js. This time the full REPORT_VERSION and REPORT_FIRWARE messages are received. However this should not block the capability query response at least not in the firmware since that is synchronous and the commands sent to the Arduino are relatively small so they are likely not overrunning the 64 byte input buffer. However this makes me wonder if the node-serialport input buffer is being overrun due to the high number of bytes returned in quick succession from the board - this being the firmware name at 2 bytes per character immediately followed by the capability response which is huge for a Mega due to the number of pins.

I'll look into this tonight on a mega.

ericogr commented 8 years ago

Yes, maybe junk in the buffer. After REPORT_FIRMWARE is ended abruptly, capability query is written but before the normal REPORT_FIRMWARE. So, I think the arduino ignores capability query and firmata.js never emit ready event.

Works great with Arduino Leonardo (StandardFirmata and StandardFirmataPlus)

I'm using these simple scripts (with random sleep after each execution) to test: firmata.js test - arduino mega

(maybe you can use forever with random pauses after each execution too...)

Thanks!

soundanalogous commented 8 years ago

How old is your Arduino Mega? Can you find the revision number on the board? There has been a problem document in the past with the ATmega16U2 that is used on the Mega and other boards for the USB connection with the computer in containing junk in the buffer on startup. This used to be really bad for the Arduino Due but I have not observed this on a Mega yet. You wouldn't notice such behavior on a Leonardo since it has it's own USB.

ericogr commented 8 years ago

I think it's an old arduino. I bought in 2/10/2012 and there is no revision information on the board... it uses mega8u2

soundanalogous commented 8 years ago

I replicated your setup on both Mac OS X and on Ubuntu 14.04. The test runs successfully every time on OS X (ran it for 105 iterations). However on Linux it fails after the first run every time. This is strange indeed. The buffers really get scrambled on Linux. I wonder if it's an issue in node-serialport or in the way Linux handles serial data in general. Perhaps Linux uses a much smaller serial buffer than OS X under the hood.

ericogr commented 8 years ago

Maybe an issue with cdc_acm. I'll try a more recent version tonight

ericogr commented 8 years ago

Today I installed ubuntu 16.04 (laptop) and it works perfectly! unfortunately the problem persist on another desktop computer, even with 16.04. Seems to be an operating system/hardware issue, not directly related to firmata.js. Thanks for your help