Datenaustausch über die Serielle Schnittstelle String zerlegen ,zusammensetzen

Hallochen

ich möchte gerne Daten von einem zum anderen Arduino über die Serielle Schnittstelle Senden und Enpfangen da meine Zahlenwerte größer als 255 sind muss ich zwei bytes senden

habe folgende überlegung

Sender:

char Senderdaten []={A234,B567};

Serial.write (Senderdaten[0]);
delay (100);
Serial.write (Senderdaten[1];

[\code]


Empfänger :
[code]


char Senderdaten[]={0,0};
if Serial.available(){

if (Serial.read () ==A){

Senderdaten[0]=Serial.read();
}

if ( Serial.read()==B){
Senderdaten[1] = Serial.read();
}
}

[\code]

und dann möchte ich die daten wieder zusammen fügen so das ich beim Empfänger 

die Zahl 234567 erhalte 

vl hat da jemand einen Link für mich wie man sowas macht hatte bei meiner Suche keinen Erfolg

write kann mehrere Bytes schicken. Schaue Dir mal struct an, um mehrere Werte zu einer Einheit zusammen zu fassen.

Gruß Tommy

basteldin:
ich möchte gerne Daten von einem zum anderen Arduino über die Serielle Schnittstelle Senden und Enpfangen ...

Wenn die Arduinos nicht zu weit von einander entfernt sind, könntest Du auch I2C als Schnittstelle verwenden. Bei UNOs und dergleichen bleibt dann die serielle für USB frei.

Beispiel ohne struct für SoftwareSerial: Telemetrie für ein Dampfschiff

char Senderdaten []={A234,B567};

Das ist leider Unsinn.

Meinst du eventuell const char* Senderdaten[] = {"A234", "B567"};     ?

Oder willst du statt 8 Buchstaben einfach nur 2 Byte übertragen? ( Was auch nicht reicht für 234567 )

Du solltest auch den Unterschied zwischen A , 'A' und "A" erkennen können, wenn du dich an solche Aufgaben wagst.

Uder dir entweder

union  { long i; byte b[4]; } data;
data.i = 234567;
 
Serial.write(data.b, 4);

Oder Zeiger-Hexereien ansehen.

An der Empfängerseite hast du dann evtl. auch noch ein bisschen zu knobeln.
Oder ist dir klar, wann die Übertragung zu Ende ist? (sind es immer 3 Ziffern nach einem Buchstaben?)

Also die Buchstaben habe ich nur gedacht um die ankommende Zahl am Empfänger zu identifizieren war mir klar das das Unsinn ist war nur eine Überlegung

der Unterschied zwischen 'A' und "A" ist das 'A' ASCI ist oder ?

also Buchstaben brauche ich eigentlich garnicht ich möchte nur große Zahlen übertragen und lernen wie das geht

Und ja für die Zahl 456 Dezimal bräuchte ich 2 Byte da sie größer als 255 ist ....?

Hi

Wenn Du die zu übertragende Variable als INT declarierst, werden 'von Haus aus' zwei Byte übertragen, da INT beim Arduino eben zwei Byte lang ist (-32tausendbatsch bis 32tausendbatsch, oder ohne Vorzeichen 0-65535).
'A' = 1 Zeichen
"A" = irgend eine Schweinerei, eine Erklärung kommt bestimmt und war die Tage bereits hier im Forum, hab's aber vergessen
"AB" = ein String, da mehr als ein Zeichen -> in Gänsefüßchen

Was stellen diese Zahlen dar, Die Du übertragen willst?

MfG

Da wollen wir Deinem Gedächtnis mal auf die Sprünge helfen: "A" ist auch eine Zeichenkette, bestehend aus 'A' und '\0'. Ich verwende bewußt das Wort String nicht, um nicht zur Verwechslung mit der Klasse String beizutragen.

Gruß Tommy

postmaster-ino:
"A" = irgend eine Schweinerei, eine Erklärung kommt bestimmt und war die Tage bereits hier im Forum, hab's aber vergessen
"AB" = ein String, da mehr als ein Zeichen -> in Gänsefüßchen

"A" = 'A' \0 = das Zeichen und die Zeilenendekennung, zusammen zwei Bytes, eine Zeichenkette!
"AB" = 'A' 'B' \0 = zwei Zeichen und die Zeilenendekennung, zusammen drei Bytes, eine Zeichenkette!

Tommy war schneller :slight_smile:

postmaster-ino:
Wenn Du die zu übertragende Variable als INT declarierst, werden 'von Haus aus' zwei Byte übertragen, da INT beim Arduino eben zwei Byte lang ist

Nicht wenn du stur nur write() machst. Schau dir die HardwareSerial Klasse an:

    inline size_t write(unsigned long n) { return write((uint8_t)n); }
    inline size_t write(long n) { return write((uint8_t)n); }
    inline size_t write(unsigned int n) { return write((uint8_t)n); }
    inline size_t write(int n) { return write((uint8_t)n); }

Man kann mit write() entweder ein Byte oder ein Array übertragen. Deshalb die Sache mit der Union

basteldin:
Buchstaben brauche ich eigentlich garnicht ich möchte nur große Zahlen übertragen und lernen wie das geht

Und ja für die Zahl 456 Dezimal bräuchte ich 2 Byte da sie größer als 255 ist ....?

Eine Zahl wie 123456 in die zwei Teile 123 und 456 aufzuteilen, ist eine schlechte Idee, weil sie intern nicht so gespeichert ist.

union ist ein Hinweis

Wenn ich Daten zwischen Arduinos, über die Serielle, schicken muss, ist der CmdMessenger die erste Wahl.

  1. du zerlegst mit MOD und DIV dein Integer in zwei Bytes
  2. du erzeugst mit einem HASH oder ähnlichem Algorithmus eine 1-Byte-Prüfsumme
  3. du sendest Startsymbol, Low-Byte, Hi-Byte, Prüfziffer, Stopsymbol
  • auf Empfängerseite hälst du ein Array mit 5 Plätzen bereit
  • jedes eintreffende Byte wird in das Feld mit dem höchsten Index (4) kopiert, zuvor werden die niedrigeren Felder je 1 Pos. weiter kopiert
  • nach jedem empfangenen Byte prüfst du, ob Feld 0 = Startsymbol, Feld 3 = korrekt berechnete Prüfziffer aus Feldern 1 und 2, Feld 4 = Stopsymbol

wenn ja: Feld 1 u. 2 auslesen, Array komplett auf Null setzen ...

combie:
Wenn ich Daten zwischen Arduinos, über die Serielle, schicken muss, ist der CmdMessenger die erste Wahl.

Wenn wir es schon aufblähen:

long wert = 234567;
Serial.println(wert);  // sendet in diesem Beispiel 8 Zeichen, die jeder lesen kann.

Hat den Vorteil, dass man zum Testen alles hernehmen kann, also Sender und Empfänger unabhängig und mit Standard-Mitteln ( SerialMonitor, hterm, ... ) testen kann.

Hi

Mit dem Nachteil erkauft, daß man diese 8 (ok, 6 Nutzzeichen) Zeichen wieder irgendwie zusammen kleben muß - zwar für jeden lesbar, aber ob die Arduinos damit auch was anfangen können - ich äußere Zweifel :wink:

MfG

Strings einzulesen und in Zahlen zu konvertieren ist trivial. Es ist mehr Aufwand als gleich Binär-Daten zu senden, aber trotzdem sehr einfach.

http://www.cplusplus.com/reference/cstdlib/atol/

Hallo Leute möchte euch meine Teillösung vorstellen habe das jetzt so gemacht wie von @qualidat vorgeschlagen nur die Prüfsumme habe ich mal auskommentiert...

Sender:

#include <Wire.h>

int Datawort=12345;
char Datawortsend[] = {'A',0,0,0,'B'};


void setup() {
  Serial.begin(9600);           // start serial for output
  Wire.begin();                 // join i2c bus (address optional for master)
}
                  

void loop() {


  
//Datawort zerlegen in zwei Byts
Datawortsend[1]=Datawort / 256;   //High Byte
Datawortsend[2]=Datawort % 256;   //Low Byte



//Prüfsummer erstellen
//int Pruefsumme=Datawortsend[1]+Datawortsend[2];
//int Pruefsummemap=map(Pruefsumme, 0, 510, 0, 255);
//Datawortsend[3]=Pruefsummemap;


//Byts senden
for (int i=0; i<=4 ;i++){
  Wire.beginTransmission(8);                // transmit to device #8
  Wire.write(Datawortsend[i]);              // sends one byte
  Wire.endTransmission();                    // stop transmitting
  delay(100);
  }

}

Reciver:

#include <Wire.h>

char Datenwortincomming[]={0,0,0,0,0,};               // eingehendes Datenwort
int Datenwort[]={0,0};                                //geprüftes Datenwort 2Byte
int Datawort=0;                                       //zusammengesetzetes Datenwort
//int Pruefsumme=0;                                     
//int Pruefsummemap=0;

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {

Serial.println(Datawort);

  
}



void receiveEvent(int howMany) {

//index array eine Stelle verschieben
Datenwortincomming[0]=Datenwortincomming[1];
Datenwortincomming[1]=Datenwortincomming[2];
Datenwortincomming[2]=Datenwortincomming[3];
Datenwortincomming[3]=Datenwortincomming[4];
Datenwortincomming[4]=Wire.read();






//check Reihenfolge Array

if (Datenwortincomming[0] ='A' &&  Datenwortincomming[4]=='B'){



  
  // Daten speichern
  Datenwort[0]=Datenwortincomming[1],DEC;
  Datenwort[1]=Datenwortincomming[2],DEC;


  //Array zurücksetzen 
  for (int i=0;i<=4;i++){
    Datenwortincomming[i] =0;     
  }
  
  //Datenwort wieder zusammensetzen
  Datawort=Datenwort[0]*256+Datenwort[1];

Serial.println(Datawort);



  
  }


}

das funzt auch soweit nur nicht bei allen Zahlen zB. bei 128-256 geht es nicht ,bei 382 bis 512 ,512 -639, usw

könnte mit bitte nochmal jemand einen Lösungsvorschlag machen das ich zuverlässig int Variabeln von sagen wir 255-30000 übertragen kann

Über welche Schnittstelle reden wir? In der Überschrift steht "Seriell", Wire.h deutet auf I2C. Bist Du im richtigen Thema? Ich wollte nur mal vorsichtig fragen :confused:

habe jetz mal Das zerlegen geändert und habe Zahl / 100 statt 256 gerechnet und Zahl%100
jetzt get es bis auf das bei jeder Zahl die eine 65 enthält eine 0 und eine 65 ausgegeben wird

//Datawort zerlegen in zwei Byts
Datawortsend[1]=Datawort / 100;   //High Byte
Datawortsend[2]=Datawort % 100;   //Low Byte

zB. Serial Monitor gibt aus

1260
1261
1262
1263
1264
1265
0
65
1267
1268
.
.
.

Normal macht man das durch eine Bitshift-Operation um 8. Nicht mit einer langsamen Modulo-Division

Ansonsten gibt es für sowas Unions:

union Data
{
   unsigned int value;
   byte asArray[sizeof(unsigned int)];
};

Damit kann man Variablen sowohl direkt als sich als auch als Array ansprechen. Und man kann sie im Request Event Handler auf einmal per write() senden.

Mit einer union aus einem anonymen struct und einem Array gehen auch mehrere Variablen:

union Data
{
   struct
   {
     unsigned int value;
     byte checksum;
   };
   byte asArray[sizeof(unsigned int) + 1];
};