You dont have javascript enabled! Please enable it!

Caso práctico: registrador de eventos en SD con Arduino UNO

Caso práctico: registrador de eventos en SD con Arduino UNO — hero

Objetivo y caso de uso

Qué construirás: Construirás un registrador de datos de eventos independiente y basado en hardware que registra activadores discretos manuales directamente en una tarjeta microSD local. Cada evento registrado se guarda de manera confiable con un ID secuencial y una marca de tiempo precisa con resolución de milisegundos.

Por qué es importante / Casos de uso

  • Conteo de inventario y almacén: Registra los conteos de artículos físicos en ubicaciones aisladas donde la infraestructura Wi-Fi o RF no está disponible.
  • Seguimiento de ciclos de máquinas: Conecta un interruptor de límite mecánico para monitorear y registrar el número exacto de veces que una máquina industrial completa un ciclo físico.
  • Registro de acceso: Interfaz con un interruptor de láminas magnético (reed switch) para registrar el momento exacto y la frecuencia de apertura de puertas, independientemente de la seguridad en red.
  • Recopilación de datos de campo sin conexión: Permite a los investigadores ambientales registrar manualmente eventos de observación durante recorridos de campo remotos.

Resultado esperado

  • Una entrada mecánica totalmente antirrebote (ej. 50ms de antirrebote por software) que evita que las pulsaciones únicas se registren como múltiples activadores falsos.
  • Persistencia de datos confiable y sin conexión en una tarjeta microSD a través de SPI con ciclos de escritura de baja latencia (<10ms).
  • Registros de eventos secuenciales y precisos formateados como CSV para un fácil procesamiento posterior.

Audiencia: Desarrolladores de sistemas embebidos e ingenieros de hardware; Nivel: Intermedio

Arquitectura/flujo: Interruptor mecánico (Entrada) → Microcontrolador (Interrupción de hardware + Lógica antirrebote) → Temporizador de milisegundos → Interfaz SPI → Tarjeta microSD (Registro CSV)

Nota educativa de validación

Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. El validador comprobó los bloques de código, la estructura del artículo, los comandos copiables y la coherencia con el catálogo de dispositivos soportados.

Evidencia de validación publicada

  • Resultado automático: PASS.
  • Estructura parseada: 3 apartados, 3 tablas y 2 bloques de código detectados antes de publicar.
  • Código comprobado: 1 Python/py_compile, 1 Arduino/arduino-cli compile.
  • Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
  • Hallazgos del informe: sin hallazgos bloqueantes.

Esta validación confirma compatibilidad sintáctica y de herramientas para el material publicado, pero no sustituye la prueba física sobre tu hardware, cableado y entorno exactos.

Nota educativa de seguridad

Este proyecto es un prototipo educativo, no un producto certificado. Antes de encender la configuración, verifique la distribución de pines de la revisión exacta de su placa ULX3S, mantenga las señales de E/S de la FPGA a 3.3 V, nunca conecte 5 V directamente a los pines de E/S, desconecte la alimentación antes de cambiar el cableado y use fuentes externas adecuadas para cargas, motores o servos mientras comparte la tierra solo cuando el cableado lo requiera.

Diagrama de bloques conceptual

Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.

Arquitectura funcional

Interruptor mecánico (Entrada)

Microcontrolador

Temporizador de milisegundos

Interfaz SPI

Tarjeta microSD (Registro CSV)

Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.

Ruta de validación

Sketch

arduino-cli compile

Upload

Prueba funcional

Resumen conceptual de las herramientas usadas para comprobar el material publicado.

Requisitos previos

Antes de comenzar este proyecto, asegúrese de tener listo lo siguiente:
* Una comprensión básica de las operaciones de Entrada/Salida de Propósito General (GPIO) de Arduino, específicamente lecturas y escrituras digitales.
* Familiaridad con el concepto de rebote de interruptores y por qué los contactos mecánicos requieren un mecanismo antirrebote por software o hardware.
* Un ordenador con Windows, macOS o Linux con una terminal de interfaz de línea de comandos.
* La arduino-cli (Interfaz de línea de comandos de Arduino) instalada y agregada al PATH de su sistema.
* Una tarjeta microSD (32GB o menor) recién formateada en FAT16 o FAT32. La biblioteca SD estándar de Arduino no admite formatos exFAT que normalmente se encuentran en tarjetas de 64GB+.

Materiales

  • Microcontrolador: Arduino UNO R3 (ATmega328P).
  • Almacenamiento: Módulo SPI para microSD (Asegúrese de que sea un módulo con un regulador de voltaje de 3.3V incorporado y un cambiador de nivel lógico, ya que el Arduino UNO R3 opera con lógica de 5V).
  • Entrada: Pulsador táctil momentáneo estándar de 4 o 2 pines.
  • Retroalimentación: LED de estado de 5mm o 3mm (cualquier color).
  • Componentes pasivos: 1x resistencia de 220 ohmios (para el LED). Utilizaremos la resistencia pull-up interna del Arduino para el pulsador.
  • Prototipado: Placa de pruebas (breadboard) y cables puente macho a macho surtidos.
  • Datos/Energía: Cable USB Tipo A a Tipo B.

Configuración/Conexión

El Arduino UNO R3 se comunica con el módulo microSD utilizando el protocolo de Interfaz Periférica Serial (SPI). El ATmega328P tiene pines SPI de hardware dedicados que deben usarse para un rendimiento óptimo.

Cableado del módulo SPI para microSD:

Pin del módulo microSDPin del Arduino UNO R3Descripción de la función
VCC5VFuente de alimentación (el módulo lo reduce a 3.3V)
GNDGNDTierra común
MISOPin 12Master In Slave Out (Datos de la SD al Arduino)
MOSIPin 11Master Out Slave In (Datos del Arduino a la SD)
SCKPin 13Serial Clock (Señal de reloj generada por el Arduino)
CSPin 4Chip Select (Indica a la tarjeta SD que escuche)

Cableado del pulsador:
* Conecte un terminal del pulsador al Pin 2 del Arduino.
* Conecte el terminal opuesto del pulsador a GND.
* Nota: No se requiere resistencia externa. Configuraremos el Pin 2 usando INPUT_PULLUP en el código, lo que conecta una resistencia interna de 20k ohmios a 5V dentro del ATmega328P. Cuando se presiona el botón, el pin lee LOW.

Cableado del LED de estado:
* Conecte la pata más larga (Ánodo) del LED de estado al Pin 8 del Arduino.
* Conecte la pata más corta (Cátodo) a un extremo de la resistencia de 220 ohmios.
* Conecte el otro extremo de la resistencia de 220 ohmios a GND.

Código validado

La siguiente sección contiene el código fuente completo requerido para el registrador de eventos, así como un script de Python complementario para analizar los datos generados.

Sketch de Arduino: SD_Event_Logger.ino

Cree un nuevo directorio llamado SD_Event_Logger y guarde el siguiente código dentro de él como SD_Event_Logger.ino.

Este código maneja el mecanismo antirrebote del botón mecánico, inicializa la comunicación SPI y agrega los datos a la tarjeta SD. Utiliza las bibliotecas estándar SD.h y SPI.h incluidas con el núcleo de Arduino.

Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.

/*
 * SD Event Data Logger
 * Target: Arduino UNO R3 (ATmega328P)
 * Objective: Log debounced button presses to a microSD card over SPI.
 */

#include <SPI.h>
#include <SD.h>

// Pin Definitions
const int chipSelect = 4;
const int buttonPin = 2;
const int ledPin = 8;

// State Variables
unsigned long eventCount = 0;
int buttonState;
int lastButtonState = HIGH; // HIGH because we use INPUT_PULLUP

// Timing Variables for Debounce
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 50 milliseconds

void setup() {
  // Initialize Serial for debugging
  Serial.begin(9600);
  while (!Serial) {
    ; // Wait for serial port to connect
  }

  // Configure Pins
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  Serial.println("Initializing SD card...");

  // Initialize SD Card
  if (!SD.begin(chipSelect)) {
    Serial.println("Critical Error: SD card initialization failed!");
    Serial.println("Check wiring, formatting (FAT16/32), and card insertion.");
    // Trap execution in an infinite loop and blink LED rapidly
    while (true) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
  }

  Serial.println("SD card initialized successfully.");

  // Optional: Write a CSV header if the file does not exist
  if (!SD.exists("events.csv")) {
    File dataFile = SD.open("events.csv", FILE_WRITE);
    if (dataFile) {
      dataFile.println("Event_ID,Uptime_ms");
      dataFile.close();
      Serial.println("Created new events.csv with headers.");
    } else {
      Serial.println("Error: Could not create events.csv");
    }
  }
}
// ... continúa para miembros en el código completo validado ...

🔒 Parte del código validado es premium. Con el pase de 7 días o la suscripción mensual podrás consultar el archivo completo validado.

