Go Down

Topic: Begriff mit Wert über Serial senden/empfangen (Read 3093 times) previous topic - next topic

stef308

Hallo

Ich habe eine kleine Frage. Wenn ich über Serial einen Wert mit Definitionszuteilung, z.B. LED1 = 55 senden und empfangen möchte, also, dass LED1 und 55 gesendet wird und dann wieder beim Empfangsarduino zu LED1 = 55 zusammengesetzt wird, kann ich das so erfolgreich durchführen?
Zu Testzwecken habe ich die Werte mal fix als int definiert. Das ist im richtigen Sketch dann eine Werteauslesung eines Joysticks zum Beispiel.

Sender:
Code: [Select]
int wert = 1023;
int wert2 = 825;

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

}

void loop() {
  Serial.print("einsTx,");
  Serial.print(wert);
  Serial.println(",");

  Serial.print("zweiTx,");
  Serial.print(wert2);
  Serial.println(",");

}


Empfänger:
Code: [Select]
int eins = 0;
int zwei = 0;
char var;
enum {einsTx, zweiTx};

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

}

void loop() {
  while (Serial.available() > 0){
    var = Serial.read();
    switch (var){
      case einsTx : eins = Serial.parseInt();
                    break;
      case zweiTx : zwei = Serial.parseInt();
                    break;
    }
  }
}


Ich hab momentan keinen Arduino mehr um das zu testen, möchte aber gerne den Sketch dafür schonmal schreiben. Kann mir da vielleicht jemand helfen das zu prüfen?

Wo ich mir auch nicht mehr ganz sicher bin, in der "while" Bedingung das > 0, das sagt nur aus, dass mehr Werte als "kein Wert" gesendet werden muss, damit die Bedingung wahr ist und durchlaufen wird, oder?

Grüsse

Stef

combie

Ich benutze, solange keine KO Kriterien dagegen sprechen, gerne den CmdMessenger für solche Zwecke.

Bis deine Arduinos eintreffen, kannste dir den ja schon mal anschauen.
Säge kein Sägemehl.

SkobyMobil

Hallo,
und funktioniert es, wenn Du es mit einem Mega<->UNO auswertest?
Gruß und Spaß
Andreas
die zweite Maus bekommt den Speck...

stef308

So, habs mit zwei älteren UNOs die ich gefunden habe versucht. Ich bekomme aber irgendwie keine Daten empfangen. Ich seh auch nicht, wo der Fehler liegen könnte. Die Ausgabe bleibt "eins = 0" und "zwei = 0" wie am Anfang definiert. Sieht einer mehr wie ich?

combie

#4
Jan 31, 2019, 03:41 pm Last Edit: Jan 31, 2019, 03:42 pm by combie
Bei UNOs wird die Serielle schon benutzt, um mit dem PC quatschen zu können.
Die Seriele ist kein Bus.
2 Partner, keine 3

Also:
Verwende SoftwareSerial, wenn 2 UNOs miteinander quatschen sollen.
Alternativ: I2C, SPI
Säge kein Sägemehl.

stef308

Stimmt schon, aber der Arduino welcher nur Empfängt ist mit dem PC verbunden und sendet dem PC die Ausgabe Serial.print. Hat so schon immer funktioniert.... Ich denke eher das das "enum" macht Probleme. Kennt sich da jemand näher mit aus? Oder anders gefragt, wenn ich wie oben "einsTx" und den Zahlenwert sende, wie kann ich "einsTX" als ganzer Begriff unter var speichern. Hab das bis jetzt immer nur mit einzelnen Buchstaben gemacht, und dann funktioniert es.
Auch weiss ich noch nicht, wie man z.B. bei mehreren Werten die gesendet werden, erst ab dem 4. Byte auslesen kann und den rest ignoriert? Wenn z.B. 12 bytes gesendet werden, ich aber nur von Byte 4 bis 10 haben möchte, dass das wie im obigen Beispiel eingeordnet wird, was muss ich da machen?

combie

#6
Jan 31, 2019, 04:11 pm Last Edit: Jan 31, 2019, 04:13 pm by combie
Die Serielle sendet "Symbole".
Meist um die 10 Symbole, pro Frame.
Ebenso "meist" wird daraus eine 8Bit Dateneinheit gebaut, welche dir dann von Serial.read() überreicht wird.


Allgemein, wenn 2 µC seriell mit einander quatschen sollen:
Dann muss der eine die Daten so senden, dass der andere in der Lage ist, die übertragenen Daten richtig zu interpretieren.
Stichworte: Datenformat, Datentype, Struktur, Parser

Natürlich kannst du das selber bauen.
Ist sehr lehrreich!
Nur wirst du dir dafür einiges an Grundlagen erarbeiten dürfen.
z.B. könntest du dir eins von den 1000 seitigen C++ Büchern anschaffen.

Die Alternative wäre:
Was schon fertiges benutzen.

Übrigens:
Deine Beispiele sagen mir nicht, was du jetzt wirklich übertragen möchtest...






Säge kein Sägemehl.

stef308

Im Endeffekt will ich mit zwei Xbees Daten senden und empfangen. Um die Grundlage mal zum laufen zu bringen, wollte ich mal einfach ein Wort mit einer Zahl über Serial senden und empfangen. Das senden klappt mit dem Sketch im ersten Beitrag gut. Das Empfangen jedoch macht noch Schwierigkeiten, da die empfangenen Daten nicht in die Switch/Case Anwendung finden. Ich vermute es liegt an der enum Definition. In den Cases dürfen ja theoretisch keine Wörter stehen. Ich habe es bisher auch nur mit Zahlen oder Buchstaben gemacht, was auch funktioniert. Der Verständlichekeit halber was gesendet wird, wollte ich aber ein Wort und Zahl übermitteln. Gibt es da eine Möglichkeit im Case ein Wort wie im Beispiel "einsTX" zu definieren, dass das von der Switchanweisung erkannt wird?

Als nächster Schritt, habe ich herausgefunden, dass die Xbees ein Datenpaket senden und empfangen. Das 4.Byte würde ich so definieren, dass mir das Xbee eine Anfrage an das zweite Xbee sendet, ob die Daten gesendet werden können, sobald die Daten übermittelt wurden, sendet das zweite Xbee eine Rückmeldung, dass die Daten empfangen wurden. Meine Daten die ich senden will, stehen dann scheinbar vom 9.Byte bis zum vorletzten Byte. Diese muss ich dann natürlich auslesen, den Rest der mitgesendet wird brauche ich ja nicht.

combie

#8
Jan 31, 2019, 05:03 pm Last Edit: Jan 31, 2019, 05:04 pm by combie
So...
Senden ist also kein Problem...

Nur das Empfangen..

Darf ich dich mal fragen, ob du, z.B. das Wort "Parser", absichtlich ignoriert hast?

Tipp:
Ein paar einfache Parser sind schon im Lieferumfang der Arduino IDE dabei.
Beispielsweise:
  • sscanf()
  • Die String Klasse
  • Auch Serial hat da schon was im Bauch
Säge kein Sägemehl.

SkobyMobil

Hallo Stef,
irgentwie ist das alles wirrs Zeug´s was Du hier, u.a. w. lieferst.
Baue doch einmal ein vernünftiges Grundgerüst auf, z.B.:

Auf dem Uno installierst Du SoftwareSerial.
Dann schreibst Du einen Sketch, der genau das als Beispiel sendet, was Du später für Dein Projekt benötigst.

z.B. so:
 Serial.print("eins Tx");
Serial.print(" ");
  Serial.print(47.11);

Mit delay läßt Du dem das alle 2sek senden.



Jetzt nimmst Du Deinen Mega, verbindest ihn mit dem PC und dem Uno.
Mega<->USB-PC
Mega Tx1/Rx1 <-> UNO<->SoftwareSerial-Pin RxTx.

So kann der UNO immer etwas an den Mega senden. Der Mega empfängt es und gibt es an den PC weiter.
Den EmpfängerSketch kannst Du jetzt jederzeit bequem in der IDE ändern.
Wenn das funktioniert, dann hast Du doch schon einen Empfänger/SendeSketch für Deine Arduino.
Gruß und Spaß
Andreas
 
die zweite Maus bekommt den Speck...

stef308

@combie: Hab was mit substring versucht, aber irgendwie gibt er nicht das aus was ich will. Muss mal schauen, ob ich das irgendwie hinbekomme, hab da (noch) nicht so viel Ahnung von.

@ Andreas: Das Beispiel vom ersten Post läuft ohne Probleme, einfach mit Buchstaben statt Wörtern. Das Problem ist, dass ich im API Modus mit den Xbee das Packet was gesendet werden soll selbst zusammenstellen muss. Das kann ich nicht einfach so von null auf hundert aus dem Ärmel schütteln. Ich mach da Stück für Stück bis ans Ziel. Ich muss die empfangenen Daten dann ja irgendwie auswerten, da kommen ja ein paar Werte vor und nach meinen gesendeten Daten, die ich da auch noch generieren muss irgendwie. Ich weiss nicht mal, ob ich das alles hinbekomme - ist totales Neuland für mich. Sonst bleib ich beim andauernden Senden ohne Unterbruch und sobald keine Daten mehr kommen weiss ich auch, dass die Verbindung weg ist. Wäre halt nicht so elegant gelöst und braucht unnötig Strom, resp. strahlt die ganze Zeit.

Tommy56

Der Anwendungszweck ist zwar ein anderer, aber die Kombination aus Kennbuchstaben und Wert ist ähnlich. Schau Dir doch mal dieses Beispiel an (ganzen Thread lesen).


Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

SkobyMobil

#12
Feb 01, 2019, 12:58 am Last Edit: Feb 01, 2019, 01:03 am by SkobyMobil
Hallo Stef,

"Das Problem ist, dass ich im API Modus mit den Xbee das Packet was gesendet werden soll"

Vergesse doch einmal diesen dämlichen API-Modus.
Konfiguriere die XBee im API-Modus richtig und gut ist!

Nun baust Du Dir Dein System so auf wie beschrieben. Nur die Kabel UNO-Rx/Tx <-> Mega-Tx/Rx
tauscht Du gegen Deine XBee aus.

Dann schreibst Du für den UNO einen Sketch der nichts weiter macht, als ein "Hallo" sendet.
Eben einen NUR "X-Text" senden.
Auf dem Mega schreibst Du Dir nun einen Sketch der, nur- diesen X-Text ausgibt.
Wenn Du das begriffen und hinbekommen hast, dann sendest Du mit dem UNO einen Wert.
z.B.
int A = 4711;
float B = 47.11;
Auf dem Mega schreibst Du Dir nun einen Sketch der, nur- diesen A-Wert und B-Wert ausgibt.

Wenn Du das begriffen und hinbekommen hast, dann solltest Du wissen, wie die serielle
Kommunikation mit dem Arduino funktionieren könnte.

So, nun kannst Du Text und Werte mit dem Arduino/XBee senden und empfangen.
Jetzt ist es an der Zeit die Sketche "Senden" & "Empfangen" hier ins Forum zu bringen.

Nun können sich die "Profis" um Deine Bit&Byte schieberei kümmern.

Wenn es nun geschafft ist, Dein 4. und 9. Byte zu selektieren, dann kannst Du Dich um das
"parse" kümmern.

Ich weiß, das hier ist alles nur palaber, rababer FrittenBude- aber die serielle Kommunikation
mit dem Arduino ist nicht ohne!

Ist ja schön das Tommy Dir einen RGB-Sketch zur Verfügung stellt, aber für Dich nicht zu
gebrauchen.
Bei Ihm leuchten RGB-Lampen, bei Dir glimmpt aber noch nicht einmal ein Glühbirne.


"selbst zusammenstellen muss. Das kann ich nicht einfach so von null auf hundert aus dem Ärmel

schütteln."

Das sagt mir, das Du noch nicht einmal weißt, was denn genau gesendet/empfangen werden soll.
D.h. hier spielen alle nur "Rate mal mit Rosenthal".

Also Stef, liefer mal vernünftiges Material, dann geht es hier auch weiter.
Gruß und Spaß
Andreas

P.S. etwas "leichtes"
die zweite Maus bekommt den Speck...

combie

Hab was mit substring versucht, aber irgendwie gibt er nicht das aus was ich will.
"Versuchen" hört sich irgendwie nach unkoordiniertem rumprobieren an.
Das ist meist wenig sinnbehaftet.
Denn, selbst wenn es dann tut, weißt du immer noch nicht "warum".


Muss mal schauen, ob ich das irgendwie hinbekomme, hab da (noch) nicht so viel Ahnung von.
Das mit der "Ahnung" kannst nur du ändern.
Wie kann ich dir dabei helfen?
(das 1000 seitige Buch, hatte ich schon genannt, oder?)

Nebenbei:
Das "keine Ahnung", oder so, musst du nicht sagen.
Denn erstens, merke ich das. Da brauche ich keinen extra Hinweis.

Und zweitens, was noch viel wichtiger ist:
Je öfter man Dinge wiederholt, desto fester setzen sie sich.
Desto mehr stabilisiert sich der Zustand, weil man um so fester selber dran glaubt.

"Ich habe keine Ahnung" ist also eher ein böses Mantra.

Besser:
"Ich lerne das!"
Säge kein Sägemehl.

stef308

Also, mal vorweg: Ich weiss was ich brauche, aber es spielt überhaupt keine Rolle, ob der Sketch nun einen Wert von nur 1 oder 1023 senden muss. Ich habe am Anfang irgendwo erwähnt, dass ich Taster (LOW, HIGH, also 0 und 1) und Joysticks (Werte von 0 bis 1023) verwenden will die die Werte an einen anderen Arduino senden.
Ich habe den einfachen Sketch wo ich einfach alle Werte am Ende der Loop mit Serial.write nacheinander sende und beim Empfänger in ein Array ornde und somit in der gleichen Reihenfolge wieder empfange. Jetzt habe ich mal den Sketch vom Anfang mit Buchstaben im "case" geändert, anstatt mit Wörtern. Jetzt klappt das Senden und Empfangen, von "bestimmten" und nicht allen Werten erfolgreich, und werden mit der switch/case auch wieder erfolgreich einsortiert. Das Funktioniert aber nur mit Zahlen und Buchstaben. Theoretisch habe ich gelesen, dass es auch mit HEX Werten gehen soll, aber wenn ich z.B. unter

Code: [Select]
case 0x7E:

schreibe, anstatt

Code: [Select]
case 'A':

, dann empfängt er diesen Teil wo eigentlich nach dem 0x7E kommt nicht. Hier ist der funktionierende Sketch mit Switch/Case:

Sender:

Code: [Select]
int wert = 1023;
int wert2 = 825;

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

}

void loop() {
  Serial.print("A,");
  Serial.print(wert);
  Serial.println(",");
  Serial.flush();

  Serial.print("B,");
  Serial.print(wert2);
  Serial.println(",");
  Serial.flush();

}


Empfänger:

Code: [Select]
int eins = 0;
int zwei = 0;
char var;

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

}

void loop() {
  while(Serial.available() > 0){
    var = Serial.read();
    switch (var){
      case 'A' : eins = Serial.parseInt();
                    break;
      case 'B' : zwei = Serial.parseInt();
                    break;
    }
  }
Serial.print("eins =");
Serial.println(eins);
Serial.print("zwei =");
Serial.println(zwei);
 
}



Jetzt habe ich mal versucht ein Beispiel zu verstehen und habe es ein wenig angepasst und meiner Meinung nach fehlende Teile ergänzt. Mit diesem Sketch und dem Parser strtok empfange ich mal die gesendeten z.B. 7E als Dezimalwert 126 oder 89 als 137. Das Problem hier ist noch, dass ich die Werte nicht alle erhalte, meistens nur die ersten fünf bis zum A (A auch als Dezimalwert = 10) und mit der Zeit stimmt die Reihenfolge, resp. auch die Werte die in die Arrays gehen nicht mehr mit dem gesendeten überein. Ich sehe da nur ein "Problem", dass die if Bedingung im readSerial() wohl einen Fehler haben muss und die empfangenen Daten nicht richtig speichert, resp. zu früh oder spät überschreibt. Hier mal den Sketch den ich versucht habe zu verstehen und anzupassen:

Sender:

Code: [Select]
int wert = 1023;
int wert2 = 825;

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

}

void loop() {
  Serial.print("7E");
  Serial.print(',');
  Serial.print("89");
  Serial.print(',');
  Serial.print("00");
  Serial.print(',');
  Serial.print("01");
  Serial.print(',');
  Serial.print("A,");
  Serial.print(wert);
  Serial.print(',');

  Serial.print("B,");
  Serial.print(wert2);
  Serial.println(';');
  Serial.flush();

}


Empfänger:

Code: [Select]

const int SERIAL_BUFFER_SIZE = 20; //Speicher für 20 gesendete Werte
char serialBuffer[SERIAL_BUFFER_SIZE]; //Array serialBuffer

byte key[8]; //Array key mit 8 Elementen

int arraySize = sizeof(key)/sizeof(key[0]); //Anzahl Elemente im Array key

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

void loop()
{
  if (readSerial())
  {
    parseSerial();

    for (int i = 0; i < arraySize; i++){ //wenn i kleiner als Anzahl Elemente im Array key, i+1...
      Serial.print("key ");
      Serial.print(i);
      Serial.print(" = ");
      Serial.println(key[i]); //zeige Array i
      Serial.println();
  }
  }
}

bool readSerial()
{
  static byte index;

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

    if (c >= 1 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c; //Array serialBuffer [index +1] gleich gelesene Daten c
    }
    else if (c == '\n') //wenn c gleich "Ende der Daten" erkannt...
    {
      serialBuffer[index] = '\0'; //Array auf null zurücksetzen
      index = 0;
      return true; //Daten wurden gelesen
    }
  }
  return false; //Daten wurden noch nicht gelesen
}

void parseSerial()
{
  char* ptr = strtok(serialBuffer, ","); //separiert gelesenen String serialBuffer bis zum , und speichert es in ptr

  for (int i = 0; i < arraySize; i++) //für i kleiner als Anzahl Elemente im Array key, i+1...
  {
    key[i] = strtoul(ptr, NULL, 16); //Array key[i] gleich separierter String ptr, Startpunkt, Anzahl Zahlen/Buchstaben die im String gelesen werden ('0x' für HEX)
    ptr = strtok(NULL, ","); //separiert nächsten Abschnitt im String bis zum ,
  }
}


Hier ist noch der Punkt unter strtoul(ptr, NULL, 16) nicht ganz klar. Der Wert 16 habe ich wo gelesen, soll die Anzahl der Zahlen/Buchstaben im String sein, die ins Array gehen. Kann aber nicht sein, da wenn ich diesen Wert nach unten oder oben ändere, nur noch Müll empfangen wird.
Ich hoffe ich bin nicht ganz auf dem Holzweg, aber ich denke ich komme der Sache schon näher und so könnte es klappen.


Zu den API Problemen die ich habe/hatte... Ich habe erfahren/gelesen, dass das Xbee das Datenpaket genau in dieser bestimmten Reihenfolge gesendet bekommen muss. Das hat mich irgendwie bisschen irritiert. Darum muss ich am Ende ja auch die empfangenen Werte aufteilen, um den für mich wichtigen Teil zu entnehmen und eine Rückmeldung zu senden.
Mittlerweile verstehe ich selbst nicht mehr was unten und oben ist. Wenn die Xbees auch nur fragen, ob die Daten gesendet werden können und das Empfänger-Xbee sagt ja und empfängt die Daten, dann muss ja eine Verbindung bestehen. Wenn es nicht gesendet werden kann, dann kann das Empfänger-Xbee doch auch nichts mehr empfangen, sprich keine Rückmeldung geben.
Der Sinn wäre ja darin, dass wenn das Sendemodul ausser Reichweite ist, beim Empfänger aber durch kurz vor dem Verbindungsabbruch Befehle empfangen wurden und nun ausgeführt werden, z.B. Motoren läufen, Licht ist an, ect. (ferngesteuertes Auto), dann muss ja der Empfänger das irgendwie bemerken und alles stoppen, resp. ausschalten. Irgendwie war mir das mit den Xbees klar geworden, aber momentan zweifle ich daran, dass das so überhaupt funktioniert  ::)

Das Beste für heute wird sein, mal eine Pause zu machen und den Kopf frei zu kriegen.

Grüsse

Stef

Go Up