Gen 202014
 

Oggi vediamo come collegare multiple schede Arduino tramite porta RS485. Il mio interesse per la comunicazione seriale fra diverse schede nasce dalla necessità di connettere insieme più schede per farle interagire tra loro nel contesto di un progetto domotico. Se cercate in rete troverete molti modi diversi per connettere insieme degli Arduini con bus diversi, I2C, RS485,RS232, etc. Ognuno ha i suoi pregi e difetti alcuni permettono trasmissioni solo a breve distanza, altri a centinaia di metri, alcuni permettono di collegare solo 2 dispositivi, altri permettono di arrivare ad un numero maggiore, alcuni permettono un collegamento di tipo master-slave, altri di tipo multimaster. Insomma, c’è davvero da perdersi. Ora vi chiederete: perchè hai scelto l’RS485? Gli obiettivi che mi prefiggevo erano la possibilità di connettere multipli dispositivi in contemporanea, poter avere una linea lunga abbastanza da cablare l’intera casa, essere abbastanza immune ai disturbi e costare poco. L’RS485 permette di raggiungere i 1200 metri senza ripetitori, permette di connettere da 32 a 256 dispositivi in base ai chip usati, è molto economica ed è scarsamente sensibile ai disturbi. Se ci fossero solo fattori positivi non esisterebbero neanche le alternative, ma come dicevamo ogni standard ha lati positivi e negativi. I negativi riguardano il fatto che l’RS485 descrive solamente la connessione fisica ma non descrive in che modo vengono trasmessi i dati seriali, quindi il protocollo dobbiamo scrivercelo da noi, dobbiamo occuparci noi del controllo d’integrità della trasmissione e l’eventuale ritrasmissione dei pacchetti di dati corrotti.

RS485: Le basi

La RS485 consiste in un bus formato da 2 soli conduttori detti A e B, per le connession Half Duplex.

Nei due conduttori scorre lo stesso segnale ma uno è speculare all’altro, se in uno scorre un segnale alto, nell’altro ci sarà un segnale basso e viceversa. Per fare un paragone, il +12 della RS232 corrisponde al +5 della linea A della RS485 e 0 (zero) della linea B. Viceversa il -12 della RS232 corrisponde a 0 di A e +5 di B. Nell’immagine in adiacenza potete vedere uno schemino comparativo.

Questo sistema di invio speculare dei dati prende il nome di “linea differenziale” in quanto il ricevitore non analizza il semplice livello del segnale ma la differenza fra i due, per questo l’RS485 è definita “linea differenziale“. Ciò fà si che la linea sia particolarmente immune ai disturbi esterni, in quanto un eventuale disturbo interferisce in maniera simile su entrambe le linee per cui la loro differenza viente mantenuta, basti pensare che anche se la RS485 usa segnali a 5V, la soglia minima è di soli 1.5V e la soglia differenziale fra le due linee per interpretare correttamente un segnale è di soli 200mV. Un’altra cosa importante è la geometria del bus. Ci sono bus che per loro natura sono obbligati ad avere una determinata configurazione, l’RS485 non è di questi per cui per aggiungere un dispositivo non si fà altro che collegare i 2 cavi in un qualunque punto della rete ed il gioco è fatto. Più sopra accennavo, senza approfondire, al termine Half Duplex, ma cosa significa? Per capirlo facciamoci una semplice domanda. Se in una rete abbiamo 5 dispositivi collegati insieme e viene rintracciato un segnale; questo ipotetico segnale da chi è stato inviato e a chi è indirizzato? Chi può inviare e chi riceve? Nella comunicazione HalfDuplex può passare un solo segnale differenziale alla volta per cui di fatto solamente UN SOLO dispositivo può inviare dati in un certo momento e TUTTI gli altri possono solo leggere quel segnale . E’ come un binario in cui il treno che può andare in una sola direzione alla volta e non ci possono essere più treni sullo stesso pezzo di rotaia nello stesso momento.

