Vai al contenuto
PLC Forum


Chiarimento su comunicazione RS485 (MAX485)


Fabri82

Messaggi consigliati

Ciao a tutti,

vi chiedo un aiuto per capire il funzionamento via seriale RS485 tra un Arduino UNO e un NANO.

Non ho mai avuto l'esigenza di utilizzare questo tipo di comunicazione ma mi sto cimentando per eventualmente includerlo in un piccolo progetto domotico.

Le due schede (Arduino UNO master --> Arduino NANO slave) sono entrambe collegate ai rispettivi moduli MAX485.

I collegamenti sono semplicissimi, ricontrollati e corretti.

Pin 10 e 11 = RO e DI

Pin 3 = RE

I due canali di trasmissione che permettono lo scambio dati tra i due MAX485 sono collegati A con A e B con B.

Leggendo qualche manuale e seguendo qualche tutorial tutto è perfetto.

In particolare ho provato un piccolo sketch di esempio dove il Master aspetta un carattere dal suo Serial Monitor lo invia allo Slave che lo riceve e lo ritrasmette al master per essere visualizzato sul Serial monitor (del Master).

 

Questi è lo Schetch del Master:

 

#include <SoftwareSerial.h>//master
SoftwareSerial rs485S(10,11);

void setup() {
  Serial.begin (9600);
  pinMode (3, OUTPUT);
  rs485S.begin(9600);
  digitalWrite (3, LOW);
}

void loop() {
  if (Serial.available()){
    int data = Serial.read();
    digitalWrite (3, HIGH); 
    rs485S.write (data);
    digitalWrite (3, LOW);
  }
  if (rs485S.available()){
    int data = rs485S.read();
    Serial.write(data);
  }
}

 

Questo dello Slave:

 

 

#include <SoftwareSerial.h> //slave
SoftwareSerial rs485S(10,11);

void setup() {
  Serial.begin (9600);
  pinMode (3, OUTPUT);
  digitalWrite (3, LOW);
  rs485S.begin(9600);
}


void loop() {
  if  (rs485S.available()){
    int data=rs485S.read();
    digitalWrite(3,HIGH);
      rs485S.write(data);
    digitalWrite(3,LOW);
  }
}

 

Dove sto sbagliando????

 

Modificato: da Fabri82
Link al commento
Condividi su altri siti


Cavolo scusate ma ho visto solo ora che il copia incolla dello sketch mi ha generato degli spazi enormi e la formattazione del testo è diciamo...."DILATATA".

Perdonatemi, capisco di essere un asino su vari fronti 😅.

Provo a sistemarla

Link al commento
Condividi su altri siti

33 minuti fa, Fabri82 ha scritto:

Dove sto sbagliando????

 

Però dovresti dire che problema riscontri.

In questi giorni sto mettendo a punto un'applicazione tra due ESP8266 che si scambiano dati in seriale facendo uso delle stesse librerie.

 Puoi fare anche un test sui singoli moduli chiudendo in corto Tx e Rx. Leggi il dato sulla seriale del monitor, lo ritrasmetti alla seriale RS485 che lo legge e lo scrive sul monitor.

 

Così, ad un'analisi veloce non mi sembra ci siano errori. Specifca quale è il problema che riscontri.

Link al commento
Condividi su altri siti

28 minuti fa, Livio Orsini ha scritto:

 

Però dovresti dire che problema riscontri.

In questi giorni sto mettendo a punto un'applicazione tra due ESP8266 che si scambiano dati in seriale facendo uso delle stesse librerie.

 Puoi fare anche un test sui singoli moduli chiudendo in corto Tx e Rx. Leggi il dato sulla seriale del monitor, lo ritrasmetti alla seriale RS485 che lo legge e lo scrive sul monitor.

 

Così, ad un'analisi veloce non mi sembra ci siano errori. Specifca quale è il problema che riscontri.

 

Ciao Livio,

scusa in effetti potevo essere più chiaro 😄. In pratica, se ho capito bene, con lo sketch che ho esposto dovrei scrivere qualcosa sul Serial Monitor del Master e aspettarmi che venga stampato sempre sul Serial monitor del Master dopo averlo ricevuto dallo slave. La stampa è di fatto inserita dentro l'"if". Però in pratica non succede nulla...io digito un qualsiasi carattere e do l'invio sulla tastiera ma il risultato è nullo (sul serial monitor non mi riporta nulla).

Link al commento
Condividi su altri siti

Il pin 3 dello slave dovrebbe andare alto ad ogni carattere ricevuto, per poi riabbassarsi akka ritrassmisione.

 

1 ora fa, Fabri82 ha scritto:
void loop() {
  if  (rs485S.available()){
    int data=rs485S.read();
    digitalWrite(3,HIGH);
      rs485S.write(data);
    digitalWrite(3,LOW);
  }
}

 inserisci un delay di 500ms prima di RS485.write(data) ed un altro subito dopo; così puoi vedere se riceve il carattere e lo ritrasmette.

Abbassa anche il boud rate della seriale RS485, quella libreria è lenta, prova inizialmente con 2400, poi sali a 4800; il 9600 non lo proverei nemmeno.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

2 ore fa, Fabri82 ha scritto:

I due canali di trasmissione che permettono lo scambio dati tra i due MAX485 sono collegati A con A e B con B.

E i 2 GND delle schede sono collegati insieme?

 

Ciao, Ale.

Link al commento
Condividi su altri siti

Il 30/11/2024 alle 18:02 , ilguargua ha scritto:

E i 2 GND delle schede sono collegati insieme?

 

Ciao, Ale.

 

Ciao Ale,

i due GND e i due +5V sono separati in quanto ho provato a collegare due pc rispettivamente su sull'UNO e sul NANO e alimentando il tutto via USB separate.

Nessun segno di vita...

 

 

Link al commento
Condividi su altri siti

Il 30/11/2024 alle 16:43 , Livio Orsini ha scritto:

Il pin 3 dello slave dovrebbe andare alto ad ogni carattere ricevuto, per poi riabbassarsi akka ritrassmisione.

 

 inserisci un delay di 500ms prima di RS485.write(data) ed un altro subito dopo; così puoi vedere se riceve il carattere e lo ritrasmette.

Abbassa anche il boud rate della seriale RS485, quella libreria è lenta, prova inizialmente con 2400, poi sali a 4800; il 9600 non lo proverei nemmeno.

 

Ciao Livio,

ho provato a fare alcune prove come hai suggerito. Niente da fare...

Ho provato con un delay prima e dopo la srittura come mi hai indicato e anche diminuendo il boud rate della seriale RS485. Nessun segnale.

Ho dato un occhiata alla libreria per capire se avevo scritto tutto correttamente ed è esattamente come viene suggerito. Cablaggio e sketch sono corretti.

La logica di funzionamento dice che il pin3 viene alzato solamente quanto si trasmette e abbassato subito dopo in modo da rimettersi in ascolto.

Ho provato anche a cortocircuitare i canali A e B sul modulo MAX485 in modo da trasmettere e ricevere sullo stesso Arduino ma senza risultato...

Anche con le resistenze di terminazione da 120 Ohm tra A e B di entrambi i moduli, nulla di nulla.

Io credo a questo punto che siano proprio queste schedine che non funzionano...

Premetto che in questo momento la mia è solo curiosità ed ho acquistato per una miseria 5 moduletti a 8€ (cinesate)...però mi piacerebbe sviluppare un'idea interessante per casa e proverei ad acquistare un MAX485 originale o quantomeno di qualità per verificare questo fatto strano. Sai dove si possono acquistare?

 

Link al commento
Condividi su altri siti

1 minuto fa, Fabri82 ha scritto:

Anche con le resistenze di terminazione da 120 Ohm tra A e B di entrambi i moduli, nulla di nulla.

Beh, queste sono obbligatorie e le davo quasi per scontate.

 

2 minuti fa, Fabri82 ha scritto:

Ho provato anche a cortocircuitare i canali A e B sul modulo MAX485 in modo da trasmettere e ricevere sullo stesso Arduino ma senza risultato...

Ed anche questo è garantito che non possa funzionare, casomai, come suggeriva Livio, devi cortocircuitare i pin rx-tx della seriale di appoggio sull'MCU per vedere se il programma è corretto.

Pubblica un link dei moduli che hai usato, così possiamo dare un'occhiata al prodotto.

 

E comunque io proverei anche a collegare i 2 GND, non mi sembra una prova impegnativa.

Link al commento
Condividi su altri siti

32 minuti fa, ilguargua ha scritto:

Pubblica un link dei moduli che hai usato, così possiamo dare un'occhiata al prodotto.

Trattasi di questo:

https://www.amazon.it/dp/B07DK4QG6H?ref=ppx_yo2ov_dt_b_fed_asin_title

 

32 minuti fa, ilguargua ha scritto:

E comunque io proverei anche a collegare i 2 GND, non mi sembra una prova impegnativa.

Fatto ma ancora tutto "dorme".

33 minuti fa, ilguargua ha scritto:

come suggeriva Livio, devi cortocircuitare i pin rx-tx della seriale di appoggio sull'MCU per vedere se il programma è corretto.

Idem come sopra...😐

Link al commento
Condividi su altri siti

Livio Orsini
9 ore fa, Fabri82 ha scritto:

Ciao Livio,

ho provato a fare alcune prove come hai suggerito. Niente da fare...

 

Quando le cose non funzionano bisogna fare resete ripartire, così da far emergere eventuali errori.

Per prima cosa collega i due arduino senza interfaccia RS485, ovvero collega il pin Rx di uno con il pint Tx del nanoe viceversa.

Prova la comunicazione così: ardu1 legge un carattere da tastiera del PC, lo trsmette al nano che lo stampa sul monitor PC e lo ritrasmette a arduu1che lo stampa sul modulo del PC.

Così deve funzionare per forza, se non funziona o hai usato degli I/O non adatti ( ma è quasi impossibile) oppure c'è un pin guasto.

Una volta che così funziona, vediamo perchè non funziona con la RS485, anche se ho già un mezza idea del possibile errore, ma devo studiarmi un attimo il modulo che hai usato.

 

Tanto per rassicurarti, se ce ne fosse bisogno, è dal 2021 che ho una piccola rete domotica di tipo LoRa, con cui scambio i dati tra un arduino1 e 2 arduino nano, uso la stessa libreria che hai usato tu, solo che invece del MAX485, ho un modem LoRa, per trasmettere e ricevere senza supporto fisico.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

5 ore fa, Livio Orsini ha scritto:

 

Quando le cose non funzionano bisogna fare resete ripartire, così da far emergere eventuali errori.

Per prima cosa collega i due arduino senza interfaccia RS485, ovvero collega il pin Rx di uno con il pint Tx del nanoe viceversa.

Prova la comunicazione così: ardu1 legge un carattere da tastiera del PC, lo trsmette al nano che lo stampa sul monitor PC e lo ritrasmette a arduu1che lo stampa sul modulo del PC.

Così deve funzionare per forza, se non funziona o hai usato degli I/O non adatti ( ma è quasi impossibile) oppure c'è un pin guasto.

Una volta che così funziona, vediamo perchè non funziona con la RS485, anche se ho già un mezza idea del possibile errore, ma devo studiarmi un attimo il modulo che hai usato.

 

Tanto per rassicurarti, se ce ne fosse bisogno, è dal 2021 che ho una piccola rete domotica di tipo LoRa, con cui scambio i dati tra un arduino1 e 2 arduino nano, uso la stessa libreria che hai usato tu, solo che invece del MAX485, ho un modem LoRa, per trasmettere e ricevere senza supporto fisico.

Ciao Livio,

si in effetti ho ricreato lo Sketch da zero (master e slave) per evitare che qualcosa mi fosse sfuggito ma di fatto sono 2 righe di codice e seguendo la logica di funzionamento passo passo di quello che la libreria comanda di fare, sembra che non ne voglia sapere di funzionare.

Questa sera avevo in mente anch'io di provare utilizzando i pin di trasmissione e ricezione 0 e 1 e togliendo di fatto la scheda MAX485. Mi aspetto che in questa condizione funzioni per forza.

