serialport e c#

ciao a tutti
ho un problema
sto cercando di far comunicare un arduino con la porta seriale del pc con un programma scritto in c#
quando faccio il test di lettura su pc con hyperterminal i valori sono giusti e aggiornati
mentre quando uso il mio programma fatto in c# i valori sono corretti solo se mando da arduino un solo valore variabile appena ne metto un altro da trasmettere non sono più corretti sembra quasi in ritardo
la velocita che utilizzo della porta seriale è 115200
programma funzionante
AngleX = String(mpu6050.getAngleX());
Serial2.print(“1=” + AngleX + “\r\n” );
qui i valori sono giusti ma appena scrivo questo
AngleX = String(mpu6050.getAngleX());
Pressione = bmx280.getPressure();
Serial2.print(“1=” + AngleX + “\r\n” + “2=” + Pressione);
i valori non corrispondono
come si può risolvere?
grazie

Beh per prima cosa è sempre bene descrivere meglio il progetto, ad esempio quale Arduino stai usando (UNO, Mega...)?

E su Arduino quale seriale stai usando, quella embedded (quindi tramite USB) o una porta seriale fisica (ed in tal caso non è che per caso stai usando una SoftwareSerial, vero???)?

E se quello che hai postato è il codice Arduino intanto cerca di abituarti ad evitare come la peste la classe String, perché su Arduino non c'è alcun "Garbage collector" come su PC, e rischi di saturare la memoria e causare malfunzionamenti inspiegabili. Devi usare le "stringhe C" ossia array di char. Se non sai come usarli, troverai parecchie risorse in rete sull'argomento "arduino stringhe c", anche qui nel forum, o comunque facci sapere se vuoi una prima "infarinata".

PS E comunque il primo dato lo separi con "\r\n" mentre il secondo no... E una bottarella di debug lato Visual Studio dovrebbe confermartelo...

sto cercando di creare un robot che manda segnali telemetrici al computer tipo dati pressione accelelometro e gps
uso arduino mega 2560 senza software serial utilizzo la serial2
ho trovato questo
string.c_str()
dovrebbe funzionare?
grazie

No, DEVI evitare le String in generale ed imparare ad usare le stringhe classiche del C.
Comunque per mandare dati via Serial senza usare String basta semplicemente scrivere i vari pezzi separati, senza passare per variabili intermedie ed il gioco è fatto:
Serial2.print("1="); Serial2.println(mpu6050.getAngleX());
Serial2.print("2="); Serial2.println(bmx280.getPressure());

E poi il programma lato C# lo possiamo vedere ? Magari l’errore è li, visto che con hyperterminal funziona e col tuo no ?

se arduino manda una stringa sola la legge correttamente
se mando più stringhe no
questo è il codice che uso in c#
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
Ricevo = RobotPort.ReadLine();
Ricevo = Ricevo.Replace("\r", string.Empty);
Ricevo = Ricevo.Replace("\n", string.Empty);
if (Ricevo.StartsWith("Dati="))
{
xx=Ricevo.substring(5);
Ricevo="";
}
if (Ricevp.StartsWith("Altro="))
{
Altro=Ricevo.substring(6);
Ricevo ="";
}
}

Ti hanno detto che nella seconda stringa manca il newline, "primastringa\r\n secondastringa \niente", siccome la serialport.ReadLine() legge fino a quando non trova il newline potresti avere comportamenti imprevisti. In pratica leggendo la seconda stringa potresti avere problemi di lettura mancando il newline.

mikibenx:
Ricevo = RobotPort.ReadLine();
Ricevo = Ricevo.Replace("\r", string.Empty);
Ricevo = Ricevo.Replace("\n", string.Empty);
if (Ricevo.StartsWith("Dati="))

Allora, già ti avevo detto che dovresti fare un poco di debug lato Visual Studio ma non l'hai fatto altrimenti lo avresti già capito da solo. Inoltre voglio sperare che quel codice tu lo abbia scritto qui nel forum e non capia/incollato dal tuo vero codice (perché non copiare esattamente??), visto che "Ricevp.StartsWith()" è sbagliato.

Ma sorvoliamo. Visto quello che stai dicendo devo supporre però che tu non sia molto pratico neanche di C# e Visual Studio, per cui provo a fartici arrivare col metodo "grezzo" ossia immagina di essere tu ad eseguire i programmi e vedi cosa succede.

Se sai come funziona la ReadLine() dovresti sapere che se tu fai UNA "ReadLine()" leggi UNA riga terminata con "\r\n", fin qui ci siamo?

Ora, il primo problema è questo: se tu da Arduino mandi "1=qualcosa\r\n2=altro" (stando al tuo codice che hai postato) quando richiami la "ReadLine()" ti restituirà "1=qualcosa" (è inutile togliere via "\r\n" perché la ReadLine non li restituisce).

Se tu fai Ricevo.StartsWith("Dati=") non lo troverai mai visto che ricevi "1="... Dovresti fare Ricevo.StartsWith("1="). Stessa cosa per Ricevo.StartsWith("Altro=") che dovrebbe essere Ricevo.StartsWith("2="). Ma anche qui suppongo che se hai digitato il codice senza mandarci quello esatto, semplicemente tu abbia sbagliato a scrivere (ma se vuoi ancora aiuto, d'ora in avanti riporta esattamente il tuo codice con copia/incolla!!)

Ma qui viene il secondo problema: tu COME vuoi mandare questi dati? Devi prima stabilire esattamente quale sia la sintassi di questo tuo protocollino. Quindi diamo per buono che "1=" è il primo dato e "2=" per il secondo. Ma tra un dato e l'altro devi sempre mettere "\r\n" per farli leggere singolarmente.

Quindi (tralasciando per ora la conversione da String a "stringa C") lato Arduino:

...
  AngleX = String(mpu6050.getAngleX());
  Pressione = bmx280.getPressure();
  Serial2.println("1=" + AngleX);
  Serial2.println("2=" + Pressione);

e lato C#:

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
   Ricevo = RobotPort.ReadLine();
   if (Ricevo.StartsWith("1="))
  {
      xx=Ricevo.substring(5);
     Ricevo="";
  }
  if (Ricevo.StartsWith("2="))
 {
   Altro=Ricevo.substring(6);
   Ricevo ="";
 }
}

è da poco che faccio queste cose con la seriale comunque se dici che non sei anche pratico di visual studio sembra quasi un offesa visto che e c# è parte di visual studio
visual studio è un insieme di programmi di sviluppo in questo caso io sto utilizzando visual c#
comunque qui sotto il copia incolla del codice
parte di arduino

 Serial2.print("Pressione=");
  Serial2.println(Pressione);
  Serial2.print("TemperaturaBarometro=");
  Serial2.println(TemperaturaBarometro);
  Serial2.print("Contatore=");
  Serial2.println(String(Contatore));
  Serial2.print("XAcc=");
  Serial2.println(XAcc);
  Serial2.print("YAcc=");
  Serial2.println(YAcc);
  Serial2.print("ZAcc=");
  Serial2.println(ZAcc);
  Serial2.print("GyroX=");
  Serial2.println(GyroX);
  Serial2.print("GyroY=");
  Serial2.println(GyroY);
  Serial2.print("GyroZ=");
  Serial2.println(GyroZ);
  Serial2.print("AngleX=");
  Serial3.println(AngleX);
  Serial2.print("AngleY=");
  Serial2.println(AngleY);
  Serial2.print("AngleZ=");
  Serial2.println(AngleZ);
  Serial2.print("TemperaturaAcc=");
  Serial2.println(TemperaturaAcc);
  Serial2.print("Contatore=");
  Serial2.println(String(Contatore));

