Edge Impulse Docs

Edge Impulse Documentation

Welcome to the Edge Impulse documentation. You'll find comprehensive guides and documentation to help you start working with Edge Impulse as quickly as possible, as well as support if you get stuck. Let's jump right in!

On STM32 using STM32Cube.AI

Impulses can be deployed as a CMSIS-PACK for STM32. This packages all your signal processing blocks, configuration and learning blocks up into a single package. You can include this package in any STM32 project with a single function call. The CMSIS-PACK uses STM32Cube.AI to run any neural network, and CMSIS-DSP for all signal processing code - ensuring that models run as fast and efficient as possible. In this tutorial you'll export an impulse, import the impulse into STM32CubeMX, and then integrate it in your STM32 project to classify sensor data.

Using this CMSIS-PACK is currently only supported from C++ applications using STM32CubeIDE, on Cortex-M4, Cortex-M7 and Cortex-M33 MCUs.

Prerequisites

Make sure you followed the Continuous motion recognition tutorial, and have a trained impulse. Also install the following software:

Make sure you have a C++ project configured that compiles for your target. You can convert an existing project to C++ by right-clicking on your project and selecting Convert to C++.

Enabling the CRC

STM32Cube.AI requires the CRC to be enabled for your target. Open your .ioc file, then:

  1. Go to Pinout & Configuration.
  2. Select Computing > CRC.
  3. Enable the Activated checkbox.

Enabling the CRC on your target.

Printing floating points

Depending on your target you might need to enable support for printing floating point numbers. This is used for printing the results of the impulse and for debugging intermediate features (alternatively you can override the weak defined ei_printf_float function). You enable this support by right-clicking on your project, then selecting Properties > C/C++ Build > Settings > Tool Settings > MCU G++ Linker > Miscellaneous, and adding -u _printf_float to the 'Other flags' section.

Enabling support for printing floats

Adding the CMSIS-PACK

Head over to your Edge Impulse project, and go to Deployment. From here you can create the full library which contains the impulse and all external required libraries. Select Cube.AI CMSIS-PACK and click Build to create the library.

To add the CMSIS-PACK library to your project, open your .ioc file, then:

  1. Go to Help > Manage embedded software packages.
  2. Select From Local ... and select the .pack file you just downloaded.
  3. Accept the license agreement, and the pack will be installed. The version number is automatically updated whenever you export the pack.

Your impulse as a CMSIS-PACK available from STM32CubeIDE

  1. Go back to your .ioc file, and go to Pinout & Configuration.
  2. Click Additional software.

This is a button

  1. Under 'Pack vendor' select EdgeImpulse, expand the pack, and add a checkbox under 'Selection'.

Selecting the CMSIS-PACK.

  1. Click OK to close the window.
  2. Under Pinout & Configuration, select 'Additional software', and click on your project name. Place a checkbox next to tinyML ML.

Enabling the CMSIS-PACK

  1. Click in the 'Project explorer' so the .ioc file loses focus.
  2. Click CTRL+S or CMD+S to save the workspace. This will regenerate the code. Afterward you should have a 'Middleware' folder in your project with your impulse and all required libraries.

The CMSIS-PACK added to a project

  1. Last, there is a bug in STM32CubeIDE where it does not pick up libraries from CMSIS-PACKs automatically, so you'll need to add the STM32Cube.AI library by hand. Right click on your project, select Properties > C/C++ Build > Settings > Tool Settings > MCU G++ Linker > Libraries. Here:
    • Under 'Libraries' add:
      • If you have a Cortex-M4 target: :NetworkRuntime500_CM4_IAR.a
      • If you have a Cortex-M7 target: :NetworkRuntime500_CM7_IAR.a
      • If you have a Cortex-M33 target: :NetworkRuntime500_CM33_IAR.a
    • Under 'Library search path', find the Middlewares/ST/AI/Lib/ABI2.1 folder and then select your architecture.
  2. The code generator always generates a new main.c file, even for C++ projects. If you have both a main.c and a main.cpp file now, remove the main.c file.

Loading the Cortex-M4 STM32Cube.AI library

Configuring printf

To log debug information the CMSIS-PACK uses the (weak defined) ei_printf function. You need to override this function in your main.cpp (if you only have a main.c rename it) to log to your UART port. E.g. this is how you set this up on the ST B-L475E-IOT01A. Under USER CODE BEGIN 0 add:

#include <stdarg.h>
#include "edge-impulse-sdk/classifier/ei_run_classifier.h"

void vprint(const char *fmt, va_list argp)
{
    char string[200];
    if(0 < vsprintf(string, fmt, argp)) // build string
    {
        HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 0xffffff); // send message via UART
    }
}

void ei_printf(const char *format, ...) {
    va_list myargs;
    va_start(myargs, format);
    vprint(format, myargs);
    va_end(myargs);
}

Running the impulse

With the CMSIS-PACK included, and the UART set up, it's time to verify that the application works. Head back to the studio and click on Live classification. Then load a validation sample, and click on a row under 'Detailed result'.

Selecting the row with timestamp '320' under 'Detailed result'.

To verify that the local application classifies the same, we need the raw features for this timestamp. To do so click on the 'Copy to clipboard' button next to 'Raw features'. This will copy the raw values from this validation file, before any signal processing or inferencing happened.

Copying the raw features

Open main.cpp (if you only have a main.c rename it) and add the following code under USER CODE BEGIN Includes (replace the features array with the data you just copied):

#include "edge-impulse-sdk/classifier/ei_run_classifier.h"

using namespace ei;

// paste the raw features here
static float features[] = {
    -19.8800, -0.6900, 8.2300, -17.6600, -1.1300, 5.9700, ...
};

int get_feature_data(size_t offset, size_t length, float *out_ptr) {
    memcpy(out_ptr, features + offset, length * sizeof(float));
    return 0;
}

Then, under USER CODE BEGIN Init, add:

signal_t signal;
signal.total_length = sizeof(features) / sizeof(features[0]);
signal.get_data = &get_feature_data;

And, under USER CODE BEGIN WHILE, add:

while (1)
{
    ei_impulse_result_t result;
    EI_IMPULSE_ERROR res = run_classifier(&signal, &result, true);
    ei_printf("run_classifier returned: %d\n", res);

    ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
        result.timing.dsp, result.timing.classification, result.timing.anomaly);

    // print the predictions
    ei_printf("[");
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
        ei_printf("%.5f", result.classification[ix].value);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
        ei_printf(", ");
#else
        if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {
            ei_printf(", ");
        }
#endif
    }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
    ei_printf("%.3f", result.anomaly);
#endif
    ei_printf("]\n\n\n");

    HAL_Delay(5000);
}

Then build and flash the application to your development board, via Project > Build All and Run > Debug.

Seeing the output

To see the output of the impulse, connect to the development board over a serial port on baud rate 115,200 and reset the board (e.g. by pressing the black button on the ST B-L475E-IOT01A).

This will run the signal processing pipeline, and then classify the output:

Running neural network...
Predictions (time: 1 ms.):
idle:   0.015319
snake:  0.000444
updown: 0.006182
wave:   0.978056
Anomaly score (time: 1 ms.): 0.133557
run_classifier_returned: 0
[0.01532, 0.00044, 0.00618, 0.97806, 0.134]

Which matches the values we just saw in the studio. You now have your impulse running on your STM32 development board!

Upgrading the CMSIS-PACK

To upgrade your CMSIS-PACK do this:

  1. Download the new version of the CMSIS-PACK from Edge Impulse.
  2. Open your .ioc file, go to Pinout & Configuration > Additional software and select the CMSIS-PACK.
  3. Unselect the checkbox next to 'tinyML ML'.

Disable the old CMSIS-PACK

  1. Click in the 'Project explorer' so the .ioc file loses focus, and press CTRL+S or CMD+S. This will generate some new code.
  2. Remove the 'Middlewares/Third_party' folder.
  3. Go back to the .ioc file, select Help > Manage embedded software packages and add the new CMSIS-PACK.
  4. On the .ioc page, click the big blue button reading 'Additional software'.
  1. Find your CMSIS-PACK, and expand the line. If the 'Selection' checkbox is selected, uncheck this first.
  2. Change the Version dropdown to the new CMSIS-PACK version.
  3. Expand the item again, and enable the 'Selection' toggle. Press OK to exit the modal.

Unselect, change version, then select again

  1. Find the new CMSIS-PACK version under 'Additional software' in the item list, click on it (there are now probably multiple CMSIS-PACKs listed here for some reason), and set a new checkbox next to 'tinyML ML'.

Enable the new CMSIS-PACK

  1. Click in the 'Project explorer' so the .ioc file loses focus, and press CTRL+S or CMD+S. This will generate some new code.
  2. Remove main.c as it will be generated again.
  3. You now have a new CMSIS-PACK version!

Updated 3 months ago

On STM32 using STM32Cube.AI


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.