Data logger with ESP 8266

Has anyone experience with this board and communication to SD cards?

It is a ESP8266-based board. So any code written for ESP8266 that stores data on an SD-card will work.

You will have to find the correct IO-pins. This Ardino-Uno Formfactor board is rather rarely used.
Post a link to the Pinout description.

Then users can help to find out which SD-card pin must be connected to which IO-pin.

You should buy a quality SD-card-reader.
In my experience the $1,50 modules do not work reliably.
So don't buy them at aliexpress or banggood. Buy one from Sparkfun oder Adafruit

best regards Stefan

Hi Stefan. I checked the connection hundred times. The ESP sends as message to the SD and it answers on the MISO. With my simple oscilloscope I see the pulses, but I cannot decode the message as professional Oscis can do. Its looks very similar to the pulses coming out, when I use a UNO successfully.

please post the complete sketch that you used for testing writing to sd-card.

Without the sketch nothing will going on towards a solution.

There are various functions for testing almost every detail about writing / reading to an SD-card. Starting with a test if mounting was successfull.

best regards Stefan

Hi Stefan
It's rather nothing.

/*
  SD card datalogger

  This example shows how to log data from three analog sensors
  to an SD card using the SD library.

  The circuit:
   analog sensors on analog ins 0, 1, and 2
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 15

  created  24 Nov 2010
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

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

const int chipSelect = 16;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  

  Serial.print("Initializing SD card...");
  Serial.println ();
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  delay (2000);
}

void loop() {
  // // make a string for assembling the data to log:
  // String dataString = "";

  // // read three sensors and append to the string:
  // for (int analogPin = 0; analogPin < 3; analogPin++) {
  //   int sensor = analogRead(analogPin);
  //   dataString += String(sensor);
  //   if (analogPin < 2) { dataString += ","; }
  // }

  // // open the file. note that only one file can be open at a time,
  // // so you have to close this one before opening another.
  // File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // // if the file is available, write to it:
  // if (dataFile) {
  //   dataFile.println(dataString);
  //   dataFile.close();
  //   // print to the serial port too:
  //   Serial.println(dataString);
  // }
  // // if the file isn't open, pop up an error:
  // else { Serial.println("error opening datalog.txt"); }
}

What is "nothing"

Unprecise description.
The more details you post the better the analysis can be.
What does the serial monitor show?
Post a picture of your SD-card-module
Post a link to the datasheet of your SD-card-module
Post a schematic how you connected the SD-card

Do you have a 24 MHz 8 ch logic analyser? They cost about $15
There is a software called sigrok pulseView that can record 8 channels
and has even a protocol analyser.

best regards Stefan

the code say in the comment

you defined

In this documentation Chip-Select ("SS") is IO-Pin 15 and not 16


so try

const int chipSelect = 15;

Here is a demo code that tests the FS-library (FileSystem)

#include "FS.h"
#include "SD.h"
#include "SPI.h"

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if(!root){
    Serial.println("Failed to open directory");
    return;
  }
  if(!root.isDirectory()){
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while(file){
    if(file.isDirectory()){
      Serial.print("  DIR : ");
      Serial.println(file.name());
      if(levels){
        listDir(fs, file.name(), levels -1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

void createDir(fs::FS &fs, const char * path){
  Serial.printf("Creating Dir: %s\n", path);
  if(fs.mkdir(path)){
    Serial.println("Dir created");
  } else {
    Serial.println("mkdir failed");
  }
}

void removeDir(fs::FS &fs, const char * path){
  Serial.printf("Removing Dir: %s\n", path);
  if(fs.rmdir(path)){
    Serial.println("Dir removed");
  } else {
    Serial.println("rmdir failed");
  }
}

void readFile(fs::FS &fs, const char * path){
  Serial.printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if(!file){
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while(file.available()){
    Serial.write(file.read());
  }
  file.close();
}

void writeFile(fs::FS &fs, const char * path, const char * message){
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if(!file){
    Serial.println("Failed to open file for writing");
    return;
  }
  if(file.print(message)){
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message){
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if(!file){
    Serial.println("Failed to open file for appending");
    return;
  }
  if(file.print(message)){
      Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(fs::FS &fs, const char * path1, const char * path2){
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(fs::FS &fs, const char * path){
  Serial.printf("Deleting file: %s\n", path);
  if(fs.remove(path)){
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void testFileIO(fs::FS &fs, const char * path){
  File file = fs.open(path);
  static uint8_t buf[512];
  size_t len = 0;
  uint32_t start = millis();
  uint32_t end = start;
  if(file){
    len = file.size();
    size_t flen = len;
    start = millis();
    while(len){
      size_t toRead = len;
      if(toRead > 512){
        toRead = 512;
      }
      file.read(buf, toRead);
      len -= toRead;
    }
    end = millis() - start;
    Serial.printf("%u bytes read for %u ms\n", flen, end);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }


  file = fs.open(path, FILE_WRITE);
  if(!file){
    Serial.println("Failed to open file for writing");
    return;
  }

  size_t i;
  start = millis();
  for(i=0; i<2048; i++){
    file.write(buf, 512);
  }
  end = millis() - start;
  Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
  file.close();
}

void setup(){
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

  Serial.println("Mounting SD-Card");
  if(!SD.begin(5)){
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if(cardType == CARD_MMC){
    Serial.println("MMC");
  } else if(cardType == CARD_SD){
    Serial.println("SDSC");
  } else if(cardType == CARD_SDHC){
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  listDir(SD, "/", 0);
  createDir(SD, "/mydir");
  listDir(SD, "/", 0);
  removeDir(SD, "/mydir");
  listDir(SD, "/", 2);
  writeFile(SD, "/hello.txt", "Hello ");
  appendFile(SD, "/hello.txt", "World!\n");
  readFile(SD, "/hello.txt");
  deleteFile(SD, "/foo.txt");
  renameFile(SD, "/hello.txt", "/foo.txt");
  readFile(SD, "/foo.txt");
  testFileIO(SD, "/test.txt");
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}


void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );  
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 2;


void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);
  
  if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
    digitalWrite(IO_Pin,!digitalRead(IO_Pin) ); 
  }
}


void loop() {
  BlinkHeartBeatLED(OnBoard_LED,250);

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {

  }  
}

best regards Stefan

Hi Stefan
I do not update the comments, when I play with the port number.

here more details:

this is the CS (yellow) and the MISO. It only comes, if a card is inserted. The zhe data lines should be correct. Also the 3.3V level is ok.
And here is my simple hardware setup.

I tried 2 different SD cards. Both work with the UNO board.

Thaks for the hint with the logic analyzer. In my job (now retired) I only worked with professional tools of e.g. Tektronix for many thousand €. So I have no experience cheap "toys". Unfortunately the sigrok page is actually not available. So I will try to find a different part. I looks very helpful.

Did you noticed that the orighinal demo-codes use

GPIO-Pin 15

There are some more differencies between your wiring and how this tutorial wired it

best regards Stefan

I googled for PulseView-Download and found this thread on stacloverflow

which shows where you still can download pulseView
https://web.archive.org/web/20201101141813/https://sigrok.org/jenkins/job/sigrok-cross-mingw/buildtype=static,debugtype=release,platform=cross-i686-w64-mingw32/lastSuccessfulBuild/artifact/pulseview-NIGHTLY-32bit-static-release-installer.exe

Thanks, I tried several download links, mine always failed. This links is ok.

For my problem: I have exactly the same wiring as you proposed. But still "not present"

I did not really see what is connected to what because your picture is not taking from vertically above.

It took me a long time to verify this. In future I will allways ask for a picture from verticaly above before analysing anything

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.