Go Down

Topic: Über Serielle Schnittstelle Kommazahl einlesen (Read 171 times) previous topic - next topic

dabr_178

Hallo,

ich bekomme über eine Serielle Schnittstelle eine Zahl zwischen 0 und 9999,99 übergeben. Diese Zahl ist zwischen den Zeichen "A" und "E" eingebettet z.B. A1234,56E oder A23,5E
Da ich die Zahlen als Integer/Double brauche war mein Gedanke die Vorkommzeichen und die Nachkommazeichen seperat in ein Array zu schreiben und diese später mit der entsprechenden Multiplikation aufzuadieren.
Ein erster Versuch mit einer ganzen Zahl ohne Komma hat super funktioniert. Doch jetzt bekomme ich für die Nachkommazahlen Werte geliefert, die nicht stimmen.

Hier mein Sketch:
Code: [Select]
#include <SoftwareSerial.h>

SoftwareSerial mySerial(6,7);


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

}

void loop() {
  if (mySerial.available()>0)                 //Abfragen, ob im Puffer seriell Daten empfangen wurden
    {     
      Serial.println("Daten da");
      int bytesAnz=mySerial.available();      //Anzahl der Bytes, die empfangen wurden

      Serial.println(bytesAnz);
     
      while (mySerial.available()>0)        //Die einzelnen Bytes werden in die Variable incomming eingelesen
      {
        char incomming =mySerial.read();      //Typ char, da ASCII Zeichen erwartet werden
       
        if (incomming == 'A')
        {
          Serial.println("A erkannt");
          int zaehlerVorkomma=0, zaehlerNachkomma=0;
          int vorkomma[4], nachkomma[2];
         
          while ((incomming=mySerial.read()) != 'E')
          {
            if (incomming == '.' || incomming == ',') //Nachkomma Zahl erfassen
            {
              Serial.println(",");
              while(incomming=mySerial.read() != 'E')
              {
                int in;
                in=(int)incomming-48;
                nachkomma[zaehlerNachkomma]=in;
                zaehlerNachkomma++;             
                Serial.println(incomming);
              }                   
            if(zaehlerNachkomma==0) {nachkomma[0]=0; nachkomma[1]=0;}
            else if(zaehlerNachkomma==1) {nachkomma[1]=0;}
            break;
            }       
                       
            int in;
            in=(int)incomming-48;
            vorkomma[zaehlerVorkomma]=in;
            Serial.println(in);
            zaehlerVorkomma++;
          }

          Serial.print("NachkommaArray: "); Serial.print(nachkomma[0]); Serial.print("  "); Serial.println(nachkomma[1]);
          Serial.println("Ende");
          //Serial.println(zaehlerVorkomma);
          bytesAnz= bytesAnz- zaehlerVorkomma;

          if (zaehlerVorkomma<=4 && zaehlerNachkomma<=1)
          {         
            eeprom_schreiben(vorkomma,nachkomma, zaehlerVorkomma, 0, 1);
          }
        }         
      }
    }   
}


Es geht hier primär umd die Schritte, die in der "if (incomming == '.' || incomming == ',')" Anweisung stehen. Wenn ich diese weglasse und nur ganze Zahlen empfange funktioniert es. Im Moment bekomme ich immer einen Wert von -47 für die jeweiligen Nachkommazeichen geliefert. Eigentlich habe ich doch genau das gleiche gemacht wie bei der Vorkommazahl..? Habe ich irgendwo einen Denkfehler?

Danke für Eure Hilfe!

Gruß
Daniel

michael_x

mach mal vor
int bytesAnz=mySerial.available();
ein kleines delay(10);  oder so.

Bei 9600 braucht jedes Zeichen 1 ms, und wenn du im ungünstigenn Zeitpunkt
Serial.available() > 0 entdeckst, ist noch längst nicht alles da und deine bytesAnz ist zu klein.

dabr_178

Ich hatte zuerst eine for-Schleife verwendet, die hochzählt bis bytesAnz. Da ist mir aber schon aufgefallen das die Zahl nicht stimmt. Mit einem delay hats gestimmt aber mein Problem trotzdem nicht gelöst :s
Ich habe jetzt eine while Schleife verwendet, dabei können die Zeichen ja noch "eintrudeln" während er schon Teile abarbeitet oder ist das immer noch zu Zeitkritisch?

Serenifly

Am einfachsten ist es immer man liest alles bis zum Endzeichen ein ein char Array und terminiert dieses. Dann hier evtl. das Komma durch einen Punkt ersetzen. Und am Ende mit atof() konvertieren

Quote
Ich habe jetzt eine while Schleife verwendet
Das geht nicht. Die serielle Schnittstelle ist viel zu langsam. Du hast ein Endzeichen. Da braucht man das nicht. Einfach immer nachschauen ob Zeichen da sind. Wenn nicht kann man was anderes tun

Rentner

Hallo,

ich würde alles in einen C-Sting einlesen bis zum E  und dann mit round() und int() weiter um an den gerundeten Integer Wert zu kommnen.

Serial.parseFloat() währe auch noch ein Versuch wert.


Heinz

dabr_178

Am einfachsten ist es immer man liest alles bis zum Endzeichen ein ein char Array und terminiert dieses. Dann hier evtl. das Komma durch einen Punkt ersetzen. Und am Ende mit atof() konvertieren
Das geht nicht. Die serielle Schnittstelle ist viel zu langsam. Du hast ein Endzeichen. Da braucht man das nicht. Einfach immer nachschauen ob Zeichen da sind. Wenn nicht kann man was anderes tun
Ja das mit dem char Array ist natürlich schöner. Da das hier beschriebene Programm später in ein anderes Programm implementiert wird und dort noch andere Werte/ Zustände über die Schnittstelle gesendet und empfangen werden, habe ich mich gegen ein Array entschieden.

Hallo,

ich würde alles in einen C-Sting einlesen bis zum E  und dann mit round() und int() weiter um an den gerundeten Integer Wert zu kommnen.

Serial.parseFloat() währe auch noch ein Versuch wert.


Heinz
Ich hätte ja schon gerne am Ende eine double Variable.



Ich habe jetzt direkt nach dem ersten Schritt
Code: [Select]
if (mySerial.available()>0)
 ein delay von 100ms eingebaut. Damit müssen auf jeden Fall alle Zeichen empfangen sein aber das Problem ist immer noch da...

dabr_178

Ich habe das Problem gelöst. Es haben zwei Klammern bei der zweiten While Schleife im Argument gefehlt.

Code: [Select]
while (incomming=mySerial.read() != 'E') //FALSCH Klammer fehlt
while ((incomming=mySerial.read()) != 'E') //RICHTIG

Go Up