Construye tu propio BCI con Python y Arduino

Construye tu propio BCI con Python y Arduino

13 Jun 2026 Violetta H. 10 vistas

Neurointerfaces de código abierto: cómo construir un BCI básico con Python, Arduino y machine learning para controlar aplicaciones de escritorio

13 de junio de 2026

¿Alguna vez has soñado con mover el cursor de tu computadora con solo pensarlo? No, no estoy hablando de magia ni de ciencia ficción barata. Estoy hablando de algo real, tangible y, lo mejor de todo, accesible para cualquiera con ganas de ensuciarse las manos con código y circuitos. Bienvenidos al fascinante mundo de las neurointerfaces de código abierto.

Hoy quiero llevarte de la mano por un viaje que combina neurociencia, programación y un poco de ese espíritu maker que tanto amamos. Vamos a construir un BCI básico —sí, un Brain-Computer Interface— usando herramientas que probablemente ya tienes en tu escritorio o puedes conseguir sin vender un riñón. Y todo esto, con la filosofía del código abierto como bandera.

¿Qué rayos es un BCI y por qué debería importarte?

Imagina que tu cerebro es como una orquesta sinfónica. Cada pensamiento, cada emoción, cada intención de mover un dedo genera una sinfonía eléctrica. Un BCI (Interfaz Cerebro-Computadora, para los amigos) es básicamente un micrófono súper sensible que escucha esa orquesta y traduce sus melodías en comandos que una computadora puede entender.

Hasta hace unos años, esto era territorio exclusivo de laboratorios con presupuestos de película. Pero gracias a proyectos como OpenBCI —que nació en Kickstarter y duplicó su financiación—, hoy podemos acceder a hardware de código abierto que cuesta una fracción de lo que costaban los equipos profesionales. Joel Murphy y Conor Russomanno, los creadores, tuvieron una visión clara: democratizar la neurociencia. Y vaya que lo lograron.

El corazón del asunto: el hardware

Para nuestro proyecto, necesitamos un dispositivo que pueda capturar las señales eléctricas del cerebro. Los electroencefalogramas (EEG) son la herramienta estándar, y aquí es donde entra la magia del código abierto.

El OpenBCI utiliza una placa ADC ADS1299 de Texas Instruments, que es básicamente un amplificador de señales biológicas de 8 canales. Esto significa que puede escuchar 8 "instrumentos" diferentes de tu orquesta cerebral al mismo tiempo. Luego, un microcontrolador Atmel AVR de 8 bits (compatible con el entorno Arduino IDE) o un PIC de 32 bits (con chipKIT) se encarga de digitalizar y enviar esos datos a tu computadora.

¿La mejor parte? Todos los archivos de diseño, esquemáticos y códigos fuente están disponibles en GitHub. Puedes construir tu propio dispositivo desde cero, modificarlo, mejorarlo o simplemente usarlo tal cual. Eso es lo que llamo libertad tecnológica.

Manos a la obra: nuestra configuración básica

Para este tutorial, vamos a asumir que tienes acceso a un OpenBCI o a un shield EEG compatible con Arduino. Si no es el caso, no te preocupes: puedes empezar con un simulador de señales para aprender el flujo de trabajo mientras consigues el hardware.

Lo que necesitas:

Hardware:

  • Placa OpenBCI o un Arduino Due con un shield EEG
  • Electrodos secos o de copa (los de gel funcionan mejor, pero los secos son más prácticos)
  • Cableado y protoboard (opcional, según tu setup)

Software:

  • Python 3.10+
  • Arduino IDE
  • Librerías Python: numpy, scipy, pyserial, sklearn, pyautogui
  • Librería para Arduino: OpenBCI library (disponible en GitHub)

Paso 1: Conectando el hardware y obteniendo datos

Lo primero es hacer que nuestro cerebro hable con la computadora. Conecta los electrodos siguiendo el sistema 10-20: el electrodo de referencia va en el lóbulo de la oreja o en el mastoides, y los electrodos activos los colocas en las zonas que te interesen. Para controlar aplicaciones de escritorio, la zona motora (C3, C4, Cz) es ideal porque captura la actividad relacionada con la intención de movimiento.

