Hello Everyone!
Project: Weather station
Components: DHT22, BMP388, SD card module, Nodemcu ESP8266 with integrated .9" OLED display. 16GB SD card formatted to FAT32, Arduino IDE
Everything works except appending the datafile on the SD card. I know i can send the data to the cloud and that is my intention but i wanted a back up copy in case internet goes down., hence, the SD card.
When creating the file in VOID setup(), the file is created and writes the data headers in the file. If the file exists already, the file creation and headers write step is bypassed.
Here's the code:
#include <Arduino.h>
#include <Wire.h>
#include <U8g2lib.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"
#include "DHT.h" // Include the temp/humidity sensor library
// Libraries to get time from NTP Server
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
//Libraries for SD Card
#include <SD.h>
#include <SPI.h>
// Network Credentials
const char *ssid = "Trumped 2.4";
const char *password = "T1h2e3E4n5d!";
// Define SPI CS pin for the SD card module
#define SD_CS 0
// Save reading number on RTC memory
//Define the reading ID for every line of data
uint32_t readingID;
//define the variable dataMessage to hold all data in one string
String dataMessage;
//Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP,"pool.ntp.org");
//Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;
#define DHTPIN 2
// what pin on NodeMCU we're connected to for the DHT22 (GPIO2) D4
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE); // Initialize DHT Sensor
//Set up SPI pins if using SPI for BMP3XX sensor
//#define BMP_SCK 14
//#define BMP_MISO 12
//#define BMP_MOSI 13
//#define BMP_CS 15
float Temp; // Temperature C
float Press; // Absolute Pressure mB
float Alt; // Altitude m
float h; //Relative Humidity %
//Define sea level pressure
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BMP3XX bmp;
U8G2_SSD1306_128X64_NONAME_F_SW_I2C
u8g2(U8G2_R0,14,12,U8X8_PIN_NONE);
//Define dataFile variable for writing data to data.txt
File dataFile;
void setup() {
//set up dataFile for write data.txt file to SD card
dataFile = SD.open("data.txt", FILE_WRITE);
//Initiate Time Client
timeClient.begin();
//Set time offset from GMT
timeClient.setTimeOffset(-21600);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
// Initialize SD card
Serial.print("Initializing SD card...");
pinMode(SD_CS,OUTPUT);
if (!SD.begin(SD_CS)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
// If the data.txt file doesn't exist
// Create a file on the SD card and write the data labels
if (SD.exists("data.txt")) {
Serial.println("Data file already exists");
}
else {
Serial.println("File doesn't exist");
Serial.println("Creating file...");
dataFile.println("Reading ID, Date, Time, Temp, Humidity, Pressure");
dataFile.close();
}
//Start DHT Sensor
dht.begin();
//Start the OLED display
u8g2.begin();
//Start serial communication with BMP388
while (!Serial);
Serial.println("Adafruit BMP388 / BMP390 test");
//Begin I2C communication
if (!bmp.begin_I2C()) { // hardware I2C mode, can pass in address & alt Wire
//if (! bmp.begin_SPI(BMP_CS)) { // hardware SPI mode
//if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) { // software SPI mode
Serial.println("Could not find a valid BMP3 sensor, check wiring!");
while (1);
}
// Set up oversampling and filter initialization
bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
bmp.setOutputDataRate(BMP3_ODR_50_HZ);
}
void loop() {
timeClient.update();
//Read Humidity
h = dht.readHumidity();
// increment readingID
readingID = readingID + 1;
// Check if any reads failed and exit early (to try again).
if (isnan(h)){
}
if (! bmp.performReading()) {
u8g2.drawStr(0,10,"Failed to perform reading :(");
return;
}
//Calculate Temperature, pressure and altitude
Temp = bmp.temperature;
Press = bmp.pressure/100;
Alt = bmp.readAltitude(SEALEVELPRESSURE_HPA);
// Calculate corrected pressure for station down to sea level:
// Z = Elevation above sea level (m)
float a = 16000 + 64*Temp;
float Z = 670.8648;
float correctedP = Press * (a + Z)/(a - Z);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_8x13_tf);
u8g2.drawStr(0,10,"T(C)= ");
u8g2.setCursor(50,10);
u8g2.print(Temp);
u8g2.drawStr(0,25,"H(%)= ");
u8g2.setCursor(50,25);
u8g2.print(h);
u8g2.drawStr(0,40,"P(mB)= ");
u8g2.setCursor(50,40);
u8g2.print(correctedP);
u8g2.drawStr(0,55,"Alt(m)= ");
u8g2.setCursor(57,55);
u8g2.print(Alt);
u8g2.sendBuffer();
//Retrieve time and date from NTP Server
time_t epochTime = timeClient.getEpochTime();
//Get a time structure
struct tm *ptm = gmtime ((time_t *)&epochTime);
String formattedTime = timeClient.getFormattedTime(); // Get formatted Time from NTP Server
int monthDay = ptm->tm_mday; // Get day of the month(integer)
int currentMonth = ptm->tm_mon+1; //Get current month (integer)
int currentYear = ptm->tm_year+1900; //Get current year
// Complete Date
String currentDate = String(currentMonth) + "/" + String(monthDay) + "/" + String(currentYear);
// Create the data reading string
dataMessage = String(readingID) + "," + String(currentDate) + "," + String(formattedTime) + "," + String(Temp) + "," +String(h) + "," + String(correctedP) +"\r\n";
// Open the file on SD card
// if the file is available, write to it:
dataFile = SD.open("data.txt", FILE_WRITE);
if (SD.exists("data.txt")) {
Serial.println("Writing Data...");
dataFile.println(dataMessage);
dataFile.close();
Serial.println("Write Complete...");
Serial.println(dataMessage);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening data.txt");
}
delay(5000);
}
Here's the Serial output:
06:03:06.659 -> .............................................................................................................................................................................
06:03:10.716 -> WiFi connected.
06:03:10.750 -> Initializing SD card...initialization done.
06:03:10.783 -> Data file already exists
06:03:11.246 -> Adafruit BMP388 / BMP390 test
06:03:11.560 -> Writing Data...
06:03:12.153 -> Write Complete...
06:03:12.153 -> 1,5/3/2024,06:03:09,24.85,nan,892.09
06:03:12.189 ->
06:03:17.762 -> Writing Data...
06:03:18.397 -> Write Complete...
06:03:18.397 -> 2,5/3/2024,06:03:15,23.10,nan,1011.24
06:03:18.441 ->
06:03:23.584 -> Writing Data...
06:03:24.246 -> Write Complete...
06:03:24.246 -> 3,5/3/2024,06:03:21,23.10,37.60,1011.24
06:03:24.292 ->
06:03:29.447 -> Writing Data...
06:03:30.077 -> Write Complete...
06:03:30.077 -> 4,5/3/2024,06:03:27,23.10,38.50,1011.24
06:03:30.077 ->
06:03:35.270 -> Writing Data...
06:03:35.867 -> Write Complete...
06:03:35.867 -> 5,5/3/2024,06:03:33,23.09,38.50,1011.24
06:03:35.900 ->
06:03:41.055 -> Writing Data...
06:03:41.725 -> Write Complete...
06:03:41.725 -> 6,5/3/2024,06:03:38,23.09,37.30,1011.24
06:03:41.725 ->
06:03:46.897 -> Writing Data...
06:03:47.549 -> Write Complete...
06:03:47.549 -> 7,5/3/2024,06:03:44,23.08,36.50,1011.24
06:03:47.549 ->
Here's the data file that is created:
You can see that no data lines have been written other than the headers. Funny thing as well, if I remove the SD card while the program is running, the serial output still says the data is writing successfully. Hope someone can help!