
Chisme del Lince AstroPi05: guarda tus datos en CSV
Tarde en la cueva del Lince. Víctor Vílchez lleva media hora mirando la consola de Thonny, donde los números del magnetómetro caen como una cascada.
—Gata, mira qué datos. Esto es ciencia de primera.
—¿Y dónde los estás guardando?
—En… la pantalla.
La Gata Montesa cierra Thonny sin decir nada. La cascada desaparece.
—¡Mis datos!
—En la ISS nadie va a hacerle una foto a la pantalla, Lince. Lo que no se guarda en un archivo no vuelve a la Tierra.
El Lince, ofendido, abre el administrador de archivos para demostrar que él sí guarda cosas. En el Escritorio hay catorce archivos llamados main.py, tres datos.csv, un datos_bueno.csv y un datos_bueno_DEFINITIVO.csv.
—Vale —admite—. A lo mejor no siempre sé dónde guardo las cosas.
—Por eso hoy el programa te va a decir dónde guarda el archivo. Y si no sabes dónde está un archivo, para la ciencia es como si no existiera.
Introducción
En AstroPi02 leímos los sensores de la Sense HAT y en AstroPi04 hicimos fotos con la cámara. Pero mirar números en la pantalla no es un experimento: hay que guardarlos.
En este chisme aprendemos a guardar un CSV Raspberry Pi con Python, exactamente como pide Mission Space Lab: junto a main.py. Y, sobre todo, aprendemos a encontrar ese archivo, a hacer nuestra primera gráfica y a entregarlo en Moodle.
Por qué este chisme
La guía de Mission Space Lab lo deja claro: el programa debe guardar los datos que recoge para que puedan volver a la Tierra y analizarse. Puede ser un archivo de datos o fotos de la cámara.
Además, en la ISS el programa no se ejecuta en «tu» Escritorio. Lo lanza automáticamente el sistema de la Astro Pi, así que no se pueden usar rutas fijas como /home/pi/Desktop. Hay que guardar todo en la carpeta de main.py, usando __file__.
Y hay un motivo muy de aula: si cada uno guarda donde le parece, luego nadie encuentra nada. El CSV Raspberry Pi siempre irá en la carpeta del chisme.
Qué es un archivo CSV
CSV significa Comma-Separated Values: valores separados por comas. Es un archivo de texto: la primera línea es la cabecera (qué hay en cada columna) y cada línea siguiente es una lectura.
time,mag_x,mag_y,mag_z,acc_x,acc_y,acc_z,gyro_x,gyro_y,gyro_z
2026-10-31T18:49:43,-2.01,-5.4,3.68,0.0584,0.1398,0.9658,-0.03444,-0.0076,-0.02133
2026-10-31T18:49:44,-5.94,-16.11,10.67,0.0611,0.1389,0.9726,-0.02955,-0.00811,-0.01966
Como es texto, lo abren Python, una hoja de cálculo como LibreOffice Calc, Excel o cualquier programa de gráficas. Por eso es el formato favorito para guardar datos de sensores.
Qué necesitamos
- La Raspberry Pi 4 B con la Sense HAT V2, con su pantalla, teclado y ratón.
- Conexión wifi en la Pi, para entregar el archivo desde su navegador.
- Thonny (viene con Raspberry Pi OS).
El simulador paso a paso
Antes de tocar la Pi, o para repasar, usad el simulador del CSV Raspberry Pi. Tiene 7 pasos en el mismo orden que la práctica real: guardar main.py en su carpeta, ejecutar, encontrar el archivo, mirarlo por dentro, ver la gráfica, leerla y entregarla.
En el paso 5 podéis cargar vuestro propio data.csv y ver su gráfica al momento. El archivo se lee solo en el navegador y no se envía a ningún sitio.

Primero: una carpeta para el chisme
- En la carpeta personal (
/home/usuarioen nuestra Pi; en la vuestra puede tener otro nombre), crea una carpetaastropiy, dentro, otra llamadaastropi05. Ahí irán todos los chismes de la serie, cada uno en su subcarpeta. Sin espacios ni tildes. - En Thonny, pega el programa y guárdalo antes de ejecutarlo como
main.pydentro de esa carpeta.
Guardar primero es importante: así Python sabe dónde está main.py, y el CSV aparecerá justo a su lado.
El código
"""
Chisme del Lince AstroPi05 - Save sensor data to a CSV file
Raspberry Pi 4 B + Sense HAT V2.
The CSV is saved next to main.py, as Mission Space Lab requires.
"""
from sense_hat import SenseHat
from pathlib import Path
from datetime import datetime
from time import sleep
import csv
# ---------------------------------------------------------------
# PART 1 - Where the file goes: ALWAYS next to main.py
# ---------------------------------------------------------------
base_folder = Path(__file__).parent.resolve()
data_file = base_folder / "data.csv"
print(f"Saving data in: {data_file}")
sense = SenseHat()
sense.set_imu_config(True, True, True)
NUMBER_OF_READINGS = 30
SECONDS_BETWEEN = 1
# ---------------------------------------------------------------
# PART 2 - THE IMPORTANT PART: write a header and one row per reading
# ---------------------------------------------------------------
with open(data_file, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["time", "mag_x", "mag_y", "mag_z",
"acc_x", "acc_y", "acc_z",
"gyro_x", "gyro_y", "gyro_z"])
for i in range(NUMBER_OF_READINGS):
mag = sense.get_compass_raw()
acc = sense.get_accelerometer_raw()
gyro = sense.get_gyroscope_raw()
writer.writerow([datetime.now().isoformat(timespec="seconds"),
round(mag["x"], 2), round(mag["y"], 2), round(mag["z"], 2),
round(acc["x"], 4), round(acc["y"], 4), round(acc["z"], 4),
round(gyro["x"], 5), round(gyro["y"], 5), round(gyro["z"], 5)])
f.flush() # write to disk now, so nothing is lost if the program stops
print(f"Reading {i + 1} of {NUMBER_OF_READINGS} saved")
sleep(SECONDS_BETWEEN)
print(f"Done! Your file is here: {data_file}")
El código, línea a línea
Parte 1: dónde va el archivo
Path(__file__)es la ruta completa demain.py..parentes su carpeta..resolve()la convierte en una ruta completa, sin atajos.base_folder / "data.csv"une la carpeta y el nombre del archivo. La barra/aquí no divide: une rutas.print(f"Saving data in: {data_file}")imprime la ruta antes de empezar. Así sabéis desde el primer segundo dónde estará el archivo.
Parte 2: escribir el CSV
with open(data_file, "w", newline="") as f:abre el archivo para escribir ("w", de write). Si ya existía, lo sustituye por uno nuevo.newline=""evita que aparezcan líneas en blanco entre filas. Al salir del bloquewith, el archivo se cierra solo.csv.writer(f)crea un «escritor» que se encarga de poner las comas por nosotros.- La primera
writer.writerow([...])escribe la cabecera: los nombres de las diez columnas. - Dentro del bucle, cada
writer.writerow([...])escribe una fila: la hora y los nueve valores. datetime.now().isoformat(timespec="seconds")escribe la hora en formato ISO 8601:2026-10-31T18:49:43. Es un formato estándar que cualquier programa entiende.round(valor, 2)redondea para no guardar quince decimales que el sensor no es capaz de medir.f.flush()obliga a escribir en el disco en ese momento. Sin él, Python acumula datos en memoria y los escribe de golpe al final. Si el programa se corta a mitad, lo ya escrito no se pierde.
Cómo probarlo
- Ejecuta
main.py. La primera línea dirá algo comoSaving data in: /home/usuario/astropi/astropi05/data.csv. - Durante los 30 segundos, mueve un poco la Pi o acércale el móvil.
- Al terminar, abre el administrador de archivos, entra en
astropi/astropi05y verásmain.pyydata.csvjuntos. - Para ver las primeras líneas sin abrir nada, escribe en el terminal:
head -5 ~/astropi/astropi05/data.csv.
Tu primera gráfica del CSV Raspberry Pi
Abre el simulador en el navegador de la Pi, ve al paso 5 y pulsa Cargar mi data.csv. Verás tres gráficas: el total del magnetómetro, del acelerómetro y del giroscopio, frente al tiempo en segundos.
Estos son los datos reales que tomamos en la terraza:

