Serielle "Telegramme" auswerten

Hallo, ich will folgendes realisieren:

Ich bekomme über Seriell folgende Daten herein:

  • A (Als Buchstabe)
  • B (Als Buchstabe)
  • Werte zwischen 0 und 100%

Wenn ich A empfange, soll Pin7 High und Pin8 Low geschaltet werden,
Wenn ich B empfange, soll Pin7 Low und Pin8 High geschaltet werden.

Der Rest soll auf einem 2x16 LCD Ausgegeben werden, also an sich nur die %, die ich empfange.

Allerdings funktionieren nur die Ausgänge, nicht aber das LCD. Wenn es gut läuft, bekomme ich einen ausgefüllten "Block" auf dem Display oder sonstiges.

Und was noch auftritt: Es werden teils Teile beim Empfangen abgehackt -> aus 1234 wird 234 oder 34, Hallo -> allo oder llo. usw.

#include <LiquidCrystal.h>


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {

  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  lcd.begin(16, 2);

  Serial.begin(9600);
}

void loop() 
{

if(Serial.available())
  {

    delay(100);
  char data = Serial.read();
  if (data == 'A')
     {
     digitalWrite(8, LOW);
     digitalWrite(7, HIGH);

     } 
    else if (data == 'B')
      {
       digitalWrite(7, LOW); 
       digitalWrite(8, HIGH);
      }
     else
     {
      delay(100);
      lcd.write(Serial.read());
     }
  }
}

Hat jemand ne Idee und kann sie mir als Arduino-Neuling gut erklären? Danke

Sorry für Doppelpost, aber anscheinend lässt mich das Forum nicht editieren:

Der obere Code ist der mit "Auswertung".
Hier der ohne Auswertung, der auch funktioniert, bis auf dass der Text teils abgehackt wird:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {

  lcd.begin(16, 2);

  Serial.begin(9600);
}

void loop() {

  if (Serial.available()) {

    delay(100);

    lcd.clear();

    while (Serial.available() > 0) {

      lcd.write(Serial.read());
    }
  }
}

Du musst erst die serielle Schnittstelle komplett auslesen und in einer Variablen speichern, die du anschließend im LCD anzeigst. Wie du das machst, findest du in den Beispielen der IDE.

ich denke in diesem gar nicht so alten Thread findest du ein paar passende Erklärungen
http://forum.arduino.cc/index.php?topic=531112.0

Vor kurzem gab es eine ähnliche Frage hier im Forum.
Vielleicht kann dir das weiterhelfen.
http://forum.arduino.cc/index.php?topic=531112.msg3620579#msg3620579

Wie von HotSystems bereits erwähnt, solltest du das Telegramm bis zum Ende (Zeilenende) auslesen und dann die einzelnen Teile auswerten. Genau das wird beim Beispiel in dem obigen Link gemacht.

Am besten ist es, wenn die einzelnen "Datenpackete" durch ein Trennzeichen unterschieden werden können, zum Beispiel durch Kommas oder irgend ein anderes Zeichen, das nicht in den Daten vorkommt. Das ist vor allem wichtig, wenn die Zeichenlänge des Telegramms unterschiedlich sein kann (in deinem Beispiel besteht Null aus nur einem Zeichen, Hundert aber aus 3 Zeichen).

Eine andere (einfachere) Möglichkeit besteht in einer byteweisen Übertragung. Das ist dann nicht so gut lesabar für uns Menschen, aber besser für Maschinen :slight_smile:

So eine byteweise Übertragung könnte zum Beispie aus nur 3 Bytes bestehen und so aussehen (als Hexwerte):
0x5f 0x32 0x0d
in dezimaler Schreibweise wäre das dann:
95, 50 und Zeilenende

Weil immer (nur) 3 Zeichen übertragen werden, ist die Auswertung also denkbar einfach.

Aber beides (menschenlesbar oder "byteweise" Übertragung) ist möglich und was besser oder einfacher ist, hängt nicht zuletzt von deinen Bedingungen ab.

Edit:
:slight_smile: :slight_smile: für ausführlichere Antworten brauche es mitunter ein wenig mehr Zeit.
Hab dabei sogar selben Thread erwähnt wie noiasca :slight_smile:

Danke schonmal für die Links. Hab sie jetzt nur mal überflogen.

Nun aber eine andere Frage:(Hätte ich evtl auch oben rein schreiben sollen)

Die Daten bekomme ich von einem Server*, der Dateien&Ordner von einem USB-Stick kopiert und folgendes ausgibt:

A => Stick sollte nicht entfernt werden(Schaltet LED)
B => Stick darf entfernt werden(Schaltet LED)
Fortschritt in % Kann je nach Größe schneller oder langsamer die 100% erreichen. Dh Es wird alle 0.5
Sekunden ein anderer %Wert gesendet

Ich will die richtige % Anzeige zeitnah auf dem LCD haben. Nicht dass die LED zum Abziehen aufleuchtet und es noch zB 90% anzeigt

Der Sinn dahinter:

Es sollen Daten von einem USB-Stick auf einen Server kopiert werden. Da dieser allerdings meist unzugänglich ist und ich meine Daten sichern will, auch wenn der Chef nicht da ist.
Also USB-Verlängerung vom Server in Pausenraum gezogen und auf dem Server mein Programm installiert, das die Dateien vollautomatisch kopiert(A), den Fortschritt in % ausgibt und den Stick auswirft(B).

Das nur zur Info.

Ist das möglich oder nicht(Die Arduino Programmierung natürlich, das andere hab ich schon zu 75% gemacht :grinning: )?

Danke

Es ist noch nicht so ganz klar, was über die serielle Schnittstelle geschickt wird.
So wie du es beschreibst stelle ich mir das etwa so vor:
Nachdem der USB-Stick wird eingesteckt wurde kommt über die serielle Schnittstelle etwa folgendes.

A
0
10
20
30
40
50
60
70
80
90
100
B

Wäre das ein "normaler" Ablauf? Die Zahlen könnten natürlich auch andere sein.
Und 'A' bedeutet: USB-Stick keinesfalls entfernen, Kopiervorgang läuft. Eine LED soll leuchten (z.B. ROT).
Und 'B' bedeutet: Kopie ist abgeschlossen, USB-Stick darf entfernt werden. Eine andere LED soll leuchten (z.B. GRÜN).

Oder gibt es einen anderen Ablauf?
Oder noch andere mögliche Nachrichten?

Wenn das etwa so geordnet abläuft lässt sich das relativ leicht realisieren.

Wichtig ist, dass das jedes "Datenpacket" (jede Zeile) ein eindeutiges Endzeichen hat.
Im Beispiel oben wäre es zum Beispiel das "Zeilenend-Zeichen": LF (ASCII 0x0A) oder CR (ASCII 0x0D).
Jede serielle Nachricht wird zuerst bis zum Zeilenende eingelesen, danach erfolgt erst die Auswertung.

Die serielle Datenübertragung ist ziemlich langsam, deshalb muss immer gewartet werden bis alle Zeichen eingetroffen sind.

