Boost Converter controllato da PID con ESP32: una guida completa per la progettazione e implementazione

Lista dei contenuti

Introduzione

Il Boost Converter controllato da PID con ESP32, presentato in questo articolo, rappresenta una soluzione efficiente e versatile per gestire le variazioni di tensione nella alimentazione di sistemi elettronici, consentendo di aumentare la tensione di ingresso a un livello desiderato, pur mantenendo il sistema stabile e preciso grazie al controllo PID (Proporzionale, Integrale, Derivativo). In questa guida completa, esploreremo i passaggi fondamentali per progettare e implementare un convertitore boost, utilizzando un microcontrollore ESP32 per il controllo, che offre un’elevata potenza di calcolo e la flessibilità necessaria per gestire in tempo reale il comportamento dinamico del sistema.

Che tu sia un hobbista alla ricerca di un progetto sfidante o un ingegnere interessato a implementare soluzioni avanzate per la gestione della potenza, questa guida ti fornirà tutti gli strumenti necessari. Inizieremo dalla comprensione di cosa sia un convertitore boost, come funzioni il controllo PID e come questi elementi si integrino all’interno del progetto. Passeremo poi alla realizzazione pratica, con un focus su come configurare i componenti hardware, come i sensori di tensione e corrente, e su come programmare l’ESP32 per ottenere un sistema stabile e reattivo.

Alla fine di questa guida, sarai in grado di implementare un sistema completo per gestire il Boost Converter, con un controllo estremamente preciso del segnale PWM (modulazione di ampiezza del segnale) e un monitoraggio dei parametri chiave in tempo reale grazie a una completa interfaccia web che ti permette non solo di visualizzare i grafici dinamici e aggiornati in tempo reale delle tensioni e correnti in ingresso e uscita, ma anche di controllare lo stato del PID con facilità, verificando il suo funzionamento in un colpo d’occhio. Inoltre, potrai interagire con il sistema tramite API REST per inviare e ricevere dati in modo flessibile e intuitivo, rendendo il monitoraggio e la gestione del Boost Converter ancora più efficienti. Come sempre, per sviluppare il software, useremo l’eccellente IDE PlatformIO. Scopri come ottimizzare il controllo della potenza con il Boost Converter controllato da PID su ESP32, attraverso un’esperienza completa e interattiva!

Il Boost Converter: introduzione e principi di funzionamento

Cosa è e a cosa serve un Boost Converter?

Il Boost Converter è un tipo di convertitore DC-DC che ha lo scopo di aumentare la tensione di ingresso (inferiore) a un valore di tensione di uscita più elevato. Questo lo rende essenziale in una vasta gamma di applicazioni elettroniche dove una sorgente a bassa tensione, come una batteria o un supercondensatore, deve fornire una tensione maggiore per alimentare dispositivi più esigenti.

Ad esempio, è utilizzato nei sistemi alimentati da celle solari, dove la tensione generata dai pannelli può variare in base alla luce disponibile, ma deve essere regolata per alimentare un circuito in maniera stabile. Allo stesso modo, nei sistemi portatili, come smartphone o dispositivi embedded (come l’Arduino), può convertire una tensione di batteria inferiore (es. 1.5V da una singola cella) in una tensione di uscita più elevata, come 3.3V, necessaria per il funzionamento di altre parti del sistema.

Come funziona un Boost Converter?

Vediamo innanzitutto lo schema elettrico di principio di un Boost Converter:

Schema di principio di un Boost Converter
Schema di principio di un Boost Converter

Come puoi vedere, la sorgente di ingresso DC da elevare sul nodo Vout è la batteria V1 da 1.5V. Un’altra sorgente è il generatore PWM (nello schema denominato con PULSE) che pilota il MOSFET IRLZ44N.

Il funzionamento del Boost Converter si basa sull’energia accumulata in un induttore durante la fase di accensione del MOSFET, che viene poi trasferita al carico nella fase di spegnimento. Il circuito base è composto da pochi elementi chiave:

  • Induttore (L): accumula energia sotto forma di campo magnetico durante la fase di carica (il MOSFET in questa fase è acceso e connette il Drain al Source) e la rilascia quando la corrente è interrotta, inducendo una tensione maggiore.
  • MOSFET: agisce come interruttore controllato che chiude il circuito per caricare l’induttore e lo apre per trasferire l’energia accumulata al carico.
  • Diodo : permette il flusso della corrente verso il carico ma blocca il ritorno di corrente, garantendo che l’energia venga trasferita correttamente verso il carico (nel nostro caso si tratta di un diodo Schottky).
  • Condensatore: è collegato in parallelo al carico (in questo caso il resistore da 33Ω) funge da filtro per stabilizzare la tensione di uscita e ridurre il ripple.

Il funzionamento di alcuni di questi componenti viene ampiamente spiegato nell’articolo Comprendere i principali componenti elettronici: una guida essenziale all’elettronica analogica e digitale che ti invito a leggere.

Il principio di funzionamento del Boost Converter si basa sull’induttore, che resiste ai cambiamenti improvvisi di corrente. Quando il MOSFET si chiude, la corrente fluisce attraverso l’induttore. Quando il MOSFET si apre, l’induttore tenta di mantenere la corrente costante, causando un innalzamento della tensione ai suoi capi. Questa tensione sommata a quella d’ingresso viene trasferita al carico tramite il diodo.

Dal link seguente puoi scaricare il progetto di Boost Converter realizzato con LTspice.

Mentre il video seguente mostra una simulazione realizzata col progetto menzionato (con sottotitoli):

Il convertitore funziona a ciclo aperto, non è soggetto a regolazione. Con un segnale PWM di controllo di 62kHz e Duty Cycle pari a 57.2% regola la tensione di uscita a 3.3V su un carico da 33Ω. La corrente sul carico è quindi pari a 100mA. Ma cosa succederebbe se, per caso, il carico cambiasse? Se, per esempio, il carico passasse da 33Ω a 330Ω cosa succederebbe? Molto probabilmente, essendo il valore del Duty Cycle fissato, il valore della tensione di uscita sarebbe molto diverso da 3.3V. Per questo motivo, come vedremo più avanti, il Boost Converter sarà inserito in un sistema più complesso che comprenderà un PID, cioè un elemento regolatore che, misurando con continuità la tensione in uscita dal convertitore, modificherà il Duty Cycle del segnale PWM in modo che, a prescindere dalle variazioni del valore del carico, la tensione in uscita su di esso si trovi sempre regolata al valore stabilito (nel nostro caso 3.3V). Per far questo, il PID verrà impostato con dei parametri (Kp, Ki e Kd) che vedremo più avanti e che ne determinano il comportamento. Ovviamente il PID potrà regolare la tensione in uscita per variazioni entro un certo range del valore del carico. Per valori estremi del carico il PID non sarà più in grado di regolare la tensione in uscita dal Boost Converter.

NOTA: in realtà il MOSFET dovrebbe essere pilotato da un componente elettronico che si chiama gate driver. Questo dispositivo è usato per trattare il segnale in modo da fornire una corrente sufficiente al gate del MOSFET, consentendo un’accensione e uno spegnimento rapidi e migliorando quindi l’efficienza del convertitore. Il gate driver è particolarmente importante quando si controlla un MOSFET con segnali a bassa potenza, come quelli generati da un microcontrollore (ad esempio, l’ESP32) che non può fornire la corrente necessaria per pilotare il MOSFET in modo efficiente. Nel nostro caso è stato omesso per ragioni di semplificazione del progetto e quindi non lo useremo ma sappi che sarebbe buona norma utilizzarlo. Un esempio di gate driver è il TC4420.

Regole fisiche e formule chiave

Il comportamento del Boost Converter può essere descritto da alcune formule chiave che collegano la tensione di ingresso Vin​, la tensione di uscita Vout, e il duty cycle del segnale PWM (D) che controlla l’interruttore (MOSFET):

Tensione di uscita

dove D è il rapporto del tempo in cui il MOSFET è attivo rispetto al periodo del segnale PWM.

Induttanza

La dimensione dell’induttore dipende dalla corrente che lo attraversa, dalla tensione e dalla frequenza del PWM. Un valore tipico dell’induttanza può essere calcolato come:

blank

dove ΔIL​ è il ripple di corrente desiderato e f è la frequenza del segnale PWM.

Condensatore

La capacità necessaria per ridurre il ripple di tensione sull’uscita è:

blank

dove Iout è la corrente di carico, ΔVoutè il ripple di tensione tollerabile e f è la frequenza del PWM.

Storia e applicazioni

Il Boost Converter è nato per rispondere alla necessità di soluzioni efficienti e compatte per l’alimentazione di dispositivi elettronici. Nel tempo, si è dimostrato una soluzione chiave in moltissimi settori: dalle energie rinnovabili (come i pannelli solari) all’industria automobilistica per la gestione delle batterie, fino ai dispositivi portatili.

La prima versione del Boost Converter è stata concepita negli anni ’60, e da allora ha visto un’enorme evoluzione, soprattutto grazie ai miglioramenti nei semiconduttori (come MOSFET a bassa resistenza e diodi Schottky con bassa caduta di tensione) e alla crescente capacità dei condensatori e degli induttori.

Perché un Boost Converter e non un alimentatore lineare?

La principale differenza tra un Boost Converter e un alimentatore lineare è l’efficienza. Gli alimentatori lineari, pur essendo semplici, dissipano molta energia sotto forma di calore perché regolano la tensione abbassandola tramite resistenza interna o tramite un trasformatore, mentre i convertitori switching come il Boost ottimizzano l’energia trasferendo tutta l’energia immagazzinata nell’induttore al carico.

I convertitori switching, come il Boost, possono facilmente raggiungere efficienze superiori all’85%, mentre i regolatori lineari raramente superano il 50%, specialmente quando c’è un ampio delta tra la tensione di ingresso e quella di uscita.

Il Boost Converter è un elemento essenziale per molte applicazioni moderne dove la flessibilità nell’adattare la tensione di ingresso è fondamentale per l’efficienza energetica. Sebbene più complesso di un alimentatore lineare, i suoi vantaggi in termini di efficienza, compattezza e versatilità lo rendono la scelta preferita in una vasta gamma di sistemi elettronici moderni.

In questo progetto specifico, l’uso del Boost Converter è cruciale per regolare una tensione di uscita stabile di 3.3V, anche con una sorgente di ingresso che varia considerevolmente (come una batteria o un supercondensatore), garantendo il corretto funzionamento di un sistema alimentato a batteria.

Nella immagine successiva possiamo vedere l’induttore da 470µH usato nel progetto:

L'induttore da 470µH utilizzato
L’induttore da 470µH utilizzato

Il MOSFET: funzionamento e applicazioni

I MOSFET (Metal-Oxide-Semiconductor Field-Effect Transistor) sono dispositivi semiconduttori che operano come interruttori o amplificatori nei circuiti elettronici. Essi si distinguono per la loro alta efficienza e la capacità di commutare grandi correnti con basse tensioni di controllo. A differenza dei BJT (Bipolar Junction Transistor), che sono controllati dalla corrente, i MOSFET sono controllati dalla tensione applicata al Gate.

Principio di funzionamento

Il MOSFET è costituito da tre terminali principali: il Gate (G), il Drain (D) e il Source (S). La tensione applicata tra il Gate e il Source (VGS) controlla il flusso di corrente tra il Drain e il Source (IDS). I MOSFET si dividono in due categorie principali:

  • MOSFET a canale N: un MOSFET a canale N si attiva quando viene applicata una tensione positiva tra il Gate e il Source. In questo stato, gli elettroni (che sono portatori di carica negativi) formano un canale tra il Drain e il Source, permettendo alla corrente di fluire.
  • MOSFET a canale P: un MOSFET a canale P funziona in modo complementare a quello a canale N. Si attiva con una tensione negativa tra il Gate e il Source, creando un canale che permette il flusso di corrente. I portatori di carica in questo caso sono le lacune (portatori positivi).

MOSFET a riempimento e a svuotamento

I MOSFET possono anche essere classificati in base alla modalità di funzionamento:

  • MOSFET a riempimento (enhancement mode): questo è il tipo più comune. Il dispositivo è normalmente spento quando la tensione Gate-Source è zero, e si accende solo quando viene applicata una tensione sufficiente a creare un canale di conduzione tra il Drain e il Source.
  • MOSFET a svuotamento (depletion mode): in questo tipo di MOSFET, il dispositivo è normalmente acceso (con un canale preesistente tra D e S), e si spegne quando viene applicata una tensione negativa (per il canale N) o positiva (per il canale P) al Gate, che riduce o elimina il canale di conduzione.

Parametri chiave del MOSFET

Quando si seleziona un MOSFET per una specifica applicazione, è importante considerare alcuni parametri fondamentali:

  • Tensione di soglia (Vth): è la tensione minima tra Gate e Source necessaria per iniziare a creare un canale di conduzione tra Drain e Source. Per i MOSFET a canale N, è generalmente positiva, mentre per quelli a canale P è negativa.
  • Resistenza di conduzione (Rds(on)): è la resistenza del canale quando il MOSFET è acceso. Un valore basso di Rds(on) è desiderabile per minimizzare le perdite di potenza e migliorare l’efficienza.
  • Tensione di Drain-Source (Vds max): è la tensione massima che il MOSFET può sopportare tra il Drain e il Source senza subire danni.
  • Corrente di Drain (Id max): è la corrente massima che può fluire attraverso il MOSFET quando è acceso.
  • Capacità di Gate (Cgs, Cgd): indica la capacità del Gate, che influisce sulla velocità di commutazione del MOSFET.

Regioni di funzionamento del MOSFET

Il MOSFET opera in diverse regioni in base alla tensione applicata tra il Gate, il Drain, e il Source:

  • Regione di Interdizione (Cutoff): in questa regione, la tensione Gate-Source è inferiore alla tensione di soglia, il che significa che non esiste un canale conduttivo tra Drain e Source, e il MOSFET è spento.
  • Regione di Triodo: qui, il MOSFET funziona come un resistore controllato dalla tensione. La corrente Drain-Source è proporzionale alla tensione Drain-Source quando il MOSFET è acceso, ed è utilizzato principalmente per applicazioni di commutazione.
  • Regione di Saturazione: in questa regione, la corrente Drain-Source non dipende più dalla tensione Drain-Source, ma solo dalla tensione Gate-Source. Questa regione è utilizzata principalmente nelle applicazioni di amplificazione.

MOSFET vs. BJT

I MOSFET offrono diversi vantaggi rispetto ai BJT:

  • Efficienza energetica: i MOSFET sono controllati dalla tensione e non richiedono corrente per rimanere nello stato attivo, il che li rende più efficienti rispetto ai BJT, che necessitano di corrente di base per funzionare.
  • Velocità di commutazione: i MOSFET hanno tempi di commutazione più rapidi rispetto ai BJT grazie alla loro bassa capacità di Gate e all’assenza di cariche di minoranza.
  • Linearità e distorsione: i BJT tendono ad avere una migliore linearità nella regione attiva, il che può essere un vantaggio nelle applicazioni di amplificazione di precisione, mentre i MOSFET possono introdurre più distorsione in questi casi.

Funzionamento come amplificatore e interruttore

  • Amplificatore: quando opera nella regione di saturazione, il MOSFET può amplificare piccoli segnali analogici. Grazie alla loro alta impedenza di ingresso e alla capacità di essere controllati dalla tensione, i MOSFET sono spesso usati negli stadi di amplificazione RF e audio.
  • Interruttore: quando utilizzato come interruttore, il MOSFET opera nella regione di triodo. Qui, il dispositivo è spento (stato di interdizione) o completamente acceso, comportandosi come un resistore a bassa resistenza. Questa caratteristica rende i MOSFET ideali per le applicazioni di commutazione rapida, come i convertitori di potenza e i circuiti digitali.

I MOSFET sono componenti fondamentali nell’elettronica moderna grazie alla loro efficienza, velocità e versatilità. La loro capacità di operare come interruttori e amplificatori li rende indispensabili in una vasta gamma di applicazioni, dai convertitori di potenza ai circuiti di amplificazione.

Questa panoramica sui MOSFET ti fornisce le basi necessarie per comprendere meglio come questi dispositivi funzionano e come selezionare il MOSFET giusto per il tuo progetto, sia che tu stia costruendo un convertitore boost, un amplificatore, o qualsiasi altro circuito che richieda un’efficace gestione della potenza.

Nell’immagine seguent abbiamo, a sinistra, il MOSFET IRLZ44N e, a destra, il diodo Schottky 1N5822:

A sinistra, il MOSFET IRLZ44N e, a destra, il diodo Schottky 1N5822
A sinistra, il MOSFET IRLZ44N e, a destra, il diodo Schottky 1N5822

Il calcolatore dei parametri del Boost Converter

Questo calcolatore è stato progettato per aiutarti a determinare i parametri chiave del convertitore boost nel progetto. L’interfaccia è intuitiva e ti guiderà attraverso l’inserimento dei dati per ottenere una risposta rapida sui valori più importanti per il dimensionamento e l’analisi del tuo convertitore.

I parametri da inserire

  1. Tensione di ingresso (Vin): questa è la tensione di alimentazione del convertitore. Inserisci il valore della tensione in volt che il sistema riceve dall’alimentazione o dalla batteria.
  2. Tensione di uscita (Vout): è la tensione desiderata all’uscita del convertitore boost, ovvero la tensione che ti aspetti di ottenere dopo il processo di conversione.
  3. Corrente di carico (Iout): indica la corrente richiesta dal carico connesso al convertitore, espressa in ampere. Questo valore è essenziale per determinare il dimensionamento dell’induttore e per calcolare il ripple di corrente.
  4. Frequenza PWM (F): è la frequenza di commutazione del segnale PWM utilizzato per regolare il convertitore. Viene espressa in hertz e influenza direttamente le perdite e le prestazioni del sistema.
  5. Ripple di corrente dell’induttore (ΔI_L): questo valore rappresenta la variazione di corrente (ripple) nell’induttore, espressa in ampere. Un ripple elevato potrebbe indicare la necessità di un induttore più grande o di una frequenza PWM più alta per ridurre le fluttuazioni.
  6. Ripple di tensione di uscita (ΔV_out): indica la variazione di tensione (ripple) all’uscita del convertitore, espressa in volt. Questo valore dipende dalle caratteristiche del carico e dalla capacità del condensatore di uscita.

Dopo aver inserito i valori nei campi appropriati, premi il pulsante “Calcola”. Il calcolatore utilizzerà i parametri forniti per eseguire i calcoli e restituire i valori importanti per il tuo progetto. L’elenco dei risultati:

  1. Duty Cycle: è la percentuale di tempo in cui il segnale PWM è attivo. Per fare un esempio, un duty cycle del 55% indica che il segnale è attivo per più della metà del periodo di commutazione.
  2. Induttore (L): il valore dell’induttore necessario per il tuo convertitore boost, calcolato in microhenry (µH) o in millihenry (mH). Questo valore è quello suggerito per il corretto funzionamento del convertitore, poiché influenza la stabilità e il ripple di corrente.
  3. Condensatore di Uscita (Cout): indica il valore del condensatore di uscita necessario per mantenere stabile la tensione in uscita, generalmente calcolato in microfarad (µF). Il valore fornito suggerisce la dimensione del condensatore per ridurre le variazioni di tensione (ripple) in uscita.
  4. Corrente di Picco Assorbita (I_in Peak): questo valore, espresso in ampere (A), rappresenta la corrente massima assorbita all’ingresso del convertitore durante il funzionamento.
  5. Corrente RMS Assorbita (I_in RMS): indica la corrente effettiva (RMS) assorbita all’ingresso del convertitore. Questo valore è generalmente inferiore alla corrente di picco, poiché rappresenta la corrente efficace assorbita.

Questi risultati forniscono una panoramica completa sui parametri chiave del circuito, aiutando l’utente a dimensionare correttamente i componenti e a valutare il comportamento del sistema.

Tabella dei criteri di scelta per MOSFET e diodi Schottky