Comunque avevo provato anche a cambiare i pin sia TX/RX che il Pin3 che comanda la trasmissione e ricezione.

 

Una domanda: magari ho capito male, ma la Serial interna all'Arduino (sia UNO che NANO) è vincolata dai pin 0 e 1, giusto? Intendo dire che se collego questi due pin per mettere in comunicazione i due dispositivi, l'USB non mi permette di vedere cosa accade tramite Serial Monitor. Corretto? Ribadisco la mia ignoranza in merito...mi ci sto approciando in questo momento.

 

Vi aggiorno e come sempre grazie infinite per la pazienza e il supporto 🙂

Link al commento
Condividi su altri siti

Livio Orsini

Si se usi la seriale nativa non puoi usare contemporaneamente monitor e seriale.

 

Link al commento
Condividi su altri siti

Livio Orsini
2 ore fa, Fabri82 ha scritto:

ho ricreato lo Sketch da zero (master e slave)

 

Non basta ti ho scritto di togliere l'intertaccia TTL-RS485 e fare la connessione diretta, così verifichi solo il Sw eliminando eventuali problemi Hw.

Sto usando, in questi giorni una circuito simile, anche se uso ESP8266 ed ESP32 in luogo di arduino. Uso le medesime librerie, uso due PC, il collegamento tra i due micro ' con 2 fili Rz <--> Tx più gnd.

 

Fai uno schemino di comne hai collegato i 2 RS485 tra loro e con i due arduino, e mettilo nel messaggio.

 

Se usi le seriali Rx0 e Tx0, puoi anche farlo a patto di caricare il programma e poi togliere il cavo dalla porta USB, altrimenti la seriale non va.

Link al commento
Condividi su altri siti

Il 2/12/2024 alle 14:53 , Livio Orsini ha scritto:

 

Non basta ti ho scritto di togliere l'intertaccia TTL-RS485 e fare la connessione diretta, così verifichi solo il Sw eliminando eventuali problemi Hw.

Sto usando, in questi giorni una circuito simile, anche se uso ESP8266 ed ESP32 in luogo di arduino. Uso le medesime librerie, uso due PC, il collegamento tra i due micro ' con 2 fili Rz <--> Tx più gnd.

 

Fai uno schemino di comne hai collegato i 2 RS485 tra loro e con i due arduino, e mettilo nel messaggio.

 

Se usi le seriali Rx0 e Tx0, puoi anche farlo a patto di caricare il programma e poi togliere il cavo dalla porta USB, altrimenti la seriale non va.

 

Ciao Livio,

ho fatto alcune prove. Scollegando i due MAX485 e utilizzando la SoftwareSerial con due pin (10,11) sui due Arduino funziona.

Come mi ha suggerito Ale ho collegato le due GND dei due Arduini insieme altrimenti i caratteri ricevuti in risposta sul Serial Monitor mi apparivano completamente diversi (Esempio digito la "P" e mi tornava una "X" o un "°" o altri simboli). Il secondo Arduino l'ho alimentato esternamente.

Questo lo schema:

image.thumb.png.5db451b6b0f4e9dc185cc0943c93f35a.png

 

Questo il codice:

 

#include <SoftwareSerial.h>;  // Master
#define RX 10
#define TX 11
SoftwareSerial port(RX,TX);

void setup() {
 Serial.begin (9600);
 port.begin (9600);
 pinMode (RX, INPUT);
 pinMode (TX, OUTPUT);
}

void loop() {
  if (Serial.available ()){
    char a = Serial.read ();
    delay (10);
    port.write (a);
    delay(10);
  }
  if (port.available()){
    char b = port.read();
    delay (10);
    Serial.println (b);
  }
}
#include <SoftwareSerial.h>; // slave
#define RX 10
#define TX 11
SoftwareSerial port(RX,TX);

void setup() {
 Serial.begin (9600);
 port.begin (9600);
 pinMode (RX, INPUT);
 pinMode (TX, OUTPUT);
}

void loop() {
  if (port.available ()){
    char a = port.read ();
    delay (50);
    port.write (a);
    delay(10);
  }
}

 

