Communicating with Arduino Uno from TK1 via Serial UART

Hi all,

I’ve been having some strange (but repeatably strange) issues trying to get my TK1 to talk to an Arduino Uno via a ROS node in C++ and was hoping someone might be able to guide me in the right direction.

Basically right now I have my Jetson running all sorts of stuff, and have an Uno hooked up to a motor driver to run a motor. I have a C++ ROS node running on the Jetson that pulls some values from a YAML file and basically writes a mode command to the Uno to tell it to perform some operation (in this case, run a motor at different speeds). The message is just a number followed by an asterisk (e.g., “3*”). Depending on the value sent to the Uno, the Uno either runs the motor, sends an encoder value back up to the Jetson, or both.

For some context, this call/response method of communicating with an Uno is something I’ve used for a long time, and have had very similar code working between a TK1 and an Arduino Due. Part of what I like about this is that I can easily test if the Arduino is working right by opening the Arduino Serial Monitor and writing the same message (e.g., “3*”) and see what it does while completely removing one end of the communications.

On to the strange issues: the bottom line is that the C++ & Arduino code work flawlessly on every possible permutation of systems I’ve tried EXCEPT for with the Jetson. The Arduino code runs fine when I test via the Serial Monitor. I have run the exact same C++ code on my laptop running 14.04 to talk to the Uno and it works flawlessly. However, when I try to run my ROS node on the TK1, the messages between the Jetson and the Uno turn to trash. A filestream to the Uno is opened up fine, and I can see via the Tx/Rx pins on the Uno that it is receiving messages. However, the Uno isn’t getting the right messages from the Jetson (or it’s not parsing them correctly, but this seems unlikely), and it isn’t sending anything back to the Jetson when it should. In an even stranger turn of events, if I run this ROS node while the Arduino Serial Monitor is open, the Uno receives the correct command from the node and does what it’s supposed to, and it sends the right message back up to the Jetson. However, the message back to the Jetson gets picked up by the Serial Monitor instead of the ROS node.

This strange turn of events where code works on my Ubuntu 14.04 laptop but not my Jetson is something I haven’t experienced before in working with UART communications. I have done a lot of work having my TK1 talk to a Due and I’ve always just developed on my laptop and downloaded the repo onto my Jetson and it worked out of the gate. For me, this is uncharted territory here.

As a note, I have recompiled my kernel using the instructions at http://elinux.org/Jetson/Tutorials/Program_An_Arduino, so driver incompatibility issues shouldn’t be a problem.

Anyway, I’m hoping someone might be able to point me in the right direction here - from what I understand, getting a Jetson to talk to an Uno should be simple, and should definitely be simpler than talking to a Due, so I don’t know what the heck I’m doing wrong.

I’m going to at least initially omit putting my code here, as others looking at it may have a similar effect as when the Nazis opened up the Ark of the Covenant in that Indiana Jones movie, but I can post my code upon request.

If the signal appears to be going out from Jetson to Uno, but acts strangely, the first thing I’d do is make sure noise is not an issue. Are lines all shielded and/or twisted pair? If an optional piece of hardware turns on and changes communications I’d again wonder about noise and also about any shared power supply or ground loop issue…see what you can do to be certain power is not taking part in any noise. You may want to add a serial protocol analyzer and see what it thinks, and if you’re getting your information via oscilloscope, be sure RX/TX line levels are actually where they should be (both sides should expect the same line levels). If you can use hardware flow control and are currently using only software flow control, switch to hardware flow control. If there is any WiFi, make sure you shield boards from antennas.

Finally got some time to look at this issue again today and just wanted to update the post. I have found a solution that has seemed to fix the problem completely, although I’m not entirely sure why it works. Figured I’d update this post in case anyone else in the future ever comes across similar issues.

In my c++ code I needed to add a pause between the call to open() and the call to tcgetattr(). I guess there is some time-consuming handshaking that needs to occur in that time. My new code looks like:

int fd = open("/dev/ArduinoUno", O_RDWR | O_NOCTTY | O_NDELAY); //open Due filestream
+  usleep(2000000);
   if (fd == -1) {
     ROS_ERROR("Unable to connect to /dev/ArduinoUno");
     return -1;
   }
   
   struct termios options;
   if (tcgetattr(fd, &options) < 0) {
     ROS_ERROR("Unable to attain attributes for filestream");
     return -2;
   }

and this seems to be working reliably. I find it odd that this sleep was not needed either when my Ubuntu laptop was running the same code, or when I have used the Jetson to talk to an Arduino Due. A further note is that I experimented with the sleep times and found that anything less than the 2 second sleep from above results in the code not working as described in the original post; 2 seconds seems to be the minimum for getting this to work reliably.

I would also like to state for the record that I hooked up an oscilloscope to the Tx/Rx lines and found that the messages sent from the Jetson to the Uno were exactly the same from Arduino Serial Monitor and from the node before I added the usleep() call, further cementing my belief that this was some sort of handshaking issue.

To summarize: this was not an issue with interference, voltage level, etc. It appears to be some sort of handshaking issue where a call to sleep()/usleep() between the calls to open() and tcgetattr() is needed. All is working now and I can work on more fun things :)