ESPNOW - Datenübertragung funktioniert nicht

Hey Leute, ich arbeite mit zwei ESP32 über ESPNOW und würde gerne mit meinem Programm über strings zahlen für links und Buchstaben für rechts ausgegeben z.B. 5pf bekommen. Ansicht hat mein Programm keine Fehlermeldungen, aber ich bekomme im seriellen monitor die Ausgabe nur am Sender obwohl es beim Receiver angezeigt werden sollte.
Ich glaube das Problem liegt im typedef bei den Strings ich müsste anscheinen arrays of char verwenden. Ich habe zwar recherchiert, aber kaum was gefunden was mir helfen konnte. Ich würde mich freuen, wenn mir jemand das erklären könnte.

//esp32 sender
#include <esp_now.h>
#include <WiFi.h>

int lesel;//speicher für fitting
int leser;
int i;    //zähler
int maxl; //gefitteter Wert
int maxr;
int Fitl; //werte für switch
int Fitr;
int wertl;//einzelmessungen
int wertr;
String Links;
String Rechts;

//mac address 94:B9:7E:DA:4C:74
uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xDA, 0x4C, 0x74};

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message { 
 String Links;
 String Rechts;
} struct_message;

// Create a struct_message called myData
struct_message myData;

esp_now_peer_info_t peerInfo;

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
 
void setup() {
 
  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA); 

  //fitting(10 messungen werden über zeitraum von 2 sekunden abgenommen und der durchschnitt wird ausgerechnet.
  delay(300);
  for(i=0;i<=10;i++)
  {
    lesel= analogRead(34)+lesel;
    leser= analogRead(32)+leser;
    delay(20);
  }
  maxl=lesel/10;
  maxr=leser/10;

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  else
  {
    Serial.println("Succes: Initialized ESP-NOW");
  }

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_peer_info_t peerInfo;
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  pinMode(34,INPUT);
  pinMode(32,INPUT);
}
 
void loop() {

  wertl= analogRead(34);
  Fitl=map(wertl,0,maxl,0,9);
  wertr= analogRead(32);
  Fitr=map(wertr,0,maxr,0,9);
  //steuerung links
  Links=Fitl;
  

  //steuerung rechts
  switch(Fitr)
  {
   case 1:  Rechts='a';break;//a
   case 2:  Rechts='b';break;//b
   case 3:  Rechts='c';break;//c
   case 4:  Rechts='d';break;//d
   case 5:  Rechts='e';break;//e
   case 6:  Rechts='f';break;//f
   case 7:  Rechts='g';break;//g
   case 8:  Rechts='h';break;//h
   case 9:  Rechts='i';break;//i
  }

//Steuerung ++
String Steuerung=String('p'+Links+Rechts);//zusammenfügen in string(p ist pfuschlösung)
//send Steuerung
delay(10);

  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  delay(2000);
}
//ESP32 receiver
#include <esp_now.h>
#include <WiFi.h>

#include <Robojax_L298N_DC_motor.h>
// motor 1 settings
#define CHA 0
#define ENA 13 // blau, this pin must be PWM enabled pin if Arduino board is used
#define IN1 5 // braun
#define IN2 4 //gelb

// motor 2 settings
#define IN3 2 // grau
#define IN4 15 // weiß
#define ENB 12// orange, this pin must be PWM enabled pin if Arduino board is used
#define CHB 1

const int CCW = 2; // do not change
const int CW  = 1; // do not change

#define motor1 1 // do not change
#define motor2 2 // do not change

// use the line below for two motors
Robojax_L298N_DC_motor motor(IN1, IN2, ENA, IN2, IN3, ENB, true);
char chama[4];
char Rechts;
char Links;
  
// Structure example to receive data
// Must match the sender structure
typedef struct struct_data {
  //String message ="";
  char chama[4];
  char Rechts;
  char Links;
} struct_data;