Link al commento
Condividi su altri siti

Sei incece collego i due Max485 tutto tace...

Questo lo schema:

Schermata2024-12-03alle22_31_18.thumb.png.f29f2db0b7c834725cb62b71cc63b46e.png

 

Questo lo Sketch:

#include <SoftwareSerial.h>; // master
#define ABILITA 3
#define RX 10
#define TX 11
SoftwareSerial port(RX,TX);

void setup() {
 Serial.begin (9600);
 port.begin (2400);
 pinMode (RX, INPUT);
 pinMode (TX, OUTPUT);
 pinMode (ABILITA, OUTPUT);
 digitalWrite (ABILITA, LOW);

}

void loop() {
  if (Serial.available ()){
    char a = Serial.read ();
    digitalWrite (ABILITA, HIGH);
    delay (50);
    port.write (a);
    delay(10);
    digitalWrite (ABILITA, LOW);
  }
  if (port.available()){
    delay (10);
    char b = port.read();
    delay (10);
    Serial.println (b);
  }
}

 

#include <SoftwareSerial.h>; // slave
#define ABILITA 3
#define RX 10
#define TX 11
SoftwareSerial port(RX,TX);

void setup() {
 Serial.begin (9600);
 port.begin (2400);
 pinMode (RX, INPUT);
 pinMode (TX, OUTPUT);
 pinMode (ABILITA, OUTPUT);
 digitalWrite (ABILITA, LOW);
}

void loop() {
  if (port.available ()){
    char a = port.read ();
    digitalWrite (ABILITA, HIGH);
    delay (50);
    port.write (a);
    delay(10);
    digitalWrite (ABILITA, LOW);
  }
}

 

Link al commento
Condividi su altri siti

Livio Orsini
8 ore fa, Fabri82 ha scritto:

Questo lo schema:

 

Lo schema senza numerare i piedini dei moduli e senza indicare marca e modello dei moduli, serve a poco, anzi non serve.

Io credo che il problema risieda nei collegamenti dei moduli e nei comandi che dai ai moduli.

 

Se colleghi i due arduino direttamente, fai una trasmissione full duplex, ovvero puoi trasmettere e ricevere in contemporanea.

Se usi i moduli RS485, la trasmissione diventa half duplex, quindi bisogna porre attenzione sia ai comandi che ai tempi.

Link al commento
Condividi su altri siti

1 ora fa, Livio Orsini ha scritto:

 

Lo schema senza numerare i piedini dei moduli e senza indicare marca e modello dei moduli, serve a poco, anzi non serve.

Osservazione più che giusta ...

Diciamo che guardando il disegno, senza avere il pinout, sembra che i moduli MAX485 siano collegati TX-TX e RX-RX e questo potrebbe essere un problema ...

Link al commento
Condividi su altri siti

Prova ad installare questa libreria, lo puoi fare direttamente dall'IDE di Arduino, compila e carica sulle schede i 2 esempi che usano la software serial, e sopratutto collega tutti e 4 i pin dell'interfaccia verso l'MCU, ovviamente adeguando eventualmente i pin usati nel codice, e collega anche i 2 GND delle schede.

