seriale e fine stringa

come faccio a intercettare la inizio/fine di un messaggio seriale senza sapere la lungezza e senza avere i caratteri cr e cenza controlli dtr dts ecc ecc

il messaggio lo invii dal serial monitor?
bene aprilo e in basso a destra hai le opzioni per selezionare il terminatore di stringa

.... mmmm ... mi sa che gli arriva da un qualche cosa di esterno su cui non ha il controllo, altrimenti ho il sospetto che lo avrebbe già fatto ::slight_smile:

Se non c'è alcun genere di separatore ... l'unica cosa che mi viene in mente è un meccanismo di timeout ...
... ma funziona solo se tra una stringa e la successiva intercorre un certo tempo, tempo che invece non deve intercorrere tra un carattere e l'altro di una singola stringa.

Guglielmo

@gbp01, in quel caso sarà meglio che specifica il cosa, dove, quando e perchè.

i dati li ricevo dall’esterno , non ho separatori di nessun tipo , è una specie di modbus ma invio solo l’indirizzo senza nessun protocollo e mi risponde con una strisciata di byte che contengono i dati
in pratica chiamo 0x01 e mi risponde 0x01 0xdd 0xee ecc ecc
le chiamate sono a rotazione 01 02 ecc

anche io pensavo a un time out tipo di un byte e mezzo altrimenti continuo la mia vecchia strada …analizzare il “protocollo” e mi leggo tutte le risposte cosi mi segno le lunghezze che non variano mai :slight_smile:

Un attimo, ma sei TU che solleciti l'invio? Quindi interroghi prima 0x01, poi 0x02, e così via?

Perché allora, indipendentemente da quanti caratteri arrivano, alla fine il flusso si interrompe sino a quando tu non interroghi il successivo, quindi ... il timeout, pur NON essendo il massimo dell'efficienza ti va benissimo.

Guglielmo

io non posso sollecitare la chiamata io sono solo in ascolto con due seriali una su rx e una sl tx
pero in teoria il flusso si interrompe magari di un paio di byte ma si interrompe

ma se faccio cosi....
dovrebbe funzionare

if (Serial1.available()> 0 ) {
// read the incoming byte:
incomingByte = (Serial1.read());
//Serial.println(incomingByte);
else
Serial.println("END");

NO, devi utilizzare la micros() (... con la millis() non hai sufficiente risoluzione, ma la logica d'uso è identica), per misurare l'intervallo tra un carattere ricevuto ed il successivo.

Se superi N microsecondi (in funzione del baud rate e del numero di bit per carattere) consideri terminata la stringa.

Hai mai usato prima la millis() ? Conosci come si usa ? Se NO ... devi a leggere prima QUI, poi QUI ed infine leggi anche QUI e QUI ... e ti si dovrebbero chiarire le idee :wink:

Guglielmo

vado a leggere ma penso di aver capito il senso

che poi alla fine a me di sapere cosa ce scritto nei byte mi interessa relativamente poco , io devo solo capire se a una chiamata ho una risposta e sapendo che non ho variazioni di stato sui bit la strisciata di byte resta sempre uguale
io adesso ho il problema che se ho un difetto non capisco di chi è la colpa se remota o locale

Stai sniffando un modbus? di cosa puoi dirlo?
allarme?
modello?

pablos:
Stai sniffando un modbus? di cosa puoi dirlo?

Mi sembra che abbia detto che è ...

alessanddrob:
una specie di modbus ma invio solo l'indirizzo senza nessun protocollo

Guglielmo

non so se puo funzionare cosi in pratica memorizzo il contatore quando la serial e available e leggo un byte e se mi aumenta lo spazio tra i byte dico che deve andare a capo

tanto alla fine ho una sequenza di 10 byte per 10 indirizzi sulla seriale 1
e una sequenza di tot byte per ogni indirizzo sulla seconda seriale

unsigned long previousMillis0= 0;
unsigned long previousMillis1 = 0;

if (Serial1.available()> 0 ) {
previousMillis1 = millis();
incomingByte = (Serial1.read());
//Serial.println(incomingByte);
else
previousMillis1 =mills() >=previousMillis2 = (millis()+200));
Serial.println("/cr");

il valore 200 è a caso

no non è un modbus una specie di PLC ma senza processore, tutta logica cablata vecchio come la ruota di legno
non si rompe mai al contrario dei plc, che ogni tanto scoppiano e se suicidano , qui ho solo problemi di connessione e visto che alcuni sono anche a 20km, devo trovare il modo di capire al volo chi si è ammutito e perchè

(40 anni e passa)

Prendi il tempo prima di entrare in un while(true) ... nel while() ricevi un carattere alla volta e, se non ti serve memorizzare quello che hai ricevuto, puoi anche buttarlo ... se ricevi un carattere riprendi il tempo ... ti chiedi se il (tempo attuale - l'ultimo tempo preso) è maggiore di timeout con un break esci dal while() ... e il gioco è fatto :slight_smile:

Guglielmo

byte serial_readTimeout(byte* d, byte n, uint32_t t)
{
    uint32_t st = micros();
    byte count = 0;
    while( n > 0 && (micros() - st < t) )
    {
        if ( 0 == Serial.available() ) continue;

        *d = Serial.read();
        ++d;
        --n;
        ++count;
        st = micros();
    }
    return count;
}

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

}

void loop() {
    byte buffer[10];
    byte nread = serial_readTimeout(buffer, 10, 1000000);  

    int i;
    for ( i = 0; i < nread; ++i)
        Serial.print(buffer[i]);
    Serial.println("");
}

in questo esempio serial_readTimeout, passatogli un buffer, la sua dimensione(10byte) e un tempo(1secondo) legge da Serial fino a che non passa un secondo da un dato al sucessivo per poi ritornare quanti byte sono stati letti, che li va dunque a ciclare e li reinvia con la Serial.
Quindi nessun carattere di terminazione, perchè sara data da un tempo di non ricezione.

Un modbus di 40 anni? sicuro che possiamo chiamarlo così?
modtramvai ahahahhaha

vbextreme... grazie per l'esempio domani me lo studio bene , ma penso di aver capito che il tutto è legato al buffer di 10 char , io non ho una misura precisa

Un modbus di 40 anni? sicuro che possiamo chiamarlo così?
modtramvai ahahahhaha

domani metto una foto cosi vi lascio a bocca aperta e capite di che diavolo di animale sto parlando :smiley:

@alessanddrob, il buffer puoi settarlo anche a 500byte, l’algoritmo termina quando non riceve più niente per un secondo.
Facciamo un esempio, se tu sai che tra una pausa di 10ms e un’altra vengono inviati circa 80byte puoi chiamarla così

void loop() {
    byte buffer[100];
    byte nread = serial_readTimeout(buffer, 100, 9000);  

    int i;
    for ( i = 0; i < nread; ++i)
        Serial.print(buffer[i]);
    Serial.println("");
}

ovvero gli passi un buffer più grande e un tempo leggermente più piccolo, la funzione ritornerà il reale numero di byte letti.

salve sono tornato
allora, riepilogando.... non sono ancora riuscito a usare i vostri esempi , ma ho provato con serial.available() e usando lo spazio tra un pacchetto e un altro gia cosi riesco ad avere un inizio e una fine trazmissione anche non sapendo la lunghezza esatta.
sull'armadio di test la trasmissione è lentissima :smiley: e questo sistema funziona perfettamente , appena passano le feste e posso rischiare sul sistema completo faro un esperimento al massimo della velocita :smiley:
per adesso grazie... avete una bevuta pagata
Buon fine anno e nuovo inizio.....e pensatemi che io sono al lavoro