// Create a struct_message called myData
struct_data myData;

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  //Serial.begin(115200);
  if (len == 0)
  {
    return;
  }
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Rechts: ");
  Serial.println(myData.Rechts);
  Serial.print("Links: ");
  Serial.println(myData.Links);;
  

}

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  motor.begin();
 //BT.begin(9600);      
 
 // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);
}

 void simpleMovements(){
  
   //splitting  
   // char chama[4]="2d4";     
       Rechts=chama[1];//buchstabe
       Links=chama[2];//Zahl 
       //Serial.println("message"); Serial.println(message);  Serial.println("\n");
       Serial.println("links"); Serial.println(Links);  Serial.println("\n");
       Serial.println("rechts");  Serial.println(Rechts);Serial.println("\n");
        
    //richtung links
       if(Links == '1') {          
            motor.rotate(motor1, 80, CW);  
            }
      if(Links == '2') {          
            motor.rotate(motor1, 120, CW);  
            }
      if(Links == '3') {          
            motor.rotate(motor1, 160, CW);  
            }
      if(Links == '4') {          
            motor.rotate(motor1, 200, CW);  
            }
      if(Links == '5') {     //stand     
            motor.rotate(motor1, 0, CW);  
            }
      if(Links == '6') {          
            motor.rotate(motor1, 200, CCW);  
            }
      if(Links == '7') {          
            motor.rotate(motor1, 160, CCW);  
            }
      if(Links == '8') {          
            motor.rotate(motor1, 120, CCW);  
            }
      if(Links == '9') {          
            motor.rotate(motor1, 80, CCW);  
            }       
   
    //rechts
     if(Rechts == 'a') {          
            motor.rotate(motor2, 80, CW);
            }
      if(Rechts == 'b') {          
            motor.rotate(motor2, 120, CW);
            }
      if(Rechts == 'c') {          
            motor.rotate(motor2, 160, CW);
            }
      if(Rechts == 'd') {          
            motor.rotate(motor2, 200, CW);
            }
      if(Rechts == 'e') {     //stand     
            motor.rotate(motor2, 0, CW);
            }
      if(Rechts == 'f') {          
            motor.rotate(motor2, 200, CCW);
            }
      if(Rechts == 'g') {          
            motor.rotate(motor2, 160, CCW);
            }
      if(Rechts == 'h') {          
            motor.rotate(motor2, 120, CCW);
            }
      if(Rechts == 'i') {          
            motor.rotate(motor2, 80, CCW);
            }        
}


 
void loop() {

 
}

Bei C++ musst du unterscheiden zwischen

  • einzelnen Zeichen char c {'p'};
  • Texten char txt[] {"pf7"};
  • String-Objekten

Wenn String Objekte funktionieren ist es nett; wenn nicht, ist die einfachste Löung immer, sie nicht zu verwenden.

Nachtrag:

typedef struct struct_message { 
 String Links;
 String Rechts;
} struct_message;

Das macht sicher Probleme, da witzigerweise die zwei Buchstaben Rechts und Links gar nicht in struct_message enthalten sind.

if(Links == '1') {
das sieht aus, als sollte Links als einfacher char definiert sein.

Ich verwende Arduino funktioniert es da anders

Hmm hätten Sie vielleicht eine Idee wie ich es anders lösen könnte?

So etwa:

byte Fitl = random(10); // eine Zahl 0 .. 9
byte Fitr = random(8); // eine Zahl 0 .. 7
char Links = '0' + Fitl; // ein Buchstabe '0' ... '9'
char Rechts = 'a' + Fitr; // ein Buchstabe 'a' ... 'i'
char Steuerung[4] = "p**";
Steuerung[1] = Links;
Steuerung[2] = Rechts;
Serial.println(Steuerung); // liefert z.B. "p3c"

Ja das macht Sinn Danke, aber was passiert jetzt eigentlich mit den Strings im typedef?

Ein String Objekt sind 6 Byte: Ein Zeiger, die reservierte Länge und die benutzte Länge.
Oder so ähnlich. Jedenfalls hast du nichts davon, das auf eine andere Maschine zu kopieren.

Wenn es denn unbedingt Zeichenketten sein müssen, dann muss man arrays of char verwenden.
Der Array of char wird auf die maximal mögliche Länge an Zeichen definiert und dann werden auch immer diese Anzahl Bytes übertragen.

                                                                      1234567 
                             10        20        30        40        50      
                    01234567890123456789012345678901234567890123456789012345
char myText[57] = {"ich bin der allerlängste Text der Übertragen werden soll"}

Zeichenkette ist 56 Zeichen lang plus eine Null ganz am Ende
als "String ist zu Ende" Kennzeichnung
Deshalb 57 Array-Elemente aber Indexierung beginnt bei 0...56
myText[0] ='i';
myText[1] ='c';
myText[2] ='h';
usw.

Es gibt functions mit denen man Strings in array of chars umkopieren kann.

myString.toCharArray(  myText,sizeof((myText)   );

parallel zum Übertragen würde ich mir immer auch den Inhalt der Array of char auf der Senderseite und der Empfängerseite auf den seriellen Monitor ausgeben lassen

vgs

Was meinst du genau damit?

typedef struct struct_message { 
 myCharArrayLinks[256]; // statt String Links;
 myCharArrayRechts[256]; // statt  String Rechts;
} struct_message;

Auf der SenderSeite

Serial.print("#");
Serial.print(struct_message.myCharArrayLinks);
Serial.print("#");
Serial.println();

Serial.print("#");
Serial.print(struct_message.myCharArrayRechts);
Serial.print("#");
Serial.println();

Und genau das gleiche auf der Empfängerseite

Nehmen wir an du hast in der struc_message auf der Senderseite
struct_message.myCharArrayLinks enthält "Hallo links 123"
struct_message.myCharArrayRechts enthält "rechts aber Hallo 9999""

Dann erscheint im seriellen Monitor

#Hallo links 123#
#rechts aber Hallo 9999#

Dadurch das am Anfang und am Ende ein "#" mitgedruckt wird fällt auch auf wenn da ein Steuerzeichen "neue Zeile" oder carriage return dazwischen hängt

Ebenso kann man dann vergleichen ob die Daten wirklich 1:1 übertragen wurden oder ob etwas abgeschnitten wird oder noch etwas altes im array steckt usw.

vgs

Moin @dilay123,

wenn man auf das Symbol der postenden Person klickt, kann man sehen, seit wann diese beim Forum angemeldet ist ...

Bei @michael_x ist das der 13. März 2012. Bist Du sicher, dass ihm der Umgang mit einem Arduino (oder auch einem ESP32) noch Schwierigkeiten bereitet? :wink:

Gruß

ec2021

Ich weiß nicht ob er noch Schwierigkeiten damit hat oder nicht

Was ich damit sagen wollte ist, dass @michael_x über einen ordentlichen Sack an Erfahrung verfügt und daher seine Hinweise für Boards jeglicher Art zutreffen, soweit sie mit C oder C++ programmiert werden; er hat zudem mit seinem Nachtrag in Post #2 schon den entscheidenden Tipp gegeben.

Die Tatsache, dass Du beim Empfänger nicht das erhältst, was Du erwartest, liegt daran, dass Du nicht das sendest, was Du gerne senden würdest :wink:

In Deinem Sketch aus Post #1 findest Du folgende Deklarationen:

String Links;
String Rechts;

//mac address 94:B9:7E:DA:4C:74
uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xDA, 0x4C, 0x74};

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message { 
 String Links;
 String Rechts;
} struct_message;

// Create a struct_message called myData
struct_message myData;
  • Du deklarierst die globalen Stringvariablen Links, Rechts und die Struktur myData.
  • Du veränderst die Variablen Links und Rechts, sendest dann aber die Struktur myData.

Links, Rechts und myData sind völlig getrennt im Speicher angelegte Variable und haben nichts miteinander zu tun. Die beiden Anteile der Struktur myData werden so adressiert:

myData.Rechts = "Dies steht nun in myData.Rechts";
myData.Links  = "Jetzt steht etwas in myData.Links!";

Entweder ersetzt Du alle Verwendungen von Links und Rechts durch myData.Links und myData.Rechts oder Du weist die Werte von Links/Rechts direkt vor dem Senden den Strukturelementen zu:

  // Send message via ESP-NOW
  myData.Rechts = Rechts;
  myData.Links  = Links;
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

So wird auch das, was in den Strings Links und Rechts steht, gesendet!

Gerne mal versuchen ...

Gruß
ec2021

Ein (uraltes) Zitat von mir: "Das Dumme an Computern ist, dass sie das tun, was man eintippt, und nicht das, was man eigentlich will ..." - Ob das in Zukunft mit AI gelöst oder nur auf ein anderes Level gehoben wird, steht noch abzuwarten ... :wink:

Ich habe das ganze gerade mal ausprobiert, jedoch wird Rechts und Links dennoch nicht geschickt es kommt nur etwas am Serial Monitor der Sender Seite was raus.

Ich vermute, die Fehler werden dann besser versteckt sein und schwerer zu finden.

Gruß Tommy

In derartigen Fällen hat es sich bewährt, die Aufgabe in kleine, überschaubare Anteile aufzuteilen und diese erst einmal zum Laufen zu bringen.

In diesem Fall:

  • Eine einfache Senderoutine mit festen (simplen) Werten auf dem ersten und eine Empfangsroutine auf dem zweiten Board und testen.
  • Wenn das läuft: Auf der Sendeseite die zu sendenden Daten auf die gewünschten Werte anpassen, auf der Empfängerseite auswerten und testen ...
  • Wenn das läuft: Routinen in die Zielsoftware einbauen und ... testen ...

Viel Erfolg!

Gruß
ec2021

Ihr scheint immer noch nicht verstanden zu haben, das man Strings Variablentyp String mit groß geschriebenem "S"

NICHT

senden kann!

Ein String ist

Jetzt überlege mal wie wird das mit 6 byte organisiert um einen String von 20 byte Länge zu übertragen?

Die 6 byte enthalten die Speicher-ADRESSE des Strings und die Länge des Strings.

Es nützt überhaupt nichts die Speicher-ADRESSE auf dem Sende-ESP and den Empfangs-ESP zu übertragen.

Der Empfänger_ESP kann NICHT auf den RAM des Sende-ESP zugreifen. Deswegen funkt du ja die Daten.

Es

muss

mit einem Array of char gesendet werden.
damit WIRKLICH byte für byte übertragen wird.

Im übrigen ist eine Aussage wie

Was bedeutet das Wörtchen "das" in diesem Fall??

Das ist nutzloses Zeitverschwendung weil Sie nur ein neues Posting nach sich zieht

poste deinen kompletten Sketch

damit man im TATSÄCHLICH verwendeten Sourcecode nach dem Fehler suchen kann.

Du bist hier in einem Userforum. Da nützt snap-chattering NULL.

Harte Fakten in Form von komplettem Sourcecode und die Texte aus der Ausgabe auf dem seriellen Monitor (ebenfalls als Code-section)

vgs

Hier mein code und die Texte aus der Ausgabe am seriellen Monitor

//Sender

#include <esp_now.h>
#include <WiFi.h>

  int lesel;//speicher für fitting
  int leser;
  int i;    //zähler
  int maxl; //gefitteter Wert
  int maxr;
  int Fitl; //werte für switch
  int Fitr;
  int wertl;//einzelmessungen
  int wertr;
  String Links;
  String Rechts;

// REPLACE WITH YOUR RECEIVER MAC Address 
//Sender COM7 ESP rechts
uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xDA, 0x4C, 0x74};

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
  String Links;
  String Rechts;
} struct_message;

// Create a struct_message called myData
struct_message myData;

esp_now_peer_info_t peerInfo;

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  //fitting(10 messungen werden über zeitraum von 2 sekunden abgenommen und der durchschnitt wird ausgerechnet.
  delay(300);
  for(i=0;i<=10;i++)
  {
    lesel= analogRead(34)+lesel;
    leser= analogRead(32)+leser;
    delay(20);
  }
  maxl=lesel/10;
  maxr=leser/10;

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
    }
    pinMode(34,INPUT);
    pinMode(32,INPUT);
}
 
void loop() {
  // Set values to send
  wertl= analogRead(34);
  //Fitl=map(wertl,0,maxl,0,9);
  Fitl=5;
  wertr= analogRead(32);
  //Fitr=map(wertr,0,maxr,0,9);
  Fitr=6;
  //steuerung links
  Links=Fitl;
  

  //steuerung rechts
  switch(Fitr)
  {
   case 1:  Rechts='a';break;//a
   case 2:  Rechts='b';break;//b
   case 3:  Rechts='c';break;//c
   case 4:  Rechts='d';break;//d
   case 5:  Rechts='e';break;//e
   case 6:  Rechts='f';break;//f
   case 7:  Rechts='g';break;//g
   case 8:  Rechts='h';break;//h
   case 9:  Rechts='i';break;//i
  }

  
  //Steuerung ++
  String Steuerung=String('p'+Links+Rechts);//zusammenfügen in string(p ist pfuschlösung)
  //send Steuerung
  delay(10);
  Serial.println(Steuerung);
  
  // Send message via ESP-NOW
  myData.Rechts = Rechts;
  myData.Links  = Links;
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
   
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  delay(2000);
}

Serial Monitor vom Sender

p5f
Sent with success

Last Packet Send Status:	Delivery Fail

//Receiver

#include <esp_now.h>
#include <WiFi.h>

int lesel;//speicher für fitting
int leser;
int i;    //zähler
int maxl; //gefitteter Wert
int maxr;
int Fitl; //werte für switch
int Fitr;
int wertl;//einzelmessungen
int wertr;
String Links;
String Rechts;

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
    String Links;
    String Rechts;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Rechts: ");
  Serial.println(myData.Rechts);
  Serial.print("Links: ");
  Serial.println(myData.Links);;
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {

}

Serial Monitor vom Receiver

Rechts:
Links:

Du überträgst zwar einzelne Bytes durch das Typecasting

  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

Das (uint8_t *) wandelt die Zeichen des Strings in Bytes um.
Aber das nützt nichts

Wenn du auf der Empfängerseite genau die gleiche Struktur verwendest dann ist in der Struktur selbst nur 6 Byte
Adresse auf den String im RAM des Empfänger-ESP
und Länge des Strings im Empfänger-ESP.
Das bedeutet wenn du ein "ABC" sendest dann steht im
Adressbyte auf der Empfängerseite "ABC" dezimal 65,66,67 aber auf keinen Fall die wirkliche Adresse an dem die Zeichen im RAM des Empfänger-ESP gespeichert werden.

Und erschwerend kommt hinzu dass sich diese Adresse bei jeder neuen Zuweisung an den String auch noch ändert!

Deshalb kannst du das mit dem Senden von Variablentyp "String"

komplett vergessen.

geht das in deinen Kopf rein??

In deinem Demo-Sketch sendest du einzelne Zeichen

   case 1:  Rechts='a';break;//a
   case 2:  Rechts='b';break;//b
   case 3:  Rechts='c';break;//c
   case 4:  Rechts='d';break;//d
   case 5:  Rechts='e';break;//e
   case 6:  Rechts='f';break;//f
   case 7:  Rechts='g';break;//g
   case 8:  Rechts='h';break;//h
   case 9:  Rechts='i';break;//i
  }

Für die 'a', 'b', 'c' usw.
kannst du den Variablentyp char definieren
char hat ein byte. Das lässt sich eins zu eins senden.

Noch eine mögliche Fehlerquelle:
Du verwendest als boradcast-adresse eine spezifische Adresse

uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xDA, 0x4C, 0x74};

broadcasting heißt sende an ALLE.
Der Name passt also nicht.
wenn du versehentlich Sender und Empfänger-MAC-Adresse verwechselt hast dann kommt natürlich auch nichts an.

Verwende zuerst die wirkliche broadcast-adresse zum testen.

Das ist wie du willst ein Paket verschicken und es soll an Eichenstrasse 5 gehen.

Du hast aber versehentlich Buchenstrasse 18 auf das Paket geschrieben.

Dann kannst du so viele Pakete an Buchenstrasse 18 senden wie du willst es wird NIEMALS in Eichenstrasse 5 ankommen

Wenn du sagst mache eine Postwurfsendung im ganzen Ort dann kommt auch eine Postwurfsendung in Eichenstrasse 5 an.
deshalb

//statt uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xDA, 0x4C, 0x74};
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

Was ist denn der Endzweck der Daten links/rechts?

Lässt du da auf der linken/rechten Hälfte eines Displays verschiedene TEXTE anzeigen oder geht es um etwas anderes?

vgs

Es werden halt bestimmte Daten von einer EMG Schaltung aufgenommen und durch die ESPs an ein Auto weitergeleitet. Diese soll sich dann selbständig bewegen können.