How to save data with arduino SD shield

I'm attempting to log my CO2 data, which is measured by an MH-Z19B sensor with the SD shield, but the data is not being successfully saved, and the file only displays "CO2 Concentration (ppm)."

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <MHZ19.h>
#include <SPI.h>
#include "SdFat.h"

#define SD_CS_PIN 4

//----------------------------------------------
SoftwareSerial co2Serial(2, 3);   //
SdFat SD;       //
File myFile;    //

void setup() {

  //--------------------------------------------
  //
  Serial.begin(9600);
  co2Serial.begin(9600);
  Serial.print("Initializing SD card...");
  //
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("initialization failed!");
    return;
  }

  Serial.println("initialization done.");

  //--------------------------------------------
  myFile = SD.open("data.txt", FILE_WRITE);

  //----------------------------------------------
  if (myFile)
  {
    Serial.print("Writing to data.txt...");
    //Write header
    myFile.println("CO2 Concentration (ppm)");

    //write data
    loop(); 

    //Close file
    myFile.close();
    Serial.println("done.");
  } 
  else 
  {
    Serial.println("error opening data.txt");
  }
}

void loop() 
{
  int count; 
  char str[256]; 

  byte request[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};  //command
  
  co2Serial.write(request, sizeof(request));

  count = 0;

  while (co2Serial.available() and count <=100) 
  {
    int response = co2Serial.read();

    if (response == 0xFF && co2Serial.peek() == 0x86) 
    {
      co2Serial.read();  
      byte highByte = co2Serial.read();
      byte lowByte = co2Serial.read();

      int co2Value = highByte * 256 + lowByte;
      Serial.print("CO2 Concentration (ppm): ");
      Serial.println(co2Value);

      sprintf(str," %5d", co2Value); //%5d = CO2 value
      myFile.println(str);

      delay(1000);
      count++;
    }
  
  }

}




Hello ute702

Welcome to the worldbest Arduino forum ever.

This is a nice project to get started.

Keep it simple and stupid firstly.
Follow the example code that comes with the library or
run some tutorials for the hardware selected.
If you are happy with the results of the tutorials you can merge these to your project.

Have a nice day and enjoy coding in C++.

I'll come back to calling the loop() from the setup but when you send the command to your co2 module

chances are that the response won't be available in the next few microseconds

and so co2Serial.available() will be 0 and you won't enter in your while, thus exiting the loop, returning to the setup where you close the file


This is not how it should be done

don't call loop() yourself from the setup, it's called for you repetitively (by the main function that is injected in the final code by the IDE)

I see, thanks for your reply!

so basically the setup() needs to configure the various elements
then the loop

  • if it's time to get a new measure (like every 10 minutes)
    • sends a command to the CO2 device
    • awaits (correctly) for the answer to arrive (or timeout may be)
    • gets the data
    • opens the file
    • writes the data
    • closes the file
    • remember the time of this last measure

having a switch that enables / disables the recording mode could be useful or turn on the built in LED or an external LED whilst the file is open so that you don't eject the SD card whilst recording data

I've tried to take the loop out of setup, but it seems the data still not be loaded. The file close after it just open.
螢幕擷取畫面 2023-07-25 182114

if you close the file in the setup then for sure the loop won't do anything.

try this

#include <SPI.h>
#include "SdFat.h"
#define SD_CS_PIN 4
SdFat SD;

void setup() {
  Serial.begin(115200);
  Serial.print("Initializing SD card...");
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("initialization failed!");
    while (true) delay(1);
  }
  Serial.println("initialization done.");

  //--------------------------------------------
  File myFile = SD.open("data.txt", FILE_WRITE);
  if (myFile) {
    Serial.println("Writing to data.txt...\n--------------------");
    myFile.println("CO2 Concentration (ppm)");
    Serial.println("CO2 Concentration (ppm)");

    // simulate some writes
    for (int count = 0; count < 10; count++) {
      char str[50];
      int co2Value = random(0, 10000);
      snprintf(str, sizeof str, "%04d\tco2\t%5d\tppm", count, co2Value);
      Serial.println(str);
      myFile.println(str);
    }
    // now that we are done, close the file
    myFile.close();
    Serial.println("--------------------\ndone.");
  } else {
    Serial.println("error opening data.txt");
  }
}

void loop() {}

(open the Serial monitor at 115200 bauds, not 9600 to see the debug info)

of course this is just everything in the setup and random values but you should see something now on your SD card

As I said the loop should do

It works!
Now I know what to do, thanks for your help!

Good have fun

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