Alarm Mode DS3231- RTClib

Hallo,

vlt. kennt sich jemand besser mit der RTClib bzw. dem DS3231 aus.

Ich würde gerne die Alarm Parameter Ds3231Alarm1Mode alarm_mode
wie z.B.: DS3231_A1_Second oder DS3231_A1_Minutes, in einer Variable oder etwas was ich im vorhinein definieren kann speichern.
Warum das ganze: um eine Variable am Beginn des Programmcodes zu haben, wo ich den Alarm Mode einstellen kann und nicht immer im Code rumsuchen muss, wo die richtige Zeile ist.

Hätte da jemand eine Idee?

Hab da was mit enum gelesen. bin aber nicht sicher ob das hilft.

Hier der Link zur Libary: https://github.com/adafruit/RTClib
Es geht genau gesagt um das hier in RTC_DS3231.cpp: https://github.com/adafruit/RTClib/blob/master/src/RTC_DS3231.cpp
Zeile:

bool RTC_DS3231::setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode)

Danke schon mal für die Hilfe und Antworten!

Noch einen schönen Abend!

Mfg

Hier noch ein Versuch der nicht funktioniert angehängt, da String alarm_param von rtc.setAlarm nicht genommen wird.

#include <RTClib.h>
// #include <Wire.h>
int timespan_day = 0;
int timespan_hour = 0;
int timespan_min = 0;
int timespan_sec = 10;
String alarm_param = "DS3231_A1_Second";

RTC_DS3231 rtc;

// the pin that is connected to SQW
#define CLOCK_INTERRUPT_PIN 33
const int sampleWindow = 1000; // Sample window width in mS (50 mS = 20Hz)

void setup() {
  Serial.begin(9600);
  delay(500);
  pinMode(27, OUTPUT);

  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 0); //1 = High, 0 = Low //Pin 33
  //esp_sleep_enable_ext1_wakeup(0x400000000, ESP_EXT1_WAKEUP_ALL_LOW); //Pin 34

  // initializing the rtc
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC!");
    Serial.flush();
    abort();
  }

  if (rtc.lostPower()) {
    // this will adjust to the date and time at compilation
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  //we don't need the 32K Pin, so disable it
  rtc.disable32K();

  // Making it so, that the alarm will trigger an interrupt
  pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING);

  // set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far)
  // if not done, this easily leads to problems, as both register aren't reset on reboot/recompile
  rtc.clearAlarm(1);
  rtc.clearAlarm(2);

  // stop oscillating signals at SQW Pin
  // otherwise setAlarm1 will fail
  rtc.writeSqwPinMode(DS3231_OFF);

  // turn off alarm 2 (in case it isn't off already)
  // again, this isn't done at reboot, so a previously set alarm could easily go overlooked
  rtc.disableAlarm(2);

  // schedule an alarm 10 seconds in the future
  if (!rtc.setAlarm1(
        rtc.now() + TimeSpan(timespan_day, timespan_hour, timespan_min, timespan_sec), alarm_param // this mode triggers the alarm when the seconds match. See Doxygen for other options
      )) {
    Serial.println("Error, alarm wasn't set!");
  } else {
    Serial.println("Alarm will happen in 10 seconds!");
  }
}

void loop() {
  unsigned long startMillis = millis(); // Start of sample window
  while (millis() - startMillis < sampleWindow)
  {
    // print current time
    char date[10] = "hh:mm:ss";
    rtc.now().toString(date);
    Serial.print(date);
    // the value at SQW-Pin (because of pullup 1 means no alarm)
    Serial.print(" SQW: ");
    Serial.print(digitalRead(CLOCK_INTERRUPT_PIN));
    // whether a alarm happened happened
    Serial.print(" Alarm1: ");
    Serial.print(rtc.alarmFired(1));
    // Serial.print(" Alarm2: ");
    // Serial.println(rtc.alarmFired(2));
    // control register values (see https://datasheets.maximintegrated.com/en/ds/DS3231.pdf page 13)
    // Serial.print(" Control: 0b");
    // Serial.println(read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), BIN);

    // resetting SQW and alarm 1 flag
    // using setAlarm1, the next alarm could now be configurated

    digitalWrite(27, HIGH);
  }
  if (rtc.alarmFired(1)) {
    rtc.clearAlarm(1);
    Serial.println("Alarm cleared");
  }

  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
}

void onAlarm() {
  Serial.println("Alarm occured!");
}

/*static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
    Wire.beginTransmission(addr);
    Wire.write((byte)reg);
    Wire.endTransmission();

    Wire.requestFrom(addr, (byte)1);
    return Wire.read();
  }*/

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Wenn Du nichts schreibst, gehe ich erstmal von einem UNO aus, was bei Dir aber nicht zutrifft. Welche Hardware nutzt Du?

Sonst bist Du schon nahe dran, siehe RTClib.h:

/** DS3231 Alarm modes for alarm 1 */
enum Ds3231Alarm1Mode {
  DS3231_A1_PerSecond = 0x0F, /**< Alarm once per second */
  DS3231_A1_Second = 0x0E,    /**< Alarm when seconds match */
  DS3231_A1_Minute = 0x0C,    /**< Alarm when minutes and seconds match */
  DS3231_A1_Hour = 0x08,      /**< Alarm when hours, minutes
                                   and seconds match */
  DS3231_A1_Date = 0x00,      /**< Alarm when date (day of month), hours,
                                   minutes and seconds match */
  DS3231_A1_Day = 0x10        /**< Alarm when day (day of week), hours,
                                   minutes and seconds match */
}; 

Da wird aber nicht ein String-Objekt verwendet, sondern der Typ Ds3231Alarm1Mode kreiert. Daher solltest Du den auch verwenden:

Ds3231Alarm1Mode alarm_param = DS3231_A1_Second;

Ich habe es nicht getestet, probier's mal aus :slightly_smiling_face:

Hallo,

warum die RTC Lib enums für Variablen Zweckentfremden ist mir nicht ganz klar, im Grunde reicht ein struct für die Alarm Variablen im Sketch und ein struct für die Adressen der DS3231 bzw. eine Konstantenliste. Am Ende eine Funktion die die Alarm Daten in die DS3231 schreibt. Wenn die Adressen als enums in der Lib nun schon vorliegen kannste dir natürlich auch verwenden.

Edit:
Zur Korrektur. Die enums sind keine Adressen sondern Bitmasken.

Hallo,

Danke für die Antwort!
Verwende einen ESP32.

Aber du hast mir die Lösung ja schon gesagt.

Nochmals danke für die Hilfe!!!

Schönen Tag noch

Mfg

Hallo,
auch dir danke für deine Antwort!
Hatte das so noch nie gesehen, bin aber auch noch am Anfang mit MC Programmierung.

Mfg

Ebenso!

Hallo nochmal,

vlt hast du ja lust und zeit mir die Frage zu beantworten falls du dich auskennst:

Gibt es einen weg den ESP32 alle 15min auzuwecken?
Mit der RTClib bekomme ich das nicht hin, da es keinen befhel dafür gint.
Vlt. bin ich aber nur zu blöd und benötige etwas hilfe oder tipps-

Danke

Mfg

Mir fallen zwei Wege ein:

  1. DS3231 weckt per Interrupt den ESP32 auf.
  2. Der ESP32 weckt sich selbst auf mit esp_sleep_enable_timer_wakeup(time_in_us), siehe ESP32 Deep Sleep with Arduino IDE and Wake Up Sources und ESP32 Timer Wake Up from Deep Sleep

Den weg mit dem RTC habe ich versucht aber bekomme die 15min nicht hin, da die Ds3231Alarm1Mode das nicht hergeben.

den Link sehe ich mir an, danke

Mfg

Hallo,

nur als Gedanke mit der RTC. Wenn es direkt nicht geht, geht es indirekt um die Ecke. Nach jedem Alarm wird die Weckzeit um 15min weiter gestellt. Wenn die ESP eigene Uhr ausreichend genau ist wäre diese Lösung einfacher.

Danke für den Tipp, leider verstehe ich nicht genau was du damit meinst?
Mein Problem ist, das mit der RTClib bzw. dem DS3231 nur zB. den befehl DS3231_A1_Minute gibt, welcher ein Signal sendet, wenn die Minuten und Sekunden übereinstimmen.
Ich kann zwar immer 15min dazu geben aber dann habe ich ein Problem wenn eine Stunde überschritten wird.

Oder verstehe ich etwas falsch?

Danke

Mfg

Hey, habs jetzt mit dem direkten Befhel mit der RTC vom ESP32 versucht.
Hab da aber bedenken, da es anscheinend oft zu Problemen mit der intenen RTC des ESP32 kommt.

Hast du noch einen Tipp?

Mfg

Verstehst Du richtig!

Zur Zeitberechnung kannst Du die Unixtime oder etwas Vergleichbares verwenden.

RTClib enthält aber auch Rechenoperationen für Zeiten, siehe Beispiel datecalc.ino.

14 Min und 59 Sekunden schlafen legen, dann kannst Du eine Minute lang sekündlich DS3231 abfragen.

Was willst Du mit Sleep erreichen? Hast Du WLAN in der Nähe?

Meine ESP32 holen sich die genaue Zeit bei meiner Fritz!Box als NTP-Server.

Grundsätzlich geht es um einen Datenlogger der alle 15min von Sensoren Daten aufnimmt und auf eine SD Speichert, da kein WLan in der nähe ist.
Und wie man sieht, stecke ich beim deep sleep vom esp32 für die 15min.

mfg

Noch eine Frage, im Internet liest man das man für den deep sleep den Pin16 mir GND verbinden muss, warum?

Und wenn der deep sleep ausgeführt wird, wird danach nochmal das setup ausgeführt, nicht oder?

mfg

Hallo,

nach dem Wecken nach dem Sleep macht das Programm an der Stelle weiter wo es in sleep ging. Wie der Controller aufgeweckt wird ist erstmal egal. Wenn von einem Pin die Rede ist, sagt mir er wird extern geweckt. Damit der Pin ein klares Ruhesignal hat wird er über Pullup/Pulldown auf ein Potential gelegt. In deinem Gelesenen vermutlich mit internen Pullup am Pin 16.
Link zu Gelesenen?
setup() wird nur nach einem Reset ausgeführt.

lies noch mal.
Da soll stehen dass du am ESP8266 Pin16 mit Reset verbinden sollst.

der ESP8266 Deepsleep macht einen Impuls am Pin16, durch irgend einen Fehler *) im System des ESP8266 funktioniert das aufwecken aber nicht ganz, daher ist die Verbindung GPIO16-RST eine Notlösung um den ESP8266 wieder starten zu können. Daher kommt es wegen dieser Verbindung nach dem Deepsleep zu einem Reset des ESP8266 und setup() wird neu ausgeführt.

Am ESP32 braucht es diesen "Hack" nicht.

Hallo,

interessant. So weit hell sehen konnte ich nicht.

Hallo,

danke für die Antwort.

Du hast vollkommen recht!
Ich habe nicht genau genug gegoogelt bzw. bin davon ausgegangen das am ESP32 es gleich wie am ESP8266 ist.

Danke nochmals für die Aufklärung und beeindruckend dass du sowas sofort gewusst hast und meinen Fehler erahnen konntest!

Eine andere Frage noch, mein DS3231 verhält sich etwas seltsam.
Kurze Erklärung:
Mit dem deep sleep schalte ich auch ein Relais um die Sensoren auszuschalten, dabei wird auch der DS3231 von der Versorgung genommen.

Nun hat dieser ja eine Batterie und sollte ja weiterlaufen und wenn der ESP32 aus dem deep sleep zurück kommt, sollte die angeforderte Zeit vom DS3231 ja der wirklichen Zeit entsprechen oder?

Komisch ist aber, das wenn ich die Zeit beim DS3231 einstelle mittels

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

und dann mein Programm laufen lasse und nach dem deep sleep die zeit wieder abfrage, ist dort wieder die Zeit von zuvor drin, wobei ich im loop aber eine schleife durchlaufe die mir auch die Zeit hochzählt aber nach dem deep sleep ist die Zeit wieder beim der vorherigen Anfangszeit vom loop..

Hoffe verständlich?

Hier sonst mein code vlt könnte mir jemand helfen.


#include <RTClib.h>
// #include <Wire.h>
#define uS_TO_S_FACTOR 1000000
int Meas_Time = 10000; // Time how long parameter from sensor will be measured -> 60000 = 1min
int TIME_TO_SLEEP = 10; // Sleep time in s

char Date[13];
char Time[13];
RTC_DS3231 rtc;

void setup() {
  Serial.begin(9600);
  delay(500);
  pinMode(27, OUTPUT);
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC!");
  }
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}

void loop() {
  unsigned long startMillis = millis(); // Start of sample window
  while (millis() - startMillis < Meas_Time)
  {
    digitalWrite(27, HIGH);
    delay(1);
    DateTime now = rtc.now();
    snprintf(Date, sizeof(Date), "%02d%02d%02d.log", now.year(), now.month(), now.day()); // ein 8.3 Name wie z.B.  "06032345.log"
    snprintf(Time, sizeof(Time), "%02d%02d%02d.log", now.hour(), now.minute(), now.second()); // ein 8.3 Name wie z.B.  "06032345.log"
    //Serial.println(Date);
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    Serial.println(Time);
    delay(1000);
  }
  digitalWrite(27, LOW);
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
}


/*static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
    Wire.beginTransmission(addr);
    Wire.write((byte)reg);
    Wire.endTransmission();

    Wire.requestFrom(addr, (byte)1);
    return Wire.read();
  }*/

Danke

Mfg

Edit:

Hier meine Ausgabe am Serial monitor:

23:45:5
234505.log
23:45:6
234506.log
23:45:7
234507.log
23:45:8
234508.log
23:45:9
234509.log
23:45:10
234510.log
23:45:11
234511.log
23:45:12
234512.log
23:45:13
234513.log
23:45:14
234514.log
Going to sleep now
81⸮⸮⸮⸮gJ⸮JaJʄ⸮⸮⸮1⸮⸮)!)⸮23:45:5
234505.log
23:45:6
234506.log
23:45:7
234507.log
23:45:8
234508.log
23:45:9
234509.log
23:45:10
234510.log
23:45:11
234511.log
23:45:12
234512.log
23:45:13
234513.log
23:45:14
234514.log
Going to sleep now