Preferences.h not working

Hello all!

I am trying to store values to the eeprom of the ESP32 and read it back out on power cycle. Unfortunately upon power cycling all values are 0. below is my code. i know i could use a loop for this, actually i have used it, I just removed it for debugging this problem. I only posted the relevant code. at some point the array is written with data, and the save variable is set to true. data should be written to eeprom. after i power cycle i read the eeprom and write it back to the array, so i would expect the array to have the same state as on the previous write. instead all values are at 0. what is wrong with my code?

#include <Preferences.h>
Preferences preferences;

String highscoreNames[10];
double highscoreScores[10];
bool savescore;

void setup(void) {
preferences.begin("highscores", false);

highscoreNames[0] = preferences.getString("name0", "--");
highscoreScores[0] = preferences.getDouble("score0", 0);
highscoreNames[1] = preferences.getString("name1", "--");
highscoreScores[1] = preferences.getDouble("score1", 0);
highscoreNames[2] = preferences.getString("name2", "--");
highscoreScores[2] = preferences.getDouble("score2", 0);
highscoreNames[3] = preferences.getString("name3", "--");
highscoreScores[3] = preferences.getDouble("score3", 0);
highscoreNames[4] = preferences.getString("name4", "--");
highscoreScores[4] = preferences.getDouble("score4", 0);
highscoreNames[5] = preferences.getString("name5", "--");
highscoreScores[5] = preferences.getDouble("score5", 0);
highscoreNames[6] = preferences.getString("name6", "--");
highscoreScores[6] = preferences.getDouble("score6", 0);
highscoreNames[7] = preferences.getString("name7", "--");
highscoreScores[7] = preferences.getDouble("score7", 0);
highscoreNames[8] = preferences.getString("name8", "--");
highscoreScores[8] = preferences.getDouble("score8", 0);
highscoreNames[9] = preferences.getString("name9", "--");
highscoreScores[9] = preferences.getDouble("score9", 0);
preferences.end();
}


void loop(void) {

 if (savescore== true)
  {

    Serial.println("highscore changed");
    Serial.println(highscoreScores[0]);
    preferences.begin("highscores", false);
    
      preferences.putString("name0", highscoreNames[0]);
      preferences.putDouble("score0", highscoreScores[0]);
      preferences.putString("name1", highscoreNames[1]);
      preferences.putDouble("score1", highscoreScores[1]);
      preferences.putString("name2", highscoreNames[2]);
      preferences.putDouble("score2", highscoreScores[2]);
      preferences.putString("name3", highscoreNames[3]);
      preferences.putDouble("score3", highscoreScores[3]);
      preferences.putString("name4", highscoreNames[4]);
      preferences.putDouble("score4", highscoreScores[4]);
      preferences.putString("name5", highscoreNames[5]);
      preferences.putDouble("score5", highscoreScores[5]);
      preferences.putString("name6", highscoreNames[6]);
      preferences.putDouble("score6", highscoreScores[6]);
      preferences.putString("name7", highscoreNames[7]);
      preferences.putDouble("score7", highscoreScores[7]);
      preferences.putString("name8", highscoreNames[8]);
      preferences.putDouble("score8", highscoreScores[8]);
      preferences.putString("name9", highscoreNames[9]);
      preferences.putDouble("score9", highscoreScores[9]);
      preferences.end();
      savescore = false;
  }
}

thank you very much!

Best regards

Igor

First of all, try to understand the purpose of this website. Then you could help your case by adding additional information like which MCU you are using and what errors you get and what about the missing data types?

Don't post snippets (Snippets R Us!)

Youre, right, sorry. I added the MCU and the datatypes of the arrays to the code. As for the snippet, I know due to tests that the rest of the code is working, and is only writing to the array when it is supposed to. For this reason I avoided posting 1300 lines. The only part relevant to the problem that is not posted is the part that updates the values inside the array, but as said, that part works and is properly changing the values inside the array.

Thank you very much for your time, and sorry for the missing information.

Problem is that "savescore" never becomes "true".

I know due to tests that the rest of the code is working

yeah, we have seen and heard that 100 times and some other part of the code is overflowing and overwriting an array or a variable and wreaked havoc...

➜ it's still not a minimum demonstrable code ...

may be you could also check if Preferences::begin() returns true

The following code works as expected on my ESP32:

void setup()
{
  Serial.begin(115200);
  while (!Serial) taskYIELD();

  Preferences pref;

  pref.begin("test", false);
  String v1 = pref.getString("Val1", "0");
  uint8_t v2 = pref.getUChar("Val2", 0);

  Serial.print("Val1=");
  Serial.println(v1);
  Serial.print("Val2=");
  Serial.println(v2);

  v2++;
  v1 = String(v2);
  
  pref.putString("Val1", v1);
  pref.putUChar("Val2", v2);
  pref.end();
}

And this means that your problem is in the code we cannot see.

Here is the full code:

#include <WiFi.h>
#include <WebServer.h>
#include <FastLED.h>
#include <sstream>
#include <ArduinoJson.h>
#include <Preferences.h>
#include "index.h"
#include "shoot.h"
#include "highscores.h"
//using std::literals::string_literals;

// Replace with your network credentials
const char* ssid     = "***********";
const char* password = "********";
WebServer server(80);

char htmlShootFull[50000];

bool startshooting = false; //prepare system
bool shooting = false; //active shooting

enum eProgStep {STARTUPTIMER, INCREASESHOT, WAITREACTION, SELECTTARGET, SETLEDS, WAITFORSHOT, CALCSCORE, WAIT, SAVEHIGHSCORE, END, SHOWGOOD, SHOWBAD};
eProgStep progStep = WAIT;

int targets[5]; //0 = not a target. 1 = target. 2 = swinging
unsigned long swingTargets[5];
int currMag = 0;
int currBull = 0;
int currMs = 0;
bool forceLeds = false;

unsigned long blinkswitch;
unsigned long startWaitReaction;
int reactionTime;
bool isOrange = false;

int micPin = 25;
int target1Pin = 32;
int target2Pin = 33;
int target3Pin = 34;
int target4Pin = 35;
int micVal;
int target1Val;
int target2Val;
int target3Val;
int target4Val;

#define LEDS_PER_TARGET  2
#define NUM_LEDS         8 //4*ledsPerTarget
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define DATA_PIN 22
CRGB leds[NUM_LEDS];

unsigned long startUpTime;
unsigned long startTime;
unsigned long startMagChange;
unsigned long lastLedWrite;
unsigned long startShowResultWrite;

String highscoreNames[10];
double highscoreScores[10];

double timeMag1[18];
double timeMag2[18];
double timeMag3[18];
double timeMag4[18];
double timeMag5[18];

double scoreMag1[18];
double scoreMag2[18];
double scoreMag3[18];
double scoreMag4[18];
double scoreMag5[18];

double totalTimeMag1;
double totalTimeMag2;
double totalTimeMag3;
double totalTimeMag4;
double totalTimeMag5;

double avgTimeMag1;
double avgTimeMag2;
double avgTimeMag3;
double avgTimeMag4;
double avgTimeMag5;

double totalScoreMag1;
double totalScoreMag2;
double totalScoreMag3;
double totalScoreMag4;
double totalScoreMag5;

double avgScoreMag1;
double avgScoreMag2;
double avgScoreMag3;
double avgScoreMag4;
double avgScoreMag5;

double totalTime;
double avgTime;
double totalScore;
double avgScore;
double rankingAvgScore;

double startdelay = 5;
double shoottimeout = 3;
int magchangetime = 3;
int magchangemin1 = 0;
int ntargets = 1;
int badtargets = 0;
int reactmode = 0;
int holster = 0;
int nmag = 3;
int nbull = 10;
String shooter = "";
double distance = 10;

Preferences preferences;


void setup(void) {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  pinMode(micPin, INPUT);
  pinMode(target1Pin, INPUT);
  pinMode(target2Pin, INPUT);
  pinMode(target3Pin, INPUT);
  pinMode(target4Pin, INPUT);

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/highscores", handleHighscores);
  server.on("/gethighscores", handleGetHighscores);
  server.on("/shoot", handleShoot);
  server.on("/getvals", handleGetVals);

  server.begin();
  Serial.println("HTTP server started");
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  progStep = END;
  preferences.begin("highscores", false);
  //String highscoreNames[10];
  //double highscoreScores[10];
/*  for (int i = 0; i < 10; i++)
  {
    highscoreNames[i] = preferences.getString("name" + i, "nothing");
    highscoreScores[i] = preferences.getDouble("score" + i, -10);
    Serial.println(highscoreScores[i]);
  }*/
    highscoreNames[0] = preferences.getString("name0", "--");
    highscoreScores[0] = preferences.getDouble("score0", 0);
    highscoreNames[1] = preferences.getString("name1", "--");
    highscoreScores[1] = preferences.getDouble("score1", 0);
    highscoreNames[2] = preferences.getString("name2", "--");
    highscoreScores[2] = preferences.getDouble("score2", 0);
    highscoreNames[3] = preferences.getString("name3", "--");
    highscoreScores[3] = preferences.getDouble("score3", 0);
    highscoreNames[4] = preferences.getString("name4", "--");
    highscoreScores[4] = preferences.getDouble("score4", 0);
    highscoreNames[5] = preferences.getString("name5", "--");
    highscoreScores[5] = preferences.getDouble("score5", 0);
    highscoreNames[6] = preferences.getString("name6", "--");
    highscoreScores[6] = preferences.getDouble("score6", 0);
    highscoreNames[7] = preferences.getString("name7", "--");
    highscoreScores[7] = preferences.getDouble("score7", 0);
    highscoreNames[8] = preferences.getString("name8", "--");
    highscoreScores[8] = preferences.getDouble("score8", 0);
    highscoreNames[9] = preferences.getString("name9", "--");
    highscoreScores[9] = preferences.getDouble("score9", 0);
  preferences.end();


}