Infatti l’applicazione più tipica dell’RS485 che trovate pressochè ovunque è la cosidetta configurazione single master – multi slave che significa che c’è un nodo “master” che è l’unico deputato all’invio spontaneo di comandi sul bus, e multipli “slave” (schiavi) che possono rispondere unicamente quando interrogati dal master. Questa è la tipologia di connessione più usata e più semplice da sviluppare ma ha un grossso difetto concettuale. Se il master si rompe, si blocca, gli tagliamo i cavi o qualunque altra cosa, tutta la rete resta bloccata perchè gli slave non sono autorizzati ad inviare dati se non in risposta a comandi inviati dal master. L’altra cosa intuibile è che quando il master invia un comando, tutti gli slave ricevono in contemporanea quel comando per cui per decidere chi è che dovrà rispondere è necessario predisporre una struttura software che gestisca questo aspetto. Esisono però dei chip che permettono la trasmissione cosidetta Full-Duplex. In questo caso non vengono usati 2 conduttori ma 4 (A,B,Z,Y) e le linee di trasmissione dei master sono collegate a quelle di ricezione degli slave. In questo modo trasmissione e ricezione possono avvenire in contemporanea, ma fate molta attenzione perchè è solo una mezza verità. Infatti solo un master alla volta potrà trasmettere e solo uno slave alla volta potrà rispondere, inoltre i master non sono collegati fra di loro e gli slave non sono collegati fra loro per cui nessun master conosce i dati inviati dagli altri e lo stesso avviene per gli slave.  Nello schema qui a fianco potete vedere il tipico collegamento Full Duplex.

Ognuno è ovviamente libero di usare lo schema che più predilige in base alle proprie esigenze, ma nel mio caso avevo l’esigenza di collegare più centraline, ognuna indipendente e tutte in grado di conoscere l”attività delle altre. Questo è il tipo di collegamento più complesso, ma sicuramente il più flessibile. In definitiva andremo ad usare una connessione RS485 half duplex multimaster, ossia una configurazione in cui tutte le schede possono decidere autonomamente quando cominciare una trasmissione seriale e in cui tutte vedono le trasmissioni delle altre. A questo punto sorge spontanea una domanda: “come facciamo a decidere chi può trasmettere e soprattutto quando?”.

MAX485 – SN75176

I nomi qui sopra altro non sono che alcuni comuni chip in grado di creare un punto di comunicazione RS4585 half duplex. Ho scelto questi due in quanto sono i più facilmente reperibili sul mercato e sono intercambiabili in quanto hanno il medesimo pinout (i pin di uscita sono nelle stessa posizione e funzionano nello stesso modo). Per praticità mi riferirò al max485, ma quanto scritto vale per entrambi. Qui vicino vi ripropongo lo schema classico del chip. Come potete vedere ci sono ci sono 8 pin di cui i classici VCC (5V) e GND per alimentazione e massa. Fate attenzione che esistono anche altri chip con alimentazione diversa dai 5V. Come vedete ci sono le linee A e B per la comunicazione differenziale di cui accennavamo sopra. Vediamo ora gli altri 4. DE (Driver Output Enable): Quando viene messo a livello alto il chip viene attivato quale output, ossia per inviare dati. Viceversa quando è allo stato basso il chip funziona da ricevente per i dati inviati da altri. Và da se che solo un chip sulla linea potrà essere a livello HIGH nel medesimo istante in quanto, come abbiamo detto, solo un chip alla volta può trasmettere dati. RE (Receiver Output Enable): Quando è messo a livello basso il chip è in grado di ricevere dati dalla linea differenziale. DI (Driver Input): riceve i dati da inviare per cui sarà collegato alla linea TX della UART del nostro Arduino RO (Receive Output): In questo pin arrivano i dati letti dalla linea differenziale, per cui andrà connesso alla linea RX della UART di Arduino. Se A > di B di almeno 200mV RO sarà allo stato alto, viceversa se A < B di almeno 200mV sarà allo stato basso.

La via più semplice…

La via in assoluto più semplice per inviare e ricevere dati è utilizzare un pin digitale aggiuntivo di controllo collegato direttamente a DE ed RE. Quando questo è posto altro il chip sarà pronto alla trasmissione di dati mentre quando sarà basso verrà usato per la ricezione. In genere si usa questo sistema nelle comunicazioni master-multislave. Gli slaves restano in ricezione ed il master in trasmissione. Quando il master ha trasmesso e si aspetta una risposta va in ricezione e lo slave che deve rispondere passa in trasmissione, per poi tornare allo stato originario quando la comunicazione è terminata. I lati negativi sono legati al fatto che usiamo un pin digitale aggiuntivo su ogni scheda ed ogni volta che decidiamo di inviare o ricevere dati dobbiamo ricordarci di settare per primo quel pin costruendo apposite routines software. Inoltre questo sistema funziona in maniera semplice con la configurazione master-multislave, ma se volete usare una configurazione multimaster siete costretti a ricorrere a complicati algoritmi software per evitare che più master inviino dati allo stesso momento.

