Hilfe bei der strcpy Funktion

hi

ich bin noch unerfahren mit arduino und c++ könnt ihr mir helfen ob ich die strcpy Funktion

richtig anwende weil meine Ausgabe gibt nichts raus

danke

#include <SoftwareSerial.h>
#include <string.h>

char Id[3], Sp[4], Dir[2], Lt[2];
char rx[18];

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() > 0){

strcpy( Id, strtok(rx, “;”));
strcpy( Sp, strtok(NULL, “;”));
strcpy( Dir, strtok(NULL, “;”));
strcpy( Lt, strtok(NULL, “;”));

for(int i=0;i<18;i++){
Serial.print( data*);*

  • }*
  • }*
    }
    }

und das kompiliert?

ah das data vergessen zu deklarieren…
dann wird es kompiliert

#include <SoftwareSerial.h>
#include <string.h>

char Id[3], Sp[4], Dir[2], Lt[2];
char rx[18];
char data[18];

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() > 0){
//Serial.readBytes(rx, 12);
//Serial.println(rx);

strcpy( Id, strtok(rx, “;”));
strcpy( Sp, strtok(NULL, “;”));
strcpy( Dir, strtok(NULL, “;”));
strcpy( Lt, strtok(NULL, “;”));

for(int i=0;i<18;i++){
Serial.print("Das befindet sich im Array ");
Serial.print( data*);*

  • Serial.println(" ");*
  • }*
    }
    }

und wo füllst du data?

du solltest dich erstmal noch etwas mit den Basics beschäftigen

Hallo,

ist ja kein Wunder das nichts passiert.
Was soll den in char rx drin stehen außer Nullen?
Du liest nichts ein in char rx.
Danach suchste in NULL ein Semikolon. Wo soll das herkommen?
Danach zählst du i bis 18 und gibts 18x ein leeres char data aus. Es ist ja nicht gefüllt.

Und ein Doppelposting wird auch ungern gesehen!
Zudem du von Serenifly schon die richtige Info bekommen hast.
Lies dazu das nochmal. http://forum.arduino.cc/index.php?topic=359203.0

Und ganz wichtig. Setze in Zukunft deinen Code in “Code Tags”. Button </> oben links.

ja sorry du hast recht…

also über rx bekomme ich mein packet :

Id;Sp;Dir;Lt zum Beispiel so $EA;100;“i”;c

dann möchte ich das packet splitten und in die entsprechenden variablen speichern

also $EA zu Id
100 zu Sp
i zu Dir
c zu Lt

ich scheitere schon das kommende packet anzuzeigen

#include <SoftwareSerial.h>
#include <string.h>

char Id[3], Sp[4], Dir[2], Lt[2];
char rx[18];

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() > 0 ){

int j = 0;
while(Serial.available() > 0){
rx[j] = Serial.read();
j++;
}

for(int i=0;i<18;i++){
Serial.print("Das befindet sich im Array ");
Serial.print( rx*);*

  • Serial.println(" ");*

  • }*

  • strcpy( Id, strtok(rx, “;”));*

  • strcpy( Sp, strtok(NULL, “;”));*

  • strcpy( Dir, strtok(NULL, “;”));*

  • strcpy( Lt, strtok(NULL, “;”));*

  • for(int i=0;i<18;i++){*

  • Serial.print("Das befindet sich nach strcpy im Array “);*
    _ Serial.print( rx*);_
    _
    Serial.println(” ");_
    _
    }_
    _
    }_
    _
    }*_

ich scheitere schon das kommende packet anzuzeigen

Du scheiterst schon beim lesen, weil du zu schnell bist.

  int j = 0;
  while(Serial.available() > 0){
    rx[j] = Serial.read();
    j++;
  }

Sobald ein Zeichen da ist, fängst du an.
Bei 9600 braucht jedes Zeichen 1 ms, also ist nach 1-2 Zeichen schluss.

Abhilfe:
a) nach jedem Serial.read() 2 ms warten, ob noch mehr kommt.
b) ohne while erstmal lesen und alle Zeichen mitzählen (int j = 0; muss da raus)

Siehe meine Antwort in dem anderen Thread:

Verwende die Einlese-Funktion die ich dir gegeben habe. Die hatte schon seinen Grund! So wie du das machst geht es nicht.

Ich sehe gerade dass du doch ein paar Strings senden willst. Muss das unbedingt sein? Hast du Kontrolle über dieses Format? Wenn ja, ändere es.

Die Einlese-Funktion kann man so für sehr viele Sachen unverändert verwenden (z.B. auch um von einer SD Karte zu lesen). Dann schreibt man sich je nach Anwendung einen anderen Parser um die Daten zu verarbeiten.

Ok, ich habe es mal mit 1 String + 2 Zeichen + 1 Integer gemacht. Aber wenn du das Format ändern kannst, dann tue das.

Wenn du dann am anderen Ende einfach ein Linefeed und/oder Carriage Return am anderen Ende schickst geht es ohne Probleme

Beachte auch dass du C Strings nicht einfach mit == vergleichen kannst. Dafür brauchst du strcmp() oder strcasecmp(). Einzelne Zeichen wie ‘c’ oder ‘i’ kann dagegen auch mit == vergleichen! Ich habe mal einen kleinen Test dafür eingefügt

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

char ld[4];
int speed;
char dir, lt;

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

void loop()
{
  if (readSerial(Serial))     //hier geht auch SoftwareSerial!
  {
    parseSerial();
  }
}

void parseSerial()
{
  strlcpy(ld, strtok(serialBuffer, ",;"), sizeof(ld));
  speed = atoi(strtok(NULL, ",;"));
  dir = *strtok(NULL, ",;");      //* dereferenziert den Zeiger. Hier wird nur ein Zeichen kopiert. Also geht das. Aber nicht mit Strings
  lt = *strtok(NULL, ",;");

  Serial.print("ld: "); Serial.println(ld);
  Serial.print("speed: "); Serial.println(speed);
  Serial.print("dir: "); Serial.println(dir);
  Serial.print("lt: "); Serial.println(lt);

  //Vergleiche als Test
  if (strcasecmp(ld, "$EA") == 0)
    Serial.println("ld ist \"$EA\"");

  if (dir == 'i')
    Serial.println("dir ist 'i'");
}

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;
}

Das:

$EA;100;i;c

Liefert:

ld: $EA
speed: 100
dir: i
lt: c
ld ist "$EA"
dir ist 'i'

Geht eben so mit “dir” und “lt” weil es nur ein Zeichen ist wenn ich das richtig sehe

strlcpy() überprüft beim Kopieren sicherheitshalber die Länge damit nichts überlauft.

danke michael_x für den hinweis

ElEspanol deine variante probiere ich mal heute abend aus

ich frage mich gerade warum mein Dir = i welches im packet ist nicht in die Variable Dir kopiert wird

Das ist die Ausgabe:

Das befindet sich im Array $
Das befindet sich im Array E
Das befindet sich im Array A
Das befindet sich im Array ;
Das befindet sich im Array 1
Das befindet sich im Array 0
Das befindet sich im Array 5
Das befindet sich im Array ;
Das befindet sich im Array i // <<<<<-------
Das befindet sich im Array ;
Das befindet sich im Array c
Das befindet sich im Array

Das befindet sich im Array
Das befindet sich im Array
Das befindet sich im Array
Das befindet sich im Array
Das befindet sich im Array
Das befindet sich im Array


Das befindet sich in Id $
Das befindet sich in Id E
Das befindet sich in Id A
Das befindet sich in Sp 1
Das befindet sich in Sp 0
Das befindet sich in Sp 5
Das befindet sich in Sp
Das befindet sich in Dir
Das befindet sich in Dir
Das befindet sich in Lt c

und hier der Code:

#include <SoftwareSerial.h>
#include <string.h>

char Id[3], Sp[4], Dir[2], Lt[2];
char rx[18];

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() > 0 ){

int j = 0;
while(Serial.available() > 0){
rx[j] = Serial.read();
delay(200);
j++;
}

for(int i=0;i<18;i++){
Serial.print("Das befindet sich im Array ");
Serial.print( rx*);*

  • Serial.println(" ");*

  • delay(200);*

  • }*

  • strcpy( Id, strtok(rx, “;”));*

  • strcpy( Sp, strtok(NULL, “;”));*

  • strcpy( Dir, strtok(NULL, “;”));*

  • strcpy( Lt, strtok(NULL, “;”));*
    _ Serial.println("*******************");_

  • for(int i=0;i<3;i++){*

  • Serial.print("Das befindet sich in Id “);*
    _ Serial.print( Id*);_
    _
    Serial.println(” ");_
    _
    delay(200);_
    _
    }_
    _
    for(int i=0;i<4;i++){ _
    _
    Serial.print("Das befindet sich in Sp “);_
    _ Serial.print( Sp);
    Serial.println(” ");
    delay(200);
    }
    for(int i=0;i<2;i++){
    Serial.print("Das befindet sich in Dir “);
    Serial.print( Dir);
    Serial.println(” ");
    delay(200);
    }
    for(int i=0;i<1;i++){
    Serial.print("Das befindet sich in Lt “);
    Serial.print( Lt);
    Serial.println(” ");
    delay(200);
    }*_

}
}

Links oben in wie du den Post schreibst ist ein </> Knopf. Klicke darauf und schreiben dann deinen Code zwischen die Tags.

Ansonsten verwerfe den Code. Das funktioniert vielleicht grob, aber ist generell Murks. Meine Einlese-Funktion wartet nicht einfach nach jedem Zeichen stur oder einmal davor. Es wird eingelesen was da ist und wenn das Endzeichen (LF oder CR) kommt, hört man auf und schaut nach. Das heißt man kann zwischendurch noch andere Dinge tun. Außerdem ist es universell und funktioniert unabhängig von der Länge. Und überprüft auch dass man nicht über das Array hinaus schreibt.

Genauso ist gleich die Konvertierung dabei. In einer extra Funktion.

Im Feld Id[3] möchtest Du “$EA” speichern. Ein Feld aus Buchstaben braucht einen Platz mehr: “Note that when declaring an array of type char, one more element than your initialization is required, to hold the required null character.” (Quelle)

Mit diesem Testsketch

char Id[4], Sp[5], Dir[3], Lt[3];
char rx[18] = "$EA;100;i;c";

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

  Serial.print("Das befindet sich im Array ");
  for (int i = 0; i < 18; i++) {
    Serial.print(rx[i]);
  }
  Serial.println(" ");

  strcpy( Id, strtok(rx, ";"));
  strcpy( Sp, strtok(NULL, ";"));
  strcpy( Dir, strtok(NULL, ";"));
  strcpy( Lt, strtok(NULL, ";"));

  Serial.println("*******************");

  Serial.print("Das befindet sich in Id ");
  Serial.println(Id);
  Serial.print("Das befindet sich in Sp ");
  Serial.println(Sp);
  Serial.print("Das befindet sich in Dir ");
  Serial.println(Dir);
  Serial.print("Das befindet sich in Lt ");
  Serial.println(Lt);
}

void loop() {
}

erhalte ich diese Ausgabe:

Das befindet sich im Array $EA;100;i;c
*******************
Das befindet sich in Id $EA
Das befindet sich in Sp 100
Das befindet sich in Dir i
Das befindet sich in Lt c