Strano comportamento libreria SoftwareSerial

Vediamo se qualcuno mi aiuta a capire qualcosa.
Ho utilizzato la libreria SoftwareSerial per dialogare con la seriale standard di arduino attraverso una interfaccia RS232C. Trasmetto una stringa dalla finestra MONITOR SERIALE dell'IDE alla miaseriale. I caratteri sono ricevuti in un array e tutto bene. La trasmissione e' senza CR o LF in coda. Ho poi pensato di trasmettere un CR dopo avere trasmesso la stringa. Se pero' faccio questo il CR si inserisce ta i caratteri del messaggio piu' di una volta e non al termine del messaggio stesso. Ho pensato di inserire un ritardo ma nulla da fare.
Qualche consiglio ? Teoricamente la trasmissione dovrebbe essere terminata prima di passare alla successiva riga di codice oppure una volta lanciata la trasmissione questa procede indipendentemente ?
Grazie a tutti.

#include <SoftwareSerial.h>

SoftwareSerial miaseriale=SoftwareSerial(7,8); 

int incomingByte = 0;   // for incoming serial data
char mes[20];

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

void loop()
{int i=0;
int k;

        if ((k=Serial.available())> 0)
            {while(Serial.available())             
               {incomingByte = Serial.read();
                mes[i]=(char)incomingByte;
                i++;
               } 
             for(i=0;i<k;i++) miaseriale.print(mes[i]);
             //miaseriale.write(13);
            }
}

Mi sa che é un overflow indice Array.
Kontrolla se k é sempre <20

Ciao Uwe

Secondo me è una questione di tempistica. Quando spedisci il primo available() carica in K quanti dati sono nel buffer, ma potrebbero anche non essere ancora tutti.
Che sò spedisci 10 char, magari nel buffer c'e' ne sono solo 6 e spedisci (con il primo CR) poi la loop prosegue (è ripetuta di continuo) e quindi becca gli altri 4 char a cui poi metti il secondo CR.
Quindi ti risultano 6 char + CR + 4 char + CR.
Non puoi spedire un terminatore ? Esempio un CR oppure un carattere noto tipo '#' oppure '@' ?

Eventualmente prova ad aumentare la velocità della USB/Serial da 9600 a valori pìù alti

La SoftwareSerial trasmette i dati in modo asincrono, cioè svuota il buffer di trasmissione secondo la disponibilità del processore.

Sulla seriale si usa il flush() per forzare lo svuotamento del buffer di trasmissione, ma non ricordo se funziona anche sulla seriale virtuale.

Prova ad usare print("\r") al posto del write(13).

Il K corrisponde alla strlen della stringa arrivata e depositata nell'array. Non cambia nulla usando '\r'. quando abilito la trasmissione del CR mi riprovo i caratteri ricevuti da Serial non sulla stessa linea ma un carattere o due poi a capo. In praticaa se trasmetto FRANCO (no cr o lf) ricevo :
F
RA
NC
O

invece che :
FRANCO(CR)

A 9600 baud la trasmissione di un byte richiede 1,042ms. Se io attendo anche 10ms tra una trasmissione e quella successiva senza fare altro, dovrei dare per scontato che il byte e' arrivato correttamente a destinazione. Inserendo questi delay pero' non cambia nulla. Adesso investighero' meglio.
Grazie comunque per i consigli e l'attenzione che mi avete dato. Rimango comunque in ascolto per altri suggerimenti.

Aggiornamento: sembra che la trasmissione di mess su miaseriale si blocchi sul primo carattere se inserisco un while che impedisce al loop principare di essere eseguitodopo la prima volta. In pratica sull'array sono ricevuti i caratteri inviati da serial e perche' siano trasmessi tutti occorre fare girare il loop principale. Per scrupolo ho inserito un miaseriale.flush() dopo la trasmissione dell'array mess ma e' ininfluente. E' la prima volta dopo tanti anni che ho problemi con una seriale. Normalmente mi creavo la mia libreria ma questa volta avendo a disposizione SoftwareSerial ho voluto utilizzarla.

#include <SoftwareSerial.h>

SoftwareSerial miaseriale=SoftwareSerial(7,8); 

int incomingByte = 0;   // for incoming serial data
char mes[20];

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

