tempo wait dopo la write

Ciao,
ho una domanda sul tempo di sleep dopo aver fatto la scrittura di un messaggio sulla seriale per mettersi poi in attesa della risposta.
Nel mio caso specifico devo inviare dei messaggi modbus RTU a 9600 baud (8-N-1) con un adattatore rs485 usb.

Considerando che ho start bit=1, data bits=8 e stop bits = 2 ho praticamente 11 bits per carattere inviato. E' corretto quindi dire che ogni secondo posso inviare 9600/11 = 872 caratteri?

Pertanto se ad esempio devo scrivere un messaggio di 15 caratteri devo fare una pausa "minima" dopo la write di (11*15) / 9600 = 0,0171875 sec => 17ms ?

Dal punto di vista empirico non mi torna tanto in quanto se faccio pause inferiori a 150/200ms mi tende a perdere messaggi.

Forse sbaglio qualcosa con la libreria nell'attesa dei messaggi di risposta, martedi controllo meglio. In generale comunque il conteggio dei tempi è corretto?

Mi è chiaro che il msg di risposta mi arriva dopo che è passato il tempo di invio del msg di richiesta (calcolato sopra), il tempo di elaborazione dello slave (circa 80ms) e il tempo di ricezione della risposta (dipende dalla grandezza, ma in genere intorno ai 20/25ms)

grazie

Non capisco perché Ti serve questo calcolo.
Mandi il messaggio, Dopo il tempo di invio metti la RS485 in ascolto e aspetti con serial.aviable() finche sono arrivati il numero di caratteri della risposta oppure se la lunghezza non é fissa allora se é arrivato il carattere di fine messaggio.
Ciao Uwe

devo cercare di capire perché se non faccio la wait dopo la write leggo robaccia sulla linea, da quel che vedo è la lettura dei dati che si ferma prima del dovuto. sto debuggando

ciao...per la comunicazione modbus usi una libreria specifica o cosa?
il o i device che vai ad interrogare cosa sono...altri arduino o altro?
fai attenzione che il device che dovrebbe risponderti deve avere il tempo di reperire le informazioni...elaborarle e dopo inviarle...in certi casi la latenza va anche oltre i 500 ms.

blacktek:
Nel mio caso specifico devo inviare dei messaggi modbus RTU a 9600 baud (8-N-1) con un adattatore rs485 usb.
Considerando che ho start bit=1, data bits=8 e stop bits = 2

Beh ma i bit di stop sono 1 o 2??

A parte questo, il calcolo va bene, ma in genere non ha senso fare sleep() per un tempo pari ai dati che hai appena inviato, per cui il problema potrebbe essere nell'adattatore RS485USB, che forse bufferizza i dati che tu gli "spari" velocemente. E poi non so se ci siano altri fattori, ad esempio c'è handshake hardware? La 485 magari fa in half duplex? La risposta dopo quanto tempo dovrebbe arrivare?

sto usando una librearia trovata in rete per leggere i dati sulla seriale. I bit di stop sono 2, scusate l'errore precedente, dovevo scrivere 8-N-2. l'handshake è sicuramente hw e lo fa l'adattatore usb, per quel che ne so il protocollo RS485 modbus RTU non è halfduplex.

Dal debug che sto facendo vedo che il problema sta con la read dal file descriptor, se non faccio una pausa abbondante prima della read quest'ultima si interrompe in mezzo al pacchetto senza finire di leggerlo tutto.
il fatto è che a livello di socket mi pare che la specifica non preveda uno speciale carattere di terminazione, quindi quando la read ritorna non è facile determinare se dopo ci sono altri byte da leggere o meno.

Io qui sto scrivendo il codice da un raspberry, e dovrò leggere da sonde arduino e altri tipi. il problema è comune cmq a tutti gli slave.

Lo stream è in non blocking mode (il contrario non funziona per nulla)

A questo punto non so dirti molto, resta un comportamento strano ma io mi concentrerei sulle caratteristiche del convertitore USB-serial (hai un link di quello che usi? Dando per scontato che non sia guasto, ad esempio verificare che magari non sia lui ad avere qualche gestione "strana" dei suoi buffer e/o non sia impostato in half duplex...).

il dispositivo usb per rs485 ha chip ch341. a tuo avviso però qualè il comportamento strano? se il protocollo mdbus rtus su rs485 non prevede una speciale sequenza di byte per indicare la fine del msg ne lunghezza del pacchetto che sta arrivando come capire quando si arriva alla fine se non con dei timeout? sto indagando in quella direzione

Il "comportamento strano" al quale mi riferisco è quello per il quale leggi "robaccia" se non fai i delay: riesci a capire se questa "robaccia" è parte di qualcosa (es. pacchetti di altri device, o magari un "eco" dei tuoi stessi dati) o se sono dati apparentemente "casuali" (il che mi farebbe pensare più ad un difetto del convertitore o un problema di cablaggio elettrico della linea)?

Io non ho mai lavorato con Modbus RTU quindi leggendo al volo qualche specifica ad esempio non mi è chiaro se tu sia master o slave e poi mi sembra che per la "fine pacchetto" questo dipenda dalla funzione, quindi "sai" quanti byte aspettarti leggendo, o sbaglio?

per robaccia intendo che legge un pacchetto parziale (incompleto). Se resto più in attesa invece riesco a leggere il pacchetto intero. Volevo fare però un qualcosa di progettato bene, non con sleep giusto per far funzionare le cose.

Sto sviluppando la parte master. la lunghezza del pacchetto di risposta dipende dalla funzione modbus richiamata (read coil, read registers etc) e dal numero di registri. Qui stavo sviluppando lo stratto di comunicazione sotto al modbus che si interfaccia con la seriale. Ho visto del codice python che tenta di stimare la lunghezza del msg di risposta a partire dalla request, ma non è proprio bellissimo, anche se mi sa che farò quella fine se non trovo soluzioni più smart

blacktek:
per robaccia intendo che legge un pacchetto parziale (incompleto). Se resto più in attesa invece riesco a leggere il pacchetto intero.

Capito, quindi il pacchetto incompleto che leggi non è qualcosa di incomprensibile come avevo erroneamente interpretato, ma solo la prima parte della risposta che ti aspetti di ricevere, ma per la quale attendendo un tempo sufficiente (qui il calcolo in base alla velocità e bit totali è corretto) avresti il pacchetto completo. Esatto?

Ok, allora hai due strade secondo me: o, come stai impostando, aspetti il tempo corrispondente al numero di byte che sai di dover ricevere dando quindi tempo al buffer del convertitore di riempirsi, oppure, meglio, leggere sempre tutti i byte eventualmente presenti ed accumularli in un buffer, poi leggere dal buffer la funzione ed in base a questa vedere se hai ricevuto la lunghezza corrispondente e solo allora iniziare a processare il pacchetto.

mi sa che le due soluzioni proposte siano la stessa alla fine, devo sapere i byte che so di dover ricevere.

ora provo a implementare questa parte del protocollo: Each message must be preceded by a time gap with a minimum length of 3.5 characters. If a receiver detects a gap of at least 1.5 characters, it assumes that a new message is coming and the receive buffer is cleared

blacktek:
mi sa che le due soluzioni proposte siano la stessa alla fine, devo sapere i byte che so di dover ricevere.

Non proprio, con la prima vai completamente "alla cieca" andando ad aspettare un tempo pari al pacchetto più lungo, con la seconda puoi invece saperlo appena ricevi il function code.

ora provo a implementare questa parte del protocollo: Each message must be preceded by a time gap with a minimum length of 3.5 characters

Uhm non mi è chiaro in cosa possa aiutarti, questo è solo il tempo minimo che devi/puoi attendere dopo aver mandato la request, a meno che tu non intenda dire che consideri concluso il pacchetto quando c'è una "pausa" di 3.5 carattteri dopo l'ultimo (ma non so se questa cosa sia per te mascherata dall'interfaccia USB).

docdoc:
Uhm non mi è chiaro in cosa possa aiutarti, questo è solo il tempo minimo che devi/puoi attendere dopo aver mandato la request, a meno che tu non intenda dire che consideri concluso il pacchetto quando c'è una "pausa" di 3.5 carattteri dopo l'ultimo (ma non so se questa cosa sia per te mascherata dall'interfaccia USB).

ho provato proprio a fare questo, ad aspettare 3.5 caratteri dopo l'ultimo byte ricevuto e purtroppo non funziona. 3.5 caratteri sono circa 4ms a 9600 baud, ma spesso ne passavano molti di più.

ho risolto in modo "sporco" e facendo funzionare il layer di comunicazione con la seriale più ad hoc per il modbus. In pratica aspetto di leggere almeno 3 caratteri, nel 3° è indicato il numero di byte, ma questo vale solo per alcuni tipi di funzione (es non per le SET), che però sono quelle con payload più grande. da verificare un pochino come va.

grazie :slight_smile:

ciao...il modbus rtu ha sì il controllo dei dati inviati...mettiamo tu voglia leggere una serie di registri, funzione 03 del protocollo, dallo slave; il master invierà un messaggio così composto:

address (1 byte)...ID dello slave a cui ti rivolgi
function (1 byte)...in questo caso 03
start register (2 bytes)...per esempio registro 100
n° of registers (2 bytes)...per esempio 3
CRC (2 bytes)....questo servirà allo slave per verificare se il buffer inviato è valido

totale 8 bytes di richiesta...lo slave risponderà così:

address (1 byte)...sempre l'ID dello slave
function (1 byte)...sempre 03
byte count (1 byte)...conteggio dei byte dei registri interrogati per esempio 3 registri tornano 6 byte.
data (ogni registro interrogato invia 2 bytes)...per creare una int per ogni registro
CRC (2 bytes)...questo serve al master per verificare se il buffer ricevuto è valido.

...poi ci sono altre funzioni sia per leggere che per scrivere...singoli o multi registri o coil...

scusate..adesso ho letto tutti i precedenti post...da quel che so io i 3.5 caratteri di vuoto sono per indicare che quel flusso è finito...il ricevente eseguirà la verifica del CRC...cercherà i dati richiesti od esegurà le operazioni richieste ed invierà risposta...di solito si imposta un tempo di timeout oltre il quale generi un errore.

per esperienza personale ho avuto slave che rispondevano tra i 200 ed i 500 ms...

quello che dici è corretto, ma non tutte le funzioni modbus rispondono con lo stesso formato di risposta. Quindi ad esempio non posso fare affidamento che nel byte 3 della risposto trovo il byte count.

Il byte count c'è solo per le funzioni READ:
01 READ COIL STATUS
02 READ INPUT STATUS
03 READ HOLDING REGISTERS
04 READ INPUT REGISTERS

non c'è per le write che di solito prevedono (in caso di esito positivo) l'ECHO della request:
05 WRITE SINGLE COIL
06 WRITE SINGLE REGISTER
15 WRITE MULTIPLE COILS
16 WRITE MULTIPLE REGISTERS

Quello che mi "dispiace" è non poter fare affidamento sulla specifica esatta del modbus che prevede appunto 3.5 caratteri di pausa alla fine del frame. Chiaramente comincio a contare la pausa a partire dall'ultimo byte di risposta ricevuto (non da quando invio la request).

Grazie :slight_smile: