Arduino ed i Motori CC

Arduino ed i Motori CC

I motori a Corrente Continua (in inglese DC Direct Current) hanno soltanto due fili (positivo e negativo). Per farli girare basta alimentarli. Al loro interno è presente un magnete permanente, situato sul corpo cilindrico, un’elettrocalamita situata sull’asse e dei contatti struscianti (spazzole) che alimentano l’elettrocalamita. Applicando una tensione l’elettrocalamita si polarizza in maniera opposta al magnete e tende a ruotare per allineare il suo Nord con il Sud del magnete e viceversa. I contatti struscianti sono disposti in modo tale da invertire la polarità dell’elettrocalamita ogni mezzo giro, quando essa si allinea col magnete. Questo fa sì che l’asse continui a ruotare, finché riceve corrente, senza mai stabilizzarsi.

Non si può pilotare direttamente un Motore CC con Arduino, infatti dai suoi Pin Arduino riesce ad erogare 5V con una corrente Max di 40 mA.

Occorrerà quindi un circuito di interfaccia che si occupi di dare la giusta tensione e corrente ai motori, Arduino si occuperà solo di dare i segnali giusti a questa interfaccia.

Esistono vari circuiti che servono a tale scopo, più o meno complessi, vediamoli:

Metodo 1: Transistor

Questo è il modo più semplice, utilizza un solo pin di Arduino, però ha un grande limite: il motore potrà girare solo in un senso.

Lo schema è il seguente:

Con questo schema il transistor viene utilizzato come interruttore elettronico, viene infatti portata la base in saturazione. Si può utilizzare un BC547 (Qui potete scaricare il datasheet) o in alternativa un più robusto TIP120 (Qui potete scaricare il datasheet), facendo attenzione alla piedinatura dei due transistor in quanto è diversa.

Per avviare il motore basterà settare HIGH il pin di Arduino collegato al transistor, così facendo la velocità di rotazione del motore sarà la massima possibile.
Per spegnere il motore di conseguenza basterà settare LOW il pin.

Se vogliamo invece regolarne anche la velocità di rotazione collegheremo il transistor ad un pin PWM di Arduino.

Se volessimo regolarne la velocità basterà collegare il transistor ad un pin PWM dell’Arduino. In questo caso però si consiglia di avviare alla massima velocità il motore per un piccolissimo tempo (per vincere le inerzie meccaniche), per poi farlo girare alla velocità desiderata. Il tempo di velocità massima iniziale andrà provato empiricamente in base alla configurazione hardware utilizzata.

Nello schema è presente un diodo. Serve a proteggere il transistor dalla corrente prodotta dal motore quando ruoterà per inerzia nel momento in cui smetteremo di alimentarlo. Infatti il motore, se ruota senza essere alimentato, si comporta come un generatore di corrente che danneggerà il transistor (il principio è simile al recupero energetico che utilizzano le auto elettriche o ibride). Il diodo, più robusto del transistor, sopporterà il flusso di energia generato dal motore, bloccandola e non facendola passare verso il transistor.

Lo sketch da utilizzare per provarne il funzionamento è il seguente:

#define pulsante 4 // pin del pulsante
#define potenziometro A0 // pin del potenziometro
#define motore 9 // pin del motore
#define avvio 50 // tempo per lo spunto del motore
int velocitaminima = 80;  // valore della velocià minima del motore
int valVelocita; // velocità impostata con potenziometro
bool pressione; // variabile per leggere lo stato del pulsante
bool ultimapressione = false; // variabile per salvare lo stato della pressione pulsante
bool statomotore = false; //
bool ultimostatomotore = false; // vairabile per salvare se il motore sta girando, se false non servirà lo spunto
void setup() {
  pinMode(pulsante, INPUT_PULLUP);
  pinMode(motore, OUTPUT);
}
void loop() {
  pressione = digitalRead(pulsante);
  if (pressione == LOW && ultimapressione == HIGH) {
    statomotore = !statomotore; // Inverte lo stato del motore
  }
  ultimapressione = pressione;
  if (statomotore == true) { // se true allora il motore deve girare
    valVelocita = map(analogRead(potenziometro), 0, 1023, 0, 255); // Legge il valore del potenz. e lo converte in velocità
    if (valVelocita < velocitaminima) { // verifico se il valore è inferiore alla velocità minima
      valVelocita = 0; // se si la velocità sarà = 0, serve a non bruciare il motore.
      ultimostatomotore = false; // Il motore viene impostato su fermo
    }
  }
  if (statomotore == true && valVelocita > 0 && ultimostatomotore == false) {
    analogWrite(motore, 255); // mando al massimo il motore per il tempo "avvio" per vincere le inerzie meccaniche
    delay (avvio); // attendo il tempo di avvio
    ultimostatomotore = true; // il motore è avviato ed ha ricevuto lo spunto
    analogWrite(motore, valVelocita);
  }
  if (statomotore == true && valVelocita > 0 && ultimostatomotore == true) {
    analogWrite(motore, valVelocita);
  }
  if (statomotore == false || valVelocita == 0) {
    analogWrite(motore, 0);
    ultimostatomotore = false; // Il motore viene impostato su fermo
  }
}

Il pulsante funzionerà da on / off del motore e la velocità sarà costantemente regolata dal potenziometro. Se la velocità di rotazione sarà sotto una certa soglia la velocità del motore sarà impostata a zero. Questo serve ad impedire che il motore si fermi fisicamente, ma che resti comunque alimentato. Infatti se ciò accadesse il motore rischierebbe di bruciarsi.
Se la velocità del motore passa da fermo ad un valore sopra la soglia minima, interviene lo spunto per farlo avviare (una sola volta, fino a quando non verrà fermato), per poi andare alla velocità impostata.

Metodo 2: Ponte H

Il Ponte H è un particolare circuito composto da Transistor e diodi di protezione. Semplificando è come avere quattro degli schemi visti precedentemente messi insieme, con una forma simile appunto ad una H, che permettono di pilotare il motore e anche di scegliere il verso di rotazione.
Rispetto allo schema precedente per pilotare il motore occorreranno 4 pin di Arduino. La combinazione degli HIGH e dei LOW dei vari pin permetteranno l’accensione del motore e la scelta della direzione di rotazione.Il risultato dei casi 1, 4 e 5 all’atto pratico risulta identico, al motore non arriva corrente e quindi è fermo.

Nei casi 2 e 3 il motore ruota in un verso o nell’altro.

Utilizzo dell’L293D o del SN754410N con Arduino

L’L293D (Qui potete scaricare il datacheet) ed il suo equivalente SN754410N (Qui potete scaricare il datacheet) sono dei circuiti Integrati con all’interno 2 ponti H.
– la corrente max erogabile è tra i 600mA dell’L293D ed 1A per L’SN754410N.

Possono essere utilizzati per:
– pilotare 4 Motori CC che ruotano in un verso solo.
– pilotare 4 Relè.
– pilotare 2 Motori CC e permettere di scegliere il verso di rotazione.

Noi vedremo quest’ultimo utilizzo.
Il circuito integrato è praticamente speculare.
Ci sono due alimentazioni:
– Vcc1 è quella logica, che noi collegheremo ai 5V di Arduino.
– Vcc2 è quella dei motori che può andare fino a 36V.
Il pin 1,2EN ed il pin 3,4EN se messi HIGH abilitano rispettivamente i motori 1,2 e 3,4 (quindi funzionano a coppie).
i 4 pin A se posti HIGH abilitano i rispettivi Motori dei pin Y.
Utilizzando la configurazione a 2 Motori, con scelta del verso di rotazione, dovremo seguire la seguente tabella:

La tabella è identica anche per il secondo motore 2,4EN, 3A, 4A.

Se non ci interessa regolare la velocità dei motori potremo collegare a 5V i pin 1,2EN e 3,4EN risparmiando così 2 pin di Arduino.

Se vogliamo invece gestirne anche la velocità di rotazione 1,2EN e 3,4EN andranno collegati a 2 pin PWM di Arduino.

Lo schema per utilizzare l’L293D o il suo equivalente SN754410N è il seguente:Lo sketch da utilizzare per provarne il funzionamento è il seguente:————

//Connessioni al L293D
#define EN12 6
#define A1 7
#define A2 8
#define A3 9
#define A4 10
#define EN34 11
#define pulsante 12
#define potenziometro A0
bool rotazione = false; // variabile per senso rotazione
bool pressione; // variabile per leggere lo stato del pulsante
bool ultimapressione = false; // variabile per salvare lo stato della pressione pulsante

int velocita = 0; // velocità predefinita
int velocitaminima = 130; // valore da trovare empiricamente in base alla propria configurazione hardware

void Motore1avanti () {
  digitalWrite(A1, 1);
  digitalWrite(A2, 0);
  analogWrite(EN12, velocita);
}

void Motore2avanti () {
  digitalWrite(A3, 1);
  digitalWrite(A4, 0);
  analogWrite(EN34, velocita);
}

void Motore1indietro () {
  digitalWrite(A1, 0);
  digitalWrite(A2, 1);
  analogWrite(EN12, velocita);
}

void Motore2indietro () {
  digitalWrite(A3, 0);
  digitalWrite(A4, 1);
  analogWrite(EN34, velocita);
}

void Motore1fermo () { // se il pin EN12 è = LOW o = 0 il motore si fermerà
  analogWrite(EN12, 0); // A1 e A2 possono quindi assumere qualunque valore
}

void Motore2fermo () { // se il pin EN34 è = LOW o = 0 il motore si fermerà
  analogWrite(EN34, 0); // A3 e A4 possono quindi assumere qualunque valore
}

