Serielle Kommunikation

Hey Leute,
Ich wühle seit na Zeit durchs Internet und durch das Forum hier, aber finde nichts vergleichbares.

Ich hab folgendes Problem:

Wenn ich eine serielle Kommunikation schreib, wo ich via dem Seriellen Monitor von der ArduinoIDE direkt Integer an den Arduino schicken will, dann gibt er mir immer zurück das er Nummer 13 empfangen hat.

Ich hab verschiedene Arduinos getestet (nano, uno und jetzt Mega) aber immer das gleiche.

#include <LiquidCrystal.h>

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

void setup() {
  lcd.begin(16, 2);
  lcd.print(“COM-Port:”);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()>0) {
      var = Serial.read();
      lcd.setCursor(0, 1);
      lcd.print(var);
    }
}

In dem Beispiel hab ich einen LCD (der Funktioniert ohne Probleme) und will mit diesem anzeigen was er über die serielle Schnittstelle bekommt… aber da kommt au immer nur 13 oder wenn ich n Buchstaben rein gib, dann nen Wert zwischen 130 und 134…

Bin echt ratlos…

Hättet ihr vllt n Tipp woran der Fehler liegen kann?

Das nennt sich ASCII. Du musst das nur richtig interpretieren und die richtigen Datentypen verwenden:
http://www.asciitable.com/

Das Problem ist aber nicht das, sondern aus den einzelnen Ziffern oder Zeichen ganze Strings und Zahlen zu basteln. Am allgemeinsten geht es wenn du den seriellen Monitor so einstellst dass am Ende ein LF/Linefeed gesendet wird. Damit kann man das Ende der Übertragung erkennen. Dann liest du alles in einen C String ein. Diesen kannst du dann bearbeiten wie du willst. Du kannst die Daten direkt als Text ausgeben. Oder mit Konvertierungsfunktionen in Zahlen umwandeln.

const int SERIAL_BUFFER_SIZE = 10;
char serialBuffer[SERIAL_BUFFER_SIZE];

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

void loop()
{
  if (readSerial(Serial))      //liefert true wenn das LF eingelesen wurde
  {
    Serial.println(serialBuffer);
  }
}


bool readSerial(Stream& stream)
{
  static byte index;

  while (stream.available())
  {
    char c = stream.read();

    if (c == '\n' && index > 0)       //wenn LF oder CR eingelesen und String länger als 0 ist
    {
      serialBuffer[index] = '\0';     //String terminieren
      index = 0;
      return true;                    //melden dass String fertig eingelesen wurde
    }
    else if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)   //solange noch Platz im Puffer ist
    {
      serialBuffer[index++] = c;    //Zeichen abspeichern und Index inkrementieren
    }
  }
  return false;        //noch nicht fertig
}

Nicht von der while-Schleife verwirren lassen. Normal ist Serial so langsam dass zwischen den Zeichen eine lange Zeit vergeht! Und die Schleife wird nur einmal durchlaufen. Deshalb muss man die Funktion immer wieder aufrufen. Das ist auch ein sehr beliebter Anfängerfehler.

Das gibt den empfangenen Text einfach direkt aus. Wenn man die Werte wirklich als Integer braucht reicht einfach das:

void loop()
{
  if (readSerial(Serial))
  {
    int value = atoi(serialBuffer);
    Serial.println(value);
  }
}

atoi() = ascii to integer. Genauso gibt es auch Konvertierungsfunktionen für andere Datentypen. Oder auch um Hex-Strings einzulesen

Rein für positive Zahlen geht auch das:

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

void loop()
{
  int value = readSerial(Serial);
  if (value > 0)
  {
    Serial.print("read: "); 
    Serial.println(value);
  }
}

int readSerial(Stream& stream)
{
  static int value;
  
  while (stream.available())
  {
    char c = stream.read();

    if (c == '\n')
    {
      int tmp = value;
      value = 0;
      return tmp;
    }
    else if (c >= '0' && c <= '9')
    {
      value *= 10;
      value += c - '0';
    }
  }
  
  return -1;
}

Da werden die Ziffern einfach aufaddiert

13 ist das CR Das letzte Zeichen in deinem String.

Immer. Und das ist soweit auch erstmal völlig korrekt so

combie: 13 ist das CR Das letzte Zeichen in deinem String.

Immer. Und das ist soweit auch erstmal völlig korrekt so

Wobei ich das Linefeed als Endzeichen bevorzuge. Dann kann man auch CR + LF genauso handhaben indem man das CR einliest und einfach ignoriert.

Prinzipiell ist aber natürlich auch CR möglich. Das wird bei ihm im Monitor halt so eingestellt sein.

Also ich bin gerade dabei das Beispiel von Serenifly nachzuvollziehen, aber reines Kopieren des Quellcodes bringt bei mir keinerlei Reaktion, jetzt habe ich zu Testzwecken mal das arduino Beispielsketch "Dimmer" ausprobiert und selbst da kommt nichts. Die LED leuchtet immer als würde man das PWM-Signal auf 13 stellen. Sollte das nicht Problemlos funktionieren oder übersehe ich gerade was ganz grob?

Hast du den seriellen Monitor so eingestellt dass am Ende ein LF/Linefeed/Newline gesendet wird? Wahrscheinlich nicht. Bei dir scheint das auf CR zu stehen. Du brauchst wie gesagt ein definiertes Endzeichen. Und ich nehme das LF weil man dann auch CR + LF ohne Umwege behandeln kann. Das hat aber zur Folge, dass CR alleine nicht geht.

Siehe unten rechts neben der Baudrate.

Wenn das nicht geht hast du irgendein Hardware Problem

Habe es mit allen Einstellungen ("Kein Zeilenende", "Neue Zeile", "Zeilenumbruch (CR)", "Sowohl NL als auch CR") probiert... Baud-Rate stimmt auch überein, aber das Beispiel funktioniert nicht.

Das wird bei ihm im Monitor halt so eingestellt sein.

Ja. Sehe ich aber nicht als Problem an, auch wenn ich andere Vorlieben habe.

dann nen Wert zwischen 130 und 134...

Das Problem ist, dass er immer seine Werte überschreibt.

Wenn da z.B. 114 steht, wirds mit 13 überschreiben und 134 steht dann da. Weil das letzte Zeichen noch vom vorherigen Byte da stehen bleibt.

Ich kann nur sagen dass es bei mir geht. Code in der Art habe ich schon zig fach verwendet. Die Funktion geht nicht für serielle Übertragung sondern z.B. auch unverändert um Text von SD Karten einzulesen

Auch die Version rein für Zahlen ohne erst mal den Text abzuspeichern habe ich getestet

Das Problem ist, dass er immer seine Werte überschreibt.

Ja. Bei LCDs muss man das natürlich auf eine konstante Breite formatieren und den Rest mit Leerzeichen überschreiben. Das geht sowohl mit Integern als auch mit Strings

Im Moment scheint er aber erst mal grundlegendere Probleme zu haben.

In das Beispiel "Dimmer" habe ich noch dazugeschrieben das er mir den Seriellen Wert ausgeben soll am Monitor, dann gibt er folgendes aus: Eingabe: 120 Ausgabe:

"49 48 48 13"

ist das möglich, das irgendwas mit dem COM-Port Einstellungen falsch ist?

---EDIT------------------------------------

Serenifly, deine Beispiele funktionieren jetzt auf einmal doch! Vielen Dank, aber das Problem mit dem Beispiel von Arduino selbst bleibt ("Dimmer")

Bei 120 + CR kommt folgendes raus:

49 50 48 13

Siehe http://www.asciitable.com/

Wenn du das in einen char statt einen int schreiben würdest dann hast du auch direkt die ASCII Zeichen. Das ist wie gesagt nur eine Interpretationssache. Du musst halt entweder die Zeichen in einen C String schreiben (d.h. ein Null-terminiertes char Array) oder direkt aufaddieren

EDIT: Das Dimmer Beispiel ist ziemlich sinnfrei. Sollte so eigentlich nicht in der IDE sein. Damit verwirrt man Anfänger nur

Ah ok, ja wenn ich mit deinen Beispielen oben arbeite, komme ich auch zu Ergebnissen,

VIELEN DANK EUCH BEIDEN