Seriell senden und empfangen von Array

Ich habe versucht, ein Array von 5 Werten (0 bis 4) über die UART TX/RX Schnittstelle zu senden und empfangen. Irgendie wills nicht so recht. Kann mir hier jemand helfen?
Ich möchte das Array wie folgt senden: Adresse, Befehlszeichen, Wert, CRC Prüfsumme.
Empfangen wird es wie folgt:

  • Erstes Zeichen einlesen und abgleichen, ob es mit der Adresse übereinstimmt. Falls ja, die Adresse ins Array 0 schreiben
  • Wenn es mit der Adresse übereinstimmt, dann die vier nächsten Werte ins Array schreiben (1 bis 4)
  • Sobald die Daten alle gelesen wurden, mit den Array 0 bis 2 die Prüfsumme rechnen und mit dem Empfangenen Array 3 und 4 vergleichen.
  • Wenn die Prüfsummen übereinstimmen, dann die Werte von Array 1 per switch ins dazugehörige case das Array 2 schreiben.

Hier mal den Programmcode wie er bis jetzt aussieht. Senden tut er was, per Serielle Ausgabe erkennt er auch die Adresse, aber er speichert keine Werte ab.

Sendecode:

char data[5];
char incomingData[5];
char crcData[2];
uint16_t crc = 0;
boolean newData = false;

const byte address = 0x82;
const byte addressRX = 0x80;

byte BUT10 = 0;
byte BUT11 = 0;
byte BUT12 = 0;
byte BUT13 = 0;
byte BUT14 = 0;

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

}

void loop() {

  readCommand(Serial);
  
  command('E',184, address, Serial);
  command('H',253, address, Serial);
  command('#',98, address, Serial);

}


//Function for driving the feet and dome motors over serial
void command(const char command, const byte value, const byte address, Stream& stream){
  data[0] = address;                            //write address in data array
  data[1] = command;                            //write command for forward/reverse/left/right in data array
  data[2] = value;                              //write movement speed in data array
  for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i <= 3
    crc16(data[index]);                         //call the function crc16
  }
  //crc = getCRC();
  data[3] = crc >> 8;                           //store checksum in data array
  data[4] = crc;
  stream.write(data, sizeof(data));             //send the data array by serial
  crc = 0;                                      //clear the checksum
}


//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {

  int i;
  crc = crc ^ ((uint16_t)data << 8);
  for (i=0; i<8; i++){
    if (crc & 0x8000){
      crc = (crc << 1) ^ 0x1021;
    }
    else{
      crc <<= 1;
    }
  }
}


void readCommand(Stream& stream){
  
  readData(stream);
  
  if(newData == true){
    for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i <= 3
      crc16(incomingData[index]);                         //call the function crc16
    }
    crcData[0] = crc >> 8;
    crcData[1] = crc;
    if(crcData[0] == incomingData[3] && crcData[1] == incomingData[4]){
      switch(incomingData[1]){
        case 'A': BUT10 = incomingData[2];
                  break;
        case 'B': BUT11 = incomingData[2];
                  break;
        case 'C': BUT12 = incomingData[2];
                  break;
        case 'D': BUT13 = incomingData[2];
                  break;
        case '@': BUT14 = incomingData[2];
                  break;
      }
    }
    Serial.print("BUT10 = ");
    Serial.println(BUT10);
    Serial.print("BUT11 = ");
    Serial.println(BUT11);
    Serial.print("BUT12 = ");
    Serial.println(BUT12);
    Serial.print("BUT13 = ");
    Serial.println(BUT13);
    Serial.print("BUT14 = ");
    Serial.println(BUT14);
    
    newData = false;
    for(byte index = 0; index < 5; index++){
      incomingData[index] = '\0';
    }
    crc = 0;
  }
}


void readData(Stream& stream){
  static boolean inProgress = false;
  static byte index = 0;
  char var = 0;
  
  while(stream.available() > 0){
    var = stream.read();

    if(inProgress == true){
      if(index < 4){
        incomingData[index++] = var;
      }
      else{
        inProgress = false;
        index = 0;
        newData = true;
      }
    }
    else if(var == addressRX && inProgress == false){
      inProgress = true;
      incomingData[0] = addressRX;
    }
  }
}

Empfängercode:

char data[5];
char incomingData[5];
char crcData[2];
uint16_t crc = 0;
boolean newData = false;

const byte address = 0x80;
const byte addressRX = 0x82;

byte BUT1 = 0;
byte BUT2 = 0;
byte BUT3 = 0;
byte BUT4 = 0;
byte BUT5 = 0;

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

}

void loop() {

  readCommand(Serial);
  
  command('A',155, address, Serial);
  command('D',247, address, Serial);
  command('B',29, address, Serial);

}


//Function for driving the feet and dome motors over serial
void command(const char command, const byte value, const byte address, Stream& stream){
  data[0] = address;                            //write address in data array
  data[1] = command;                            //write command for forward/reverse/left/right in data array
  data[2] = value;                              //write movement speed in data array
  for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i <= 3
    crc16(data[index]);                         //call the function crc16
  }
  //crc = getCRC();
  data[3] = crc >> 8;                           //store checksum in data array
  data[4] = crc;
  stream.write(data, sizeof(data));             //send the data array by serial
  crc = 0;                                      //clear the checksum
}


//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {

  int i;
  crc = crc ^ ((uint16_t)data << 8);
  for (i=0; i<8; i++){
    if (crc & 0x8000){
      crc = (crc << 1) ^ 0x1021;
    }
    else{
      crc <<= 1;
    }
  }
}


void readCommand(Stream& stream){
  
  readData(stream);
  
  if(newData == true){
    for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i <= 3
      crc16(incomingData[index]);                         //call the function crc16
    }
    crcData[0] = crc >> 8;
    crcData[1] = crc;
    if(crcData[0] == incomingData[3] && crcData[1] == incomingData[4]){
      switch(incomingData[1]){
        case 'E': BUT1 = incomingData[2];
                  break;
        case 'F': BUT2 = incomingData[2];
                  break;
        case 'G': BUT3 = incomingData[2];
                  break;
        case 'H': BUT4 = incomingData[2];
                  break;
        case '#': BUT5 = incomingData[2];
                  break;
      }
    }
    Serial.print("BUT1 = ");
    Serial.println(BUT1);
    Serial.print("BUT2 = ");
    Serial.println(BUT2);
    Serial.print("BUT3 = ");
    Serial.println(BUT3);
    Serial.print("BUT4 = ");
    Serial.println(BUT4);
    Serial.print("BUT5 = ");
    Serial.println(BUT5);
    
    newData = false;
    for(byte index = 0; index < 5; index++){
      incomingData[index] = '\0';
    }
    crc = 0;
  }
}


void readData(Stream& stream){
  static boolean inProgress = false;
  static byte index = 0;
  char var = 0;
  
  while(stream.available() > 0){
    var = stream.read();

    if(inProgress == true){
      if(index < 4){
        incomingData[index++] = var;
      }
      else{
        inProgress = false;
        index = 0;
        newData = true;
        Serial.println(incomingData[0]);
        Serial.println(incomingData[1]);
        Serial.println(incomingData[2]);
        Serial.println(incomingData[3]);
        Serial.println(incomingData[4]);
      }
    }
    else if(var == addressRX && inProgress == false){
      inProgress = true;
      incomingData[0] = addressRX;
      Serial.println("inProgress = true!");
    }
  }
}

Moooment...
Das ist was anderes als das bisherige Problem - aber gehört dazu??

Wo hängt es jetzt? Am Sender, Am Empfänger, Am Mittler?

Ja, ich habe ein neues Thema eröffnet, weil es nichts mit dem Compilierungsproblem zu tun hat im andern Fall.

Es gehört mal dazu, ist aber noch kein Bestandteil des Programmes. Im Prinzip ist die Idee, dass ich im selben Schema wie die Motorbefehle die command(....serial1) ersetzen kann. Dann wäre es möglich, mit einer TX Leitung drei Geräte anzusprechen, danstelle die SoftwareSerial lib zu verwenden. Die RX Leitung wird bis auf Weiteres nur von einem Gerät verwendet, daher weniger das Problem. Es soll mit dem gleichen Schema wie der motor() Befehl vom Hauptsketch gesendet werden. Dies muss vom andern Arduino (Empfänger) nun empfangen werden. Die CRC Prüfsumme wäre bei diesem noch egal, aber damit das Array als Ganzes eingelesen wird, habe ich diese übernommen. Ist ja nicht riesig. Senden sollte so gehen, da meine Motorcontroller die Befehle erhalten. Was die dann aber da wie einlesen weiss ich nicht. Habe dies jetz mal so versucht wie hier gepostet.

Hab den Fehler gefunden! Musste in der Zeile while(stream.available() > 0); natürlich noch sagen, dass er nicht immer fortlaufend einliest, sondern nur, wenn die neu empfangenen Daten noch nicht alle da sind: while(stream.available() > 0 && newData == false)

So funktioniert es nun falls ich mal umstellen möchte.

Sender:

char data[5];                 //data array for sending characters
char incomingData[5];         //incomingData array for receiving characters
char crcData[2];              //crcData array for calculated checksum
uint16_t crc = 0;             //crc checksum
boolean newData = false;      //newData received = true, newData not received = false

const byte address = 0x82;    //address from this device (sender)
const byte addressRX = 0x80;  //address from other device where the data was sent from (expected receiving)

byte BUT10 = 0;
byte BUT11 = 0;
byte BUT12 = 0;
byte BUT13 = 0;
byte BUT14 = 0;

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

}

void loop() {

  readCommand(Serial);                //function for reading transmitted data by serial
  
  command('E',184, address, Serial);  //function to sendby serial (command character, value, address, serial port)
  command('H',253, address, Serial);
  command('#',98, address, Serial);

}


//function for sending data by serial
void command(const char command, const byte value, const byte address, Stream& stream){
  data[0] = address;                            //write address in data array
  data[1] = command;                            //write command (for forward/reverse/left/right) in data array
  data[2] = value;                              //write movement speed in data array
  for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i < 3
    crc16(data[index]);                         //call the function crc16 to calculate the checksum
  }
  //crc = getCRC();
  data[3] = crc >> 8;                           //store 16-bit checksum in data array
  data[4] = crc;
  stream.write(data, sizeof(data));             //send the data array by serial
  crc = 0;                                      //clear the checksum
}


//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {

  int i;
  crc = crc ^ ((uint16_t)data << 8);
  for (i=0; i<8; i++){
    if (crc & 0x8000){
      crc = (crc << 1) ^ 0x1021;
    }
    else{
      crc <<= 1;
    }
  }
}


//function to store the received data by serial
void readCommand(Stream& stream){
  
  readData(stream);                           //function to receive the incoming data
  
  if(newData == true){                        //if newData is true = all data received, then make...
    for(byte index = 0; index < 3; index++){  //create the checksum for the received array incomingData[i] with 0 <= i < 3
      crc16(incomingData[index]);             //call the function crc16
    }
    crcData[0] = crc >> 8;                    //store 16-bit checksum in data array
    crcData[1] = crc;
    if(crcData[0] == incomingData[3] && crcData[1] == incomingData[4]){ //if the received crc checksum is equal to the calculated checksum of received data, then make...
      switch(incomingData[1]){                                          //switch the second array of incomingData that contains the command character
        case 'A': BUT10 = incomingData[2];                              //if the command character is A, then store the third array of incomingData that contains the value, to BUT10
                  break;                                                //leave the switch/case function
        case 'B': BUT11 = incomingData[2];
                  break;
        case 'C': BUT12 = incomingData[2];
                  break;
        case 'D': BUT13 = incomingData[2];
                  break;
        case '@': BUT14 = incomingData[2];
                  break;
      }
    }
    Serial.print("BUT10 = ");                        //only to show the received data, not used in the main program!
    Serial.println(BUT10);
    Serial.print("BUT11 = ");
    Serial.println(BUT11);
    Serial.print("BUT12 = ");
    Serial.println(BUT12);
    Serial.print("BUT13 = ");
    Serial.println(BUT13);
    Serial.print("BUT14 = ");
    Serial.println(BUT14);
    
    newData = false;                                //set newData to false => data were received now!
    for(byte index = 0; index < 5; index++){        //for index = 0 <= i < 5, make...
      incomingData[index] = '\0';                   //delete the whole incomingData array
    }
    crc = 0;                                        //set crc = 0
  }
}


//function for reading the incoming data by serial
void readData(Stream& stream){
  static boolean inProgress = false;                  //inProgree = true = receive incoming data, inProgress = false = ready to receive incoming data
  static byte index = 0;                              //index for byte array incomingData
  byte var = 0;                                       //variable var to read the incoming serial data
  
  while(stream.available() > 0 && newData == false){  //while serial is available and newData is not already received, make...
    var = stream.read();                              //read serial data and store it to var

    if(inProgress == true){                           //if inProgress is active, then make...
      if(index < 5){                                  //if index is less than 5, then make...
        incomingData[index] = var;                    //store var to incomingData array with [index]
        index++;                                      //index +1
      }
      else{                                           //else if index is not less than 5, then make...
        inProgress = false;                           //inProgress is not active anymore
        index = 0;                                    //index is equal to 0
        newData = true;                               //newData is true = all data received and ready to store it
      }
    }
    else if(var == addressRX && inProgress == false){ //else if inProgress is not active and var is equal to addressRX, then make...
      inProgress = true;                              //inProgress is active now
      incomingData[0] = addressRX;                    //store the addressRX into the incomingData array 0
      index++;                                        //index +1
    }
  }
}

Empfänger:

char data[5];                 //data array for sending characters
char incomingData[5];         //incomingData array for receiving characters
char crcData[2];              //crcData array for calculated checksum
uint16_t crc = 0;             //crc checksum
boolean newData = false;      //newData received = true, newData not received = false

const byte address = 0x80;    //address from this device (sender)
const byte addressRX = 0x82;  //address from other device where the data was sent from (expected receiving)

byte BUT1 = 0;
byte BUT2 = 0;
byte BUT3 = 0;
byte BUT4 = 0;
byte BUT5 = 0;

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

}

void loop() {

  readCommand(Serial);                //function for reading transmitted data by serial
  
  command('A',155, address, Serial);  //function to sendby serial (command character, value, address, serial port)
  command('D',247, address, Serial);
  command('B',29, address, Serial);

}


//function for sending data by serial
void command(const char command, const byte value, const byte address, Stream& stream){
  data[0] = address;                            //write address in data array
  data[1] = command;                            //write command (for forward/reverse/left/right) in data array
  data[2] = value;                              //write movement speed in data array
  for(byte index = 0; index < 3; index++){      //create the checksum for the array data[i] with 0 <= i < 3
    crc16(data[index]);                         //call the function crc16 to calculate the checksum
  }
  data[3] = crc >> 8;                           //store 16-bit checksum in data array
  data[4] = crc;
  stream.write(data, sizeof(data));             //send the data array by serial
  crc = 0;                                      //clear the checksum
}


//Calculates CRC16 of nBytes of data[index] in byte array
void crc16(uint8_t data) {

  int i;
  crc = crc ^ ((uint16_t)data << 8);
  for (i=0; i<8; i++){
    if (crc & 0x8000){
      crc = (crc << 1) ^ 0x1021;
    }
    else{
      crc <<= 1;
    }
  }
}


//function to store the received data by serial
void readCommand(Stream& stream){
  
  readData(stream);                           //function to receive the incoming data
  
  if(newData == true){                        //if newData is true = all data received, then make...
    for(byte index = 0; index < 3; index++){  //create the checksum for the received array incomingData[i] with 0 <= i < 3
      crc16(incomingData[index]);             //call the function crc16
    }
    crcData[0] = crc >> 8;                    //store 16-bit checksum in data array
    crcData[1] = crc;
    
    if(crcData[0] == incomingData[3] && crcData[1] == incomingData[4]){ //if the received crc checksum is equal to the calculated checksum of received data, then make...
      switch(incomingData[1]){                                          //switch the second array of incomingData that contains the command character
        case 'E': BUT1 = incomingData[2];                               //if the command character is E, then store the third array of incomingData that contains the value, to BUT1
                  break;                                                //leave the switch/case function
        case 'F': BUT2 = incomingData[2];
                  break;
        case 'G': BUT3 = incomingData[2];
                  break;
        case 'H': BUT4 = incomingData[2];
                  break;
        case '#': BUT5 = incomingData[2];
                  break;
      }
    }
    Serial.print("BUT1 = ");                        //only to show the received data, not used in the main program!
    Serial.println(BUT1);
    Serial.print("BUT2 = ");
    Serial.println(BUT2);
    Serial.print("BUT3 = ");
    Serial.println(BUT3);
    Serial.print("BUT4 = ");
    Serial.println(BUT4);
    Serial.print("BUT5 = ");
    Serial.println(BUT5);
    
    newData = false;                                //set newData to false => data were received now!
    for(byte index = 0; index < 5; index++){        //for index = 0 <= i < 5, make...
      incomingData[index] = '\0';                   //delete the whole incomingData array
    }
    crc = 0;                                        //set crc = 0
  }
}


//function for reading the incoming data by serial
void readData(Stream& stream){
  static boolean inProgress = false;                  //inProgree = true = receive incoming data, inProgress = false = ready to receive incoming data
  static byte index = 0;                              //index for byte array incomingData
  byte var = 0;                                       //variable var to read the incoming serial data
  
  while(stream.available() > 0 && newData == false){  //while serial is available and newData is not already received, make...
    var = stream.read();                              //read serial data and store it to var

    if(inProgress == true){                           //if inProgress is active, then make...
      if(index < 5){                                  //if index is less than 5, then make...
        incomingData[index] = var;                    //store var to incomingData array with [index]
        index++;                                      //index +1
      }
      else{                                           //else if index is not less than 5, then make...
        inProgress = false;                           //inProgress is not active anymore
        index = 0;                                    //index is equal to 0
        newData = true;                               //newData is true = all data received and ready to store it
      }
    }
    else if(var == addressRX && inProgress == false){ //else if inProgress is not active and var is equal to addressRX, then make...
      inProgress = true;                              //inProgress is active now
      incomingData[0] = addressRX;                    //store the addressRX into the incomingData array 0
      index++;                                        //index +1
    }
  }
}

Hallo
das wird nix. Eine normale serielle Verbindung RX/TX ist zunächst mal einen Punkt zu Punkt Verbindung für zwei Geräte , es ist kein Bus. Du sucht eine Busverbindung z.B I2C, Canbus )
Heinz

Das ist so, aber meine Idee war, wenn ich jedem Gerät eine Adresse vergebe, dann werden die Daten an alle angeschlossenen Geräte gesendet, aber nur beim korrespondierenden Gerät welches die richtige Adresse hat eingelesen. Oder nicht? Ich habe mal zwei LED-Lampen per Serial so angesteuert. Gleiche Befehle an beide Geräte gesendet und nur das eine hat dann die Befehle erkannt und ausgeführt. Dies war aber mit je einer TX-Leitung pro Gerät!

Edit: Habe es getestet! Solange nur ein "Master" im System ist, der Daten sendet, dann können x-beliebige Arduinos an der TX-Leitung vom Master stecken (natürlich zu RX verbunden) um die Daten die der Master sendet, zu empfangen! Funktioniert als Einwegübertragung einwandfrei, solange dies ausreicht!

Naja, der Fall ist nun eingetreten! Ich war gerade in der Werkstatt um nochmals zu testen warum meine I2C Verbindung hängt und blockiert. Der Gedanke den ich mal hatte, war glaube ich nicht mal so doof. Vor ein paar Tagen hatte ich einen Traum, da hat die SoftwareSerial Lib zusammen mit der Wire Lib herumgezickt. Als ich dann am Morgen aufgewachen bin wusste ich, was ich versuchen möchte! Habe jetzt einfach mal knallhart den Arduino mit der Wire Lib und SoftwareSerial Lib vom I2C getrennt. Und siehe da...... es läuft wie eine eins!

Nun theoretisch wäre das ein anderes Thema, aber ich frage hier trotzdem mal. Wieso stört die SoftwareSerial Lib so ziemlich alles? Ich hatte herumzuckende Servos und nun auch eine I2C Verbindung die komplett abgeschmiert ist.

Jetzt kann ich den obigen Testsketch ja gut gebrauchen. Dann hat meine Motorsteuerung halt nur eine Empfangsleitung RX und kann keine Rückmeldung mehr geben, aber ich sag mal vorsichtig, was solls. Ich habe mal geplant, dass die Motorsteuerung nach dem Akkustand oder der Motorenbelastung abgefragt werden kann, dafür bräuchte ich aber die TX Leitung die zu meinem Arduino geht. Dann ist dies halt Geschichte. Eine Akkuanzeige kann man auch per Spannungsteiler am Arduino anhängen und so die Spannung, resp. Prozente rechnen die der Akku noch hat!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.