Raspberry Pi Pico PIO y doble núcleo: _thread, setup1 y WS2812B
Guía de Raspberry Pi Pico PIO: máquinas de estado, onda cuadrada y WS2812B, dos núcleos con MicroPython _thread y Arduino setup1/loop1, y cambios del Pico 2.
El bloque PIO de la Raspberry Pi Pico y sus dos núcleos son las dos características que distinguen a esta pequeña placa de la mayoría de microcontroladores de su precio. El chip RP2040, el corazón de la Pico, tiene dos núcleos de procesador independientes y 8 máquinas de estado PIO. Gracias a los núcleos puedes leer sensores por un lado mientras una pantalla o una animación de LEDs sigue funcionando sin cortes por el otro. PIO, en cambio, son pequeños motores de temporización que trabajan sin depender del procesador: generan la señal con precisión de nanosegundos que piden los LEDs WS2812B, un UART extra o una onda cuadrada sin cargar la CPU.
En esta guía primero pondrás en marcha los dos núcleos con el módulo _thread de MicroPython y luego con setup1() y loop1() en el Arduino IDE. Después aprenderás cómo funciona PIO, cuántas máquinas de estado hay y qué instrucciones entienden, y escribirás dos programas reales: un generador de onda cuadrada que toca notas en un zumbador y un arcoíris con WS2812B. Al final veremos qué cambia en la Pico 2 (RP2350) y cuándo necesitas de verdad estas funciones. Si eres nuevo con la Pico, te recomiendo leer antes ¿Qué es la Raspberry Pi Pico? y ¿Qué es MicroPython?.

¿Qué son los dos núcleos y el PIO de la Raspberry Pi Pico?
El RP2040 tiene dos procesadores Cortex-M0+ idénticos llamados núcleo 0 y núcleo 1. Al arrancar tu programa solo funciona el núcleo 0; el núcleo 1 duerme hasta que lo inicias. Ambos comparten los mismos 264 KB de RAM y los mismos pines, así que pasar datos entre ellos es fácil, pero no deben escribir la misma variable a la vez. Para eso el chip tiene una pequeña cola de hardware en ambos sentidos (FIFO, 8 palabras en cada dirección) y 32 cerrojos de hardware (spinlocks). PIO es un mundo totalmente aparte: cada uno de los dos bloques PIO tiene 4 máquinas de estado, una memoria de programa compartida de 32 instrucciones y acceso directo a los pines. Una vez iniciada, la máquina de estado ejecuta su propio programa ciclo a ciclo aunque el procesador esté ocupado con otra cosa.
| Recurso | RP2040 (Pico, Pico W) | ¿Para qué sirve? |
|---|---|---|
| Núcleo de procesador | 2 x Cortex-M0+, 133 MHz (hasta 200 MHz en la documentación actual) | Ejecutar dos programas distintos realmente a la vez |
| FIFO entre núcleos | 8 x 32 bits en cada sentido | Enviar números y órdenes entre los núcleos |
| Cerrojo de hardware (spinlock) | 32 | Acceder por turnos a datos compartidos |
| Bloque PIO | 2 (PIO0, PIO1) | Quitar al procesador el trabajo de pines con tiempos críticos |
| Máquina de estado | 4 por bloque, 8 en total | Cada una ejecuta su propio programa PIO |
| Memoria de programa PIO | 32 instrucciones por bloque | La comparten las 4 máquinas de ese bloque |
| FIFO de PIO | TX 4 + RX 4 palabras por máquina (8 si se unen) | Datos entre el procesador y la máquina de estado |
El segundo núcleo en MicroPython: el módulo _thread
En MicroPython el núcleo 1 se usa con la llamada _thread.start_new_thread(función, argumentos). En la Pico esta llamada arranca la función en el segundo núcleo, mientras tu programa principal sigue en el núcleo 0. Solo puede funcionar un hilo extra a la vez, porque no hay un tercer núcleo. En el ejemplo siguiente, el núcleo 0 lee un potenciómetro en GP26 y muestra el valor, y el núcleo 1 hace parpadear el LED integrado a la velocidad que marca el potenciómetro. La espera sleep_ms() del núcleo 1 no afecta en nada al núcleo 0; con un solo núcleo necesitarías un temporizador o asyncio.
1# Pico - iki çekirdek (MicroPython _thread) / two cores (MicroPython _thread)
2import _thread
3import time
4from machine import Pin, ADC
5
6led = Pin("LED", Pin.OUT) # Pico ve Pico W dahili LED / onboard LED on Pico and Pico W
7pot = ADC(26) # GP26 = ADC0, potansiyometre / potentiometer
8
9lock = _thread.allocate_lock() # ortak veri kilidi / shared data lock
10blink_ms = 500 # çekirdek 0 yazar, çekirdek 1 okur / core 0 writes, core 1 reads
11running = True # durdurma bayrağı / stop flag
12
13
14def core1_task():
15 # Çekirdek 1: LED'i kendi hızında yakıp söndürür / Core 1: blinks the LED at its own pace
16 while running:
17 with lock:
18 period = blink_ms
19 led.toggle()
20 time.sleep_ms(period)
21 led.off()
22
23
24_thread.start_new_thread(core1_task, ()) # ikinci çekirdekte başlat / start on the second core
25
26try:
27 while True:
28 # Çekirdek 0: sensörü okur ve hızı ayarlar / Core 0: reads the sensor and sets the speed
29 raw = pot.read_u16() # 0-65535
30 with lock:
31 blink_ms = 50 + raw * 950 // 65535 # 50-1000 ms
32 print("ham / raw:", raw, "ms:", blink_ms)
33 time.sleep_ms(200)
34except KeyboardInterrupt:
35 running = False # çekirdek 1'e dur de / tell core 1 to stop
36 time.sleep_ms(1100)- El cerrojo creado con allocate_lock() garantiza que dentro de un bloque with lock: solo un núcleo toque la variable compartida.
- La bandera running le dice al núcleo 1 que salga de su bucle cuando detienes el programa con Ctrl+C; si no, el LED sigue parpadeando.
- Escribir Pin("LED") encuentra el LED integrado tanto en la Pico como en la Pico W; en la Pico W el LED está conectado al chip inalámbrico, así que Pin(25) no funciona.
- Un buen reparto es dejar en el núcleo 1 los cálculos largos, el dibujo de la pantalla o los tiempos precisos, y en el núcleo 0 el WiFi, los menús y la interacción con el usuario.
Dos núcleos en el Arduino IDE: setup1() y loop1()
El paquete para la Pico más usado en el Arduino IDE es el núcleo Raspberry Pi Pico/RP2040/RP2350 de Earle Philhower (arduino-pico). Con él, usar los dos núcleos es sorprendentemente fácil: las conocidas setup() y loop() se ejecutan en el núcleo 0; si añades setup1() y loop1() al sketch, el núcleo 1 arranca solo y ejecuta esas dos funciones. Los datos entre núcleos se envían con el objeto rp2040.fifo. El paquete oficial "Arduino Mbed OS RP2040" no admite setup1(), así que asegúrate de elegir el paquete correcto en el Gestor de tarjetas.
1// Raspberry Pi Pico - iki çekirdek (Arduino-Pico çekirdeği) / two cores (Arduino-Pico core)
2const int POT_PIN = 26; // GP26 = ADC0, potansiyometre / potentiometer
3
4// ---- Çekirdek 0 / Core 0 ----
5void setup() {
6 Serial.begin(115200);
7}
8
9void loop() {
10 int raw = analogRead(POT_PIN); // 0-1023 (varsayılan 10 bit / default 10-bit)
11 rp2040.fifo.push_nb(raw); // FIFO doluysa bekleme, değeri atla / skip the value if the FIFO is full
12 Serial.print("pot: ");
13 Serial.println(raw);
14 delay(100);
15}
16
17// ---- Çekirdek 1 / Core 1 ----
18void setup1() {
19 pinMode(LED_BUILTIN, OUTPUT);
20}
21
22void loop1() {
23 static uint32_t periodMs = 500;
24 uint32_t value;
25 while (rp2040.fifo.pop_nb(&value)) { // FIFO'yu boşalt, sonuncuyu kullan / drain the FIFO, keep the last one
26 periodMs = map(value, 0, 1023, 50, 1000);
27 }
28 digitalWrite(LED_BUILTIN, HIGH);
29 delay(periodMs); // yalnız çekirdek 1'i bekletir / only blocks core 1
30 digitalWrite(LED_BUILTIN, LOW);
31 delay(periodMs);
32}| Función | Qué hace |
|---|---|
| rp2040.fifo.push(x) | Envía un valor de 32 bits al otro núcleo; espera hueco si la cola está llena |
| rp2040.fifo.push_nb(x) | Intenta enviar sin esperar; devuelve false si la cola está llena |
| rp2040.fifo.pop() | Lee un valor del otro núcleo; espera si la cola está vacía |
| rp2040.fifo.pop_nb(&x) | Si hay un valor lo escribe en x y devuelve true; si no, devuelve false al instante |
| rp2040.fifo.available() | Devuelve cuántos valores esperan a ser leídos |
| rp2040.idleOtherCore() / resumeOtherCore() | Pausa un momento el otro núcleo y lo reanuda (por ejemplo al escribir en la flash) |
¿Qué es PIO? Cómo funciona la E/S programable
En la mayoría de los microcontroladores, los bloques de comunicación y señal como UART, SPI, I2C y PWM están fijos en el silicio; si necesitas un protocolo que no está en la lista, el procesador lo resuelve encendiendo y apagando pines uno a uno (bit-banging). Eso mantiene ocupado al procesador y la temporización se rompe cuando una interrupción se cruza. PIO (Programmable Input/Output) resuelve el problema de raíz: cada máquina de estado es un pequeño procesador con nueve instrucciones pensado solo para trabajar con pines. Cada instrucción tarda exactamente un ciclo de reloj, y se le puede añadir al final un retardo de 0 a 31 ciclos. Así sabes con exactitud cuántos nanosegundos tarda cada flanco de la señal solo contando ciclos. La velocidad de la máquina se fija dividiendo el reloj del sistema con un divisor entre 1 y 65536.
| Instrucción | Función |
|---|---|
| set(pins, v) | Escribe una constante de 0 a 31 en pines o en los registros X/Y |
| out(destino, n) | Pasa n bits del registro de desplazamiento de salida (OSR) a pines o a X/Y |
| in_(origen, n) | Introduce n bits de pines o registros en el registro de desplazamiento de entrada (ISR) |
| pull() / push() | Trae una palabra de la FIFO TX al OSR y envía la palabra del ISR a la FIFO RX |
| jmp(condición, etiqueta) | Salta según una condición (X cero, pin alto, X-- etc.) |
| wait(polaridad, origen, n) | Espera hasta que un pin o una bandera IRQ tenga el nivel deseado |
| mov(destino, origen) | Copia entre registros, invirtiendo los bits si se quiere |
| irq(n) | Envía una bandera de interrupción a la CPU o a otra máquina de estado |
| nop() y .side(v) | Instrucción vacía; side-set cambia un pin en el mismo ciclo que cualquier instrucción |
En MicroPython, los programas PIO son funciones de Python escritas con el decorador @rp2.asm_pio; la función no se llama, MicroPython la ensambla en código máquina. Después la cargas en una máquina de estado con rp2.StateMachine(n, programa, freq=..., set_base=...). En la Pico, los números 0-3 pertenecen a PIO0 y 4-7 a PIO1. El valor freq es el número de ciclos de instrucción por segundo y no puede ser menor que 1/65536 del reloj del sistema; a 125 MHz son unos 1,9 kHz y a 150 MHz unos 2,3 kHz. Si necesitas una señal más lenta, usa retardos o bucles con los contadores X/Y.
Onda cuadrada con PIO: tu primer programa de máquina de estado
En el primer ejemplo tocaremos una escala en un zumbador pasivo conectado a GP15 y al final dejaremos una onda cuadrada continua de 1 kHz. El programa tiene solo dos instrucciones: pon el pin en HIGH y espera 9 ciclos, pon el pin en LOW y espera 9 ciclos. Como cada instrucción tarda 1 ciclo, un periodo son 20 ciclos; basta con dar a la máquina de estado 20 veces la frecuencia del tono que quieres. Conecta el positivo del zumbador a GP15 y el negativo a GND. En lugar del zumbador también puedes usar un osciloscopio o un LED con una resistencia de 220 ohmios; elige la resistencia con la calculadora de resistencia para LED.
1# PIO ile kare dalga ve buzzer notaları / square wave and buzzer notes with PIO
2import time
3import rp2
4from machine import Pin
5
6
7@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
8def square():
9 wrap_target()
10 set(pins, 1) [9] # 1 + 9 = 10 döngü HIGH / 10 cycles HIGH
11 set(pins, 0) [9] # 1 + 9 = 10 döngü LOW / 10 cycles LOW
12 wrap() # başa dön, işlemci karışmaz / loop back, no CPU involved
13
14
15def tone(freq_hz):
16 # Bir periyot 20 döngü: durum makinesi frekansı = 20 x ton
17 # One period is 20 cycles: state machine frequency = 20 x tone
18 sm = rp2.StateMachine(0, square, freq=freq_hz * 20, set_base=Pin(15))
19 sm.active(1)
20 return sm
21
22
23notes = [262, 294, 330, 349, 392, 440, 494, 523] # Do-Re-Mi ... / C4 ... C5
24for n in notes:
25 sm = tone(n)
26 time.sleep_ms(300) # işlemci boşta, ses PIO'dan / CPU is idle, PIO makes the sound
27 sm.active(0)
28
29sm = tone(1000) # 1 kHz sürekli kare dalga / continuous 1 kHz square wave
30print("GP15: 1 kHz kare dalga / square wave")La fórmula es sencilla: frecuencia del tono = frecuencia de la máquina de estado / número de ciclos. Para 1000 Hz la máquina trabaja a 20 000 Hz, muy por encima del límite inferior. Si quitas los retardos y dejas solo las dos instrucciones set(), un periodo baja a 2 ciclos; con la máquina a 125 MHz obtienes una onda cuadrada de 62,5 MHz en el pin. Recuerda que el PWM por hardware puede hacer lo mismo: para un tono simple o el brillo de un LED basta con PWM. Lo que distingue a PIO es que tú decides la forma exacta de la señal; con pocas líneas puedes generar pulsos de ancho variable, un número exacto de pulsos o salidas que reaccionan a una entrada.
Controlar LEDs WS2812B (NeoPixel) con PIO

Los LEDs WS2812B esperan un pulso de unos 1,25 microsegundos por bit; si el bit es 1 o 0 se deduce de cuánto tiempo se mantiene el pulso en HIGH. Es un caso de manual para PIO. El programa siguiente se basa en el ejemplo oficial de MicroPython de Raspberry Pi: la máquina de estado funciona a 8 MHz y cada bit dura exactamente 10 ciclos, de modo que se envían 800 000 bits por segundo. Gracias a autopull, la máquina toma un nuevo color de la FIFO cada 24 bits; el procesador solo deja el array en la FIFO con sm.put(). Cambia el número de LEDs según tu tira; para saber cómo funciona el WS2812B y su orden de colores, consulta la guía de WS2812B NeoPixel.
| Pin WS2812B | Pin de la Pico | Nota |
|---|---|---|
| DIN (entrada de datos) | GP16 (pin físico 21) | Una resistencia de 330 ohmios en serie protege la señal |
| 5V / VCC | VBUS (pin 40) | 5 V del USB; con muchos LEDs usa una fuente externa de 5 V |
| GND | GND (p. ej. pin 38) | El GND de la fuente externa también debe ir aquí |
1# PIO ile WS2812B (NeoPixel) gökkuşağı / WS2812B (NeoPixel) rainbow with PIO
2import array
3import time
4import rp2
5from machine import Pin
6
7NUM_LEDS = 24 # halka ya da şeritteki LED sayısı / LEDs in the ring or strip
8LED_PIN = 16 # DIN bağlantısı / DIN connection
9BRIGHTNESS = 0.2 # 0.0-1.0, akımı düşük tutar / keeps current low
10
11
12@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT,
13 autopull=True, pull_thresh=24)
14def ws2812():
15 T1 = 2
16 T2 = 5
17 T3 = 3
18 wrap_target()
19 label("bitloop")
20 out(x, 1) .side(0) [T3 - 1] # 1 biti al, hat LOW / take 1 bit, line LOW
21 jmp(not_x, "do_zero") .side(1) [T1 - 1] # hat HIGH / line HIGH
22 jmp("bitloop") .side(1) [T2 - 1] # bit 1: uzun HIGH / long HIGH
23 label("do_zero")
24 nop() .side(0) [T2 - 1] # bit 0: kısa HIGH / short HIGH
25 wrap()
26
27
28# Bit başına 10 döngü x 8 MHz = 800 kHz / 10 cycles per bit x 8 MHz = 800 kHz
29sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(LED_PIN))
30sm.active(1)
31
32pixels = array.array("I", [0] * NUM_LEDS)
33
34
35def set_pixel(i, r, g, b):
36 r = int(r * BRIGHTNESS)
37 g = int(g * BRIGHTNESS)
38 b = int(b * BRIGHTNESS)
39 pixels[i] = (g << 16) | (r << 8) | b # WS2812B sırası GRB / byte order is GRB
40
41
42def show():
43 sm.put(pixels, 8) # 24 biti sola hizala / left-align the 24 bits
44
45
46def wheel(pos):
47 # 0-255 arası değeri renge çevir / turn 0-255 into a colour
48 pos %= 255
49 if pos < 85:
50 return 255 - pos * 3, pos * 3, 0
51 if pos < 170:
52 pos -= 85
53 return 0, 255 - pos * 3, pos * 3
54 pos -= 170
55 return pos * 3, 0, 255 - pos * 3
56
57
58step = 0
59while True:
60 for i in range(NUM_LEDS):
61 set_pixel(i, *wheel(i * 255 // NUM_LEDS + step))
62 show()
63 step = (step + 3) % 255
64 time.sleep_ms(30) # kare arası bekleme, aynı zamanda reset / frame gap, also the reset timeSigamos el programa línea a línea. out(x, 1) pasa un bit del OSR al registro X mientras side-set mantiene la línea en LOW (3 ciclos). Luego la línea pasa a HIGH y se comprueba X (2 ciclos). Si el bit es 1, la línea sigue en HIGH 5 ciclos más; si es 0, la línea baja a LOW y la máquina espera 5 ciclos. Los dos caminos suman 10 ciclos, es decir 1,25 µs. pull_thresh=24 indica a la máquina que use solo 24 bits de cada palabra; por eso en Python el color se desplaza a la izquierda (sm.put(pixels, 8)). El orden de colores es GRB, no RGB; si el rojo y el verde salen cambiados, ese es el motivo. Como 24 LEDs en blanco total pueden consumir hasta 1,4 A, en el ejemplo el brillo se limita al 20 %.
¿Qué cambia con la Pico 2 (RP2350)?
La Raspberry Pi Pico 2 es la nueva generación, con el mismo tamaño y la misma distribución de pines pero con un chip RP2350 dentro. Sigue teniendo dos núcleos, pero ahora puedes elegir al arrancar entre dos núcleos Arm Cortex-M33 o dos núcleos RISC-V Hazard3. Todo el código de este artículo funciona sin cambios en la Pico 2: _thread es igual en MicroPython, y en el núcleo Arduino-Pico setup1()/loop1() y rp2040.fifo mantienen sus nombres. En la parte PIO se añade un tercer bloque, así que hay 12 máquinas de estado (0-11 en MicroPython) y algunas opciones de instrucción nuevas.
| Característica | Pico (RP2040) | Pico 2 (RP2350) |
|---|---|---|
| Núcleos | 2 x Cortex-M0+ | 2 x Cortex-M33 o 2 x Hazard3 RISC-V |
| Velocidad de reloj | 133 MHz | 150 MHz |
| RAM | 264 KB | 520 KB |
| Flash en placa | 2 MB | 4 MB |
| PIO | 2 bloques, 8 máquinas de estado | 3 bloques, 12 máquinas de estado |
| Coma flotante | Por software (rutinas rápidas en ROM) | FPU por hardware (precisión simple) + coprocesador de doble precisión |
| Seguridad | Ninguna | TrustZone, arranque seguro, 8 KB OTP |
| Archivo MicroPython | RPI_PICO (.uf2) | RPI_PICO2 (.uf2) |
En la práctica, la diferencia más notable de la Pico 2 es la velocidad: gracias a la FPU por hardware, los cálculos con mucha coma flotante (filtros, fusión de sensores, procesado de audio) van varias veces más rápido, y el doble de RAM deja sitio para búferes de pantalla grandes. Solo debes cuidar de grabar el archivo UF2 correcto para la placa; el de la Pico no funciona en la Pico 2. Las primeras versiones del RP2350 tenían un fallo de hardware conocido (E9) con entradas que usan el pull-down interno, corregido en la revisión A4; usar una resistencia externa al conectar pulsadores es la opción segura en ambos casos.
¿Cuándo necesitas dos núcleos y cuándo PIO?
| Lo que necesitas | Mejor opción | ¿Por qué? |
|---|---|---|
| Brillo de LED, servo, tono simple | PWM por hardware | Bloque listo, una línea de código |
| Algunos sensores + pantalla + pulsador | Un núcleo, millis() o asyncio | No hace falta más complejidad |
| Animación fluida durante cálculos largos | Dos núcleos | El cálculo en el núcleo 1 no congela la pantalla |
| Medición continua junto al WiFi | Dos núcleos | Los retrasos de red no alteran el intervalo de muestreo |
| WS2812B, UART extra, emisor IR, encoder | PIO | Precisión de nanosegundos, CPU libre |
| Vídeo VGA/DVI, audio I2S, señales muy rápidas | PIO + DMA | Velocidades de datos que la CPU no alcanzaría |
En resumen: piensa en el segundo núcleo cuando las tareas chocan en el software, y en PIO cuando los pines necesitan precisión por debajo del microsegundo. La mayoría de proyectos de hobby no necesitan ninguno de los dos; pero si un día tu animación WS2812B empieza a dar tirones durante una petición WiFi o la placa se queda sin UART, la solución ya te espera dentro de la Pico.
Ideas de proyectos con PIO y doble núcleo en la Pico
- Anillo de LEDs que reacciona a la música: el núcleo 1 procesa las muestras del micrófono, PIO controla el anillo WS2812B y el núcleo 0 atiende los pulsadores.
- Generador de pulsos de ocho canales: cada máquina de estado genera una onda cuadrada de distinta frecuencia para drivers de motores paso a paso o bancos de prueba.
- Registrador de datos sin huecos: el núcleo 1 lee el ADC cada 10 ms y el núcleo 0 envía los datos por WiFi; aunque la red vaya lenta, no se pierde ninguna muestra.
- Puertos serie extra: abre un tercer y un cuarto UART con PIO y conecta a la vez un GPS y un módulo Bluetooth.
- Contador de encoder rotativo: PIO cuenta los pulsos del encoder sin perder ninguno; el procesador solo lee el resultado.
- Luz nocturna que respira: deja los fundidos suaves con PWM al núcleo 1 y el sensor de luz al núcleo 0.
Errores frecuentes y cómo solucionarlos
| Síntoma | Causa | Solución |
|---|---|---|
| La placa no responde tras detenerla | El bucle del núcleo 1 sigue funcionando | Usa una bandera de parada; si hace falta, desconecta y conecta el USB |
| start_new_thread falla la segunda vez | La Pico solo admite un hilo extra | No inicies otro antes de que termine el anterior |
| Las variables toman a veces valores absurdos | Los dos núcleos escriben datos compartidos sin cerrojo | Usa allocate_lock() o la FIFO |
| StateMachine lanza ValueError | freq es menor que reloj del sistema / 65536 | Sube la frecuencia y frena con retardos |
| PIOASMError: delay too large | Los bits de side-set reducen el campo de retardo | Divide el retardo o añade un nop() |
| Rojo y verde cambiados en el WS2812B | El orden de colores es GRB | Usa el formato (g << 16) | (r << 8) | b |
| setup1() nunca se ejecuta | Está elegido el paquete Arduino Mbed RP2040 | Instala el paquete Raspberry Pi Pico/RP2040 de Earle Philhower |
Los dos núcleos y PIO son lo que convierte a la Pico de un simple parpadeador de LEDs en un sistema embebido serio, pero todo se apoya en la misma base: conocer bien los pines, los tiempos y los LEDs. En la app BlueGrays encontrarás proyectos con Raspberry Pi Pico como encender LEDs, luces secuenciales, el efecto coche fantástico, una máquina de estados con pulsador y el efecto respiración con PWM, cada uno con esquema y código MicroPython paso a paso, listos para añadirles las técnicas de este artículo.
Preguntas frecuentes
¿Qué es PIO en la Raspberry Pi Pico?
PIO (E/S programable) son pequeñas máquinas de estado de los chips RP2040 y RP2350 que funcionan independientemente del procesador. Cada una ejecuta con precisión de ciclo un programa escrito en un lenguaje sencillo de nueve instrucciones. Se encarga de tareas con tiempos críticos como LEDs WS2812B, UART extra, emisión IR o lectura de encoders sin ocupar la CPU.
¿Cuántos núcleos tiene la Raspberry Pi Pico?
El chip RP2040 de la Pico y la Pico W tiene dos núcleos Cortex-M0+. El RP2350 de la Pico 2 también tiene dos, y al arrancar se puede elegir entre núcleos Cortex-M33 o Hazard3 RISC-V. Al iniciar el programa solo funciona el núcleo 0; el núcleo 1 lo arrancas tú.
¿Cuántas máquinas de estado PIO tiene la Pico?
El RP2040 tiene dos bloques PIO con 4 máquinas de estado cada uno, es decir, 8 en total. La memoria de programa de 32 instrucciones de cada bloque se comparte entre sus máquinas. El RP2350 de la Pico 2 tiene tres bloques PIO, o sea, 12 máquinas de estado.
¿Se pueden usar los dos núcleos de la Pico con MicroPython?
Sí. En la Pico, una función iniciada con _thread.start_new_thread() se ejecuta en el segundo núcleo. Solo puede haber un hilo extra a la vez y los datos compartidos deben protegerse con un cerrojo de _thread.allocate_lock(). Como el soporte multinúcleo de MicroPython sigue siendo experimental, conviene evitar operaciones pesadas de memoria en el hilo extra.
¿Cómo uso el segundo núcleo de la Pico en el Arduino IDE?
Tras instalar el paquete Raspberry Pi Pico/RP2040/RP2350 de Earle Philhower, basta con añadir las funciones setup1() y loop1() al sketch; el núcleo 1 las ejecuta automáticamente. Los valores de 32 bits se pasan entre núcleos con rp2040.fifo.push() y rp2040.fifo.pop(). El paquete RP2040 de Arduino basado en Mbed no ofrece esta función.
¿Es obligatorio usar PIO para los LEDs WS2812B?
No. El módulo neopixel integrado de MicroPython y la librería Adafruit NeoPixel de Arduino funcionan sin problemas en la Pico. La ventaja de escribirlo tú con PIO es que el procesador queda libre durante el envío y puedes aplicar la misma técnica a otros protocolos con tiempos críticos.
Proyectos para hacer después de leer esto
Ver todos los proyectos
Parpadeo LED Integrado Raspberry Pi Pico (Pico y Pico W)
¡El proyecto de apertura de la serie Raspberry Pi Pico! Hacemos parpadear el LED verde integrado para verificar que la placa funciona — un experimento clásico "Hello World". SIN componentes externos, solo Pico y cable USB. El código está escrito en MicroPython (el lenguaje oficialmente respaldado por la Raspberry Pi Foundation). Aprende la clase machine.Pin, el modo Pin.OUT, los métodos led.on()/off() y time.sleep() en Thonny IDE. Sigue cada cambio en vivo en l

Encendido de un LED externo con la Raspberry Pi Pico (placa de pruebas)
El siguiente paso tras el LED integrado de Pico: conectar un LED externo a la placa de pruebas y controlarlo a través del pin GP14. Con este proyecto aprenderás a utilizar cualquier pin GPIO de uso general del Pico como salida, la polaridad del LED (patilla larga = ánodo/+, patilla corta = cátodo/–) y por qué es imprescindible utilizar una resistencia limitadora de corriente (220 Ω). Si no colocas la resistencia, el LED recibirá una corriente excesiva y podría quemarse. El circuito es muy sencil

Simulador de Semáforo Raspberry Pi Pico (3 LEDs Secuenciales)
Simulamos un semáforo real con LEDs rojo, amarillo y verde. Verde 4 seg "pase", amarillo 1,5 seg "prepárese", rojo 3 seg "detenga" y rojo+amarillo 1 seg "arranque" (patrón europeo). Aprende definición de función, lógica de máquina de estados y sincronización multi-GPIO. Circuito simple: 3 LEDs en GP11/GP12/GP13.

Raspberry Pi Pico LED Secuencial (6 LEDs)
¡Animación clásica de LED secuencial con Pico — versión 6 LEDs! 6 LEDs se encienden de izquierda a derecha secuencialmente. Aprende lista Python, comprensión de listas ([Pin(p, Pin.OUT) for p in LED_PINS]), bucle for con control de pines y enumerate(). 6 LEDs en GP9-GP14, cada uno con resistencia 220Ω. Código muy limpio: en lugar de definir 6 LEDs uno por uno, usamos una lista — puedes añadir LED hasta agotar los GPIO libres y utilizables, cada uno con su propia resistencia. Para controlar 100 L

Raspberry Pi Pico Knight Rider LED Escáner (6 LED Ida-Vuelta)
¡Efecto escáner LED "Knight Rider" clásico con Pico! 6 LEDs van de izquierda a derecha, luego de derecha a izquierda, indefinidamente. Aprende reversed() y dos bucles for separados para patrón ida-vuelta.

Semáforo Raspberry Pi Pico con selector de 4 modos (máquina de estados)
¡4 modos diferentes para el semáforo con un solo botón! Cada vez que se pulsa el botón, cambia el modo: Ciclo normal (rojo → ámbar → verde en ese orden), Solo rojo (señal de parada), Ámbar intermitente (atención/modo nocturno), Apagado (mantenimiento). Conceptos: máquina de estados (la variable mode determina qué comportamiento se ejecutará), ciclo de modos por módulo ((mode + 1) % 4 → 0→1→2→3→0, ciclo infinito), sincronización sin bloqueo (las fases de los LED se

Raspberry Pi Pico Botón Debounce: IRQ vs Software Polling
¿Una pulsación y el código cuenta 3-4? ¡Es contact bounce! Compara 2 métodos de conteo en Serial: polling RAW (captura bounce, cuenta mal) vs IRQ + software debounce (preciso). Aprende física del bounce, software debounce, Pin.irq() interrupt, IRQ_FALLING trigger, ISR handlers, seguridad de variables globales en ISR.

Raspberry Pi Pico PWM LED Fade (Efecto Respiración)
¡El LED ya no solo parpadea — respira! Con el PWM (modulación por ancho de pulso) del Raspberry Pi Pico, el brillo sube y baja lentamente. Aprende la clase machine.PWM, duty_u16() (brillo de 16 bits 0–65535), la frecuencia PWM, bucles range() y salida tipo analógica. Base para mezcla de color RGB, control de motores, servos y buzzer.
Más artículos
App BlueGrays
Monta este circuito paso a paso en tu teléfono
Esquema, código y lista de piezas en una sola pantalla. Más de 200 proyectos de Arduino, ESP32 y Pico listos para montar.
Escanea con tu teléfono
Apunta la cámara al código y se abrirá la tienda de apps de tu teléfono.
o ábrela en la tienda

