Serial communication seems to be slower now

I will make a new topic for this question, because it has not really to do with my original post about the sending with a checksum.
Now, the problem is, that my original code transmitted the data with simple serial.write() and received the first character, a letter with serial.read() and after that gone in a switch/case to store the value to the correct designation with serial.parseInt(). That worked really good and fast enough to run the code to move servos and lights that are controlled with joysticks and buttons.
Because I received sometimes a bad value, that moved the servos wrong, I had decided to rewrite the sending method with a checksum. And because I needed some more UART ports, I have added the SC16IS750 over I2C, what should not be a problem. I2C is much faster as serial UART.
The updated code looks now like that:

Master sender:

/*Arduino 1 has the SC16IS750 connected on SDA/SCL
 *TX/RX of the SC16IS750 is connected to Arduino 2
 *VCC/GND
 *I2C of the SC16IS750 is connected to VCC
 *A0 and A1 of the SC16IS750 is connected as shown in the address table below
 */
 
#include <Wire.h>
#include <SC16IS750.h>

SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA);   /*Address table:  A1    A0    Address
                                                                                               VDD   VDD    0x90 => AA
                                                                                               VDD   GND    0x92 => AB
                                                                                               VDD   SCL    0x94 => AC
                                                                                               VDD   SDA    0x96 => AD
                                                                                               GND   VDD    0x98 => BA
                                                                                               GND   GND    0x9A => BB
                                                                                               GND   SCL    0x9C => BC
                                                                                               GND   SDA    0x9E => BD
                                                                                               SCL   VDD    0xA0 => CA
                                                                                               SCL   GND    0xA2 => CB
                                                                                               SCL   SCL    0xA4 => CC
                                                                                               SCL   SDA    0xA6 => CD
                                                                                               SDA   VDD    0xA8 => DA
                                                                                               SDA   GND    0xAA => DB
                                                                                               SDA   SCL    0xAC => DC
                                                                                               SDA   SDA    0xAE => DD
                                                                                               */

const byte bufferSize {10};
char serialBuffer[bufferSize+1] {""};
char incomingData[bufferSize] {""};
char value[bufferSize] {""};
char variable[bufferSize] {""};
uint16_t crc = 0;    //checksum crc
byte crcData[2] {""};        //create array for packet serial
byte crcDataRec[2] {""};        //create array for packet serial

int E = 0;
int F = 0;
int G = 0;
int H = 0;
int BUT = 0;

const byte DPangle = 158;

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

void loop()
{
  readCommand(i2cuart);
  
  
  Serial.print("E = ");
  Serial.println(E);
  Serial.print("F = ");
  Serial.println(F);
  Serial.print("G = ");
  Serial.println(G);
  Serial.print("H = ");
  Serial.println(H);
  Serial.print("BUT = ");
  Serial.println(BUT);

  
  command("A01",i2cuart);
  command("B57",i2cuart);
  command("C"+String(DPangle),i2cuart);
  command("D122",i2cuart);
  command("@19",i2cuart);
 
}



void command(String value, Stream& stream) {
  memset(serialBuffer, 0, sizeof serialBuffer);
  sendToI2CUART(serialBuffer, value, stream);
}


void sendToI2CUART (char *const buffer, String command, Stream& stream)
{
  command.toCharArray(buffer, bufferSize);
  const size_t characters {strlen(buffer)};
  //Serial.print("laenge: "); Serial.println(characters);

  for(byte index = 0; index < characters; index++){            //create the checksum for the array data[i] with 0 <= i <= 3
        crc16(buffer[index]);                                  //call the function crc16
      }
      crc = getCRC();
      byte crcIndex = characters;
      byte crcIndex2 = crcIndex++;
      buffer[crcIndex] = crc >> 8;                         //store checksum in data array
      buffer[crcIndex2] = crc;
      crc = 0;
    
  for (byte i = 0; i < characters; i++){
      stream.write(buffer[i]);
      //Serial.print("gesendet: ");
      //Serial.println(buffer[i]);
  }
    stream.write('\0');
    stream.write(buffer[crcIndex]);
    //Serial.print("gesendet CRC: ");
    //Serial.println(buffer[crcIndex],HEX);
    stream.write(buffer[crcIndex2]);
    //Serial.print("gesendet CRC: ");
    //Serial.println(buffer[crcIndex2],HEX);
    stream.write('\n');

}


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

