L298N pilotare un motore DC con Arduino

Gli esperimenti continuano! Dopo il primo articolo “elettronico” in cui spiegavo come interfacciare un sensore ad ultrasuoni HC-SR04 con Arduino, in quello di oggi parlo del modulo L298N, conosciuto anche come L298N DualFull-Bridge Motor Driver.
Si tratta di un modulo basato appunto sull’integrato L298, principalmente utilizzato per pilotare motori, relè, solenoidi e motori passo passo. In alcune configurazioni lo si può vedere a comando di potenti led o led strip. Tranne nel caso in cui si voglia pilotare un motore passo passo (lo vedremo in un articolo futuro) le due uscite possono essere comandate autonomamente.
Una breve descrizione per dirti che è composto da due connettori laterali ai quali collegare i motori (o i carichi in generale), e da connettori frontali dove collegare l’alimentazione e le connessioni logiche atte a pilotare i carichi. Qui puoi trovare il datasheet dell’integrato in se, mentre qui sotto ti ho messo una foto per rendere meglio l’idea delle connessioni.

Pinout L298N

Pinout L298N

Altre info tecniche per dirti che il modulo può funzionare con tensioni dai 5 ai 35 volt e fornire 2A di corrente per ogni uscita. Il modulo L298N presenta inoltre una chicca abbastanza utile in certi casi, quando alimentato a 12 volt, dal connettore di alimentazione, in corrispondenza dell’uscita +5v è possibile prelevare una tensione regolata a 5 volt per alimentare un eventuale Arduino o altri componenti del progetto. Per abilitare questa funzione lasciare in sede il jumperino presente dietro i connettori di alimentazione, ma se il nostro modulo è alimentato con tensioni maggiori di 12 volt questo jumper va rimosso per impedire che venga danneggiato il regolatore di tensione a 5 volt.
Nell’esperimento di oggi prenderò in considerazione soltanto un’uscita (Output A della foto), in quanto l’intento è quello di pilotare un solo motore, ma come potrai ben notare, l’utilizzo del modulo L298N è estremamente semplice che comandarne un secondo non comporta nulla di complicato, se non aggiungere qualche riga di codice in più 😉

Lo schema:

Schema dei collegamenti per questo esempio

Schema dei collegamenti per questo esempio

Uno dei motivi principali per i quali vengono utilizzati questi moduli, è quello di evitare di dover alimentare carichi dispendiosi tramite il povero Arduino, che come ben sappiamo, non ha voglia di far passare troppa corrente in uscita dai suoi pin. Per fare questo, il modulo L298N è predisposto in modo da poter fornire ai motori o ai carichi in genere, un’alimentazione esterna indipendente dalle connessioni logiche di chi lo pilota.
Quindi vediamo una batteria da 12 Volt collegata ai connettori +12 e GND del modulo. Cosa importante però, è la massa in comune, questa garantirà il funzionamento della logica di comando. La breadboard messa nello schema serve proprio a far notare il particolare della massa in comune.
Dall’uscita Output A, ai connettori M1 e M2, ho collegato il motore DC. Non ha importanza la polarità dei cavi, perchè a determinare il senso di marcia saranno il modulo L298N e Arduino.
Quindi passiamo alle connessioni logiche, come già detto, lo scopo è quello di pilotare un solo motore, quindi sono stati interessati solo tre pin di comando. I pin in questione sono EN1, IN1 e IN2. Il primo detto anche Enable, ha un duplice scopo, abilitare o meno il segnale in uscita indipendentemente dai valori in ingresso, e qualora lo si voglia, determinare la potenza del segnale in uscita applicando ad esso un segnale di tipo PWM, dall’inglese pulse-width modulation. Ricapitolando, se al pin Enable applichiamo una tensione alta, lo stato di abilitato è true, quindi l’uscita connessa al motore dipenderà dagli stati logici di IN1 e IN2, viceversa se applichiamo una tensione bassa, lo stato di enable sarà false, ed indipendentemente dagli stati di IN1 e IN2 il segnale in uscita sarà nullo, il motore non si muove. Se invece al pin EN1 applichiamo un segnale di tipo PWM, la potenza di uscita sarà proporzionale a questo segnale… (dal codice capirai meglio).
Proprio per sfruttare la capacità PWM dei pin Enable, ho deciso di aggiungere un potenziometro al progetto, così da poter variare il valore in ingresso sul pin EN1 e far accelerare o decelerare il motore. Arduino leggerà il valore analogico del potenziometro tramite il pin A0, e dopo averlo opportunamente mappato, lo darà in pasto al pin EN1 del modulo L298N tramite il suo pin 11.

