Bräuchte Hilfe bei Sketch Anpassung

Hallo,

Ich habe mir einen Temperaturlogger zur Erfassung von Außentemperaturen gebaut.
Hardware: Elegoo Uno mit aufgestecktem SD/RTC Shield und Sensor TMP 36 dessen Signal über
Analog “0” eingelesen wird. Die Schaltung mit passendem Sketch (siehe Anlage) habe ich im Internet gefunden und funktioniert einwandfrei. Das Original Programm zeichnet alle 5 sec. die Temp. auf die SD Karte.
Ich möchte jedoch daß die Temperaturen täglich immer zu festen Zeiten eingelesen werden, und zwar
um 6:00 / 12:00 / 18:00 / 24:00 Uhr. Da ich leider zu wenig Programmierkenntnisse besitze, könnte mir da jemand behilflich sein?

Gruß
Günther

Temperaturlogger_mit_TMP_36.ino (8.19 KB)

Gueni:
Die Schaltung mit passendem Sketch (siehe Anlage) …

Könntest Du noch die Schaltung zeigen oder verlinken?

Gruß

Gregor

Es wäre sinnvoll, Deinen Sketch hier in Codetags (</> oben links im Forumseditor) einzustellen, damit ihn alle lesen können. Die DS1307 ist nicht besonders genau, besonders wenn Du Langzitmessungen durchführen willst.

Ein Link zu den jeweiligen Libs wäre auch nicht schlecht, da es oft Libs mit gleichem Namen aber unterschiedlichen Inhalten gibt.

Gruß Tommy

Hier der Link:

/////////////////////////////////////////////////////////////////
//
// Datalogger Demo (c) Michael Stal, 2016
//
// Messung der Temperatur an einem TMP36
// Zeitverarbeitung mit RTClib (Chip DS1307, über IIC)
// SD Card Zugriff mit SdFat   (über SPI MISO/MOSI)
// RTC und SD Card entweder separat angeschlossen
// oder über Adafruit Datalogger Shield
//
/////////////////////////////////////////////////////////////////


// ******************** DEKLARATIONEN ***************************

/////////////////////////////////////////////////////////////////
// DEKLARATIONEN RTC (Echtzeituhr)
/////////////////////////////////////////////////////////////////
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc; // Zugriff auf RTC

char WochenTage[7][12] = {"Sonntag",
                          "Montag",
                          "Dienstag",
                          "Mittwoch",
                          "Donnerstag",
                          "Freitag",
                          "Samstag"};


/////////////////////////////////////////////////////////////////
// DEKLARATIONEN SD Card
/////////////////////////////////////////////////////////////////
#define LOGDATEI "TMP36"



#include <SPI.h>
#include "SdFat.h"

// Chip Selector auf Arduino Board
const uint8_t chipSelect = SS;

// Separatorzeichen für Dateiausgabe
const String SEP = ";";

// Zugriff auf Dateisystem der SD Card
SdFat sd;

// Log-Datei
SdFile datei;

// Fehlermeldungen im Flash ablegen.
#define error(msg) sd.errorHalt(F(msg))


/////////////////////////////////////////////////////////////////
// DEKLARATIONEN TemperaturSensor
/////////////////////////////////////////////////////////////////

const int   TMP36Pin              = A0;
const float VersorgungsSpannung   = 5.0;  // ändern für 3.3V
const int   ZeitZwischenMessungen = 5;    // in Sekunden


// ********************** METHODEN ******************************

