Raspberry Pi Pico PIO e doppio core: _thread, setup1 e WS2812B
Guida a Raspberry Pi Pico PIO: macchine a stati, onda quadra ed esempio WS2812B, i due core con MicroPython _thread e Arduino setup1/loop1, novità del Pico 2.
Il blocco PIO del Raspberry Pi Pico e i suoi due core sono le due caratteristiche che distinguono questa piccola scheda dalla maggior parte dei microcontrollori della stessa fascia di prezzo. Il chip RP2040, il cuore del Pico, ha due core di processore separati e 8 macchine a stati PIO. Grazie ai core puoi leggere i sensori da una parte mentre un display o un'animazione di LED continua a girare senza scatti dall'altra. Le PIO invece sono minuscoli motori di temporizzazione che lavorano indipendentemente dal processore: generano il segnale preciso al nanosecondo richiesto dai LED WS2812B, una UART in più o un'onda quadra senza caricare la CPU.
In questa guida avvierai prima i due core con il modulo _thread di MicroPython e poi con setup1() e loop1() nell'Arduino IDE. Poi imparerai come funziona la PIO, quante macchine a stati ci sono e quali istruzioni capiscono, e scriverai due programmi reali: un generatore di onda quadra che suona note su un buzzer e un arcobaleno di WS2812B. Alla fine vedremo cosa cambia con il Pico 2 (RP2350) e quando servono davvero queste funzioni. Se il Pico è nuovo per te, ti consiglio di leggere prima Che cos'è il Raspberry Pi Pico? e Che cos'è MicroPython?.

