Secret to serial communication?

I'm trying to write a linux program to communicate with my arduino using a simple binary protocol, and I have become mystified by the fact that I can single step through the program and it works perfectly, but if I run at full speed, it never seems to talk correctly.

My sample test program sends a grand total of 2 bytes and expects to get back the awesome total of 4 bytes in reply, so I wouldn't think any buffers are getting filled up anywhere.

The problems only seem to happen when talking over USB to the /dev/ttyACM0 device.

If I switch to the bluetooth shield and talk to /dev/rfcomm0, the same test program always works perfectly.

Is there something I'm supposed to be setting via tcsetattr() or something for USB ports that I don't know about? (Maybe I should dig through the avrdude source and see how it opens the USB port...)

maybe post some code would give us insight about how the Arduino side works?

robtillaart:
maybe post some code would give us insight about how the Arduino side works?

Fortunately, I've just finished updating my web pages with the latest software descriptions:

http://home.comcast.net/~tomhorsley/hardware/arduino/software.html

I doubt there is any problem on the arduino side since it can't actually tell if it is talking to USB or bluetooth (just some jumpers are moved), and it works perfectly via bluetooth, so I expect the problem in the linux side, but I don't know what magic I might need to properly open the USB serial device.

Ah-HA! I don't need delays throughout the program, but I do need a big delay right after I open the /dev/ttyACM0 device and do the tcsetattr calls. Once I get past that with a big enough delay I can run full speed. Must be something in the linux ACM driver since I don't need any of the delays for talking to /dev/rfcomm0.

Or that the Arduino resets when you establish a serial link to it.
The delay just waits it out. :wink:

but I do need a big delay right after I open the /dev/ttyACM0 device

Because opening the port resets the Arduino and it takes a while for it to get up and running.


Rob

Well, that's annoying. You mean if I want to talk to this thing over USB, I have to hold the port open all the time or I'll reset it? Sure seems to be the case though. I changed my test to ask for the micros() value and send it back, and it is always about the same, so it sure looks like it is reset simply by opening the tty.

I wonder why avrdude has all sorts of code in it to diddle the RTS and DTR signals to do a reset? Maybe different hardware versions need that?

I guess it is just as well my long term plans are to use it over bluetooth :-).

The auto-reset is a good idea 98% of the time because it means you don't have to try and press the reset button at exactly the right moment every time you program the Arduino.

It does catch people doing what you are doing though.

The smart thing to have done with the design is put a jumper in so you can disable the feature at will, but Arduino tend not to think of such niceties. However many other people do and if you check out some of the clones they have fixed this issue.

You can also disable the reset feature by cutting a track, removing a cap, or adding a large cap, try searching the forum I'm sure there will be many threads about this with links to fixes.


Rob

I decided the thing to do is modify my microcode to send out a "I just got reset" message from setup(). Now when I open the device, I can send a bad command and wait and see if I get back an error message or a reset message. That let's me figure out when I can talk as soon as possible without putting in arbitrary large delays and works if I get reset (USB) or don't get reset (bluetooth). Should be handy for letting me know if the arduino got a power hit as well since I'll see a reset message when it comes up after that.

If I ever have any state I need saved, I'd better keep it in eeprom I guess.

In any case, this technique does seem to be working.

Another option you could do is to add a 10 microfarad capacitor to the reset pin to keep the arduino from rebooting (unless you press and hold the button). That way your data flow would be as it would be over Bluetooth.