void loop()
{int i=0;
 int k;

        if ((k=Serial.available())> 0)
            {while(Serial.available())             
               {incomingByte = Serial.read();
                mes[i]=(char)incomingByte;
                i++;
               } 
              miaseriale.print(mes);
              //miaseriale.write('\r');
              //while(1);     
            }
}

Rivedendo più attentamente il tuo sketch, mi sono accorto che tu ricevi attraverso il Serial.read().

Evidentemente quando il while non trova altri caratteri, passa alla fase successiva.

Sarebbe meglio inserire anche un timeout all'interno della condizione while, per consentire al PC la trasmissione completa della stringa.

Da quello che mi sembra Serial.read legge un carattere alla volta. Quindi in abbinamento a Serial.available si riesce a spillare il contenuto del buffer di ricezione seriale sino a che non ci sono piu' caratteri disponibili (Serial.avilable ritorna 0).
L'array e' correttamente formattato con i valori ricevuti e, se prima inizializzo tutti i suoi 20 byte a '\0', quando lo vado a riempire con i dati ricevuti realizzo una stringa corretta da passare alla Serial.print. Questo in via teorica. Leggendo qua e la sembra che dalla versine 1.0 in poi sia la Serial.print che la Serial.write non attendano piu' il termine della trasmissione fisica dei dati che gli sono dati in pasto. La gestione e' affidata ad un interrupt che a cadenza trasmette i dati in background. Se si vuole attendere la fine fisica della trasmissione, cosi' ho letto, occorre usare Serial.flush subito dopo la Serial.write o print. Io ho provato ma niente da fare.
Quanto riporto vale anche senza usare la seriale software ma la Serial hardware utilizzando come terminale di input/output il monitor seriale. Ripeto che l'array e' correttamente formato e terminato da '\0' e quindi e' di fatto una stringa in tutto e per tutto.
A momento non ho piu' idee. Riesco a trasmettere e ricevere correttamente qualsiasi messaggio a patto di non volere inserire al suo termine un CR. Il messaggio trasmesso e' senza CR o LF e quindi volevo aggiungere un CR per andare a capo per la successiva visualizzazione di un ulteriore messaggio. Certo, se dico al terminale di output di inserire un CR in coda lui lo fa' e tutto funziona, ma non capisco perche' se lo inserisco io dopo avere ricevuto il messaggio non funziona.
chissa' chi lo sa.

Appunto. Chi spedisce è meglio inserisca un terminatore (in spedizione) di indicazione "fine spedizione" e chi riceve sà come comportarsi.

così si legge.

void readstr(char *d, byte sz)
{
    if ( sz < 2 ) { *d = '\0'; return; }

    do
    {
        while( !Serial.available() );
        *d = Serial.read();
    }while ( --sz && *d++ );
    *d = '\0';
}

così si usa

void loop()
{
    char buf[32];
    readstr(buf,31);
    ...
    ...
}

Grazie per i suggerimenti. Questa sera al ritorno dall'ospedale per controlli postoperazione provo la procedura suggeritami. Vi ringrazio molto per la collaborazione e per la pazienza che avete.



Bene, ho provato il tuo codice pari pari ma devo dire che purtroppo non funziona, almeno secondo le mie necessita'. Mi spiego meglio.Funziona se definisci in anticipo il numero di caratteri che devi ricevere dalla seriale. In caso contrario continua a ciclare all'interno del do-while in quanto non trova le condizioni per uscire soddisfatte.
Il mio obbiettivo e' ricevere messaggi a lunghezza variabile ma ovviamente non piu' lunghi della dimensione dell'array deputato alla sua ricezione. Ti ringrazio comunque dell'interessamento e spero di non averti fatto perdere tempo.
Grazie ancora per l'attenzione.

succede ciò perché il codice postato attende il terminatore '\0' che a quanto pare non viene inviato.
Puoi provare con '\r\n' i classici di windows

void readstr(char *d, byte sz)
{
    if ( sz < 2 ) { *d = '\0'; return; }

    do
    {
        while( !Serial.available() );
        *d = Serial.read();
        if ( *d == '\r' ) continue;
        if ( *d == '\n' ) break;
    }while ( --sz && *d++ );
    *d = '\0';
}