Pages: 1 ... 3 4 [5] 6   Go Down
Author Topic: 4 Arduino Master Slave in RS485  (Read 12254 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 2
Posts: 105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
eccomi...io ci sono...purtroppo ho avuto un po di impegni e ho trascurato questo topic...non mi ero nemmeno accorto che lo avevate "riesumato"...io ancora non ho sviluppato nulla...

Per Peppe91 ...Purtroppo anche io ho poco tempo da dedicare a questo progetto...
Per Leo72...si può spostare il post magari nella sezione Megatopic o altra sezione tipo "Progetti in sviluppo" e il progetto sarebbe chiaramente  "Realizzazione Protocollo rs485" ??
Caro Leo lo scopo ripeto dovrebbe essere quello di attirare l'attenzione di più utenti perchè il titolo di questo topic
( "4 Arduino Master Slave in RS485" )è generico e magari viene ignorato da molti...

Domanda tecnica sull'argomento:ma per mandare i byte di comando tra Arduino Master e Arduini Slave oltre al metodo "serial.Write byte(x,x,x,x,x,x)" esiste un'altro modo più semplice e più comprensibile oppure devo soffrire a inventare i numeri a caso ??

La mia domanda sicuramente a molti sembrerà cretina ma senza sketch di esempio di riferimento e di prova chiaramente brancolo nel buio...buon lavoro a tutti e guarda caso oggi mi troverò a lavorare con dei componenti elettronici che colloquiano con una seriale Rs485...sistemi d'allarme...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22935
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Per Peppe91 ...Purtroppo anche io ho poco tempo da dedicare a questo progetto...
Per Leo72...si può spostare il post magari nella sezione Megatopic o altra sezione tipo "Progetti in sviluppo" e il progetto sarebbe chiaramente  "Realizzazione Protocollo rs485" ??
Caro Leo lo scopo ripeto dovrebbe essere quello di attirare l'attenzione di più utenti perchè il titolo di questo topic
( "4 Arduino Master Slave in RS485" )è generico e magari viene ignorato da molti...
In Megatopic ci vanno i progetti completi. Qui siamo per ora al livello di discussione per la stesura di un protocollo, non c'è nulla di pronto.

Quote
Domanda tecnica sull'argomento:ma per mandare i byte di comando tra Arduino Master e Arduini Slave oltre al metodo "serial.Write byte(x,x,x,x,x,x)" esiste un'altro modo più semplice e più comprensibile oppure devo soffrire a inventare i numeri a caso ??

La mia domanda sicuramente a molti sembrerà cretina ma senza sketch di esempio di riferimento e di prova chiaramente brancolo nel buio...buon lavoro a tutti e guarda caso oggi mi troverò a lavorare con dei componenti elettronici che colloquiano con una seriale Rs485...sistemi d'allarme...
Prendi il codice del ModBus e studialo, non c'è nulla di astruso dietro. Si tratta di spedire dei byte e dargli un significato.
Quando tu leggi un sensore, i dati che ricevi hanno un significato per te, giusto? Eppure, sei tu a darglielo, di per sé quelli sono solo numeri.  smiley-wink
Logged


Battipaglia (SA)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 72
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Se lo slave sta ricevendo un pacchetto, dati non deve interpretare i byte contenuti in esso. Lui deve solo riconoscere:
1) il byte di start, ed iniziare a leggere;

E' qui che nasce il mio problema, ma senz'altro sono stato poco chiaro. Provo a spiegarmi con un esempio. Il master invia il seguente pacchetto secondo il protocollo che proponevo: 255, 0, 3, 5, 4, 2, 255, 6, 2, X

255 = Start
0 = IDMittente, il master ha ID = 0
3 = IDDestinatario, il master vuole interrogare lo slave con ID = 3
5 = IDComando, il master sta inviando il comando ID=5
4 = LunghezzaPacchetto, di seguito ci sono 4 bytes che, per esempio, rappresentano un long
2
255
6
2
X = Checksum, calcolato per esempio con uno XOR dei 9 bytes (escluso il checksum) che compongono il pacchetto

Ora supponiamo che uno slave si avvii (per esempio venga alimentato...) durante la trasmissione del pacchetto e quindi riceva il seguente frammento: 5, 4, 2, 255, 6, 2, X (ha perso i primi 3 bytes...)

