Oggi vediamo come collegare numerosi relè 12V ad Arduino. Uno degli articoli più visitadi di questo blog è il primo articolo sul collegamento di un relè 12V a cui vi rimando per un ripasso delle informazioni di base; inoltre vi ricordo che qui ho pubblicato un calcolatore online utile per dimensionare la resistenza alla base del transistor. Oggi vediamo l’evoluzione di quegli articoli e ci chiediamo: come facciamo ad aggiungere altri relè? E se volessi comandare 24 relè con un singolo Arduino posso farlo? E se si come? Ora che sappiamo quali sono le domande cominciamo con la parte pratica.
ULN2803
Se abbiamo studiato come collegare un relè, possiamo facilmente espandere la cosa sino an un massimo di 14, ossia il numero di porte digitali in uscita da arduino, anche se a dirla tutta potremmo sfruttare anche quelle analogiche per pilotare i transistors, ma non complichiamoci la vita inutilmente. Se ricordate, per ogni relè ci servirà una resistenza, un diodo ed un transistor, oltre al relè vero e proprio.
Ma andiamo oltre. Arduino possiede altre porte libere per cui potremmo affiancare un altro ULN2803 per unire ulteriori relè, anche se non riusciremmo a sfruttare tutte le uscite del secondo integrato. Ma se volessimo andare oltre ad esempio collegando 16 relè? E’ possibile farlo?
Shift Register 74HC595
La soluzione è lo shift register, come ad esempio il 74HC595 che è un chip SIPO (Serial In Output Out). Cose significa? Significa che riceve un input seriale e fornisce un output parallelo. Pensiamoci bene. Sappiamo già cos’è una trasmissione seriale, un singolo carattere trasmesso occupa 8 bit per cui con un solo byte inviato serialmente si potrebbe indicare lo stato di ben 8 uscite. Il concetto è proprio questo. Vengono inviati i singoli bit allo shift register, questi “si spostano” all’interno delle otto celle di memoria dello shift register stesso fino al completamento dei bit ricevuti. Arriva il primo bit che si mette nella prima cella. Quando arriva il secondo, il precedente sarà spostato (shift) nella cella adiacente e la prima sarà occupata dal nuovo bit e via discorrendo sino al termine dei dati. A questo punto, per completezza, meglio specificate che esistono due grosse
Ovviamente alle uscite dell’ULN2803 vanno collegati i relè, io ho disegnato dei connettori con contatti a coppie 12V/Gnd. Alcune note: come vedete il MR è collegato direttamente ai +5V per cui le uscite non vengono mai azzerate. OE è collegato a massa, ciò significa che non appena memorizziamo qualcosa nello storage register il suo contenuto si riflette direttamente sull’effettivo contenuto delle uscite. Ovviamente se OE è collegato a massa, dobbiamo per forza controllare direttamente il ST_CP per decidere quando copiare le celle dello shift register nello storage register. In definitiva potete notare come con soli 3 pin di Arduino occupati siamo in grado di pilotare 8 relè, ma la bella notizia è che possiamo unire in serie multipli 74HC595 per andare a comandare 16,24,32 o oltre uscite in contemporanea. Per farlo non facciamo altro che collegare Q7′ al DS del chip successivo ed il gioco fatto. Nello schema qui sotto vi faccio vedere come si collegano in serie. In questo caso il pin Q7′ è l’uscita seriale del primo chip ed andrà nell’ingresso (DS) del secondo, e così a cascata per eventuali ulteriori chip.
Ora vi domandereet: dov’è la fregatura? La risposta è la velocità, ma solo teoricamente. Infatti, a titolo di paragone, il nostro Arduino arriva a 16MHz mentre questi chip da 57 a 100MHz (ci sono diversi modelli), ossia possono cambiare stato dello shift register decine di decine di migliaia di volte al secondo, motivo per cui occorre collegarne davvero tanti prima di riuscire a percepire un rallentamento umanamente riconoscibile. Ho fatto un test con 8 led al posto dei relè che si accendo in serie dal primo all’ultimo per poi riprendere e, togliendo ogni tipo di ritardo, la velocità è tale che i led sembrano sempre accesi, non è possibile vedere ad occhio la variazione di luminosità. Anche con 16 led non risulta possibile distinguere ad occhio le tempistiche di illuminazione e spegnimento.
Una cosa importante che ho scordato di dire è che le uscite del 74HC595 hanno una tensione pari a quella di alimentazione (tipicamente 5V ma funziona anche a 3) con una corrente che è inferiore a quella delle uscite di Arduino, tipicamente 20mA.
A dirla tutta è possibile usare degli artifizi misti tra hardware e software per ridurre ulteriormente il numero di pin Arduino impiegati, il rovescio della medaglia è una ulteriore riduzione della velocità ed un incremento della complessità del software, ma in alcuni casi può essere un’opzione da tenere in considerazione, specie se invece che usare l’Arduino si utilizzano chip con un minor numero di pin (come l’AT tiny85) o vi sia la necessità di risparmiare pin per altri utilizzi. Un caso tipico è l’uso di display LCD in cui non vi è la necessità di refresh real-time, magari in futuro potrei scrivere un articolo in merito visto che è una tecnica che non ho mai provato e potrebbe essere interessante compararla con le vie più classiche.
Ora che abbiamo visto la parte hardware dobbiamo passare a quella software che in realtà è davvero molto semplice.
const int latchPin = 12; //Pin connected to latch pin (ST_CP) of 74HC595 const int clockPin = 11; //Pin connected to clock pin (SH_CP) of 74HC595 const int dataPin = 13; //Pin connected to Data in (DS) of 74HC595 void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); } void loop() { for (int i=0;i<8;i++) { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, 1<<i); digitalWrite(latchPin, HIGH); delay(90); } }
Con questo codice vedrete i led o comunque ciò che collegate alle uscite, aprirsi in sequenza: si accende il primo, si spegne e si accende il secondo, si spegne e accende il terzo e via discorrendo. Questo listato gestisce le prime 8 uscite, ma fate attenzione a questa cosa. Quando abbiamo inviato gli 8 bit che determinano quali uscite vanno accese o spente, tutte le celle di memoria sono occupate. A questo punto quando passiamo ad un nuovo ciclo ed inviamo un nuovo bit, l’ultimo presente nelle celle dello shif register passa a Q7′ e quindi, se vi sono shift register aggiuntivi collegati in cascata, andrà a finire nel secondo integrato. Di fatto quel che succede è che, inviando sempre il medesimo loop, i due shift register connessi insieme avranno le uscite disposte nella stessa maniera per cui si forma una sorta di copia. Il listato di sopra è molto semplice. Prima vengono definite tre costanti per memorizzare a quale pin abbiamo connesso il 74HC595, questo passo non è obbligatorio, ma ci permette di modificare in maniera semplice il listato se decidiamo di modificare l’hardware. Nel setup vengono impostati come uscite i tre pin necessari al collegamento. Poi si passa al loop principale in cui abbiamo inserito un ciclo for che determina l’accensione di un led alla volta. Vediamo che prima portiamo a LOW la linea latch, poi facciamo lo shift con l’apposita finzione shiftOut e poi riportiamo ad HIGH la linea latch per copiare i dati shiftati precedentemente nelle relative uscite. Ricordiamo che OE è sempre connesso a massa per cui non dobbiamo preoccuparcene da un punto di vista software. Per quanto riguarda l’istruzione shiftOut, vediamo che prende come parametri il pin ove inviare i dati seriali, il clock SH_CP e altri due parametri. Il primo dei due può essere impostato a MSBFIRST o a LSBFIRST, ossia indica se inviare il byte di dati a partire dal bit più significativo o dal meno significativo a seconda di come abbiamo fatto i collegamenti sull’hardware e come vogliamo utilizzare il software. L’ultimo parametro riguarda il byte da shiftare dentro il 74HC595. Ricordatevi che deve essere un valore compreso fra 0 (tutte le uscite spente) a 255 (tutte accese), utilizzando la logica binaria.
Nell’esempio ho usato 1 < < i che è l’equivalente di 2 elevato alla i, quindi inizialmente abbiamo 2 alla 0 che vale 1 (solo prima uscita aperta), poi vale 2,4,8,16,32,64 e per finire 128. Se banalmente sommate questi valori, nel caso abbiate problemi con la matematica binaria, ottenete l’accensione delle relative uscite.
L’istruzione shiftOut invia solamente un byte alla volta per cui se ad esempio ne avete due, vi conviene mantere un array di caratteri con le diverse uscite ed inviarle in successione. Giusto per fare un esempio, prendiamo quello di sopra ed inviamo al secondo shift register la copia speculare del primo, in modo che il primo accenda le luci da sinistra a destra ed il secondo da destra a sinistra:
const int latchPin = 12; //Pin connected to latch pin (ST_CP) of 74HC595 const int clockPin = 11; //Pin connected to clock pin (SH_CP) of 74HC595 const int dataPin = 13; //Pin connected to Data in (DS) of 74HC595 void setup() { pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); } void loop() { for (int i=0;i<8;i++) { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, 1<<(7-i)); // oppure shiftOut(dataPin, clockPin, LSBFIRST, 1<<i); shiftOut(dataPin, clockPin, MSBFIRST, 1<<i); // shiftOut(dataPin, clockPin, MSBFIRST, 1<<i); digitalWrite(latchPin, HIGH); delay(90); } }
}
Come vedete la differenza rispetto a prima è minima è solo l’aggiunta della riga che invia i dati al secondo shift register. Dato che i dati scorrono dal primo al secondo, risulta ovvio che prima vanno inviati per primi
Bellissimo Post.
Una domanda: io sto usando una scheda relè da 8 (http://www.sainsmart.com/8-channel-dc-5v-relay-module-for-arduino-pic-arm-dsp-avr-msp430-ttl-logic.html).
E’ attivata mettendo a GND il pin desiderato.
Al momento sto usando uno shift register come sopra solo che al posto di avere ULN2803 ho dei singoli transistor. Fin qui tutto bene. Quando faccio il test funziona tutto alla grande. Quando invece attacco il carico (ogni relè serve per attivare una tapparella da 200W – 220V 1A circa) e gioco un po attivando e disattivando il relè, magicamente si attivano dei relè che non ho comandato. Domanda:
– può essere qualche induzione provocata dalla 220V ?
– come posso risolvere?
– questa scheda relè è attivata per LOW quindo posso usare uno ULN2803 lo stesso?
Grazie
l’ULN si lo puoi usare, le uscite sono a massa e non i positivi, per cui non hai problemi. Se però “senza carichi” non hai problemi, non dipende certo dal fatto che usi i transistor piuttosto che l’uln. Difficile darti una risposta certa, l’unica cosa sicura è che non dovresti avere questo tipo di problema :-). Hai messo il condensatore di disaccopiamento della linea di alimentazione dello shift register? Se la risposta è non aggiungilo. Altre cosa, come alimenti la “scheda relè”? Se prelevi direttamente da Arduino potrebbe essere che sei ai limiti (o oltre) le possibilità del regolatore di tensione il che si comincia a manifestare con problemi un po’ casuali….prova ad usare una fonte di alimentazione esterna che garantisca il massimo assorbimento quando tutti i relè sono chiusi……anche se in teoria non dovrebbe cambiare nulla con o senza carico esterno collegato.
Ciao Simone,
ho avuto qualche problema anche io con l’attivazione carichi induttivi sui relè.
Ho risolto con qualche prova mettendo dei filtri RC in uscita ai contatti dei relè.
Per carichi 24Vac ho messo un condensatore da 0,1uF in serie a una resistenza da 47ohm, mentre per carichi 220Vac condensatore 0,1uF e resistenza 100ohm. Fai attenzione al condensatore sulla 220Vac che regga la tensione (lo vedi sul lato) altrimenti scoppia.
Se non hai problemi senza carichi dovrebbe funzionare.
Ciao
Grazie 1000 per il tuo contributo. Io personalmente non ho mai avuto questo tipo di problema ma probabilmente dipende dalla tipologia di carichi applicati. Vediamo se Simone risolve i suoi problemi in questo modo