Introduzione a Pybricks per Powered Up

Questo articolo ha lo scopo di introdurre il firmware Pybricks fornendo informazioni ed indicazioni comprensibili anche da coloro che non hanno conoscenze di programmazione (in generale) e di MicroPython in particolare, il linguaggio tramite il quale si può programmare uno Smart Hub LEGO equipaggiato con Pybricks.

Partiremo dal capire cos’è effettivamente Pybricks e vedremo come differisce rispetto al firmware originale LEGO, confrontando pregi e difetti di entrambi i sistemi in modo da saper scegliere quello più adatto alle nostre esigenze: pilotare un treno, anziché azionare una giostra o, più in generale, una MOC “animata”.

Seguiranno articoli più specifici che illustreranno come sfruttare al massimo Pybrick e, per i più temerari, approfondiremo anche aspetti tecnici più “spinti” ovvero come apportare eventuali eventuali modifiche al firmware, come interagire da linea di comando e come realizzare sensori/attuatori personalizzati con hardware Arduino/ESP al fine di estendere le possibilità dell’ecosistema Powered Up.

Innanzitutto, cos’è un firmware? In parole semplici, è un programma (software) residente nella memoria di un microcontrollore (hardware) e che determina il funzionamento di uno specifico dispositivo elettronico: che sia un telefono, una lavatrice, un drone o uno Smart Hub LEGO poco importa… se all’interno di questi dispositivi c’è un microcontrollore, dentro ad esso ci sarà un firmware!
Questo programma resta nella memoria del microcontrollore anche quando viene tolta l’alimentazione.

Molti dispositivi elettronici consentono, tramite specifiche procedure definite dal produttore, di aggiornare il firmware allo scopo di implementare nuove funzionalità non previste al momento del rilascio del prodotto e/o per risolvere eventuali bug (del resto, non esiste software che non abbia qualche bug).

Gli ingegneri LEGO hanno pertanto dotato gli Smart Hub LEGO della possibilità di aggiornare il loro firmware, ed è proprio grazie a questa funzionalità che un paio di AFOL con forti competenze tecniche, sono stati in grado di sostituire il firmware originale LEGO con uno di loro creazione per estendere le capacità di questi Smart Hub.

Facciamo prima un passo indietro…

Con il sistema Powered Up, LEGO ha introdotto nel suo catalogo 3 nuovi dispositivi intelligenti genericamente identificati come Smart Hub: il Move Hub, il City Hub e Technic Hub (nel gergo di Pybricks sono identificati rispettivamente come MoveHub, CityHub e CPlusHub).

Nota: Pybricks è disponibile per: EV3, Move Hub, City Hub e Control+ Hub/Technic Hub. In questo articolo tratteremo solo gli Smart Hub del sistema Powered Up, quindi escluderemo l’EV3 per il quale prevedo di scrivere in futuro qualcosa di specifico:

I 3 Smart Hub condividono tra loro più o meno lo stesso firmware dato che il ‘cuore’ dell’hardware è abbastanza simile. Le differenze sostanziali sono nella forma del contenitore, nel numero di porte di I/O (Input e Output) e nella presenza di motori e/o sensori integrati (in particolare per quanto riguarda il MoveHub e il CPlusHub). In realtà questi dispositivi si differenziano anche nei singoli microcontrollori utilizzati (tutti della famiglia STM32) ma sono dettagli che poco contano per la maggior parte degli utilizzatori.

Per comodità, e anche perché è quello più ampiamente diffuso, gli esempi e i riferimenti di questo articolo si baseranno sull’utilizzo del CityHub al quale affiancheremo il motore ‘treno’ e il sensore di colore/distanza. Le stesse informazioni, ovviamente, si potranno applicare anche al MoveHub e al CPlusHub.

City Hub, Train Motor, Color & Distance Sensor

Il firmware originale LEGO consente di interagire con le funzionalità degli Smart Hub e dei dispositivi a loro connessi (motori e sensori) per mezzo di una comunicazione Bluetooth di tipo Low Energy (BLE) e, di conseguenza, tramite un dispositivo di controllo esterno che invierà comandi verso l’Hub e riceverà eventuali informazioni dallo stesso.

Nel caso più semplice tale dispositivo è il Controller Remoto LEGO, tramite il quale è possibile solo pilotare i motori connessi all’Hub (Nota: data la sua inutilità riferita all’ambito Pybricks, in questo articolo non tratterò l’utilizzo di tale controller ma se vuoi approfondire l’uso ti suggerisco questo video di Hispa Bricks Magazine).

In alternativa al controller LEGO può essere utilizzato un qualsiasi smartphone/tablet sul quale abbiamo preventivamente installato l’App ufficiale “LEGO Powered Up”, disponibile sia per Android che per iOS. Tale App offre funzionalità enormemente più evolute rispetto al Controller Remoto e, tra le altre cose, è solo tramite essa che può essere aggiornato il firmware originale LEGO o, nel caso in cui se ne avesse bisogno, ripristinarlo dopo un uso di Pybricks (vedremo meglio più avanti cosa significa tutto ciò).

Grazie a questa App, infatti, possiamo facilmente ‘costruire’ (con una serie di blocchi di azioni che si ‘incastrano’ tra loro) la logica che determinerà il funzionamento del nostro Smart Hub.

Facciamo un esempio pratico, realizzando uno specifico task che attiva il motore di tipo “treno” (ad una velocità pari al 75% di quella massima) per un tempo di 5 secondi, fermandolo successivamente 3 secondi, in un loop che proseguirà all’infinito finché non interrotto esplicitamente dall’utente (o dalle batterie scariche!)

(Nota: il motore deve essere connesso alla ‘Porta A’ del CityHub)

La comodità di ‘disegnare’ uno specifico task con l’App LEGO è in parte ‘inficiata’ dal fatto che la logica del task è in esecuzione sullo smartphone e che verso l’Hub vengono inviati solo, e continuamente, i comandi di attivazione/disattivazione del motore. Pertanto, se (a) viene a mancare la connessione Bluetooth (per disturbi o per lontananza tra i dispositivi), se (b) lo smartphone va in stand-by o comunque se (c) l’App passa in secondo piano, il task in esecuzione verrà bruscamente interrotto.

Inoltre, la continua comunicazione tra Hub e smartphone può comportare leggeri ritardi nella lettura dei dati di un sensore e, in rari casi, anche alla perdita del dato di tale lettura.

Vediamo ora un esempio leggermente più complesso, che vede l’introduzione del sensore di colore e distanza (connesso alla Porta B dell’Hub). Anche in questo caso il task sarà eseguito in loop continuo e il suo scopo sarà quello avviare il motore e di fermarlo per 3 secondi, ogni volta che il sensore intercetterà il colore rosso.

Provate ad mmaginate un tracciato ferroviario lungo il cui percorso sono presenti dei tile 2×4 di colore rosso. L’Hub, il motore e il sensore sono a bordo di un treno. Quando il treno passerà in corrispondendo di uno di questi tile (il sensore sarà ovviamente posizionato in modo tale da “vederli” con facilità) si fermerà per 3 secondi per poi riprendere la marcia fino al successivo tile.

Tracciato ferroviario con tile 2×4 rosso come marcatore di posizione

Nel video qui sopra è stata utilizzata una logica più “complessa” (tiene conto anche di suoni, di velocità progressive, di rallentamenti, ecc.).
La versione minimale, utile allo scopo di questo articolo, è la seguente:

(Nota: il motore deve essere connesso alla ‘Porta A’, il sensore sulla ‘Porta B’)

Eseguendo questo task, l’App invierà all’Hub il comando di ‘avvio motore‘ e poi resterà in “ascolto”. Il sensore di colore, infatti, restituirà continuamente all’Hub il valore delle sue letture e l’Hub, a sua volta, comunicherà questi valori all’App che li utilizzerà per valutare la corrispondenza “colore letto=rosso?“.

Quando l’App riscontrerà la corretta corrispondenza, invierà all’Hub il comando di ‘stop motore’ e, dopo 3 secondi, invierà un nuovo comando ‘avvia motore’. Il ritardo di 1 secondo che si può notare subito dopo il comando di ‘avvio motore’ serve a dare quel minimo di tempo affinché il treno posso spostarsi evitando un eventuale stop immediato nel caso in cui il sensore sia ancora sul tile rosso. il posizionamento reale del treno è infatti dipendente da diversi fattori come velocità e peso dello stesso. Non possiamo escludere che il treno si fermi in una posizione tale che il sensore riesca comunque a leggere il colore del tile e quindi, per sicurezza, è necessario un piccolo delay tra partenza del motore e lettura del sensore per assicurarci uno spostamento del sensore.