la parte di c#

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    Ricevo = serialPort1.ReadLine();
    if (Ricevo.StartsWith("Xacc="))
    {
       AccX = Ricevo.Substring(5);
       Ricevo = "";
     }
     if (Ricevo.StartsWith("Yacc="))
     {
        AccY = Ricevo.Substring(5);
        Ricevo = "";
      }
      if (Ricevo.StartsWith("Xacc="))
      {
         AccX = Ricevo.Substring(5);
         Ricevo = "";
       }
       if (Ricevo.StartsWith("GyroX="))
       {
          GyroX = Ricevo.Substring(6);
          Ricevo = "";
       }
       if (Ricevo.StartsWith("GyroY="))
       {
           GyroY = Ricevo.Substring(6);
           Ricevo = "";
       }
       if (Ricevo.StartsWith("GyroZ="))
       {
            GyroZ = Ricevo.Substring(6);
            Ricevo = "";
        }
        if (Ricevo.StartsWith("AngleX="))
        {
             AngleX = Ricevo.Substring(7);
             Ricevo = "";
         }
         if (Ricevo.StartsWith("AngleY="))
         {
             AngleY = Ricevo.Substring(7);
             Ricevo = "";
         }
         if (Ricevo.StartsWith("AngleZ="))
         {
              AngleZ = Ricevo.Substring(7);
              Ricevo = "";
          }
          if (Ricevo.StartsWith("Pressione="))
          {
              PressioneBarometrica = Ricevo.Substring(10);
              Ricevo = "";
          }

il problema secondo me è che utilizzo timer1
per mettere le stringhe ricevute su dei label visto che sotto datareceived non lo permette
avete altre soluzioni? grazie

>mikibenx: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More → Modify che si trova in basso a destra del tuo post) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non avrai sistemato il codice come richiesto, nessuno ti potrà rispondere, quindi ti consiglio di farlo al più presto. :wink:

Hai un errore madornale nel tuo codice.

Quel

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

é un evento. Ovvero il programma esegue quel codice quando sulla seriale é apparso qualcosa.

In questo evento poi, aspetti che venga inoltrato una riga intera e “blocchi” tutto il programma.

Non é così che va risolto.

In generale, quel serialPort1.ReadLine(); andrebbe evitato, visto che poi, se non leggi la riga, il programma non va avanti.

Basta scrivere però serialPort1.ReadExisting(); e ricevi la stringa inviata dall’Arduino e lo aggiungi ad una variabile esistente.

A questo punto poi, puoi guardare se é arrivata una riga, oppure mostrarlo direttamente nella console, per avere anche più informazioni su cosa hai ricevuto.

Altro punto, dividerei poi la stringa con Split(’=’), così hai sia il valore che il nome del parametro.

Concordo con @Adrianotiger, e se preferisci puoi usare il timer per fare tutto:

private void Timer1_Tick(object sender, EventArgs e) {
  string IncomingData = SerialPort1.ReadExisting();

  if (string.IsNullOrEmpty(IncomingData)) {
    return;
  }

  //Fai il parsing della stringa, controlli i valori, etc
}

Ti consiglio anche la lettura di questo post, per la corretta configurazione della Serial.NewLine lato Net.

Federico

mikibenx:
è da poco che faccio queste cose con la seriale comunque se dici che non sei anche pratico di visual studio sembra quasi un offesa visto che e c# è parte di visual studio
visual studio è un insieme di programmi di sviluppo in questo caso io sto utilizzando visual c#

Si, non volevo offenderti (sai, leggendo nel forum non è che si possa conoscere bene quanto uno sia esperto di cose diverse da Arduino...), e comunque lo so bene, anche io uso VS e C#!

Quello che dicevo (e che ripeto) è che se nel tuo programma ti metti in debug con qualche breakpoint nel tuo codice, puoi vedere direttamente cosa ricevi, cosa fa il tuo codice passo-passo, cosa contengono le variabili, e quindi capire come correggerlo se necessario (o magari confermare che lato C# è tutto a posto quindi il problema sono i dati che ricevi, non come li gestisci).

Scusa, ma è una cosa normalissima che fanno tutti quando sviluppano (ovviamente non solo con Visual Studio, qualsiasi IDE di linguaggi ad alto livello fa questo), per cui, oltre a ripetere che devi definire esattamente il tuo protocollo (o postare qui il VERO codice, non digitato appositamente...) continuo a non capire come mai tu non faccia debug lato VS/C# visto che almeno lì c'è questa possibilità, e credo che in quel modo riusciresti a capire il tuo problema e quindi a risolverlo...

E come vedi, quello che ti hanno detto e consigliato Adrianotiger e Federico66 sono tutte cose lato C# che hai fatto in modo errato. Per cui o dai tutte le informazioni oppure ti conviene passare su un forum di programmazione C#...