RaspberryPI

Introduzione a Raspberry Pi Pico e MicroPython

Una guida pratica per configurare Raspberry Pi Pico e usare Thonny

Introduzione alla programmazione di Raspberry Pi Pico con MicroPython

Raspberry Pi Pico è una scheda a microcontrollore pensata per controllare ingressi, uscite, sensori, piccoli attuatori e periferiche digitali. A differenza di una Raspberry Pi tradizionale, non esegue un sistema operativo Linux: il programma viene caricato direttamente nella memoria della scheda e viene eseguito dal microcontrollore.

Questo approfondimento integra la guida introduttiva dedicata alla gestione della Raspberry Pi Pico con Thonny, aggiungendo una panoramica pratica dei primi comandi MicroPython utili per configurare la scheda, verificare il funzionamento dell’ambiente, pilotare i pin GPIO e dialogare con periferiche esterne.

MicroPython è una versione compatta del linguaggio Python pensata per dispositivi embedded. Il vantaggio principale è la possibilità di scrivere istruzioni semplici, provarle subito nel REPL e poi trasformarle in script permanenti salvati nella memoria della Pico.

Caratteristiche tecniche essenziali della scheda

Prima di scrivere il primo programma è utile fissare alcuni dati tecnici della Raspberry Pi Pico basata su RP2040. Queste informazioni sono importanti perché determinano tensioni, limiti dei pin e periferiche disponibili.

Scheda: Raspberry Pi Pico / Raspberry Pi Pico H
Microcontrollore: RP2040
CPU: dual-core Arm Cortex-M0+
Frequenza operativa di riferimento: fino a 133 MHz
SRAM: 264 kB
Memoria flash onboard: 2 MB
GPIO multifunzione disponibili: 26
Interfacce hardware principali: 2 SPI, 2 I2C, 2 UART
ADC: 3 ingressi analogici esterni a 12 bit
PWM: 16 canali
Tensione logica dei GPIO: 3,3 V
Programmazione iniziale: USB in modalità BOOTSEL con file UF2

Il dato più importante per i primi collegamenti è la tensione logica: i pin GPIO lavorano a 3,3 V. Non vanno collegati direttamente a segnali da 5 V, perché si rischia di danneggiare il microcontrollore. Per sensori o moduli a 5 V è necessario verificare la compatibilità logica oppure usare adattatori di livello.

Preparazione dell’ambiente con Thonny

Il percorso più semplice per iniziare è utilizzare Thonny. Dopo aver collegato la Pico al computer tenendo premuto BOOTSEL, la scheda viene vista come unità di archiviazione. A quel punto si carica il firmware MicroPython in formato UF2. Una volta riavviata, la Pico può essere gestita tramite USB seriale.

In Thonny occorre selezionare l’interprete MicroPython per Raspberry Pi Pico. Da quel momento è possibile eseguire comandi direttamente nella console oppure salvare file sulla scheda. Il lavoro iniziale si divide quindi in due modalità:

  • uso interattivo del REPL, adatto per test rapidi e verifica dei pin;
  • salvataggio di script, adatto per eseguire automaticamente un programma all’accensione.

REPL e primi comandi di verifica

Il REPL è la console interattiva di MicroPython. Permette di scrivere un’istruzione, premere invio e vedere subito il risultato. È il modo migliore per controllare che la scheda risponda correttamente.

import sys
sys.implementation

Questo comando restituisce informazioni sull’interprete MicroPython e sulla scheda per cui è stato compilato il firmware.

import machine
machine.freq()

Il comando mostra la frequenza corrente del microcontrollore. Su RP2040 è anche possibile impostare una frequenza diversa, ma per una prima gestione è consigliabile lasciare il valore predefinito.

import os
os.listdir()

Questo comando mostra i file presenti nella memoria MicroPython della scheda. All’inizio la memoria può essere vuota oppure contenere file già creati durante prove precedenti.

Gestione dei file sulla Pico

MicroPython dispone di un piccolo filesystem interno. I file più importanti sono generalmente main.py e boot.py. Il file main.py viene usato per il programma principale, mentre boot.py è destinato a inizializzazioni eseguite molto presto all’avvio.

import os

os.listdir()

Per creare un file direttamente da console è possibile usare la scrittura su file. In pratica, durante l’uso quotidiano, è più comodo salvare il programma da Thonny scegliendo come destinazione la Raspberry Pi Pico.

f = open("test.txt", "w")
f.write("Pico pronta")
f.close()

os.listdir()

Per leggere il contenuto:

f = open("test.txt", "r")
contenuto = f.read()
f.close()

print(contenuto)

Per cancellare un file:

import os
os.remove("test.txt")

Questi comandi sono utili per capire che la Pico non è solo una scheda da programmare al volo, ma possiede anche una piccola memoria interna dove salvare script, configurazioni e dati leggeri.

Il primo controllo hardware: LED integrato

Il test classico per verificare che tutto funzioni è il lampeggio del LED integrato. Sulle Pico non wireless il LED è associato al pin GP25; su alcune versioni e firmware è disponibile anche il nome simbolico LED. Per rendere l’esempio più robusto si può usare una piccola gestione alternativa.

from machine import Pin
from time import sleep

try:
    led = Pin("LED", Pin.OUT)
except:
    led = Pin(25, Pin.OUT)

while True:
    led.on()
    sleep(0.5)
    led.off()
    sleep(0.5)

Se questo script viene eseguito da Thonny, il LED inizia a lampeggiare. Per interrompere il ciclo si usa il comando di stop dell’IDE oppure Ctrl+C nel REPL.

Pin GPIO in uscita

I GPIO sono i pin generici di ingresso e uscita. In uscita possono pilotare segnali logici, LED con resistenza, ingressi di moduli esterni o transistor di comando. Non devono essere usati per alimentare direttamente carichi importanti come motori, relè o strisce LED.

from machine import Pin
from time import sleep

uscita = Pin(0, Pin.OUT)

uscita.value(1)
sleep(1)
uscita.value(0)

Il metodo value permette di impostare o leggere il valore logico del pin. In uscita, value(1) porta il pin a livello alto, mentre value(0) lo porta a livello basso.

uscita.on()
uscita.off()

I metodi on e off sono più leggibili quando il pin controlla un LED o un segnale digitale semplice.

Pin GPIO in ingresso

Un pin in ingresso serve per leggere pulsanti, contatti, segnali digitali provenienti da sensori o stati logici generati da altri circuiti. Per un pulsante è spesso utile attivare una resistenza interna di pull-up o pull-down.

from machine import Pin
from time import sleep

pulsante = Pin(14, Pin.IN, Pin.PULL_UP)

while True:
    stato = pulsante.value()
    print(stato)
    sleep(0.2)

Con pull-up attivo, il pin normalmente legge 1. Quando il pulsante collega il pin a GND, il valore letto diventa 0. Questa configurazione è molto usata perché riduce i componenti esterni necessari.

Lettura analogica con ADC

La Pico può leggere segnali analogici tramite ADC. Gli ingressi analogici principali sono associati a GP26, GP27 e GP28. Il valore letto da MicroPython viene restituito su scala 0-65535, anche se il convertitore hardware è a 12 bit.

from machine import ADC, Pin
from time import sleep

adc = ADC(Pin(26))

while True:
    valore = adc.read_u16()
    print(valore)
    sleep(0.5)

Questo esempio è adatto per un potenziometro collegato tra 3,3 V e GND, con il cursore centrale collegato a GP26. Il valore stampato cresce o diminuisce ruotando il potenziometro.

Collegamento potenziometro:
estremo 1 -> 3V3
estremo 2 -> GND
centrale  -> GP26 / ADC0

Bisogna sempre verificare che il segnale analogico non superi 3,3 V.

PWM per luminosità LED e piccoli controlli

Il PWM consente di generare un segnale digitale a impulsi, utile per variare la luminosità di un LED, pilotare buzzer passivi o fornire segnali di controllo a moduli esterni. Il parametro più importante è il duty cycle, cioè la percentuale di tempo in cui il segnale rimane alto.

from machine import Pin, PWM
from time import sleep

pwm = PWM(Pin(15))
pwm.freq(1000)

while True:
    for duty in range(0, 65535, 1000):
        pwm.duty_u16(duty)
        sleep(0.02)

    for duty in range(65535, 0, -1000):
        pwm.duty_u16(duty)
        sleep(0.02)

Il valore duty_u16 varia da 0 a 65535. Un valore basso produce una luminosità ridotta, mentre un valore alto produce una luminosità maggiore. Per spegnere l’uscita PWM si può impostare il duty a zero oppure disattivare la periferica.

pwm.duty_u16(0)
pwm.deinit()

Timer software con sleep e sleep_ms

Per introdurre ritardi semplici si usa il modulo time. Nelle prime prove è sufficiente conoscere sleep, sleep_ms e ticks_ms.

from time import sleep, sleep_ms, ticks_ms

sleep(1)
sleep_ms(250)

inizio = ticks_ms()
print(inizio)

sleep usa i secondi, sleep_ms usa i millisecondi. Per programmi più evoluti è preferibile evitare pause bloccanti molto lunghe e usare una logica basata su ticks_ms, ma per i primi esempi i ritardi sono chiari e immediati.

Comunicazione seriale UART

UART è una comunicazione seriale semplice, utile per moduli GPS, lettori RFID, sensori seriali e collegamenti tra microcontrollori. La Pico mette a disposizione due UART hardware.

from machine import UART, Pin
from time import sleep

uart = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))

uart.write("ciao da Pico\n")

while True:
    if uart.any():
        dati = uart.read()
        print(dati)
    sleep(0.1)

In questo esempio TX è su GP4 e RX su GP5. Il collegamento con un altro dispositivo deve sempre incrociare le linee: TX della Pico verso RX del dispositivo, RX della Pico verso TX del dispositivo, con GND in comune.

Collegamento UART:
Pico GP4 TX -> RX dispositivo
Pico GP5 RX -> TX dispositivo
Pico GND    -> GND dispositivo

Bus I2C per sensori e display

I2C è un bus a due fili molto diffuso per sensori ambientali, display OLED, espansori di I/O, memorie e convertitori. Usa una linea dati SDA e una linea clock SCL. Una prima operazione utile è la scansione degli indirizzi presenti sul bus.

from machine import Pin, I2C

i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)

dispositivi = i2c.scan()
print(dispositivi)

Se il collegamento è corretto, scan restituisce una lista di indirizzi numerici. Se la lista è vuota, bisogna controllare alimentazione, massa comune, linee SDA/SCL e presenza delle resistenze di pull-up, spesso già integrate nei moduli.

Collegamento I2C tipico:
Pico 3V3 -> VCC modulo
Pico GND -> GND modulo
Pico GP4 -> SDA
Pico GP5 -> SCL

Bus SPI per periferiche veloci

SPI è usato per display, memorie, convertitori, moduli radio e periferiche che richiedono comunicazioni più veloci rispetto a I2C. Usa almeno tre linee principali: SCK, MOSI e MISO. Spesso si aggiunge una linea CS per selezionare il dispositivo.

from machine import Pin, SPI

spi = SPI(
    0,
    baudrate=1000000,
    polarity=0,
    phase=0,
    sck=Pin(6),
    mosi=Pin(7),
    miso=Pin(4)
)

cs = Pin(5, Pin.OUT)
cs.value(1)

Per inviare dati si abbassa CS, si esegue il trasferimento, poi si rialza CS.

cs.value(0)
spi.write(b"1234")
cs.value(1)

La configurazione esatta di polarity e phase dipende dalla periferica collegata. Questi valori sono indicati nel datasheet del modulo SPI.

Connessione Wi-Fi su Raspberry Pi Pico W

La gestione Wi-Fi riguarda solo le versioni Pico W e Pico WH, non la Pico base. Prima di usare il Wi-Fi è necessario caricare un firmware MicroPython adatto alla variante wireless.

import network
from time import sleep

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("NOME_RETE", "PASSWORD_RETE")

while not wlan.isconnected():
    print("connessione in corso...")
    sleep(1)

print(wlan.ifconfig())