uint16_t getCRC() {
  return crc;
}


void readCommand(Stream& stream){

  char var = 0;
  int val = 0;
  byte i = 0;
  byte j = 0;
  byte k = 0;
  byte state = 0;

  while(stream.available()) {
    char m = stream.read();
    if(m == '\0') {
      state = 1;
      i = 0;
    }

    if(m == '\n') {
      state = 2;
      i = 0;
    }

    switch(state){
      case 0: incomingData[i++] = m;
              //Serial.print("incomingData = ");
              //Serial.println(incomingData[i]);
              break;
      case 1: if(m != '\0'){
                crcData[i++] = m;
                //Serial.print("empfangen CRC: ");
                //Serial.println(crcData[i]);
              }
              else {
                break;
              }
              break;
      case 2: for(byte index = 0; index < strlen(incomingData); index++){            //create the checksum for the array data[i] with 0 <= i <= 3
                crc16(incomingData[index]);                                  //call the function crc16
              }
              crc = getCRC();
              crcDataRec[0] = crc >> 8;                         //store checksum in data array
              crcDataRec[1] = crc;
              crc = 0;

              //Serial.print("crcData[0] = ");
              //Serial.println(crcData[0],HEX);
              //Serial.print("crcDataRec[0] = ");
              //Serial.println(crcDataRec[0],HEX);
              //Serial.print("crcData[1] = ");
              //Serial.println(crcData[1],HEX);
              //Serial.print("crcDataRec[1] = ");
              //Serial.println(crcDataRec[1],HEX);

              if(crcData[0] == crcDataRec[0] && crcData[1] == crcDataRec[1]) {
                while(i <= strlen(incomingData) ) {
                  if(isdigit(incomingData[i]) == true) {
                    value[j] = incomingData[i];
                    j++;
                    i++;
                  }
                  else {
                    variable[k] = incomingData[i];
                    k++;
                    i++;
                  }
                }
                memset(incomingData, 0, sizeof incomingData);
                j = 0;
                k = 0;
                i = 0;
      
                val = atoi(value);  //making the integer part
                var = variable[0];

                memset(value, 0, sizeof value);
                memset(variable, 0, sizeof variable);

                switch(var) {
                  case 'E' : E = val;
                             break;
                  case 'F' : F = val;
                             break;
                  case 'G' : G = val;
                             break;
                  case 'H' : H = val;
                             break;
                  case '#' : BUT = val;
                             break;
                }
              }
              else if(crcData[0] != crcDataRec[0] || crcData[1] != crcDataRec[1]){
                memset(incomingData, 0, sizeof incomingData);
              }
              state = 0;
              var = 0;
              val = 0;
              memset(crcData, 0, sizeof crcData);
              memset(crcDataRec, 0, sizeof crcDataRec);
              break;
    }
  }
}

Slave receiver:

/*Arduino 2 has the SC16IS750 connected on TX/RX
 */

const byte bufferSize {10};
char serialBuffer[bufferSize+1] {""};
char incomingData[bufferSize] {""};
char value[bufferSize] {""};
char variable[bufferSize] {""};
uint16_t crc = 0;    //checksum crc
byte crcData[2] {""};
byte crcDataRec[2] {""};

int A = 0;
int B = 0;
int C = 0;
int D = 0;
int BUT = 0;

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

void loop() {

  readCommand();

  
  Serial.print("A = ");
  Serial.println(A);
  Serial.print("B = ");
  Serial.println(B);
  Serial.print("C = ");
  Serial.println(C);
  Serial.print("D = ");
  Serial.println(D);
  Serial.print("BUT = ");
  Serial.println(BUT);


  command("E10");
  command("F5");
  command("G147");
  command("H251");
  command("#33");
  
}


void command(String value) {
  memset(serialBuffer, 0, sizeof serialBuffer);
  sendToUART(serialBuffer, value);
}


void sendToUART (char *const buffer, String command)
{
  command.toCharArray(buffer, bufferSize);
  const size_t characters {strlen(buffer)};
  //Serial.print("laenge: "); Serial.println(characters);

  for(byte index = 0; index < characters; index++){            //create the checksum for the array data[i] with 0 <= i <= 3
        crc16(buffer[index]);                                  //call the function crc16
      }
      crc = getCRC();
      byte crcIndex = characters;
      byte crcIndex2 = crcIndex++;
      buffer[crcIndex] = crc >> 8;                         //store checksum in data array
      buffer[crcIndex2] = crc;
      crc = 0;

  for (byte i = 0; i < characters; i++)
  {
    Serial.write(buffer[i]);
    //Serial.print("gesendet: ");
    //Serial.println(buffer[i]);
  }
  Serial.write('\0');
  Serial.write(buffer[crcIndex]);
  //Serial.print("gesendet CRC: ");
  //Serial.println(buffer[crcIndex],HEX);
  Serial.write(buffer[crcIndex2]);
  //Serial.print("gesendet CRC: ");
  //Serial.println(buffer[crcIndex2],HEX);
  Serial.write('\n');

}


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

uint16_t getCRC() {
  return crc;
}


void readCommand(){

  char var = 0;
  int val = 0;
  byte i = 0;
  byte j = 0;
  byte k = 0;
  byte state = 0;
  
  while(Serial.available()) {
    char m = Serial.read();
    if(m == '\0') {
      state = 1;
      i = 0;
    }

    if(m == '\n') {
      state = 2;
      i = 0;
    }

    switch(state){
      case 0: incomingData[i++] = m;
              //Serial.print("incomingData = ");
              //Serial.println(incomingData[i]);
              break;
      case 1: if(m != '\0'){
                crcData[i++] = m;
                //Serial.print("empfangen CRC: ");
                //Serial.println(crcData[i]);
              }
              else {
                break;
              }
              break;
      case 2: for(byte index = 0; index < strlen(incomingData); index++){            //create the checksum for the array data[i] with 0 <= i <= 3
                crc16(incomingData[index]);                                  //call the function crc16
              }
              crc = getCRC();
              crcDataRec[0] = crc >> 8;                         //store checksum in data array
              crcDataRec[1] = crc;
              crc = 0;

              //Serial.print("crcData[0] = ");
              //Serial.println(crcData[0],HEX);
              //Serial.print("crcDataRec[0] = ");
              //Serial.println(crcDataRec[0],HEX);
              //Serial.print("crcData[1] = ");
              //Serial.println(crcData[1],HEX);
              //Serial.print("crcDataRec[1] = ");
              //Serial.println(crcDataRec[1],HEX);
  
              if(crcData[0] == crcDataRec[0] && crcData[1] == crcDataRec[1]) {
                while(i <= strlen(incomingData) ) {
                  if(isdigit(incomingData[i]) == true) {
                    value[j] = incomingData[i];
                    j++;
                    i++;
                  }
                  else {
                    variable[k] = incomingData[i];
                    k++;
                    i++;
                  }
                }
                memset(incomingData, 0, sizeof incomingData);
                j = 0;
                k = 0;
                i = 0;
      
                val = atoi(value);  //making the integer part
                var = variable[0];

                memset(value, 0, sizeof value);
                memset(variable, 0, sizeof variable);

                switch(var) {
                case 'A' : A = val;
                           break;
                case 'B' : B = val;
                           break;
                case 'C' : C = val;
                           break;
                case 'D' : D = val;
                           break;
                case '@' : BUT = val;
                           break;
                }
              }
              else if(crcData[0] != crcDataRec[0] || crcData[1] != crcDataRec[1]){
                memset(incomingData, 0, sizeof incomingData);
              }
              state = 0;
              memset(crcData, 0, sizeof crcData);
              memset(crcDataRec, 0, sizeof crcDataRec);
              break;
    }
  }
}

The problem is, that when I move a joystick to send the data, it seems that the servos will not move smoothly as they did before with the normal serial.write(), serial.read() and serial.parseInt(). It looks like they received the data a lot slower now and the servos will not move as mentioned (smooth and corresponding to the joystick movements). The servos will not move the full path and it seems as they do not receive all angle values that the joystick sends with his moving path.
Could someone take a look at the new code and help to solve it what it makes slowly? When I test the transmission only, without some other code in the loop function (as posted here), it seems to send and receive on both sides (receiver and sender) fast enough. But the special thing is, that I have only updated the transmission code as posted, all other code in the loop is the same as at the beginning and that worked without any issues with the first simple transmission method.

Regards

Bally

The String type is not well suited for controllers with small RAM.

No?
I2C works at 100K, there are lots of serial speeds you can use that are much faster.

All those cosmetic serial print statements are slowing down the whole process.

Could you help me to make it better, please?

That is true, I2C can work up to 400k. But as I know, this is fast enough for normal I2C transmissions that works most better as UART.
The serial.print() outputs are added to show the transmission for testing and seeing if it transmitts the correct data. In the running code I have removed them. That means, it is really the String that causes the problems?! How to fix that?

Well much faster than that. The official top speed is 1MHz although if both ends can handle it it can run as fast as you want. I have run it at 5MHz between a Pi 2040 Pico and an OLED display.

Don’t use them in the first place.
The code for receiving data is quite complex given that it is only a single ASCII character command. Just use the ASCII byte, why bother converting it into a string.

I will try it if 400k makes any differences. I know only the option from the wire.h lib, the command Wire.setClock();. It is suggested to use it up to 400k. above that, it is not sure if the microcontroller supports it. I use an Uno and Mega.

Where I should move it?
I used only a string in the sending part that is converted to a char array, because I have to transmitt data as "H125" or the letter H and a stored value as posted in my code above. How to transmit something like that without a string? Is that possible? It is a combination of letters and numbers, sometimes a stored number and a letter, for example: a=3; and I have to send the letter H and the value from a.

The String type is a C++ invention. C instead uses char arrays for holding text. See the Serial output basics tutorial.

Can somebody help where all the tutorials have gone?

This I know, but did not understood how to make a char array instead of the string. I make also a char array from the strin with the command toCharArray(), if I know how to make that from beginning, I will try it! Some googling does not brought me forward. I really does not understand that part for some reason. If you have a link to the tutorials or can help with some code example?

Serial.write('H'); //write characters
Serial.print(125); //print value or variable as text

Yes, that was my first transmission version, but with the checksum that is not possible...
Also to have a simple sending command, I have made the function command(); and put in the data to send. That makes the code a lot easier and shorter.
And what was the main problem, the SC16IS750 is connected over I2C and needs a byte by byte transmission. I needed a method to transmit over the serial UART from Arduino and the SC16IS750 with one method. Other way the RAM is not big enough.

Perhaps to add something, the checksum I have added to receive the correct data. I have received sometimes a wrong value that moved the servo with a wrong angle.

Serial Input Basics - updated

Rather than that

void command(const char *value, Stream& stream) {
  memset(serialBuffer, 0, sizeof serialBuffer);
  sendToI2CUART(serialBuffer, value, stream);
}


void sendToI2CUART (char *const buffer,  const char *command, Stream& stream)
{
  //command.toCharArray(buffer, bufferSize);
  strncpy(buffer, command, bufferSize);

That's only one (bad) example of a usable tutorial. "Serial Basics" and most other tutorials have vanished - whereto?
Bad is the number of contributions, 3 for the tutorial itself then extending into 10 before the topic was locked.

The forum is a poor place for tutorials and hard to find with the new Forum GUI. Forum topics tend to expand into hundreds of contributions which make them unusable as compact tutorials.

That is a great tutorial anyway! But my transmission is a little more complex as the examples there. But anyway there has some good examples. Thanks for posting it!

Thanks a lot for this part of code! That is really all to change!? I thought to remove the string is more complex. I will try it out!

What makes it bad? It is a widely used/referenced approach.

Nothing, the "bad" was a relict from multiple edits.

That works with a very simple transmission test on a second Arduino I have here in my workshop. I will test it tomorrow in my system where it causes problems.
The only thing are the data I will send like that before where for example DPangle is a defined value and needs only the letter in front of it to receive "H158":

const byte DPangle = 158;

command("H"+String(DPangle));

How to solve that? Strcat will not work, because this way I have to declare for all commands two strings. Sometimes I have to send directly "H125" for example and that is only one string.

Do you actually have to concatenate the strings for transmission? Why not just send them consecutively?