Abbiamo visto a lezione in cosa consiste la Modulazione di Larghezza di Impulso, in altro modo conosciuta come PWM (Pulse Width Modulation). Questo tipo di modulazione permette ad un sistema digitale di controllare dispositivi di tipo analogico in corrente continua facendo variare in modo continuo la potenza erogata, quindi moduliamo la larghezza di un impulso, ovvero la durata temporale di una serie di impulsi che regolerà l’attivazione e disattivazione del motore. Con il PWM agiamo non sulla tensione di alimentazione per controllare la velocità del motore, ma bensì sul tempo, per maggiori informazioni vi rimando alle slide: Alfabeto Arduino – Lezione 2 in cui come esempio viene controllata l’intensità luminosa di LED. (Per i miei studenti fate riferimento al libro di testo e agli appunti di teoria).
Il transistor nell’immagine che segue viene fatto funzionare in modalità ON-OFF e quindi possiamo assimilarlo ad un interruttore che si apre e si chiude in corrispondenza del segnale presente sulla base del transistor. Se il segnale sulla base è alto il transistor sarà in conduzione e il motore potrà essere alimentato (si chiude verso massa il collegamento del motore). Se il segnale sulla base del transistor è a livello basso il transistor è assimilabile ad un interruttore aperto per cui il motore risulta non alimentato (non si ha collegamento a massa). Quindi al motore verrà applicata una tensione continua proporzionale al duty cycle e quindi variando il duty cycle varieremo la velocità di rotazione del motore.
La generazione dell’onda quadra, che controlla la velocità del motore, viene eseguita da Arduino. Il diodo presente nel circuito è chiamato diodo di ricircolo ed è inserito in parallelo al motore (carico induttivo) per sopprimere i transienti elettrici ed è collegato in modo tale che non conduce quando il carico (il motore) viene alimentato.
Quando il motore viene disattivato rapidamente si avrà un picco di tensione in senso inverso perché l’induttore tenderà a mantenere costante la corrente che circola al suo interno, in questa situazione però il diodo sarà polarizzato direttamente e tutta la corrente scorrerà dall’induttore al diodo e l’energia che era stata immagazzinata dall’induttore viene dissipata in calore dalla componente resistiva dell’induttore. Inserendo il diodo si eviterà di applicare una sovratensione sul collettore del transistor evitando quindi che si danneggi.
Controlliamo con Arduino il movimento del motore
Lista Componenti
- Arduino UNO R3
- Resistore da 1 K Ohm
- Dido: 1N4001
- Transistor: 2N2222
- Condensatore: 0,1 microF
Pinout transistor 2N2222
Circuito 1 di montaggio: alimentazione del motore prelevata da Arduino
Circuito 2 di montaggio: alimentazione del motore esterna ad Arduino
Esempio 1
Si faccia riferimento al circuito 1. Realizziamo uno sketch che permette la regolazione della velocità del motore inserendo un numero compreso tra 0 e 9. Il valore 0 ferma il motore, il valore 9 permette di muovere il motore alla velocità massima, valori intermedi movimenteranno il motore ad una velocità proporzionale al numero inserito.
Valori fuori dall’intervallo impostato restituiscono un messaggio di errore.
Per la realizzazione di questo sketch si utilizza la funzione isDigit() che restituisce TRUE verifica se il carattere inviato sulla Serial Monitor è un numero, altrimenti restituisce FALSE.
/* Prof. Maffucci Michele Controllo motore a spazzola: accensione, spegnimento, controllo velocità. All'avvio del programma il motore è spento. La velocità del motore è impostata con un valore compreso tra 0 e 9 Valori non numerici restituiscono un messaggio di errore Data: 19.01.2021 */ // driver del motore collegato al pin 6 const byte pinMotore = 6; // motor driver is connected to pin 3 // per stampare una sola volta il messaggio sulla Serial Monitor bool abilitaMessaggio = 0; void setup() { // inizializzazione della serial monitor Serial.begin(9600); // inizializzazione OUTPUT del pin 6 pinMode(pinMotore, OUTPUT); } void loop() { // consente di visualizzare sulla Serial Monitor // una sola stampa delle stringa if (abilitaMessaggio == 0) { // ritardo che evita la doppia stampa del messaggio delay(200); Serial.println("Controllo velocità motore"); Serial.println("Inserire la velocità (0 - 9)"); Serial.println(); abilitaMessaggio = 1; } // Controlla se è disponibile almeno un carattere sulla seriale // La Serial.available() restituisce // 1 se presente un cattere, // 0 se non è presente un carattere // per maggior informazioni sull'uso di parseInt() consultare il link: // https://wp.me/p4kwmk-4Ah if (Serial.available()) { // Viene controllato se è disponibile un carattere // definizione di una variabile di tipo char in cui memorizzare // il carattere inviato ad Arduino mediante la Serial Monitor char carattere = Serial.read(); // La funzione isDigit restituisce TRUE se se il carattere // inviato sulla Serial Monitor è un numero altrimenti restituisce FALSE if (isDigit(carattere)) // verifica se è un numero { // mappiamo l'intervallo dei caratteri da '0' a '9' // in un valore compreso tra 0 e 255, intervallo di valori // del Duty Cycle int vel = map(carattere, '0', '9', 0, 255); analogWrite(pinMotore, vel); Serial.print("Valore del Duty Cycle: "); Serial.println(vel); Serial.println("--------------------------"); Serial.print("Velocità impostata: "); Serial.println(carattere); Serial.println("=========================="); } else { // nel caso in cui il carattere inserito non è un numero // viene restituito un messaggio e stampa il carattere Serial.println(); Serial.println("******************************"); Serial.print("Carattere non riconosciuto: "); Serial.println(carattere); Serial.println("******************************"); Serial.println(); } } }
Esempio 2
Si faccia riferimento al circuito 1. Realizziamo uno sketch che permette la regolazione della velocità del motore inserendo un numero compreso tra 0 e 9. Il valore 0 ferma il motore, il valore 9 permette di muovere il motore alla velocità massima, valori intermedi movimenteranno il motore ad una velocità proporzionale al numero inserito.
Valori fuori dall’intervallo impostato fermano il motore.
Per la realizzazione di questo sketch si utilizza la funzione Serial.parseInt() che legge i caratteri sulla seriali e restituisce la loro rappresentazione numerica (tipo long). I caratteri che non sono numeri interi (o con segno meno) vengono ignorati.
Nel dettaglio
- I caratteri iniziali che non sono cifre o sono numeri negativi vengono ignorati;
- L’analisi si interrompe quando non sono stati letti caratteri per un valore di tempo di timeout che può essere configurato oppure viene letta una non cifra;
- Se non sono state lette cifre valide quando si verifica il timeout (vedere Serial.setTimeout ()), viene restituito 0; Serial.parseInt () eredita dalla classe Stream.
/* Prof. Maffucci Michele Controllo motore a spazzola: accensione, spegnimento, controllo velocità. All'avvio del programma il motore è spento. La velocità del motore è impostata con un valore compreso tra 0 e 9 Valori non numerici fermano il motore. Viene utilizzata la funzione Serial.parseInt() per leggere Data: 19.01.2021 */ // driver del motore collegato al pin 6 const byte pinMotore = 6; // motor driver is connected to pin 3 // per stampare una sola volta il messaggio sulla Serial Monitor bool abilitaMessaggio = 0; void setup() { // inizializzazione della serial monitor Serial.begin(9600); // inizializzazione OUTPUT del pin 6 pinMode(pinMotore, OUTPUT); } void loop() { // consente di visualizzare sulla Serial Monitor // una sola stampa delle stringa if (abilitaMessaggio == 0) { // ritardo che evita la doppia stampa del messaggio delay(200); Serial.println("Controllo velocità motore"); Serial.println("Inserire la velocità (0 - 9)"); Serial.println(); abilitaMessaggio = 1; } // Controlla se è disponibile almeno un carattere sulla seriale // La Serial.available() restituisce // 1 se presente un cattere, // 0 se non è presente un carattere // per maggior informazioni sull'uso di parseInt() consultare il link: // https://wp.me/p4kwmk-4Ah if (Serial.available()) { // Viene controllato se è disponibile un carattere // definizione di una variabile di tipo char in cui memorizzare // il carattere inviato ad Arduino mediante la Serial Monitor // per maggior informazioni sull'uso di parseInt() consultare il link: // https://wp.me/p4kwmk-4Ah int valore = Serial.parseInt(); // La funzione isDigit verifica se il carattere inviato è un numero // e restituisce TRUE se il carattere è un numero altrimenti restituisce FALSE // mappiamo l'intervallo dei caratteri da '0' a '9' // in un valore compreso tra 0 e 255, intervallo di valori // del Duty Cycle if (valore >= 0 && valore <= 9) { if (valore == 0) { Serial.println(); Serial.println("************************************"); Serial.println("MOTORE FERMO"); Serial.println("Valore inserito 0 o fuori intervallo"); Serial.println("************************************"); Serial.println(); } int vel = map(valore, 0, 9, 0, 255); analogWrite(pinMotore, vel); Serial.print("Valore del Duty Cycle: "); Serial.println(vel); Serial.println("--------------------------"); Serial.print("Velocità impostata: "); Serial.println(valore); Serial.println("=========================="); } } }
Esercizio 1
Aggiungere al circuito 1 due pulsanti che permettono di aumentare o diminuire la velocità del motore. Fare in modo che la velocità impostata del motore sia proporzionale ai valori numerici interi nell’intervallo tra 0 e 9, così come fatto negli esempi precedenti. Ad ogni pressione del pulsante P1 si incrementa di una unità il valore della velocità. Ad ogni pressione del pulsante P2 si decrementa la velocità del motore i una unità. All’avvio di Arduino il motore è spento. Mostrare la velocità impostata sulla serial monitor.
Esercizio 2
Aggiungere all’esercizio precedente un pulsante P3 di emergenza che alla pressione ferma il motore. Se è stata azionata l’emergenza i pulsanti P1 e P2 di incremento e decremento non funzionano. Per poter riattivare il sistema bisogna premere nuovamente P3.