Una via alternativa…

Se ci interessasse la via più semplice non avrebbe avuto molto senso scrivere questo articolo, internet ne è già piena, sarebbe l’ennesimo inutile copia-incolla. Durante lo sviluppo del mio progetto mi sono imbattuto in una tecnica che da un lato aggiunge complessità hardware, dall’altro fa risparmiare risorse software e ne riduce la complessità migliorando l’affidabilità del software stesso.  Non voglio dire che sia una via migliore o peggiore, è solo una via diversa per risolvere lo stesso problema delegando all’hardware ciò che prima facevamo via software. Vorrei specificare che non è una mia invenzione, ho solo ripreso un articolo di Jan Axelson ritenendo che la sua soluzione fosse quando di più adatto potessi trovare per il mio progetto. Il concetto di per se è estremamente semplice, ossia, anziché sprecare un pin digitale per dire al nostro chip se ricevere o inviare dati, facciamo si che di base li riceve e non appena inviamo dati sulla uart commuta il chip 485 per  inviare dati. Per farlo utilizziamo un NE555 di cui abbiamo parlato in questo articolo in configurazione monostabile. In pratica non appena dalla UART viene intercettato il fronte di discesa del bit di start, l’output del 555 mette il max485 in uno stato di invio. Non appena arriva il bit di stop o un fronte di salita l’NE555 fà si che entro 40microsecondi venga commutato lo stato del max485 dalla trasmissione alla ricezione. Il tempo di 40 microsecondi corrisponde a circa mezzo bit nella trasmissione a 9600baud. La domanda che potrebbe sorgere spontanea è: ma ogni volta che ho un fronte di salita mi si chiude la connessione? In effetti è così, ma nello stato base il segnale è alto per cui non ha alcuna importanza se il chip in trasmissione si è momentaneamente messo in ricezione, l’importante è che i destinatari vedano il segnale alto, poi se c’è un nuovo zero da inviare l’NE555 riattiva la trasmissione del max485. Ora vediamo lo schema con le varie connessioni: rs485autoSembra più complesso di quel che è realmente, ma se guardate bene non sono che pochi componenti. Ci sono alcune cose importanti da notare. Sulla destra ho preparato un “connettore” in cui “scorrono” i canali A e B della RS485 assieme a massa e 5V. Questo perchè la massa deve essere comune fra i vari chip RS485 connessi per cui sono costretto ad usare un cavo comune. Inoltre i 5V mi permettono di alimentare i chip distanti ed eventualmente altri Arduini per cui con 4 conduttori ho sia alimentazione che dati. Si notino, vicino al connettore, le resistenze da 560 Ohm che permettono di tenere alto il segnale quando nessuno trasmette. Si noti anche la resistenza da 120Ohm e l’adiacente Jumper. Questa resistenza deve essere messa all’inizio ed alla fine della linea RS485 per cui possiamo usare il jumper per abilitarla solamente nelle due schede che stanno all’inizio ed alla fine della linea, lasciando aperto il jumper nelle restanti schede connesse in serie. Si noti anche la “linea verde”, ossia la linea di trasmissione che esce da Arduino e si porta sia al Max485 per trasmettere i dati veri e propri, che al 555 per determinare l’inizio della trasmissione vera e propria.

Pronti…via..A B 5555

Non ci resta che costruirci il circuito e scrivere il software per gestire il tutto. Nella foto poco più sotto potete vedere il circuito replicato due volte in quanto ho fatto i primi test con 2 schede Arduino connesse insieme. Sul versante software ho cercato di mantenere la massima semplicità, non è infatti questa la sede per dedicarsi ad un vero e proprio protocollo di trasmissione. Una prima scheda Arduino invia sulla seriale il numero 7 all’infinito, ogni 100ms, l’altra scheda invia il “2”, inoltre legge dalla porta seriale e se riconosce il “7” inviato dall’altra scheda fà lampeggiare il led collegato alla porta 13. Volevo farvi un video, ma diciamocelo, un filmato in cui si vedono dei led lampeggiare non è che sia molto utile.  In compenso ho testato il circuito con l’oscilloscopio, e qui vicino vi allego l’immagine delle tracce digitali rilevate: le due tracce bianche sono rispettivamente A e B, ossia le linee differenziali in uscita. In viola, in basso, c’è l’uscita del 555. Come potete vedere si nota come l’inizio della trasmissione coincide perfettamente con l’abilitazione in trasmissione del max485 mentre quando il segnale torna alto la trasmissione viene chiusa con un leggero ritardo.   Per quanto riguarda la parte software ho programmato un Arduino con questo listato:

rs485hd

void setup()
{
  Serial.begin(9600);
}

pinMode(13, OUTPUT);

void loop() 
{
  Serial.print("7"); 
  delay(100);
}

..e l’altro con ques’altro:  

void setup()
{
  Serial.begin(9600);
  delay(500);
}

void loop() 
{
  Serial.print("2"); 
  while (Serial.available())
  {
    char inChar = (char)Serial.read(); 
    if(inChar=='7')
    {
     digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
     delay(50);               // wait for a second
     digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    }
}
delay(111);
}

Prima di concludere vorrei aggiungere alcune note. La prima riguarda la resistenza da 120 Ohm posta fra le linee A e B ai due estremi del bus. Nel circuito di prova che vedete nella foto sopra ho dovuto toglierle in quanto si materializzava una strana asimmetria dei segnali A e B che non sono riuscito a spiegare anche se la precarietà del circuito su breadboard lascia sempre delle perplessità in sospeso. Un’altra cosa che devo dirvi è che tutto ciò che vi ho raccontato lo potete in realtà semplificare con dei chip che incorporano già al loro interno le funzionalità descritte in questo articolo, come ad esempio MAX13487 o il MAX13488 che peraltro permettono di connettere 128 chip sulla medesima linea a differenza dei 32 dei Max485. Ovviamente io stesso dovrò fare test più approfonditi e scrivere un vero e proprio protocollo di comunicazione, ma per ora devo fermarmi qui anche perchè non ho certo un centinaio di schede Arduino da poter collegare insieme. Magari potrei fare qualche test mescolando le 4 Arduino Uno, la Mega, la Due e Raspberry anche se queste ultime due introducono nuovi problemi dato che i loro pin non operano a 5V ma a 3.3, ma vi terrò aggiornati, anche in base a quanto interesse avrete verso questo articolo.

  4 Responses to “Arduino e porta seriale RS485 – it”

  1.  

    Mi piacerebbe, ma non li ho ancora provati per cui non ho fatto ancora alcuna prova. Quel che dici è giusto, ossia elimina la necessità di usare il 555, ma purtroppo anch’io l’ho scoperto quando già stavo scrivendo l’articolo qui sopra e quindi non ho fatto in tempo ad acquistarlo per fare le prove del caso. Tieni conto che ogni circuito che trovi sul blog viene testato a lungo prima di venir pubblicato, per cui ci sono sempre ore ed ore di lavoro dietro ogni articolo, motivo per il quale non trovi schemi di cose che non ho testato prima.
    Ora, tra le altre, sto ristrutturando casa e tutto il materiale elettronico è inscatolato al piano di sotto. Per questi motivi dovrai avere un bel po’ di pazienza prima di vedere un max1348x su queste pagine, lo terrò comunque presente per il prossimo futuro.

    Ciao
    Stefano

  2.  

    Ciao è un bellissimo articolo anch’io vorrei crearmi una Domotica a casa ma essendo poco pratico nn so da dove iniziare speravo che qualcuno pi potesse aiutare sopratutto nella programmazione dove do delle lacune dato che nn ne ho mai fatte per l’impianto nn ho problemi dato che sono un’elettricista e decisamente il mio campo!!!

  3.  

    Ciao, progetto molto interessante, vorrei collegare il max485 a una Raspberry PI, su alcuni forum sconsigliano di collegare direttamente 5v al gpio (che lavora a 3,3V).
    Se utilizzassi il tuo circuito però aggiungendo un partitore di tensione, come questo che ho trovato?
    1K
    3,3V <—————-|——-\/\/\/\/——-< 5V MAX485
    \
    / 2K
    \
    /
    |

    ///