ESP32-S3 N16R8 Tensorflow Memory Allocation Problem

#include <tensorflow/lite/micro/micro_interpreter.h>
#include <tensorflow/lite/micro/micro_mutable_op_resolver.h>
#include <tensorflow/lite/schema/schema_generated.h>
#include <esp_camera.h>
#include "model.h" // TensorFlow Lite model dosyasını buraya ekleyin
#include <driver/i2s.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

// BLE UUID'leri
#define SERVICE_UUID        "00001101-0000-1000-8000-00805F9B34FB"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

// I2S Pin Yapılandırması (MAX98357A için)
#define I2S_BCK_IO 18
#define I2S_WS_IO 17
#define I2S_DO_IO 16

// OV7670 Kamera Pin Yapılandırması
#define CAM_SCL_PIN 9    // I2C Clock
#define CAM_SDA_PIN 46   // I2C Data
#define CAM_XCLK_PIN 3   // Kamera Saat Sinyali
#define CAM_PCLK_PIN 8   // Piksel Saat
#define CAM_HREF_PIN 18  // Yatay Senkronizasyon
#define CAM_VSYNC_PIN 17 // Dikey Senkronizasyon

// OV7670 Kamera Veri Pinleri (8-bit paralel veri yolu)
#define CAM_D0_PIN 16
#define CAM_D1_PIN 15
#define CAM_D2_PIN 7
#define CAM_D3_PIN 5
#define CAM_D4_PIN 4
#define CAM_D5_PIN 41
#define CAM_D6_PIN 40
#define CAM_D7_PIN 39

#define CAM_PWDN_PIN -1   // PWDWN GND'ye bağlı olduğu için kullanılmıyor
#define CAM_RESET_PIN 21  // RESET GPIO21'e bağlı
#define TENSOR_ARENA_SIZE 120 * 1024 // Tensor Arena Boyutu

// TensorFlow Lite nesneleri
uint8_t *tensor_arena;
tflite::MicroMutableOpResolver<4> resolver;
tflite::MicroInterpreter *interpreter = nullptr;
TfLiteTensor *input_tensor = nullptr;


void *AllocatePersistentBuffer(size_t bytes) {
    void *ptr = heap_caps_malloc(bytes, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
    if (!ptr) {
        Serial.printf("PSRAM'de bellek tahsis edilemedi! Boyut: %u bytes\n", bytes);
    }
    return ptr;
}

// BLE Server nesneleri
BLEServer *pServer = nullptr;
BLECharacteristic *pCharacteristic = nullptr;

void setupCamera() {
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = CAM_D0_PIN;
    config.pin_d1 = CAM_D1_PIN;
    config.pin_d2 = CAM_D2_PIN;
    config.pin_d3 = CAM_D3_PIN;
    config.pin_d4 = CAM_D4_PIN;
    config.pin_d5 = CAM_D5_PIN;
    config.pin_d6 = CAM_D6_PIN;
    config.pin_d7 = CAM_D7_PIN;
    config.pin_xclk = CAM_XCLK_PIN;
    config.pin_pclk = CAM_PCLK_PIN;
    config.pin_vsync = CAM_VSYNC_PIN;
    config.pin_href = CAM_HREF_PIN;
    config.pin_sscb_sda = CAM_SDA_PIN;
    config.pin_sscb_scl = CAM_SCL_PIN;
    config.pin_pwdn = CAM_PWDN_PIN;
    config.pin_reset = CAM_RESET_PIN;
    config.xclk_freq_hz = 20000000; // 20 MHz
    config.pixel_format = PIXFORMAT_RGB888; // RGB888 formatı
    config.frame_size = FRAMESIZE_QVGA; // Çözünürlük: 320x240
    config.fb_count = 1;
    config.fb_location = CAMERA_FB_IN_PSRAM;

    if (esp_camera_init(&config) != ESP_OK) {
        Serial.println("Kamera başlatılamadı!");
        while (1) delay(1000);
    } else {
        Serial.println("Kamera başarıyla başlatıldı!");
    }
}

// Yeniden boyutlandırma fonksiyonu
void resizeImage(uint8_t *src, uint8_t *dst, int src_width, int src_height, int dst_width, int dst_height) {
    for (int y = 0; y < dst_height; y++) {
        for (int x = 0; x < dst_width; x++) {
            int src_x = x * src_width / dst_width;
            int src_y = y * src_height / dst_height;
            int src_index = (src_y * src_width + src_x) * 3; // RGB888 için
            int dst_index = (y * dst_width + x) * 3; // RGB888 için
            dst[dst_index] = src[src_index];       // R
            dst[dst_index + 1] = src[src_index + 1]; // G
            dst[dst_index + 2] = src[src_index + 2]; // B
        }
    }
}

// I2S Başlatma
void initI2S() {
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
        .sample_rate = 16000, // Telefonla eşleşmeli
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
        .communication_format = I2S_COMM_FORMAT_I2S_MSB,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
        .dma_buf_count = 8,
        .dma_buf_len = 64,
        .use_apll = false,
        .tx_desc_auto_clear = true,
        .fixed_mclk = 0
    };
    i2s_pin_config_t pin_config = {
        .bck_io_num = I2S_BCK_IO,
        .ws_io_num = I2S_WS_IO,
        .data_out_num = I2S_DO_IO,
        .data_in_num = I2S_PIN_NO_CHANGE
    };

    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_pin(I2S_NUM_0, &pin_config);
}

void playAudio(const char *audioData, size_t length) {
    size_t bytes_written;
    i2s_write(I2S_NUM_0, audioData, length, &bytes_written, portMAX_DELAY);
    Serial.println("Ses çalındı.");
}

// BLE Server Callbacks
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
        Serial.println("BLE cihazına bağlanıldı.");
    }

    void onDisconnect(BLEServer* pServer) {
        Serial.println("BLE cihazından bağlantı kesildi.");
    }
};

// BLE Kurulumu
void setupBLE() {
    BLEDevice::init("ESP32-TTS");
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());

    BLEService *pService = pServer->createService(SERVICE_UUID);

    pCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID,
        BLECharacteristic::PROPERTY_READ |
        BLECharacteristic::PROPERTY_WRITE |
        BLECharacteristic::PROPERTY_NOTIFY
    );

    pCharacteristic->addDescriptor(new BLE2902());
    pService->start();

    pServer->getAdvertising()->start();
    Serial.println("BLE hizmeti başlatıldı.");
}

void printMemoryUsage() {
    Serial.printf("Heap Toplam: %u bytes\n", ESP.getHeapSize());
    Serial.printf("Heap Kullanılabilir: %u bytes\n", ESP.getFreeHeap());
    Serial.printf("PSRAM Toplam: %u bytes\n", ESP.getPsramSize());
    Serial.printf("PSRAM Kullanılabilir: %u bytes\n", ESP.getFreePsram());
}


void setup() {
    Serial.begin(115200);

    // BLE Başlatma
    setupBLE();

    // I2S Başlatma
    initI2S();

    // Kamera Başlatma
    setupCamera();

        tensor_arena = (uint8_t *)heap_caps_malloc(TENSOR_ARENA_SIZE, MALLOC_CAP_SPIRAM);
    if (!tensor_arena) {
        Serial.println("Tensor Arena tahsisi başarısız!");
        printMemoryUsage();
        while (1) delay(1000);
    } else {
        Serial.println("Tensor Arena başarıyla tahsis edildi.");
    }

static tflite::MicroInterpreter static_interpreter(
    tflite::GetModel(model), resolver, tensor_arena, TENSOR_ARENA_SIZE);
interpreter = &static_interpreter;

    if (interpreter->AllocateTensors() != kTfLiteOk) {
        Serial.println("Tensor Bellek Ayırma Başarısız!");
        printMemoryUsage();
        while (1) delay(1000);
    } else {
        Serial.println("TensorFlow Bellek Başarıyla Ayırıldı.");
    }

    input_tensor = interpreter->input(0);
    Serial.println("TensorFlow Lite Başarıyla Başlatıldı!");

    // PSRAM kontrolü
    if (psramFound()) {
        Serial.println("PSRAM bulundu!");
        Serial.printf("PSRAM Toplam: %u bytes\n", ESP.getPsramSize());
        Serial.printf("PSRAM Kullanılabilir: %u bytes\n", ESP.getFreePsram());
    } else {
        Serial.println("PSRAM bulunamadı!");
        while (1) delay(1000);
    }

    printMemoryUsage();

    // TensorFlow Lite kurulum
    resolver.AddConv2D();
    resolver.AddFullyConnected();
    resolver.AddSoftmax();
    resolver.AddReshape();
}


void loop() {
    // TensorFlow Lite işlemleri
    camera_fb_t *frame = esp_camera_fb_get();
    if (!frame) {
        Serial.println("Görüntü alınamadı!");
        return;
    }

    int input_width = input_tensor->dims->data[1];
    int input_height = input_tensor->dims->data[2];
    int input_channels = input_tensor->dims->data[3];

    uint8_t *resized_image = (uint8_t *)malloc(input_width * input_height * input_channels);
    if (!resized_image) {
        Serial.println("Yeniden boyutlandırma için bellek tahsisi başarısız!");
        esp_camera_fb_return(frame);
        return;
    }

        // Görüntüyü yeniden boyutlandır
    resizeImage(frame->buf, resized_image, frame->width, frame->height, input_width, input_height);

    // Yeniden boyutlandırılmış görüntüyü giriş tensörüne kopyala
    memcpy(input_tensor->data.uint8, resized_image, input_width * input_height * input_channels);

    free(resized_image);
    esp_camera_fb_return(frame);

    if (interpreter->Invoke() != kTfLiteOk) {
        Serial.println("Model çalıştırılamadı!");
        return;
    }

    memcpy(input_tensor->data.uint8, frame->buf, input_tensor->bytes);

    if (interpreter->Invoke() != kTfLiteOk) {
        Serial.println("Model çalıştırılamadı!");
        esp_camera_fb_return(frame);
        return;
    }
    

    TfLiteTensor *output_tensor = interpreter->output(0);
    int num_classes = output_tensor->dims->data[1];
    for (int i = 0; i < num_classes; i++) {
        float confidence = output_tensor->data.f[i];
        if (confidence > 0.5) { // Güven eşiği
            String object_name = "Object " + String(i);
            Serial.printf("Sınıf %d: %.2f\n", i, confidence);

            pCharacteristic->setValue(object_name.c_str());
            pCharacteristic->notify();
            Serial.println("Nesne bilgisi gönderildi.");
        }
    }

    esp_camera_fb_return(frame);
    delay(1000); // 1 saniye bekle
}


I bought a ESP32-S3 WROOM-1 N16R8 from Temu.
I wrote code but Tensorflow can't allocate memory. Area is generating but i getting this problem.

Arduino IDE choosed Fri3d Badge 2024 (PSRAM working just this board setup, when i choose i can't run PSRAM With ESP32S3 DEV BOARD)

I tried many partition scheme.

Arduino IDE Serial Monitor:

BLE service started.
Tensor Arena has been successfully deployed.
Tensor Memory Allocation Failed! (Code 155.)
Total Heap: 352484 bytes
Heap Available: 248148 bytes
PSRAM Total: 8388608 bytes
PSRAM Available: 8180668 bytes

Not sure what your problem is, you have memory available. Maybe if you posted the complete verbose error log in code tags we could see a problem