ParametroMOSFET ConsigliatoDiodo Schottky Consigliato
Vout ≤ 30V, IinPeak ≤ 30AIRLZ44N (55V, 47A, Rds(on): 0.022Ω, TO-220)1N5822 (40V, 3A, Vf: 0.525V, DO-201)
Vout ≤ 60V, IinPeak ≤ 15AIRF540N (100V, 33A, Rds(on): 0.044Ω, TO-220)1N5822 (40V, 3A, Vf: 0.525V, DO-201)
Vout > 60V o IinPeak > 15AVerifica un MOSFET con tensione e corrente più elevate.Verifica un diodo Schottky con tensione e corrente più elevate.
Vout ≤ 40V, IinPeak ≤ 3AIRLZ44N (55V, 47A, Rds(on): 0.022Ω, TO-220)1N5822 (40V, 3A, Vf: 0.525V, DO-201)
Vout ≤ 100V, IinPeak ≤ 20AIRF540N (100V, 33A, Rds(on): 0.044Ω, TO-220)MBR360 (60V, 3A, Vf: 0.525V, DO-201)

Spiegazione dei parametri

  • Vout: tensione di uscita del convertitore Boost. È importante scegliere un MOSFET e un diodo che possano gestire la tensione massima prevista.
  • IinPeak: corrente di picco assorbita dal circuito. Questo parametro determina la capacità di gestione della corrente da parte del MOSFET e del diodo.
  • Rds(on): resistenza di accensione del MOSFET, che influisce sull’efficienza del convertitore. Valori più bassi sono preferibili per ridurre le perdite di potenza.

Il segnale PWM

Abbiamo visto che il segnale utilizzato per controllare il Boost Converter è di tipo PWM. Il segnale PWM (Pulse Width Modulation) è una tecnica usata per modulare la larghezza di un impulso, in modo da controllare la quantità media di potenza fornita a un carico. Il segnale PWM è un’onda quadra che alterna periodi ON (dove il segnale è attivo, o alto) e OFF (dove il segnale è inattivo, o basso).

Caratteristiche principali del segnale PWM

  • Frequenza: la frequenza rappresenta quante volte il segnale si ripete in un secondo. Una frequenza più alta implica cicli più veloci del segnale PWM.
  • Duty Cycle: è la percentuale del tempo in cui il segnale è alto (ON) rispetto alla durata totale del ciclo (periodo). Ad esempio, un duty cycle del 50% significa che il segnale è attivo per la metà del ciclo, mentre un duty cycle del 75% indica che il segnale è attivo per il 75% del tempo. Il duty cycle è essenziale per modulare la potenza media fornita: maggiore è il duty cycle, maggiore è la potenza erogata al carico.

Il segnale PWM (Pulse Width Modulation) è una tecnica usata per modulare la larghezza di un impulso, in modo da controllare la quantità media di potenza fornita a un carico. Il segnale PWM è un’onda quadra che alterna periodi ON (dove il segnale è attivo, o alto) e OFF (dove il segnale è inattivo, o basso).

Il Duty Cycle può essere calcolato tramite la seguente formula:

blank

Utilizzi del PWM

  1. Controllo dei motori: il PWM è comunemente usato per regolare la velocità dei motori DC, poiché modulando il duty cycle si varia la potenza fornita al motore.
  2. Illuminazione a LED: modificando il duty cycle di un segnale PWM, è possibile regolare l’intensità luminosa di un LED. Un duty cycle più elevato significa più tempo ON, e quindi una luminosità maggiore.
  3. Alimentatori a commutazione: nei convertitori DC-DC, come i convertitori boost e buck, il segnale PWM controlla i transistor di commutazione per regolare la tensione di uscita in base alle esigenze del circuito.
  4. Modulazione Audio: il PWM viene anche usato nei sistemi audio per trasmettere segnali analogici in digitale, come nella codifica di suoni o segnali audio.

Come si ottiene

Un segnale PWM può essere generato facilmente attraverso microcontrollori come l’ESP32, che dispone di timer integrati per la gestione del segnale. In generale, si imposta una frequenza e un duty cycle, e il microcontrollore gestisce l’alternanza tra gli stati ON e OFF del segnale in base a questi parametri.

Nel contesto del progetto del Boost Converter, il PWM viene utilizzato per controllare la commutazione del transistor che regola la tensione di uscita. Modificando il duty cycle del segnale PWM, è possibile controllare quanta energia viene accumulata nell’induttore e trasferita al carico, influenzando così la tensione e la corrente di uscita.

Il PID

Prima di illustrare il funzionamento del PID, chiariamo il concetto di sistema di regolazione a ciclo chiuso come quello mostrato nell’immagine seguente:

Sistema di regolazione a ciclo chiuso con PID
Sistema di regolazione a ciclo chiuso con PID

Un sistema di regolazione a ciclo chiuso, come quello mostrato nell’immagine, viene utilizzato per controllare processi in cui la variabile di uscita deve essere mantenuta vicina a un valore di riferimento. Vediamo i principali blocchi del sistema:

Segnale di riferimento X(t): questo rappresenta il valore desiderato che vogliamo ottenere all’uscita del sistema. Può essere, ad esempio, una tensione o una velocità target.

Segnale di errore e(t): è la differenza tra il segnale di riferimento e il valore effettivo della grandezza regolata (feedback). Questa differenza è l’errore, e rappresenta il segnale che il PID utilizza per correggere il sistema. Formula:

blank

Regolatore PID: il blocco PID prende l’errore e(t) e lo processa con tre componenti fondamentali: Proporzionale (P), Integrale (I), e Derivativa (D), come descritto nel paragrafo successivo. L’uscita del PID viene quindi inviata al processo che deve essere controllato.

Processo controllato P(t): questo è il sistema fisico o il componente che viene regolato, come ad esempio un motore o un convertitore boost nel nostro progetto. L’uscita Y(t) è la variabile che desideriamo controllare, come ad esempio la tensione di uscita in un convertitore o la velocità di rotazione di un motore elettrico.

Retroazione H(t): una parte dell’uscita Y(t) viene restituita al regolatore sotto forma di feedback. Questo permette al sistema di “sapere” quanto si avvicina il valore corrente dell’uscita al riferimento.

Funzionamento complessivo

Il sistema si regola in modo da minimizzare l’errore e(t), correggendo continuamente la variabile controllata. In un convertitore boost, ad esempio, la tensione di uscita viene monitorata e confrontata con il valore di riferimento (es. 3.3V). Se l’errore aumenta, il PID interviene aumentando o diminuendo il duty cycle del PWM per mantenere la tensione di uscita stabile.

Il PID, come vedremo, ha tre componenti:

  • Proporzionale: agisce sull’errore corrente e tende a ridurlo rapidamente.
  • Integrale: si occupa di correggere gli errori passati e stabilizza la risposta del sistema a lungo termine.
  • Derivativo: predice gli errori futuri in base alla velocità di variazione dell’errore e riduce oscillazioni o sovraelongazioni.

Nella teoria dei controlli, è importante distinguere tra sistemi di regolazione e sistemi di asservimento (o servosistemi).

Sistemi di regolazione

Un sistema di regolazione è un sistema di controllo progettato per mantenere una variabile di uscita costante, nonostante possibili variazioni nei parametri del sistema o nell’ambiente circostante. Il compito principale del regolatore è stabilizzare l’uscita rispetto a un valore di riferimento fisso, cercando di minimizzare l’errore tra il valore desiderato e il valore misurato.

Esempi classici di sistemi di regolazione includono:

  • Controllo della temperatura in un forno, dove il sistema deve mantenere una temperatura costante.
  • Regolatori di tensione, come nel nostro progetto di Boost Converter, dove la tensione in uscita viene mantenuta stabile a 3.3V, indipendentemente dalle fluttuazioni della tensione di ingresso o dalle variazioni del carico.

Sistemi di asservimento

Dall’altro lato, un sistema di asservimento (o servosistema) non solo cerca di mantenere una variabile stabile, ma è progettato per seguire un segnale di riferimento variabile nel tempo. In questo caso, il segnale di riferimento non è statico, ma può cambiare in modo continuo o discreto, e il sistema deve “inseguire” questo segnale in modo che l’uscita segua fedelmente le variazioni del riferimento.

Esempi di servosistemi includono:

  • Sistemi di controllo di posizione, come nei motori che azionano il braccio di un robot, dove il sistema deve seguire i movimenti programmati (il riferimento) nel modo più preciso possibile.
  • Controlli di velocità, come nei sistemi di cruise control di un’auto, dove il sistema cerca di mantenere la velocità impostata ma può reagire ai cambiamenti dinamici dell’ambiente (salite, discese, ecc.).

Relazione tra PID e sistemi di asservimento/regolazione

Un PID può essere utilizzato in entrambe le tipologie di sistemi. Nel caso di un sistema di regolazione, il PID si occupa di stabilizzare l’uscita rispetto a un valore fisso (come mantenere la tensione del Boost Converter a 3.3V). Nel caso di un sistema di asservimento, invece, il PID regola l’uscita in modo da seguire il segnale di riferimento variabile (come controllare la velocità di un motore che varia in funzione del tempo).

Il nostro progetto di Boost Converter è un sistema di regolazione, poiché vogliamo mantenere la tensione di uscita costante a un valore specifico. Tuttavia, in applicazioni come quelle in cui il segnale di riferimento varia nel tempo, si entra nel campo dei sistemi di asservimento, dove lo scopo è che l’uscita segua fedelmente queste variazioni. Il PID è versatile e può essere configurato per lavorare in entrambi i contesti.

Questo approfondimento permette di comprendere meglio la distinzione tra mantenere un valore costante e seguire un valore che cambia dinamicamente.

Il PID controller (Proportional-Integral-Derivative) è uno dei più diffusi e utilizzati algoritmi di controllo in ingegneria, particolarmente adatto per applicazioni di regolazione automatica in sistemi di controllo ad anello chiuso. È stato introdotto nei primi decenni del XX secolo, e il suo sviluppo si deve in gran parte all’avvento della teoria del controllo moderno. Il PID controlla una variabile di processo (PV) confrontandola con un valore di riferimento o setpoint (SP), e cerca di minimizzare l’errore, ossia la differenza tra il valore desiderato e il valore reale. L’output del controller agisce su un attuatore, come una valvola, un motore o altri dispositivi, per regolare il processo in base a tre componenti principali: proporzionale (P), integrale (I) e derivativo (D).

