Gleicher Code UNO / Nano

Hallo zusammen ich habe den Code auf dem Tisch mit einem Nano erstellt bis ich damit zufrieden war. Zum Simulieren gibt es ein Steckbrett. Beim Nano blinkt die OnBoardLED bei jedem beschreiben der SDkarte. Dann den Code auf den UNO übertragen die OnBoardLED bleibt dunkel.Dies wurde schon in einem weiteren Post erläutert.

Also wieder 2ten Pin für den Schreibvorgang eingebunden.Hier Pin (9) . Geht Led an Pin 9 blinkt .Per Zufall gesehen das die LED nicht blinkt.Wird nichts gespeichert.

Sketch auf den Nano geladen zusätzlich Pin 9 mit Led beschaltet,hier blinkt die OnBoardLED aber nicht die Led an Pin 9.

/*
  Code von my_xy_projekt Arduinoforum bearbeitet
  ===========================================================
  Heizungsüberwachung – Arduino UNO R3
  -----------------------------------------------------------
  Funktionen:
   - Messung Vorlauf/Rücklauf mit 3 x DS18B20 (OneWire-Bus)
   - Erfassung der Zustände:
         Brenner EIN/AUS / BZ
         Ventil Heizung
         Ventil Warmwasser
   - Logging auf SD-Karte (nur bei Zustandsänderung)
   - erweitert wenn Brenner Ein & BZ 
     loggen in sekundentakt  
   - Echtzeit über DS3231 RTC
   - Alarm-Ausgang bei Vorlauf > 75 °C (mit Hysterese)
   - zum Testen serielle Eingabe der Vorlauftemperatur 14.11.25
   - Zähler der Alarme im EEPROM
     Reset über Pin 5 
  -----------------------------------------------------------
  Hardware:
   - DS18B20 Data → Pin 2, Pullup 4,7kΩ nach 5V
   - IO PINS
   - Brenner
   - BZ
   - Ventil Warmwasser
   - Alarm-LED/Relais
       SD-Karte wie folgt an SPI-Bus angeschlossen:
       - MOSI - Pin 11 auf Arduino Uno/Nano/Duemilanove/Diecimila
       - MISO - Pin 12 auf Arduino Uno/Nano/Duemilanove/Diecimila
       - CLK  - Pin 13 auf Arduino Uno/Nano/Duemilanove/Diecimila
       - SD-CS -Pin 10
   - RTC DS3231 via I2C (A4 = SDA, A5 = SCL)
   - ON-Board-LED Fehlererkennung
  ===========================================================
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>
#include <EEPROM.h>
// ----------------------------------------------------------
// Pinbelegung angepasst 30-10-25
// ----------------------------------------------------------
constexpr uint8_t ONE_WIRE_BUS{ 2 };
constexpr uint8_t VENTIL_WW_PIN{ 4 };
constexpr uint8_t RESET_PIN{ 5 };  // zum reset des Alarmzählers beim starten nach Ground verdrahten
constexpr uint8_t BRENNER_PIN{ 6 };
constexpr uint8_t BZ_PIN{ 7 };

constexpr uint8_t ALARM_PIN{ 8 };
constexpr uint8_t SP_PIN{ 9 };  // nur bei Uno Anzeige speichern
constexpr uint8_t SD_CS_PIN{ 10 };

constexpr uint8_t EEPROM_ADDR{ 0 };  // Die Adresse im EEPROM, an der der Zähler gespeichert wird

// ----------------------------------------------------------
// Globale Objekte
// ----------------------------------------------------------
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RTC_DS3231 rtc;
File logfile;
DateTime now;

constexpr uint32_t _ONESECOND{ 1000 };
constexpr char heizungFile[]{ "heizung.csv" };
/* Für die Zählfunktion des Alarms */
// Globale oder statische Variablen, die ihren Zustand beibehalten müssen
static uint8_t zaehler = 0;
static int lastAlarmState = HIGH;  // Der vorherige Zustand des Pins

constexpr uint32_t intervalOk{ _ONESECOND };  // LED 1 Sekunde an
constexpr uint32_t intervalFail{ 200 };       // Blink-Intervall (200ms an, 200ms aus)
bool writeSuccess = false;                    // Flag, das den Erfolg des letzten Schreibvorgangs speichert

// Schwellwerte für Alarm
constexpr uint8_t ALARM_ON_TEMP{ 75 };   // Alarm EIN über 75°C
constexpr uint8_t ALARM_OFF_TEMP{ 68 };  // Alarm AUS unter 68°C
constexpr bool alarmOn{ LOW };           // Pinzustand wenn Relais EIN geschaltet
constexpr bool alarmOff{ !alarmOn };

bool brennerStatus;
bool ventilHzgStatus;
bool ventilWWStatus;

// Letzte bekannte Zustände
bool alarmState = alarmOff;
bool BZStatus;

float tempVorlauf;
float tempRueckl_HZG;
float tempRueckl_WW;
/* 14-11-2025  Werteeingabe zum testen 
  Temperaturwert Vorlauf manuell setzen 

*/
float temperaturWert = 0.0;
bool benutzeEingabeWert = false;
/*-------------------------------------*/

uint32_t lastCheckTime;  // Merker, wann das letzte Mal die sensoren abgefragt wurden
uint32_t lastBlinkTime;  // Merker, wann das letzte Mal blinkLed geschaltetn wurde

bool changed;

char speicher[10];
// ----------------------------------------------------------
// Adressen der Sensoren 3.11.25
// mit den Adressen könnte ich
//       tempVorlauf = sensors.getTempCByIndex(1);
// gegen tempVorlauf = sensors.getTempC(sensorVlauf); ersetzen
//
// DeviceAddress sensorHzg = { 0x28, 0x55, 0x37, 0xB4, 0x00, 0x00, 0x00, 0x91 };    // Adresse Sensor 1
// DeviceAddress sensorVlauf = { 0x28, 0x4B, 0xCA, 0xB2, 0x00, 0x00, 0x00, 0x9A };  // Adresse Sensor 2
// DeviceAddress sensorWw = { 0x28, 0xEF, 0xD3, 0xB1, 0x00, 0x00, 0x00, 0x1D };     // Adresse Sensor 3


// ----------------------------------------------------------
// Setup
// ----------------------------------------------------------
void setup() {
  Serial.begin(9600);
  delay(300);
  Serial.println(F("=== Heizungsüberwachung startet ==="));

  inputPinInit();


  // Ausgang konfigurieren (Alarm)
  pinMode(ALARM_PIN, OUTPUT);
  digitalWrite(ALARM_PIN, true);  // Anfangszustand: aus
  pinMode(SP_PIN, OUTPUT);
  digitalWrite(SP_PIN, false);  // Anfangszustand: aus

  // RTC starten
  if (!rtc.begin()) {
    Serial.println(F("RTC nicht gefunden!"));
    /* 31.10.25 */
  }
  /*
   * erweitert am 13.11.25 
   * auskommentieren wenn nicht erwünscht 
   */
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  lastCheckTime = millis();

  /* 14.11.25 Zähler der Alarme */
  // --- Logik zum Nullen beim Start ---
  // Prüfen des RESET_PIN
  if (digitalRead(RESET_PIN) == LOW) {
    // Wenn der Pin mit Ground verbunden ist (LOW), nullen wir den Zähler im EEPROM
    EEPROM.write(EEPROM_ADDR, 0);
    zaehler = 0;
    Serial.println(F("Zaehler wurde genullt (Reset-Pin war LOW)."));
  } else {
    // Andernfalls laden wir den letzten Wert aus dem EEPROM
    zaehler = EEPROM.read(EEPROM_ADDR);
    Serial.print(F("Zaehler aus EEPROM geladen: "));
    Serial.println(zaehler);
  }
  // OnBoardLED entsprechend des Zählerstandes blinken lassen
  for (uint8_t i = 0; i < zaehler; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
  }
  /* 15.11.25 
    delay eingefügt da der Fehler 
    "SD-Karte nicht initialisierbar oder nicht vorhanden."
    im Serialmonitor erschien.
  */
  delay(1000);

  sdCardInit();
}

// ----------------------------------------------------------
// Hauptschleife
// ----------------------------------------------------------
void loop() {
  now = rtc.now();

  if (millis() - lastCheckTime >= _ONESECOND) {
    lastCheckTime = millis();
    getSensorsData();
    getPinData();
    checkAlarm();
    digitalWrite(SP_PIN, false);  // nur UNO
    /*
      loggen wenn Brenner Ein 
      13.11.25 
    */
    if (digitalRead(BRENNER_PIN) == LOW && digitalRead(BZ_PIN) == LOW) {
      data2LogFile();
    }
    /*
      Temperatur manuell setzen  
      14.11.25 
    */
    temp();  // Temperaturwert Vorlauf manuell setzen
  }

  if (changed == true) {
    data2LogFile();
    changed = false;
  }
}
//
void checkAlarm() {
  // --------------------------------------------------------
  // Alarmsteuerung mit Hysterese
  // Erweitert um den zaehler 14.11.25
  // nach dem 4ten auslösen wird das Relais
  // nicht mehr automatisch zurückgesetzt
  // --------------------------------------------------------
  if (alarmState == alarmOff) {
    if (tempVorlauf > ALARM_ON_TEMP) {
      alarmState = alarmOn;
      strcpy(speicher, "Alarm");
    }
  } else {
    if (tempVorlauf < ALARM_OFF_TEMP && zaehler < 4) { alarmState = alarmOff; }
  }

  // Ausgang entsprechend setzen
  digitalWrite(ALARM_PIN, alarmState);
  zaehl();
}