void setup() {
  pinMode(EN12, OUTPUT);
  pinMode(EN34, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(pulsante, INPUT_PULLUP);
  analogWrite(EN12, 0); // blocca il motore A
  analogWrite(EN34, 0); // blocca il motore B
}

void loop() {
  velocita = map(analogRead(potenziometro), 0, 1023, 0, 255);
  if (velocita < velocitaminima) {
    velocita = 0;
  }
  pressione = digitalRead(pulsante);
  if (pressione == LOW && ultimapressione == HIGH) {
    rotazione = !rotazione; // Inverte lo stato del motore
  }
  ultimapressione = pressione;
  if (rotazione == true) { // se true allora il motore gira in Avanti
    Motore1avanti();
    Motore2avanti();
  }
  if (rotazione == false) { // se true allora il motore gira in Indietro
    Motore1indietro();
    Motore2indietro();
  }
}

Funzionamento del programma:
– Inizialmente acquisisce il valore della velocità dal potenziometro e la compara con la velocità minima.
Come già detto, se i motori girano al di sotto di una certa velocità si fermeranno fisicamente, rimanendo però alimentati, con il rischio di bruciarsi. Quindi al di sotto di una certa velocità (da verificare empiricamente in base al proprio hardware), la velocità verrà impostata a 0.
– I motori ruoteranno in avanti o indietro cambiando verso ogni volta che si premerà il pulsante

NOTA: Come per l’esempio del Transistor, se si impostano velocità basse di rotazione e si deve avviare il motore da fermo, si rischia che questo non vinca le inerzie meccaniche e non si avvii, rischiando così di bruciarsi. Conviene gestire questo evento dando per un brevissimo tempo la velocità massima per poi andare alla velocità impostata. Si veda lo sketch di esempio all’inizio di questa pagina.

Utilizzo dell’ L298N con Arduino

Se i nostri motori necessitano di correnti maggiori e fino a 2A, si può utilizzare un altro circuito integrato: l’L298N (Qui potrete scaricare il datasheet).

Cambia il packaging, ma il funzionamento è identico; ha però 2 pin in più: il current sensing A ed il B, che non tratteremo ora.

Il L298N si trova già assemblato con tutta l’elettronica necessaria al suo funzionamento. Una versione è la seguente:

Note sulla scheda: Enable A ed Enable B sono forniti con due ponticelli, se non ci interessa regolare la velocità di rotazione dei motori possiamo lasciare i ponticelli montati, altrimenti dovremmo collegare i relativi pin a dei pin PWM di Arduino.

Il JUMPER +5V permette di far circolare la tensione dei motori dentro uno stabilizzatore a +5V che alimenta la logica del L298N, se alimentiamo i motori con tensioni maggiori di +12V DEVE essere rimosso, altrimenti lo stabilizzatore si danneggia. Una volta rimosso tale JUMPER si dovrà provvedere a fornire i +5V esternamente. Nel caso si alimenti con tensioni inferiori a +12V il JUMPER può essere lasciato, così facendo lo stabilizzatore fornirà sia tensione +5V alla logica, che in uscita del morsetto (potremmo utilizzare questi +5V per alimentare Arduino).

Lo schema per utilizzare l’L298N è il seguente:

Lo sketch da utilizzare per provarne il funzionamento è il seguente:

//Connessioni al L298N
#define ENA 11
#define IN1 10
#define IN2 9
#define IN3 8
#define IN4 7
#define ENB 6
#define potenziometro A0
#define pulsante 4

int velocita = 0; // velocità predefinita
int velocitaminima = 100; // valore da trovare empiricamente in base alla propria configurazione hardware

void MotoreAavanti () {
  digitalWrite(IN1, 1);
  digitalWrite(IN2, 0);
  analogWrite(ENA, velocita);
}

void MotoreBavanti () {
  digitalWrite(IN3, 1);
  digitalWrite(IN4, 0);
  analogWrite(ENB, velocita);
}

void MotoreAindietro () {
  digitalWrite(IN1, 0);
  digitalWrite(IN2, 1);
  analogWrite(ENA, velocita);
}

void MotoreBindietro () {
  digitalWrite(IN3, 0);
  digitalWrite(IN4, 1);
  analogWrite(ENB, velocita);
}

void MotoreAfermo () { // se il pin ENA è = LOW o = 0 il motore si fermerà
  analogWrite(ENA, 0); // IN1 e IN2 possono quindi assumere qualunque valore
}

void MotoreBfermo () { // se il pin ENB è = LOW o = 0 il motore si fermerà
  analogWrite(ENB, 0); // IN3 e IN4 possono quindi assumere qualunque valore
}

void setup() {
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(pulsante, INPUT_PULLUP);
  analogWrite(ENA, 0); // blocca il motore A
  analogWrite(ENB, 0); // blocca il motore B
}

void loop() {
  velocita = map(analogRead(potenziometro), 0, 1023, 0, 255);
  if (velocita < velocitaminima) {
    velocita = 0;
  }
  if (analogRead(pulsante) == LOW) {
    MotoreAavanti();
    MotoreBavanti();
  }
  else {
    MotoreAindietro ();
    MotoreBindietro ();
  }
}

Funzionamento del programma:
– Inizialmente acquisisce il valore della velocità dal potenziometro e la compara con la velocità minima.
Come già detto, se i motori girano al di sotto di una certa velocità si fermeranno fisicamente, rimanendo però alimentati, con il rischio di bruciarsi. Quindi al di sotto di una certa velocità (da verificare empiricamente in base al proprio hardware), la velocità verrà impostata a 0.
– I motori ruoteranno in un verso alla velocità impostata
– Se si preme il pulsante i motori ruoteranno nell’altro verso alla velocità impostata

Fondamentalmente non c’è differenza nel programma tra usare l’L293D, l’SN754410N  L298N.