Componente Proporzionale (P): la parte proporzionale è direttamente proporzionale all’errore attuale. Il termine proporzionale Kp amplifica l’errore, fornendo una risposta immediata al controller. Se Kp è troppo basso, il sistema sarà lento a rispondere; se è troppo alto, il sistema potrebbe diventare instabile. Più alto è il Kp, maggiore sarà l’azione correttiva per un dato errore.

blank

Dove e(t) è l’errore al tempo t e Kp è il guadagno proporzionale.

Componente Integrale (I): la parte integrale accumula gli errori passati, aiutando a ridurre l’errore stazionario che la parte proporzionale da sola non può eliminare. L’integrale “ricorda” l’errore passato e continua a sommare fino a quando l’errore non viene eliminato. Il termine integrale Ki è particolarmente utile quando il sistema non riesce a raggiungere esattamente il setpoint.

blank

Dove Ki è il guadagno integrale.

Componente Derivativa (D): il termine derivativo prevede il futuro comportamento del sistema in base alla velocità di variazione dell’errore. Aiuta a ridurre l’overshoot e migliora la stabilità del sistema attenuando i cambiamenti troppo rapidi. Questa componente agisce sulla “pendenza” dell’errore e cerca di prevenire errori futuri.

blank

Dove Kd​ è il guadagno derivativo.

Formula del PID

Combinando le tre componenti si ottiene l’equazione completa del PID:

blank

Dove:

  • u(t) è il segnale di controllo che regola l’attuatore.
  • e(t) è l’errore, cioè la differenza tra il setpoint e la variabile di processo.

Effetti delle componenti P, I, D

  • Kp aumenta la risposta del sistema, ma può causare instabilità se troppo alto.
  • Ki riduce l’errore stazionario, ma può introdurre oscillazioni se sovrastimato.
  • Kd attenua le oscillazioni e riduce l’overshoot, migliorando la stabilità.

Ottimizzazione e tuning del PID

Uno degli aspetti cruciali per l’efficacia del PID è la sintonia (tuning) dei tre guadagni. Tecniche comuni per il tuning includono:

  • Metodo di Ziegler-Nichols: una procedura empirica che aiuta a trovare valori iniziali per Kp, Ki, e Kd.
  • Sintonizzazione manuale: basata su tentativi ed errori, dove i valori vengono aggiustati fino a ottenere la risposta desiderata.
  • Sintonizzazione automatica: algoritmi software avanzati che calcolano in modo dinamico i valori ottimali di Kp, Ki e Kd in base alla risposta del sistema.

Utilizzi del PID

Il PID è utilizzato in numerose applicazioni industriali e non solo. Alcuni esempi includono:

  • Controllo della temperatura (come in forni o sistemi HVAC).
  • Controllo della velocità dei motori.
  • Sistemi di controllo della pressione.
  • Controllo di processi chimici e produzione industriale.

Vantaggi e limiti del PID

Vantaggi:

  • Semplice da implementare e concettualmente facile da capire.
  • Applicabile a una vasta gamma di processi.
  • Adatto per sistemi lineari e non lineari.

Limiti:

  • Può richiedere un tuning accurato per ottenere prestazioni ottimali.
  • Il termine derivativo è sensibile al rumore nel segnale, quindi potrebbe peggiorare la stabilità in presenza di rumore elevato.
  • Non è ideale per sistemi con tempi morti lunghi.

PID nei sistemi embedded

Nel contesto di sistemi embedded, come il tuo progetto con ESP32, la libreria PID semplifica molto l’implementazione del controllo. Ad esempio, il PID in sistemi di controllo di tensione e corrente, come nel caso del Boost Converter, regola dinamicamente il duty cycle del segnale PWM per mantenere costante la tensione di uscita anche quando le condizioni variano, come la caduta di tensione della batteria o una variazione del carico.

In conclusione, il PID è uno strumento molto potente che consente di ottenere controllo preciso e affidabile in un’ampia gamma di applicazioni. È essenziale avere una buona comprensione delle dinamiche del sistema per impostare correttamente i parametri e sfruttare appieno le potenzialità di questo tipo di regolatore.

La libreria PID_v1

La libreria PID_v1 per Arduino è una delle implementazioni più diffuse e ben strutturate del controllo PID (Proporzionale, Integrale, Derivativo) in ambiente Arduino e microcontrollori. Il PID è un algoritmo di controllo usato in vari campi dell’automazione per mantenere una variabile d’uscita (ad esempio la temperatura, la velocità o la tensione) vicina a un valore desiderato, chiamato setpoint. Questo viene fatto calcolando l’errore tra il setpoint e il valore attuale della variabile, e regolando l’uscita del sistema per minimizzare questo errore nel tempo.

Composizione dell’algoritmo PID

Componente Proporzionale (P): questa componente è proporzionale all’errore attuale. Se l’errore è grande, l’azione correttiva sarà grande, e viceversa. Il fattore di proporzionalità è chiamato Kp. Se Kp è troppo alto, l’uscita può oscillare; se è troppo basso, il sistema potrebbe rispondere troppo lentamente.

Componente Integrale (I): la componente integrale considera la somma degli errori passati. Se l’errore persiste nel tempo, l’integrale accumulerà e l’azione correttiva aumenterà. Il fattore Ki controlla il peso di questa componente. Se Ki è troppo alto, il sistema potrebbe reagire in modo eccessivo, causando instabilità.

Componente Derivativa (D): la componente derivativa si basa sulla velocità di cambiamento dell’errore. Se l’errore sta cambiando rapidamente, la componente derivativa risponderà per smorzare questo cambiamento. Il fattore Kd controlla l’influenza di questa componente. Se Kd è troppo alto, può causare rumore nel sistema.

Funzionamento della libreria PID_v1

La libreria PID_v1 di Arduino offre un modo semplice e strutturato per implementare il controllo PID su microcontrollori, facilitando l’interazione con sensori e attuatori. La libreria fornisce tutti gli strumenti necessari per la gestione del PID in real-time, calcolando le tre componenti (P, I, D) e producendo un’uscita regolata che viene applicata al sistema di controllo.

Componenti principali della libreria:

  1. Costruttore del PID: quando inizializzi un oggetto PID, passi tre parametri fondamentali:
    • Input: la variabile da controllare (ad esempio, la temperatura letta da un sensore). Setpoint: il valore desiderato della variabile da controllare. Output: la variabile su cui l’algoritmo PID agirà (ad esempio, la velocità di un motore o la potenza di un riscaldatore).
    Ecco un esempio di dichiarazione: PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
  2. Funzione Compute(): questa è la funzione principale che esegue i calcoli del PID e aggiorna l’uscita in base all’input corrente. Deve essere chiamata ripetutamente nel ciclo loop() per assicurarsi che l’algoritmo continui a regolare l’uscita. Ecco un esempio di dichiarazione: myPID.Compute();
  3. Modalità di controllo: il PID può funzionare in modalità AUTOMATIC o MANUAL. In modalità manuale, l’output non viene regolato dal PID, ma può essere impostato manualmente. Questo è utile se si vuole testare o disattivare temporaneamente l’algoritmo.
  4. Impostazione dei limiti di uscita: la libreria ti consente di impostare i limiti dell’uscita in modo che il valore generato dal PID rimanga entro un intervallo accettabile (ad esempio, 0-255 per il controllo PWM): myPID.SetOutputLimits(0, 255);
  5. Aggiornamento dei parametri PID: la libreria permette di aggiornare i valori di Kp, Ki e Kd in qualsiasi momento durante l’esecuzione: myPID.SetTunings(newKp, newKi, newKd);
  6. Modalità di direzione: il PID può funzionare in modalità DIRECT o REVERSE, a seconda di come l’uscita deve influenzare il sistema. Ad esempio, se l’aumento dell’uscita riduce l’input, allora si dovrebbe usare la modalità REVERSE.

Vantaggi della libreria PID_v1:

  • Facilità d’uso: anche se l’algoritmo PID può essere complesso, la libreria lo rende accessibile anche a chi ha poca esperienza nel controllo automatico, fornendo un’interfaccia semplice e intuitiva.
  • Efficienza: la libreria è ottimizzata per girare su microcontrollori come l’ESP32 o Arduino, permettendo un calcolo rapido ed efficiente.
  • Flessibilità: la possibilità di configurare i parametri, impostare limiti e cambiare la direzione del controllo offre grande flessibilità nella gestione di una vasta gamma di sistemi fisici.

Applicazioni tipiche

La libreria PID_v1 viene usata comunemente per controllare:

  • Motori DC o Servo: regolazione della velocità o posizione.
  • Sistemi di riscaldamento: regolazione della temperatura in sistemi HVAC o stampanti 3D.
  • Controllo di tensione o corrente: come nei convertitori boost o buck.

In sintesi, la libreria PID_v1 per Arduino è un potente strumento per implementare sistemi di controllo di precisione, rendendo accessibile il controllo automatico anche per progetti amatoriali o didattici. La possibilità di gestire in modo modulare le tre componenti del PID la rende una soluzione versatile per molte applicazioni di automazione.

I moduli INA219

Nel progetto, i moduli INA219 vengono utilizzati per monitorare in modo preciso sia la tensione che la corrente in ingresso e in uscita dal convertitore boost. Questi sensori, collegati tramite il bus I2C, permettono di effettuare misurazioni in tempo reale e di trasmettere i dati al microcontrollore ESP32.

Il sensore INA219 è un modulo versatile progettato per misurare la corrente attraverso un resistore di shunt e la tensione sul bus. È in grado di rilevare correnti fino a 3.2 A (a seconda della configurazione) e tensioni fino a 32V. La sua alta precisione e la capacità di configurare diverse modalità di risoluzione lo rendono ideale per applicazioni come il monitoraggio di alimentatori, convertitori DC-DC, o qualsiasi altro sistema che richieda un controllo accurato di corrente e tensione.

