Contenido
- FASE 1. Diseño del sistema
- FASE 2. Montaje del hardware
- FASE 3. Programación de cada Arduino
- FASE 4. Comprobación de los Arduinos en la Raspberry Pi
- FASE 5. Preparación del entorno Python en Raspberry Pi
- FASE 6. Programa receptor en Raspberry Pi
- FASE 7. Ejecución del programa
- FASE 8. Validación del sistema
- FASE 9. Posibles errores y soluciones
- Entrega del trabajo
1. Introducción
En esta práctica vais a construir un pequeño sistema de adquisición de datos distribuido. En lugar de trabajar con un único sensor conectado a un solo dispositivo, vais a montar una arquitectura formada por varios Arduinos, cada uno con uno o varios sensores, y una Raspberry Pi que actuará como centro de recepción y almacenamiento.
El objetivo no es solo «leer sensores», sino comprender cómo se organiza un sistema real donde varios nodos capturan información y un equipo central la recibe, la procesa y la guarda para su análisis posterior.
Este tipo de arquitectura se parece mucho a sistemas reales de monitorización, automatización, IoT, domótica o control industrial.
2. Objetivos de la práctica
Al finalizar la práctica, debéis ser capaces de:
- Conectar sensores a varios Arduinos.
- Leer datos de sensores desde Arduino.
- Enviar esos datos por comunicación serie a través de USB.
- Conectar varios Arduinos a una Raspberry Pi.
- Identificar los puertos serie de cada Arduino en Linux.
- Crear en la Raspberry Pi un programa en Python que reciba datos desde varios Arduinos.
- Guardar los datos recibidos en archivos CSV o JSON.
- Documentar correctamente el montaje, el código y el funcionamiento del sistema.
3. Descripción general del sistema
La arquitectura general de la práctica será la siguiente:
[Sensores] → [Arduino 1] ┐
[Sensores] → [Arduino 2] ├── USB ──> [Raspberry Pi] ──> [CSV / JSON]
[Sensores] → [Arduino 3] ┘
Cada Arduino actuará como nodo de captura de datos.
La Raspberry Pi actuará como:
- receptor central,
- sistema de almacenamiento,
- y punto de análisis de los datos.
4. Material necesario
Cada grupo deberá disponer, como mínimo, de:
- 1 Raspberry Pi con Raspberry Pi OS.
- 2 o más placas Arduino.
- Sensores asignados por el profesor.
- Cables USB para conectar los Arduinos a la Raspberry Pi.
- Protoboard y cables Dupont.
- Resistencias si el sensor lo necesita.
- Tarjeta microSD con sistema operativo funcional en la Raspberry Pi.
- Acceso al terminal de la Raspberry Pi.
Material opcional recomendable
- Hub USB alimentado, si se van a usar muchos Arduinos.
- Teclado, ratón y monitor para la Raspberry Pi, o acceso por SSH.
5. Requisitos mínimos del proyecto
El sistema desarrollado debe cumplir, al menos, con los siguientes requisitos:
- Usar varios Arduinos conectados a la Raspberry Pi.
- Cada Arduino debe leer al menos un sensor.
- Cada Arduino debe enviar sus datos por puerto serie.
- La Raspberry Pi debe recibir datos de todos los Arduinos.
- Los datos deben guardarse en un archivo CSV o JSON.
- Cada dato debe quedar identificado con:
- fecha y hora,
- identificador del Arduino,
- nombre del sensor,
- valor recibido.
- El grupo debe entregar documentación técnica y capturas.
FASE 1. Diseño del sistema
6.1. Planificación previa
Antes de montar nada, debéis diseñar vuestro sistema.
Debéis definir:
- Cuántos Arduinos vais a usar.
- Qué sensor o sensores irá conectado a cada Arduino.
- Qué tipo de dato enviará cada uno.
- Qué formato de mensaje vais a usar.
- Si guardaréis los datos en CSV, JSON o ambos.
Ejemplo de reparto
- Arduino 1: temperatura y humedad
- Arduino 2: luz
- Arduino 3: movimiento
6.2. Formato común de los datos
Todos los grupos debéis usar un formato de texto común para enviar los datos desde Arduino a la Raspberry Pi.
Formato recomendado
arduino=A1;sensor=temp;valor=23.4
arduino=A1;sensor=hum;valor=41.2
arduino=A2;sensor=luz;valor=820
arduino=A3;sensor=mov;valor=1
Reglas del formato
- Cada línea representa una lectura.
- Cada dato estará compuesto por pares
clave=valor. - Los pares estarán separados por
;. - Cada línea terminará con salto de línea.
Este formato es muy sencillo de leer y muy fácil de procesar en Python.
FASE 2. Montaje del hardware
7. Conexión de sensores a los Arduinos
Cada grupo conectará los sensores asignados a sus placas Arduino.
Recomendaciones
- Revisad siempre el voltaje de trabajo del sensor.
- Comprobad si necesita resistencia pull-up o pull-down.
- Verificad qué pin usaréis: digital o analógico.
- Etiquetad en vuestra documentación qué sensor está conectado a qué pin.
Ejemplo de tabla de montaje
| Arduino | Sensor | Tipo de pin | Pin usado |
|---|---|---|---|
| A1 | Sensor de temperatura | Analógico | A0 |
| A1 | Sensor de humedad | Analógico | A1 |
| A2 | LDR | Analógico | A0 |
| A3 | PIR | Digital | D2 |
8. Conexión de los Arduinos a la Raspberry Pi
Una vez que cada Arduino funcione correctamente con su sensor, debéis conectarlos a la Raspberry Pi mediante USB.
Importante
- Cada Arduino se conectará con su propio cable USB.
- Si no hay suficientes puertos USB en la Raspberry, usad un hub USB.
- Si usáis varios Arduinos, es recomendable que el hub sea alimentado externamente.
FASE 3. Programación de cada Arduino
9. Objetivo del código Arduino
Cada Arduino debe:
- Inicializar su comunicación serie.
- Leer el valor del sensor.
- Construir un mensaje con el formato definido.
- Enviar ese mensaje por el puerto serie.
- Repetir el proceso cada cierto tiempo.
10. Estructura general del programa Arduino
Ejemplo genérico
const String ID_ARDUINO = "A1";
void setup() {
Serial.begin(9600);
}
void loop() {
int valorSensor = analogRead(A0);
Serial.print("arduino=");
Serial.print(ID_ARDUINO);
Serial.print(";sensor=luz;valor=");
Serial.println(valorSensor);
delay(2000);
}
11. Recomendaciones para el código Arduino
- No enviéis datos demasiado rápido.
- Para empezar, una lectura cada 1 o 2 segundos es suficiente.
- No mezcléis mensajes de depuración con mensajes de datos.
- Usad siempre el mismo formato.
Mal ejemplo
Serial.println("Leyendo sensor...");
Serial.println(valor);
Buen ejemplo
Serial.println("arduino=A1;sensor=luz;valor=830");
FASE 4. Comprobación de los Arduinos en la Raspberry Pi
12. Detectar los puertos serie
Cuando conectéis los Arduinos a la Raspberry, debéis comprobar qué puertos se han creado.
Comandos útiles
ls /dev/ttyACM*
ls /dev/ttyUSB*
También podéis usar:
dmesg | tail
Posible resultado
/dev/ttyACM0
/dev/ttyACM1
/dev/ttyACM2
Cada uno suele corresponder a un Arduino distinto.
13. Identificación más estable de los dispositivos
En algunos casos, el nombre /dev/ttyACM0 puede cambiar al reiniciar o reconectar.
Para identificar los puertos de forma más estable, podéis usar:
ls /dev/serial/by-id/
Esto mostrará nombres más largos, pero normalmente más estables.
14. Prueba manual del puerto serie
Antes de escribir el programa final en Python, comprobad que la Raspberry recibe datos.
Podéis usar herramientas como:
cat /dev/ttyACM0
O instalar herramientas como screen o minicom.
FASE 5. Preparación del entorno Python en Raspberry Pi
15. Instalar Python y pyserial
Normalmente Python ya estará instalado. Debéis instalar la librería pyserial.
sudo apt update
sudo apt install python3-pip -y
pip3 install pyserial
Si el sistema os da problemas con permisos, podéis usar entorno virtual o instalar el paquete del sistema si está disponible.
FASE 6. Programa receptor en Raspberry Pi
16. Objetivo del programa Python
El script en Python debe:
- abrir varios puertos serie,
- escuchar los datos de varios Arduinos,
- interpretar cada línea recibida,
- añadir fecha y hora,
- guardar los datos en CSV o JSON.
17. Formato final recomendado de almacenamiento
Opción CSV
timestamp,arduino,sensor,valor
2026-03-10 10:15:00,A1,temp,23.4
2026-03-10 10:15:01,A1,hum,41.2
2026-03-10 10:15:03,A2,luz,820
Opción JSON (un registro por línea)
{"timestamp":"2026-03-10 10:15:00","arduino":"A1","sensor":"temp","valor":"23.4"}
{"timestamp":"2026-03-10 10:15:01","arduino":"A1","sensor":"hum","valor":"41.2"}
{"timestamp":"2026-03-10 10:15:03","arduino":"A2","sensor":"luz","valor":"820"}
18. Script Python de ejemplo para varios Arduinos y CSV
import serial
import threading
import csv
import os
from datetime import datetime
PUERTOS = [
"/dev/ttyACM0",
"/dev/ttyACM1",
"/dev/ttyACM2"
]
BAUDIOS = 9600
ARCHIVO_CSV = "datos_sensores.csv"
CAMPOS = ["timestamp", "arduino", "sensor", "valor"]
lock_csv = threading.Lock()
def parsear_linea(linea):
datos = {}
partes = linea.strip().split(";")
for parte in partes:
if "=" in parte:
clave, valor = parte.split("=", 1)
datos[clave.strip()] = valor.strip()
return datos
def inicializar_csv():
if not os.path.exists(ARCHIVO_CSV) or os.path.getsize(ARCHIVO_CSV) == 0:
with open(ARCHIVO_CSV, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=CAMPOS)
writer.writeheader()
def guardar_csv(registro):
with lock_csv:
with open(ARCHIVO_CSV, "a", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=CAMPOS)
writer.writerow(registro)
def escuchar_puerto(puerto):
try:
ser = serial.Serial(puerto, BAUDIOS, timeout=1)
print(f"Escuchando {puerto}")
while True:
linea = ser.readline().decode("utf-8", errors="ignore").strip()
if linea:
print(f"{puerto} -> {linea}")
datos = parsear_linea(linea)
if "arduino" in datos and "sensor" in datos and "valor" in datos:
registro = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"arduino": datos["arduino"],
"sensor": datos["sensor"],
"valor": datos["valor"]
}
guardar_csv(registro)
except Exception as e:
print(f"Error en {puerto}: {e}")
def main():
inicializar_csv()
hilos = []
for puerto in PUERTOS:
hilo = threading.Thread(target=escuchar_puerto, args=(puerto,), daemon=True)
hilo.start()
hilos.append(hilo)
for hilo in hilos:
hilo.join()
if __name__ == "__main__":
main()
19. Script Python de ejemplo para guardar en JSON
import serial
import threading
import json
from datetime import datetime
PUERTOS = [
"/dev/ttyACM0",
"/dev/ttyACM1"
]
BAUDIOS = 9600
ARCHIVO_JSON = "datos_sensores.jsonl"
lock_json = threading.Lock()
def parsear_linea(linea):
datos = {}
partes = linea.strip().split(";")
for parte in partes:
if "=" in parte:
clave, valor = parte.split("=", 1)
datos[clave.strip()] = valor.strip()
return datos
def guardar_json(registro):
with lock_json:
with open(ARCHIVO_JSON, "a", encoding="utf-8") as f:
f.write(json.dumps(registro, ensure_ascii=False) + "\n")
def escuchar_puerto(puerto):
try:
ser = serial.Serial(puerto, BAUDIOS, timeout=1)
print(f"Escuchando {puerto}")
while True:
linea = ser.readline().decode("utf-8", errors="ignore").strip()
if linea:
print(f"{puerto} -> {linea}")
datos = parsear_linea(linea)
if "arduino" in datos and "sensor" in datos and "valor" in datos:
registro = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"arduino": datos["arduino"],
"sensor": datos["sensor"],
"valor": datos["valor"]
}
guardar_json(registro)
except Exception as e:
print(f"Error en {puerto}: {e}")
def main():
hilos = []
for puerto in PUERTOS:
hilo = threading.Thread(target=escuchar_puerto, args=(puerto,), daemon=True)
hilo.start()
hilos.append(hilo)
for hilo in hilos:
hilo.join()
if __name__ == "__main__":
main()
FASE 7. Ejecución del programa
20. Guardar y ejecutar el script
Guardad el script con un nombre como:
nano receptor_sensores.py
Pegad el código, guardadlo y ejecutadlo:
python3 receptor_sensores.py
Si todo funciona, deberíais ver en pantalla líneas como estas:
/dev/ttyACM0 -> arduino=A1;sensor=temp;valor=23.7
/dev/ttyACM1 -> arduino=A2;sensor=luz;valor=801
/dev/ttyACM2 -> arduino=A3;sensor=mov;valor=1
21. Comprobar los archivos generados
Para CSV
cat datos_sensores.csv
Para JSON
cat datos_sensores.jsonl
FASE 8. Validación del sistema
22. Qué debéis comprobar
Debéis verificar que:
- todos los Arduinos envían datos,
- la Raspberry recibe los mensajes,
- los datos se guardan correctamente,
- cada línea incluye el identificador del Arduino,
- los archivos se actualizan conforme llegan nuevas lecturas.
23. Pruebas recomendadas
Realizad pruebas como estas:
- Desconectar un Arduino y comprobar qué ocurre.
- Volver a conectarlo.
- Modificar el valor del sensor (por ejemplo, tapar una LDR o mover un PIR).
- Verificar que el cambio se refleja en el CSV o JSON.
- Comprobar si el sistema sigue funcionando con varios Arduinos enviando datos al mismo tiempo.
FASE 9. Posibles errores y soluciones
24. Error: no aparece /dev/ttyACM0
Posibles causas
- El cable USB no funciona.
- El Arduino no está correctamente conectado.
- El sistema no ha detectado la placa.
Soluciones
- Probar otro cable.
- Ejecutar
dmesg | tail. - Probar con otro puerto USB.
25. Error: permiso denegado al abrir el puerto serie
Solución posible
Añadir el usuario al grupo adecuado:
sudo usermod -a -G dialout $USER
Después debéis cerrar sesión y volver a entrar.
26. Error: el script recibe líneas vacías o mal formadas
Posibles causas
- El Arduino está enviando texto extra.
- La velocidad en baudios no coincide.
- El formato del mensaje no es correcto.
Soluciones
- Revisar
Serial.begin(9600)en Arduino. - Comprobar que Python usa la misma velocidad.
- Revisar el formato
clave=valor;clave=valor.
Entrega del trabajo
27. Qué debéis entregar
Cada grupo debe entregar:
- Código de todos los Arduinos.
- Código Python de la Raspberry Pi.
- Archivo README o memoria técnica.
- Esquema del sistema.
- Fotografías del montaje.
- Capturas del terminal mostrando la recepción de datos.
- Ejemplo del CSV o JSON generado.
- Explicación de problemas encontrados y cómo los resolvisteis.
28. Estructura recomendada de carpetas
practica-raspberry-arduinos/
├── README.md
├── arduino/
│ ├── arduino_1/
│ │ └── arduino_1.ino
│ ├── arduino_2/
│ │ └── arduino_2.ino
│ └── arduino_3/
│ └── arduino_3.ino
├── raspberry/
│ ├── receptor_csv.py
│ └── receptor_json.py
├── evidencias/
│ ├── foto_montaje_1.jpg
│ ├── terminal_recepcion.png
│ └── csv_generado.png
└── datos_ejemplo/
├── datos_sensores.csv
└── datos_sensores.jsonl
Conclusión
Esta práctica os permitirá trabajar con una arquitectura completa de adquisición de datos usando varios microcontroladores y un sistema Linux central.
No se trata solo de conectar cables y leer números, sino de entender cómo diseñar un sistema modular, organizado y ampliable. Ese enfoque es mucho más valioso que hacer una sola lectura aislada en un monitor serie.
Cuando el sistema funcione, habréis construido una pequeña red de sensores con almacenamiento centralizado, algo muy cercano a muchos proyectos reales de automatización, IoT y monitorización.







