CORRUPT HEAP error on ESP32 Xiao S3 with MPU 6050 accelerometer

Hi, I just recently started using Edge Impulse, and I just ran into an error where the console logs a Corrupt Heap Bad Tail error whenever I try to run my code. Here is the code I’m using below:

/* Edge Impulse ingestion SDK
 * Copyright (c) 2022 EdgeImpulse Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/* Includes ---------------------------------------------------------------- */
#include <ianc-project-1_inferencing.h>
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

/* Constant defines -------------------------------------------------------- */
MPU6050 imu;
int16_t ax, ay, az;

#define ACC_RANGE           1 // 0: -/+2G; 1: +/-4G
#define CONVERT_G_TO_MS2    (9.81/(16384/(1.+ACC_RANGE)))
#define MAX_ACCEPTED_RANGE  (2*9.81)+(2*9.81)*ACC_RANGE   

/* Private variables ------------------------------------------------------- */
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal

/**
* @brief      Arduino setup function
*/
void setup()
{
    // put your setup code here, to run once:
    Serial.begin(115200);
    // comment out the below line to cancel the wait for USB connection (needed for native USB)
    while (!Serial);
    Serial.println("Edge Impulse Inferencing Demo");

    // initialize device
    Serial.println("Initializing I2C devices...");
    Wire.begin();
    imu.initialize();
    delay(10);

    //Set MCU 6050 OffSet Calibration 
    imu.setXAccelOffset(-4732);
    imu.setYAccelOffset(4703);
    imu.setZAccelOffset(8867);
    // imu.setXGyroOffset(61);
    // imu.setYGyroOffset(-73);
    // imu.setZGyroOffset(35);

    imu.setFullScaleAccelRange(ACC_RANGE);

    if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) {
        ei_printf("ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME should be equal to 3 (the 3 sensor axes)\n");
        return;
    }
}

/**
 * @brief Return the sign of the number
 * 
 * @param number 
 * @return int 1 if positive (or 0) -1 if negative
 */
float ei_get_sign(float number) {
    return (number >= 0.0) ? 1.0 : -1.0;
}

/**
* @brief      Get data and run inferencing
*
* @param[in]  debug  Get debug info if true
*/
void loop()
{
    ei_printf("\nStarting inferencing in 2 seconds...\n");

    delay(2000);

    ei_printf("Sampling...\n");

    // Allocate a buffer here for the values we'll read from the IMU
    float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };

    for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 3) {//3
        // Determine the next tick (and then sleep later)

        uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000);

        imu.getAcceleration(&ax, &ay, &az);       
        buffer[ix + 0] = ax;
        buffer[ix + 1] = ay;
        buffer[ix + 2] = az;
       
        ei_printf("raw values:    %.2f, %.2f, %.2f\n", ax*CONVERT_G_TO_MS2, ay*CONVERT_G_TO_MS2, az*CONVERT_G_TO_MS2);
        
        buffer[ix + 0] *= CONVERT_G_TO_MS2;
        buffer[ix + 1] *= CONVERT_G_TO_MS2;
        buffer[ix + 2] *= CONVERT_G_TO_MS2;

        for (int i = 0; i < 3; i++) {
            if (fabs(buffer[ix + i]) > MAX_ACCEPTED_RANGE) {
                buffer[ix + i] = ei_get_sign(buffer[ix + i]) * MAX_ACCEPTED_RANGE;
            }
        }

        delayMicroseconds(next_tick - micros());
    }

    // Turn the raw buffer in a signal which we can the classify
    signal_t signal;
    int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
    if (err != 0) {
        ei_printf("Failed to create signal from buffer (%d)\n", err);
        return;
    }

    // Run the classifier
    ei_impulse_result_t result = { 0 };

    err = run_classifier(&signal, &result, debug_nn);
    if (err != EI_IMPULSE_OK) {
        ei_printf("ERR: Failed to run classifier (%d)\n", err);
        return;
    }

    // print the predictions
    ei_printf("Predictions ");
    ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
        result.timing.dsp, result.timing.classification, result.timing.anomaly);
    ei_printf(": \n");
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
        ei_printf("    %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
    }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
    ei_printf("    anomaly score: %.3f\n", result.anomaly);
#endif
}

#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_ACCELEROMETER
#error "Invalid model for current sensor"
#endif

This code comes from this link. As for the whole error message displayed, it shows:

CORRUPT HEAP: Bad tail at 0x3fced090. Expected 0xbaad5678 got 0xdd952ced

assert failed: multi_heap_free multi_heap_poisoning.c:276 (head != NULL)


Backtrace: 0x40376662:0x3fceb2e0 0x4037aee9:0x3fceb300 0x403802f1:0x3fceb320 0x4037f48d:0x3fceb450 0x40377372:0x3fceb470 0x40380349:0x3fceb490 0x4201e8e1:0x3fceb4b0 0x4201d9e1:0x3fceb4d0 0x420079d1:0x3fceb4f0 0x42005d0a:0x3fceb510 0x42006165:0x3fceb570 0x42006d8e:0x3fceb620 0x42006fcb:0x3fceb6c0 0x4200438b:0x3fceb6f0 0x420044cd:0x3fceb780 0x4200472a:0x3fceb830 0x4200b289:0x3fcebe40

Any suggestions on how I can fix this?

Hello @ianc,
it seems like a buffer overflow. Maybe your program is too big. Make sure you selected the max size of your mcu in flash size and a partition scheme that have the bigger app memory, or make your custom partition table.

@msalexms thank you for your suggestion, however, it seems as though setting the Flash Size and Partition Scheme to its maximum size does not solve the issue. Since this code is mainly based on the pre-rendered example library given by Edge Impulse, do you have any suggestions on how to make the program smaller?