mercoledì 20 luglio 2016

Arduino comunicazione seriale RS485

Come far comunicare due o più schede Arduino o EDI su seriale (bus) RS485 ?

In questo Tutorial mostreremo come far comunicare tra loro più schede Arduino o ETA BETA EDI utilizzando la comunicazione seriale RS485 che può essere sfruttata in un progetto domotico fai da te.

Ciò che faremo è comandare i 2 relè della scheda con ID1 con i 2 button della scheda con ID2 ed allo stesso modo con i 2 button della scheda con ID2 comanderemo i relè della scheda ID1 .



Collegamento di tipo seriale RS485 con resistenza di terminazione RT


  1. Cos’è la connessione seriale rs485?
Altro non è che un sistema di connessione a due fili denominati A e B, HALF DUPLEX, che sfrutta la trasmissione differenziale del segnale tra i 2 fili, cioè la differenza di tensione tra i due cavi (almeno di 0,2Volt) è il dato trasmesso.


Segnale Differenziale A-B

Perchè utilizzare questo tipo di comunicazione (BUS)?
  • Può arrivare a distanze di comunicazione maggiori rispetto agli altri bus (1200m)
  • Possono essere connesse da 2 a 256 schede a seconda del tipo di driver.
  • Scarsamente sensibile ai disturbi.


Lo svantaggio di questo tipo di comunicazione seriale RS485 è quello di non essere un bus ma solo un trasmettitore e ricevitore di segnale, va quindi realizzato un BUS a seconda delle necessità progettuali. Quindi dovremmo scriverci noi il protocollo di comunicazione da utilizzare.

Questo sistema di comunicazione è attualmente quello maggiormente utilizzato sia nei sistemi domotici che di allarme.


  1. Di cosa abbiamo bisogno?
Per realizzare il nostro progetto abbiamo bisogno:


  • ELENCO MATERIALE PER TUTORIAL CON ARDUINO
  1. n.2 Schede Arduino 2009/UNO
  2. n.2 Max485 o ADM485
  3. n.2 NE555
  4. n.2 Diodi 1N4001
  5. n.2 Resistenze da 3.9 Kohm
  6. n.4 Condensatori da 10 nF
  7. n.2 Resistenze da 100 ohm
  8. n°4 Relè a 5Vdc di tensione bobina tipo OMRON G5LA-14 (acquistabile qui)
  9. n°4 Pulsanti tattili switch (acquistabili qui)
  10. n°4 Resistenze da 1.5K
  11. n°8 Resistenze da 1K
  12. n°4 Transistor BC337
  13. n°4 Diodi 1N4148
  14. n.1 Breadboard bella capiente
  15. Vari cavetti per bradboard
  16. n.2 Cavi USB


  • ELENCO MATERIALE PER TUTORIAL CON ETA BETA EDI
  1. n.2 Schede ETA BETA EDI
  2. n.2 Cavi Usb
  3. n.2 cavetti per collegare le due schede


Il chip utilizzato per realizzare la comunicazione RS485 è il chip ADM1485 (max 485), un ricetrasmettitore differenziale conforme con lo Standard RS-485 , questo chip contiene un driver di linea differenziale ed un ricevitore di linea differenziale che possono essere attivati in modo indipendente.
Per gestire la comunicazione multimaster andremo ad aggiungere un NE555 in configurazione monostabile che commuta l’ ADM1485 dalla trasmissione alla ricezione e viceversa.
Dalla seriale viene “sentito” il bit di start (fronte di discesa) e l’uscita del NE555 commuta l’ADM in invio, e viceversa, cioè quando arriva il bit di stop l’ADM viene commutato in ricezione. Grazie a questo componente le schede possono commutare automaticamente il loro stato da MASTER a SLAVE e viceversa, ciò evita la gestione complessa della commutazione via software.


Questa configurazione garantisce il funzionamento anche in caso di guasto di uno dei moduli presenti nel sistema.


  1. Schemi Elettrici
Ecco gli schemi realizzati con FRITZING per Arduino ed ETA BETA EDI:

Con EDi posizionare Dip switch DS2 , 7 e 8 in ON per abilitare la RS485 al termine della programmazione.



Schema elettrico per Arduino parte BUS:




Schema Fritzing Relè + Switch Button per Arduino:






  1. Sketch uguale sia per Arduino 2009 sia per ETA BETA EDI
Gli Sketch caricati su entrambe le schede sono uguali, l’unica differenza è l’indirizzo della scheda (vedi parte evidenziata in giallo).

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const int buttonPin1 = 5;    // the number of the pushbutton pin
const int buttonPin2 = 6;    // the number of the pushbutton pin
int ledPin = 13;      // the number of the LED pin
int rel1 = 7; 
int rel2 = 8;
boolean i = false;
boolean j = false;

int buttonState1;             // the current reading from the input pin
int buttonState2;             // the current reading from the input pin
int relState1 = LOW;
int relState2 = LOW;
int lastButtonState1 = LOW;   // the previous reading from the input pin
int lastButtonState2 = LOW;   // the previous reading from the input pin
long lastDebounceTime1 = 0;  // the last time the output pin was toggled
long lastDebounceTime2 = 0;  // the last time the output pin was toggled

long debounceDelay1 = 50;    // the debounce time; increase if the output flickers
long debounceDelay2 = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(rel1, OUTPUT);
  pinMode(rel2, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  
  int reading1 = digitalRead(buttonPin1);      // LEGGERE VALORE BUTTON1
  int reading2 = digitalRead(buttonPin2);      // LEGGERE VALORE BUTTON2
// PRESSIONE DEL BUTTON 1
  if (reading1 != lastButtonState1) {
    // reset the debouncing timer
    lastDebounceTime1 = millis();
  }

  if ((millis() - lastDebounceTime1) > debounceDelay1) {
    if (reading1 != buttonState1) {
      buttonState1 = reading1;
      if (buttonState1 == HIGH) {
        i= !i;                // MODIFICA VALORE VARIABILE
               if (i == true){
    String stringa1 = "";
    stringa1 += ("b");  // COMANDO PER ATTIVARE VOID SU SCHEDA DESTINATARIO
    stringa1 += ("2");  //INDIRIZZO SCHEDA DESTINATARIO
    stringa1 += ("1");  //ATTACCA RELE' 1 SCHEDA 2
    Serial.println(stringa1);
      }
               if (i == false){
    String stringa1 = "";
    stringa1 += ("b");  // COMANDO PER ATTIVARE VOID SU SCHEDA DESTINATARIO
    stringa1 += ("2");  //INDIRIZZO SCHEDA DESTINATARIO
    stringa1 += ("0");  //STACCA RELE' 1 SCHEDA 2
    Serial.println(stringa1);
       }        
      }
    }
  }
  lastButtonState1 = reading1;
  
 // PRESSIONE DEL BUTTON 2
 if (reading2 != lastButtonState2) {
    // reset the debouncing timer
    lastDebounceTime2 = millis();
  }

  if ((millis() - lastDebounceTime2) > debounceDelay2) {
    if (reading2 != buttonState2) {
      buttonState2 = reading2;
       if (buttonState2 == HIGH) {
        j= !j;                  // MODIFICA VALORE VARIABILE
          if (j == true){
String stringa2 = "";
 stringa2 += ("b");  // COMANDO PER ATTIVARE VOID SU SCHEDA DESTINATARIO
 stringa2 += ("2");  //INDIRIZZO SCHEDA DESTINATARIO
 stringa2 += ("3");  //ATTACCA RELE' 2 SCHEDA 2
  Serial.println(stringa2);
      }
      if (j == false){
String stringa2 = "";
 stringa2 += ("b");  // COMANDO PER ATTIVARE VOID SU SCHEDA DESTINATARIO
 stringa2 += ("2");  //INDIRIZZO SCHEDA DESTINATARIO
 stringa2 += ("2");  //STACCA RELE' 2 SCHEDA 2
  Serial.println(stringa2);
       }
      }
    }
  }
  lastButtonState2 = reading2; 
 
if (Serial.available() > 0 ) {      //LETTURA DA SERIALE
  int ser;
  ser=Serial.read(); 
   switch (ser) {
     case 'b':   
     comando();  
     break;
}
}  
  
}        //FINE LOOP

