Serielle Schnittstelle int data

Hallo an alle,

ich hoffe ihr könnt mir weiterhelfen. Ich bin wirklich am verzweifeln. :confused:

Zu meinem Problem:

Ich schicke den Befehl (1) via Visual Basic an den (Arduino Uno) und dieser schaltet anschließend meinen digitalen Ausgang auch frei. Soweit alles gut. Mit dem Befehl (2) schließt dieser den wieder. Auch das funktioniert alles.

Aber:

Wenn ich statt den befehl (1) sprich den Befehl (11) schicke dann funktioniert das nicht.

Es reagiert nur bei einstelligen Zahlen oder Buchstaben. Ich habe aber mehrere Schaltungen. Das heist ich brauche entsprechend mehrere Befehle.

Hier mal ein Beispiel:

if ((data == '1')){ // möchte hier aber zum Beispiel statt (1) die (11) haben.

digitalWrite(8, HIGH); } if ((data == '2')){ // // möchte hier aber zum Beispiel statt (2) die (22) haben. digitalWrite(8, LOW); }

Vorab schon mal danke an alle die mir einen Tip geben :(

Du musst einfach nur .... Serial.available() ... Serial.read() .... Buffer .... CR/LF ... aber strncmp_P .... oder atoi wenn.... oder strtol ... wenn dann strtok.

Wenn du nicht den ganzen Kode zeigst, zeige ich auch keine ganze Antwort.

Stelle den seriellen Monitor so ein dass ein Linefeed als Endzeichen gesendet wird:

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

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

void loop()
{
  if (readSerial(Serial) == true)
    parseSerial();
}

void parseSerial()
{
  if (strcasecmp(serialBuffer, "test") == 0)
  {
    Serial.println(F("Kommando \"test\" erkannt"));
  }
  else
  {
    int cmd = atoi(serialBuffer);

    switch (cmd)
    {
      case 11:
        Serial.println(F("\"11\""));
        break;
      case 22:
        Serial.println(F("\"11\""));
        break;
      default:
        Serial.println(F("Unbekanntes Kommando"));
    }
  }
}

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

  while (stream.available() > 0)
  {
    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;
}

Du willst den zweiten Teil nach dem else. Aber ich habe der Vollständigkeit halber mal gezeigt wie man Text-Kommandos abfragen kann

Überlege dir aber mal bessere Kommandos. Was z.B. geht ist “8,0” und “8,1”. Oder “8,aus” und “8,an”:

void parseSerial()
{
  int pin = atoi(strtok(serialBuffer, ","));
  int state = atoi(strtok(NULL, ","));

  Serial.print("Pin: "); Serial.println(pin);
  Serial.print("State: "); Serial.println(state);
}

Alles andere bleibt gleich. Man muss nur die Auswertungsfunktion ändern

Dann kann man direkt digitalWrite(pin, state); machen. Eventuell ist aber eine Plausibilitätsüberprüfung sinnvoll.

Was will man mit dem bisherigen Code? Funktioniert sowieso nicht richtig

Aus Deiner Beschreibung geht leider nicht hervor, was Du konkret meinst, wenn Du 1 und 11 schreibst?

eht es um die druckbaren ASCII-Zeichen für ‘1’ oder um das nicht-druckbare Steuerzeichen mit dem Dezimalcode 1 oder 11?

Am besten machst Du Dir für den Arduino erstmal ein Echo-Prorammm das alle Eintreffenden Zeichen als Echo auf den seiellen Monitor sendet.

Probiere diese beiden loop-Funktionen, einmal mit Serial.print und einmal mit Serial.write:

void loop()
{
 byte b=Serial.read();
 if(b>0 &&b<255) Serial.write(b);
}

oder:

void loop()
{
{
  byte b=Serial.read();
  if(b>0 &&b<255) Serial.print(b);
}

Und dann gib mal Bescheid, was der serielle Monitor ausspuckt, wenn Du Deine zwei Zeichen vom PC sendest!

Und zwar per copy-and-paste aus dem seriellen Monitor herauskopiert als Text und NICHT als Screenshot-Bild!

Warum willst du 0xFF und 0x00 einfach unterschlagen?

 if(b>0 &&b<255) Serial.print(b);
void setup() {
  Serial.begin(250000);
}
void loop()
{
  if (Serial.available()) {
    byte got = Serial.read();
    Serial.write('\'');
    if (got < 0x20) {
      Serial.write('\\');
      Serial.write('x');
      if (got < 16) {
        Serial.write('0');
      }
      Serial.print(got, HEX);
      Serial.print(F("' ="));
    } else {
      Serial.write(got);
      Serial.print(F("' = 0x"));
      Serial.print(got, HEX);
    }
    Serial.write(' ');
    Serial.println(got);
  }
}

bei Eingabe von

11
test
'1' = 0x31 49
'1' = 0x31 49
'\x0D' = 13
'\x0A' = 10
't' = 0x74 116
'e' = 0x65 101
's' = 0x73 115
't' = 0x74 116
'\x0D' = 13
'\x0A' = 10

Wieso so kompliziert denken? Wenn er sagt dass einstellige Zahlen gehen und er dann von 11 und 22 spricht sind klar zweistellige Zahlen gemeint

Serenifly: Wieso so kompliziert denken?

Damit der Fragende etwas lernt, oder zumindestens versteht was hinter der Lösung steckt?

Davon dass die meisten eine mehrstellige Zahl via Serial lesen können, gehe ich mal aus.

Whandall: Warum willst du 0xFF und 0x00 einfach unterschlagen? )

Die Werte sind zum Debuggen irrelevant, egal ob er ASCII-Einsen '1' mit Dezimalcode 49 sendet oder Steuerzeichen-Einsen mit Dezimalcode 1 oder Dezimalcode 11.

Woher weisst du was das VB Programm sendet?

Warum willst du zwei gültige Zeichen in einem Echo-Programm unterschlagen? Warum willst du zwei Programme benutzen um zwei Aspekte der gleichen Sache anzuzeigen?

"read() ohne available() in ein byte...", du solltest dich schämen so etwas zu posten.

Hi an alle,

und danke für eure Hilfestellung.

ich schätze das ich mich nicht richtig ausgedrückt habe.

Also folgender Sachverhalt:

Ich habe in Visual Basic mehrere "Button" die verschiedene Befehle ausführen.

Zum Beispiel:

Button.1 schickt den Befehl "1" an den Arduino und aktiviert somit digitalWrite (4, HIGH) Button.2 schickt den Befehl "2" an den Arduino und aktiviert somit digitalWrite (4, LOW)

Bei einstelligen Zahlen funktioniert dies auch. Aber wenn ich jetzt zum Beispiel auf Button.3 den Befehl "11" schicke also sprich zwei stellige Zahlen dann passiert gar nichts.

" sprich keine Reaktion "

Wieso ?

Bermudaor:
und danke für eure Hilfestellung.

Da du die ja offensichtklich nicht verwenden oder beachten willst, wozu war sie gut?

Hi Whandall,

sorry aber ich weis nicht wie ich deinen Code anwenden soll.

So sieht mein Code aus.

void setup() { pinMode(12, OUTPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT);

pinMode(13, OUTPUT);

Serial.begin(9600);

void loop(){

{ if (Serial.available()){

if ((data == '1')){

digitalWrite(8, HIGH); } if ((data == '2')){ digitalWrite(8, LOW); } if ((data == '3')){

digitalWrite(7, HIGH); } if ((data == '4')){ digitalWrite(7, LOW);

} }

Unser Kode sollte dir zeigen, welche Zeichen übertragen werden, wenn du Zeilen (begrenzt mit CR/LF) aus mehreren Zeichen an den Arduino sendest.

Dein Kode ist mehrere Schritte von einer erfolgreichen Übersetzung entfernt.

In den Kode ist nichts eingeflossen was wir angemerkt haben.

Du musst alle Zeichen in einem Puffer sammeln bis die Zeile vollstängig ist, dann kannst du diese Zeile verarbeiten (z.B. die Zahl aus mehreren Zeichen in einen int verwandeln).

Dazu hat dir Serenifly bereits ein vollständiges Beispiel gezeigt.

const byte maxLen = 33;
char Puffer[maxLen];

enum {
  cbLF = 10,
  cbCR = 13,
  cbBlank = ' ',
};

byte pIndex;

void setup() {
  for (byte i = 2; i <= 13; i++) {
    pinMode(i, OUTPUT);
  }
  Serial.begin(250000);
  Serial.println(F("Leds 2 bis 13 steuern:  '2 an' '13 aus' '2an' '4aus'"));
  Serial.println(F("ein Befehl pro Zeile"));
}

void loop() {
  if (Serial.available()) {
    byte zeichen = Serial.read();
    if (zeichen != cbLF) {
      if (zeichen != cbCR) {
        if (pIndex < maxLen - 2) {
          Puffer[pIndex++] = zeichen;
        }
      } else {
        Puffer[pIndex] = 0;
        char* ptr;
        byte val = strtoul(Puffer, &ptr, 0);
        if (2 <= val && val <= 13) {
          while (*ptr == cbBlank) {
            ptr++;
          }
          if (!strcasecmp_P(ptr , PSTR("an"))) {
            digitalWrite(val, HIGH);
          } else if (!strcasecmp_P(ptr , PSTR("aus"))) {
            digitalWrite(val, LOW);
          }
          Serial.print(F("LED "));
          Serial.print(val);
          Serial.print(F(" ist A"));
          Serial.println(digitalRead(val) ? F("N") : F("US"));
        }
        pIndex = 0;
      }
    }
  }
}
Leds 2 bis 13 steuern:  '2 an' '13 aus' '2an' '4aus'
ein Befehl pro Zeile

@Bermudaor: Bitte setz den Code mal in Code-Tags, dann ist es besser lesbar. Dein Code kann so wie er gepostet ist nicht funktionieren, denn nach dem Serial.available() fehlt in dem Block noch mind. ein data = Serial.read().

Dein Grundproblem ist, das Du immer nur Zeichen übertragen kannst. Wenn Du per VisualBasic eine "1" schickst, dann wird nicht die Zahl Eins übertragen, sondern das Zeichen '1'. Du prüfst ja auch in Deinen Abfragen auf dem Arduino auf das Zeichen '1' und nicht auf die Zahl.

Wenn Du nun "11" überträgst, dann sendest Du zwei mal das Zeichen '1' und nicht die Zahl 11. Daher musst Du (vereinfacht ausgedrückt) auch 2 Zeichen einlesen. Das Problem ist natürlich zu erkennen ob jetzt zwei Mal der Befehl '1' gemeint ist, oder einmal der Befehl '11'. Daher trennt man bei solchen Übertagungen die Befehle mit einem Trennzeichen voneinander, damit man weiss wann der eine Befehl aufhört und der nächste anfängt. Was die werten Forumskollegen Dir in ihren Posts sagen wollen ist, das Du das z.B. mit einem Zeilenumbruch/Zeilenende als Trenner machen kannst.

Du kannst es Dir aber einfach machen und z.B. a-z und A-Z als einzelne Zeichen senden, dann hast Du insgesamt 62 verschiedene Möglichkeiten die Du mit je einem einzelnen Zeichen abdecken kannst.

Mario.