Premetto che non sono un esperto di RS485 (non l'ho mai usato), ma nel codice della libreria vedo che entrambi i pin di controllo (RE e DE) devono essere usati per trasmettere o ricevere, in particolare:

void MAX_RS485::setModeToReceiver()
{
    flush();
    delay(rxDelay);
    digitalWrite(rePin, LOW);
    digitalWrite(dePin, LOW);
}


void MAX_RS485::setModeToTransmitter()
{
    delay(txDelay);
    digitalWrite(rePin, HIGH);
    digitalWrite(dePin, HIGH);
}

Considera che i moduli che stai usando hanno le resistenze di pull-up sui pin di controllo:

411PTilsAQL._AC_.jpg

quindi se non li colleghi entrambi non potranno mai essere entrambi bassi, situazione necessaria per ricevere.

 

Ciao, Ale.

Link al commento
Condividi su altri siti

Ciao a tutti,

ieri sera sono riuscito a lavorarci seguendo i vostri consigli che ogni volta mi illuminano la via.

Premetto che da idiota quale sono non avevo capito che il cablaggio del MAX485 ha bisogno di ponticellare i due pin RE/DE che prevedono di ricevere il comando di trasmissione o ricezione (HIGH oppure LOW). Come dicevi tu Ale.

Fatto questo il siestema funziona.

Se posso vi chiedo un'ulteriore cosa. Ho provato a scambiare valori di temperatura tra il Nano sul quale è cablato un DS18B20 e l'UNO che visualiza sul Serial Monitor il dato ogni 10sec.

Funziona tutto ma i valori di temperatura non tengono conto dei decimali. Intendo che quando la lettura visualizzata sul Serial Monitor del NANO mi indica 20.85, per esempio, una volta trasmesso il valore all'UNO mi stampa 20.00.

Entrambe le variabili sono float sia da chi trasmette che da chi riceve.

Devo utilizzare un'altro tipo di variabile e poi convertirla?

Grazie ancora a tutti!

 

Link al commento
Condividi su altri siti

1 ora fa, Fabri82 ha scritto:

remetto che da idiota quale sono non avevo capito che il cablaggio del MAX485 ha bisogno di ponticellare i due pin RE/DE che prevedono di ricevere il comando di trasmissione o ricezione (HIGH oppure LOW).

 

 

Il 4/12/2024 alle 07:36 , Livio Orsini ha scritto:

Lo schema senza numerare i piedini dei moduli e senza indicare marca e modello dei moduli, serve a poco, anzi non serve.

Io credo che il problema risieda nei collegamenti dei moduli e nei comandi che dai ai moduli.

 

E proprio per questo motivo che che ti avevo richiesto lo schema con nomi dei moduli e numero di piedini, perchè ero sicuro al 99% che c'era un problema di collegamenti.

 

1 ora fa, Fabri82 ha scritto:

Funziona tutto ma i valori di temperatura non tengono conto dei decimali. Intendo che quando la lettura visualizzata sul Serial Monitor del NANO mi indica 20.85, per esempio, una volta trasmesso il valore all'UNO mi stampa 20.00.

 

 

Io, per trasmettere e ricevere 2 variabili float uso la converso con la funzione "dtostrf).

Cerca e studia la spiegazione di cosa fa e come si usa questa funzione, la trovi nel sito ufficiale di arduino. Volutamente non aggiungo altro proprio per costringerti a consultare la documentazione ufficiale.

 

....

    // read humidity
    float humi  = dht_sensor.readHumidity();
    // read temperature in Celsius
    float temperature_C = dht_sensor.readTemperature();
    // read temperature in Fahrenheit
    float temperature_F = dht_sensor.readTemperature(true);
    // Create msg, and send using UART over Rx/Tx (D7/D8)
.................
       dtostrf(humi, 5, 2, buffr);
       buffr[6] = 0x0C;
       Ser2.print("Umidità = ");
       Ser2.write(buffr);
       Ser2.println("");
       Serial.write(buffr);
       Serial.println("");
       for (ii = 0; ii <= 6; ii++) 
         {
           buffr[ii] = 0;  
         }
 .....

 

Link al commento
Condividi su altri siti

26 minuti fa, Livio Orsini ha scritto:

Volutamente non aggiungo altro proprio per costringerti a consultare la documentazione ufficiale.

🤣🤣🤣 Grazie mille Livio!!! Non conosco questa funzione ma vedo di studiarmela!!

Quindi nella mia condizione attuale è corretto che i dati che ricevo in risposta dal NANO mi passino senza considerare i decimali...?

 

Link al commento
Condividi su altri siti

23 minuti fa, Fabri82 ha scritto:

Quindi nella mia condizione attuale è corretto che i dati che ricevo in risposta dal NANO mi passino senza considerare i decimali...?

 

 

Certo.  E una questione di formattazione.

La funzione che ti ho indicato usa un vettore (array) di 6 elementi: 2 caratteri per decine e unoità, uno per il punto decimale, 2 caratteri per i decimali., l'ultimo carattere è il codice del ritorno a capo e nuova linea.

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...