Datalloger con SD: problema con creazione file all'interno di sottocartella

Buonasera a tutti,
vorrei fare un datalogger in standalone per la raccolta dati per la temperatura del terreno durante l'anno. Essendo agli inizi del progetto, non ho ancora incluso lo sleep ecc..
con questo codice:

#include <SD.h>
#include <Wire.h>
#include "DHT.h"
#include <HCRTC.h>
#include "RTClib.h"
//#include <SoftwareSerial.h>
#define I2CDS1307Add 0x68
#define DHTTYPE DHT22

bool semaforo, semaforo2, semaforo3;
const byte DHTPIN = 7;
float minH = 1023, maxH = 0, h, minT = 1023, maxT = 0, t; //sommaT, sommaH, mediaT, mediaH;
const byte PinChipSelect = 10;
char nomefile[15], indirizzoCartelle[30];
//String  comando;
HCRTC HCRTC;
RTC_DS1307 RTC;
//SoftwareSerial mySerial(9, 8);
File dataLogger;
DHT dht(DHTPIN, DHT22);
void setup()
{
  pinMode(DHTPIN, INPUT);
  RTC_DS1307 RTC;
  //  mySerial.begin(9600);
  Serial.begin(9600);
  SD.begin();
  dht.begin();
  RTC.begin();
  pinMode(PinChipSelect, OUTPUT);
  analogReference(INTERNAL);
  //RTC.adjust(DateTime(__DATE__, __TIME__));
  HCRTC.RTCWrite(I2CDS1307Add, 20, 12, 1, 00, 0, 0, 1); //impostare una data predefinita
}
void loop()
{
  //PRINT SD-CARD
  //giornaliero
  HCRTC.RTCRead(I2CDS1307Add);
  if ((HCRTC.GetHour() == 0) && (HCRTC.GetMinute() == 0)){
    if (semaforo == 0){
      letturaDHT();
      Serial.println("lettura DHT 00.00");
      snprintf(indirizzoCartelle, 30, "%02d/%02d", HCRTC.GetYear() % 100, HCRTC.GetMonth());
      if (SD.mkdir(indirizzoCartelle)){ //se esiste, crea file nomefile
        sprintf(nomefile, "%02d_%02d_%02d.csv", HCRTC.GetDay(), HCRTC.GetMonth(), HCRTC.GetYear() % 100);
        dataLogger = SD.open(nomefile, FILE_WRITE);
        if (dataLogger) {
          ScriviFile(t, h, 1);
          //        sommaT = 0;
          //        sommaH = 0;
          Serial.println("scrittura 00.00");
          semaforo = 1;
        }
      }
    }
  }
  else semaforo = 0;
  HCRTC.RTCRead(I2CDS1307Add);
  if ((HCRTC.GetMinute() == 1) || (HCRTC.GetMinute() == 15) || (HCRTC.GetMinute() == 30) || (HCRTC.GetMinute() == 45)){
    if (semaforo2 == 0){
      letturaDHT();
      Serial.println("lettura DHT durante il giorno");
      sprintf(nomefile, "%02d_%02d_%02d.csv", HCRTC.GetDay(),  HCRTC.GetMonth(), HCRTC.GetYear() % 100);
      dataLogger = SD.open(nomefile, FILE_WRITE);
      if (dataLogger){
        mySerial.println("scrittura durante il giorno");
        semaforo2 = 1;
        ScriviFile(t, h, 0);
        //        sommaT = 0;
        //        sommaH = 0;
      }
    }
  }
  else semaforo2 = 0;
  HCRTC.RTCRead(I2CDS1307Add);
  if ((HCRTC.GetHour() == 23) && (HCRTC.GetMinute() == 59)){
    if (semaforo3 == 0){
      letturaDHT();
      Serial.println("lettura DHT 23.59");
      sprintf(nomefile, "%02d_%02d_%02d.csv", HCRTC.GetDay(),  HCRTC.GetMonth(), HCRTC.GetYear() % 100);
      dataLogger = SD.open(nomefile, FILE_WRITE);
      if (dataLogger){
        Serial.println("scrittura 23.59");
        semaforo3 = 1;
        dataLogger.print(";");
        dataLogger.print(";");
        dataLogger.print(";");
        dataLogger.print(";");
        dataLogger.print(minT);
        dataLogger.print(";");
        dataLogger.print(maxT);
        dataLogger.print(";");
        dataLogger.print(minH);
        dataLogger.print(";");
        dataLogger.print(maxH);
        dataLogger.print(";");
        dataLogger.close();
        minT = 0; maxT = 0; minH = 0; maxH = 0;
      }
    }
  }
  else semaforo3 = 0;
  /*
    if (mySerial.available() > 0)
    {
    comando = mySerial.readString();
    comando.trim();
    }
    else if (comando.indexOf("controllo") > -1)
    {
    comando.remove(0, 9);
    comando.trim();
    HCRTC.RTCRead(I2CDS1307Add);
    mySerial.print(HCRTC.GetDateString());
    mySerial.print(F(" - "));
    mySerial.println(HCRTC.GetTimeString());
    }
    else if (comando.indexOf("data") > -1)
    {
    comando.remove(0, 4);
    comando.trim();
    HCRTC.RTCRead(I2CDS1307Add);
    String giorn = comando.substring(0, 2);
    String mes = comando.substring(2, 4);
    String ann = comando.substring(4, 6);
    long giorno = 0, mese = 0, anno = 0;
    giorno = giorn.toInt();
    mese = mes.toInt();
    anno = ann.toInt();
    mySerial.print (F("Data aggiornata: "));
    if (giorno < 10)
      mySerial.print(F("0"));
    mySerial.print(giorno); mySerial.print(F("/"));
    if (mese < 10)
      mySerial.print(F("0"));
    mySerial.print(mese); mySerial.print(F("/"));
    if (anno < 10)
      mySerial.print(F("0"));
    mySerial.println(anno);
    RTC.adjust(DateTime(anno, mese, giorno, 0, 0, 0));
    }
    else if (comando.indexOf("rtc") > -1)
    {
    comando.remove(0, 3);
    comando.trim();
    String hora = comando.substring(0, 2);
    String minut = comando.substring(2, 4);
    long ora = 0, minuto = 0;
    ora = hora.toInt();
    minuto = minut.toInt();
    mySerial.print(F("Ora aggiornata: "));
    if (ora < 10)
      mySerial.print(F("0"));
    mySerial.print(ora); mySerial.print (F(":"));
    if (minuto < 10)
      mySerial.print(F("0"));
    mySerial.println(minuto);
    RTC.adjust(DateTime(HCRTC.GetYear(), HCRTC.GetMonth(), HCRTC.GetDay(), ora, minuto,  HCRTC.GetSecond()));
    }
  */
}
void ScriviFile(float t, float h, byte condata)
{
  if (condata > 0) dataLogger.print(HCRTC.GetDateString());
  dataLogger.print(";");
  if (HCRTC.GetHour() < 10) dataLogger.print("0");
  dataLogger.print(HCRTC.GetHour());
  dataLogger.print(":");
  if (HCRTC.GetMinute() < 10) dataLogger.print("0");
  dataLogger.print(HCRTC.GetMinute());
  dataLogger.print(";");
  dataLogger.print(t);
  dataLogger.print(";");
  dataLogger.print(h);
  dataLogger.println(";");
  dataLogger.close();
}
void letturaDHT ()
{
  t = dht.readTemperature();
  h = dht.readHumidity();
  maxH = max(h, maxH);
  minH = min(h, minH);
  maxT = max(t, maxT);
  minT = min(t, minT);
  /*for (byte i = 0; i < 10; i++)
    {
    t = dht.readTemperature();
    h = dht.readHumidity();
    sommaT = + t;
    sommaH = + h;
    }
    mediaT = sommaT / 10;
    mediaH = sommaH / 10;

  */
}

troverò nella directory principale due file:

  1. 31_03_20.csv che risulterà essere corrotto (non so per quale motivo viene creato :o )
  2. 01_12_20.csv con la stampa corretta dei dati. (in setup ho impestato l'RTC al 01/12/2020 alle 00:00

e poi due cartelle:
directoryPrincipale/20/12 (vuoto)

il mio intento però è quello di creare il file 01_12_20.csv all'interno della cartella 12 (che indica il mese corrente)

come posso risolvere? :confused:

La libreria SD non ha un concetto di cartella corrente, quindi la open deve dire tutto il percorso completo se vuoi creare il file nella sottocartella.
esempio nomefile="/cartella1/subcartella/file.txt";

grazie nid per la risposta.
c'è un modo per sommare "indirizzoCartelle" con "nomeFile"?
dovrei fare la somma di due array di char

Si, strcat() ma devi avere un array di char grande abbastanza

Grazie nid, ho risolto e funziona.
Adesso ogni giorno mi crea un file diverso all'interno delle cartelle.
Adesso però vorrei creare anche dei file "settimanali" e non solo "giornalieri".
ad esempio:

6_12
13_19
20_26
27_3

ma temo che quest'impostazione sia impossibile da fare >:(

  1. perchè se sono al giorno 27, dovrei creare un file che mi dia un valore di 27 + 7 giorni, ch però con un semplice incremento non funziona perchè potrebbe darmi 34...e non esiste mese di 34 giorni..

  2. perchè prendendo l'ultima settimana del mese attuale "27_3" succederebbe che nella cartella di "aprile" mi viene salvato fino al 30 e poi un altro file continuo nlla cartella "maggio" fino al 3.

Riducendo il campionamento (da una settimana a meno) non cambia nulla, avrò sempre gli stessi problemi :roll_eyes:
non so in che modo venirne a capo...chiedo agli esperti la fattibilità :slight_smile:

EDIT:
Essendo un quesito abbastanza difficile, ho risolto nel terminale del sistema operativo concatenando con un comando tutti i file csv di una cartella

Scusami, ma non ho capito
Giornalieri, un file per ogni giorno, con i dati del singolo e relativo giorno
Settimanali, file con dentro i dati di 7 giorni ?

Si, esatto

Il file settimanale potresti usare il numero della settimana. In un anno ci sono 52 settimane circa, però la libreria che usi non credo abbia una funzione che ti dice la settimana corrente. Oggi per esempio siamo alla 14 settimana.

Oppure ti fai un tuo contatore, uno da 1 a 7, e un altro da 1 a 52. Quando scatta il 1..7 rimetti a 1 e aumenti l'altro. Arrivato a 52, rimetti a 1

io il problema lo vedo abbastanza semplice da risolvere, certo c'é da sbattersi un pochino, ma nemmeno tanto
una road-map:

  1. decidere se la settimana comincia col lunedì, il martedì o la domenica o cosa
  2. cercare, trovare e capire la funzione in C che data una data dice che giorno della settimana è
    in questo il santo google è una manna
  3. giorno per giorno vedere se è cominciata una settimana oppure no
  4. se no nulla di grave, si va via salvando normalmente i file i giornalieri
  5. se sì si legge la data dell'inizio della settiamana precedente (vedere dopo)
    da quella data e dalla data attuale si conosce il nome del file settimanale da creare
    si crea il file
    si aprono gli ultimi 7 file giornalieri, si leggono riga a riga e si copiano nel settimanale
    si salva la nuova data di inizio settimana (vedi prima)
  6. lavoro finito

nid69ita:
ti fai un tuo contatore, uno da 1 a 7, e un altro da 1 a 52. Quando scatta il 1..7 rimetti a 1 e aumenti l'altro. Arrivato a 52, rimetti a 1

Ottimo, ho optato per questo. Adesso ho un problemino inaspettato..

io dichiaro queste variabili globali:

char nomeFileGiornaliero[13]; //esempio: 05_04_20.csv incluso null 0x00
indirizzoCartelleGiornaliero[20]; // esempio: /20/12/01_12_20.csv incluso null 0x00
nomeFileSettimanale[17];  // settimana_14.csv incluso null 0x00
indirizzoCartelleSettimanale[21]; // /20/settimana_14.csv incluso null 0x00

e poi in loop:

  snprintf(indirizzoCartelleGiornaliero, 30, "/%02d/%02d/", HCRTC.GetYear() % 100, HCRTC.GetMonth());
  SD.mkdir(indirizzoCartelleGiornaliero);
  sprintf(nomeFileGiornaliero, "%02d_%02d_%02d.csv", HCRTC.GetDay(), HCRTC.GetMonth(), HCRTC.GetYear() % 100);
  strcat(indirizzoCartelleGiornaliero, nomeFileGiornaliero);

  dataLogger = SD.open(indirizzoCartelleGiornaliero, FILE_WRITE);
  if (dataLogger) ScriviFile(t, 1, 1);
  Serial.print("nomeFile Giornaliero: ");
  Serial.println(nomeFileGiornaliero);
  Serial.print("indirizzo Cartelle Giornaliero: ");
  Serial.println(indirizzoCartelleGiornaliero);

in Seriale non mi stampa nulla..nè l'indirizzo giornaliero nè quello settimanale :o

Standardoil:
io il problema lo vedo abbastanza semplice da risolvere, certo c'é da sbattersi un pochino, ma nemmeno tanto
una road-map:

  1. decidere se la settimana comincia col lunedì, il martedì o la domenica o cosa
  2. cercare, trovare e capire la funzione in C che data una data dice che giorno della settimana è
    in questo il santo google è una manna
  3. giorno per giorno vedere se è cominciata una settimana oppure no
  4. se no nulla di grave, si va via salvando normalmente i file i giornalieri
  5. se sì si legge la data dell'inizio della settiamana precedente (vedere dopo)
    da quella data e dalla data attuale si conosce il nome del file settimanale da creare
    si crea il file
    si aprono gli ultimi 7 file giornalieri, si leggono riga a riga e si copiano nel settimanale
    si salva la nuova data di inizio settimana (vedi prima)
  6. lavoro finito

Ciao Standardoil, grazie per la risposta. Purtroppo questa strada non è fattibile per un semplice motivo: i due file non sono identici. Il giornaliero è più dettagliato, ha una maggiore mole di dati in un intervallo però più ristretto. Apprezzo molto la risposta :slight_smile: