Integration of ROS and Arduino

ROS has good messaging system that uses publisher/subscriber model. My project requires an Arduino to talk to a ROS network. Rosserial for Arduino exists to enable such communication. My previous attempt to use rosserial on Atmega168 was not successful due to 1 kilobyte SRAM limit on the Atmega. This time, I will use Atmega2560 with 8 kilobytes of SRAM.

The goal of this post is to go through a set-up procedure of a ROS package in order to build and install AVR firmware.
I also describe a couple of problems and solutions that I came across during the procedure.

ROS packages are built with catkin build system which lets me

Use a unified system for development of ROS software and Arduino firmware

Avoid using a graphical user interface such as Arduino IDE, but do all of my development in vim editor

I plan to use ROS on a Raspberry Pi as a controller. Since Raspberry Pi is short on resources, I chose to develop software on a desktop computer. Once the code is more or less in condition for testing on real hardware, I’ll sync the required build artifacts to the Raspberry Pi.

On YouTube

Procedure

At this point, ROS kinetic is already installed in Ubuntu 16.04 virtual box that runs on my mac. I ssh-ed into the VM, and ready to go.

First, I need to create a ROS workspace, which I named clawbot_ws.
The workspace needs to be re-created whenever I switch to a new dev box.

The environment has to be initialized every time I open a new shell. Often, I forget to do that, and then I waste my brain cycles to determine what’s wrong with the build. Therefore, I wrote a shell function and put it into ~/.bashrc so that it gets executed automatically whenever I open a new shell.

There is more stuff you can put into the function like I did here. For example, I change log directory to something I prefer. The function would take me directly to the source code via the command roscd clawbot. Of course, the package has to exist first. So,
now, I go ahead and create the package:

The tutorial in ROS wiki instructs to replace the content of CMakeLists.txt with their example. Instead, I will keep that auto-generated code for later modifications. For now, I just add or update the required macros:

Who is supposed to build that file? I know nothing about what it contains.

When I go back to the wiki and double-check the example, I see this:

1
2
3

...
SRCS chatter.cpp ${ROS_LIB_DIR}/time.cpp
...

The second file in SRCS is time.cpp! When writing CMakeLists.txt, I removed it because nothing in my source code was using it. After all, I didn’t have to build any other ROS files using my project’s CMakeLists.txt.

It seems like an oversight. Why the file couldn’t be built as part of a ROS library? Alternatively, all the code in time.cpp could be implemented in the header file time.h. Who knows?

In any case, once I include the file in my CMakeLists.txt, the build completes fine.

Let’s look at the firmware size and make sure we still have room for more code of ours:

The field Data indicates the amount of used up RAM at compile time, and it’s around 29%. We still have ~70% for the runtime. Although, it would be good to check the amount of SRAM used by the above hello-world program during the runtime.
There is still 96% of free space for the program code.

Now, I upload the firmware to the Arduino:

1

$ catkin_make VERBOSE=1 -j4 clawbot_firmware_m2560-upload

Before I run the test, I need to add my user account to dialout group so that I’m allowed to access the USB device. I also restart the VM (logging out and back in would also work):

1
2

$ sudo usermod -a-G dialout sergey
$ sudo init 6

Also, since my $ROS_LOG_DIR points to /var/log/ros directory, I create it and change permissions like so:

1
2

$ sudo mkdir /var/log/ros
$ sudo chmod a+w /var/log/ros

Now, open three console windows.

In console 1, I start the ROS core

1

$ roscore

In console 2, I start a rosserial node to listen for messages from the Arduino:

1

$ rosrun rosserial_python serial_node.py /dev/ttyACM0

In console 3, I print the received messages

1

$ rostopic echo chatter

My console 3 shows this:

1
2
3
4
5
6

data: hello world!
---
data: hello world!
---
data: hello world!
---

At this point, the results look good enough to me to move forward with my project.

You may also like

Have you thought of how to filter the data coming from an analog sensor?
Why do you even want to filter that data? Should you use arithmetic mean or
median? Why can’t you just grab a sample from Arduino::analogRead() and be
done with it?

After spending your time on learning advanced “hello world” tutorial of some third-party
library, and trying to code something more useful, you hit your first problem. Scavenging the
internet for help on seemingly simple issues burns more of your precious time with little
return. You think - there has to be a better way to move your project along.

After connecting an infrared sensor to my Arduino, I noticed that an ultrasonic sensor, which is connected to the same board, started reporting inconsistent measurements. The investigation took me a few hours, but now I know better to pay attention to the power requirements for electronic components.