Hello!
I'm working on a datalogger (using Arduino MEGA) for a few measurements for my master of science thesis. The logger has 12 soil humidity sensors, one sensor for relative humidity and temperature, two fans, and LCD that automatically showcases the current measurements in a certain order as a simple button is clicked. The measurements happen every 30 seconds and all the data is logged, together with the date and time, on an SD card.
Everything works but, for some reason, sometimes the file just does not get created. Obviously I've put a few lines that stop the whole thing if
- an SD module is not present
- the file cannot be created/accessed for the first time (this is necessary to write header)
- the file cannot be accessed during a measurement
The error messages never appear. I can't understand what I'm doing wrong, I suspected that maybe it could be because I take the SD out at the wrong time, so I'm using the LED on the board to signal when the measurement is taking place. I always take it out during the resting cycle.
The code is a little long so I'll hide it.
DHT to pin 22
LCD: rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7
Soil sensors to pins A15-A4
Button to pin 24
RTC (clock) to pin 20(SDA) and 21(SCL)
SD to pin 50 (MISO), 51 (MOSI), 52 (SCK), 53 (CS)
#include <LiquidCrystal.h>
#include <SimpleDHT.h>
#include <RTClib.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
void writeTime();
#define ENABLEA 9
#define ENABLEB 11
#define DIRA 8
#define DIRB 10
SimpleDHT11 dht11(22); //RH and T
const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
RTC_DS3231 rtc; //clock
DateTime nowDT;
File data_file;
int soil1t = 0; // for soil humidity
int soil1b = 0;
int soil2t = 0;
int soil2b = 0;
int soil3t = 0;
int soil3b = 0;
int soil4t = 0;
int soil4b = 0;
int soil5t = 0;
int soil5b = 0;
int soil6t = 0;
int soil6b = 0;
//const int SDpin = 20;
const int buttonPin = 24;
bool buttonState = 0;
byte temperature = 0;
byte humidity = 0;
unsigned long previousMillis = 0;
const int interval = 30000;
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // pin 13 lights up when measurements are being taken
lcd.begin(16, 2);
lcd.print("Prova LCD");
delay(1000);
lcd.clear();
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
digitalWrite(LED_BUILTIN, LOW);
// setup SD
if (SD.begin(53))
{
Serial.println("modulo SD pronto");
lcd.setCursor(0,0);
lcd.print("SD OK");
delay(1000);
lcd.clear();
}
else
{
Serial.println("SD non funzionante");
lcd.print("errore SD (1)");
while(1);
}
// writing Header on data sheet (date, time, RH, T, 1Top, 1Bottom, 2T, 2B ... 6T, 6B)
data_file = SD.open("test1.txt", FILE_WRITE);
if (data_file)
{
Serial.print("Intesto il file...");
lcd.print("intesto il file");
data_file.print("date, time, RH, T, 1T, 1B, 2T, 2B, 3T, 3B, 4T, 4B, 5T, 5B, 6T, 6B");
data_file.print("\n");
data_file.close();
Serial.println("fatto");
lcd.clear();
lcd.print("file OK");
delay(1000);
lcd.clear();
}
else
{
Serial.println("SD non aperta. Cambia SD o prova a formattarla.");
lcd.print("errore SD (2)");
while(1);
}
// clock setup
if (! rtc.begin())
{
Serial.println("Clock non funzionante");
lcd.print("errore clock");
while (1);
}
else
{
Serial.print("Imposto il tempo...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// rtc.adjust(DateTime(2023, 4, 12, 3, 0, 0)); //if we need to start the thing without a pc
Serial.println("fatto");
lcd.print("Clock OK");
delay(1000);
lcd.clear();
}
//setup theta sensors
pinMode(A15, INPUT); //for now only A15-A11, relative to 1T, 1B, 2T, 2B e 3T (see photo for reference)
pinMode(A14, INPUT);
pinMode(A13, INPUT);
pinMode(A12, INPUT);
pinMode(A11, INPUT);
pinMode(A10, INPUT);
pinMode(A9, INPUT);
pinMode(A8, INPUT);
pinMode(A7, INPUT);
pinMode(A6, INPUT);
pinMode(A5, INPUT);
pinMode(A4, INPUT);
pinMode(ENABLEA, OUTPUT);
pinMode(ENABLEB, OUTPUT);
pinMode(DIRA, OUTPUT);
pinMode(DIRB, OUTPUT);
digitalWrite(ENABLEA, HIGH); // fans
digitalWrite(ENABLEB, HIGH);
digitalWrite(DIRA, HIGH);
digitalWrite(DIRB, HIGH);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) { // the measurements are taken every 30 seconds (from here to line 287)
previousMillis = currentMillis;
digitalWrite(LED_BUILTIN, HIGH); // led lights up
// opening the file and writing the date and time
data_file = SD.open("test1.txt", FILE_WRITE);
int err = SimpleDHTErrSuccess;
if (data_file) {
writeTime();
data_file.close();
}
else {
Serial.println("SD non aperta. Cambia SD o prova a formattarla.");
lcd.print("errore SD(3)");
while(1);
}
// RH and T measurements
if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess)
{
Serial.print("Errore nella lettura del DHT");
lcd.print("errore DHT");
while(err = dht11.read(&temperature, &humidity, NULL) != SimpleDHTErrSuccess);
lcd.clear();
}
else
{
data_file = SD.open("test1.txt", FILE_WRITE);
Serial.print("H = ");
Serial.print(humidity);
Serial.print(", T = ");
Serial.println(temperature);
data_file.print(humidity);
data_file.print(",");
data_file.print(temperature);
data_file.print(",");
data_file.close();
}
//writing theta measurements
data_file = SD.open("test1.txt", FILE_WRITE);
soil1t = analogRead(A15);
data_file.print(soil1t);
data_file.print(",");
soil1b = analogRead(A14);
data_file.print(soil1b);
data_file.print(",");
soil2t = analogRead(A13);
data_file.print(soil2t);
data_file.print(",");
soil2b = analogRead(A12);
data_file.print(soil2b);
data_file.print(",");
soil3t = analogRead(A11);
data_file.print(soil3t);
data_file.print(",");
soil3b = analogRead(A10);
data_file.print(soil3b);
data_file.print(",");
soil4t = analogRead(A9);
data_file.print(soil4t);
data_file.print(",");
soil4b = analogRead(A8);
data_file.print(soil4b);
data_file.print(",");
soil5t = analogRead(A7);
data_file.print(soil5t);
data_file.print(",");
soil5b = analogRead(A6);
data_file.print(soil5b);
data_file.print(",");
soil6t = analogRead(A5);
data_file.print(soil6t);
data_file.print(",");
soil6b = analogRead(A4);
data_file.print(soil6b);
data_file.print("\n");
data_file.close();
digitalWrite(LED_BUILTIN, LOW);
}
while (millis() - previousMillis <= interval) //until it's not time for a new measurement, check if the button is pressed
{
// LCD shows data if button is pressed
buttonState = digitalRead(buttonPin);
if (buttonState == 0)
{
Serial.println("Bottone");
lcd.clear();
lcd.print(nowDT.day());
lcd.print("/");
lcd.print(nowDT.month());
lcd.print(",");
lcd.print(nowDT.hour());
lcd.print(":");
if (nowDT.minute()<10)
{
lcd.print("0");
lcd.print(nowDT.minute());
}
else
{ lcd.print(nowDT.minute());}
lcd.print(":");
if (nowDT.second()<10)
{
lcd.print("0");
lcd.print(nowDT.second());
}
else { lcd.print(nowDT.second()); }
delay(1000);
lcd.clear();
lcd.print("H = ");
lcd.print(humidity);
lcd.setCursor(0, 1);
lcd.print("T = ");
lcd.print(temperature);
delay(1500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("1T = ");
lcd.print(soil1t);
lcd.setCursor(0,1);
lcd.print("1B = ");
lcd.print(soil1b);
delay(1500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("2T = ");
lcd.print(soil2t);
lcd.setCursor(0,1);
lcd.print("2B = ");
lcd.print(soil2b);
delay(1500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("3T = ");
lcd.print(soil3t);
lcd.setCursor(0,1);
lcd.print("3B = ");
lcd.print(soil3b);
delay(1500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("4T = ");
lcd.print(soil4t);
lcd.setCursor(0,1);
lcd.print("4B = ");
lcd.print(soil4b);
delay(1500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("5T = ");
lcd.print(soil5t);
lcd.setCursor(0,1);
lcd.print("5B = ");
lcd.print(soil5b);
delay(1500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("6T = ");
lcd.print(soil6t);
lcd.setCursor(0,1);
lcd.print("6B = ");
lcd.print(soil6b);
delay(1500);
lcd.clear();
buttonState = 1;
}
}
}
void writeTime()
{
nowDT = rtc.now();
// debug
Serial.print(nowDT.day());
Serial.print("/");
Serial.print(nowDT.month());
Serial.print(",");
Serial.print(nowDT.hour());
Serial.print(":");
if (nowDT.minute()<10)
{
Serial.print("0");
Serial.print(nowDT.minute());
}
else
{ Serial.print(nowDT.minute());}
Serial.print(":");
if (nowDT.second()<10)
{
Serial.print("0");
Serial.println(nowDT.second());
}
else { Serial.println(nowDT.second()); }
//
data_file.print(nowDT.day());
data_file.print("/");
data_file.print(nowDT.month());
data_file.print(",");
data_file.print(nowDT.hour());
data_file.print(":");
if (nowDT.minute() < 10)
{
data_file.print("0");
data_file.print(nowDT.minute());
}
else
{
data_file.print(nowDT.minute());
}
data_file.print(":");
if (nowDT.second() < 10)
{
data_file.print("0");
data_file.print(nowDT.second());
}
else
{
data_file.print(nowDT.second());
}
data_file.print(",");
}
Thanks in advance!