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
Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.
Ruta de validación
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 microSD | Pin del Arduino UNO R3 | Descripción de la función |
|---|---|---|
| VCC | 5V | Fuente de alimentación (el módulo lo reduce a 3.3V) |
| GND | GND | Tierra común |
| MISO | Pin 12 | Master In Slave Out (Datos de la SD al Arduino) |
| MOSI | Pin 11 | Master Out Slave In (Datos del Arduino a la SD) |
| SCK | Pin 13 | Serial Clock (Señal de reloj generada por el Arduino) |
| CS | Pin 4 | Chip 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 .../*
* 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 comando | Comando CLI |
|---|---|
| Actualizar índice del núcleo | arduino-cli core update-index |
| Instalar núcleo AVR | arduino-cli core install arduino:avr |
| Compilar sketch | arduino-cli compile --fqbn arduino:avr:uno SD_Event_Logger |
| Subir a la placa | arduino-cli upload --fqbn arduino:avr:uno --port <PORT> SD_Event_Logger |
| Monitor serial | arduino-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.
- 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.
- 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.
- 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].
- 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).
- 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.
- Observación: Apague el Arduino. Retire la tarjeta SD, insértela en su ordenador y ejecute el script de análisis en Python:
Solución de problemas
| Síntoma | Causa probable | Solución |
|---|---|---|
| La inicialización de la SD falla (Rápido |
Encuentra este producto y/o libros sobre este tema en 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.




