---
title: TurtleBot3 OpenCR firmware update from a snap
description: Explore a way update firmware with a snap. Keep the OpenCR firmware of
  the TurtleBot3 up to date and transparent to the user.
url: https://canonical.com/blog/turtlebot3-opencr-firmware-update-from-a-snap?format=md
---

1. [Blog](https://canonical.com/blog)
2. Article

---

[gbeuzeboc](https://canonical.com/blog/author/gbeuzeboc "More about gbeuzeboc")

25 September 2024

# TurtleBot3 OpenCR firmware update from a snap

[iot snaps](https://canonical.com/blog/tag/iot-snaps)
[robotics](https://canonical.com/blog/tag/robotics)
[ROS](https://canonical.com/blog/tag/ros)
[ROS 2](https://canonical.com/blog/tag/ros-2)
[snapcraft](https://canonical.com/blog/tag/snapcraft)
[Snaps](https://canonical.com/blog/tag/snaps)

---

Share the article

The [TurtleBot3](https://emanual.robotis.com/docs/en/platform/turtlebot3/overview/) robot is a standard platform robot in the ROS community, and it’s a reference that Canonical knows well, since we’ve used it in [our tutorials](https://ubuntu.com/robotics/docs/tutorials). As a matter of fact, we use it to demonstrate some of our work, such as distributing a ROS stack through snaps. This robot embeds two boards, a Raspberry Pi 4 that runs Ubuntu and the ROS stack, and an embedded board called the [OpenCR](https://emanual.robotis.com/docs/en/parts/controller/opencr10/). This board is the interface between the Raspberry Pi and the motors, the IMU and the battery.

The OpenCR board does not run an OS like [Ubuntu](https://ubuntu.com/desktop). Instead, the microcontroller runs a firmware that can be upgraded as shown in [the documentation](https://emanual.robotis.com/docs/en/platform/turtlebot3/opencr_setup/), and it uses a connection via USB to the Raspberry Pi for robot control (data exchange and motor operation) and firmware updates for the OpenCR board itself.

The version of the firmware used on the robot must match the ROS distro: a ROS noetic snap won’t be able to operate with the OpenCR board if it uses the firmware version that is compatible with ROS 2 Humble. In that case, we need to update the OpenCR board.

We’ve recently [published a tutorial on how to create a custom Ubuntu Core image](https://ubuntu.com/robotics/docs/ros-deployment-with-snaps-part-5) for the TurtleBot3 that ships with everything necessary for out of the box operations (except for the automation of the firmware update). By adding the firmware update to a snap, we will make sure to never face incompatibility between the firmware version and the ROS distribution, as well as to always run the latest version of the firmware.

Over the course of this blog, we explore the solution we employed to keep the OpenCR firmware up to date from within a snap. The approach taken in this blog is just an example of how we can update a firmware with a snap. Other ways are possible, and we could explore other possibilities in the future.

## The context

We are not starting from scratch. Indeed, the TurtleBot3 already has a defined procedure to update firmware.

Additionally, [in the robotics documentation](https://ubuntu.com/robotics/docs), we have already worked with the [TurtleBot3 and developed snaps for it](https://github.com/canonical/turtlebot3c-snap).

These will be the starting point of our work here, so make sure to familiarise yourself with these to better follow along.

### The OpenCR scripts

In the [OpenCR firmware update documentation](https://emanual.robotis.com/docs/en/platform/turtlebot3/opencr_setup/), we see that we need binaries hosted on the GitHub repository: [github.com/ROBOTIS-GIT/OpenCR-Binaries](https://github.com/ROBOTIS-GIT/OpenCR-Binaries/tree/master).

These binaries contain the firmware as well as the tools to flash the update from a host. We must include them in a snap and reproduce the instructions from the documentation in the snap to be able to update the firmware.

### Sharing access to the port

In the [TurtleBot3 Ubuntu Core image tutorial](https://ubuntu.com/robotics/docs/ros-deployment-with-snaps-part-5), we’ve shipped as part of the Ubuntu Core image the [turtlebot3c-bringup snap](https://github.com/canonical/turtlebot3c-snap/tree/feature/multi-snap) that launches the ROS node that communicates with the OpenCR board over the `/dev/ttyACM0` port.

The firmware update uses the same port and cannot run when the ROS node is running, since they need the very same resource.

Since those two processes are conflicting, we chose to ship the firmware updater in the very same snap that makes use of the OpenCR board to control the robot. This way, we ease their orchestration for the purpose of this post.

## Update the firmware from the snap

First, we focus on writing a snap application that updates the firmware without bothering with the orchestration. We ship the firmware update files and add an application to update it.

### Add the firmware files to the snap

The first step is [to add](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/snapcraft.yaml#L60) the [OpenCR-Binaries](https://github.com/ROBOTIS-GIT/OpenCR-Binaries/tree/master) repository to our snap. We download and decompress the tarball into the `$SNAP/opencr` directory.

Additionally, in the same part, [we list the `libc6:armhf`](https://github.com/canonical/turtlebot3c-snap/blob/52e20ce17e22b30e85bcfd5455f66caf024a3878/turtlebot3c-bringup-snap/snap/snapcraft.yaml#L68) for the runtime of our snap. This is because the binary to upload the firmware is built for `armhf` (32 bits). Two interesting things to note here: first, how we [distinguish between the architecture in the snapcraft.yaml](https://snapcraft.io/docs/architectures); and second, how an `arm64` architecture can stage packages from its 32 bit equivalent (`armhf` in this case) and vice versa.

### Scripts to facilitate the firmware flashing

The [OpenCR update documentation](https://emanual.robotis.com/docs/en/platform/turtlebot3/opencr_setup/) mentions that there are some environment variables to specify, and so we need to write [a script](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/local/update_firmware.sh) of the whole process.

First, [the script](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/local/update_firmware.sh) proceeds with some preparation:

* Since we provide the update only for the robot with a Raspberry Pi, the script exits if it is not running on arm architecture.
* Define the `OPENCR_PORT` to `/dev/ttyACM0`, which is the default port.
* Define the `OPENCR_MODEL` from the `turtlebot3c-model` snap configuration already present.

Finally, the firmware update is executed with the proper configuration.

### Firmware update application

With the custom script that we’ve added, we now [add an application](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/snapcraft.yaml#L82) to our snap.

The [opencr-update](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/snapcraft.yaml#L82) application is simply calling the script and declaring, as a plug, the [raw-usb interface](https://snapcraft.io/docs/raw-usb-interface). With this interface, the application is capable of accessing the `/dev/ttyACM0` port.

And that is all we need to be able to manually update the firmware of the OpenCR board from the snap. Note that when manually updating, we should first make sure to stop the `turtlebot3c-bringup.core` daemon.

From there, wouldn’t it be great to push our luck and make the flashing automatic? So that we could remotely update the firmware without any human intervention. Let’s see how we can make that a seamless experience.

## Orchestrate the firmware update

We’ve already reviewed the [ROS orchestration with snaps](https://ubuntu.com/blog/ros-orchestration-with-snaps) in a previous blog. As we want to flash the firmware when the snap updates, we will use the same mechanism: [snap hooks](https://snapcraft.io/docs/supported-snap-hooks).

### Flash on update hooks

As represented in the following diagram, we use the [default-configure hook](https://snapcraft.io/docs/supported-snap-hooks#heading--default-configure) to flash the firmware on the first install after the [gadget](https://snapcraft.io/docs/the-gadget-snap) configuration. Furthermore, we also use the [post-refresh hook](https://snapcraft.io/docs/supported-snap-hooks#heading--post-refresh) to update the firmware after a snap update and before the `turtlebot3c.core` application is started.

To avoid duplication, our [`default-configure-script`](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/hooks/default-configure) simply calls the [`post-refresh-script`](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/hooks/post-refresh) where the logic is implemented. Similarly to the app, we added the `raw-usb` interface to the hooks [in the `snapcraft.yaml`](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/snapcraft.yaml#L40) so they can access the OpenCR port.

### The opencr-auto-update configuration

The [`turtlebot3c-bringup`](https://snapcraft.io/turtlebot3c-bringup) snap is meant to run on [Ubuntu Core](https://ubuntu.com/core/docs) as well as Ubuntu Desktop/Server. In some situations, we may not want the [`turtlebot3c-bringup`](https://snapcraft.io/turtlebot3c-bringup) snap to update or attempt to update the firmware. For that reason, we introduce a configuration to our snap called `opencr-auto-update` to enable/disable the firmware auto-update feature.

We first define it in our [`install` hook](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/hooks/install) and set the default value to `false`.

Additionally, we make sure in our [`configure` hook](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/hooks/configure) to properly validate the given input.
With the auto-update happening in our [`post-refresh` hook](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/hooks/post-refresh), we [make sure to check](https://github.com/canonical/turtlebot3c-snap/blob/feature/multi-snap/turtlebot3c-bringup-snap/snap/hooks/post-refresh#L6) for the `opencr-auto-update` value before flashing.

### Update only on firmware change

Because we ship the firmware in the [turtlebot3c-bringup](https://snapcraft.io/turtlebot3c-bringup) snap, it might happen that we update our snap without updating the firmware. In fact, the firmware is unlikely to change. Additionally, it’s preferable to limit the flashing of a microcontroller to save the flash memory.

For those reasons, we included a mechanism to update the firmware only when it changes. As the following diagram shows, after a firmware update, we generate a hash from the directory of our snap that contains the firmware and save it for later comparison. Then, on the next update, we regenerate the hash and compare it with the one saved to verify if there is any change. In case of an update, we flash the new firmware and then save the new hash for later comparison.

Using this functionality in the [`post-refresh` hook](https://github.com/canonical/turtlebot3c-snap/blob/52e20ce17e22b30e85bcfd5455f66caf024a3878/turtlebot3c-bringup-snap/snap/hooks/post-refresh), we can ensure that the firmware is only updated if necessary.

## Conclusion

I hope that reading this blog has piqued your interest and shown you that even microcontrollers can be remotely flashed and kept up to date with snaps.

Snaps can run applications on the host, but they can also carry and flash firmwares. This way, we benefit from the OTA update feature of snaps for devices that cannot even run an OS.

The approach taken in this blog could surely benefit from various improvements. For example, a backup strategy in case the flashing goes wrong. Since almost every microcontroller has its own flashing method, you can adapt the strategy used in this blog to your specific use cases.
If you have any feedback, questions or ideas regarding firmware update with snaps, please join [our forum](https://forum.snapcraft.io/) or [contact us](https://ubuntu.com/core/contact-us) and let us know what you think. Furthermore, have a look at the [Canonical robotics documentation](https://ubuntu.com/robotics/docs) if you want to learn more about snaps for [robotics applications](https://ubuntu.com/robotics).

[Get in touch

Interested in running Ubuntu in your organization?](https://ubuntu.com/about/contact-us/form)

## Sign up for our newsletter

Get the latest Canonical news and updates in your inbox.

Work email:

\*I agree to receive information about Canonical's
products and services.

By submitting this form, I confirm that I have read and agree to [Canonical's Privacy Policy](https://canonical.com/legal/dataprivacy).

Sign up

## Share on

---

## Related posts

[### Canonical is now a platinum member in the Open Source Robotics Alliance](https://canonical.com/blog/osra-membership)

Ubuntu is the home of ROS. The very first ROS distribution, Box Turtle, launched on Ubuntu 8.04 LTS, Hardy Heron, and since then, Ubuntu and ROS have grown hand in hand. With...

[Gabriel Aguiar Noury](https://canonical.com/blog/author/g-aguiar-noury)

20 August 2025

[### ROS Noetic is EOL – take action to maintain fleet security](https://canonical.com/blog/ros-noetic-is-eol-take-action-to-maintain-fleet-security)

As of May 2025, the Robot Operating System (ROS) Noetic Ninjemys officially reached its end of life (EOL). First released in 2020 as the final ROS (1) distribution, ROS Noetic...

[Florencia Cabral Berenfus](https://canonical.com/blog/author/flor-cabral)

8 August 2025

[### Extending ROS Noetic Support with ESM-Enabled Content Snaps](https://canonical.com/blog/extending-ros-noetic-support-with-esm-enabled-content-snaps)

Canonical has now extended its ESM (Expanded Security Maintenance) for ROS coverage to ROS Noetic content-sharing snaps. With ESM for ROS now available in both deb and snap...

[Florencia Cabral Berenfus](https://canonical.com/blog/author/flor-cabral)

17 December 2025

[### Discover your fully open source robotics observability at ROSCon 2025](https://canonical.com/blog/roscon-2025)

Another year, another ROSCon! This year we’re heading to Singapore, and Canonical is once again thrilled to sponsor this important community event. Just like last year in...

[Gabriel Aguiar Noury](https://canonical.com/blog/author/g-aguiar-noury)

22 October 2025
