Introducción a la Arquitectura de Memoria
El ESP32 es un SoC (System on a Chip) diseñado para aplicaciones de Internet de las Cosas (IoT) y sistemas embebidos. Como evolución del ESP8266, incrementa significativamente la capacidad de procesamiento y añade conectividad Bluetooth. Su arquitectura de memoria está cuidadosamente diseñada para optimizar el rendimiento en aplicaciones mecatrónicas.
Tipos de Memoria en el ESP32
La gestión eficiente de memoria es fundamental en mecatrónica e IoT, donde los recursos suelen ser limitados. El ESP32 incorpora tres tipos principales de memoria, cada una con características específicas para diferentes aplicaciones:
Tipos de Memoria del ESP32
SRAM
Static Random-Access Memory - Volátil y rápida
Flash
Memoria no volátil para código y datos persistentes
PSRAM
Pseudo-Static RAM para expansión de memoria
Mapas de Memoria y Especificaciones
El ESP32 utiliza un mapa de memoria complejo que permite optimizar el acceso a diferentes tipos de memoria según las necesidades de cada aplicación mecatrónica.
Distribución de Memoria
- DRAM (Data RAM) 328 KB
- IRAM (Instruction RAM) 192 KB
- ROM 448 KB
- RTC Fast Memory 8 KB
- RTC Slow Memory 8 KB
- Flash SPI 4-16 MB
- PSRAM SPI 0-16 MB
- Cache 32 KB I/D
Gestión de Memoria con Atributos
El ESP32 permite usar directivas especiales para controlar dónde se almacenan las variables y funciones. Esto es crucial para optimizar el rendimiento en aplicaciones mecatrónicas.
// Demostración de gestión de memoria en ESP32
#include
#include
#include
// Variables en diferentes tipos de memoria
DRAM_ATTR int contador_dram = 0; // Variable en DRAM
IRAM_ATTR int contador_iram = 0; // Variable en IRAM
RTC_DATA_ATTR int contador_rtc = 0; // Variable en RTC (persiste en deep sleep)
// Arrays grandes en PSRAM (si está disponible)
MALLOC_CAP_SPIRAM int* array_psram = nullptr;
// Función crítica en IRAM (para interrupciones)
IRAM_ATTR void funcion_critica() {
contador_iram++;
// Esta función se ejecuta desde IRAM para máximo rendimiento
digitalWrite(2, !digitalRead(2));
}
// Buffer estático en DRAM
DRAM_ATTR static uint8_t buffer_sensor[1024];
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=== ESP32 Memory Management Demo ===");
// Mostrar información de memoria disponible
mostrarInfoMemoria();
// Intentar asignar memoria en PSRAM
if (esp_spiram_is_initialized()) {
Serial.println("PSRAM detectada - Asignando memoria...");
array_psram = (int*)heap_caps_malloc(10000 * sizeof(int), MALLOC_CAP_SPIRAM);
if (array_psram != nullptr) {
Serial.println("Memoria PSRAM asignada exitosamente");
// Llenar array con datos de prueba
for (int i = 0; i < 10000; i++) {
array_psram[i] = i * 2;
}
} else {
Serial.println("Error: No se pudo asignar memoria PSRAM");
}
} else {
Serial.println("PSRAM no disponible en este ESP32");
}
// Configurar pin 2 como salida para la función crítica
pinMode(2, OUTPUT);
// Configurar timer para función crítica cada 1ms
hw_timer_t* timer = timerBegin(0, 80, true); // 80MHz/80 = 1MHz
timerAttachInterrupt(timer, &funcion_critica, true);
timerAlarmWrite(timer, 1000, true); // 1000 us = 1ms
timerAlarmEnable(timer);
Serial.println("Sistema inicializado - Monitor de memoria activo");
}
void loop() {
contador_dram++;
contador_rtc++; // Se mantiene en deep sleep
// Mostrar estadísticas cada 5 segundos
if (contador_dram % 50 == 0) {
Serial.println("\n--- Estadísticas de Memoria ---");
Serial.printf("Contador DRAM: %d\n", contador_dram);
Serial.printf("Contador IRAM: %d\n", contador_iram);
Serial.printf("Contador RTC: %d\n", contador_rtc);
mostrarInfoMemoria();
// Test de velocidad de acceso
testVelocidadMemoria();
}
// Simular procesamiento de sensor
procesarDatosSensor();
delay(100);
}
void mostrarInfoMemoria() {
Serial.println("\n--- Información de Memoria ---");
Serial.printf("Free Heap: %d bytes\n", esp_get_free_heap_size());
Serial.printf("Min Free Heap: %d bytes\n", esp_get_minimum_free_heap_size());
Serial.printf("Free Internal: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
Serial.printf("Free SPIRAM: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
Serial.printf("Free DMA: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_DMA));
}
void testVelocidadMemoria() {
const int TEST_SIZE = 1000;
unsigned long tiempo_inicio, tiempo_fin;
// Test DRAM
tiempo_inicio = micros();
for (int i = 0; i < TEST_SIZE; i++) {
buffer_sensor[i] = i % 256;
}
tiempo_fin = micros();
Serial.printf("Velocidad DRAM: %lu us para %d bytes\n",
tiempo_fin - tiempo_inicio, TEST_SIZE);
// Test PSRAM (si está disponible)
if (array_psram != nullptr) {
tiempo_inicio = micros();
for (int i = 0; i < TEST_SIZE; i++) {
array_psram[i] = i;
}
tiempo_fin = micros();
Serial.printf("Velocidad PSRAM: %lu us para %d enteros\n",
tiempo_fin - tiempo_inicio, TEST_SIZE);
}
}
void procesarDatosSensor() {
// Simular lectura de múltiples sensores
static uint16_t indice_buffer = 0;
// Almacenar datos en buffer DRAM
buffer_sensor[indice_buffer] = analogRead(A0) >> 4; // 8 bits
indice_buffer = (indice_buffer + 1) % sizeof(buffer_sensor);
// Si tenemos PSRAM, almacenar histórico
if (array_psram != nullptr) {
static int indice_historico = 0;
array_psram[indice_historico] = millis();
indice_historico = (indice_historico + 1) % 10000;
}
}
Ejercicios Prácticos
Objetivo: Crear un monitor que muestre el uso de SRAM en tiempo real.
Materiales:
- ESP32 DevKit
- Monitor serie
- Arduino IDE
Conceptos: Heap memory, stack, fragmentación
Objetivo: Implementar sistema de almacenamiento persistente usando SPIFFS.
Aplicación: Guardar configuraciones de sensores y logs de eventos
Conceptos: SPIFFS, NVS, particiones de memoria Flash
Objetivo: Utilizar PSRAM para procesamiento de grandes volúmenes de datos de sensores.
Aplicación: Buffer circular para datos de acelerómetro con FFT
Análisis: Comparativa de rendimiento SRAM vs PSRAM
Aplicaciones de Gestión de Memoria en Mecatrónica
Estrategias de Memoria para Sistemas Mecatrónicos
La gestión inteligente de memoria en el ESP32 permite implementar sistemas mecatrónicos complejos y eficientes:
SRAM (Runtime):
- Variables de control PID
- Buffers de comunicación
- Estados de máquina en tiempo real
Flash (Persistente):
- Configuraciones de sistema
- Logs de eventos y calibraciones
- Firmware y aplicaciones