Ricordo che non tutti i pin di Arduino sono PWM ready, cioè abilitati a fornire questo tipo di segnale. Nella maggior parte dei casi (Arduino che montano i processori ATmega168 o ATmega328), questa funzione è abilitata sui pin 3, 5, 6, 9, 10 e 11. Sulla Arduino Mega, i pin abilitati sono dal 2 al 13 e dal 44 al 46. Vecchie versioni di Arduino con processore ATmega8 supportano questa funzione solo sui pin 9, 10 e 11.

Il codice

Dico sempre che è buona norma commentare il codice, ed io lo faccio ampiamente… quindi non sto a descrivere quello che ho fatto ma ti invito a leggere i commenti del codice. Se qualcosa non ti è chiaro, a fondo articolo trovi un video dimostrativo e ancora più giù c’è la zona discussioni dove commentare ed eventualmente fare domande 😉

/*
 * L298N pilotare un motore DC con Arduino
 * Programmino per imparare il funzionamento del Modulo L298N e del suo utilizzo con Arduino
 *
 * Autore  : Andrea Lombardo
 * Web     : http://www.lombardoandrea.com
 * Post    : http://bit.ly/L298N-ARDUINO-MOTOREDC
 * Git     : https://github.com/AndreaLombardo/Arduino-L298N-Motore-DC
 */ 

//definizione dei pin
static int pinAcceleratore = A0; //pin analogico deputato a leggere i valori del potenziometro
static int mA = 12; //pin digitale per determinare gli stati logici da inviare al modulo
static int mB = 13; //pin digitale per determinare gli stati logici da inviare al modulo
static int pinPotenza = 11; //pin digitale tramite il quale inviare un segnale di tipo PWM tramite la funzione analgWrite()

//variabili usate per gestire e mostrare i valori di operaizone
int accelerazione;  //valore letto dal pin A0
int potenza;  //valore in uscita dal pin 11

void setup() {
  //inizializzo la comunicazione seriale cosi da mostrare i valori nel Mointor Seriale
  Serial.begin(9600);

  //inizializzo variabili
  accelerazione = 0;
  potenza = 0;

  //definisco tipologia pin
  pinMode(pinAcceleratore, INPUT); //input in quanto legge il valore analogico del pin A0
  pinMode(mA, OUTPUT); //output perche' definisce lo stato logico del pin IN1 del modulo L298N
  pinMode(mB, OUTPUT); //output perche' definisce lo stato logico del pin IN2 del modulo L298N
  pinMode(pinPotenza, OUTPUT);  //output perche' definisce il valore PWM del pin EN1 del modulo L298N

  //pullDown sensore pinAcceleratore
  digitalWrite(pinAcceleratore, LOW);

  //Definisco il senso di marcia del motore
  /*
    mA |   mB  | Evento
  -----|-------|----------------------
  LOW  | LOW   | fermo
  LOW  | HIGH  | Movimento in un senso
  HIGH | LOW   | Movimento senso opposto
  HIGH | HIGH  | Fermo
  */
  
  digitalWrite(mA, LOW);
  digitalWrite(mB, HIGH);

}


void loop() {
  
  //leggo il valore analogico del potenziometro sul pin A0.
  accelerazione = analogRead(pinAcceleratore);
  
  /*
  Il range dei valori analogici e' da 0 a 1024 mentre il range dei valori PWM  e' da 0 a 255
  per mantenere questa proporzionalita' eseguo la mappatura dei valori
  */
  potenza = map(accelerazione, 0, 1024, 0, 255);

  //Invio i dati letti al Monitro seriale, cosi da poterli vedere a video
  Serial.print("Accelerazione = ");
  Serial.print(accelerazione);
  Serial.print(" - potenza = ");
  Serial.println(potenza);
  
  //invio costantemente il valore PWM della potenza in modo da far variare la velocita' del motore in base alla posizione del potenziometro
  analogWrite(pinPotenza, potenza);
}

Quello che ho mostrato nel codice è solo un minuscolo esempio di quelle che sono le potenzialità di questo modulo in abbinamento ad Arduino. Velocità e senso di marcia del motore possono essere modificati e alterati continuamente in base alle condizioni dettate dal codice, così che creare sistemi automatici diventa semplice e divertente… Unico limite è la fantasia!

    Come sempre

  • Assicurati che tutti i collegamenti siano corretti;
  • Ricordati di impostare la porta COM del tuo Arduino;
  • Imposta la stessa velocità seriale definita in Serial.begin(9600), nel Monitor Seriale
  • E ricorda che io non mi assumo nessuna responsabilità per eventuali danni o disastri che causi 😀

Prodotti Amazon




Il mio video


Puoi clonare il progetto direttamente da GitHub!

Approfondimenti

Ricerche che hanno riportato a questa pagina:
  • Pingback: L298N Pilotare un motore passo passo con Arduino - Andrea Lombardo()

  • Stefano Stefanelli

    Ciao, l’articolo mi sembra molto interessante anche per uno come me che comincia solo ora ad affrontare questi problemi.
    Vorrei realizzare uno slider motorizzato per time-lapse e avrei quindi bisogno di pilotare un motore (preferibilmente passo passo ma non è obbligatorio) in maniera molto molto lenta, al massimo 1 giro al minuto ma in maniera controllabile e precisa arrivando anche ad un giro ogni 10 minuti.
    E’ possibile con il tuo progetto?
    Se si come?
    Grazie in anticipo per l’aiuto!

  • Ciao, la tua idea non è male, sicuramente si può fare, ma spiegartela cosi su due piedi non mi sembra il caso. In questi giorni sono un pò preso con il lavoro, ma appena mi libero un attimo faccio un prototipo e scrivo un articolo. Che ne pensi!?

  • Stefano Stefanelli

    perfetto! ti lascio anche la mia mail per poterti dare anche dei suggerimenti su quelle che possono essere le esigenze.
    Intanto ti ringrazio per la disponibilità!
    Ste 😉

  • Ok, ho tolto la mail dal commento… non è proprio l’ideale lasciare email al pubblico 😉
    A presto

  • lume48

    Ho caricato il codice per comandare il motore DC con L298N ma non funziona. Con alcune modifiche invece va avanti e indietro e resta fermo con il potenziometro a metà.
    Vorrei intrdurre anche due possibilità.
    1 feedback velocità e impostazione limite.
    2 feedback corrente e impostazione limite prima che salti il fusibile o l’LM298 (ne ho già bruciato uno )

  • lume48

    ho avuto lo stesso problema. Lo scketch di Andrea va bene ma quando fermo il motore da programma la corrente in un canale a caso del motore stepper non si azzera e scalda parecchio. Ho risolto usando i pin enable dell’ LM298N e attivandoli ogni due ore

  • Ciao ragazzi, scusate se vi rispondo solo adesso, ma ultimamente non riesco a dedicare molto tempo al sito. Spero di analizzare al più presto le vostre richieste e rimontare lo sketch cosi da rifare le prove.
    @lume48:disqus non ho ben capito il tuo problema. Nel mio esempio il pin enable viene usato come “sensore” che determina la velocità del motore in base al segnale PWM che riceve da arduino. Tale segnale è determinato dal valore (mappato) della resistenza variabile. Hai provato con un potenziometro di valore diverso?
    Buona serata!

  • Giuseppe Sagramoni

    Salve , volevo far notare che nella prima immagine (foto del modulo l298n) sono invertiti i morsetti del +5v con quelli del +12v

  • Grazie mille, ma l’immagine è a solo scopo dimostrativo, ogni casa produttrice potrebbe cambiare l’ordine dei pin a piacere. Io stesso ne possiedo due identici tranne che per la piedinatura.
    Grazie comunque per l’interessamento.

  • Enrico

    Buongiorno, gentilmente Mi interessa la modifica del codice per lasciare lasciare fermo il motore con il potenziometro a metà e utilizzarlo con i cambi del senso di marcia, riuscirebbe ad aiutarmi. grazie

  • Ciao, mappando il valore del potenziometro tra 0 e 255 puoi creare una funzione che una volta letto il valore, controlli le seguenti condizioni:
    se valore >=129 vai in un senso
    se valore =135 vai in un senso
    se valore 121 e valore < 135 rimani fermo
    Facci sapere come va.

  • Enrico

    Intanto grazie infinite per la risposta.
    Ero riuscito a far muovere nei due sensi il motore ma senza il blocco centrale, inoltre non mi legge più la potenza e quindi non varia la velocità che invece rimane costante.
    purtroppo non ho alcuna nozione di programmazione e quindi sto facendo mota fatica. questa è la modifica che ho fatto ma come detto prima ha delle enormi lacune.

    //definizione dei pin
    static int pinAcceleratore = A0; //pin analogico deputato a leggere i valori del potenziometro
    static int mA = 12; //pin digitale per determinare gli stati logici da inviare al modulo
    static int mB = 13; //pin digitale per determinare gli stati logici da inviare al modulo
    static int pinPotenza = 11; //pin digitale tramite il quale inviare un segnale di tipo PWM tramite la funzione analgWrite()

    //variabili usate per gestire e mostrare i valori di operaizone
    int accelerazione; //valore letto dal pin A0
    int potenza; //valore in uscita dal pin 11

    void setup() {
    //inizializzo la comunicazione seriale cosi da mostrare i valori nel Mointor Seriale
    Serial.begin(9600);

    //inizializzo variabili
    accelerazione = 0;
    potenza =0;

    //definisco tipologia pin
    pinMode(pinAcceleratore, INPUT); //input in quanto legge il valore analogico del pin A0
    pinMode(mA, OUTPUT); //output perche’ definisce lo stato logico del pin IN1 del modulo L298N
    pinMode(mB, OUTPUT); //output perche’ definisce lo stato logico del pin IN2 del modulo L298N
    pinMode(pinPotenza, OUTPUT); //output perche’ definisce il valore PWM del pin EN1 del modulo L298N

    //pullDown sensore pinAcceleratore
    digitalWrite(mA, LOW);
    digitalWrite(mB, LOW);

    }

    void loop() {

    potenza = map(accelerazione, 0, 500, 0, 255);

    accelerazione = analogRead(pinAcceleratore);

    if (accelerazione =500){
    digitalWrite(mA, LOW);
    digitalWrite(mB, HIGH);

    analogWrite(pinPotenza, potenza);

    //Invio i dati letti al Monitro seriale, cosi da poterli vedere a video
    Serial.print(“Accelerazione = “);
    Serial.print(accelerazione);
    Serial.print(” – potenza = “);
    Serial.println(potenza);

    //invio costantemente il valore PWM della potenza in modo da far variare la velocita’ del motore in base alla posizione del potenziometro
    potenza= analogRead(pinPotenza);
    }}}

  • Ciao Enrico, ho scritto al volo questa bozza. Fai un test e fammi sapere. Purtroppo non ho nulla a portata di mano per testare il codice.
    http://www.lombardoandrea.com/motore-dc-direzione-velocita-arduino-potenziometro/
    Lo schema rimane invariato.
    Non mi assumo nessuna responsabilità 😉

  • Enrico

    funziona perfettamente grazie infinite, gentilissimo

  • Sauro campagna

    Salve Andrea,

    complimenti per l’articolo, molto chiaro ed istruttivo per chi come me e’ un po’ agli inizi in questo campo.

    Sto cercando di regolare questo motore dc 7,2 v Clash 28 T http://www.ebay.it/itm/125000014-Clash-Turn-28-540-Motor-16-600-rpm-4-2a-7-2v-7-2-v-RC-/330452127018?hash=item4cf07b4d2a:m:mY0oZ2zdhh8nqOBy50QUnOA
    il cui assorbimento al massimo del carico e’ di 4,2 A
    In realtà quando lo regolo senza driver direttamente con un banale potenziometro ho verificato che tranne che all’avvio, l’assorbimento per il carico di lavoro che gli faccio fare varia fra i 500 e gli 800 mA, quindi al di sotto della soglia di 2 A che se non sbaglio è il massimo erogabile per canale del L298N.
    Ora provandolo a controllare con Arduino UNO R3 ed L298N tutto funzionerebbe a meraviglia ma dopo pochi secondi il modulo L298N si scalda da morire e devo staccare tutto.
    Al modulo di solito do corrente in ingresso di 5v ma nulla cambia se lo alimento a 12v.
    Secondo te sto sbagliando qualcosa o semplicemente il modulo L298N e’ inadatto allo scopo?
    In questo caso per la tua esperienza quale altro driver (economico) potrei utilizzare?
    Grazie per l’aiuto e complimenti ancora per i tuoi articoli.

  • Ciao Sauro, innanzitutto grazie per gli apprezzamenti.
    Per quanto riguarda il tuo problema, credo che la soluzione migliore per pilotare motori del genere sia quella di utilizzare un ESC (http://amzn.to/2psLu8H).
    Non mi sono mai trovato nelle condizioni di doverne utilizzare uno, quindi non ti so dire molto, ma sentendo e leggendo un pò in giro credo che sia quello che fa per te.
    Per quanto riguarda l’assorbimento degli Ampere da te verificato, lo scenario potrebbe essere questo: il potenziometro limita la corrente e la tua lettura sotto carico si riferisce alla corrente che riesce a passare sotto effetto del potenziometro. Utilizzando invece il modulo l298, la limitazione di corrente viene meno, e lui fa passare tutti gli ampere che il motore richiede… conseguenza il surriscaldamento.
    Non so se ti sto per dire una grossa cavolata, ma puoi provare ad utilizzare il potenziometro posto tra il motore e il modulo l298n… il modulo risponderà agli ordini di Arduino, mentre il potenziometro farebbe da limitatore di corrente come nel tuo esperimento senza Arduino.
    Quando avrai fatto, fammi sapere come hai risolto 😉

%d blogger hanno fatto clic su Mi Piace per questo: