DÍA 011 DE 365

Fase 1: Fundamentos de C y Lógica de Software

📖 Teoría Explícita: Arreglos y Búferes Circulares

1. ¿Qué es un Array (Arreglo)?

Un array es un bloque contiguo y fijo de memoria. En lugar de declarar Ticket_t t1, t2, t3;, declaras Ticket_t historial[5];. El compilador reserva inmediatamente el espacio exacto para 5 estructuras apiladas una tras otra. El acceso se hace mediante un índice, sabiendo que en el lenguaje C el primer elemento siempre es el índice 0.

2. El Problema del Desbordamiento (Out of Bounds)

En lenguajes de alto nivel (como Python), si intentas guardar un sexto ticket en un historial de 5, el programa lanza una excepción y se detiene. En C Bare-Metal, el procesador obedecerá ciegamente. Escribirá el sexto ticket en el índice [5], sobrescribiendo variables críticas que estén al lado en la memoria (corrupción de memoria RAM), provocando un Hard Fault catastrófico.

3. La Solución Industrial: El Búfer Circular

Como nuestro despachador operará las 24 horas, generará miles de tickets. Usaremos una técnica llamada Búfer Circular (Ring Buffer). Cuando el índice llega al final del arreglo, utilizamos aritmética modular para que el siguiente ticket sobrescriba al más antiguo (el índice 0). Matemáticamente, el índice se calcula así: $Indice = (Indice + 1) \pmod{MAX}$.

ARQUITECTURA DE BÚFER CIRCULAR (RING BUFFER) ARRAY: historial_tickets[5] Ticket Viejo Índice [0] Ticket Índice [1] Ticket Índice [2] Ticket Índice [3] Ticket Nuevo Índice [4] Puntero Actual Siguiente escritura: (4 + 1) % 5 = 0 El nuevo ticket sobrescribirá al más antiguo sin fragmentar la memoria.

⚙️ Ejercicios Prácticos: Código C Estricto

Ejercicio 1: Historial de Tickets. Implementaremos un arreglo global estático para almacenar las últimas 5 transacciones de la máquina. Utilizaremos aritmética modular para proteger el índice.


#include <stdint.h>

#define MAX_TICKETS 5

// 1. DEFINICIÓN DEL MOLDE DE DATOS (STRUCT)
typedef struct {
    uint32_t id_transaccion;
    uint32_t volumen_ml;    // Volumen en punto fijo
    uint32_t cobro_c;       // Cobro en centavos
} Ticket_t;

// 2. DECLARACIÓN DEL ARREGLO ESTÁTICO Y EL ÍNDICE
// Al usar 'static', encapsulamos este arreglo para que solo este archivo pueda tocarlo.
// El compilador reserva sizeof(Ticket_t) * 5 bytes inmediatamente en la SRAM (.BSS).
static Ticket_t historial_tickets[MAX_TICKETS];

// El índice que nos dirá dónde guardar el próximo ticket
static uint8_t indice_actual = 0;
static uint32_t contador_global_transacciones = 0;

/**
 * @brief  Guarda un nuevo ticket de despacho en el Búfer Circular.
 * @param  volumen  Volumen final despachado.
 * @param  cobro    Cobro total calculado.
 */
void Guardar_Ticket_Historial(uint32_t volumen, uint32_t cobro) {
    
    // 1. Acceso seguro al índice actual mediante los corchetes [ ]
    historial_tickets[indice_actual].id_transaccion = ++contador_global_transacciones;
    historial_tickets[indice_actual].volumen_ml = volumen;
    historial_tickets[indice_actual].cobro_c = cobro;
    
    // 2. ARITMÉTICA MODULAR (Protección de Memoria)
    // El operador módulo (%) devuelve el residuo de una división.
    // Ej: 0%5=0, 1%5=1, 2%5=2, 3%5=3, 4%5=4.
    // ¡Pero 5%5 = 0! Automáticamente nos devuelve al inicio del arreglo.
    indice_actual = (indice_actual + 1) % MAX_TICKETS;
}

/**
 * @brief  Lee un ticket del historial (Paso por referencia para eficiencia).
 * @param  posicion  La posición deseada (0 a 4).
 * @param  ptr_destino Puntero a la estructura donde se copiarán los datos.
 */
void Extraer_Ticket(uint8_t posicion, Ticket_t *ptr_destino) {
    // 1. Validación estricta para evitar Out-of-Bounds si nos mandan una posición > 4
    if (posicion >= MAX_TICKETS || ptr_destino == 0x00) {
        return; // Abortar
    }
    
    // 2. Copiamos los datos de nuestro arreglo al puntero de destino
    ptr_destino->id_transaccion = historial_tickets[posicion].id_transaccion;
    ptr_destino->volumen_ml     = historial_tickets[posicion].volumen_ml;
    ptr_destino->cobro_c        = historial_tickets[posicion].cobro_c;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Hito Logrado: Implementación de Búfer Circular sin memoria dinámica.

Tu máquina ahora puede recordar el pasado. En un entorno de gasolinera o planta despachadora, si el módulo Wi-Fi (ESP32) pierde conexión a internet durante una venta, el despacho no se pierde. Queda enclavado en este Búfer Circular. Al regresar el internet, el módulo ESP32 puede hacer un *Polling* de los últimos 5 tickets y enviarlos en bloque. Y lo más importante: lo lograste usando cero bytes de memoria dinámica, garantizando que el despachador pueda correr durante años sin requerir reinicios por agotamiento de RAM.

📝 Resumen del Día