Ignorerà i bytes 5, 4, 2 perchè aspetta un 255 di start, quindi interpreterà bytes seguenti come:

255 = Start
6 = IDMittente
2 = IDDestinatario
X = IDComando

e qui continuerà ad attendere in attesa dei rimanenti bytes del pacchetto che non arriveranno mai. Tuttavia interverrà il timeout ed i bytes verranno scartati con codice di errore = TIMEOUT.

In effetti mi pare che funzioni, volevo soltanto confrontarmi anche con voi sulla correttezza della soluzione, nel caso mi sfugga qualcosa.

Quote
2) il byte contenente il numero di byte ulteriori che deve ricevere, e questo valore non può essere confuso con altri perché è in una posizione ben precisa, e poi i byte di stop e di checksum, che arrivano in determinate posizioni (dipendenti da quanti byte sono stati trasmessi).

Non avevo previsto un byte di stop... ti sembra necessario?

Quote
Quindi è una catena da verifica con timeout in ogni operazione critica, come hai capito anche tu.

Qui non so se basta il timeout, come dicevo nel post precedente, in caso di ritardo nella risposta dello slave, potrebbe verificarsi una collisione perchè il master non ricevendo risposta entro il timeout, pensa che lo slave sia down ed inizia una nuova trasmissione, magari verso un altro slave. Contemporaneamente lo slave precedente trasmette la sua risposta generando la collisione che rileveremo attraverso il controllo del checksum. Dobbiamo però capire come fanno tutti gli oggetti sul bus (il master e gli n slaves) a ritornare in una condizione stabile.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22935
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

1) Secondo me, se lo slave si aggancia alla trasmissione quando questa è in corso la deve semplicemente ignorare non appena si accorge che il primo byte che riceve non è quello di start. Sempre secondo me, deve scaricare tutti i byte che riceve perché altrimenti non può capire se ad esempio un byte $FF ricevuto a metà di un messaggio fa parte del pacchetto di dati oppure se è il byte di start. Sarà magari cura del master, rispedire il pacchetto se non riceve una risposta dallo slave.

2) byte di stop. Avendo una trasmissione variabile in termini di lunghezza del pacchetto, quantità di dati indicata da uno specifico byte, forse non serve metterlo.

3) la collisione non c'è se fai come ho detto al punto 1)
Logged


Messina
Offline Offline
Jr. Member
**
Karma: 1
Posts: 74
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote from: leo72
Prendi il codice del ModBus e studialo, non c'è nulla di astruso dietro. Si tratta di spedire dei byte e dargli un significato.
Quando tu leggi un sensore, i dati che ricevi hanno un significato per te, giusto? Eppure, sei tu a darglielo, di per sé quelli sono solo numeri.  smiley-wink

Per quanto riguarda il Modbus ci stavo lavorando io....ma sinceramente non capisco come inviare e ricevere i dati....cioè...come fargli inviare un determinato dato o una lettura di un sensore e agire di conseguenza per me è un mistero...lo reputo troppo complicato...forse anche per l'esigenza di "adattare" il protocollo a qualcosa di commerciale...non so...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22935
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Guarda, ho spulciato nel Playground:
http://playground.arduino.cc//Main/InterfacingWithHardware#Communication

Ci sono già diversi progetti sul ModBus.
Logged


Offline Offline
Full Member
***
Karma: 2
Posts: 105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Quegli esempi sul playground purtoppo non sono ben documentati e non hanno influenza didattica su tante persone che come me si avvicinano per la prima volta al mondo del Modbus o dei protocolli su un arduino...

Quegli esempi almeno io come molte altre persone già li avevo visti e stravisti senza nessun risultato...
Quando parliamo di esempi tipo "buttons,analog input...etc..etc" allora il singolo maker ci mette del suo per imparare dagli esempi ma con i link citati nel playground aihmè...sfido chiunque al di fuori di programmatori e ingegneri a capire la struttura di un protocollo come il modbus che è sì uno standard ma tra la teoria e la pratica c'è di mezzo proprio la mancanza di esempi concreti...

Scusate per la minipolemica...buona giornata a tutti...e intanto continuo a sperimentare come un piccolo Leonardo con il protocollo 485...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22935
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non capisco il problema nello spedire 1 byte e nell'interpretarlo come un comando. Speditelo con ModBus o con qualsiasi altro protocollo, ma alla fine si tratta di ricevere qualcosa e fare un'azione.

Quando spedite la lettera "A" dal computer e fate accendere un led sull'Arduino non avete spedito 1 byte ed interpretato questo byte come un "comando"?
Logged


Battipaglia (SA)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 72
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

scusami leo72 ma ho ancora qualche dubbio sulla robustezza dell'implementazione.

Quote
Secondo me, se lo slave si aggancia alla trasmissione quando questa è in corso la deve semplicemente ignorare non appena si accorge che il primo byte che riceve non è quello di start. Sempre secondo me, deve scaricare tutti i byte che riceve perché altrimenti non può capire se ad esempio un byte $FF ricevuto a metà di un messaggio fa parte del pacchetto di dati oppure se è il byte di start. Sarà magari cura del master, rispedire il pacchetto se non riceve una risposta dallo slave.

Nell'esempio che facevo prima lo slave si agganciava perdendo i primi tre bytes e riceveva 5, 4, 2, 255, 6, 2, X. Cosa succede se si aggancia perdendo i primi 6 bytes ricevendo quindi 255, 6, 2, X? In questo caso il primo byte che riceve è proprio un 255 (indistinguibile da uno start...) che però non è uno start.

Ma come dicevo, questo problema mi pare risolto dal timeout...

Veniamo invece al tuo terzo punto sul quale ho il dubbio maggiore.

Quote
3) la collisione non c'è se fai come ho detto al punto 1)

Il punto 1 si occupa di come far individuare allo slave l'inizio del pacchetto. La collisione invece può avvenire nel seguente scenario.

  • Il master invia una richiesta ad uno slave ed attende una risposta entro 10ms (è solo un esempio... se è un tempo troppo lungo lo rivediamo successivamente)
  • Lo slave è occupato ed impiega un tempo maggiore per rispondere, per problemi del tutto estranei alla trasmissione dati (nel tuo esempio precedente c'e' un sensore difettoso).
  • Il master, trascorso il timeout, avvia una nuova trasmissione. Magari riprova ad interrogare lo stesso slave, magari passa allo slave successivo, non importa, la questione è che impegna nuovamente il bus
  • Lo slave, che ha ricevuto correttamente la prima richiesta (ma l'ha elaborata in ritardo), risponde mentre il bus è occupato dalla nuova trasmissione del master generando quindi la collisione.

Mi pare che questo scenario non abbia nulla a che vedere con la gestione dello start. Mi sbaglio?
Mi pare tuttavia che vada gestita altrimenti si corre il rischio di compromettere il funzionamento dell'intero bus dato che il master e gli slaves potrebbero entrare un uno stato dal quale non riescono più ad uscire bloccandosi definitivamente.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22935
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nell'esempio che facevo prima lo slave si agganciava perdendo i primi tre bytes e riceveva 5, 4, 2, 255, 6, 2, X. Cosa succede se si aggancia perdendo i primi 6 bytes ricevendo quindi 255, 6, 2, X? In questo caso il primo byte che riceve è proprio un 255 (indistinguibile da uno start...) che però non è uno start.

Ma come dicevo, questo problema mi pare risolto dal timeout...
Non tornerebbero tante cose. Ad esempio, leggerebbe un byte che indica il numero di byte da ricevere nel posto sbagliato, stando quindi in ricezione per un quantitativo di dati che non torna. Il checksum o arriva dal byte sbagliato oppure proprio non arriva. Se i dati in ricezione terminano, il timeout taglia la comunicazione.

Quote
Veniamo invece al tuo terzo punto sul quale ho il dubbio maggiore.
Hai visto come il protocollo implementato nel ModBus gestisce (se lo fa) questo evento?
Io no, chiedo per questo.
Logged


Battipaglia (SA)
Offline Offline
Jr. Member
**
Karma: 0
Posts: 72
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ho trovato questo documento che mi pare molto interessante.

Al secondo punto dell'elenco che c'e' all'inizio di pag. 10, si dice che il Response Time (ossia il tempo che si concede allo slave per rispondere dopo aver elaborato la richiesta), sia tipicamente compreso tra 1 e diversi secondi. E questo sembrerebbe un tempo enorme... ma in realtà non lo è!

Infatti, in sostanza mi pare di capire che la logica sia questa: il timeout è altissimo tanto da poter ragionevolmente supporre che se la risposta non arriva entro questo tempo non arriverà più (slave bloccato, spento, scollegato...).

Questo non rallenta le prestazioni del sistema perchè lo slave risponderà tipicamente in un tempo molto più bassso (pochi ms) mantenendo buone le prestazioni. Quando si verifica il malfunzionamento di uno slave (e si spera che sia un evento molto raro...) il bus rimane "bloccato" per pochi secondi che sono un tempo, tutto sommato, molto basso per identificare ed isolare (il master esclude lo slave dalla lista di quelli da interrogare) un problema.
Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Non capisco il problema nello spedire 1 byte e nell'interpretarlo come un comando. Speditelo con ModBus o con qualsiasi altro protocollo, ma alla fine si tratta di ricevere qualcosa e fare un'azione.

Quando spedite la lettera "A" dal computer e fate accendere un led sull'Arduino non avete spedito 1 byte ed interpretato questo byte come un "comando"?
Caro Leo io quello che non riesco a capire è proprio questo ,se io mi invento un miniprotocollino dove decido che :

byte "a" significa accendi led2       byte  "d"  significa spegni led2
byte "b" significa accendi led3       byte  "e"  significa spegni led3
byte "c" significa accendi led4       byte  "f"  significa spegni led4

...a questo punto come fare il passo da gigante per decidere di mandare i byte con il formato
Quote
Byte 1: Start Byte ( 0 hexadecimal ).
Byte 2-3: ASCII Arduino's address.
Byte 4: Byte ENQ, ACK or NAK (0x05h, 0x06h y 0x15h) .
Byte 5: ASCII Requested command.
Byte 6 y 7: ASCII Function number.
Byte 8: Sign byte (Positive 0x20h y Negative 2D)
Byte 9-12: ASCII of data bytes (0x00h-0xFFFFh)
Byte 13: Byte EOT (End of Text) (0x03h)
Byte 14-15: Checksum (addition from 2nd byte to 13th byte)
...o meglio io vorrei un piccolo esempio dove un master con Address "0x00"  invia un semplicissimo comando ad uno slave "0x01" e gli dice di accendere un led sul pin 13 per un secondo e lo spegne dopo un secondo...

MASTER "0x00"  invia Byte "accendi led pin13" a SLAVE"0x01"  come dovrebbe essere questo comando ??
Scusate ma proprio non riesco a capirlo e la volontà non mi manca...
Qualcuno che per favore ci scriva un esempio per il comando sopra citato...
Logged

Messina
Offline Offline
Jr. Member
**
Karma: 1
Posts: 74
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Non capisco il problema nello spedire 1 byte e nell'interpretarlo come un comando. Speditelo con ModBus o con qualsiasi altro protocollo, ma alla fine si tratta di ricevere qualcosa e fare un'azione.

Quando spedite la lettera "A" dal computer e fate accendere un led sull'Arduino non avete spedito 1 byte ed interpretato questo byte come un "comando"?
Caro Leo io quello che non riesco a capire è proprio questo ,se io mi invento un miniprotocollino dove decido che :

byte "a" significa accendi led2       byte  "d"  significa spegni led2
byte "b" significa accendi led3       byte  "e"  significa spegni led3
byte "c" significa accendi led4       byte  "f"  significa spegni led4

...a questo punto come fare il passo da gigante per decidere di mandare i byte con il formato
Quote
Byte 1: Start Byte ( 0 hexadecimal ).
Byte 2-3: ASCII Arduino's address.
Byte 4: Byte ENQ, ACK or NAK (0x05h, 0x06h y 0x15h) .
Byte 5: ASCII Requested command.
Byte 6 y 7: ASCII Function number.
Byte 8: Sign byte (Positive 0x20h y Negative 2D)
Byte 9-12: ASCII of data bytes (0x00h-0xFFFFh)
Byte 13: Byte EOT (End of Text) (0x03h)
Byte 14-15: Checksum (addition from 2nd byte to 13th byte)
...o meglio io vorrei un piccolo esempio dove un master con Address "0x00"  invia un semplicissimo comando ad uno slave "0x01" e gli dice di accendere un led sul pin 13 per un secondo e lo spegne dopo un secondo...

MASTER "0x00"  invia Byte "accendi led pin13" a SLAVE"0x01"  come dovrebbe essere questo comando ??
Scusate ma proprio non riesco a capirlo e la volontà non mi manca...
Qualcuno che per favore ci scriva un esempio per il comando sopra citato...


Ragazzi, io sono nelle stesse condizioni di pietro....sono diplomato geometra...non sono ingegnere elettronico...quindi quello che bene o male so...l'ho imparato dagli esempi commentati...(ottimo strumento didattico a mio avviso), questo protocollo per me è qualcosa fuori dagli schemi....io penso che se avessimo due sketch(uno per il master e uno per lo slave) con gli integer dichiarati, il void setup e nel void loop anche solo un comando che invia una serie di byte alla pressione di un pulsante e lo slave che esegue e restituisce risposta penso che potremmo metterci in moto anche noi...non voglio essere polemico ma inviare una "a" con il serial.write e leggerla con il serial.read è tutto un'altro discorso dall'inviare una serie di byte, integrare checksum e quant'altro e gestire il timeout....può apparentemente sembrare facile per chi sa farlo....personalmente non ne sono capace al momento...magari fra un mesetto vi dirò...ma si...che ci voleva....ma al momento no...purtroppo...
Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
io penso che se avessimo due sketch(uno per il master e uno per lo slave) con gli integer dichiarati, il void setup e nel void loop anche solo un comando che invia una serie di byte alla pressione di un pulsante e lo slave che esegue e restituisce risposta penso che potremmo metterci in moto anche noi...non voglio essere polemico ma inviare una "a" con il serial.write e leggerla con il serial.read è tutto un'altro discorso dall'inviare una serie di byte, integrare checksum e quant'altro e gestire il timeout....

Quoto in pieno Peppe91...meno male che non sono solo...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22935
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Prima di tutto mi scuso per una cosa, se avete frainteso il mio atteggiamento all'interno di questo thread.
Dovevo specificarlo prima, ma no l'ho fatto. Partecipo come "dispensatore di idee", non era nei miei interessi prendere parte attivamente alla cosa perché non è di mio primario interesse.
Finora ho dato l'idea di quello che parla parla, ma non fa  smiley-kiss
Mi spiace, ma era solo per darvi delle idee, non un aiuto concreto.

Se siete rimasti un po' impantanati nella cosa, cerco di aiutarvi finché posso, finché cioè la cosa non diventa (secondo il mio punto di vista) troppo impegnativa come partecipazione, perché non ho il tempo materiale per partecipare attivamente.

...o meglio io vorrei un piccolo esempio dove un master con Address "0x00"  invia un semplicissimo comando ad uno slave "0x01" e gli dice di accendere un led sul pin 13 per un secondo e lo spegne dopo un secondo...

MASTER "0x00"  invia Byte "accendi led pin13" a SLAVE"0x01"  come dovrebbe essere questo comando ??
Scusate ma proprio non riesco a capirlo e la volontà non mi manca...
Qualcuno che per favore ci scriva un esempio per il comando sopra citato...


Un esempio di spedizione di un dato con il protocollo che avevi proposto qualche post fa:

Quote
byte Start1;
byte IDMittente;
byte IDDestinatario;
byte IDComando;
byte LunghezzaPacchetto;
... qui un numero di bytes pari a LunghezzaPacchetto
byte Checksum;
potrebbe essere questo, assumendo l'indirizzo dello slave ipoteticamente $0001:

Code:
Serial.write(0xFF); //byte di start
Serial.write(0x00); //ID master ($00)
Serial.write(0x01); //ID slave ($01)
Serial.write(0x01); //comando: accendi led
Serial.write(0x01); //lunghezza pacchetto dati: 1 byte
Serial.write(0x0A); //pacchetto dati (qui, $0A = 13, indica il led 13)
Serial.write(0xxx); //byte di checksum (dipende dall'algoritmo usato)
Logged


Pages: 1 ... 3 4 [5] 6   Go Up
Jump to: