I am working on a weather station. I am using a UNO, with an Adafruit Data Logging shield for Arduino Product ID: 1141, an Adafruit BME280 I2C or SPI Temperature Humidity Pressure product ID: 2652, and a 2004 LCD with I2C interface. I have looked an many examples and used them for inspiration to compile this code. This issue is when I activate the LCD the data stops logging. The code compiles with no errors. I done understand where the conflict is between the LCD and the SD logging function.
here is the code
/*Arduino weather station
Thomas T Rush 19JUN2023
R-01 getting the RTC to function
01-Date and time functions using a PCF8523 RTC connected via I2C and Wire lib
02-SD card loging the Date ant Time to a file
03-Non-interrupt timer for writing data to SD card
04-removing rem-ed statments used for development
05-Setting up the BME280 temperature, pressure, humidity sensor
05A- adding "logfile.flush();" and a delay inbetween data wrights to the SD card
06A- Adding the LCD a 2004 and making a custom character for the degree symbol
*/
//Libraries
#include "RTClib.h"//to access the Real Time Clock
#include <SPI.h> //Used to communicate with the SD card
#include <SD.h> //SD card command set
#include <Adafruit_Sensor.h>//used by the BME280
#include <Adafruit_BME280.h>//used by the BME280
#include <Wire.h>//used for I2C comminications, The BME 280
#include <LiquidCrystal_I2C.h>//used by the LCD display
//Setting up the RTC clock
RTC_PCF8523 rtc; // define the Real Time Clock object
unsigned long CurrentTime;// used to measure elapsed time agenst the StartTime
unsigned long StartTime;// for storing the unixtime to manage the time interval
// SD card configuration
const int chipSelect = 10;// for the data logging shield, we use digital pin 10 for the SD cs line
File logfile;// the logging file
// Setting up the BME280 temperature, pressure, humidity sensor
Adafruit_BME280 bme; // the i2c address is 0x77.
// Setting up the LCD desplay to function on I2C
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 20 chars and 4 line display
// making a custom Degree symbol:
byte Degree[] = {
B00111,
B00101,
B00111,
B00000,
B00000,
B00000,
B00000,
B00000
};
void setup() {
Serial.begin(9600);//establishing serial monitor feedback
#ifndef ESP8266
while (!Serial); // wait for serial port to connect. Needed for native USB
#endif
Serial.println("");
Serial.println("testing RTC");
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
if (! rtc.initialized() || rtc.lostPower()) {
Serial.println("RTC is NOT initialized, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
//
// Note: allow 2 seconds after inserting battery or applying external power
// without battery before calling adjust(). This gives the PCF8523's
// crystal oscillator time to stabilize. If you call adjust() very quickly
// after the RTC is powered, lostPower() may still return true.
}
// When time needs to be re-set on a previously configured device, the
// following line sets the RTC to the date & time this sketch was compiled
//rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
//rtc.adjust(DateTime(2023, 6, 25, 19, 4, 10));
// When the RTC was stopped and stays connected to the battery, it has
// to be restarted by clearing the STOP bit. Let's do this to ensure
// the RTC is running.
rtc.start();
// The PCF8523 can be calibrated for:
// - Aging adjustment
// - Temperature compensation
// - Accuracy tuning
// The offset mode to use, once every two hours or once every minute.
// The offset Offset value from -64 to +63. See the Application Note for calculation of offset values.
// https://www.nxp.com/docs/en/application-note/AN11247.pdf
// The deviation in parts per million can be calculated over a period of observation. Both the drift (which can be negative)
// and the observation period must be in seconds. For accuracy the variation should be observed over about 1 week.
// Note: any previous calibration should cancelled prior to any new observation period.
// Example - RTC gaining 43 seconds in 1 week
float drift = 43; // seconds plus or minus over oservation period - set to 0 to cancel previous calibration.
float period_sec = (7 * 86400); // total obsevation period in seconds (86400 = seconds in 1 day: 7 days = (7 * 86400) seconds )
float deviation_ppm = (drift / period_sec * 1000000); // deviation in parts per million (μs)
float drift_unit = 4.34; // use with offset mode PCF8523_TwoHours
// float drift_unit = 4.069; //For corrections every min the drift_unit is 4.069 ppm (use with offset mode PCF8523_OneMinute)
int offset = round(deviation_ppm / drift_unit);
// rtc.calibrate(PCF8523_TwoHours, offset); // Un-comment to perform calibration once drift (seconds) and observation period (seconds) are correct
// rtc.calibrate(PCF8523_TwoHours, 0); // Un-comment to cancel previous calibration
Serial.print("Offset is ");
Serial.println(offset); // Print to control offset
DateTime now = rtc.now();
StartTime = now.unixtime();
Serial.print("Unit StartTime ");
Serial.println(StartTime);
Serial.println("RTC test done");
Serial.println();
// SD card configuration
Serial.println("testing SD card");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
}
Serial.println("card initialized.");
// create a new file
char filename[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
Serial.println("couldnt create file");
}
Serial.println("file created");
Serial.println("SD card and file test done");
Serial.println("");
//BME280 sensor configuration and test
Serial.println("Testing the BME280");
Serial.println(F("BME280 test"));
bool status;
// default settings
// (you can also pass in a Wire library object like &Wire2)
status = bme.begin();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
Serial.println("BME280 test done");
Serial.println("");
//configuring the LCD
Serial.println("initialize the lcd and setting the backlight");
lcd.init(); //initialize the lcd
lcd.backlight(); //open the backlight
Serial.println("LCD setup done");
Serial.println("");
// Create a custom character:
lcd.createChar(0, Degree);
}
void loop() {
//checking the current time
DateTime now = rtc.now();
CurrentTime = now.unixtime();//setting "CurrentTime" used for the non-interupt timer for the SD card write
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.println(now.second(), DEC);
Serial.print("Unix Time ");
Serial.print(now.unixtime());
Serial.print("s");
Serial.println();
Serial.println();
//Checking the BME280 sensor
Serial.print("Temperature = ");
Serial.print(bme.readTemperature());
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bme.readPressure() / 100.0F);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(bme.readHumidity());
Serial.println(" %");
Serial.println("");
// log time
// The Data will be stored on the SD card every interval. The interval is the seconds added to "StartTime"
// check in the elapsed time to record data to the SD card the interval is 5 minints
if (CurrentTime >= StartTime + 30){
StartTime=CurrentTime;//resetting the StartTime for the next interval
Serial.println("interval compleat, saving data to SD Card:)");
logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(",");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
logfile.print(',');
logfile.flush();
delay(50);
//loging the BME280 data
logfile.print(bme.readTemperature());
logfile.print(",*C,");
logfile.flush();
delay(50);
logfile.print(bme.readPressure() / 100.0F);
logfile.print(",hPa,");
logfile.flush();
delay(50);
logfile.print(bme.readHumidity());
logfile.println(",%");
logfile.flush();
delay(50);
}
//Printing data to the LDC
//lcd.clear(); //Clears the LCD screen and positions the cursor in the upper-left corner.
// Print the date and Time to the LCD;
lcd.setCursor(0, 0);
lcd.print(now.year(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.day(), DEC);
lcd.print(" ");
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
lcd.print(" ");
// Print the Temperature to the LCD;
lcd.setCursor(0, 1);
lcd.print("Temperature:");
lcd.print(bme.readTemperature());
lcd.write(0); // print the custom character
lcd.print("C");
// Print the Pressure to the LCD;
lcd.setCursor(0, 2);
lcd.print("Pressure:");
lcd.print(bme.readPressure() / 100.0F);
lcd.print(" hPa");
// Print the Humidity to the LCD;
lcd.setCursor(0, 3);
lcd.print("Humidity:");
lcd.print(bme.readHumidity());
lcd.print(" %");
// wait a quarter second between readings;
delay(250);
}