Reading from SD card, one value not reading at all

Hi, i hope someone could help me with this odd error.
This is a part of a larger project that will be built upon this starting position, this not complete by any means, all functions are in the setup portion.

Ive managed to save data to an SD card perfectly fine with two files, config.txt and wifi.txt, both files are created by the arduino if they do not already exist, and they do get created perfectly.
I have static values in such case if there are no files already on the SD card, as well as local variables that can be changed in the future elsewhere, which (not implemented yet) will use those local variables to then update the files on the SD card. If there are files on the SD card already (or created if they did not already exist), it will read those values stored on the card and change the local variables to then (in the future) run the program. local variables are names the same as the staic ones just with an "R" in front.

Now, all works fine so far except for reading the SSID in the Wifi.txt file. It saves both SSID and password perfectly fine to the SD card, and the password in the same file, the line below will read fine, but the SSID wont, i have attached it to the serial monitor to read back what it has "stored" in the local variable.
Config file opens and all contents are read fine, ssid opens and reads back "d" for SSID and the password reads back fine.

As far as i can tell i have writen the exact same thing for both Config and the Wifi files, im not sure what is exactly causing the issue with the SSID not reading properly, i have tried keeping it simple naming and nothing seems to make any change, read-back always shows "d".

I should mention, it is currently setup on a breadboard using an ESP32 (Lolin D32) using SPI, an Adafruit SD card breakout (Adafruit Micro SD SPI or SDIO Card Breakout Board - 3V ONLY! : ID 4682 : $2.95 : Adafruit Industries, Unique & fun DIY electronics and kits) and a SanDisk 32GB card formatted to FAT32.

here is the serial monitor output from a blank SD card upon first bootup:

Initializing SD card...initialization done.
File did not exist, writing default values to Config.txt...Done writing to Config.txt
File did not exist, writing default values to Wifi.txt...Done writing to Wifi.txt
Reading Config.txt and changing Rxxxxxxx local variable
Reading Wifi.txt and changing Rxxxxxxx local variable
Config.txt:
baltarget = 10
balVmin = 3400
overvoltD = 3650
overvoltR = 200
undervoltD = 2000
undervoltR = 200
overvoltW = 3600
undervoltW = 2200
overtempD = 40
overtempR = 5
undertempD = 0
undertempR = 5
Wifi.txt:
ssid = d
password = password
// 01
// Read/write to SD card
// Check files on the SD card, if none exist, creates them with default settings.
// Reads files from SD card and saves them to the Rxxxxxxx local variable.
// Outputs Rxxxxxxx variable to serial monitor after it has read from the SD card


//SD Card        ESP32
// 3V             3V
// GND            GND
// CLK            18 (SCK)
// SO(Dataout)    18 (MISO)
// SI(Datain)     23 (MOSI)
// CS(chipselect) 5 (SC0)

#include <SPI.h>
#include <SD.h>

File Config;
File Wifi;

const int chipselect = 5;

//Wite Data (default values)
const int baltarget = 10;
const int balVmin = 3400;
const int overvoltD = 3650;
const int overvoltR = 200;
const int undervoltD = 2000;
const int undervoltR = 200;
const int overvoltW = 3600;
const int undervoltW = 2200;
const int overtempD = 40;
const int overtempR = 5;
const int undertempD = 0;
const int undertempR = 5;

const char* ssid = "login";
const char* password = "password";

//Read Data (read from SD card)
int Rbaltarget;
int RbalVmin;
int RovervoltD;
int RovervoltR;
int RundervoltD;
int RundervoltR;
int RovervoltW;
int RundervoltW;
int RovertempD;
int RovertempR;
int RundertempD;
int RundertempR;

char* Rssid;
char* Rpassword;


void setup() {

  Serial.begin(115200);
  Serial.print("Initializing SD card...");

  if (!SD.begin(chipselect)) {
    Serial.println("initialization failed!");
    return;
  }
  else {
    Serial.println("initialization done.");
  }

  //Check SD card for files
  if (SD.exists("/Config.txt")) {                                            // check to see if file exists
    Serial.println("File already exists, Config.txt");                      // if the file exists, print an error:
  }
  else {                                                                   // otherwise...
    Config = SD.open("/Config.txt", FILE_WRITE);                           // open the file or create file if it does not exist
    if (Config) {                                                        // if file opened ok write to it:
      Serial.print("File did not exist, writing default values to Config.txt...");                           // if the file opened okay, write to it:

      Config.print("baltarget = "); Config.println(baltarget);
      Config.print("balVmin = "); Config.println(balVmin);
      Config.print("overvoltD = "); Config.println(overvoltD);
      Config.print("overvoltR = "); Config.println(overvoltR);
      Config.print("undervoltD = "); Config.println(undervoltD);
      Config.print("undervoltR = "); Config.println(undervoltR);
      Config.print("overvoltW = "); Config.println(overvoltW);
      Config.print("undervoltW = "); Config.println(undervoltW);
      Config.print("overtempD = "); Config.println(overtempD);
      Config.print("overtempR = "); Config.println(overtempR);
      Config.print("undertempD = "); Config.println(undertempD);
      Config.print("undertempR = "); Config.println(undertempR);

      Config.close();  Serial.println("Done writing to Config.txt");                       // close the file
    } else {
      Serial.println("Error opening Config.txt");                      // if the file didn't open or create, print an error
    }
  }


  if (SD.exists("/Wifi.txt")) {                                            // check to see if file exists
    Serial.println("File already exists, Wifi.txt");                      // if the file exists, print an error:
  }
  else {                                                                   // otherwise...
    Wifi = SD.open("/Wifi.txt", FILE_WRITE);                           // open the file or create file if it does not exist
    if (Wifi) {                                                        // if file opened ok write to it:
      Serial.print("File did not exist, writing default values to Wifi.txt...");       // if the file opened okay, write to it:

      Wifi.print("ssid = "); Wifi.println(ssid);
      Wifi.print("password = "); Wifi.println(password);

      Wifi.close();  Serial.println("Done writing to Wifi.txt");                       // close the file
    } else {
      Serial.println("Error opening Wifi.txt");                      // if the file didn't open or create, print an error
    }
  }

  // Read from the SD card
  //Config file
  Config = SD.open("/Config.txt");
  if (Config) {
    Serial.println("Reading Config.txt and changing Rxxxxxxx local variable");

    char buffer[40]; // May need to be a bit bigger if you have long names
    byte index = 0;
    while (Config.available())
    {
      char c = Config.read();
      if (c == '\n' || c == '\r') // Test for <cr> and <lf>
      {
        parseAndSave(buffer);
        index = 0;
        buffer[index] = '\0'; // Keep buffer NULL terminated
      }
      else
      {
        buffer[index++] = c;
        buffer[index] = '\0'; // Keep buffer NULL terminated
      }
    }

    Config.close();                                                 // close the file:
  } else {
    Serial.println("error opening Config.txt");                 // if the file didn't open, print an error:
  }

  //Wifi file
  Wifi = SD.open("/Wifi.txt");
  if (Wifi) {
    Serial.println("Reading Wifi.txt and changing Rxxxxxxx local variable");

    char buffer[40]; // May need to be a bit bigger if you have long names
    byte index = 0;
    while (Wifi.available())
    {
      char c = Wifi.read();
      if (c == '\n' || c == '\r') // Test for <cr> and <lf>
      {
        parseAndSave(buffer);
        index = 0;
        buffer[index] = '\0'; // Keep buffer NULL terminated
      }
      else
      {
        buffer[index++] = c;
        buffer[index] = '\0'; // Keep buffer NULL terminated
      }
    }

    Wifi.close();                                                 // close the file:
  } else {
    Serial.println("error opening Wifi.txt");                 // if the file didn't open, print an error:
  }

  Serial.println("Config.txt:");
  Serial.print("baltarget = "); Serial.println(Rbaltarget);
  Serial.print("balVmin = "); Serial.println(RbalVmin);
  Serial.print("overvoltD = "); Serial.println(RovervoltD);
  Serial.print("overvoltR = "); Serial.println(RovervoltR);
  Serial.print("undervoltD = "); Serial.println(RundervoltD);
  Serial.print("undervoltR = "); Serial.println(RundervoltR);
  Serial.print("overvoltW = "); Serial.println(RovervoltW);
  Serial.print("undervoltW = "); Serial.println(RundervoltW);
  Serial.print("overtempD = "); Serial.println(RovertempD);
  Serial.print("overtempR = "); Serial.println(RovertempR);
  Serial.print("undertempD = "); Serial.println(RundertempD);
  Serial.print("undertempR = "); Serial.println(RundertempR);
  Serial.println("Wifi.txt:");
  Serial.print("ssid = "); Serial.println(Rssid);
  Serial.print("password = "); Serial.println(Rpassword);

}

void loop() {
  // put your main code here, to run repeatedly:

}


void parseAndSave(char *buff)
{
  char *name = strtok(buff, " =");
  if (name)
  {
    char *junk = strtok(NULL, " ");
    if (junk)
    {
      char *valu = strtok(NULL, " ");
      if (valu)
      {
        if (strcmp(name, "baltarget") == 0)
        {
          Rbaltarget = atoi(valu);
        }
        if (strcmp(name, "balVmin") == 0)
        {
          RbalVmin = atoi(valu);
        }
        if (strcmp(name, "overvoltD") == 0)
        {
          RovervoltD = atoi(valu);
        }
        if (strcmp(name, "overvoltR") == 0)
        {
          RovervoltR = atoi(valu);
        }
        if (strcmp(name, "undervoltD") == 0)
        {
          RundervoltD = atoi(valu);
        }
        if (strcmp(name, "undervoltR") == 0)
        {
          RundervoltR = atoi(valu);
        }
        if (strcmp(name, "overvoltW") == 0)
        {
          RovervoltW = atoi(valu);
        }
        if (strcmp(name, "undervoltW") == 0)
        {
          RundervoltW = atoi(valu);
        }
        if (strcmp(name, "overtempD") == 0)
        {
          RovertempD = atoi(valu);
        }
        if (strcmp(name, "overtempR") == 0)
        {
          RovertempR = atoi(valu);
        }
        if (strcmp(name, "undertempD") == 0)
        {
          RundertempD = atoi(valu);
        }
        if (strcmp(name, "undertempR") == 0)
        {
          RundertempR =  atoi(valu);
        }
        if (strcmp(name, "ssid") == 0)
        {
          Rssid = valu;
        }
        if (strcmp(name, "password") == 0)
        {
          Rpassword = valu;
        }
      }
    }
  }
}

your issue is that you assign a temporary pointer to your Rssid or Rpassword. You need space to store that content, not just the pointer as content is lost at the next call (and your pointers point nowhere).

it works for the other stuff as you call atoi() and so the string is interpreted as a number and you have storage for that number;

try declaring

const byte maxSize = 40;
char Rssid[maxSize+1];  // +1 for the trailing null char
char Rpassword[maxSize+1];  // +1 for the trailing null char

and in the code

        if (strcmp(name, "ssid") == 0)
        {
          strncpy(Rssid, valu, maxSize);
          Rssid[maxSize] = '\0';
        }
        if (strcmp(name, "password") == 0)
        {
          strncpy(Rpassword, valu, maxSize); 
          Rpassword[maxSize] = '\0';
        }

you should also add else in between all those ifs as once you found a match, there is no point checking the others

I see, it all makes sense now. I've implemented your sugguestion and all works as expected, including the "else".

Thank you very much for your swift reply.
James.

great - have fun

1 Like

@Jamhough22, your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with (nor for advise on) your project :wink: See About the Installation & Troubleshooting category.

1 Like