Nel progetto, due moduli INA219 sono utilizzati con indirizzi I2C distinti:

  • I2C_ADDRESS_in: per monitorare la tensione e la corrente in ingresso al convertitore.
  • I2C_ADDRESS_out: per monitorare la tensione e la corrente in uscita dal convertitore.

Il microcontrollore legge questi dati attraverso la comunicazione I2C e li utilizza per controllare il loop di feedback del PID, che regola il duty cycle del PWM per mantenere la tensione di uscita desiderata (3.3V). Quando la tensione in ingresso scende sotto una soglia predefinita dall’utente, lo sketch disabilita automaticamente il PID, mettendo a zero il duty cycle del PWM e spegnendo il convertitore.

Una delle caratteristiche più utili di questi moduli è la possibilità di configurare il loro indirizzo I2C, permettendo di collegare più sensori allo stesso bus senza conflitti di indirizzo.

Configurazione degli indirizzi I2C sui moduli INA219

Gli indirizzi I2C dei moduli INA219 sono configurabili tramite dei pad di selezione dell’indirizzo, chiamati A0 e A1, presenti sul modulo. In base alla configurazione di questi pad, si può assegnare uno tra quattro possibili indirizzi al modulo.

Ecco le configurazioni degli indirizzi I2C in base allo stato dei pin A0 e A1. In pratica si possono saldare tra loro i pad indicati con A0, oppure saldare tra loro i pad indicati con A1 oppure saldare tra loro i pad indicati con A0 e , sempre tra loro, saldare i pad indicati con A1:

  • pad A0 non saldati, pad A1 non saldati: indirizzo I2C predefinito è 0x40
  • pad A0 saldati, pad A1 non saldati: indirizzo I2C è 0x41
  • pad A0 non saldati, pad A1 saldati: indirizzo I2C è 0x44
  • pad A0 saldati, pad A1 saldati: indirizzo I2C è 0x45.

Nel nostro progetto il modulo in uscita ha indirizzo 0x40 in quanto i pad A0 e A1 sono tutti NON saldati mentre il modulo in ingresso ha indirizzo 0x44 in quanto i pad A0 sono NON saldati mentre i pad A1 sono saldati tra loro.

Questa configurazione permette di gestire entrambi i sensori con un singolo bus I2C, senza conflitti di indirizzo, garantendo così letture accurate e affidabili di corrente e tensione per il sistema di controllo del PID.

Se devi aggiungere più sensori o modificarne gli indirizzi, puoi farlo facilmente cambiando lo stato dei pin A0 e A1, permettendo una gestione flessibile del bus I2C.

Nella foto seguente la coppia di sensori, uno con i connettori non saldati e l’altro con i connettori saldati:

Sensori INA219
Sensori INA219

Se hai necessità di saldare i connettori ma non sai come si effettua una saldatura, ti invito a dare un’occhiata all’articolo Un altro tutorial su come saldare su questo stesso blog.

Abbiamo detto che i sensori INA 219 comunicano tramite protocollo I2C. Come funziona questo protocollo?

Interfaccia I2C

Il protocollo I2C, noto anche come Two-Wire Interface (TWI), è uno standard di comunicazione seriale che consente la trasmissione di dati tra dispositivi elettronici. Questo protocollo è ampiamente utilizzato in molte applicazioni, inclusi i microcontroller, per facilitare la comunicazione tra diversi componenti di un sistema. Il protocollo I2C è caratterizzato da alcune caratteristiche chiave che lo rendono ideale per applicazioni di basso consumo energetico e con limitate risorse hardware.

  • Comunicazione bidirezionale: I2C supporta la comunicazione bidirezionale, permettendo a un dispositivo di inviare dati a un altro dispositivo e viceversa. Questa caratteristica è particolarmente utile in sistemi che richiedono un’interazione continua tra componenti.
  • Uso di due linee: come suggerisce il nome, I2C utilizza solo due linee per la comunicazione: una per il clock (SCL) e una per i dati (SDA). Questo riduce significativamente il numero di pin necessari per la comunicazione, rendendo il protocollo ideale per dispositivi con limitate risorse di pin.
  • Gestione dell’indirizzo: ogni dispositivo I2C ha un indirizzo unico, permettendo a più dispositivi di comunicare sulla stessa linea di clock e dati. Questo sistema di indirizzamento consente una comunicazione efficiente e organizzata tra i dispositivi. È da rimarcare il fatto che su tale bus non possono coesistere dispositivi con lo stesso indirizzo.
  • Comunicazione con velocità standard e a bassa velocità: I2C supporta velocità di comunicazione standard fino a 100 kHz e a bassa velocità fino a 400 kHz. Queste velocità sono sufficienti per la maggior parte delle applicazioni, rendendo il protocollo adatto per dispositivi che non richiedono velocità di comunicazione elevate.
  • Compatibilità e facilità d’uso: il protocollo I2C è ampiamente supportato da molte piattaforme e dispositivi, rendendolo una scelta popolare per la comunicazione tra componenti. La sua semplicità e la presenza di molte librerie e documentazione lo rendono facile da implementare e da utilizzare.

Il protocollo I2C è un esempio perfetto di come la progettazione di protocolli di comunicazione possa essere semplice e potente, offrendo una soluzione efficiente e versatile per la comunicazione tra dispositivi in un’ampia gamma di applicazioni.

Ma il nostro progetto prevede anche l’utilizzo di alcune API REST. Vediamo più in dettaglio di cosa si tratta.

Le API REST

Le API REST (Representational State Transfer) sono un paradigma di comunicazione molto diffuso, soprattutto nel contesto dell’Internet of Things (IoT), che permette l’interazione tra diversi sistemi attraverso un’interfaccia standardizzata e semplice da usare. Introdotte da Roy Fielding nei primi anni 2000, le API REST si basano su principi architetturali che sfruttano il protocollo HTTP per permettere a dispositivi, servizi e applicazioni di comunicare tra loro in modo scalabile, efficiente e indipendente dalla piattaforma.

Scopo delle API REST

Le API REST servono a esporre funzionalità di un sistema o servizio a un’altra applicazione, sia essa un’app mobile, un’applicazione web o un dispositivo IoT. Questo avviene tramite operazioni CRUD (Create, Read, Update, Delete) che mappano direttamente sulle operazioni HTTP: POST, GET, PUT/PATCH, DELETE. In pratica, queste API permettono di leggere, creare, modificare e cancellare risorse su un server remoto, il tutto utilizzando richieste HTTP semplici e facilmente comprensibili.

Tipi di API REST

Le API REST possono essere classificate in diversi tipi a seconda del tipo di risorsa che gestiscono:

  • API REST JSON: le risposte vengono fornite in formato JSON (JavaScript Object Notation), il formato più comune e leggibile per la trasmissione di dati strutturati.
  • API REST XML: anche se meno comune di JSON, alcune API REST utilizzano XML (eXtensible Markup Language) per rappresentare le risorse.
  • API REST Streaming: utilizzate per trasmettere grandi flussi di dati in tempo reale, come video o dati di sensori IoT.

Importanza delle API REST nell’IoT

Nel contesto dell’IoT, le API REST sono fondamentali per diverse ragioni:

  • Interoperabilità: consentono a dispositivi eterogenei di comunicare tra loro, indipendentemente dal loro sistema operativo o linguaggio di programmazione.
  • Scalabilità: grazie alla loro architettura leggera, le API REST sono facilmente scalabili, il che le rende ideali per ambienti IoT con un numero crescente di dispositivi connessi.
  • Facilità di implementazione: le API REST sono semplici da implementare e comprendere, rendendo più rapido lo sviluppo di applicazioni IoT.
  • Accessibilità: permettono ai dispositivi di essere accessibili da qualsiasi luogo, favorendo la gestione e il controllo remoto di sistemi IoT, attraverso reti globali come Internet.

Perché le API REST sono importanti

Le API REST rappresentano un ponte tra il mondo fisico e quello digitale. Nell’IoT, dove i dispositivi generano e consumano grandi quantità di dati, le API REST forniscono un metodo strutturato e standardizzato per accedere a questi dati e utilizzarli in applicazioni diverse. Facilitano l’integrazione tra sistemi nuovi e legacy, migliorando l’interoperabilità e riducendo la complessità dello sviluppo. Inoltre, grazie alla loro flessibilità, le API REST possono essere utilizzate per una vasta gamma di applicazioni, dal controllo domestico alla gestione di grandi impianti industriali.

Le API REST sono un elemento chiave per lo sviluppo di soluzioni IoT moderne. Offrono un’interfaccia universale che semplifica la comunicazione tra dispositivi e servizi, garantendo flessibilità, scalabilità e facilità di uso. Grazie alla loro adozione globale, rappresentano uno standard di fatto per la creazione di ecosistemi IoT interconnessi e interoperabili.

Se sei particolarmente interessato all’uso delle API REST, ti invito a dare un’occhiata all’articolo Come realizzare un server API REST con la ESP32 che spiega come creare un server web con la ESP32 in modo che questa esponga un set di API REST da utilizzare per interagire col dispositivo in modo da ricevere o mandare dei dati.

In questo progetto sono previste due sole API REST: la get-parameters che ci restituisce un documento Json contenente i valori di tensione e corrente in ingresso e uscita del Boost Converter, il Duty Cycle del segnale di controllo, lo stato del PID e i suoi parametri (Kp, Ki e Kd); la set-pid che ci consente di modificare i parametri di funzionamento del PID (Kp, Ki e Kd).

Per testare le API REST in questo progetto ci avvarremo di un noto software: Postman.

Postman

Postman è uno strumento potente e versatile utilizzato per testare e sviluppare API REST, essenziale per chiunque lavori con comunicazioni tra server e client, specialmente nell’ambito dell’Internet of Things (IoT). Grazie alla sua interfaccia intuitiva, Postman consente di inviare richieste HTTP di tipo GET, POST, PUT, DELETE e di visualizzare le risposte in tempo reale. Questo facilita il debugging e la verifica del corretto funzionamento delle API, rendendolo uno strumento indispensabile per sviluppatori e ingegneri.

