/*
Forum: https://forum.arduino.cc/t/datenlogger-mit-sd-karte-messwerte-fehlen-teilweise/1427809
Wokwi: https://wokwi.com/projects/454665695292654593
Original siehe Forum, Post 1
Angepasst durch "Invertieren" der Kommentare sowie des #includes der genutzten Lib, siehe unten
im Sketch
Ausserdem bereinigt:
Fehlerhafte Deklaration interval
Mangelhafte Deklaration timer und interval als long bzw. int
Die Lib stammt von https://github.com/cvmanjoo/RTC/tree/master
Die Entwicklung scheint noch nicht abgeschlossen zu sein (diverse auskommentierte Code-Anteile,
Kommentarklammern ohne Text dazwischen, beim #include guard fehlt das #define RTC_H in I2C_RTC.h).
Der mangelhafte include guard wurde durch '#pragma once' ersetzt
Anstelle des DS3231 wird eine RTC DS1307 verwendet, die die erforderlichen Daten liefert.
2026/01/31
ec2021
*/
/*
Damit die Zeit beim RTC aktuell ist, muss bei der Inbetriebnahme
und beim Verlust der Speisung zuerst das Programm: RTC_SetAutoTime auf den Arduino geladen werden
und danach muss dieses Programm nochmals auf den Arduino geladen werden!
AnalogInput 30V anhand Spannungsteiler = 5V am Eingang, 1 Volt = 34.1
SD Karte Fat32
*/
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "I2C_RTC.h" // Von < > auf " " geändert, da das Headerfile hier im Sketch-Verzeichnis liegt
// Im IC2_RTC.h wurde alle von DS3231 abweichenden Klassen auskommentiert, um hier
// nur DS3231.cpp hinterlegen zu müssen: in DS3231.cpp bei #include ebenfalls
// auf "I2C_RTC.h" angepasst
const int chipSelect = 10; //Pin SD-Karte Freischalten
// interval als integer zu deklarieren UND einen float-Wert zuzuweisen ist sträflich ...
// interval gleich als unsigned long in [ms] definieren und als constexpr, da es sich nicht ändert!
// int interval = 0.005; //Interval Daten loggen alle 5 milli Sekunden
constexpr unsigned long interval {5}; //Interval Daten loggen alle 5 milli Sekunden
int analogValue1 = A0; // Input 1 Spannung 0 to 5V R1=100kOhm, R2=20kOhm, U ges 30V
int analogValue2 = A1; // Input 2 Spannung 0 to 5V R1=100kOhm, R2=20kOhm, U ges 30V
int analogValue3 = A2; // Input 1 Spannung 0 to 5V R1=100kOhm, R2=20kOhm, U ges 30V
int analogValue4 = A3; // Input 2 Spannung 0 to 5V R1=100kOhm, R2=20kOhm, U ges 30V
// timer sollte unsigned long sein!
//long timer;
unsigned long timer;
String timestring;
String mvalue;
static DS3231 RTC;
float V1; //Messwert Analogeingang 0
float V2; //Messwert Analogeingang 1
float V3; //Messwert Analogeingang 2
float V4; //Messwert Analogeingang 3
//Konstanten zur Umrechnung
// Spannungsteiler: R1 = 100kΩ, R2 = 20kΩ
// Umrechnung: Eingang max. 30V -> Ausgang max. 5V
const float Vref = 5.0; // Referenzspannung ADC Uno
const int ADCmax = 1023; // 10-bit ADC
const float R1 = 100000.0; // Ohm
const float R2 = 20000.0; // Ohm
void setup() {
//Initialisierung SD Karte und Serieller Schnittstelle zur Fehlersuche
pinMode(analogValue1, INPUT);
pinMode(analogValue2, INPUT);
pinMode(analogValue3, INPUT);
pinMode(analogValue4, INPUT);
// Wenn mehr als 960 Zeichen/s übertragen werden sollen,
// muss dies
// Serial.begin(9600);
// hochgesetzt werden 115200 ist für heutige Rechner keine Herausforderung
Serial.begin(115200);
delay(3000);
Serial.println("Initializing SD card...");//Rückmeldung Verbindung SD-Karte mit Arduino
if (!SD.begin(chipSelect)) {
Serial.println("SD Card error");
return;//Ende Rückmeldung Verbindung SD-Karte mit Arduino
}
Serial.println("card initialized");//Rückmeldung Verbindung RTC mit Arduino
if (! RTC.begin()) {
Serial.println("No RTC found");
} else {
Serial.println("RTC clock found");
}
if (! RTC.isRunning()) {
Serial.println("RTC is not configured");
}//Ende Rückmeldung Verbindung SD-Karte mit Arduino
}
void loop() {
//Für alle vier Analogeingänge
// ACHTUNG:
// Mit int interval = 0.0005 wird interval zu Null!
// Der u.a. Vergleich ist nicht "überlaufsicher" (nach ca. 50 Tagen)
/*************************************************
if ((timer + interval * 1000) < millis()) {
**************************************************/
// Korrekt sieht das Ganze mit constexpr unsigned long interval {5} so aus:
if (millis() - timer > interval ) {
timer = millis();
get_logvalue(); //Funktion Messwert holen
get_time(); //Funktion Zeit holen von RTC
write_data(); //Funktion Zeit und Messwert auf SD-Karte schreiben
}
}
void get_logvalue() {
//Messwerte einlesen
int val1 = analogRead(analogValue1); //Speichervariable int val1
int val2 = analogRead(analogValue2); //Speichervariable int val2
int val3 = analogRead(analogValue3); //Speichervariable int val3
int val4 = analogRead(analogValue4); //Speichervariable int val4
//Umrechnung
V1 = ((val1 * Vref) / ADCmax) * (R1 + R2) / R2;
V2 = ((val2 * Vref) / ADCmax) * (R1 + R2) / R2;
V3 = ((val3 * Vref) / ADCmax) * (R1 + R2) / R2;
V4 = ((val4 * Vref) / ADCmax) * (R1 + R2) / R2;
}
void get_time() { //Read Time from RTC
//Zeit holen
timestring = RTC.getWeekString().substring(0, 3);
timestring += "-";
timestring = RTC.getDateString();
timestring += "-";
timestring = RTC.getTimeString();
//Zeit an serielle Schnittstelle melden zur Fehlersuche
Serial.print(RTC.getWeekString().substring(0, 3));
Serial.print(" ");
Serial.print(RTC.getDateString());
Serial.print(" ");
Serial.print(RTC.getTimeString());
Serial.println();
}
void write_data() { //Daten zusammensetzen und auf SD-Karte schreiben
// CSV Format: Zeit, V1, V2, V3, V4
String dataString = timestring + "," + String(V1, 2) + "," + String(V2, 2) + "," + String(V3, 2) + "," + String(V4, 2);
//V1 steht für den umgerechneten Wert von Analogeingang 0, V2->A1, ...
File dataFile = SD.open("datalog.csv", FILE_WRITE);
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
Serial.println(dataString);
}
else {
Serial.println("error writing datalog.txt");
}
}
/*
!!!!!!!!!ACHTUNG AB HIER IST DAS ZUSATZPROGRAMM RTC_SetAutoTime!!!!!!!!!!!!!!!/* ------------------------------------------------------------
"THE BEERWARE LICENSE" (Revision 42):
<[email protected]> wrote this code. As long as you retain this
notice, you can do whatever you want with this stuff. If we
meet someday, and you think this stuff is worth it, you can
buy me a beer in return.
------------------------------------------------------------
Auto_setTime.ino
Created by Manjunath CV.
Released into the public domain.
----------------------------------------------------------*/
/*
#include <Wire.h>
#include <I2C_RTC.h>
static DS3231 RTC;
//Format
int hours,minutes,seconds,day,month,year;
void setup()
{ //Initialisierung der seriellen Schnittstelle zur Fehlersuche
Serial.begin(115200);
while (!Serial);
RTC.begin();
//Rückmeldung RTC mit Arduino verbunden
if(RTC.isConnected() == false)
{
Serial.println("RTC Not Connected!");
while(true);
}
//Rückmeldung Uhr funktioniert
Serial.print("Is Clock Running: ");
if(RTC.isRunning())
{
Serial.println("Yes");
while(true)
{
switch (RTC.getWeek()) //Auswahl Tag
{
case 1: Serial.print("SUN");
break;
case 2: Serial.print("MON");
break;
case 3: Serial.print("TUE");
break;
case 4: Serial.print("WED");
break;
case 5: Serial.print("THU");
break;
case 6: Serial.print("FRI");
break;
case 7: Serial.print("SAT");
break;
}
Serial.print(" ");
//Funktionen zur Erfassung von Tag, Monat, Jahr
day=RTC.getDay();
month=RTC.getMonth();
year=RTC.getYear();
//Auswahl Tag
if(day<10)
Serial.print("0");
Serial.print(RTC.getDay());
Serial.print("-");
//Auswahl Monat if(month<10)
Serial.print("0");
Serial.print(RTC.getMonth());
Serial.print("-");
Serial.print(RTC.getYear());
Serial.print(" ");
//Funktion zur Erfasung von Stunden, Minuten, Sekunden
hours = RTC.getHours();
minutes = RTC.getMinutes();
seconds = RTC.getSeconds();
if(hours<10)
Serial.print("0");
Serial.print(hours);
Serial.print(":");
if(minutes<10)
Serial.print("0");
Serial.print(minutes);
Serial.print(":");
if(seconds<10)
Serial.print("0");
Serial.print(seconds);
Serial.print(""); //Einstellung 12 oder 24 Stunden schreibweise
if (RTC.getHourMode() == CLOCK_H12)
{
switch (RTC.getMeridiem())
{
case HOUR_AM:
Serial.print(" AM");
break;
case HOUR_PM:
Serial.print(" PM");
break;
}
}
Serial.println();
delay(1000);
}
}
else
{
delay(250);
Serial.println("No");
Serial.println("Setting Time");
//RTC.setHourMode(CLOCK_H12); //Comment if RTC PCF8563
RTC.setHourMode(CLOCK_H24);
RTC.setDateTime(__TIMESTAMP__);
Serial.println(__TIMESTAMP__);
//RTC.setDateTime("Fri Mar 08 00:01:53 2024");
// RTC.setDateTime(__DATE__, __TIME__);
// Serial.print(__DATE__);
// Serial.print(" ");
// Serial.println(__TIME__);
// RTC.setDateTime("Dec 26 2009", "00:34:56");
Serial.println("New Time Set, Reset Manually ");
RTC.startClock(); //Start the Clock;
Serial.println();
}
}
//RTC ist betriebsbereit
void loop()
{
}
*/