user58373: I am using the attached code.
What I am trying to do is:
Test if there is a personalized "board serial number" written in the EEPROM (by previous code run)
If data found was not 7 characters (e.g SN-XXXX), then generate a serial number and save it to EEPROM
Problem is: it generates a serial correctly, it even stores and reads it a few times, but when I disconnect the USB cable and reconnect to test again, it returns some bad data from the EEPROM, like: ⸮^R⸮y⸮| which seems to pass my 7 characters test and it doesn't generate a new one.
What am I doing wrong ?

#include <EEPROM.h>

// board SERIAL number
char serial_characters[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"};
// will be filled as SN-A2KH
String serial_number;


void setup() {

  Serial.begin(9600);

  // Get the float data from the EEPROM at position 0
  EEPROM.get(0, serial_number);

  // serial from EEPROM valid
  if (serial_number.length() == 7) {
    Serial.println("Found valid serial in EEPROM");
    Serial.println(serial_number);
  }

  // serial from EEPROM not valid (e.g not: SN-XYZ5)
  if (serial_number.length() != 7) {

    Serial.println("Serial from eeprom is NOT 7 chars, generating a random serial");
    Serial.println(serial_number);

    // if analog input pin 0 is not connected, use noise from it in order to generate a random seed, otherwise random is not so random
    randomSeed(analogRead(0));

    // serial might be empty now, set a "SN-" prefix
    serial_number = "SN-";
    for (int i = 1; i <= 4 ; i++) {
      serial_number = serial_number + serial_characters[random(0, 35)];
    }
    Serial.println("Generated serial now: " + serial_number);

    // save to eeprom if format is valid
    if (serial_number.length() == 7) {
      EEPROM.put(0, serial_number);
      Serial.println("Written serial to EEPROM");
    }

  } // <<< serial from eeprom not correct, generated one

}

void loop() {}


user58373: Just to have the full working code, I ended up with this:
#include <EEPROM.h>

char serial_characters[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"};
// 7 chars for serial and one for string end '\0'
char serial_number[8];

void setup() {

  Serial.begin(115200);

  EEPROM.get(0, serial_number);

  // check found format
  if (serial_number[0] == 'S' && serial_number[1] == 'N'  && serial_number[2] == '-' && serial_number[7] == '\0') {

    Serial.println("serial from eeprom is valid");
    Serial.println((char*)serial_number);

  } else {

    Serial.println("no valid serial found in eeprom, generating new serial");

    // if analog input pin 0 is unconnected, use noise from it in order to generate a random seed, otherwise random is not so random
    randomSeed(analogRead(0));

    // generate a new serial
    serial_number[0] = 'S';
    serial_number[1] = 'N';
    serial_number[2] = '-';

    // overwrite ending chars of serial with random values
    serial_number[3] = serial_characters[random(0, 35)];
    serial_number[4] = serial_characters[random(0, 35)];
    serial_number[5] = serial_characters[random(0, 35)];
    serial_number[6] = serial_characters[random(0, 35)];

    // end string with null as raw C strings ?!
    serial_number[7] = '\0';

    Serial.println((char*)serial_number);

    // write new serial to eeprom
    EEPROM.put(0, serial_number);

  }

}

void loop() {

}


user7508: You are saving a String object in EEPROM, which is useless. A string
object does not store the contents of your string. Instead, it just
stores:

the memory address where the actual contents (the characters) is
stored
the amount of memory allocated for this contents
the number of characters that actually make the string

This is what you are storing to, and retrieving from EEPROM. So you get
the correct number of characters (third item in the list above), but the
memory address now points to uninitialized RAM.
I suggest instead storing in the EEPROM a raw C string, i.e. an array of
8 chars (7 printable chars plus the terminating NUL). You could achieve
this by just changing the declaration of serial_number:
char serial_number[8];

For checking the validity, I would just check that it starts with "SN-"
and the last char is a NUL:
if (memcmp(serial_number, "SN-", 3) == 0 && serial_number[7] == '\0') {
    ...
}

You could do a more stringent validation though, and check that the
other 4 chars are within the valid set.
Edit: to build serial_number with random chars:
strcpy(serial_number, "SN-");
for (int i = 3; i < 7; i++)
  serial_number[i] = serial_characters[random(0, 36)];
serial_number[7] = '\0'; // terminating NUL


58373: <p>I am using the attached code.
What I am trying to do is:</p>

<p>Test if there is a personalized "board serial number" written in the EEPROM (by previous code run)
If data found was not 7 characters (e.g <code>SN-XXXX</code>), then generate a serial number and save it to EEPROM</p>

<p>Problem is: it generates a serial correctly, it even stores and reads it a few times, but when I disconnect the USB cable and reconnect to test again, it returns some bad data from the EEPROM, like: <code>⸮^R⸮y⸮|</code> which seems to pass my 7 characters test and it doesn't generate a new one.</p>

<p>What am I doing wrong ?</p>

<pre><code>
#include &lt;EEPROM.h&gt;

// board SERIAL number
char serial_characters[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"};
// will be filled as SN-A2KH
String serial_number;


void setup() {

  Serial.begin(9600);

  // Get the float data from the EEPROM at position 0
  EEPROM.get(0, serial_number);

  // serial from EEPROM valid
  if (serial_number.length() == 7) {
    Serial.println("Found valid serial in EEPROM");
    Serial.println(serial_number);
  }

  // serial from EEPROM not valid (e.g not: SN-XYZ5)
  if (serial_number.length() != 7) {

    Serial.println("Serial from eeprom is NOT 7 chars, generating a random serial");
    Serial.println(serial_number);

    // if analog input pin 0 is not connected, use noise from it in order to generate a random seed, otherwise random is not so random
    randomSeed(analogRead(0));

    // serial might be empty now, set a "SN-" prefix
    serial_number = "SN-";
    for (int i = 1; i &lt;= 4 ; i++) {
      serial_number = serial_number + serial_characters[random(0, 35)];
    }
    Serial.println("Generated serial now: " + serial_number);

    // save to eeprom if format is valid
    if (serial_number.length() == 7) {
      EEPROM.put(0, serial_number);
      Serial.println("Written serial to EEPROM");
    }

  } // &lt;&lt;&lt; serial from eeprom not correct, generated one

}

void loop() {}
</code></pre>
 58373: <p>Just to have the full working code, I ended up with this:</p>

<pre><code>#include &lt;EEPROM.h&gt;

char serial_characters[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"};
// 7 chars for serial and one for string end '\0'
char serial_number[8];

void setup() {

  Serial.begin(115200);

  EEPROM.get(0, serial_number);

  // check found format
  if (serial_number[0] == 'S' &amp;&amp; serial_number[1] == 'N'  &amp;&amp; serial_number[2] == '-' &amp;&amp; serial_number[7] == '\0') {

    Serial.println("serial from eeprom is valid");
    Serial.println((char*)serial_number);

  } else {

    Serial.println("no valid serial found in eeprom, generating new serial");

    // if analog input pin 0 is unconnected, use noise from it in order to generate a random seed, otherwise random is not so random
    randomSeed(analogRead(0));

    // generate a new serial
    serial_number[0] = 'S';
    serial_number[1] = 'N';
    serial_number[2] = '-';

    // overwrite ending chars of serial with random values
    serial_number[3] = serial_characters[random(0, 35)];
    serial_number[4] = serial_characters[random(0, 35)];
    serial_number[5] = serial_characters[random(0, 35)];
    serial_number[6] = serial_characters[random(0, 35)];

    // end string with null as raw C strings ?!
    serial_number[7] = '\0';

    Serial.println((char*)serial_number);

    // write new serial to eeprom
    EEPROM.put(0, serial_number);

  }

}

void loop() {

}
</code></pre>
 7508: <p>You are saving a String object in EEPROM, which is useless. A string
object does not store the contents of your string. Instead, <a href="https://github.com/arduino/ArduinoCore-avr/blob/1.8.1/cores/arduino/WString.h#L196-L198" rel="nofollow noreferrer">it just
stores</a>:</p>

<ul>
<li>the memory address where the actual contents (the characters) is
stored</li>
<li>the amount of memory allocated for this contents</li>
<li>the number of characters that actually make the string</li>
</ul>

<p>This is what you are storing to, and retrieving from EEPROM. So you get
the correct number of characters (third item in the list above), but the
memory address now points to uninitialized RAM.</p>

<p>I suggest instead storing in the EEPROM a raw C string, i.e. an array of
8 chars (7 printable chars plus the terminating NUL). You could achieve
this by just changing the declaration of <code>serial_number</code>:</p>

<pre class="lang-cpp prettyprint-override"><code>char serial_number[8];
</code></pre>

<p>For checking the validity, I would just check that it starts with "SN-"
and the last char is a NUL:</p>

<pre class="lang-cpp prettyprint-override"><code>if (memcmp(serial_number, "SN-", 3) == 0 &amp;&amp; serial_number[7] == '\0') {
    ...
}
</code></pre>

<p>You could do a more stringent validation though, and check that the
other 4 chars are within the valid set.</p>

<p><strong>Edit</strong>: to build <code>serial_number</code> with random chars:</p>

<pre class="lang-cpp prettyprint-override"><code>strcpy(serial_number, "SN-");
for (int i = 3; i &lt; 7; i++)
  serial_number[i] = serial_characters[random(0, 36)];
serial_number[7] = '\0'; // terminating NUL
</code></pre>
