Skip to content

Commit 2c3b9f5

Browse files
committed
applications: gesture_recognition: Add Axon configuration
Add Axon configuration for gesture recognition application. Add new model compatible with axon NPU architecture. JIRA: NCSDK-36993 Signed-off-by: Jan Zyczkowski <jan.zyczkowski@nordicsemi.no>
1 parent 7f08580 commit 2c3b9f5

17 files changed

Lines changed: 683 additions & 23 deletions

File tree

applications/gesture_recognition/CMakeLists.txt

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,26 @@ set(APPLICATION_CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/configuration/\${NORMALI
1212
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
1313
project(gesture_recognition)
1414

15-
# Check if platform-specific neural network model file exists
16-
set(NN_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/src/nrf_edgeai_generated/${BOARD}")
17-
set(NN_PATH "${NN_SOURCE}/nrf_edgeai_user_model.c")
18-
if(EXISTS "${NN_PATH}")
19-
message(STATUS "Using Edge AI model for board: ${BOARD}")
15+
set(NN_BASE "${CMAKE_CURRENT_SOURCE_DIR}/src/nrf_edgeai_generated/${BOARD}")
16+
17+
if(CONFIG_NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON)
18+
set(NN_SOURCE "${NN_BASE}/Axon")
2019
else()
21-
message(FATAL_ERROR "Edge AI model file not found for board '${BOARD}'.\n"
22-
"Expected file: ${NN_PATH}\n"
23-
"Please create ${NN_PATH} or use one of the supported boards."
24-
)
20+
# Neuton: use Neuton subdir only for nrf54lm20dk (has both Axon and Neuton)
21+
if(BOARD STREQUAL "nrf54lm20dk")
22+
set(NN_SOURCE "${NN_BASE}/Neuton")
23+
else()
24+
set(NN_SOURCE "${NN_BASE}")
25+
endif()
26+
endif()
27+
28+
set(NN_PATH "${NN_SOURCE}/nrf_edgeai_user_model.c")
29+
if(NOT EXISTS "${NN_PATH}")
30+
message(FATAL_ERROR "Edge AI model file not found for board '${BOARD}' (model dir: ${BOARD_BASE}).\n"
31+
"Expected: ${NN_PATH}\n"
32+
"Create the model at that path or use a supported board.")
2533
endif()
34+
message(STATUS "Using Edge AI model: ${NN_SOURCE}")
2635

2736
target_include_directories(app PRIVATE
2837
${CMAKE_CURRENT_SOURCE_DIR}/src/hw_modules

applications/gesture_recognition/Kconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ source "Kconfig.zephyr"
99
config DATA_COLLECTION_MODE
1010
bool "Enable Data Collection Mode (no inference run)"
1111

12+
choice NRF_EDGEAI_GESTURE_RECOGNITION_MODEL
13+
prompt "Edge AI model backend"
14+
default NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON if SOC_NRF54LM20B
15+
default NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_NEUTON
16+
help
17+
Select which model implementation to use. Axon (NPU) is only available
18+
on nRF54L20 (nrf54lm20b). Other boards use Neuton (CPU).
19+
20+
config NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_NEUTON
21+
bool "Neuton (CPU)"
22+
help
23+
Use the Neuton model. Works on all supported boards.
24+
25+
config NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON
26+
bool "Axon (NPU)"
27+
depends on SOC_NRF54LM20B
28+
select NRF_AXON
29+
help
30+
Use the Axon model. Only available on Axon-enabled devices.
31+
32+
endchoice
33+
1234
choice BLE_MODE
1335
prompt "BLE mode"
1436
default BLE_MODE_HID if !DATA_COLLECTION_MODE

applications/gesture_recognition/README.rst

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ This application demonstrates a gesture-based remote control device using Nordic
1212
Application overview
1313
********************
1414

15-
.. note::
15+
The gesture recognition application demonstrates how to use an nRF Edge AI model to recognize hand gestures from motion sensor data and expose them as standard HID inputs over Bluetooth® Low Energy.
16+
There are two variants of the application that differ in where the model is executed:
1617

17-
Currently, the gesture recognition application supports only Neuton CPU-based neural network models.
18+
* The Neuton variant, which uses a CPU-based model, also called the Neuton model.
19+
* The Axon variant, which uses an NPU-based model, also called the Axon model.
1820

19-
The gesture recognition application demonstrates how to use an nRF Edge AI model to recognize hand gestures from motion sensor data and expose them as standard HID inputs over Bluetooth® Low Energy.
2021
When connected to a PC, the device appears as a Bluetooth LE HID device, allowing recognized gestures to control media playback or presentation slides.
2122
Based on accelerometer and gyroscope data, the nRF Edge AI model recognizes eight gesture classes:
2223

@@ -179,6 +180,17 @@ Configuration
179180

180181
|config|
181182

183+
Choosing the model backend
184+
==========================
185+
186+
The application supports two execution backends:
187+
188+
* `Neuton models`_ - Highly optimized models that run on the CPU.
189+
* `Axon NPU`_ - Models that run on the Axon NPU (AI accelerator core).
190+
191+
The Neuton model is used by default on all boards that do not have the Axon NPU.
192+
You can use the Axon model by enabling the ``CONFIG_NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON`` Kconfig option.
193+
182194
Choosing Bluetooth LE mode
183195
==========================
184196

applications/gesture_recognition/configuration/nrf54lm20dk_nrf54lm20b_cpuapp/app.overlay

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,7 @@
126126
spi-max-frequency = <DT_FREQ_M(8)>;
127127
};
128128
};
129+
130+
&axon {
131+
status = "okay";
132+
};

applications/gesture_recognition/configuration/nrf54lm20dk_nrf54lm20b_cpuapp/prj.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,6 @@ CONFIG_FLASH_PAGE_LAYOUT=y
4747
CONFIG_FLASH_MAP=y
4848
CONFIG_NVS=y
4949
CONFIG_SETTINGS=y
50+
51+
# nRF Axon
52+
CONFIG_NRF_AXON_INTERLAYER_BUFFER_SIZE=512

applications/gesture_recognition/src/main.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,12 @@ typedef enum app_remotectrl_mode_e {
7272

7373
typedef int (*led_set_func_t)(float brightness);
7474

75-
static void send_imu_data(int16_t *input_data);
75+
#if IS_ENABLED(CONFIG_NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON)
76+
static void execute_inference(flt32_t *input_data);
77+
#else
7678
static void execute_inference(int16_t *input_data);
79+
#endif
80+
static void send_imu_data(int16_t *input_data);
7781
static void hw_modules_init(void);
7882
static void led_glowing_timer_handler(struct k_timer *timer);
7983
static void handle_inference_result(nrf_edgeai_t *model);
@@ -111,7 +115,10 @@ int main(void)
111115
nrf_edgeai_solution_id_str(p_model));
112116

113117
imu_data_t imu_data = {0};
114-
int16_t input_data[NRF_EDGEAI_INPUT_DATA_LEN];
118+
119+
flt32_t input_data_f32[NRF_EDGEAI_INPUT_DATA_LEN];
120+
int16_t input_data_i16[NRF_EDGEAI_INPUT_DATA_LEN];
121+
115122

116123
for (;;) {
117124
/* Wait for the semaphore to be released by IMU data ready interrupt */
@@ -121,17 +128,28 @@ int main(void)
121128
continue;
122129
}
123130

124-
input_data[0] = imu_data.accel[0].raw;
125-
input_data[1] = imu_data.accel[1].raw;
126-
input_data[2] = imu_data.accel[2].raw;
127-
input_data[3] = imu_data.gyro[0].raw;
128-
input_data[4] = imu_data.gyro[1].raw;
129-
input_data[5] = imu_data.gyro[2].raw;
131+
input_data_f32[0] = (flt32_t)(imu_data.accel[0].phys * 1000);
132+
input_data_f32[1] = (flt32_t)(imu_data.accel[1].phys * 1000);
133+
input_data_f32[2] = (flt32_t)(imu_data.accel[2].phys * 1000);
134+
input_data_f32[3] = (flt32_t)(imu_data.gyro[0].phys * 1000);
135+
input_data_f32[4] = (flt32_t)(imu_data.gyro[1].phys * 1000);
136+
input_data_f32[5] = (flt32_t)(imu_data.gyro[2].phys * 1000);
137+
138+
input_data_i16[0] = imu_data.accel[0].raw;
139+
input_data_i16[1] = imu_data.accel[1].raw;
140+
input_data_i16[2] = imu_data.accel[2].raw;
141+
input_data_i16[3] = imu_data.gyro[0].raw;
142+
input_data_i16[4] = imu_data.gyro[1].raw;
143+
input_data_i16[5] = imu_data.gyro[2].raw;
130144

131145
if (IS_ENABLED(CONFIG_DATA_COLLECTION_MODE)) {
132-
send_imu_data(input_data);
146+
send_imu_data(input_data_i16);
133147
} else {
134-
execute_inference(input_data);
148+
#if IS_ENABLED(CONFIG_NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON)
149+
execute_inference(input_data_f32);
150+
#else
151+
execute_inference(input_data_i16);
152+
#endif
135153
}
136154
}
137155

@@ -300,11 +318,15 @@ static void ble_send_recognized_class(const class_label_t class_label, size_t pr
300318
}
301319
#endif
302320

321+
#if IS_ENABLED(CONFIG_NRF_EDGEAI_GESTURE_RECOGNITION_MODEL_AXON)
322+
static void execute_inference(flt32_t *input_data)
323+
#else
303324
static void execute_inference(int16_t *input_data)
325+
#endif
304326
{
305327
nrf_edgeai_err_t res;
306328

307-
res = nrf_edgeai_feed_inputs(p_model, input_data, NRF_EDGEAI_INPUT_DATA_LEN);
329+
res = nrf_edgeai_feed_inputs(p_model, (void *)input_data, NRF_EDGEAI_INPUT_DATA_LEN);
308330

309331
if (res == NRF_EDGEAI_ERR_SUCCESS) {
310332
res = nrf_edgeai_run_inference(p_model);

applications/gesture_recognition/src/nrf_edgeai_generated/nrf54lm20dk/README.md renamed to applications/gesture_recognition/src/nrf_edgeai_generated/nrf54lm20dk/Axon/README.md

File renamed without changes.

0 commit comments

Comments
 (0)