void loop(void) {
  server.handleClient();

  //check for swinging targets

  for (int i = 1; i <= 4; i++)
  {
    if ((millis() - swingTargets[i] > 500) and (targets[i] == 2))
    {
      targets[i] = 0;
    }
  }

  handleLeds();

  if (startshooting)
  {
    targets[1] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
    targets[2] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
    targets[3] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
    targets[4] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.

    currMag = 1;
    currBull = 0;
    currMs = 0;
    startshooting = false;
    shooting = true;

    totalTimeMag1 = 0;
    totalScoreMag1 = 0;
    avgTimeMag1 = 0;
    avgScoreMag1 = 0;
    totalTimeMag2 = 0;
    totalScoreMag2 = 0;
    avgTimeMag2 = 0;
    avgScoreMag2 = 0;
    totalTimeMag3 = 0;
    totalScoreMag3 = 0;
    avgTimeMag3 = 0;
    avgScoreMag3 = 0;
    totalTimeMag4 = 0;
    totalScoreMag4 = 0;
    avgTimeMag4 = 0;
    avgScoreMag4 = 0;
    totalTimeMag5 = 0;
    totalScoreMag5 = 0;
    avgTimeMag5 = 0;
    avgScoreMag5 = 0;
    totalTime = 0;
    totalScore = 0;
    avgTime = 0;
    avgScore = 0;
    startUpTime = millis();
    progStep = STARTUPTIMER;
  }

  //enum progStep {STARTUPTIMER, INCREASESHOT, WAITREACTION, SELECTTARGET, WAITFORSHOT, CALCSCORE, WAIT, END};

  if (shooting)
  {
    if (progStep == STARTUPTIMER)
    {
      unsigned long now = millis();
      if (now - startUpTime > 1000 * startdelay)
      {
        progStep = INCREASESHOT;
      }
    }

    if (progStep == INCREASESHOT)
    {
      //increase the current shot:
      currBull = currBull + 1;

      if (reactmode == 0)
      {
        progStep = SELECTTARGET;
      }
      else
      {
        startWaitReaction = millis();
        reactionTime = random(500, 5000);
        progStep = WAITREACTION;
      }

      if ((currBull == nbull) and (magchangemin1 == 1) and (currMag < nmag))
      {
        startMagChange = millis();
        Serial.println("WAIT");        progStep = WAIT;
      }

      if (currBull > nbull)
      {
        currMag = currMag + 1;
        currBull = 1;
        startMagChange = millis();
        if (magchangemin1 == 0)
        {
          progStep = WAIT;
        }
        else
        {
          if (reactmode == 0)
          {
            progStep = SELECTTARGET;
          }
          else
          {
            startWaitReaction = millis();
            reactionTime = random(500, 5000);
            progStep = WAITREACTION;
          }
        }

      }

      if (currMag > nmag)
      {
        progStep = SAVEHIGHSCORE;
      }
    }

    if (progStep == WAITREACTION)
    {
      unsigned long now = millis();
      if (now - startWaitReaction > reactionTime)
      {

        progStep = SELECTTARGET;

      }
    }

    if (progStep == SELECTTARGET)
    {
      bool foundTarget = false;
      while ( not foundTarget)
      {

        //int targets[5]; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.

        int iTarget;
        iTarget = random(1, 5);
        if (targets[iTarget] == 0)
        {
          targets[iTarget] = 1;
          foundTarget = true;
          //if needed search for a bad target.
          if (badtargets == 1)
          {
            bool foundBADTarget = false;
            while ( not foundBADTarget)
            {
              int iTarget;
              iTarget = random(1, 5);
              if (targets[iTarget] == 0)
              {
                targets[iTarget] = 3;
                foundBADTarget = true;

              }
            }
          }

          progStep = WAITFORSHOT;
          forceLeds = true;
          startTime = millis();
        }
      }

    }

    if (progStep == WAIT)
    {
      unsigned long now = millis();
      if (now - startMagChange > 1000 * magchangetime)
      {
        if (reactmode == 0)
        {
          progStep = SELECTTARGET;
        }
        else
        {
          startWaitReaction = millis();
          reactionTime = random(500, 5000);
          progStep = WAITREACTION;
        }
      }
    }

    if (progStep == WAITFORSHOT)
    {
      micVal = digitalRead(micPin);
      target1Val = digitalRead(target1Pin);
      target2Val = digitalRead(target2Pin);
      target3Val = digitalRead(target3Pin);
      target4Val = digitalRead(target4Pin);
      int iHitTarget = 0;
      if (target1Val == 1)
      {
        iHitTarget = 1;
      }
      if (target2Val == 1)
      {
        iHitTarget = 2;
      }
      if (target3Val == 1)
      {
        iHitTarget = 3;
      }
      if (target4Val == 1)
      {
        iHitTarget = 4;
      }

      if ((targets[1] == 1 and target1Val == 1) or (targets[2] == 1 and target2Val == 1) or (targets[3] == 1 and target3Val == 1) or (targets[4] == 1 and target4Val == 1))
      {

        /*
          double startdelay = 5;
          double shoottimeout = 3;
          int magchangetime = 3;
          int magchangemin1 = 0;
          int ntargets = 1;
          int badtargets = 0;
          int reactmode = 0;
          int holster = 0;
          int nmag = 3;
          int nbull = 10;
          String shooter = "";
          double distance = 10;*/

        //Correct target hit

        currMs = millis() - startTime;

        double score;
        //base score
        if ((holster == 1) and (currMag == 1) and (currBull == 1))
        {
          score = (1.0 / (double)(currMs - 700)) * 1000;
        }
        else
        {
          score = (1.0 / (double)currMs) * 1000;
        }

        //correct for distance
        double distFactor = atan2(0.1, distance) * 50;
        score = score / distFactor;

        //correct for shot timeout
        score = score - shoottimeout / 20;

        //correct for enabled bad targets
        score = score + score * badtargets * 0.1;



        targets[1] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
        targets[2] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
        targets[3] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
        targets[4] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.

        targets[iHitTarget] = 2;
        swingTargets[iHitTarget] = millis();

        if (currMag == 1)
        {
          scoreMag1[currBull] = score;
          timeMag1[currBull] = currMs;
        }
        if (currMag == 2)
        {
          scoreMag2[currBull] = score;
          timeMag2[currBull] = currMs;
        }
        if (currMag == 3)
        {
          scoreMag3[currBull] = score;
          timeMag3[currBull] = currMs;
        }
        if (currMag == 4)
        {
          scoreMag4[currBull] = score;
          timeMag4[currBull] = currMs;
        }
        if (currMag == 5)
        {
          scoreMag5[currBull] = score;
          timeMag5[currBull] = currMs;
        }
        startShowResultWrite = millis();
        progStep = SHOWGOOD;
      }
      else if ((targets[1] == 1 and (target2Val == 1 or target3Val == 1 or target4Val == 1))
               or (targets[2] == 1 and (target1Val == 1 or target3Val == 1 or target4Val == 1))
               or (targets[3] == 1 and (target1Val == 1 or target2Val == 1 or target4Val == 1))
               or (targets[4] == 1 and (target1Val == 1 or target2Val == 1 or target3Val == 1))
               or (micVal == 1)
               or (millis() - startTime >= shoottimeout * 1000))
      {

        targets[1] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
        targets[2] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
        targets[3] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.
        targets[4] = 0; //0 = not a target. 1 = target. 2 = swinging. 3 = good guy. 4 = wait state.

        targets[iHitTarget] = 2;
        swingTargets[iHitTarget] = millis();
        currMs = millis() - startTime;

        if (currMs > shoottimeout * 1000)
        {
          currMs = shoottimeout * 1000;
        }
        double score = -5  - shoottimeout / 20;
        //hit wrong plate or missed
        if (currMag == 1)
        {
          scoreMag1[currBull] = score;
          timeMag1[currBull] = currMs;
        }
        if (currMag == 2)
        {
          scoreMag2[currBull] = score;
          timeMag2[currBull] = currMs;
        }
        if (currMag == 3)
        {
          scoreMag3[currBull] = score;
          timeMag3[currBull] = currMs;
        }
        if (currMag == 4)
        {
          scoreMag4[currBull] = score;
          timeMag4[currBull] = currMs;
        }
        if (currMag == 5)
        {
          scoreMag5[currBull] = score;
          timeMag5[currBull] = currMs;
        }

        startShowResultWrite = millis();
        progStep = SHOWBAD;

      }



    }

    if (progStep == SAVEHIGHSCORE)
    {
      //check if the highscore needs to be saved.
      bool highscoreChanged = false;
      int rankinglocation = 10;
      for (int i = 9; i >= 0; i--)
      {
        //find index where we have to insert the score
        if (highscoreScores[i] < rankingAvgScore)
        {
          rankinglocation = i;
        }
      }

      if (rankinglocation < 9)
      {
        for (int i = 8; i >= rankinglocation; i--)
        {
          Serial.println("write 1");
          highscoreNames[i] = highscoreNames[i - 1];
          highscoreScores[i] = highscoreScores[i - 1];
        }
      }

      if (rankinglocation < 10)
      {
        highscoreNames[rankinglocation] = shooter;
        highscoreScores[rankinglocation] = rankingAvgScore;
        highscoreChanged = true;
        Serial.println("save value");
        Serial.println(rankinglocation);
        Serial.println(highscoreNames[rankinglocation]);
      }



      if (highscoreChanged == true)
      {

        Serial.println("highscore changed");
        Serial.println(highscoreScores[0]);
        preferences.begin("highscores", false);
      /*  for (int i = 0; i < 10; i++)
        {
          preferences.putString("name" + i, highscoreNames[i]);
          preferences.putDouble("score" + i, highscoreScores[i]);
        }*/
        
          preferences.putString("name0", highscoreNames[0]);
          preferences.putDouble("score0", highscoreScores[0]);
          preferences.putString("name1", highscoreNames[1]);
          preferences.putDouble("score1", highscoreScores[1]);
          preferences.putString("name2", highscoreNames[2]);
          preferences.putDouble("score2", highscoreScores[2]);
          preferences.putString("name3", highscoreNames[3]);
          preferences.putDouble("score3", highscoreScores[3]);
          preferences.putString("name4", highscoreNames[4]);
          preferences.putDouble("score4", highscoreScores[4]);
          preferences.putString("name5", highscoreNames[5]);
          preferences.putDouble("score5", highscoreScores[5]);
          preferences.putString("name6", highscoreNames[6]);
          preferences.putDouble("score6", highscoreScores[6]);
          preferences.putString("name7", highscoreNames[7]);
          preferences.putDouble("score7", highscoreScores[7]);
          preferences.putString("name8", highscoreNames[8]);
          preferences.putDouble("score8", highscoreScores[8]);
          preferences.putString("name9", highscoreNames[9]);
          preferences.putDouble("score9", highscoreScores[9]);
        preferences.end();
      }
      progStep = END;
    }

    if (progStep == SHOWGOOD)
    {
      if (millis() - startShowResultWrite >= 200)
      {
        progStep = INCREASESHOT;
      }
    }

    if (progStep == SHOWBAD)
    {
      if (millis() - startShowResultWrite >= 200)
      {
        progStep = INCREASESHOT;
      }
    }
  }

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                          FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
.......

}

Do you ever get the message "highscore changed" (line 580 in code) in the serial monitor? Have you tried to declare the "preferences" variable as being local where it is needed?

the idea was to get a minimum code demonstrating the issue.

try this code:

#include <Preferences.h>
Preferences preferences;

const char* nameKeys[]    = {"n0", "n1", "n2", "n3"};
String highscoreNames[]   = {"Fred", "Pat", "Gil", "Suzy"};

const char* scoreKeys[]   = {"k0", "k1", "k2", "k3"};
double highscoreScores[]  = {11.11, 22.22, 33.33, 44.44};

const byte prefCount = sizeof nameKeys / sizeof nameKeys[0];

void setup(void) {

  Serial.begin(115200);

  if (preferences.begin("highscores", false)) {
    for (byte i = 0; i < prefCount; i++) {
      preferences.putString(nameKeys[i], highscoreNames[i]);
      preferences.putDouble(scoreKeys[i], highscoreScores[i]);
    }
    preferences.end();
  } else Serial.println("Error writing Prefernces");

  if (preferences.begin("highscores", false)) {
    for (byte i = 0; i < prefCount; i++) {
      Serial.print(preferences.getString(nameKeys[i], "err"));
      Serial.write('\t');
      Serial.println(preferences.getDouble(scoreKeys[i], NAN), 3);
    }
    preferences.end();
  } else Serial.println("Error Reading Prefernces");
}

void loop() {}

does it work for you?

ah.... try also this code, that should give you a hint on an issue you might had...


void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    String s = "name" + i;
    Serial.println(s);
  }
}

void loop() {}

"name" + i is a pointer to a constant string which you increment by i, so you get the end of the cString

Yes, I do get the highscore changed message. nope, I did not try to declare preferences as local variable.. will try as soon as I am at home.

thank you, will try those codes as soon as I am at home.

one thing I thought that just came to my mind: i had the code running with a bug for 10 minutes. it kept writing to the eeprom.. maybe in these 10 minutes i killed it by writing it too often? if that is the case, is there a way to write on another location inside the memory?

There is no EEPROM in your ESP, it's emulated in flash. I doubt you would have killed it. Trying my code in #10 should let us know.

the output in the serial is this:

err	nan
err	nan
err	nan
err	nan

EDIT:

I Just tried it with a new board and it worked.. so i guess i killed something on the other one...

interesting , I tried it on an ESP32 (nothing connected) and Serial Monitor (@ 115200 bauds) showed

Fred 11.110
Pat 22.220
Gil 33.330
Suzy 44.440

seems like an hardware issue

you probably missed the edit above.. I have two boards.. with one it works, with the other it doesnt...

right... something weird indeed then with your board.

did you get why the "name" + i thingy you were trying to do did not work?

Yep got that.. thank you!

enjoy !