/*
 * SD Event Data Logger
 * Target: Arduino UNO R3 (ATmega328P)
 * Objective: Log debounced button presses to a microSD card over SPI.
 */

#include <SPI.h>
#include <SD.h>

// Pin Definitions
const int chipSelect = 4;
const int buttonPin = 2;
const int ledPin = 8;

// State Variables
unsigned long eventCount = 0;
int buttonState;
int lastButtonState = HIGH; // HIGH because we use INPUT_PULLUP

// Timing Variables for Debounce
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 50 milliseconds

void setup() {
  // Initialize Serial for debugging
  Serial.begin(9600);
  while (!Serial) {
    ; // Wait for serial port to connect
  }

  // Configure Pins
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  Serial.println("Initializing SD card...");

  // Initialize SD Card
  if (!SD.begin(chipSelect)) {
    Serial.println("Critical Error: SD card initialization failed!");
    Serial.println("Check wiring, formatting (FAT16/32), and card insertion.");
    // Trap execution in an infinite loop and blink LED rapidly
    while (true) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
  }

  Serial.println("SD card initialized successfully.");

  // Optional: Write a CSV header if the file does not exist
  if (!SD.exists("events.csv")) {
    File dataFile = SD.open("events.csv", FILE_WRITE);
    if (dataFile) {
      dataFile.println("Event_ID,Uptime_ms");
      dataFile.close();
      Serial.println("Created new events.csv with headers.");
    } else {
      Serial.println("Error: Could not create events.csv");
    }
  }
}

void loop() {
  // Read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // Check to see if you just pressed the button
  // (i.e. the input went from HIGH to LOW), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only trigger an event if the new button state is LOW (pressed)
      if (buttonState == LOW) {
        logEventToSD();
      }
    }
  }

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;
}

void logEventToSD() {
  eventCount++;
  unsigned long currentTimestamp = millis();

  // Open the file. Note that only one file can be open at a time.
  // The filename must follow the 8.3 format (max 8 chars name, 3 chars extension)
  File dataFile = SD.open("events.csv", FILE_WRITE);

  // If the file is available, write to it:
  if (dataFile) {
    dataFile.print(eventCount);
    dataFile.print(",");
    dataFile.println(currentTimestamp);
    dataFile.close();

    // Print to the serial port too:
    Serial.print("Logged -> Event: ");
    Serial.print(eventCount);
    Serial.print(" | Time: ");
    Serial.println(currentTimestamp);

    // Visual feedback: Quick pulse on the status LED
    digitalWrite(ledPin, HIGH);
    delay(150); // Short blocking delay is acceptable here to stretch the visual flash
    digitalWrite(ledPin, LOW);
  } 
  else {
    // If the file isn't open, pop up an error:
    Serial.println("Error: Failed to open events.csv for writing.");

    // Visual feedback: Three slow flashes indicating a write error
    for (int i = 0; i < 3; i++) {
      digitalWrite(ledPin, HIGH);
      delay(300);
      digitalWrite(ledPin, LOW);
      delay(300);
    }
  }
}

Script de análisis en Python: analyze_events.py

Guarde este archivo en su ordenador como analyze_events.py. Una vez que haya recopilado datos en su tarjeta SD, inserte la tarjeta SD en su ordenador y ejecute este script contra el archivo events.csv para analizar las métricas básicas.

#!/usr/bin/env python3
"""
SD Event Logger Analysis Tool
Objective: Parse the events.csv file generated by the Arduino UNO R3 prototype
and calculate basic duration metrics.
"""

import csv
import sys

def analyze_log(filename):
    try:
        with open(filename, 'r') as file:
            reader = csv.reader(file)
            header = next(reader) # Skip the header row

            events = list(reader)

        total_events = len(events)
        print(f"--- Log Analysis for {filename} ---")
        print(f"Total discrete events logged: {total_events}")

        if total_events >= 2:
            first_time_ms = int(events[0][1])
            last_time_ms = int(events[-1][1])

            duration_ms = last_time_ms - first_time_ms
            duration_sec = duration_ms / 1000.0

            print(f"First event registered at: {first_time_ms} ms")
            print(f"Last event registered at:  {last_time_ms} ms")
            print(f"Total duration between first and last event: {duration_sec:.2f} seconds")

            if duration_sec > 0:
                frequency = total_events / duration_sec
                print(f"Average event frequency: {frequency:.2f} events/second")

    except FileNotFoundError:
        print(f"Error: Could not find '{filename}'. Ensure the path is correct.")
    except ValueError as ve:
        print(f"Error parsing data (likely malformed CSV row): {ve}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python analyze_events.py <path_to_events.csv>")
    else:
        analyze_log(sys.argv[1])

Comandos de compilación/flasheo/ejecución

Utilice la CLI de Arduino para compilar y cargar el código. Conecte su Arduino UNO R3 a su ordenador a través de USB. Identifique el puerto (ej., COM3 en Windows o /dev/ttyACM0 en Linux/macOS).

Propósito del comandoComando CLI
Actualizar índice del núcleoarduino-cli core update-index
Instalar núcleo AVRarduino-cli core install arduino:avr
Compilar sketcharduino-cli compile --fqbn arduino:avr:uno SD_Event_Logger
Subir a la placaarduino-cli upload --fqbn arduino:avr:uno --port <PORT> SD_Event_Logger
Monitor serialarduino-cli monitor --port <PORT> --config baudrate=9600

Flujo de trabajo:
1. Abra su terminal y navegue hasta el directorio padre que contiene la carpeta SD_Event_Logger.
2. Ejecute los comandos de actualización del índice y de instalación del núcleo para asegurarse de que su entorno esté listo.
3. Compile el sketch utilizando la bandera --fqbn para el UNO.
4. Reemplace <PORT> con su puerto serial real y ejecute el comando de subida.
5. Inicie inmediatamente el monitor serial para observar el proceso de inicialización.

Validación paso a paso

Siga estos puntos de control para asegurarse de que su prototipo esté funcionando correctamente.

  1. Comprobación de inicialización de la SD
    • Observación: Abra el monitor serial inmediatamente después de encender la placa.
    • Condición de aprobación: El monitor serial muestra «Initializing SD card…» seguido de «SD card initialized successfully.» El LED de estado permanece apagado.
  2. Comprobación de manejo de errores por falta de tarjeta
    • Observación: Desconecte la alimentación, expulse la tarjeta microSD, restaure la alimentación y observe el LED de estado.
    • Condición de aprobación: El monitor serial muestra «Critical Error: SD card initialization failed!» y el LED de estado parpadea rápida y continuamente.
  3. Comprobación del activador de eventos
    • Observación: Vuelva a insertar la tarjeta SD, encienda la placa y presione el pulsador una vez.
    • Condición de aprobación: El LED de estado parpadea brevemente (150ms). El monitor serial imprime Logged -> Event: 1 | Time: [timestamp].
  4. Comprobación de la lógica antirrebote
    • Observación: Mantenga presionado el pulsador, muévalo ligeramente sin soltarlo por completo, luego suéltelo.
    • Condición de aprobación: Solo se registra un evento por cada ciclo distinto de presionar y soltar. El recuento de eventos se incrementa suavemente sin saltar números (ej., saltando del 1 al 4).
  5. Comprobación de integridad de datos
    • Observación: Apague el Arduino. Retire la tarjeta SD, insértela en su ordenador y ejecute el script de análisis en Python: python analyze_events.py /ruta/a/la/SD/events.csv.
    • Condición de aprobación: El script analiza con éxito el archivo, informando el número total correcto de eventos y calculando la duración de tiempo entre la primera y la última pulsación.

Solución de problemas

SíntomaCausa probableSolución
La inicialización de la SD falla (Rápido

Encuentra este producto y/o libros sobre este tema en Amazon

Ir a Amazon

Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.

Quiz rápido

Pregunta 1: ¿Qué tipo de dispositivo se construirá según el artículo?




Pregunta 2: ¿Dónde se guardan los registros de los eventos en este dispositivo?




Pregunta 3: ¿Qué información específica se guarda con cada evento registrado?




Pregunta 4: ¿Por qué es útil este dispositivo para el conteo de inventario en almacenes aislados?




Pregunta 5: ¿Qué componente se sugiere conectar para el seguimiento de ciclos de máquinas industriales?




Pregunta 6: En el caso de registro de acceso, ¿qué tipo de sensor se menciona para registrar la apertura de puertas?




Pregunta 7: ¿Cuál es una ventaja del registro de acceso propuesto en el texto?




Pregunta 8: ¿Para qué pueden usar este dispositivo los investigadores ambientales?




Pregunta 9: ¿Qué tipo de activadores registra principalmente el dispositivo?




Pregunta 10: ¿Cuál es la resolución de la marca de tiempo que se guarda con cada evento?




Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio