The serial don't send me the same data with the same string

Hello i never had this type of trouble, i need to send data with RS232 but the first time it work correctly and the second time i don't have the same data.
serial

i work on a arduino nano, if anyone have an idea?

/************************************************************************

************************************************************************/
#define RX 11 // affectation des broches
#define TX 10

#include <SoftwareSerial.h> // appel de la bibliothèque
SoftwareSerial RS232(RX, TX); // création de l'objet RS232

//const String Chaine_Intro = String(char(0x7E) + char(0x01));
String Packet = "";
const String Chaine_Intro = String(char(0x7E)) + String(char(0x01));
const String Adresse = String(char(0xFE)) + String(char(0xFE));
const String Cmd_INST = String(char(0x49)) + String(char(0x4E)) + String(char(0x53)) + String(char(0x54));
const char Msg_Sep = char(0x00);
const String Num_Prog = String(char(0x0A));
const String FILL  = String(char(0x09)) + String(char(0x01)) + Msg_Sep;
const String Maintien = String(char(0x09));
const String Defilement = String(char(0x01));
const String Nom_Programme = "Program01";
const String Chaine_Outro = String(char(0xFF)) + String(char(0xFF)) + String(char(0x7E)) + char(0x00);
const String Vert = String(char(0x02));
const String Rouge = String(char(0x01));
const String Blanc = String(char(0x07));
byte SCRC1[]={0x00,0x00,0x00,0x00};
byte SCRC2[]={0x00,0x00,0x00,0x00};
String Couleur = String(char(0x07));    //blanc
String Police = String(char(0x01)) + String(char(0x18)) + String(char(0x01)) + String(char(0x18));    //par defaut
String Texte = "Bonjour a VOUS !!";
int CRC1,CRC2;
const String Msg_Fin = String(char(0xFF));
bool val;

int i;
byte Entree = 0;


void setup()
{
pinMode(13, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, INPUT);
pinMode(19, INPUT);
pinMode(20, INPUT);
pinMode(21, INPUT);
pinMode(22, INPUT);
pinMode(23, INPUT);
pinMode(24, INPUT);
pinMode(25, INPUT);
pinMode(26, INPUT);
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT);
pinMode(6, INPUT);
pinMode(7, INPUT);
pinMode(8, INPUT);
pinMode(12, INPUT);

RS232.begin(9600); // initialisation de la liaison série RS232
Serial.begin(57600);//pour test
const String RAZ = String(char(0x7E)) + String(char(0x01)) + String(char(0xFE))+ String(char(0xFE)) + char(0x00) + char(0x04) + char(0x44) + String(char(0x41)) + String(char(0x4C)) + String(char(0x4C)) + String(char(0xFF)) + String(char(0xFF)) + String(char(0x7E)) + char(0x00);
Envoie (RAZ);
}



void loop()
{

Entree = (digitalRead(2)*1)+(digitalRead(3)*2)+(digitalRead(4)*4);


delay(4000);
  

switch (Entree) {
  case 0:
    Afficheur ("Rien",Rouge,"1");
    break;
  case 1:
    Afficheur ("MESSAGE 1",Blanc,"1");
    break;
  case 2:
    Afficheur ("MESSAGE 2",Blanc,"1");
    break;
  case 3:
    Afficheur ("MESSAGE 3",Blanc,"1");
    break;
  case 4:
    Afficheur ("MESSAGE 4",Blanc,"1");
    break;
  case 5:
    Afficheur ("MESSAGE 5",Blanc,"1");
    break;
  case 6:
    Afficheur ("MESSAGE 6",Blanc,"1");
    break;
  case 7:
    Afficheur ("MESSAGE 7",Blanc,"1");
    break;
  case 8:
    Afficheur ("MESSAGE 8",Blanc,"1");
    break;
  case 9:
    Afficheur ("MESSAGE 9",Blanc,"1");
    break;

}


}

void Afficheur(String Txt,String Coul,String Pol){
  int CRC1,CRC2;
//choix couleur
//    if (Coul = "blanc"){
//      Couleur = String(char(0x07));    //blanc
//    }
//    else if (Coul = "cyan"){
//      Couleur = String(char(0x06));    //cyan
//      }
//    else if (Coul = "rose"){
//      Couleur = String(char(0x05));    //rose
//      }
//    else if (Coul = "bleu"){
//      Couleur = String(char(0x04));    //bleu
//      }
//    else if (Coul = "jaune"){
//      Couleur = String(char(0x03));    //jaune
//      }
//    else if (Coul = "vert"){
//      Couleur = String(char(0x02));    //vert
//      }
//    else if (Coul = "rouge"){
//      Couleur = String(byte(0x01));    //rouge
//      }
//    else {
//      Couleur = String(char(0x07));    //blanc
//      }
Couleur=Coul;
  
  CRC1 = 37 + Nom_Programme.length() + Txt.length();
  CRC2 = Nom_Programme.length() + Txt.length();


  SCRC1[2] = byte (CRC1);
  SCRC1[1] = byte (CRC1>>8);

  SCRC2[2] = byte (CRC2);
  SCRC2[1] = byte (CRC2>>8);
  Couleur = String(char(0x02));    //vert
  Envoie(String(char(0x7E)) + String(char(0x01)) + Adresse);      //construction 1er partie trame a envoyer
  //Envoie(Packet);
  Serial.write(SCRC1[1]);
  Serial.write(SCRC1[2]);                                     //CRC1

  //Packet = Cmd_INST + char(NULL) + char(NULL) + Num_Prog + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + FILL + Couleur + Police + char(0x00) + char(0x00) + Maintien + Defilement + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00);    //construction 1er trame a envoyer
  Packet = String(char(0x49)) + String(char(0x4E)) + String(char(0x53)) + String(char(0x54)) + char(0x00) + char(0x00) + char(0x01) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + FILL + Couleur + Police + char(0x00) + char(0x00) + Maintien + Defilement + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00) + char(0x00);    //construction 1er trame a envoyer
  if (Packet.charAt(7) != char(0x0A)){
    digitalWrite (13,1);
    Packet.remove(7,0);
  }
  Envoie(Packet);
  Serial.write(SCRC2[1]);
  Serial.write(SCRC2[2]);
  Packet = Nom_Programme + Txt + Chaine_Outro;      //construction trame a envoyer
  Envoie(Packet);
 }

void Envoie(String STRG){
  int Long_Msg;
  Long_Msg = STRG.length();
  for (int i=0;i<Long_Msg;i=i+1) // envoi caractère par caractère
    {
    while (Serial.availableForWrite()>63) {
    delay(10);
    }
    //RS232.write(STRG.charAt(i));
    Serial.write(STRG.charAt(i));
    }
  }

Don't use the "String" class on AVR's like the Nano. "String" causes all sorts of weird behaviour, memory corruption and crashes.

Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation of your ask like how things are wired and powered for example).


you probably should look into byte arrays like

const byte Chaine_Intro[] = {0x7E, 0x01};
const byte Adresse[] = {0xFE, 0xFE};
const byte Cmd_INST[] = {0x49, 0x4E, 0x53, 0x54};
const byte Msg_Sep[] = {0x00};
...

Why do you want your sketch to freeze if there is room for more than 63 characters in the output buffer?!?

OK, thanks i gonna try to avoid Strings.
i can only test this tomorrow.

yes,i need to delete this :sweat_smile:
its my last try to be certain the buffer is not the probleme.

thanks for the tips. i assume its the same with arduino uno?

it's just not the right storage for a byte array (and abuse of the String class can lead to issues)

for example if you insert a nulll character (your Msg_Sep) somewhere in the middle, that creates issues and the length won't be what you expect.

you don't need to pre-build the full binary command and send it in one go, just issue multiple write() to send the data

It is just not true that Strings cause memory corruption and crashes in AVR. Please provide an example sketch. Strings are very very safe on AVR boards and don't crash. The only 'weird' behaviour is that when they run out of memory Strings just stop adding chars. See my tutorial on Taming Arduino Strings

However in this case I agree with J-M-L, if you have embedded nulls 0x00 then Strings are not the thing to use.

Here you go!

Thanks that is a very nice example.

A simple application of Guideline 6) from Taming Arduino Strings gives the unending output (below).

You may have found a bug in the library, there are a few, see the section
Some Errors in Arduino's WString code in the SafeString tutorial. I will have a closer look at what is happening under the hood.

Output

BOOT
*i=1461i=1462i=1463i=1464i=1465i=1466i=1467
*i=2761i=2762i=2763i=2764i=2765i=2766i=2767i=2768i=2769
*i=4051i=4052i=4053i=4054
*i=5351i=5352i=5353i=5354i=5355i=5356
*i=6651i=6652i=6653i=6654i=6655i=6656i=6657
*i=7941
*i=9241i=9242i=9243i=9244i=9245
*i=1451i=1452i=1453i=1454i=1455i=1456i=1457i=1458i=1459
*i=2751i=2752i=2753i=2754i=2755i=2756i=2757i=2758
*i=4051i=4052i=4053i=4054i=4055i=4056i=4057i=4058
*i=5341i=5342
*i=6641i=6642i=6643i=6644i=6645i=6646i=6647
*i=7931
*i=9231i=9232i=9233i=9234i=9235
*i=1441i=1442i=1443i=1444i=1445i=1446i=1447i=1448i=1449
*i=2741i=2742i=2743i=2744i=2745i=2746i=2747i=2748i=2749
*i=4041i=4042i=4043i=4044i=4045i=4046i=4047
*i=5331i=5332
. . . . 

The revised sketch, following the guidelines in Taming Arduino Strings , is

//from https://forum.arduino.cc/t/strings/672616/12
// re https://forum.arduino.cc/t/the-serial-dont-send-me-the-same-data-with-the-same-string/869353/11
void setup() {
  Serial.begin(115200);
  for (int i = 10; i > 0; i--) {
    Serial.print(' '); Serial.print(i);
    delay(500);
  }
  Serial.println();
  Serial.println("BOOT");
}

void gonna_bite_ya() {
  unsigned long ms = millis();
  String s = "*";
  for (int i = 0; i < 10000; i++) {
    // Guideline 6) from Taming Arduino Strings
    // https://www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/index.html
    // Do not use the String + operator at all
    //   so break the s += "i=" + i; into two statements
    s += "i=";
    s += i;
    if (i % 10 == 0) {
      s = "*";
    }
    if (millis() - ms >= 100)
    {
      ms += 100;
      Serial.println(s);
    }
  }
}

void loop() {
  gonna_bite_ya();
}

So this seemed to be a very opinionated statement

And now you say

You may have found a bug in the library, there are a few,

So much for the fuss…

May be best to go back to cStrings, they are well understood :wink:

And still very fragile. Better to fix the odd error in the String library.

They are not fragile at all. they need a bit of love and care and will do wonder on small micros :wink:

(You should propose some bug correction in GitHub for the String class, you know it well by now)

1 Like

The compiler does not bark when compiling my example and people will accept this as working code, even if it is not. I have never heard of the guide linked to and I think most of the people who get stuck due to the improper use of "String" will not even understand the guide if they knew about it.

On AVR's (and any other MCU/device without a half-decent MMU): Do NOT use the String class and do NOT advice anyone to do so! It is a lazy mans habbit and a bad choice of design which may result in instability and bugs that are hard to debug. <= PERIOD!

1 Like

It is trivial to generate non-String sketches that compile but crash.
But you are correctly holding the String library to a higher standard.
No complaint about that. It should not crash.
It is the foundation of text processing in Arduino and should be fixed.

Yes, but in most cases the cause is much more transparent than having the String class being the culprit. It is easier to avoid the usage of the String class than it is to understand and mitigate its caveats.

No new bug in the String library, the error in your code is a basic C code error not a String error.
the statement
s += "i=" + i;
more clearly written as
s += ("i=" + i);
So what you are asking the code to do it add i to the char* pointing to "i=" and being C it compiles anyway and you get what you ask for even if it is garbage.

To use String + operator you need a String on at least one side of the + operator
s += String("i=") +i;
or
s += "i=" + String(i);
works.

Now it is not uncommon for even experienced programmers to forget how the left hand side of this equations works, and users new to C miss it completely, hence my
Guideline 6) Don't use the String + operator at all.
Nothing wrong with the + operator but it only works on Strings

So I stand by my statement

The same cannot be said of char pointer manipulations, J-M-L

My code works perfectly until the String class craps out.

Many inexperienced programmers will look at the String class as a convenient way of handling strings and they will consider a sketch that compiles and runs as a working sketch until their gizmo locks up for no apparent reason. Then they fail in understanding what might be the problem and another "Fix my gizmo/sketch" topic is posted. In 99% of these cases, there would have been no issue if the String class was not part of the sketch. Even if the String class is flawless when properly used, it is broken beyond repair for that reason.

As noted above it is not the String class that is the problem in your example sketch.
So that statement is not supported by the example you have given.
Do you have another one?

Using the String class saves you from buffer overflow and missing terminating '\0' and gives you convenient text manipulation methods. It does not absolve you from writing the rest of your code correctly. Unfortunately new users need to learn the idiosyncrasies (advantages?) of C/C++