ute702
July 25, 2023, 8:08am
1
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++.
J-M-L
July 25, 2023, 8:13am
3
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
ute702:
//write data
loop();
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)
ute702
July 25, 2023, 8:20am
4
I see, thanks for your reply!
J-M-L
July 25, 2023, 9:15am
5
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
ute702
July 25, 2023, 10:30am
6
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.
J-M-L
July 25, 2023, 11:51am
7
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
J-M-L:
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
ute702
July 25, 2023, 2:29pm
8
It works!
Now I know what to do, thanks for your help!
system
Closed
January 21, 2024, 3:43pm
10
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.