Una delle principali caratteristiche di Postman è la sua capacità di simulare richieste API in modo preciso, permettendo di testare le interazioni tra diversi dispositivi o tra un dispositivo e un server remoto. Questo è particolarmente utile quando si sviluppano applicazioni IoT, dove i dispositivi devono spesso comunicare con servizi cloud o scambiarsi dati in tempo reale. Inoltre, Postman supporta la creazione di collezioni di richieste, che possono essere salvate e riutilizzate, rendendo il processo di test più efficiente e strutturato.

In sintesi, Postman non è solo un semplice client per testare API, ma un vero e proprio strumento di sviluppo che supporta l’intero ciclo di vita delle API, dalla progettazione al test, fino al monitoraggio. Nel contesto dell’IoT, la sua capacità di gestire e testare le API REST in modo efficiente lo rende un alleato indispensabile per garantire che i dispositivi possano comunicare tra loro senza problemi. Integrando Postman nel tuo workflow, puoi assicurarti che le API che sviluppi siano robuste, affidabili e pronte per essere implementate in ambienti di produzione.

Di che componenti abbiamo bisogno?

La lista dei componenti non è particolarmente lunga:

  • una breadboard per connettere la NodeMCU ESP32 agli altri componenti
  • alcuni fili DuPont (maschio – maschio, maschio – femmina, femmina – femmina)
  • due moduli INA219
  • un induttore da 470µH
  • un resistore da 47Ω
  • un resistore da 10kΩ
  • un resistore da 330Ω
  • un resistore da 33Ω 1W
  • un MOSFET IRLZ44N
  • un diodo Schottky 1N5822
  • un condensatori elettrolitico da 100µF 50V
  • 4 porta batterie AA singoli
  • 4 batterie AA da 1.5V
  • e, ovviamente, una NodeMCU ESP32 !

Il modello di ESP32 scelto per questo progetto è quello dell’azienda AZ-Delivery.

Nella foto seguente è possibile vedere un esemplare di portabatteria AA singolo:

Portabatteria AA singolo
Portabatteria AA singolo

Dovremo collegare quattro di questi portabatteria in parallelo, quindi collegando tutti i fili rossi assieme tra loro e i fili neri assieme tra loro. Questo “pacco batterie” ci fornirà la tensione a 1.5V da fare entrare in ingresso al Boost Converter in modo che la elevi a 3.3V sul carico. Perché proprio quattro batterie e non una o due? In realtà potremmo collegarne in parallelo anche dieci. Il punto è che mentre la tensione rimane sempre 1.5V, la corrente erogata si somma quindi quante più sono le batterie tanto più grande è la corrente che possono fornire. Il problema della alta corrente in ingresso non è particolarmente sentito quando il carico è pari a 330Ω in quanto esso, a 3.3V, assorbirà solo 10mA. Ma quando faremo l’esperimento col resistore da 33Ω 1W (che a 3.3V assorbirà 100mA) questo relativamente alto valore di corrente fornito dalle batterie in parallelo sarà necessario. Una sola batteria si scaricherebbe in brevissimo tempo e potrebbe addiritura non essere in grado di mantenere la sua tensione a 1.5V dato l’altro assorbimento da parte del Boost Converter.

Realizzazione del progetto

Lo schema elettrico

Prima di realizzare il circuito vero e proprio diamo un’occhiata al pinout della board:

Pinout della ESP32
Pinout della ESP32

Lo schema elettrico, realizzato con Fritzing, non è proprio immediato ma neanche troppo difficile. Lo possiamo osservare nell’immagine successiva:

Schema di realizzazione del Boost Converter controllato da PID con ESP32
Schema di realizzazione del Boost Converter controllato da PID con ESP32

Lo sketch

Creiamo il progetto PlatformIO

Abbiamo già visto la procedura di creazione di un progetto PlatformIO nell’articolo Come creare un progetto per NodeMCU ESP8266 con PlatformIO.

Anche se si riferisce alla board ESP8266, la procedura è simile.
Semplicemente, nella scelta della piattaforma, dovrai scegliere la AZ-Delivery ESP-32 Dev Kit C V4.

Non installare nessuna delle librerie indicate nell’articolo.

Ora modifica il file platformio.ini per aggiungere alcune righe in modo che il file abbia un aspetto del genere:

[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
framework = arduino
monitor_speed = 115200
upload_speed = 921600
lib_deps = 
	SPIFFS
	wollewald/INA219_WE@^1.3.8
	br3ttb/PID@^1.2.1
	wnatth3/WiFiManager @ 2.0.16-rc.2
	me-no-dev/ESP Async WebServer @ ^1.2.3
	bblanchon/ArduinoJson @ ^6.18.5

Le librerie utilizzate sono numerose: abbiamo la SPIFFS per gestire il file system che conterrà la pagina web dell’applicazione e che sarà consultabile sia da browser nel pc che nel cellulare, la libreria per la gestione del PID, la libreria WiFiManager per la gestione della connessione WiFi di cui parleremo in seguito, le librerie ESP Async WebServer e ArduinoJson che gestiranno le API REST e le loro risposte in formato Json.

Puoi comunque scaricare il progetto dal link seguente:

decomprimerlo, prendere il file main.cpp e sostituirlo al posto di quello che hai nel progetto precedentemente creato.

Poi, nel progetto che hai creato, crea una cartella di nome data allo stesso livello della cartella src e crea al suo interno un file vuoto che chiamerai index.html.

All’interno di questo file copia il seguente codice:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Boost Converter Monitoring</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
    }
    .container {
      max-width: 800px;
      margin: auto;
    }
    canvas {
      margin: 20px 0;
    }
    .info-container {
      margin-top: 40px;
      padding: 20px;
      border: 1px solid #ccc;
      border-radius: 10px;
      background-color: #f9f9f9;
    }
    .info-container p {
      font-size: 18px;
    }
    #resetButton {
      background-color: red;
      color: white;
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    #resetButton:hover {
      background-color: darkred;
    }
    #pidStatus {
      font-weight: bold;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>Boost Converter Monitoring</h2>

    <canvas id="voltageChart" width="400" height="200"></canvas>
    <canvas id="currentChart" width="400" height="200"></canvas>

    <div class="info-container">
      <p>PWM Value: <span id="pwmValue">N/A</span></p>
      <p>Duty Cycle: <span id="dutyCycle">N/A</span>%</p>
      <p>PID Status: <span id="pidStatus">N/A</span></p>
      <h3>PID Parameters (Read Only)</h3>
      <p>Kp: <span id="kpValue">N/A</span></p>
      <p>Ki: <span id="kiValue">N/A</span></p>
      <p>Kd: <span id="kdValue">N/A</span></p>
    </div>

    <button id="resetButton" onclick="resetESP()">Reset ESP32</button>
  </div>

  <script>
    const ESP32_IP = window.location.hostname;
    let voltageChart, currentChart;

    // loads parameters and refresh the page
    function loadParameters() {
      fetch(`http://${ESP32_IP}/api/get-parameters`)
        .then(response => response.json())
        .then(data => {
          console.log(data); // verufy if JSON contains data
          // Update PWM, Duty Cycle and PID parameters
          document.getElementById('pwmValue').innerText = data.pwm_value.toFixed(1);
          document.getElementById('dutyCycle').innerText = data.duty_cycle.toFixed(1);

          // updates PID status with colors
          const pidStatusElement = document.getElementById('pidStatus');
          pidStatusElement.innerText = data.pid_status;
          if (data.pid_status === "ON") {
            pidStatusElement.style.color = "green";
          } else {
            pidStatusElement.style.color = "red";
          }

          // Aggiorna i parametri PID
          document.getElementById('kpValue').innerText = data.Kp ? data.Kp.toFixed(2) : "N/A";
          document.getElementById('kiValue').innerText = data.Ki ? data.Ki.toFixed(2) : "N/A";
          document.getElementById('kdValue').innerText = data.Kd ? data.Kd.toFixed(2) : "N/A";

          // updates charts
          updateCharts(data.voltage_in, data.voltage_out, data.current_in, data.current_out);
        })
        .catch(error => console.error('Errore nel caricamento dei parametri:', error));
    }

    //  updates charts
    function updateCharts(voltageIn, voltageOut, currentIn, currentOut) {
      const time = new Date().toLocaleTimeString();

      // updates voltages chart
      if (!voltageChart) {
        const voltageCtx = document.getElementById('voltageChart').getContext('2d');
        voltageChart = new Chart(voltageCtx, {
          type: 'line',
          data: {
            labels: [time],
            datasets: [{
              label: 'Input Voltage (V)',
              borderColor: 'rgb(75, 192, 192)',
              data: [voltageIn],
              fill: false
            }, {
              label: 'Output Voltage (V)',
              borderColor: 'rgb(255, 99, 132)',
              data: [voltageOut],
              fill: false
            }]
          }
        });
      } else {
        voltageChart.data.labels.push(time);
        voltageChart.data.datasets[0].data.push(voltageIn);
        voltageChart.data.datasets[1].data.push(voltageOut);
        voltageChart.update();
      }

      // updates currents chart
      if (!currentChart) {
        const currentCtx = document.getElementById('currentChart').getContext('2d');
        currentChart = new Chart(currentCtx, {
          type: 'line',
          data: {
            labels: [time],
            datasets: [{
              label: 'Input Current (mA)',
              borderColor: 'rgb(54, 162, 235)',
              data: [currentIn],
              fill: false
            }, {
              label: 'Output Current (mA)',
              borderColor: 'rgb(153, 102, 255)',
              data: [currentOut],
              fill: false
            }]
          }
        });
      } else {
        currentChart.data.labels.push(time);
        currentChart.data.datasets[0].data.push(currentIn);
        currentChart.data.datasets[1].data.push(currentOut);
        currentChart.update();
      }
    }

    // Fresets the ESP32
    function resetESP() {
      fetch(`http://${ESP32_IP}/api/reset`)
        .then(response => response.text())
        .then(data => {
          console.log("ESP32 in reset:", data);
          alert('ESP32 in reset...');
        })
        .catch(error => {
          console.error('Error resetting ESP32:', error);
        });
    }

    // loads initial parameters
    window.onload = loadParameters;

    // updates parameters every 5 seconds
    setInterval(loadParameters, 5000);
  </script>
</body>
</html>

Questa è la pagina web di controllo dell’applicazione che puoi consultare tramite browser sia sul computer che sullo smartphone.

Questo file verrà trasferito (con una procedura che vedremo fra poco) nel file system SPIFFS interno alla board. Comunque troverai questo file, assieme al main.c e al platformio.ini, nel file zip che puoi scaricare dal link precedente.

Come trasferire il file index.html verso il file system SPIFFS

L’operazione è abbastanza semplice. È necessario aprire un nuovo terminale su PlatformIO col tasto indicato in figura:

Pulsante per aprire un nuovo terminale
Pulsante per aprire un nuovo terminale

scrivere il seguente comando:

pio run --target uploadfs

e premere il tasto INVIO. Se tutto sarà andato bene il file verrà trasferito sul file system SPIFFS. Se necessario, interrompi la visualizzazione tramite Serial Monitor in quanto potrebbe entrare in conflitto con l’operazione di caricamento dato che utilizza (e certe volte monopolizza) la porta di comunicazione.

NOTA: è importante che il file index.html si trovi, come già detto all’inizio, in una cartella di nome data allo stesso livello della cartella src.

Il caricamento dello sketch, invece, segue la via normale.

Funzionamento dello sketch

Vediamo ora come funziona lo sketch.

Lo sketch inizia con l’inclusione delle librerie necessarie:

#include <Arduino.h>
#include <Wire.h>
#include <INA219_WE.h>
#include <PID_v1.h>
#include <WiFiManager.h> 
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <SPIFFS.h>

Segue poi una #define che stabilisce se stampare i messaggi di debug sul Serial Monitor :

#define DEBUGSERIAL

Se questa define viene lasciata come sopra, i messaggi di debug verranno stampati. Se invece viene commentata come qui sotto:

// #define DEBUGSERIAL

i messaggi non verranno stampati.

Vengono poi definiti gli indirizzi I2C per i due sensori INA219:

#define I2C_ADDRESS_in 0x44
#define I2C_ADDRESS_out 0x40

Definiamo le variabili che conterranno i valori di tensione e corrente in ingresso e uscita misurati dai sensori INA219:

double busVoltage_in = 0.0;
double current_in = 0.0;
double busVoltage_out = 0.0;
double current_out = 0.0;

Seguono la variabile PIDOffThreshold che contiene il valore di soglia della tensione in ingresso sotto la quale il PID viene escluso e il Boost Converter spento (questo valore deve essere determinato sperimentalmente controllando se al di sotto di esso il PID in funzione è ancora in grado di regolare la tensione in uscita), la definizione della variabile Setpoint (che verrà valorizzata nella funzione setup e conterrà il valore desiderato di tensione in uscita), la definizione del flag disabledPID che determina quando il Boost è acceso o deve essere spento, l’inizializzazione del server che gestisce le API REST e che rimane in ascolto sulla porta 80:

double PIDOffThreshold = 0.9;       // below this battery voltage value the PID is excluded and the PWM is set to 0 (BOOST off)

double Setpoint;

bool disabledPID = false;          // flag to turn off Boost if battery voltage is too low

// Initializing the server on port 80
AsyncWebServer server(80);

Istanziamo i due sensori INA219 in ingresso e in uscita passando loro gli indirizzi I2C:

INA219_WE ina219_in = INA219_WE(I2C_ADDRESS_in);
INA219_WE ina219_out = INA219_WE(I2C_ADDRESS_out);

Segue poi la definizione dei parametri del segnale PWM:

// PWM parameters
const int pwmPin = 25; // PWM GPIO
const int pwmChannel = 0; // PWM channel
const int pwmFrequency = 62000; // PWM frequency: 62 kHz
const int pwmResolution = 8; // duty cycle resolution: 8 bit (0-255)
double dutyCycle = 128; // Initially sets the duty cycle to 50%
double dutyCycle_percent;

Definiamo quindi il GPIO 25, il canale 0, la frequenza di 62 kHz, la risoluzione del Duty Cycle pari a 8 (che ci dice che il Duty Cycle può variare solo tra i due estremi 0 e 255), il valore iniziale del Duty Cycle posto a metà (128) tra 0 e 255 e la variabile che esprime il Duty Cycle in percentuale.

Seguono poi i parametri di funzionamento del PID e la creazione dell’istanza che gestisce il PID:

// PID parameters
double Kp = 2.0, Ki = 5.0, Kd = 1.0;

PID myPID(&busVoltage_out, &dutyCycle, &Setpoint, Kp, Ki, Kd, DIRECT);

Segue poi la funzione setup. Per prima cosa viene inizializzata la porta seriale, viene inizializzato il file system SPIFFS (se l’inizializzazione fallisce lo sketch si ferma sul return;), viene settato il Setpoint al valore desiderato (3.3V), inizializzato il bus I2C (Wire.begin();) e, poi, inizializzati i due sensori INA219:

// put your setup code here, to run once:
Serial.begin(115200);
delay(2000);

if (!SPIFFS.begin(true)) {
Serial.println("An error has occurred while mounting SPIFFS");
return;
}
Serial.println("SPIFFS mounted successfully");

Setpoint = 3.3;

Wire.begin();

while(!ina219_in.init()){
Serial.println("INA219 in not connected!");
}

while(!ina219_out.init()){
Serial.println("INA219 out not connected!");
}

La funzione setup continua, tralasciando le parti commentate di spiegazione, col setting dei due sensori:

ina219_in.setADCMode(SAMPLE_MODE_128); // choose mode and uncomment for change of default
ina219_out.setADCMode(SAMPLE_MODE_128); // choose mode and uncomment for change of default

ina219_in.setMeasureMode(CONTINUOUS);
ina219_out.setMeasureMode(CONTINUOUS);  

ina219_in.setPGain(PG_320);
ina219_out.setPGain(PG_320); 

ina219_in.setBusRange(BRNG_16);
ina219_out.setBusRange(BRNG_16);  

ina219_in.setShuntSizeInOhms(0.1);
ina219_out.setShuntSizeInOhms(0.1);

Rimando il lettore ai commenti presenti nel codice per la spiegazione precisa delle funzioni precedenti.

La funzione setup continua eseguendo subito una lettura dei sensori:

busVoltage_in = ina219_in.getBusVoltage_V();
current_in = ina219_in.getCurrent_mA();
busVoltage_out = ina219_out.getBusVoltage_V();
current_out = ina219_out.getCurrent_mA();

Segue poi la sezione che imposta i valori per il PWM:

//  PWM section
// Configures the PWM channel
ledcSetup(pwmChannel, pwmFrequency, pwmResolution);
// Assign the PWM channel to the pin
ledcAttachPin(pwmPin, pwmChannel);
// Sets the initial duty cycle
ledcWrite(pwmChannel, dutyCycle);

la sezione che imposta il PID in modalità di funzionamento automatica e che imposta i limiti del Duty Cycle del segnale PWM generato:

myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(10, 250); // PWM range 0-255

Segue poi la sezione che gestisce il WiFi:

// WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
// it is a good practice to make sure your code sets wifi mode how you want it.


//WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wm;

// reset settings - wipe stored credentials for testing
// these are stored by the esp library
// wm.resetSettings();

// Automatically connect using saved credentials,
// if connection fails, it starts an access point with the specified name ( "AutoConnectAP"),
// if empty will auto generate SSID, if password is blank it will be anonymous AP (wm.autoConnect())
// then goes into a blocking loop awaiting configuration and will return success result

bool res;
// res = wm.autoConnect(); // auto generated AP name from chipid
res = wm.autoConnect("AutoConnectAP"); // anonymous ap
//res = wm.autoConnect("ESP32_AP","password"); // password protected ap

if(!res) {
    Serial.println("Failed to connect");
    // ESP.restart();
} 
else {
    //if you get here you have connected to the WiFi    
    Serial.println("Connected...yeey :)");
    Serial.println("My WiFi IP is: ");
    Serial.print(WiFi.localIP());
    Serial.println();
}

Vedremo in un paragrafo successivo come connettere la ESP32 al Wifi con questo sistema.

La funzione setup termina con la definizione delle API REST esposte dall’ESP32:

La prima, molto semplice, prende la pagina index.html dal file system SPIFFS e la mostra sul browser all’IP assegnato dal router all’ESP32:

// Serve the index.html file from SPIFFS
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/index.html", "text/html");
});

La seconda, api/get-parameters, restituisce tutti i parametri di funzionamento del Boost Converter e del PID sotto forma di documento Json:

// API to get system parameters
server.on("/api/get-parameters", HTTP_GET, [](AsyncWebServerRequest *request){
String jsonResponse;
StaticJsonDocument<200> jsonDoc;
jsonDoc["voltage_in"] = busVoltage_in;
jsonDoc["current_in"] = current_in;
jsonDoc["voltage_out"] = busVoltage_out;
jsonDoc["current_out"] = current_out;
jsonDoc["pwm_value"] = dutyCycle;
jsonDoc["duty_cycle"] = dutyCycle_percent;
jsonDoc["pid_status"] = !disabledPID ? "ON" : "OFF";
jsonDoc["Ki"] = Ki;
jsonDoc["Kp"] = Kp;
jsonDoc["Kd"] = Kd;

serializeJson(jsonDoc, jsonResponse);
request->send(200, "application/json", jsonResponse);
});

La terza, api/set-pid, aggiorna i valori dei parametri di funzionamento del PID (Kp, Ki, Kd) con i valori che inseriamo tramite l’API:

// API for setting PID parameters
server.on("/api/set-pid", HTTP_GET, [](AsyncWebServerRequest *request){
    if (request->hasParam("Kp") && request->hasParam("Ki") && request->hasParam("Kd")) {
        Kp = request->getParam("Kp")->value().toDouble();
        Ki = request->getParam("Ki")->value().toDouble();
        Kd = request->getParam("Kd")->value().toDouble();

        // Aggiorna i valori del PID
        myPID.SetTunings(Kp, Ki, Kd);

        String response = "PID updated: Kp=" + String(Kp) + ", Ki=" + String(Ki) + ", Kd=" + String(Kd);
        request->send(200, "text/plain", response);
    } else {
        request->send(400, "text/plain", "Missing parameters");
    }
});

Possiamo variare i parametri del PID per tentativi e vedere se riusciamo a migliorarne la dinamica e la precisione.

Seguono, poi, l’api api/reset che resetta l’ESP32 premendo l’apposito bottone sull’interfaccia web e la funzione che fa partire il web server:

  // API for resetting ESP32
  server.on("/api/reset", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Resetting ESP32...");
    delay(1000); // wait before resetting to send response
    ESP.restart(); // restart the microcontroller
  });

  // Starting the web server
  server.begin();

Terminata la funzione setup, inizia la funzione loop.

Inizialmente viene controllato il flag disabledPID. Se è stato posto a true il PWM viene spento (e di conseguenza il Boost Converter), altrimenti viene chiamato in causa il PID che calcolerà il valore adeguato del Duty Cycle del PWM:

if(disabledPID) {
dutyCycle = 0;    // Boost turned off
} else {
// PWM controlled by the PID only if disabledPID is false
myPID.Compute();
}

Poi c’è il controllo sulla tensione di ingresso per vdere se è il caso di spegnere il Boost. Se la tensione in ingresso è inferiore al valore di soglia PIDOffThreshold (da determinare sperimentalmente), il flag disabledPID viene posto a true facendo sì che il blocco if precedente spenga il Boost ponendo il Duty Cycle del segnale PWM a 0 al giro successivo:

// here we decide if PID must be disabled and Boost turned off
if(busVoltage_in < PIDOffThreshold) {
disabledPID = true;
}

Nel blocco di istruzioni successivo viene aggiornato il Duty Cycle del segnale PWM e calcolato il suo valore in termini percentuali e vengono riletti i sensori INA219 per aggiornare i valori di tensione e corrente in ingresso e uscita:

ledcWrite(pwmChannel, dutyCycle); // update the duty cycle
dutyCycle_percent = dutyCycle * 100 / 255;

busVoltage_in = ina219_in.getBusVoltage_V();
current_in = ina219_in.getCurrent_mA();
busVoltage_out = ina219_out.getBusVoltage_V();
current_out = ina219_out.getCurrent_mA();

Infine troviamo un blocco che, se attivato tramite la #define DEBUGSERIALcome spiegato all’inizio dello sketch, stampa sul Serial Monitor le varie informazioni di funzionamento del sistema:

#ifdef DEBUGSERIAL
  Serial.println();
  Serial.print(busVoltage_in);
  Serial.print(", ");
  Serial.print(current_in);
  Serial.print(", ");
  Serial.print(busVoltage_out);
  Serial.print(", ");
  Serial.print(current_out);
  Serial.print(", ");
  Serial.print("DC: ");
  Serial.print(dutyCycle);
  Serial.print(", ");
  Serial.print("DC % ");
  Serial.print(dutyCycle_percent);
  Serial.print("%");
  Serial.print(", ");
  Serial.print("disabledPID ");
  Serial.print(disabledPID);
  Serial.print(", ");
  Serial.print("Kp ");
  Serial.print(Kp);
  Serial.print(", ");
  Serial.print("Ki ");
  Serial.print(Ki);
  Serial.print(", ");
  Serial.print("Kd ");
  Serial.print(Kd);
#endif

  delay(10);

Come connettere la board ad Internet

Dopo aver caricato lo sketch sulla board, apri il Serial Monitor per vedere i messaggi provenienti dal dispositivo.

Per prima cosa la board va in modalità Access Point e ci fornirà un indirizzo IP che useremo a breve. Questa operazione serve per connettere la board ad Internet senza dover inserire nel codice i parametri della rete WiFi (SSID e password).

La board ci fornisce il suo indirizzo IP
La board ci fornisce il suo indirizzo IP

In questo caso l’indirizzo IP è 192.168.4.1.

A questo punto la ESP32 è in modalità Access Point (con SSID AutoConnectAP) e dobbiamo connettere il nostro computer alla rete AutoConnectAP. Se andiamo nel menu delle reti del nostro computer, dovremmo vedere anche la rete AutoConnectAP nell’elenco delle reti wireless.

Lista delle reti WiFi disponibili
Lista delle reti WiFi disponibili

Connetti il computer alla rete AutoConnectAP. Quindi vai sul tuo browser e inserisci l’IP precedentemente fornito dalla ESP32 (che in questo esempio è 192.168.4.1)

Vedrai una schermata come questa:

La schermata del browser per scegliere la rete
La schermata del browser per scegliere la rete

Clicca il bottone ConfigureWiFi. Ti mostrerà le reti disponibili:

Lista delle reti disponibili
Lista delle reti disponibili

Scegli la SSID della tua rete:

Scegli la tua rete
Scegli la tua rete

Inserisci la password della tua rete e clicca il bottone save:

Inserisci la password
Inserisci la password

La risposta della board
La risposta della board

Il modulo ESP32 conserva memorizzati i parametri di accesso anche se lo spegni, li ricorderà al riavvio e si ricollegherà automaticamente senza dover ripetere questa procedura. Solo se lo resetti rimuovendo il commento da questa riga

// wm.resetSettings();

perderà i parametri di connessione.

Fra i vari messaggi che verranno stampati sul Serial Monitor, la libreria WiFiManager ci indicherà anche quale IP le è stato assegnato dal modem WiFi.

Nota Bene: il dispositivo può memorizzare solo una rete. Se successivamente lo colleghi a un’altra rete, dimenticherà le impostazioni della rete precedente.

La pagina web di monitoraggio e le API REST

Una volta che la ESP32 è stata connessa alla rete WiFi ci fornirà tramite il Serial Monitor di PlatformIO il suo indirizzo IP, come visibile nella figura seguente:

Ricaviamo l'IP della board
Ricaviamo l’IP della board

In questo caso l’IP assegnato dal router alla board è 192.168.1.129. Non è assolutamente detto che nel tuo caso venga assegnato lo stesso IP (anzi, molto probabilmente sarà diverso). Tale IP ci servirà per visualizzare la pagina web e per comporre le API REST.

Per visualizzare la pagina web è sufficiente digitare l’indirizzo IP assegnato alla ESP32 sulla barra del browser del proprio PC o del proprio smartphone. Di seguito un esempio della pagina web all’indirizzo 192.168.1.129 che quello che il mio router WiFi ha assegnato alla mia ESP32:

Pagina web di monitoraggio
Pagina web di monitoraggio

Come già anticipato più sopra, per interagire con le API REST della board abbiamo bisogno di un software apposito che si chiama Postman. Dopo aver installato il programma, siamo pronti ad usarlo.

Ecco come si presenta la sua schermata iniziale:

Schermata iniziale di Postman
Schermata iniziale di Postman

Nella finestra principale si trova una barra in cui dovrai inserire l’API.

Alla sinistra di questa barra c’è un menù a tendina che consente di scegliere il tipo di API (per esempio GET, POST, PUT…).

Supponiamo di volere aggiornare i parametri del PID in questo modo: Kp=3.0, Ki=2.0 e Kd=5.0 (sono valori messi a caso).

Scegli il tipo GET e inserisci l’API set-pid che avrà formato:

http://<ESP32_IP>/api/set-pid?Kp=3.0&Ki=2.0&Kd=5.0

Per esempio, in questo caso, essendo l’IP assegnato 192.168.1.129, l’URL dell’API sarà:

http://192.168.1.129/api/set-pid?Kp=3.0&Ki=2.0&Kd=5.0

Ovviamente tu dovrai mettere l’indirizzo IP assegnato alla tua ESP32.

Premi il tasto Send sulla destra.

L’API restituirà un messaggio come questo: PID updated: Kp=3.00, Ki=2.00, Kd=5.00

Ora vogliamo testare l’altra API, get-parameters, che restituisce i parametri di funzionamento del sistema su un documento Json.

Scegli il tipo GET e inserisci l’API get-parameters che avrà formato:

http://<ESP32_IP>/api/get-parameters

Nel caso del mio IP avrebbe la forma:

http://192.168.1.129/api/get-parameters

Premi il tasto Send sulla destra.

Se tutto va bene, Postman ti mostrerà i dati richiesti in una forma simile a questa:

{
  "voltage_in": 1.519999981,
  "current_in": 20.00000038,
  "voltage_out": 3.019999981,
  "current_out": 10.10000038,
  "pwm_value": 137.7280003,
  "duty_cycle": 54.0198049,
  "pid_status": "Attivo",
  "Ki": 5,
  "Kp": 2,
  "Kd": 1
}

Ad ogni modo vedrai più in dettaglio il funzionamento del sistema e delle API REST usate con Postman nel video che segue (con sottotitoli):

Oscillogrammi di due casi d’uso

Nell’immagine seguente vediamo una vera fotografia dell’oscilloscopio che immortala il funzionamento del Boost Converter nel caso di carico da 330Ω. In questo caso la base dei tempi è settata su 5µs.:

Boost Converter con carico da 330Ω
Boost Converter con carico da 330Ω

Il funzionamento è abbastanza regolare. La traccia violetta è il segnale PWM di controllo generato dall’ESP32, il segnale celeste è quello presente sul Drain del MOSFET e il segnale giallo è la tensione in uscita sul carico. Si notano sulla traccia gialla le oscillazioni in corrispondenza delle commutazioni.

Nell’immagine seguente vediamo una vera fotografia dell’oscilloscopio che immortala il funzionamento del Boost Converter nel caso di carico da 33Ω. :

Boost Converter con carico da 33Ω
Boost Converter con carico da 33Ω

In questo caso la base dei tempi è settata su 20µs. La cosa da notare è che la commutazione (il ripple) sulla traccia gialla (la tensione di uscita) è molto più evidente in quanto il carico ora assorbe molta più corrente. Nonostante tutto il PID riesce comunque a regolare la tensione al valore richiesto di 3.3V.

Newsletter

Se vuoi essere aggiornato sui nuovi articoli, iscriviti alla newsletter. Prima dell’iscrizione alla newsletter leggi la pagina Privacy Policy (UE)

Se ti vuoi disiscrivere dalla newsletter clicca sul link che troverai nella mail della newsletter.

Inserisci il tuo nome
Inserisci la tua email
0 0 votes
Valutazione articolo
guest
0 Commenti
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
Torna in alto