void comando(){
delay(50);   // questo delay è indispensabile!!
 if (Serial.available()) {     
      int a = Serial.read()-48;
      int c = Serial.read()-48;                       //viene sottratto 48 per rientrare nel range dei caratteri numerici ASCII (0=49,1=50....9=58)
digitalWrite (13, HIGH);     
if (a==2){
    if(c == 0){
digitalWrite (7, LOW);     
   }   
     if(c == 1){
digitalWrite (7, HIGH);     
   } 
      if(c == 2){
digitalWrite (8, HIGH);     
   }
      if(c == 3){
digitalWrite (8, LOW);     
   }   
  }
 }
}   //FINE VOID COMANDO



N.B.Quando viene caricato il firmware su Arduino o sulla scheda ETA BETA EDI bisogna staccare il max485.




  1. Spiegazione dello Skecth uguale per entrambe le schede
Parte 1 - Dichiarazioni Variabili:
Come da schema sia per Arduino sia per ETA BETA EDI abbiamo i button 1 e 2 collegati rispettivamente ai pin 5 e 6 ed i 2 relè ai pin 7 e 8.
Inizializziamo le due variabili booleane “i” e “j” (assumono 2 valori: vero e falso) come FALSE, e lo stato iniziale dei Button e dei relè come LOW.
Introduciamo anche il tempo di debounce per la funzione anti-rimbalzo indispensabile per il corretto funzionamento dei BUTTON.


Parte 2 - Void Setup
Impostiamo i button come INPUT ed i relè come OUTPUT ed ovviamente inizializziamo la seriale a 9600.


Parte 3 - Void LOOP
Con le dichiarazioni:   
int reading1 = digitalRead(buttonPin1)   
int reading2 = digitalRead(buttonPin2)
andiamo a leggere i valori in ingresso dati dai pulsanti.
Quando premiamo il button 1  e lo portiamo in HIGH ed è trascorso il tempo impostato viene  cambiato il valore della variabile booleana “i” e sulla seriale andremo a scrivere la stringa: b21 oppure b20 a seconda se la booleana è vera o è falsa.
La prima lettera della stringa attiva il VOID comando, il primo numero è l’INDIRIZZO del modulo destinatario ed il terzo numero fa eseguire una determinata operazione, nel nostro caso:
0 - Stacca il primo relè
1- Attacca il primo relè
2- Stacca il secondo relè
3- Attacca il secondo relè
Lo stesso accade quando premiamo il button 2.
Nella seconda parte del LOOP andiamo ad intercettare i valori letti dalla seriale:
Serial.available
La prima lettera letta sulla seriale è la b che attiva il void comando creato nello switch case.


Parte 4 - Void COMANDO
Questo VOID si attiva quando IL DESTINATARIO legge sulla seriale la lettera b.
int a = Serial.read()-48;
int b = Serial.read()-48;                      
Queste due dichiarazioni permettono di identificare i numeri successivi alla lettera b necessari per capire le operazioni da fare
N.B. viene sottratto 48 per rientrare nel range dei caratteri numerici ASCII (0=49, 1=50 ...)
Se il primo numero letto sulla seriale è uguale all’indirizzo della scheda va avanti.

Buon lavoro!
Christian Acqua
Massimo Pinto



1 commento:

  1. perche' il segnale per ricevere o trasmettere e' gestito da un timer e non da arduino ?

    RispondiElimina