I comandi e le informazioni scambiati tra Hub e App sono definiti da un protocollo proprietario LEGO denominato LWP “LEGO Wireless Protocol” di cui LEGO ha rilasciato una documentazione sufficiente esaustiva, benché non completa al 100%. Tant’è che, come ho già spiegato in questo mio appunto, ci sono anche software/librerie di terze parti per interagire con l’Hub. Resta comunque il problema del legame Hub<->dispositivo di controllo citato prima.

Ed è ora che entra in gioco Pybricks!

David e Laurens, i due ideatori/sviluppatori del firmware Pybricks hanno fatto un enorme lavoro di reverse engineering dell’hardware LEGO e grazie alla loro pregressa esperienza in ambito Embedded/STM32 (e robotica LEGO) hanno completamente riscritto da zero un nuovo firmware per sostituire quello originale LEGO implementando caratteristiche e funzionalità aggiuntive. Tra queste, la possibilità di eseguire un task direttamente all’interno dell’Hub senza la necessità che ci sia un collegamento continuo e stabile con l’esterno.

Infatti, una volta mandato in esecuzione il nostro task (ovvero, una volta inviate all’Hub il set delle istruzioni da eseguire) è possibile interrompere il collegamento tra PC/smartphone e Hub senza che questa interruzione possa influire sul funzionamento del task stesso.

Ma non solo… anzi (e per me è la caratteristica fondamentale di Pybricks) è persino possibile salvare in modo permanente uno specifico task nella memoria del microcontrollore e lanciarlo immediatamente dopo l’accensione dell’Hub, senza la necessità di avere uno smartphone/PC a disposizione. Insomma, è possibile programmare in modo permanente uno Smart Hub affinché esegua uno specifico compito in completa autonomia, con la comodità di poter cambiare questo compito quando se ne presenterà la necessità e, non di meno, con l’opzione di tornare ad utilizzare il firmware originale LEGO in qualsiasi momento!

Di contro, perderemo la semplicità dell’ambiente di sviluppo grafico a ‘blocchi di azione’ dell’App LEGO, al cui posto sarà necessario scrivere letteralmente le istruzioni che dovrà espletare nostro task utilizzando il linguaggio di programmazione MicroPython, una versione minimale del più noto Python. Come vedremo più avanti non è nulla di così complesso e con un minimo di studio sarà semplice prendere confidenza con tale tipo di programmazione.
(se vuoi subito approndire qualcosa su MicroPython, leggi qui e qui)

A questo punto, non ci resta che vedere come “installare” Pybrick sul nostro CityHub e replicare con MicroPython i due task sviluppati poc’anzi con l’App LEGO.

Nota bene: Pybricks è tutt’ora in fase di beta e quindi non sono esclusi comportamenti non previsti. Io lo utilizzo oramai da un paio di mesi, avendo partecipato anche alla fase di beta “privata” e, a parte alcuni aspetti tecnici particolari, il firmware è tranquillamente utilizzabile anche se non ancora definitivo. Come già anticipato, sarà comunque possibile ripristinare il firmware originale LEGO.

Per programmare uno Smart Hub con Pybricks si può utilizzare un PC/Tablet con un qualsiasi sistema operativo (incluso Android) a patto di avere una chiavetta Bluetooth (o il supporto Bluetooth integrato nel dispositivo) e aver installato una versione di Chrome ‘Canary’ superiore alla 85.

Chrome Canary è sostanzialmente una versione molto-molto beta di Chrome, compilata praticamente giornalmente, ed introduce le novità che in un prossimo futuro passeranno alla versione ‘stabile’ ovvero quella che usiamo quotidianamente. Canary può essere installata parallelamente alla versione stabile di Google Chrome, senza influire con quest’ultima. Dalla versione 85 in poi sono state implementate alcune migliorie alle Web-API Bluetooth, sulle quali si basa l’ambiente di sviluppo di Pybricks (in un prossimo articolo vedremo anche che è possibile utilizzare metodi alternativi, a linea di comando, per programmare uno Smart Hub).

Installato Canary, siamo pronti per caricare Pybricks sul nostro smart hub!

Colleghiamoci a https://code.pybricks.com e ci apparirà l’ambiente per programmare Pybricks.

L’interfaccia di sviluppo di Pybricks

