This repository demonstrates how to run IMU-based Edge Impulse models on Zephyr using the Edge Impulse Zephyr Module.
Drop in your model > build > flash > get real-time motion inference.
west init https://github.com/edgeimpulse/ei-zephyr-imu-inference.git
cd ei-zephyr-imu-inference
west updateThis fetches:
- Zephyr RTOS
- Edge Impulse Zephyr SDK module
- All module dependencies
In Edge Impulse Studio go to:
Deployment > Zephyr library > Build
Download the generated .zip
Extract into the model/ folder:
unzip -o ~/Downloads/your-model.zip -d model/Your model/ directory should contain:
CMakeLists.txtedge-impulse-sdk/model-parameters/tflite-model/
The project support the following sensor shield:
- X-NUCLEO-IKS02A1 enabled passing
-DCONFIG_EI_IKS02A1=y - IKS01A3 enabled passing
-DCONFIG_EI_IKS01A3=y
Choose your board and the shield you are targeting,
For example: Nucleo U585ZI + IKS01A3
west build --pristine -b nucleo_u585zi_q -- -DCONFIG_EI_IKS01A3=yOr Renesas EK RA6M5 + IKS02A1
west build --pristine -b ek_ra6m5 -- -DCONFIG_EI_IKS02A1=yNote
You need to define one of the supported shield otherwise the build will fail with an error.
west flashOr specify runner:
west flash --runner jlink
west flash --runner nrfjprog
west flash --runner openocdAll sensors accessible through I²C/SPI + Zephyr sensor drivers are compatible.
├── CMakeLists.txt # Build configuration
├── prj.conf # Zephyr config
├── west.yml # Manifest (declares Edge Impulse SDK module)
├── model/ # Your Edge Impulse model (Zephyr library)
└── src/
├── main.cpp
├── inference/ # Inference state machine
└── sensors/ # IMU interface
- Initialize - Sensor setup via Zephyr sensor API
- Sample - Continuous data collection at model frequency
- Buffer - Circular buffer stores samples
- Infer - Run classifier when buffer full
- Output - Print classification results
- Loop - Repeat
Key settings in prj.conf:
CONFIG_EDGE_IMPULSE_SDK=y # Enable Edge Impulse SDK
CONFIG_MAIN_STACK_SIZE=8192 # Adjust for your model size
CONFIG_SENSOR=y # Enable sensor subsystem
CONFIG_I2C=y # Enable I2C for sensorsFor larger models, increase stack size:
CONFIG_MAIN_STACK_SIZE=16384Add to your west.yml:
projects:
- name: edge-impulse-sdk-zephyr
path: modules/edge-impulse-sdk-zephyr
revision: v1.75.4 # See https://github.com/edgeimpulse/edge-impulse-sdk-zephyr/tags
url: https://github.com/edgeimpulse/edge-impulse-sdk-zephyrThen:
west updateAdd to your CMakeLists.txt:
list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_SOURCE_DIR}/model)west update# In prj.conf
CONFIG_MAIN_STACK_SIZE=16384# In prj.conf - enable debug logging
CONFIG_I2C_LOG_LEVEL_DBG=y
CONFIG_SENSOR_LOG_LEVEL_DBG=ySymptom:
CMake Error at .../zephyr/cmake/modules/zephyr_module.cmake:73 (message):
Unmet or cyclic dependencies in modules:
/path/to/your-project/model
depends on: ['edge-impulse-sdk-zephyr']
Cause:
Your project has two module.yml files registering different parts of your application as Zephyr modules. This creates a hierarchical conflict where the module system can't determine the correct dependency resolution order.
How to Check: From your project root, run:
find . -maxdepth 2 -name "module.yml"You should see only ONE result:
./model/zephyr/module.yml ✓ CORRECT
If you see both of these:
./zephyr/module.yml DELETE THIS
./model/zephyr/module.yml KEEP THIS
Fix:
Delete the zephyr/module.yml file at your project root:
rm zephyr/module.ymlThen run:
west update
west build -b <your_board> -pWhy This Happens:
model/zephyr/module.ymlcorrectly registers your trained ML model as a modulezephyr/module.ymlincorrectly registers the entire application as a module- The build system finds the project-level module first, then encounters the model module nested inside, creating a circular dependency
Key Principle:
Only the model should be a Zephyr module. Your application project is a Zephyr application, not a module.
Clear BSD License - see LICENSE file
Copyright (c) 2025 EdgeImpulse Inc.