//
void data2LogFile() {
  // --------------------------------------------------------
  // Loggen bei Änderung
  // --------------------------------------------------------
  char buf[200] = { '\0' };
  // sprintf kann ggfls. kein float. Darum vorher zusammenbauen
  char vlT[5] = { '\0' };
  dtostrf(tempVorlauf, 2, 1, vlT);
  char rlH[5] = { '\0' };
  dtostrf(tempRueckl_HZG, 2, 1, rlH);
  char rlW[5] = { '\0' };
  dtostrf(tempRueckl_WW, 2, 1, rlW);
  // CSV-Zeile zusammensetzen
  // ACHTUNG! die zweite Zeile gehört dazu!
  snprintf(buf, sizeof(buf), "%02d.%02d.%d,%02d:%02d:%02d,%s,%s,%s,%d,%d,%d,%d,%s,%d",
           now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(),
           vlT, rlH, rlW, ventilWWStatus, brennerStatus, BZStatus, alarmState == alarmOff ? 0 : 1, speicher, zaehler);
  // Auf SD-Karte schreiben
  writeSuccess = false;  // DEFAULT: Fehler beim Öffnen oder Schreiben
  logfile = SD.open(heizungFile, FILE_WRITE);

  if (logfile) {
    logfile.println(buf);
    writeSuccess = true;  // Schreibvorgang erfolgreich
    digitalWrite(SP_PIN, true);
  }

  logfile.close();
  // Ausgabe zur Kontrolle
  Serial.println(buf);
  strcpy(speicher, "     ");
}
//
void getPinData() {
  // --------------------------------------------------------
  // Digitale Eingänge lesen (bei Optokopplern evtl. invertiert)
  // --------------------------------------------------------
  if (!digitalRead(BRENNER_PIN) != brennerStatus) {
    brennerStatus = !brennerStatus;
    strcpy(speicher, "LÜ");
    changed = true;
  }

  if (!digitalRead(VENTIL_WW_PIN) != ventilWWStatus) {
    ventilWWStatus = !ventilWWStatus;
    strcpy(speicher, "WW");
    changed = true;
  }

  if (!digitalRead(BZ_PIN) != BZStatus) {
    BZStatus = !BZStatus;
    strcpy(speicher, "BZ");
    changed = true;
  }
}
//
void getSensorsData() {
  // --------------------------------------------------------
  // Temperaturen erfassen
  // --------------------------------------------------------
  tempVorlauf = sensors.getTempCByIndex(1);
  tempVorlauf = temperaturWert + tempVorlauf;  // temperaturWert zum Simulieren eingefügt
  tempRueckl_HZG = sensors.getTempCByIndex(0);
  tempRueckl_WW = sensors.getTempCByIndex(2);
  sensors.requestTemperatures();  // löst neuen Lese-Zyklus aus! Braucht je nach Auflösung bis zu 750ms
  // Serial.println(tempVorlauf);
}

void sdCardInit() {

  /* 31.10.2025 */
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println(F("SD-Karte nicht initialisierbar oder nicht vorhanden."));
    writeSuccess = false;  // Initialisierungsfehler
  } else {
    writeSuccess = true;
  }

  if (writeSuccess == true) {
    Serial.println(F("SD-Karte initialisiert."));
    // Logdatei vorbereiten
    logfile = SD.open(heizungFile, FILE_WRITE);
    Serial.print(F("System "));

    if (logfile) {
      logfile.println(F("Datum,Uhrzeit,Vorl [°C], HZG [°C], WW [°C] , WW , BR , BZ , Al , ,ALZä"));
      logfile.close();
    } else {
      writeSuccess = false;
      Serial.print(F("nicht "));
    }

    Serial.println(F("bereit"));
  }
}
//
void inputPinInit() {
  // Eingänge konfigurieren
  pinMode(BRENNER_PIN, INPUT_PULLUP);
  pinMode(RESET_PIN, INPUT_PULLUP);
  pinMode(VENTIL_WW_PIN, INPUT_PULLUP);
  pinMode(BZ_PIN, INPUT_PULLUP);
  getPinData();
  sensors.begin();
}
//
void temp() {
  // 1. Seriellen Monitor auf neue Eingaben pruefen
  if (Serial.available() > 0) {
    // Lesen des eingegebenen Float-Wertes
    float eingabe = Serial.parseFloat();

    // Prüfen, ob die Eingabe gültig war (parseFloat gibt 0.0 zurück, wenn keine gültige Zahl gefunden wurde)
    if (eingabe != 0.0 || (eingabe == 0.0 && Serial.peek() == '0')) {
      temperaturWert = eingabe;
      benutzeEingabeWert = true;
      Serial.print("Temperatur auf manuellen Wert gesetzt: ");
      Serial.println(temperaturWert);
    } else {
      Serial.println("Ungueltige Eingabe.");
    }
    // Puffer leeren, um alte Daten zu entfernen
    while (Serial.available() > 0) {
      Serial.read();
    }
  }
  // Serial.print(F(" Temperatur eingegeben : "));
  // Serial.println(temperaturWert);
}
//
void zaehl() {
  // Aktuellen Zustand des Pins lesen
  int currentAlarmState = digitalRead(ALARM_PIN);

  // Prüfen, ob eine fallende Flanke vorliegt:
  // War der Pin vorher HIGH UND ist jetzt LOW?
  if (currentAlarmState == LOW && lastAlarmState == HIGH) {
    zaehler++;
    changed = true;
    Serial.print(F("Flanke erkannt. Zaehler: "));
    Serial.println(zaehler);
    // Sofort nach dem Inkrementieren im EEPROM speichern
    EEPROM.write(EEPROM_ADDR, zaehler);
  }

  // Den aktuellen Zustand für den nächsten Durchlauf speichern
  lastAlarmState = currentAlarmState;
}

Bitte wo ist mein Fehler ?

Du hast in Deinem Code LED_BUILDIN „fest verdrahtet“.

for (uint8_t i = 0; i < zaehler; i++) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
  }

Du schaltetst SP_PIN nur ein wenn logfile true wird.

Die Onboard LED auf Pin 13 kann flackern, weil da auch der SCK Pin von SPI dran hängt.

In einem Sketch mit SPI Komponenten die Onboard LED auch für eine Statusanzeige verwenden zu wollen finde ich absurd.

Das passiert doch nur im Setupteil und ja die Led blinkt nach dem Zählerstand.
Aber am Nano blinkt eine Led an Pin 9 nicht !

/*
  Code von my_xy_projekt Arduinoforum bearbeitet
  ===========================================================
  Heizungsüberwachung – Arduino UNO R3
  -----------------------------------------------------------
  Funktionen:
   - Messung Vorlauf/Rücklauf mit 3 x DS18B20 (OneWire-Bus)
   - Erfassung der Zustände:
         Brenner EIN/AUS / BZ
         Ventil Heizung
         Ventil Warmwasser
   - Logging auf SD-Karte (nur bei Zustandsänderung)
   - erweitert wenn Brenner Ein & BZ
     loggen in sekundentakt
   - Echtzeit über DS3231 RTC
   - Alarm-Ausgang bei Vorlauf > 75 °C (mit Hysterese)
   - zum Testen serielle Eingabe der Vorlauftemperatur 14.11.25
   - Zähler der Alarme im EEPROM
     Reset über Pin 5
  -----------------------------------------------------------
  Hardware:
   - DS18B20 Data → Pin 2, Pullup 4,7kΩ nach 5V
   - IO PINS
   - Brenner
   - BZ
   - Ventil Warmwasser
   - Alarm-LED/Relais
       SD-Karte wie folgt an SPI-Bus angeschlossen:
       - MOSI - Pin 11 auf Arduino Uno/Nano/Duemilanove/Diecimila
       - MISO - Pin 12 auf Arduino Uno/Nano/Duemilanove/Diecimila
       - CLK  - Pin 13 auf Arduino Uno/Nano/Duemilanove/Diecimila
       - SD-CS -Pin 10
   - RTC DS3231 via I2C (A4 = SDA, A5 = SCL)
   - ON-Board-LED Fehlererkennung
  ===========================================================
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <RTClib.h>
#include <SPI.h>
#include <SD.h>
#include <EEPROM.h>
// ----------------------------------------------------------
// Pinbelegung angepasst 30-10-25
// ----------------------------------------------------------
constexpr uint8_t ONE_WIRE_BUS{ 2 };
constexpr uint8_t VENTIL_WW_PIN{ 4 };
constexpr uint8_t RESET_PIN{ 5 };  // zum reset des Alarmzählers beim starten nach Ground verdrahten
constexpr uint8_t BRENNER_PIN{ 6 };
constexpr uint8_t BZ_PIN{ 7 };

constexpr uint8_t ALARM_PIN{ 8 };
constexpr uint8_t SP_PIN{ 9 };  // nur bei Uno Anzeige speichern
constexpr uint8_t SD_CS_PIN{ 10 };

constexpr uint8_t EEPROM_ADDR{ 0 };  // Die Adresse im EEPROM, an der der Zähler gespeichert wird

// ----------------------------------------------------------
// Globale Objekte
// ----------------------------------------------------------
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
RTC_DS3231 rtc;
File logfile;
DateTime now;

constexpr uint32_t _ONESECOND{ 1000 };
constexpr char heizungFile[] { "heizung.csv" };
/* Für die Zählfunktion des Alarms */
// Globale oder statische Variablen, die ihren Zustand beibehalten müssen
static uint8_t zaehler = 0;
static int lastAlarmState = HIGH;  // Der vorherige Zustand des Pins

constexpr uint32_t intervalOk{ _ONESECOND };  // LED 1 Sekunde an
constexpr uint32_t intervalFail{ 200 };       // Blink-Intervall (200ms an, 200ms aus)
bool writeSuccess = false;                    // Flag, das den Erfolg des letzten Schreibvorgangs speichert

// Schwellwerte für Alarm
constexpr uint8_t ALARM_ON_TEMP{ 75 };   // Alarm EIN über 75°C
constexpr uint8_t ALARM_OFF_TEMP{ 68 };  // Alarm AUS unter 68°C
constexpr bool alarmOn{ LOW };           // Pinzustand wenn Relais EIN geschaltet
constexpr bool alarmOff{ !alarmOn };

bool brennerStatus;
bool ventilHzgStatus;
bool ventilWWStatus;

// Letzte bekannte Zustände
bool alarmState = alarmOff;
bool BZStatus;

float tempVorlauf;
float tempRueckl_HZG;
float tempRueckl_WW;
/* 14-11-2025  Werteeingabe zum testen
  Temperaturwert Vorlauf manuell setzen

*/
float temperaturWert = 0.0;
bool benutzeEingabeWert = false;
/*-------------------------------------*/

uint32_t lastCheckTime;  // Merker, wann das letzte Mal die sensoren abgefragt wurden
uint32_t lastBlinkTime;  // Merker, wann das letzte Mal blinkLed geschaltetn wurde

bool changed;

char speicher[10];
// ----------------------------------------------------------
// Adressen der Sensoren 3.11.25
// mit den Adressen könnte ich
// tempVorlauf = sensors.getTempCByIndex(1);
// gegen tempVorlauf = sensors.getTempC(sensorVlauf); ersetzen
//
// DeviceAddress sensorHzg = { 0x28, 0x55, 0x37, 0xB4, 0x00, 0x00, 0x00, 0x91 };    // Adresse Sensor 1
// DeviceAddress sensorVlauf = { 0x28, 0x4B, 0xCA, 0xB2, 0x00, 0x00, 0x00, 0x9A };  // Adresse Sensor 2
// DeviceAddress sensorWw = { 0x28, 0xEF, 0xD3, 0xB1, 0x00, 0x00, 0x00, 0x1D };     // Adresse Sensor 3

// ----------------------------------------------------------
// Setup
// ----------------------------------------------------------
void setup()
{
  Serial.begin(9600);
  delay(300);
  Serial.println(F("=== Heizungsüberwachung startet ==="));
  inputPinInit();
  // Ausgang konfigurieren (Alarm)
  pinMode(ALARM_PIN, OUTPUT);
  digitalWrite(ALARM_PIN, true);  // Anfangszustand: aus
  pinMode(SP_PIN, OUTPUT);
  digitalWrite(SP_PIN, false);  // Anfangszustand: aus

  // RTC starten
  if (!rtc.begin())
  {
    Serial.println(F("RTC nicht gefunden!"));
    /* 31.10.25 */
  }

  /*
     erweitert am 13.11.25
     auskommentieren wenn nicht erwünscht
  */
  if (rtc.lostPower())
  {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  lastCheckTime = millis();

  /* 14.11.25 Zähler der Alarme */
  // --- Logik zum Nullen beim Start ---
  // Prüfen des RESET_PIN
  if (digitalRead(RESET_PIN) == LOW)
  {
    // Wenn der Pin mit Ground verbunden ist (LOW), nullen wir den Zähler im EEPROM
    EEPROM.write(EEPROM_ADDR, 0);
    zaehler = 0;
    Serial.println(F("Zaehler wurde genullt (Reset-Pin war LOW)."));
  }
  else
  {
    // Andernfalls laden wir den letzten Wert aus dem EEPROM
    zaehler = EEPROM.read(EEPROM_ADDR);
    Serial.print(F("Zaehler aus EEPROM geladen: "));
    Serial.println(zaehler);
  }

  // OnBoardLED entsprechend des Zählerstandes blinken lassen
  for (uint8_t i = 0; i < zaehler; i++)
  {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
  }

  /* 15.11.25
    delay eingefügt da der Fehler
    "SD-Karte nicht initialisierbar oder nicht vorhanden."
    im Serialmonitor erschien.
  */
  delay(1000);
  sdCardInit();
}

// ----------------------------------------------------------
// Hauptschleife
// ----------------------------------------------------------
void loop()
{
  now = rtc.now();

  if (millis() - lastCheckTime >= _ONESECOND)
  {
    lastCheckTime = millis();
    getSensorsData();
    getPinData();
    checkAlarm();

    if (writeSuccess == true)
    { digitalWrite(SP_PIN, !digitalRead(SP_PIN)); } // toggelt
    else
    { digitalWrite(SP_PIN, false); }

    /*
      loggen wenn Brenner Ein
      13.11.25
    */
    if (digitalRead(BRENNER_PIN) == LOW && digitalRead(BZ_PIN) == LOW)
    {
      data2LogFile();
    }

    /*
      Temperatur manuell setzen
      14.11.25
    */
    temp();  // Temperaturwert Vorlauf manuell setzen
  }

  if (changed == true)
  {
    data2LogFile();
    changed = false;
  }
}
//
void checkAlarm()
{
  // --------------------------------------------------------
  // Alarmsteuerung mit Hysterese
  // Erweitert um den zaehler 14.11.25
  // nach dem 4ten auslösen wird das Relais
  // nicht mehr automatisch zurückgesetzt
  // --------------------------------------------------------
  if (alarmState == alarmOff)
  {
    if (tempVorlauf > ALARM_ON_TEMP)
    {
      alarmState = alarmOn;
      strcpy(speicher, "Alarm");
    }
  }
  else
  {
    if (tempVorlauf < ALARM_OFF_TEMP && zaehler < 4)
    {
      alarmState = alarmOff;
    }
  }

  // Ausgang entsprechend setzen
  digitalWrite(ALARM_PIN, alarmState);
  zaehl();
}

//
void data2LogFile()
{
  // --------------------------------------------------------
  // Loggen bei Änderung
  // --------------------------------------------------------
  char buf[200] = { '\0' };
  // sprintf kann ggfls. kein float. Darum vorher zusammenbauen
  char vlT[5] = { '\0' };
  dtostrf(tempVorlauf, 2, 1, vlT);
  char rlH[5] = { '\0' };
  dtostrf(tempRueckl_HZG, 2, 1, rlH);
  char rlW[5] = { '\0' };
  dtostrf(tempRueckl_WW, 2, 1, rlW);
  // CSV-Zeile zusammensetzen
  // ACHTUNG! die zweite Zeile gehört dazu!
  snprintf(buf, sizeof(buf), "%02d.%02d.%d,%02d:%02d:%02d,%s,%s,%s,%d,%d,%d,%d,%s,%d",
           now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(),
           vlT, rlH, rlW, ventilWWStatus, brennerStatus, BZStatus, alarmState == alarmOff ? 0 : 1, speicher, zaehler);
  // Auf SD-Karte schreiben
  writeSuccess = false;  // DEFAULT: Fehler beim Öffnen oder Schreiben
  logfile = SD.open(heizungFile, FILE_WRITE);

  if (logfile)
  {
    logfile.println(buf);
    writeSuccess = true;  // Schreibvorgang erfolgreich
  }

  logfile.close();
  // Ausgabe zur Kontrolle
  Serial.println(buf);
  strcpy(speicher, "     ");
}
//
void getPinData()
{
  // --------------------------------------------------------
  // Digitale Eingänge lesen (bei Optokopplern evtl. invertiert)
  // --------------------------------------------------------
  if (!digitalRead(BRENNER_PIN) != brennerStatus)
  {
    brennerStatus = !brennerStatus;
    strcpy(speicher, "LÜ");
    changed = true;
  }

  if (!digitalRead(VENTIL_WW_PIN) != ventilWWStatus)
  {
    ventilWWStatus = !ventilWWStatus;
    strcpy(speicher, "WW");
    changed = true;
  }

  if (!digitalRead(BZ_PIN) != BZStatus)
  {
    BZStatus = !BZStatus;
    strcpy(speicher, "BZ");
    changed = true;
  }
}
//
void getSensorsData()
{
  // --------------------------------------------------------
  // Temperaturen erfassen
  // --------------------------------------------------------
  tempVorlauf = sensors.getTempCByIndex(1);
  tempVorlauf = temperaturWert + tempVorlauf;  // temperaturWert zum Simulieren eingefügt
  tempRueckl_HZG = sensors.getTempCByIndex(0);
  tempRueckl_WW = sensors.getTempCByIndex(2);
  sensors.requestTemperatures();  // löst neuen Lese-Zyklus aus! Braucht je nach Auflösung bis zu 750ms
  // Serial.println(tempVorlauf);
}

void sdCardInit()
{
  /* 31.10.2025 */
  if (!SD.begin(SD_CS_PIN))
  {
    Serial.println(F("SD-Karte nicht initialisierbar oder nicht vorhanden."));
    writeSuccess = false;  // Initialisierungsfehler
  }
  else
  {
    writeSuccess = true;
  }

  if (writeSuccess == true)
  {
    Serial.println(F("SD-Karte initialisiert."));
    // Logdatei vorbereiten
    logfile = SD.open(heizungFile, FILE_WRITE);
    Serial.print(F("System "));

    if (logfile)
    {
      logfile.println(F("Datum,Uhrzeit,Vorl [°C], HZG [°C], WW [°C] , WW , BR , BZ , Al , ,ALZä"));
      logfile.close();
    }
    else
    {
      writeSuccess = false;
      Serial.print(F("nicht "));
    }

    Serial.println(F("bereit"));
  }
}
//
void inputPinInit()
{
  // Eingänge konfigurieren
  pinMode(BRENNER_PIN, INPUT_PULLUP);
  pinMode(RESET_PIN, INPUT_PULLUP);
  pinMode(VENTIL_WW_PIN, INPUT_PULLUP);
  pinMode(BZ_PIN, INPUT_PULLUP);
  getPinData();
  sensors.begin();
}
//
void temp()
{
  // 1. Seriellen Monitor auf neue Eingaben pruefen
  if (Serial.available() > 0)
  {
    // Lesen des eingegebenen Float-Wertes
    float eingabe = Serial.parseFloat();

    // Prüfen, ob die Eingabe gültig war (parseFloat gibt 0.0 zurück, wenn keine gültige Zahl gefunden wurde)
    if (eingabe != 0.0 || (eingabe == 0.0 && Serial.peek() == '0'))
    {
      temperaturWert = eingabe;
      benutzeEingabeWert = true;
      Serial.print("Temperatur auf manuellen Wert gesetzt: ");
      Serial.println(temperaturWert);
    }
    else
    {
      Serial.println("Ungueltige Eingabe.");
    }

    // Puffer leeren, um alte Daten zu entfernen
    while (Serial.available() > 0)
    {
      Serial.read();
    }
  }

  // Serial.print(F(" Temperatur eingegeben : "));
  // Serial.println(temperaturWert);
}
//
void zaehl()
{
  // Aktuellen Zustand des Pins lesen
  int currentAlarmState = digitalRead(ALARM_PIN);

  // Prüfen, ob eine fallende Flanke vorliegt:
  // War der Pin vorher HIGH UND ist jetzt LOW?
  if (currentAlarmState == LOW && lastAlarmState == HIGH)
  {
    zaehler++;
    changed = true;
    Serial.print(F("Flanke erkannt. Zaehler: "));
    Serial.println(zaehler);
    // Sofort nach dem Inkrementieren im EEPROM speichern
    EEPROM.write(EEPROM_ADDR, zaehler);
  }

  // Den aktuellen Zustand für den nächsten Durchlauf speichern
  lastAlarmState = currentAlarmState;
}

Nur als Idee.

Sowas testet man mit einem Minimal Programm.
Und einem Multimeter, oder Oszi.
Dann weiß man ob es die Software oder die Hardware ist.

Vieleicht LED falsch herum angeschlossen oder das PinMode vergessen?
Grüße Uwe

Neuer Code von my_xy_project


nach dem ersten laden blinkte die Led an pin 9
Reset erfolglos Spannungsversorgung entfernt ohne Erfolg.
Nochmal geladen

Soll ich mal das Blinken der OnBoardLed über den Zählerstand rausnehmen ??
Wäre so eine Idee.

Im Serialmonitor werden Werte im Sekundentakt aktualiesiert.

Ich würde eher meinen, dass irgendwas mit der Verdrahtung der SD-Karte nicht passt.

Alternativ setze das blinken von Anfang auf den PIN 9:

  // OnBoardLED entsprechend des Zählerstandes blinken lassen
  for (uint8_t i = 0; i < zaehler; i++)
  {
    digitalWrite(SD_PIN, HIGH);
    delay(1000);
    digitalWrite(SD_PIN, LOW);
    delay(1000);
  }

@my_xy_projekt
Was meiner Meinung nach gegen defekte Hardware spricht ist das der UNO und auch der Nano mit dem Code nicht funktionieren.

Es spricht keiner von def. HW sondern von falscher Verdrahtung: SD Karte nicht gefunden

1 Like

Ich habe bereits mit der bestehender Verdrahtung auf die SDkarten geschrieben.
Werde jetzt nochmal einen sketch aus den Beispielen versuchen.

Der Beispiel Datenlogger schreibt auf die Karte,ohne Karte kommt die Fehlermeldung ? Muss ich den Testcode auch hier zeigen ? Es ist der Beispielcode
der IDE.

Ersetze mal bitte das setup()

void setup()
{
  Serial.begin(9600);
  delay(500);
  Serial.println(F("=== Heizungsüberwachung startet ==="));
  sdCardInit();
  inputPinInit();
  // Ausgang konfigurieren (Alarm)
  pinMode(ALARM_PIN, OUTPUT);
  digitalWrite(ALARM_PIN, true);  // Anfangszustand: aus
  pinMode(SP_PIN, OUTPUT);
  digitalWrite(SP_PIN, false);  // Anfangszustand: aus

  // RTC starten
  if (!rtc.begin())
  {
    Serial.println(F("RTC nicht gefunden!"));
    /* 31.10.25 */
  }

  /*
     erweitert am 13.11.25
     auskommentieren wenn nicht erwünscht
  */
  if (rtc.lostPower())
  {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  lastCheckTime = millis();

  /* 14.11.25 Zähler der Alarme */
  // --- Logik zum Nullen beim Start ---
  // Prüfen des RESET_PIN
  if (digitalRead(RESET_PIN) == LOW)
  {
    // Wenn der Pin mit Ground verbunden ist (LOW), nullen wir den Zähler im EEPROM
    EEPROM.write(EEPROM_ADDR, 0);
    zaehler = 0;
    Serial.println(F("Zaehler wurde genullt (Reset-Pin war LOW)."));
  }
  else
  {
    // Andernfalls laden wir den letzten Wert aus dem EEPROM
    zaehler = EEPROM.read(EEPROM_ADDR);
    Serial.print(F("Zaehler aus EEPROM geladen: "));
    Serial.println(zaehler);
  }

  // OnBoardLED entsprechend des Zählerstandes blinken lassen
  for (uint8_t i = 0; i < zaehler; i++)
  {
    digitalWrite(SD_PIN, HIGH);
    delay(1000);
    digitalWrite(SD_PIN, LOW);
    delay(1000);
  }

}

Kompiliert nicht
Sollte dort nicht SP_PIN stehen ?

[quote="my_xy_projekt, post:14, topic:1414771"]

// OnBoardLED entsprechend des Zählerstandes blinken lassen
  for (uint8_t i = 0; i < zaehler; i++)
  {
    digitalWrite(SD_PIN, HIGH);
    delay(1000);
    digitalWrite(SD_PIN, LOW);

Was ich auch noch gefunden habe !
digitalRead() am Output-Pin funktioniert nicht immer zuverlässig, je nach Mikrocontroller.
Sicherer ist es, den Zustand selbst zu speichern:

bool spState = LOW; // global oder static in der Funktion

if (writeSuccess) {
spState = !spState; // toggle
} else {
spState = LOW; // reset
}

digitalWrite(SP_PIN, spState);

Ja

Das bezweifle ich. Zumindest für den Fall, dass kein Defekt vorliegt. Im übrigen sind beim Nano und Uno R3 die Controller identisch, es handelt sich lediglich um zwei verschiedene Board-Layouts.

Die Geschichte mit digitalRead () am Output stand auch im www. finde es aber nicht wieder.
Der Code von my_xy_projekt läuft ja,bricht aber immer wieder ab dann blinkt die LED nicht mehr.Die OnBoardLed blinkt im Sekundentakt ( SPI geschuldet ) glaub ich.Auf der SDkarte sind dann aber keine neuen Werte gespeichert.

Danke.

@walter_meister
Wenn ich das auf dem mickrigen Handydisplay tippe, passiert sowas schon mal. sorry.

Wenn die LED onBoard leuchtet, ist das clock-Signal aktiv.
Wenn die LED an PIN 9 nicht mehr leuchtet, ist das schreiben auf, bzw. öffnen der Karte schief gegangen.

Alles gut langsam freunde ich mich mit dem Arduino an .Dann fällt mir das auf.
Dein Code funktioniert ja grundsätzlich.Sollte ich SD open SD close suchen oder nicht so oft speichern?