Qué estamos midiendo realmente
Las primeras lecturas mienten un poco
El magnetómetro arrancó en 6,8 µT y tardó unos 6 segundos en estabilizarse cerca de 33 µT. Esas primeras lecturas no son el campo magnético real: el sensor todavía se está asentando. Por eso, en un experimento serio, se descartan las primeras lecturas.
Se ve cuándo se movió la Pi
Hacia el segundo 11 el giroscopio pasa de 1 rad/s: alguien movió la Pi. A la vez, el total del magnetómetro baja y después se queda cerca de 46 µT. No es que cambiara el campo de la Tierra: cambiaron la posición y la orientación de la placa, y con ellas lo que tenía cerca. Medir no significa medir bien.
sleep(1) no es un segundo exacto
Mirad la columna time: después de las 18:49:48 viene 18:49:50, y después de 18:50:02 viene 18:50:04. Faltan dos segundos. Cada vuelta del bucle tarda un segundo de sleep(1) más lo que tardan en leerse los sensores y escribirse el archivo. Ese retraso se va acumulando.
En la ISS, con 10 minutos justos, eso importa. Lo resolveremos en AstroPi06 controlando el tiempo con un reloj, no contando vueltas.
Entrega tu CSV Raspberry Pi en Moodle
- Abre el navegador de la Raspberry Pi y entra en Moodle.
- Abre la tarea y pulsa Agregar entrega.
- En el selector de archivos, ve a la carpeta
astropi/astropi05y eligedata.csv. - Pulsa Guardar cambios. El estado debe cambiar a «Enviado para calificar».
Como sabéis exactamente dónde está el archivo, no hay que buscarlo por todo el disco.
Para el aula
- ¿Dónde está? Antes de ejecutar, cada grupo escribe la ruta completa donde aparecerá
data.csv. Después la comparan con la que imprime el programa. - Cuenta filas: ¿cuántas líneas tiene el archivo? ¿Por qué hay una más que lecturas?
- Cuenta segundos: ¿cuántos segundos han pasado entre la primera y la última fila? ¿Cuántos esperabais?
- Hipótesis: si dejáis la Pi completamente quieta, ¿qué esperáis ver en el giroscopio? Comprobadlo.
- Hoja de cálculo: abrid
data.csvcon LibreOffice Calc en la propia Pi y haced una gráfica demag_x.
Retos
Reto 1
Haz que funcione: guarda main.py en astropi/astropi05, ejecútalo y encuentra data.csv.
Reto 2
Cambia el programa para tomar 60 lecturas, una cada 2 segundos.
Reto 3
Añade a cada fila el total del magnetómetro, √(x² + y² + z²), con su columna mag_total en la cabecera.
Reto 4
Añade las cuatro columnas del sensor de color: r, g, b y c.
Reto 5
Descarta las 5 primeras lecturas: no las escribas en el archivo.
Reto 6
Mide cuánto tarda de verdad cada vuelta del bucle comparando las horas de la primera y la última fila.
Reto 7
Carga tu data.csv en el simulador y explica con tus palabras qué pasó en cada momento de la gráfica.
Qué hemos aprendido
- Un CSV Raspberry Pi es texto: una cabecera y una fila por lectura.
- Con
Path(__file__).parentel archivo se guarda siempre junto amain.py, como pide Mission Space Lab. - El programa imprime la ruta, así que siempre sabemos dónde está el archivo.
- Con una gráfica se ven cosas que en una tabla pasan desapercibidas: el arranque del sensor, los movimientos y los segundos que faltan.
Próximamente: AstroPi06, controlar los 10 minutos de la misión.
Para seguir investigando
Etiqueta:AIDARAC, Astro Pi, CSV, datos, ies monterroso, Mission Space Lab, montesteam, python, Raspberry Pi, Sense HAT



