I have successfully trained a keyword spotting model using Edge Impulse and deployed it by generating a binary image and flashing it to the STM32L475 IoT Discovery board.
When I run the model using the AT+RUNIMPULSECONT
command, it performs impressively, predicting keywords with over 85% accuracy. I would like to sincerely thank you for developing such a powerful and accessible platform.
However, since the binary image cannot be modified, I opted to regenerate the deployment using the Cube.MX CMSIS-PACK option. I successfully installed the required software packs and integrated the Edge Impulse SDK into a custom STM32CubeIDE project.
I followed your documentation and referenced your GitHub project:
firmware-st-b-l475e-iot01a/main.cpp
To record audio for inference, I reused your MP34DT01
microphone driver and ei_microphone_interface.cpp
.
Here is the content of my main()
function:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_CRC_Init();
/* USER CODE BEGIN 2 */
microphone_present = ei_microphone_init();
if (EI_CLASSIFIER_FREQUENCY != 16000) {
ei_printf(“ERR: Frequency is %d but can only sample at 16000Hz\r\n”, (int)EI_CLASSIFIER_FREQUENCY);
}
int print_results = -(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);
// summary of inferencing settings (from model_metadata.h)
ei_printf(“Inferencing settings:\r\n”);
ei_printf(“\tInterval: %.2f ms.\r\n”, (float)EI_CLASSIFIER_INTERVAL_MS);
ei_printf(“\tFrame size: %d\r\n”, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
ei_printf(“\tSample length: %d ms.\r\n”, EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16);
ei_printf(“\tNo. of classes: %d\r\n”, sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0]));
run_classifier_init();
ei_microphone_inference_start(EI_CLASSIFIER_SLICE_SIZE);
/* USER CODE END 2 */
/* Infinite loop /
/ USER CODE BEGIN WHILE */
while (1)
{
bool m = ei_microphone_inference_record();
if (!m) {
ei_printf(“ERR: Failed to record audio…\r\n”);
break;
}
signal_t signal;
signal.total_length = EI_CLASSIFIER_SLICE_SIZE;
signal.get_data = &ei_microphone_audio_signal_get_data;
ei_impulse_result_t result = { 0 };
EI_IMPULSE_ERROR r = run_classifier_continuous(&signal, &result, debug_nn);
if (r != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\r\n", r);
break;
}
// print the predictions
ei_printf("[");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf_float(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_float(result.anomaly);
#endif
ei_printf("]\r\n\n");
if(result.classification[2].value > 0.5)
{
ei_printf("off\r\n");
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
ei_microphone_inference_end();
run_classifier_deinit();
/* USER CODE END 3 */
}
The application builds and runs without errors. However, when I monitor the serial output, I notice that the model fails to accurately recognize some keywords. The accuracy is significantly lower than when using the original binary from Edge Impulse Studio.
I’ve been troubleshooting this issue for nearly two weeks without success.
Here are a few relevant configuration details:
#define SAMPLE_BUFFER_SIZE 4000
#define BSP_AUDIO_IN_DEFAULT_BUFFER_SIZE 4000U
And here is the:
bool ei_microphone_inference_start(uint32_t n_samples)
{
inference.buffers[0] = (int16_t *)malloc(n_samples * sizeof(int16_t));
if (inference.buffers[0] == NULL) {
return false;
}
inference.buffers[1] = (int16_t *)malloc(n_samples * sizeof(int16_t));
if (inference.buffers[1] == NULL) {
free(inference.buffers[0]);
return false;
}
inference.buf_select = 0;
inference.buf_count = 0;
inference.n_samples = n_samples;
inference.buf_ready = 0;
ei_microphone_inference_set_bsp_callback(&pdm_data_ready_inference_callback);
int32_t ret;
uint32_t state;
ret = BSP_AUDIO_IN_GetState(AUDIO_INSTANCE, &state);
if (ret != BSP_ERROR_NONE) {
printf("Cannot start recording: Error getting audio state (%ld)\n", ret);
return false;
}
if (state == AUDIO_IN_STATE_RECORDING) {
printf("Cannot start recording: Already recording\n");
return false;
}
ret = BSP_AUDIO_IN_Record(AUDIO_INSTANCE, (uint8_t *)sampleBuffer, SAMPLE_BUFFER_SIZE * 2);
if (ret != BSP_ERROR_NONE) {
printf("Error failed to start recording (%ld)\n", ret);
return false;
}
record_ready = true;
return true;
}
I’ve verified that the microphone clock is running at approximately 2.04 MHz, which is consistent with the binary image.
I’m using the default DFSDM configuration from your GitHub reference.
Despite this, I suspect that either:
- Some parameters are misconfigured in the CMSIS-based project, or
- The DMA/buffer handling is not functioning identically to the prebuilt binary.
I would truly appreciate your guidance in identifying what might be missing or misconfigured.
My project ID is 690540.
Kind regards,
Ahmad