Sube el firmware básico a tu placa usando el Arduino IDE. El código de ejemplo de OpenBCI ya viene configurado para enviar datos en tiempo real por puerto serie a 115200 baudios. Verás algo como esto en el monitor serie:

$$$ 0, 125.3, 127.1, 124.8, 126.5, 123.9, 125.7, 124.2, 126.0

Ese primer número es el timestamp, y los siguientes son los valores de los 8 canales en microvoltios. ¡Ya tienes datos cerebrales!

Paso 2: Python al rescate

Ahora viene lo divertido. Vamos a escribir un script en Python que lea esos datos y los prepare para el machine learning.

python import serial import numpy as np from collections import deque

Configuración del puerto serie

ser = serial.Serial('COM3', 115200) # Ajusta el puerto según tu sistema buffer = deque(maxlen=256) # Ventana de 256 muestras

def leer_datos(): while True: linea = ser.readline().decode('utf-8').strip() if linea.startswith('$$$'): datos = [float(x) for x in linea.split(',')[1:]] buffer.append(datos) if len(buffer) == 256: yield np.array(buffer)

Este código crea un buffer circular que mantiene las últimas 256 muestras (aproximadamente 1 segundo de datos a 256 Hz). Cada vez que el buffer se llena, generamos una ventana de datos lista para procesar.

Paso 3: Procesamiento de señales

Las señales EEG son ruidosas. Literalmente. Tu corazón, tus músculos faciales, incluso el parpadeo generan artefactos que contaminan la señal. Necesitamos limpiarla antes de alimentar nuestro modelo de machine learning.

Aquí aplicamos tres técnicas fundamentales:

  1. Filtrado paso banda: Queremos quedarnos con las frecuencias relevantes (0.5-40 Hz). Las ondas delta, theta, alfa, beta y gamma viven en este rango.
  2. Filtro notch: Eliminamos el ruido de 50/60 Hz de la red eléctrica.
  3. Normalización: Escalamos los datos para que todas las características tengan el mismo peso.

python from scipy import signal

def procesar_senal(ventana, fs=256):

Filtro paso banda

b, a = signal.butter(4, [0.5, 40], btype='band', fs=fs)
ventana_filtrada = signal.filtfilt(b, a, ventana, axis=0)

# Filtro notch para 60 Hz
b_notch, a_notch = signal.iirnotch(60, 30, fs)
ventana_filtrada = signal.filtfilt(b_notch, a_notch, ventana_filtrada, axis=0)

# Normalización
ventana_norm = (ventana_filtrada - np.mean(ventana_filtrada)) / np.std(ventana_filtrada)

return ventana_norm

Paso 4: Extracción de características

Ahora necesitamos convertir esas señales limpias en características que nuestro modelo pueda entender. Las más comunes para BCI son:

  • Potencia en bandas de frecuencia: Calculamos la potencia de las ondas delta (0.5-4 Hz), theta (4-8 Hz), alfa (8-12 Hz), beta (12-30 Hz) y gamma (30-40 Hz) para cada canal.
  • Asimetría entre hemisferios: La diferencia de potencia entre canales izquierdos y derechos puede indicar intención de movimiento.
  • Covarianza: Las relaciones entre canales revelan patrones de conectividad funcional.

python def extraer_caracteristicas(ventana, fs=256): caracteristicas = [] for canal in range(ventana.shape[1]): frecuencias, psd = signal.welch(ventana[:, canal], fs, nperseg=128)

Potencia en bandas

    delta = np.trapz(psd[(frecuencias >= 0.5) & (frecuencias < 4)])
    theta = np.trapz(psd[(frecuencias >= 4) & (frecuencias < 8)])
    alfa = np.trapz(psd[(frecuencias >= 8) & (frecuencias < 12)])
    beta = np.trapz(psd[(frecuencias >= 12) & (frecuencias < 30)])
    gamma = np.trapz(psd[(frecuencias >= 30) & (frecuencias <= 40)])
    caracter
V
Autor del artículo Violetta H.

Comentarios

Deja un comentario