/////////////////////////////////////////////////////////////////
//
// initRTC()
//    Echtzeituhr initialisieren
//
/////////////////////////////////////////////////////////////////
void initRTC()
{
    if (! rtc.begin()) { // ist eine Uhr angeschlossen?
      Serial.println("Echtzeituhr fehlt");
      while(1); // Fehlerschleife
    }
    if (! rtc.isrunning()) { // Uhr schon gesetzt?
    Serial.println("RTC bisher noch nicht gesetzt!");
    // => Initialisiere Zeit und Datum auf Datum/Zeit des Host-PCs
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}


/////////////////////////////////////////////////////////////////
//
// initSDCardReader()
//    Kartenleser initialisieren
//
/////////////////////////////////////////////////////////////////
void initSDCardReader()
{
  const uint8_t NAMENSLAENGE= sizeof(LOGDATEI) - 1;
  char dateiName[13] = LOGDATEI "00.csv"; // Z.B. TMP3604.csv
 
  delay(1000);
  // SD Card mit SPI_HALF_SPEED initialisieren, um Fehler
  // bei Breadboardnutzung zu vermeiden.  Sonst => SPI_FULL_SPEED 
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { // Zugriff auf SD?
    sd.initErrorHalt();
  }
 
  // Dateiformat 8.3
  if (NAMENSLAENGE > 6) {
    error("Dateipräfix zu lang");
  }

  // Standarddateiname LOGDATEI  + laufende Nummer, z.B.
  // TMP3603.csv
  // Sobald alle Suffixe 00..09 verbraucht sind,
  // geht es von vorne los: round robin
 
  while (sd.exists(dateiName)) {
    if (dateiName[NAMENSLAENGE + 1] != '9') {
     dateiName[NAMENSLAENGE + 1]++;
    }
    else if (dateiName[NAMENSLAENGE] != '9') {
      dateiName[NAMENSLAENGE + 1] = '0';
      dateiName[NAMENSLAENGE]++;
    }
    else {
      error("Kann Datei nicht erzeugen");
    }
  }
  // Jetzt öffnen:
  if (!datei.open(dateiName, O_CREAT | O_WRITE | O_EXCL)) {
    error("Datei öffnen misslungen!");
  }

  Serial.print(F("Logging auf: "));
  Serial.println(dateiName);

  // Header schreiben
  schreibeHeader();
}


/////////////////////////////////////////////////////////////////
//
// setup()
//    Echtzeituhr und SD Card Leser initialisieren
//
/////////////////////////////////////////////////////////////////
void setup()
{
  Serial.begin(9600); // Serielle Kommunikation an
  initRTC();          // Echtzeituhr initialisieren
  initSDCardReader(); // SD Card initialisieren
}


/////////////////////////////////////////////////////////////////
//
// temperaturInCMessen()
//   Temperatur vom TMP36 über Analogeingang lesen
//
/////////////////////////////////////////////////////////////////
float temperaturInCMessen()
{
  int digitalWertTmp36 = analogRead(TMP36Pin); // A0 einlesen
  float messwertSpannung = digitalWertTmp36 * VersorgungsSpannung / 1024.0;

  Serial.print("Spannung gemessen an Analogeingang ");
  Serial.print(TMP36Pin);
  Serial.print(" => ");
  Serial.println(messwertSpannung);

  // Wir berücksichtigen ausschließlich Celsius
  float temperaturInC = (messwertSpannung - 0.5) * 100;
 
  Serial.print("Temperatur in C = ");
  Serial.println(temperaturInC);
  return temperaturInC;
}


/////////////////////////////////////////////////////////////////
//
// ausgebenZeit()
//   Zeitausgabe zur Diagnose
//
/////////////////////////////////////////////////////////////////
void ausgebenZeit(DateTime jetzt) // easy Code
{
    Serial.print(jetzt.year(), DEC);
    Serial.print('/');
    Serial.print(jetzt.month(), DEC);
    Serial.print('/');
    Serial.print(jetzt.day(), DEC);
    Serial.print(" (");
    Serial.print(WochenTage[jetzt.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(jetzt.hour(), DEC);
    Serial.print(':');
    Serial.print(jetzt.minute(), DEC);
    Serial.print(':');
    Serial.print(jetzt.second(), DEC);
    Serial.println();
}


/////////////////////////////////////////////////////////////////
//
// loop()
//   In jeder Iteration
//      Temperatur messen
//      Zeit erfassen
//      Daten auf SC Card schreiben
//      Terminierungsbedingung prüfen und ggf. stoppen
//      inkl. Dateischließen!
//
/////////////////////////////////////////////////////////////////
void loop()
{
 
  // Messwert am TMP36 auslesen
  float temperaturInC = temperaturInCMessen();

  // Vorgegebene Zeit warten
  delay(ZeitZwischenMessungen * 1000);

  // Datum & Zeit holen:
  DateTime jetzt = rtc.now();
  ausgebenZeit(jetzt); // und schreiben am seriellen Monitor

  // Jetzt Daten schreiben:
  schreibeMessung(temperaturInC, "C", jetzt);

  // Zufallsmechanismus für Stopp der Messungen
  if (random(7) == 1) {
      dateiSchliessen();
  }
}


/////////////////////////////////////////////////////////////////
// Statt in einer .csv-Datei könnte man z.B. auch im JSON Format
// speichern !!!
/////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////
//
// schreibeHeader
//    Schreiben von Header Information in Datei
//
/////////////////////////////////////////////////////////////////
void schreibeHeader() {
  datei.println(F("Temperaturmessungen mit TMP36 mit Nutzung eines Dataloggers"));
  datei.print(F("Datum")); 
  datei.print(SEP);
  datei.print(F("Zeit")); 
  datei.print(SEP);
  datei.print(F("Temperatur (Einheit Celsius)"));
  datei.println();
}


/////////////////////////////////////////////////////////////////
//
// schreibeMessung()
//    messwert nehmen und in gewählter Einheit ausgeben
//    und zusammen mit Datum und Uhrzeit in Datei schreiben
//
/////////////////////////////////////////////////////////////////
void schreibeMessung(float messwert,
                     String einheit,
                     DateTime jetzt)
{
  datei.print(jetzt.day());
  datei.print(".");
  datei.print(jetzt.month());
  datei.print(".");
  datei.print(jetzt.year());
  datei.print(SEP);
  datei.print(jetzt.hour());
  datei.print(":");
  datei.print(jetzt.minute());
  datei.print(":");
  datei.print(jetzt.second());
  datei.print(SEP);
  datei.print(messwert);
  datei.print(einheit);
  datei.println();
   // Dateisync, um Datenverlust zu vermeiden:
  if (!datei.sync() || datei.getWriteError()) {
    error("Schreibfehler!");
  }
}


/////////////////////////////////////////////////////////////////
//
// dateiSchliessen()
//    Datei wieder schließen
//
/////////////////////////////////////////////////////////////////
void dateiSchliessen()
{
  datei.close();
  Serial.println(F("Datei steht bereit!"));
  SysCall::halt();
}

// ********************** DATEIENDE *****************************

Tommy56:
Es wäre sinnvoll, Deinen Sketch hier in Codetags (</> oben links im Forumseditor) einzustellen, damit ihn alle lesen können. Die DS1307 ist nicht besonders genau, besonders wenn Du Langzitmessungen durchführen willst.

Ein Link zu den jeweiligen Libs wäre auch nicht schlecht, da es oft Libs mit gleichem Namen aber unterschiedlichen Inhalten gibt.

Gruß Tommy

Die Genauigkeit wäre mir jetzt nicht so wichtig, zumal ich jetzt das RTC Shield schon habe.
Die Links zun den Lib´s weiß ich nicht mehr weils schon eine Weile her ist, aber ich meine von GitHub.
Aber der Originalsketch läuft ja einwandfrei.

Gruß Günther

Probiers mal so (ungetestet):

// global
boolean gemessen = false;

...
if (!gemessen && rtc.minute() == 0 && (rtc.hour() == 0 || rtc.hour() == 6 || rtc.hour() == 12 || rtc.hour() == 18) {
  gemessen = true;
  // hier Deine Messung und das Schreiben der Werte
}
if (gemessen && rtc.minute() != 0) gemessen = false;

Gruß Tommy

Edit: das delay mit der Messzeit muss natürlich raus.

Tommy56:
Probiers mal so (ungetestet):

// global

boolean gemessen = false;

...
if (!gemessen && rtc.minute() == 0 && (rtc.hour() == 0 || rtc.hour() == 6 || rtc.hour() == 12 || rtc.hour() == 18) {
  gemessen = true;
  // hier Deine Messung und das Schreiben der Werte
}
if (gemessen && rtc.minute() != 0) gemessen = false;




Gruß Tommy

Edit: das delay mit der Messzeit muss natürlich raus.

Danke für den Code,
werde es mal austesten. Hoffe nur daß ich ihn an der richtigen Stelle einfüge.

Gruß Günther