Questo esempio attiva l’interfaccia Wi-Fi in modalità station, tenta la connessione alla rete e stampa la configurazione IP ottenuta. In un progetto reale è opportuno non scrivere le credenziali direttamente nel programma principale, ma salvarle in un file separato o gestirle con maggiore attenzione.

Reset e riavvio della scheda

Durante le prove può essere necessario riavviare la scheda via software. Il comando principale è machine.reset.

import machine
machine.reset()

Nel REPL è anche utile conoscere Ctrl+C per interrompere un programma in esecuzione e Ctrl+D per eseguire un riavvio software dell’ambiente MicroPython.

Struttura minima di un programma salvato

Quando uno script deve partire automaticamente all’alimentazione, va salvato come main.py nella memoria della Pico. Una struttura ordinata separa import, configurazione dei pin e ciclo principale.

from machine import Pin
from time import sleep

try:
    led = Pin("LED", Pin.OUT)
except:
    led = Pin(25, Pin.OUT)

pulsante = Pin(14, Pin.IN, Pin.PULL_UP)

while True:
    if pulsante.value() == 0:
        led.on()
    else:
        led.off()

    sleep(0.05)

Questo programma accende il LED quando il pulsante viene premuto. È un esempio semplice, ma contiene già la struttura tipica di molti progetti embedded: inizializzazione, lettura di un ingresso, decisione logica e controllo di un’uscita.

Comandi essenziali da ricordare

Per una prima gestione della scheda è utile memorizzare un piccolo set di istruzioni. Questi comandi coprono controllo generale, file, GPIO, conversione analogica e periferiche comuni.

Verifica ambiente:
import sys
sys.implementation

Controllo frequenza:
import machine
machine.freq()

Reset:
machine.reset()

Filesystem:
import os
os.listdir()
os.remove("nomefile.py")

GPIO uscita:
from machine import Pin
pin = Pin(0, Pin.OUT)
pin.on()
pin.off()
pin.value(1)
pin.value(0)

GPIO ingresso:
pulsante = Pin(14, Pin.IN, Pin.PULL_UP)
pulsante.value()

ADC:
from machine import ADC
adc = ADC(Pin(26))
adc.read_u16()

PWM:
from machine import PWM
pwm = PWM(Pin(15))
pwm.freq(1000)
pwm.duty_u16(32768)

I2C:
from machine import I2C
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
i2c.scan()

UART:
from machine import UART
uart = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart.write("test")
uart.read()

SPI:
from machine import SPI
spi = SPI(0, baudrate=1000000, sck=Pin(6), mosi=Pin(7), miso=Pin(4))
spi.write(b"test")

Errori comuni nelle prime prove

Uno degli errori più frequenti è confondere la numerazione fisica dei pin con il numero GPIO. In MicroPython, quando si scrive Pin(15), si fa riferimento a GP15, non necessariamente al piedino fisico numero 15 del connettore.

Un altro errore comune è collegare moduli alimentati a 5 V senza verificare il livello logico dei segnali. La Pico lavora a 3,3 V: questa regola va considerata prima di collegare sensori, display o schede relè.

Se un programma salvato come main.py entra in un ciclo infinito e rende difficile usare la console, si può interrompere l’esecuzione con Ctrl+C subito dopo il collegamento oppure ricaricare il firmware MicroPython in modalità BOOTSEL nei casi più critici.

Metodo consigliato per imparare

Il modo più efficace per iniziare è procedere per piccoli test. Prima si verifica il LED integrato, poi un pulsante, poi un ingresso analogico, quindi una periferica I2C o UART. Ogni nuovo componente dovrebbe essere provato con uno script minimo prima di essere integrato in un progetto più grande.

MicroPython rende questo processo rapido perché permette di sperimentare direttamente nel REPL. Una volta trovata la configurazione corretta, le istruzioni possono essere copiate in uno script main.py più ordinato e commentato.

Admin | MST-Tutorial

Appassionato di elettronica, elettrotecnica e programmazione. Fondatore di MST-Tutorial, condivido con entusiasmo conoscenze, esperienze e progetti legati all’innovazione tecnologica, con l’obiettivo di rendere accessibili concetti tecnici complessi attraverso tutorial chiari e pratici.

Articoli Correlati

Pulsante per tornare all'inizio