Hi. I'm working on a proyect that consists on an auto watering system with sensors, an rtc module and a SD card module. The model of the RTC is RTC3231. Arduino Nano.
Inside the SD card is a csv file called "config.csv", i want to read that file.
Because i'm not the best at saving dynamic memory space, i checked a library called CSV_Parser, that does the work well.
When i used this library alone, there was no issues, but when i added the library RTClib (Adafruit) and used rtc.begin(), the csv parser started to throw weird lectures.
Why does this happen? How could i locate the problem? How should i solve it?
Down here is the code.
#define ROW_LENGTH 57 // Fixed length of each row, counting the EOL characters
#include "Time.h"
#include <SPI.h>
#include "SD.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <EEPROM.h>
#include "RTClib.h"
#include <CSV_Parser.h>
Sd2Card card;
SdVolume volume;
SdFile root;
File myFile;
DateTime now;
RTC_DS3231 rtc;
const int chipSelect = 4;
unsigned long wateringTime; // Cantidad de tiempo(en milisegundos) el cual dura el riego
const int8_t wateringTimeAdr = 0; // Dirección en la memoria EEPROM donde se guardará la variable
unsigned long logInterval; // cada cuanto tiempo se realizan los senseos y guardado de ellos
const int8_t logIntervalAdr = 4;
unsigned long wateringInterval; // Período de tiempo para el riego, osea, cada cuanto está disponible el riego, si todavía no paso este tiempo desde el último regado, no se riega
const int8_t wateringIntervalAdr = 8;
uint16_t soilHumLim; // Umbral de humedad del suelo para saber si regar o no
const int8_t soilHumLimAdr = 12;
byte ambHumLim; // Umbral de humedad del ambiente para saber si prender el extractor o no
const int8_t ambHumLimAdr = 16;
byte startWateringAt; // Se desea regar en un rango horario del día determinado
const int8_t startWateringAtAdr = 20;
byte endWateringAt; // start y end representan las horas en donde arranca y termina el período
const int8_t endWateringAtAdr = 21;
byte lightsON; // Cuando prendemos las luces
const int8_t lightsONAdr = 22;
byte lightsOFF; // Cuando apagamos las luces
const int8_t lightsOFFAdr = 23;
time_t lastWatered; // Variable que guarda la fecha y hora del último regado, tipo de dato uint32_t para guardar tiempo, ver más adelante cuando se guarde en el regado
const int8_t lastWateredAdr = 24;
CSV_Parser cp(/*format*/ "ucuLuLuLuducucucucuc", /*has_header*/ true, /*delimiter*/ ',');
void setup() {
Serial.begin(9600);
Wire.begin();
if(! rtc.begin()) {
delay(5000);
Serial.println("Error rtc");
}
// Establece la fecha y hora del rtc a la fecha en el cual se compiló el sketch, si el rtc no está corriendo
if (rtc.lostPower()) { // If we have a rtc model other than 3231, we could use the "isrunning" method
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
now = rtc.now();
pinMode(chipSelect, OUTPUT);
delay(5000);
if (!SD.begin(chipSelect)){
Serial.println("error sd");
}
myFile = SD.open("/config.CSV", O_RDWR);
checkConfig();
for (int16_t n = 0 ; n < 200 ; n++) {
myFile.seek(n);
Serial.print(n);
Serial.print(", ");
Serial.write(myFile.read());
Serial.println(".");
delay(5);
}
myFile.flush();
cp.print();
}
void loop() {
// put your main code here, to run repeatedly:
}
// Function that marks a row as already used by changing the first character from 1 to 0
void deleteLine(uint32_t lineNumber) { // lineNumber is the number of the line selected to mark as already loaded (starting at 1)
SD.open("config.CSV", O_RDWR);
uint32_t pointer = (lineNumber + 1)*ROW_LENGTH;
myFile.seek(pointer); // sets the pointer of the file at the start of the desired row
// We only want to overwrite the first character.
myFile.print("0");
}
void checkConfig(){
if (cp.readSDfile("/config.CSV")) {
uint8_t *notLoaded = (uint8_t*)cp["loaded"];
uint32_t *configTime = (uint32_t*)cp["cTime"];
uint32_t *SDwateringTime = (uint32_t*)cp["wTime"];
uint32_t *SDwateringInterval = (uint32_t*)cp["watInt"];
uint16_t *SDsoilHumLim = (uint16_t*)cp["soilLim"];
uint8_t *SDambHumLim = (uint8_t*)cp["ambLim"];
uint8_t *SDstartWateringAt = (uint8_t*)cp["sW"];
uint8_t *SDendWateringAt = (uint8_t*)cp["eW"];
uint8_t *SDlightsON = (uint8_t*)cp["lON"];
uint8_t *SDlightsOFF = (uint8_t*)cp["lOFF"];
for (int row = 0; row <= cp.getRowsCount(); row++) {
//if(notLoaded[row] == 1) {
Serial.print(row);
Serial.print(" , ");
Serial.println(SDstartWateringAt[row]);
delay(500);
if (notLoaded[row] == 1) { // (rtc.now().unixtime() > configTime[row])
deleteLine(row);
}
}
}
else {
Serial.println("Error");
}
}
Before i added the rtc.begin() line, everything went fine, but when i added it, the program parsed me this:
Header:
loaded | cTime | wTime | watInt | soilLim | ambLim | sW | eW | lON | lOFF
Types:
uint8_t | uint32_t | uint32_t | uint32_t | uint16_t | uint8_t | uint8_t | uint8_t | uint8_t | uint8_t
Values:
0 | 1357971456 | 1111111111 | 1357971456 | 1111 | 111 | 11 | 11 | 11 | 11
0 | 117637459 | 1111111111 | 117637459 | 1111 | 111 | 11 | 11 | 11 | 11
0 | 524292 | 1111111111 | 524292 | 1111 | 111 | 11 | 11 | 11 | 11
0 | 327880 | 1111111111 | 327880 | 1111 | 111 | 11 | 11 | 11 | 11
0 | 4 | 1111111111 | 4 | 1111 | 111 | 11 | 11 | 11 | 11
But the columns "cTime" and "watInt" should be all 1's, why does this happen?