L’interfaccia è abbastanza intuitiva:
1) Aprire un file di script *.py presente sul nostro PC (.py è l’estensione dei file di script Python/MicroPython);
2) Salva il codice dello script sul PC locale;
3) Attiva la connessione Bluetooth tra PC e Smart Hub;
4) Avvia l’esecuzione del programma presente nella finestra dell’editor;
5) Ferma l’esecuzione del programma;
6) Attiva la modalità REPL (argomento che tratterò in un futuro articolo…);
7) Carica il firmware Pybricks nella memoria dello Smart Hub;
8) Editor del codice MicroPython;
9) Finestra del terminale (tramite la quale verranno pubblicate le informazioni provenienti dallo Smart Hub o interagiremo con lo stesso durante la modalità REPL);
Infine, sull’area destra della interfaccia, c’è la documentazione relativa alle API di Pybricks.

Partiamo!

1) Assicuriamoci che l’Hub sia spento!
2) Scolleghiamo dal CityHub qualsiasi dispositivo (c’è un bug nel Bootloader LEGO del solo CityHub che non consente di caricare/aggiornare un nuovo firmware se ci sono dispositivi connessi ad esso. Non è un problema connesso a Pybricks tant’è che anche l’App LEGO va in blocco se si tenta di aggiornare il firmware con un motore connesso all’hub);
3) Premiamo il tasto di accensione del CityHub, continuando a tenerlo premuto ad oltranza. Ad un certo punto il Led presente sull’hub inizierà a lampeggiare con una luce colore viola… Continuiamo comunque a tenerlo premuto fino a ulteriori istruzioni;
4) Clicchiamo sul pulsante di caricamento del firmware (pulsante 7) ed autorizziamo il sito code.pybricks.com all’utilizzo del dispositivo Bluetooth del nostro PC;
5) A questo punto comparirà la finestra di connessione BLE nella quale dovrebbe essere elencato il nostro dispositivo LEGO, con la descrizione “LEGO Bootloader”


6) Clicchiamo sul pulsante ‘Accoppia’;
7) Se tutto va a buon fine, dopo pochi istanti il Led dovrebbe cambiare colore iniziando una sequenza rosso, verde, blue a conferma che l’accoppiamento è riuscito e che sta iniziando l’operazione di caricamento del nuovo firmware;
9) A questo punto è possibile rilasciare il pulsante verde ed attendere il completamento dell’operazione;

Questo video, riassume la procedura di caricamento del firmware:

Caricamento del firmware Pybricks

Per caricare l’intero firmware sono necessari circa 90-120 secondi e si può monitorare il l’andamento dell’operazione tramite la progress bar presente in basso a sinistra (Nota: su alcuni PC ho potuto notare tempi di caricamento ben più lunghi… abbiate pazienza, se vi capita, e soprattutto abbiate la voglia di segnalare l’inconveniente qui (link a github).

Al termine dell’operazione, il led dell’Hub assumerà il colore blu fisso ad indicare che è pronto per essere programmato nella modalità “Pybricks”.

Verifichiamo che sia andato tutto liscio, usando questo semplice programma il cui scopo è far lampeggiare il led dello Smart Hub:

1) Copiamo il seguente codice nella finestra dell’editor:

from pybricks.hubs import CityHub
from pybricks.parameters import Color
from pybricks.tools import wait

hub = CityHub()
for x in range(10):
    hub.light.on(Color.WHITE)
    wait(200)
    hub.light.off()
    wait(200)

2) Clicchiamo sul pulsante con l’icona di connessione Bluetooth (pulsante 3) e dovremmo vedere una finestra simile a quella precedente, ma questa volta con il dispositivo ‘Pybrick Hub’:

3) Selezioniamo il dispositivo Pybricks Hub e clicchiamo su accoppia;
4) Dopo qualche istante l’icona del pulsante Bluetooth cambierà stato e il pulsante di avvio dello script diventerà attivo;

5) Clicchiamo sul pulsante ‘Avvia script’ (la tooltip, per l’esattezza, è “Download and run this program“)…. il nostro programma verrà “compilato” e trasferito nelle memoria dell’Hub e, dopo pochi istanti, eseguito.

Dopo 10 lampeggi, il programma terminerà e vedremo nuovamente il led diventare blu e il pulsante ‘Avvia script’ cambiare stato e tornare a quella di riposo.

Apportiamo ora una leggerla modifica al codice affinché il led lampeggi all’infinito, ovvero fin quando non interverremo esplicitamente noi ad interrompere l’esecuzione del codice.

from pybricks.hubs import CityHub
from pybricks.parameters import Color
from pybricks.tools import wait

hub = CityHub()
while True:
    hub.light.on(Color.WHITE)
    wait(200)
    hub.light.off()
    wait(200)

La modifica è molto banale e riguarda il diverso tipo di loop: abbiamo sostituito un ciclo for x in range(10) che ripete il blocco di codice indentato per 10 volte, con un ciclo infinito while True (vedi le istruzioni loop in MicroPython).

Una volta lanciato questo task lo potremo interrompere in due modi:

  1. Premendo il tasto verde dello Smarth Hub
  2. Premendo il pulsante Stop (pulsante 5) sull’editor

Bene… passiamo ora al successivo test, che ci confermerà come Pybricks, una volta ricevuto il programma da eseguire, diventa indipendente dall’editor di codice:

Lanciamo nuovamente il programma per far lampeggiare continuamente il Led e, una volta che vedremo Led lampeggiare chiudiamo la finestra del browser. Questo farà si che la connessione Bluetooth tra PC e Hub venga chiusa. Se proprio non siamo convinti, possiamo anche spegnere il PC! 😉

Il Led del CityHub continuerà imperterrito a lampeggiare… smetterà solamente nel momento in cui premeremo il pulsante verde!

Andiamo avanti, e concludiamo questo primo tutorial su Pybricks replicando con il codice MicroPython i due task che precedentemente abbiamo ‘costruito’ con l’App LEGO.

Il codice per avviare il motore del treno al 75% di velocità, per 5 secondi, per poi andare in pausa per 3 secondi è il seguente:

#importazione librerie Pybricks
from pybricks.pupdevices import DCMotor
from pybricks.parameters import Port
from pybricks.tools import wait

#creazione di una istanza dell'oggetto DCMotor, connesso alla Porta A
trainMotor=DCMotor(Port.A)
#ciclo infinito
while True:
    traiMotor.dc(75) #avvia il motore al 75% di velocità
    wait(5000) #attendi 5 secondi (5000 ms)
    traiMotor.stop() #ferma il motore
    wait(3000) #attendi 3 secondi

Il codice è molto semplice e dovrebbe essere comprensibile, nelle sue azioni, anche da chi non ha rudimenti di programmazione.

Introduciamo ora il sensore di colore e vediamo come replicare, con Pybricks, quanto già fatto con l’App LEGO:

from pybricks.pupdevices import DCMotor
from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Color
from pybricks.parameters import Port
from pybricks.tools import wait

#Istanze degli oggetti motore e sensore di colore
trainMotor=DCMotor(Port.A)
colorSensor=ColorDistanceSensor(Port.B)
#primo ciclo infinito (ciclo principale)
while True:
    trainMotor.dc(75)
    wait(1000)
    #secondo ciclo infinito:
    while True:
        #se il sensore rileva il colore rosso...
        if (colorSensor.color()==Color.RED):
            trainMotor.stop() #ferma il motore
            wait(3000)  #attendi 3 secondi
            break #interrompi questo ciclo infinito

Una volta eseguito questo codice, vedrete come il motore partirà immediatamente e si fermerà nel momento in cui avvicinerete un oggetto rosso al sensore di colore!

Bene, direi che come primo contatto con Pybricks può essere sufficiente 😉

A questo punto non ci resta che esplorare la documentazione di Pybricks, seguire il repository GitHub per essere sempre informati sulle novità del firmware (in continuo e veloce sviluppo), mettere un like alla pagina Facebook di Pybricks (dove potrai vedere numerose applicazioni d’uso= e leggere gli altri miei articoli sull’argomento, ai quali se ne aggiungeranno molti altri nelle prossime settimane.

Il prossimo, vi anticipo, sarà quello in cui spiegherò come salvare, in modo permanente, un programma sul vostro Smart Hub per eseguirlo ad ogni accensione del dispositivo!

E se proprio volete tornare ad utilizzare il firmware originale e l’App LEGO, seguite le istruzioni di questo video 😉

Procedura per il ripristino del firmware originale LEGO

2 pensieri su “Introduzione a Pybricks per Powered Up

  1. Ottima guida, molto chiara ed esaustiva. Installato e testato il firmware su un CityHub e… funziona alla grande!!! Complimenti Giancann

  2. This is a fantastic guide!

    Making a train start and stop with the colour sensor is a great example. It is something that a lot of people will want to do.

Lascia una risposta

L'indirizzo email non verrà pubblicato.I campi obbligatori sono contrassegnati *