edgeimpulse_ota
that does the job for you, so this part is completely automated. You can refer to the Colab Notebook for the code.
The patched library is the one that needs to be deployed on your board. Here’s an example sketch that runs the FOMO model on a static sample (containing a penguin). When running, you should only see the message “loop”, indicating that no object has been detected.
The sketch is available on GitHub.
ota
into the serial monitor. It is up to you to replace this part with your custom logic. The new model is fetched from the internet in this case, but you can load the binary data from any instance of Arduino’s stream
class.
The public endpoint at eloquentarduino.com
prepends the string edgeimpulse
to the OTA payload so that you can easily seek the request at the correct position. The ei_update_weights
will start reading the stream from its current position, so be sure you seek it correctly in case you are going to adapt this sketch to your own needs!
edgeimpulse_ota
Python package to do the conversion for us. Refer to the Colab Notebook here for the code. You will produce a .bin
file that can be read by the Arduino OTA code to update the model’s weights on the fly. How you will serve this file is up to you. The 2 most common use cases are by hosting it on a web server accessible at, for example http://your-domain.com/ei-ota.bin
, or saving it to an SD card accessible from the microcontroller.
As a convenience for you, I made a public API endpoint available for free that leverages the Edge Impulse API to serve the model’s latest version binary data available at https://eloquentarduino.com/edgeimpulse-ota/serve/<api-key>/<project-id>.bin
.
To generate an API key, head to the Project Dashboard in the Studio and navigate to the Keys tab at the top, then click Add a new api key in the right corner. A read-only key will suffice for the purpose.
To get the Project ID, inspect the URL: it will look like https://studio.edgeimpulse.com/studio/123456
: those digits are the ID you need.
Since the whole point of OTA updates is to not physically touch the device after deployment, the SD card approach has an interesting collateral use case that is model swapping. You can pre-load multiple models into your SD card and allow the user to choose which one they want. Working with a camera, for example, you can ask the user if they want to recognize dogs, or cats, or penguins… Working with audio, the user could choose their preferred wake word from many available, or swap between voice commands for home automation (e.g. light on, light off) vs media control (e.g. play, pause, next), which would be too many to predict accurately for a single model.
edgeimpulse_ota
library strips the const
modifier and makes them editable. The downside of this process is that now those weights will be stored in the RAM instead of the FLASH memory, and RAM is usually more limited.
Then, there exists an ei_restore_weights()
function that allows you to restore the original weights if something goes wrong during the update process (e.g. corrupted OTA payload, or broken internet connection). This is not called by default because it essentially doubles the memory needed to store a model. Given the update payload is read as a unidirectional stream and that the weights are updated inplace, there’s no mechanism to selectively revert the weights. Hence, we need to store a full copy of the original weights that won’t be altered.