Datalogger e funzione

Sto realizzando un semplice datalogger e mi piacerebbe capire come creare una funzione per semplificare un po’ il listato. Ammesso che si possa fare, (le funzioni devo ancora capirle per bene) è possibile crearla da questo blocco

      RTC.read(tm);
      dataFile.print("Data= ");
      dataFile.print(tm.Day);
      dataFile.print('/');
      dataFile.print(tm.Month);
      dataFile.print('/');
      dataFile.print(tmYearToCalendar(tm.Year));
      dataFile.print("   ");
      dataFile.print("Time= ");
      dataFile.print(tm.Hour);
      //print2digits(tm.Hour);
      dataFile.print(':');
      dataFile.print(tm.Minute);
      //print2digits(tm.Minute);
      dataFile.print(':');
      dataFile.print(tm.Second);
      //print2digits(tm.Second);
      dataFile.print("  >> ");
      dataFile.print(incoming);
      dataFile.println(" <<");
      dataFile.close();

preso dal listato completo ciè questo?

/* Connessioni:

 * SD card collegata al bus SPI
 - MOSI - pin 11
 - MISO - pin 12
 - CLK - pin 13
 - CS - pin 10
 */

// Ricevitore con funzione "Uomo presente"
//#include <SoftwareSerial.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

#define out1 3
//#define out2 7                             // feedback di stato uscita
//SoftwareSerial mySerial(8, 9);            // RX, TX per debug
char incoming;
const int chipSelect = 10;

void setup()
{
  pinMode(out1, OUTPUT);
  //pinMode(out2, OUTPUT);   
  Serial.begin(9600);                            // inzializzo seriale
  //mySerial.begin(9600);                     // inzializzo seriale di debug
  SD.begin(chipSelect);

  /*
  mySerial.println("Inizializzo SD card...");
  if (!SD.begin(chipSelect)) {  // see if the card is present and can be initialized
    mySerial.println("Inizializzazione fallita o SD non presente");
    return; // don't do anything more:
  }
  mySerial.println("Card inizializzata.");
  */
}

void loop()
{
  tmElements_t tm;

  if(Serial.available()>0){
    incoming = Serial.read();
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if (dataFile) {         // if the file is available, write to it
      RTC.read(tm);
      dataFile.print("Data= ");
      dataFile.print(tm.Day);
      dataFile.print('/');
      dataFile.print(tm.Month);
      dataFile.print('/');
      dataFile.print(tmYearToCalendar(tm.Year));
      dataFile.print("   ");
      dataFile.print("Time= ");
      dataFile.print(tm.Hour);
      //print2digits(tm.Hour);
      dataFile.print(':');
      dataFile.print(tm.Minute);
      //print2digits(tm.Minute);
      dataFile.print(':');
      dataFile.print(tm.Second);
      //print2digits(tm.Second);
      dataFile.print("  >> ");
      dataFile.print(incoming);
      dataFile.println(" <<");
      dataFile.close();
    } 
    /*
    else {  // if the file isn't open, pop up an error:
     mySerial.println("error opening datalog.txt");
    }
    */

    if(incoming == 'H' ){                      // se arriva comando ON
      digitalWrite(out1, HIGH);                // scrivo su out1
      //digitalWrite(out2, HIGH);
      //mySerial.println('H');
      delay(100);
    }
    if(incoming == 'L'){                       // se arriva comando OFF
      digitalWrite (out1, LOW);                // scrivo su out1
      //digitalWrite (out2, LOW);
      //mySerial.println('L');
      delay(100); 
    }
  }     
}
/*
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}
*/

Ho provato parecchio anche tentando di capire cosa c’è scritto su alcuni testi in mio possesso ma proprio non ci riesco…
Grazie per l’eventuale dritta.

Spostando quel pezzo di codice in una funzione tutte le variabili che usa devono essere passate alla tua funzione.
In alcuni casi, anche se non bello, puoi fare uso delle variabili globali (come programmazione è penosa).
Esempio RTC potresti non passarla alla funzione, ma di sicuro devi passare datafile. A questo punto mi pare meglio se la funzione di incarica anche di aprire il file e chiuderlo. In questo caso la tua funzione deve avere come parametri il nome del file e "incoming". Poi tra le variabili locali alla funzione puoi mettere una variabile "tm"

nid69ita:
In alcuni casi, anche se non bello, puoi fare uso delle variabili globali (come programmazione è penosa).

Ma assolutamente no, l’uso delle variabili globali è caldamente consigliato quando dei valori devono essere visibili a tutto il programma.
Passare una variabile ad una funzione, con relativa creazione di quella locale, è un modo ottimo per usare più ram e sprecare tempo cpu :slight_smile:
Va da se che creare una variabile globale che poi sarà usata solo dentro una singola funzione è inutile e spreca ram.

@astro, in programmazione generale, una funzione dovrebbe essere isolata dal resto del programma.
Ovviamente questo su PC con tanta RAM, su queste piccole MCU sono d'accordo con te che più risparmi memoria è meglio è. :slight_smile:

Purtroppo avete scritto cose che avevo gia letto ma non compreso…

nello specifico leggo che dovrei passare le variabili:
ma datafile che tipo di variabile è ?

Il risultato potrebbe essere questo?

      void lettura (RTC, datafile, char incoming){
      RTC.read(tm);
      dataFile.print("Data= ");
      dataFile.print(tm.Day);
      dataFile.print('/');
      dataFile.print(tm.Month);
      dataFile.print('/');
      dataFile.print(tmYearToCalendar(tm.Year));
      dataFile.print("   ");
      dataFile.print("Time= ");
      dataFile.print(tm.Hour);
      //print2digits(tm.Hour);
      dataFile.print(':');
      dataFile.print(tm.Minute);
      //print2digits(tm.Minute);
      dataFile.print(':');
      dataFile.print(tm.Second);
      //print2digits(tm.Second);
      dataFile.print("  >> ");
      dataFile.print(incoming);
      dataFile.println(" <<");
      dataFile.close();
}

Non ho aggiunto la parte di apertura file in quanto scriverei sicuramente una cosa assolutamente a caso dato che non ho chiaro come si fa…

Un esempio pratico su quanto postato è sempre molto ben accetto.
Grazie

nid69ita:
@astro, in programmazione generale, una funzione dovrebbe essere isolata dal resto del programma.

Mica è vero, in C/C++ le funzioni sono il programma stesso e se devono condividere delle informazioni, praticamente quasi sempre, il modo migliore per farlo è usare le variabili globali, vale sia per le piccole mcu che per i micro Arm 32/64 bit e il pc. :slight_smile:
Se usare i normali tipi base di dato, delle strutture o unioni, oppure dei puntatori dipende da quali dati devono essere visibili da tutto il programma.

Cioè chiameresti "lettura" una funzione che scrive in un file ?

Siccome il file lo chiudi nella funzione (datafile.close) allora anche l'apertura mi pare più sensata averla nella funzione.

Poi se lasci le variabili come globali, come dice @astro, alla fine puoi fare una funzione void senza parametri e ci ficchi tutto quel pezzo di codice.

void ScriviFile()
{ 
}

Se intendevi il nome un po' fuorviante, si può cambiare...

Siccome il file lo chiudi nella funzione (datafile.close) allora anche l'apertura mi pare più sensata averla nella funzione.

Assolutamente vero, solo che come dicevo non so come strutturarlo.

[Poi se lasci le variabili come globali, come dice @astro, alla fine puoi fare una funzione void senza parametri e ci ficchi tutto quel pezzo di codice.

É la prima strada che ho tentato solo che mi uscivano una marea di errori e non ho trovato nessun esempio che mi potesse dare uno spunto.