Cosa sono i due core e la PIO del Raspberry Pi Pico?
L'RP2040 ha due processori Cortex-M0+ identici chiamati core 0 e core 1. All'avvio del programma lavora solo il core 0; il core 1 dorme finché non lo avvii tu. I due core condividono gli stessi 264 KB di RAM e gli stessi pin, quindi scambiarsi dati è facile, ma non devono scrivere la stessa variabile nello stesso istante. Per questo il chip ha una piccola coda hardware bidirezionale (FIFO, 8 parole per direzione) e 32 lock hardware (spinlock). La PIO è un mondo completamente separato: ciascuno dei due blocchi PIO ha 4 macchine a stati, una memoria di programma condivisa da 32 istruzioni e accesso diretto ai pin. Una volta avviata, una macchina a stati esegue il proprio programma ciclo dopo ciclo anche mentre il processore è occupato con altro.
| Risorsa | RP2040 (Pico, Pico W) | A cosa serve? |
|---|---|---|
| Core del processore | 2 x Cortex-M0+, 133 MHz (fino a 200 MHz nella documentazione attuale) | Eseguire due programmi distinti davvero nello stesso momento |
| FIFO tra i core | 8 x 32 bit per direzione | Inviare numeri e comandi tra i core |
| Lock hardware (spinlock) | 32 | Accedere a turno ai dati condivisi |
| Blocco PIO | 2 (PIO0, PIO1) | Togliere al processore il lavoro sui pin con tempi critici |
| Macchina a stati | 4 per blocco, 8 in totale | Ognuna esegue il proprio programma PIO |
| Memoria di programma PIO | 32 istruzioni per blocco | Condivisa dalle 4 macchine del blocco |
| FIFO della PIO | TX 4 + RX 4 parole per macchina (8 se unite) | Dati tra il processore e la macchina a stati |
Il secondo core in MicroPython: il modulo _thread
In MicroPython il core 1 si usa con la chiamata _thread.start_new_thread(funzione, argomenti). Sul Pico questa chiamata avvia la funzione sul secondo core, mentre il programma principale continua sul core 0. Può girare un solo thread aggiuntivo alla volta, perché non esiste un terzo core. Nell'esempio seguente il core 0 legge un potenziometro su GP26 e stampa il valore, mentre il core 1 fa lampeggiare il LED integrato alla velocità impostata dal potenziometro. L'attesa sleep_ms() del core 1 non influisce per niente sul core 0; con un solo core servirebbero un timer 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)- Il lock creato con allocate_lock() garantisce che dentro un blocco with lock: un solo core tocchi la variabile condivisa.
- Il flag running dice al core 1 di uscire dal ciclo quando fermi il programma con Ctrl+C; altrimenti il LED continua a lampeggiare.
- Scrivere Pin("LED") trova il LED integrato sia sul Pico sia sul Pico W; sul Pico W il LED è collegato al chip wireless, quindi Pin(25) non funziona.
- Una buona divisione è lasciare al core 1 i calcoli lunghi, il disegno del display o le temporizzazioni precise, e al core 0 il WiFi, i menu e l'interazione con l'utente.
Due core nell'Arduino IDE: setup1() e loop1()
Il pacchetto per Pico più usato nell'Arduino IDE è il core Raspberry Pi Pico/RP2040/RP2350 di Earle Philhower (arduino-pico). Con questo, usare entrambi i core è sorprendentemente facile: le solite setup() e loop() girano sul core 0; se aggiungi setup1() e loop1() allo sketch, il core 1 parte da solo ed esegue queste due funzioni. I dati tra i core si inviano con l'oggetto rp2040.fifo. Il pacchetto ufficiale "Arduino Mbed OS RP2040" non supporta setup1(), quindi assicurati di scegliere il pacchetto giusto nel Gestore schede.
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}| Funzione | Cosa fa |
|---|---|
| rp2040.fifo.push(x) | Invia un valore a 32 bit all'altro core; aspetta spazio se la coda è piena |
| rp2040.fifo.push_nb(x) | Prova a inviare senza attendere; restituisce false se la coda è piena |
| rp2040.fifo.pop() | Legge un valore dall'altro core; aspetta se la coda è vuota |
| rp2040.fifo.pop_nb(&x) | Se c'è un valore lo scrive in x e restituisce true, altrimenti restituisce subito false |
| rp2040.fifo.available() | Indica quanti valori aspettano di essere letti |
| rp2040.idleOtherCore() / resumeOtherCore() | Mette in pausa per poco l'altro core e lo riavvia (per esempio durante la scrittura in flash) |
Cos'è la PIO? Come funziona l'I/O programmabile
Nella maggior parte dei microcontrollori i blocchi di comunicazione e di segnale come UART, SPI, I2C e PWM sono fissi nel silicio; se ti serve un protocollo che non è nella lista, il processore lo gestisce accendendo e spegnendo i pin uno per uno (bit-banging). Questo tiene occupato il processore e la temporizzazione salta appena si mette in mezzo un interrupt. La PIO (Programmable Input/Output) risolve il problema alla radice: ogni macchina a stati è un minuscolo processore con nove istruzioni pensato solo per lavorare sui pin. Ogni istruzione dura esattamente un ciclo di clock e alla fine si può aggiungere un ritardo da 0 a 31 cicli. Così sai con precisione, contando i cicli, dopo quanti nanosecondi arriva ogni fronte del segnale. La velocità della macchina si imposta dividendo il clock di sistema con un divisore tra 1 e 65536.
| Istruzione | Funzione |
|---|---|
| set(pins, v) | Scrive una costante da 0 a 31 sui pin o nei registri X/Y |
| out(dest, n) | Sposta n bit dal registro a scorrimento di uscita (OSR) ai pin o a X/Y |
| in_(src, n) | Porta n bit dai pin o dai registri nel registro a scorrimento di ingresso (ISR) |
| pull() / push() | Preleva una parola dalla FIFO TX nell'OSR, spinge la parola dell'ISR nella FIFO RX |
| jmp(cond, label) | Salta in base a una condizione (X zero, pin alto, X-- ecc.) |
| wait(polarità, src, n) | Aspetta che un pin o un flag IRQ raggiunga il livello voluto |
| mov(dest, src) | Copia tra registri, invertendo i bit se richiesto |
| irq(n) | Invia un flag di interrupt alla CPU o a un'altra macchina a stati |
| nop() e .side(v) | Istruzione vuota; il side-set cambia un pin nello stesso ciclo di qualsiasi istruzione |
In MicroPython i programmi PIO sono funzioni Python scritte con il decoratore @rp2.asm_pio; la funzione non viene chiamata, MicroPython la assembla in codice macchina. Poi la carichi in una macchina a stati con rp2.StateMachine(n, programma, freq=..., set_base=...). Sul Pico i numeri 0-3 appartengono a PIO0 e 4-7 a PIO1. Il valore freq è il numero di cicli di istruzione al secondo e non può scendere sotto 1/65536 del clock di sistema; a 125 MHz sono circa 1,9 kHz, a 150 MHz circa 2,3 kHz. Se ti serve un segnale più lento, usa ritardi o cicli con i contatori X/Y.
Onda quadra con la PIO: il tuo primo programma a macchina a stati
Nel primo esempio suoneremo una scala su un buzzer passivo collegato a GP15 e alla fine lasceremo attiva un'onda quadra continua a 1 kHz. Il programma ha solo due istruzioni: porta il pin a HIGH e aspetta 9 cicli, portalo a LOW e aspetta 9 cicli. Poiché ogni istruzione dura 1 ciclo, un periodo è di 20 cicli: basta dare alla macchina a stati 20 volte la frequenza del tono che vuoi. Collega il positivo del buzzer a GP15 e il negativo a GND. Al posto del buzzer puoi usare un oscilloscopio o un LED con una resistenza da 220 ohm; scegli la resistenza con il calcolatore di resistenza per 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 formula è semplice: frequenza del tono = frequenza della macchina a stati / numero di cicli. Per 1000 Hz la macchina lavora a 20.000 Hz, ben sopra il limite inferiore. Se togli i ritardi e lasci solo le due istruzioni set(), un periodo scende a 2 cicli; con la macchina a 125 MHz ottieni un'onda quadra di 62,5 MHz sul pin. Ricorda che il PWM hardware può fare lo stesso lavoro: per un tono semplice o la luminosità di un LED basta il PWM. Ciò che distingue la PIO è che decidi tu la forma esatta del segnale; con poche righe generi impulsi a larghezza variabile, un numero preciso di impulsi o uscite che reagiscono a un ingresso.
Pilotare LED WS2812B (NeoPixel) con la PIO

I LED WS2812B si aspettano un impulso di circa 1,25 microsecondi per bit; se il bit è 1 o 0 lo si capisce da quanto tempo l'impulso resta HIGH. È un caso da manuale per la PIO. Il programma seguente si basa sull'esempio ufficiale MicroPython di Raspberry Pi: la macchina a stati lavora a 8 MHz e ogni bit dura esattamente 10 cicli, quindi vengono inviati 800.000 bit al secondo. Grazie ad autopull la macchina preleva un nuovo colore dalla FIFO ogni 24 bit; il processore si limita a depositare l'array nella FIFO con sm.put(). Cambia il numero di LED in base alla tua striscia; per il funzionamento del WS2812B e l'ordine dei colori consulta la guida ai WS2812B NeoPixel.
| Pin WS2812B | Pin del Pico | Nota |
|---|---|---|
| DIN (ingresso dati) | GP16 (pin fisico 21) | Una resistenza da 330 ohm in serie protegge il segnale |
| 5V / VCC | VBUS (pin 40) | 5 V dall'USB; con molti LED usa un alimentatore esterno da 5 V |
| GND | GND (es. pin 38) | Anche il GND dell'alimentatore esterno va collegato qui |
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 timeSeguiamo il programma riga per riga. out(x, 1) prende un bit dall'OSR e lo mette nel registro X mentre il side-set tiene la linea LOW (3 cicli). Poi la linea va HIGH e si controlla X (2 cicli). Se il bit è 1, la linea resta HIGH per altri 5 cicli; se è 0, la linea torna LOW e la macchina aspetta 5 cicli. Entrambi i percorsi fanno 10 cicli, cioè 1,25 µs. pull_thresh=24 dice alla macchina di usare solo 24 bit di ogni parola; per questo in Python il colore viene spostato a sinistra (sm.put(pixels, 8)). L'ordine dei colori è GRB, non RGB; se rosso e verde sono scambiati, il motivo è questo. Poiché 24 LED in bianco pieno possono assorbire fino a 1,4 A, nell'esempio la luminosità è limitata al 20%.
Cosa cambia con il Pico 2 (RP2350)?
Il Raspberry Pi Pico 2 è la nuova generazione, con le stesse dimensioni e la stessa piedinatura ma con un chip RP2350. Ha sempre due core, ma questa volta puoi scegliere all'avvio tra due core Arm Cortex-M33 o due core RISC-V Hazard3. Tutto il codice di questo articolo funziona senza modifiche sul Pico 2: _thread è identico in MicroPython e nel core Arduino-Pico setup1()/loop1() e rp2040.fifo mantengono gli stessi nomi. Sul lato PIO si aggiunge un terzo blocco, quindi le macchine a stati diventano 12 (0-11 in MicroPython), più alcune nuove opzioni di istruzione.
| Caratteristica | Pico (RP2040) | Pico 2 (RP2350) |
|---|---|---|
| Core | 2 x Cortex-M0+ | 2 x Cortex-M33 o 2 x Hazard3 RISC-V |
| Frequenza di clock | 133 MHz | 150 MHz |
| RAM | 264 KB | 520 KB |
| Flash sulla scheda | 2 MB | 4 MB |
| PIO | 2 blocchi, 8 macchine a stati | 3 blocchi, 12 macchine a stati |
| Virgola mobile | Software (routine veloci in ROM) | FPU hardware (singola precisione) + coprocessore a doppia precisione |
| Sicurezza | Nessuna | TrustZone, avvio sicuro, 8 KB di OTP |
| File MicroPython | RPI_PICO (.uf2) | RPI_PICO2 (.uf2) |
In pratica la differenza più evidente del Pico 2 è la velocità: grazie alla FPU hardware i calcoli con molti numeri in virgola mobile (filtri, fusione di sensori, elaborazione audio) diventano molto più rapidi, e il doppio della RAM lascia spazio a grandi buffer per il display. L'unica attenzione è caricare il file UF2 giusto per la scheda; quello del Pico non funziona sul Pico 2. Le prime versioni dell'RP2350 avevano un difetto hardware noto (E9) con gli ingressi che usano il pull-down interno, corretto nella revisione A4; usare una resistenza esterna per i pulsanti resta comunque la scelta sicura.
Quando servono due core e quando la PIO?
| Cosa ti serve | Soluzione migliore | Perché? |
|---|---|---|
| Luminosità LED, servo, tono semplice | PWM hardware | Blocco pronto, una riga di codice |
| Qualche sensore + display + pulsante | Un core, millis() o asyncio | Non serve altra complessità |
| Animazione fluida durante calcoli lunghi | Due core | Il calcolo sul core 1 non blocca il display |
| Misura continua insieme al WiFi | Due core | I ritardi di rete non disturbano l'intervallo di misura |
| WS2812B, UART in più, trasmettitore IR, encoder | PIO | Precisione al nanosecondo, CPU libera |
| Video VGA/DVI, audio I2S, segnali molto veloci | PIO + DMA | Velocità di dati che la CPU non reggerebbe |
In breve: pensa al secondo core quando i compiti si ostacolano nel software, e alla PIO quando i pin richiedono una precisione sotto il microsecondo. La maggior parte dei progetti hobbistici non ha bisogno di nessuno dei due; ma se un giorno la tua animazione WS2812B inizia a scattare durante una richiesta WiFi o la scheda resta senza UART, la soluzione ti aspetta già dentro il Pico.
Idee di progetti con PIO e doppio core del Pico
- Anello LED che reagisce alla musica: il core 1 elabora i campioni del microfono, la PIO pilota l'anello WS2812B e il core 0 ascolta i pulsanti.
- Generatore di impulsi a otto canali: ogni macchina a stati produce un'onda quadra a una frequenza diversa per driver di motori passo-passo o banchi di prova.
- Data logger senza buchi: il core 1 legge l'ADC ogni 10 ms mentre il core 0 invia i dati via WiFi; anche se la rete rallenta non si perde nessun campione.
- Porte seriali extra: apri una terza e una quarta UART con la PIO e collega insieme un GPS e un modulo Bluetooth.
- Contatore per encoder rotativo: la PIO conta gli impulsi dell'encoder senza perderne nemmeno uno; il processore legge solo il risultato.
- Luce notturna che respira: affida le dissolvenze morbide in PWM al core 1 e il sensore di luce al core 0.
Errori comuni e soluzioni
| Sintomo | Causa | Soluzione |
|---|---|---|
| La scheda non risponde dopo lo stop | Il ciclo sul core 1 è ancora attivo | Usa un flag di arresto; se serve scollega e ricollega l'USB |
| start_new_thread fallisce la seconda volta | Il Pico consente un solo thread aggiuntivo | Non avviarne un altro prima che finisca il precedente |
| Le variabili a volte hanno valori assurdi | I due core scrivono dati condivisi senza lock | Usa allocate_lock() o la FIFO |
| StateMachine genera ValueError | freq è sotto clock di sistema / 65536 | Aumenta la frequenza e rallenta con i ritardi |
| PIOASMError: delay too large | I bit di side-set riducono il campo del ritardo | Dividi il ritardo o aggiungi un nop() |
| Rosso e verde invertiti sui WS2812B | L'ordine dei colori è GRB | Usa il formato (g << 16) | (r << 8) | b |
| setup1() non parte mai | È selezionato il pacchetto Arduino Mbed RP2040 | Installa il pacchetto Raspberry Pi Pico/RP2040 di Earle Philhower |
I due core e la PIO trasformano il Pico da semplice lampeggiatore di LED in un vero sistema embedded, ma tutto poggia sulla stessa base: conoscere bene pin, temporizzazioni e LED. Nell'app BlueGrays trovi progetti con il Raspberry Pi Pico come accendere un LED, le luci in sequenza, l'effetto Supercar, una macchina a stati con pulsante e l'effetto respiro in PWM, ognuno con schema e codice MicroPython passo passo, pronti per aggiungere le tecniche di questo articolo.
Domande frequenti
Cos'è la PIO del Raspberry Pi Pico?
La PIO (I/O programmabile) è un insieme di piccole macchine a stati dei chip RP2040 e RP2350 che lavorano indipendentemente dal processore. Ognuna esegue con precisione al ciclo un programma scritto in un linguaggio semplice di nove istruzioni. Si occupa di compiti con tempi critici come LED WS2812B, UART aggiuntive, trasmissione IR o lettura di encoder senza tenere occupata la CPU.
Quanti core ha il Raspberry Pi Pico?
Il chip RP2040 del Pico e del Pico W ha due core Cortex-M0+. Anche l'RP2350 del Pico 2 ha due core e all'avvio si può scegliere tra core Cortex-M33 o Hazard3 RISC-V. Quando il programma parte lavora solo il core 0; il core 1 lo avvii tu.
Quante macchine a stati PIO ha il Pico?
L'RP2040 ha due blocchi PIO con 4 macchine a stati ciascuno, quindi 8 in totale. La memoria di programma da 32 istruzioni di ogni blocco è condivisa tra le sue macchine. L'RP2350 del Pico 2 ha tre blocchi PIO, cioè 12 macchine a stati.
MicroPython può usare entrambi i core del Pico?
Sì. Sul Pico una funzione avviata con _thread.start_new_thread() gira sul secondo core. Può esistere un solo thread aggiuntivo alla volta e i dati condivisi vanno protetti con un lock creato da _thread.allocate_lock(). Poiché il supporto multicore in MicroPython è ancora sperimentale, conviene evitare operazioni pesanti sulla memoria nel thread aggiuntivo.
Come si usa il secondo core del Pico nell'Arduino IDE?
Dopo aver installato il pacchetto Raspberry Pi Pico/RP2040/RP2350 di Earle Philhower basta aggiungere allo sketch le funzioni setup1() e loop1(); il core 1 le esegue automaticamente. I valori a 32 bit passano tra i core con rp2040.fifo.push() e rp2040.fifo.pop(). Il pacchetto RP2040 di Arduino basato su Mbed non offre questa funzione.
Per i LED WS2812B è obbligatorio usare la PIO?
No. Il modulo neopixel integrato in MicroPython e la libreria Adafruit NeoPixel in Arduino funzionano senza problemi sul Pico. Il vantaggio di scriverla da te con la PIO è che il processore resta libero durante l'invio e puoi applicare la stessa tecnica ad altri protocolli con tempi critici.
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
Lampeggio LED Integrato Raspberry Pi Pico (Pico e Pico W)
Il progetto di apertura della serie Raspberry Pi Pico! Facciamo lampeggiare il LED verde integrato per verificare che la scheda funzioni — un classico primo esperimento "Hello World". NESSUN componente esterno, solo Pico e cavo USB. Il codice è scritto in MicroPython (il linguaggio ufficialmente supportato dalla Raspberry Pi Foundation). Impara la classe machine.Pin, la modalità Pin.OUT, i metodi led.on()/off() e time.sleep() in Thonny IDE. Segui ogni commutazi

Accensione di un LED esterno con Raspberry Pi Pico (breadboard)
Il passo successivo dopo il LED integrato di Pico: collegare un LED esterno alla breadboard e controllarlo tramite il pin GP14. Con questo progetto imparerai come utilizzare qualsiasi pin GPIO generico del Pico come uscita, la polarità del LED (stelo lungo = anodo/+, stelo corto = catodo/–) e perché è indispensabile un resistore di limitazione della corrente (220 Ω). Se non inserisci il resistore, l’LED riceverà una corrente eccessiva e potrebbe bruciarsi. Il circuito è molto semplice: Pico GP14

Simulatore Semaforo Raspberry Pi Pico (3 LED Sequenziali)
Simuliamo un vero semaforo con LED rosso, giallo e verde. Verde 4 sec "vai", giallo 1,5 sec "preparati", rosso 3 sec "fermati" e rosso+giallo 1 sec "partenza" (pattern europeo). Impara la definizione di funzione, la logica della macchina a stati e la sincronizzazione multi-GPIO. Circuito semplice: 3 LED su GP11/GP12/GP13.

Raspberry Pi Pico LED Sequenziale (6 LED)
Animazione LED sequenziale classica con Pico — versione 6 LED! 6 LED si accendono da sinistra a destra sequenzialmente. Impara la lista Python, la comprensione di liste ([Pin(p, Pin.OUT) for p in LED_PINS]), il ciclo for con controllo pin e enumerate(). 6 LED su GP9-GP14, ciascuno con resistenza 220Ω. Codice molto pulito: invece di definire 6 LED uno per uno, usiamo una lista — puoi aggiungere LED fino al numero di GPIO liberi e utilizzabili, ciascuno con la propria resistenza. Per controllare 1

Raspberry Pi Pico Knight Rider LED Scanner (6 LED Avanti-Indietro)
Effetto scanner LED "Knight Rider" classico con Pico! 6 LED vanno da sinistra a destra, poi da destra a sinistra, all'infinito. Impara reversed() e due cicli for separati per pattern avanti-indietro.

Semaforo Raspberry Pi Pico con selettore a 4 posizioni (macchina a stati)
4 diverse modalità del semaforo con un solo pulsante! Ad ogni pressione del pulsante, la modalità cambia: Ciclo normale (rosso → giallo → verde in sequenza), Solo rosso (segnale di stop), Giallo lampeggiante (attenzione/modalità notturna), Spento (manutenzione). Concetti: state machine (macchina a stati — la variabile mode determina quale comportamento verrà eseguito), modulo mod cycling ((mode + 1) % 4 → 0→1→2→3→0 ciclo infinito), temporizzazione non bloccante (l

Raspberry Pi Pico Pulsante Debounce: IRQ vs Software Polling
Una pressione e il codice conta 3-4? È contact bounce! Confronta 2 metodi di conteggio in Serial: polling RAW (cattura bounce, conta male) vs IRQ + software debounce (preciso). Impara fisica del bounce, software debounce, Pin.irq() interrupt, IRQ_FALLING trigger, ISR handler, sicurezza delle variabili globali ISR.

Raspberry Pi Pico PWM LED Fade (Effetto Respiro)
Il LED non lampeggia più — respira! Con il PWM (modulazione di larghezza d'impulso) del Raspberry Pi Pico, la luminosità sale e scende lentamente. Impara la classe machine.PWM, duty_u16() (luminosità a 16 bit 0–65535), la frequenza PWM, i cicli range() e l'uscita quasi analogica. Base per miscelazione colori RGB, controllo motori, servo e buzzer.
Altri articoli
App BlueGrays
Costruisci questo circuito passo passo sul telefono
Schema, codice ed elenco componenti in un’unica schermata. Oltre 200 progetti Arduino, ESP32 e Pico da realizzare.
Inquadra con il telefono
Punta la fotocamera sul codice: si apre lo store del tuo telefono.
oppure apri lo store

