Serielle Übertragung mehrerer Werte

Hi,

ich bastel Momentan an einer Bluetooth-Steuerung für einen Quadcopter.

Nun hab ich ein Problem bei der Seriellen Datenübertragung von meinem Smartphone über Bluetooth(HC-05) zum Arduino Uno.

Bewege ich meinen Schubregler langsam auf und ab kommen die Daten Einwandfrei am Arduino an.

Bewege ich den Regler jedoch ein wenig schneller bzw. kommt noch die x und y variable des Controllers hinzu werden die übertragenen Bytes gemischt so das Beispielsweise aus einer

100 und einer 99 dann einer 1009 und eine 9 wird.

Ich habe die Serielle Ausgabe und den Arduino Code angehangen.
Hoffe jemand kann mir bei der Lösung meines Problems helfen.

Du unterschätzt völlig wie langsam Serial ist. Man kann nicht einfach in einer while Schleife hängen und auf einmal alles einlesen. Ein Zeichen dauert 1 / Baudrate * 10 Sekunden!

Weil ich gerade in einem anderen Thread dabei war. Stelle den Serial Monitor (oder dein Sende-Programm auf dem Handy) so ein dass ein LF oder CR am Ende gesendet wird! Sonst geht es nicht

Dann Sende einfach zwei Zahlen die durch ein Komma getrennt sind:
100,200
150,300
etc.

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

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

void loop()
{
  if (readSerial(Serial) == true)
  {
    int x = atoi(strtok(serialBuffer, ","));
    int y = atoi(strtok(NULL, ","));

    Serial.println(x);
    Serial.println(y);
    Serial.println();
  }
}

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

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

    if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c;
    }
    else if ((c == '\n' || c == '\r') && index > 0)
    {
      serialBuffer[index] = '\0';
      index = 0;
      return true;
    }
  }
  return false;
}

Auch in dem Code könnte das while auch ein if sein. Wenn der restliche Code nicht blockiert wird bei jedem Funktionsaufruf bestenfalls nur ein Zeichen eingelesen! Dann ist der Eingangspuffer leer und man muss erst wieder warten bis das nächste Zeichen da ist. In den meisten Fällen kehrt die Funktion sofort wieder zurück weil available() false ist

Hab so gut es geht versucht eine Lösung aus deinen Vorschlägen zu erstellen.
Jedoch bin ich aufgrund meiner Erfahrung mit Arduinos die noch eher sehr gering ist nicht weit gekommen.

Ich bin aber auf eine andere Lösung gekommen.

Ich habe mich auf 4 Zeichen begrenzt d.h für x und y sowie den schub sende ich ein Zeichen zur Identifikation und den momentanen Wert.

[Beispiel]: x140 /dies wird vom Arduino als wert der x Achse erkannt/
s100 /dies wird vom Arduino als wert des Schubs erkannt/

Das ganze arbeitet auf einem Intervall von 140 - 240.
Ob es die schönste und Performance beste Lösung ist bezweifle ich.

Kannst du mir evtl. erklären was du genau meintest mit LF oder CR anhängen?

Kannst du mir evtl. erklären was du genau meintest mit LF oder CR anhängen?

Carriage Return und Line Feed? ASCII Steuerzeichen? Sollte eigentlich bekannt sein. Auch wenn du noch nichts mit Arduino gemacht hast. Das ist sehr universell. Funktionen wie println() oder writeLine() (je nach Programmierumgebung haben die andere Namen) senden beides.

Es geht nur darum dass man das Ende der Übertragung erkennt.

Ich habe mich auf 4 Zeichen begrenzt d.h für x und y sowie den schub sende ich ein Zeichen zur Identifikation und den momentanen Wert.

Das geht auch mit meinem Code:

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

int x, y, s;

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

void loop()
{
  if (readSerial(Serial) == true)
  {
    switch(serialBuffer[0])
    {
      case 'x':
      case 'X':
        Serial.print("x: ");
        x = atoi(serialBuffer + 1);
        Serial.println(x);
        break;
      case 'y':
      case 'Y':
        Serial.print("y: ");
        y = atoi(serialBuffer + 1);
        Serial.println(y);
        break;
      case 's':
      case 'S':
        Serial.print("s: ");
        s = atoi(serialBuffer + 1);
        Serial.println(s);
      break;
      default: 
        Serial.println("unbekanntes Kommando");
    }
  }
}

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

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

    if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c;
    }
    else if ((c == '\n' || c == '\r') && index > 0)
    {
      serialBuffer[index] = '\0';
      index = 0;
      return true;
    }
  }
  return false;
}

An der Einlese-Funktion ändert sich gar nichts. Nur die Auswertung ist anders. Das ist ein großer Vorteil dieser Vorgehensweise. Das Einlesen mit der Auswertung zu vermischen ist dagegen sehr unflexibel.