Wie das funktioniert (Einlesen bis zum Zeilenende, danach erst Auswertung) ist im Link oben (#3 und #4) beschreiben.

Und das soll über nen USB Verlängerungskabel funktionieren?

Hi

Bedenken habe ich wegen der USB-Verlängerung - bei USB 2 war bei 5m Ende - hätte noch nicht gesucht, wie Das mit USB 3 aussieht.
Dann: Da kann JEDER einen USB-Ding anschließen - mit etwas Glück sogar mit den erwarteten Dateien - wenn die kopierten Dateien auf dem Server ausführbar sind, würde ich mir Das noch einige Dutzend Male überlegen wollen - ob ich wirklich ungeprüft fremden Code auf meinem Server haben möchte (wie User-Eingaben, so was muß man parsen).
Wenn's 'nur' irgend welche Daten sind - was passiert, wenn dort falsche Daten hin kopiert werden?
Was, wenn durch diese USB-Verlängerung, ob bösartig oder nicht, Mal mehr als 5V drüber gehen?

Auf der Seite vom Arduino sehe ich keine größeren Probleme, wobei mir noch nicht ganz klar ist, wo der Arduino zu liegen kommt.
Fest am Server verbaut bzw. als eine Art Terminal mit USB-Loch 'Ihren USB-Stick bitte hier', also direkte Verbindung zur Server-Serial-Schnittstelle: Pegelwandler RS323<->TTL und ich sehe gar keine Probleme.
Den Rest, also USB-Stock erkennen, einbinden, Arduino A senden, Kopiervorgang starten, alle halbe Sekunde dem Arduino einen Wert senden, Kopiervorgang beenden, Stick auswerfen, Arduino B senden - muß Dein Script auf dem Server erledigen.

MfG

postmaster-ino:
Bedenken habe ich wegen der USB-Verlängerung - bei USB 2 war bei 5m Ende - hätte noch nicht gesucht, wie Das mit USB 3 aussieht.

Es gibt USB over LAN. Dabei wird das USB-Signal am Anfang verstärkt und am Ende wieder auf den normalen Pegel gesetzt. Einfach ne Cat.7 Leitung gezogen und Stecker drauf gemacht. Funktioniert bei mir auf ca 20m ganz gut, solange ich am Ende einen aktiven Hub setze. Ist gegen Überspannung abgesichert. Habs bereits ausversehen in die falsche Datendose mit PoE gesteckt, funktioniert immernoch.

postmaster-ino:
Dann: Da kann JEDER einen USB-Ding anschließen - mit etwas Glück sogar mit den erwarteten Dateien - wenn die kopierten Dateien auf dem Server ausführbar sind, würde ich mir Das noch einige Dutzend Male überlegen wollen - ob ich wirklich ungeprüft fremden Code auf meinem Server haben möchte (wie User-Eingaben, so was muß man parsen).

Theoretisch ja, praktisch nein. Da ich zb ne Datei mit dem Namen und Endung "USBX.kdp" mit einem Inhalt, der auf jedem der 2 Sticks unterschiedlich ist, damit diese eindeutig identifiziert werden können neben der Seriennummer.
Außerdem wird der USB-Port nur von max 2 Leuten benutzt: Mir und meinem Kollegen, da wir beide KNX programmieren.
8-Mann Betrieb, Firma ist wie Fort Knox - also wenn jemand reingeht und da nen Stick anschließt, ohne dass jemand es mitbekommt, ist sehr sehr gut. oder auch sehr sehr dumm.

postmaster-ino:
Was, wenn durch diese USB-Verlängerung, ob bösartig oder nicht, Mal mehr als 5V drüber gehen?

Vertrau mir, ich bin Elektriker ;D

postmaster-ino:
Den Rest, also USB-Stock erkennen, einbinden, Arduino A senden, Kopiervorgang starten, alle halbe Sekunde dem Arduino einen Wert senden, Kopiervorgang beenden, Stick auswerfen, Arduino B senden - muß Dein Script auf dem Server erledigen.

Das ist mir klar. Der Code schickt dem Arduino jedes %

uxomm:
Es ist noch nicht so ganz klar, was über die serielle Schnittstelle geschickt wird.
So wie du es beschreibst stelle ich mir das etwa so vor:
Nachdem der USB-Stick wird eingesteckt wurde kommt über die serielle Schnittstelle etwa folgendes.

A

0
10
20
30
40
50
60
70
80
90
100
B



Wäre das ein "normaler" Ablauf? Die Zahlen könnten natürlich auch andere sein.
Und 'A' bedeutet: USB-Stick keinesfalls entfernen, Kopiervorgang läuft. Eine LED soll leuchten (z.B. ROT).
Und 'B' bedeutet: Kopie ist abgeschlossen, USB-Stick darf entfernt werden. Eine andere LED soll leuchten (z.B. GRÜN).

So sieht es aus. Wobei logischerweise

A und B nicht als diese angezeigt werden sollen sondern

A = "Fortschritt:" und darunter die % und die Rote LED

und

B = lcd.clear und "Fertig!" und die Grüne LED

uxomm:
Oder gibt es einen anderen Ablauf?

Nein

uxomm:
Oder noch andere mögliche Nachrichten?

Nein.

Sowas in die Richtung? Allerdings bekomm ich wieder einen fast ausgefüllten Block in das Display(█), was ich glaub, das es das "\n" ist. Wie bekomm ich das weg?

while (Serial.available() > 0)
    {
        char recieved = Serial.read();
        inData += recieved; 

        if (recieved == '\n')
        {
            Serial.print("Arduino Received: ");
            Serial.print(inData);
            lcd.print(inData);

            if(inData == "+++\n"){
              Serial.println("OK. Press h for help.");
            }   


            inData = "";
        }
    }

Edit: habs mit trim() gemacht.

Danke

Hi

Hätte jetzt den eingelesenen Inhalt erst dazugeschrieben, wenn's nicht das Zeilenende war.
Du prüfst die Eingabe ja eh erst, wenn Return erkannt wurde, so könntest Du eben solange den String füllen, wenn's kein Return ist und Prüfen, wenn's ein Return war.
Statt Deiner

if (received=='/n'){
...Prüfung...

Wäre der Ablauf ungefähr

if (received!='/n'){
   inData += recieved;
}else{
...Prüfung... nur ohne das /n

Spart auch das Byte für /n im Prüf-String.

Wenn's jetzt aber auch mit trim klappt, würde ich Das erst Ändern, wenn der Platz eng wird (wobei wir hier wohl nur von wenigen Byte reden)

MfG

PS: jaja ... diese Kabelaffen :wink: (keine Angst, böse Zungen behaupten, mir wäre das Gleiche passiert, nur ohne KNX)