Skip to content

Instantly share code, notes, and snippets.

@Redstone-RM
Last active September 12, 2024 02:50
Show Gist options
  • Save Redstone-RM/0ca459c32ec5ead8700284ff56a136f7 to your computer and use it in GitHub Desktop.
Save Redstone-RM/0ca459c32ec5ead8700284ff56a136f7 to your computer and use it in GitHub Desktop.
Getting PlatformIO to install micro-ROS on Arduino Nano RP2040 Connect

Arduino Nano RP2040 Connect and micro-ROS

Goals:

Step 1. To get the board working with PlatformIO in VSCode with the micro-ROS Arduino library installed.

Step 2. Flash an example micro-ROS publisher app to the hardware.

Gotcha. Noun. Meaning: A road bump that I ran into that you can keep in mind. YMMV

My Env #Ubuntu 20.04 #VSCode #PlatformIO #Arduino Nano RP2040 Connect #micro-ROS #Foxy installed on host or Docker container

  • Install the board support in your IDE.

    • Arduino IDE board manager > Install: Arduino #Mbed OS Nano Boards
    • Do the same in VsCode #PlatformIO Boards Menu
  • Run the script included with the Arduino IDE called post_install.sh ( sudo). This will fix the #udev rules that cause problems with the RP boot loader that prevents flashing the board from Arduino IDE. Copies of the script were located here for me /home/username/.arduino15/packages/arduino/hardware/mbed_nano/2.8.0/post_install.sh /home/username/.platformio/packages/framework-arduino-mbed/post_install.sh These should contain: Raspberry Pi RP2040 bootloader mode UDEV rules

  • Configure PlatformIO

[env:nanorp2040connect]
platform = raspberrypi
board = nanorp2040connect
framework = arduino
extra_scripts = fix_linker.py

build_flags =
    -L ./.pio/libdeps/nanorp2040connect/micro_ros_arduino/src/cortex-m0plus/
    -D ARDUINO_NANO_RP2040_CONNECT

lib_deps =
    arduino-libraries/WiFiNINA@^1.8.13
    https://github.com/micro-ROS/micro_ros_arduino
    SPI

platform_packages =
  toolchain-gccarmnoneeabi @ ~1.70201.0
  framework-arduino-mbed @ ~2.4.1

lib_ldf_mode = chain+
- If you need to manually specify the serial port settings add your own version of the following for port and baud. Ignore this otherwise.
	upload_port = /dev/ttyACM0
	monitor_speed = 57600
  • Create fix_linker.py in same dir as platformio.ini - Ref Known issue. 774 & 780

    fix_linker.py

Import("env")

env["_LIBFLAGS"] =  ('-Wl,--start-group -Wl,--whole-archive '
                    '${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)} '
                    '-Wl,--no-whole-archive -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys -lmicroros -Wl,--end-group')
  • Run a test build. I used the blink sketch that was included as an example in the Ardunio IDE for the board.

#gotcha I ran into a problem that was a known issue but the posted fix required an extra step of manually including SPI in the ini file. This has been done. For ref: SPI.h not found. micro-ROS/micro_ros_arduino#780

Step 2 Build and flash micro-ros Application Arduino Nano RP2040 Connect

The micro-ROS build system workflow is a four-step procedure.

  • Create
    • Download all the required code repositories and cross-compilation toolchains for the specific hardware platform. Also some sample micro-ROS apps.
  • Configure
    • We select which app is going to be cross-compiled by the toolchain. Some other options, such as transport, agent’s IP address/port (for UDP transport) or device ID (for serial connections) will be also selected in this step. Skipped. As we are cmpiling micro-ROS in the host machine, rather than on a board or with an RTOS, the cross-compilation implemented by the configuration step is not required in this case..
  • Build
    • Cross-compilation takes place and the platform-specific binaries are generated
  • Flash
    • The binaries generated in the previous step are flashed onto the hardware platform memory

You can use a docker container with a fresh ROS 2 Foxy installation. (I did not) The one that serves the purpose is the container run by the command:

docker run -it --net=host -v /dev:/dev --privileged ros:foxy

List of gotchas

#gotcha 1 **I did not have #rosdep** . The source tutorial seemed to take it for granted that it was already installed. I had to install it. 

#gotcha 2 **I did not have #colcon installed** So I needed to install it.   

Install micro-ROS build system & Firmware Workspace

Once you have a ROS 2 installation in the computer, follow these steps to install the micro-ROS build system:

# Source the ROS 2 installation
source /opt/ros/$ROS_DISTRO/setup.bash

# Create a new firmware workspace  workspace and download the micro-ROS tools
cd /home/username/Dev/ROS2/micro-ROS
mkdir microros_ws
cd microros_ws
git clone -b $ROS_DISTRO https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup


# Install pip & rosdep
sudo apt update
sudo apt install python3-rosdep2 python3-pip

# Update dependencies using rosdep - #gotcha 
sudo apt update && rosdep update
rosdep install --from-path src --ignore-src -y

# Install colcon if not installed. 
sudo apt install python3-colcon-common-extensions

# Build micro-ROS tools - #gotcha
colcon build

# Source micro-ROS tools 
source install/local_setup.bash

# Create firmware 
ros2 run micro_ros_setup create_firmware_ws.sh host
# Once executed, a folder named `firmware` must be present in your workspace.

Build Step

ros2 run micro_ros_setup build_firmware.sh
source install/local_setup.bash

After a 13min 37s with my CPU pinned to max and hoping it would not overheat. I received the following output.

title: build summary
Summary: 38 packages finished [13min 37s]
  9 packages had stderr output: common_interfaces micro_ros_demos_rclc micro_ros_demos_rclcpp micro_ros_setup microxrcedds_client rmw_microxrcedds rosidl_typesupport_microxrcedds_c_tests rosidl_typesupport_microxrcedds_cpp_tests rosidl_typesupport_microxrcedds_test_msg

The #micro-ROS app is ready to be connected to a #micro-ROS-agent to start talking to the rest of the #ROS2 world.

Creating and running the micro-ROS agent

# Download micro-ROS-Agent packages
ros2 run micro_ros_setup create_agent_ws.sh

# Build step
# Build the agent packages. When this is done, source the installation:
ros2 run micro_ros_setup build_agent.sh
source install/local_setup.bash

# Now that we have the client and agent installed 

# Run a micro-ROS agent
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888

# Open another terminal to run the mcro-ROS node
source /opt/ros/$ROS_DISTRO/setup.bash
source install/local_setup.bash

# Use RMW Micro XRCE-DDS implementation
export RMW_IMPLEMENTATION=rmw_microxrcedds

# Run the micro-ROS node
ros2 run micro_ros_demos_rclc ping_pong

Testing

To test if everything is working. Open a bunch of terminal windows so you can:

# Subscribe to micro-ROS ping topic
ros2 topic echo /microROS/ping
# Subscribe to micro-ROS pong topic
ros2 topic echo /microROS/pong

Now publish 'fake_ping' on the ping topic with ROS 2 from yet another command line

# Send a fake ping
ros2 topic pub --once /microROS/ping std_msgs/msg/Header '{frame_id: "fake_ping"}'

You should see the fake_ping some into the ping topic and the reply on the pong topic. If you open multiple ping_pong micro-ros apps then you will see their different IDs while the interact.

Flash Step

Flashing the #firmware

At this point we have the micro_ros Tools and Agent installed. Above we ran the agent listening on UDP port 8888. Here we use serial port / USB (in this case my board is ttyACM0)

ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0

Hit Ctrl-C. We dont want anything using the serial port on when we upload to the Arduino.

Grab the sample code #micro-ROS_publisher

I Pasted the sample code into Main.cpp in the platformIO project and ran the build and upload. I ran the agent again and I hit reset the Arduino and agent started to see the publisher.

username@laptop:~/Dev/ROS2/micro-ROS/microros_ws$ ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 
[1648508910.130826] info     | TermiosAgentLinux.cpp | init                     | running...             | fd: 3
[1648508911.571930] info     | Root.cpp           | delete_client            | delete                 | client_key: 0x3E6A72F9
[1648508911.571971] info     | SessionManager.hpp | destroy_session          | session closed         | client_key: 0x3E6A72F9, address: 0
[1648508911.571987] info     | Root.cpp           | create_client            | create                 | client_key: 0x3FDE8509, session_id: 0x81
[1648508911.572000] info     | SessionManager.hpp | establish_session        | session established    | client_key: 0x3FDE8509, address: 0
[1648508911.580306] info     | ProxyClient.cpp    | create_participant       | participant created    | client_key: 0x3FDE8509, participant_id: 0x000(1)
[1648508911.583246] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x3FDE8509, topic_id: 0x000(2), participant_id: 0x000(1)
[1648508911.585176] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x3FDE8509, publisher_id: 0x000(3), participant_id: 0x000(1)
[1648508911.587138] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x3FDE8509, datawriter_id: 0x000(5), publisher_id: 0x000(3)

username@laptop:~/Dev/ROS2/micro-ROS/microros_ws$ ros2 topic echo /micro_ros_arduino_node_publisher
data: 0
---
data: 1
---
data: 2
---

Note. I wrote this as documnetation of my own process so it was repeatable. All acknowlegement to the source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment