Kalender Daten Sortieren

Hallo zusammen :),

ich bin noch ziemlich neu mit meinem Arduino und wollte mir einen Kleinen Kalender/Erinnerungsstütze für Geburtstage machen. Das ganze soll über einen Arduino UNO mit einer Echtzeituhr laufen und auf einem LCD Display ausgegeben werden.

Das sind die Teile die ich mal bestellt hab den Arduino hab ich bereits.

WINGONEER Tiny DS3231 AT24C32 I2C Modul Precision Real Time Clock Module für Arduino
[WayinTop 20x4 2004 LCD Display Zeichen Bildschirm mit TWI IIC I2C LCD Schnittstelle Adapter für Arduino für Mega 2560 (Blau/2004)]

Jetzt mein eigentliches Problem ich will das mir immer das nächste ereigniss angezeigt wird jedoch weis ich nicht wie ich dies abfragen kann. Ich hab für ein datum z.B. den 23.03. eine Int Zahl gemacht hier 0323. Ich hab auch schon eine Lösung gemacht wie ich das genaue Datum abfegen kann.

Das ist das Programm das ich bis jetzt habe.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display

RTC_DS3231 rtc; // Es wird eine Objekt rtc aus der Klasse RTC_3231 der RTClib.h erstellt

const int ldrPin = A0;

int aktuellertag;

int MamaGeb = 0323;
int MamaJahr = 1968;
int Ich = 0306;
int IchJahr = 1996;

void setup()
{
pinMode (ldrPin, INPUT);
while (!Serial);
Serial.begin(9600);

if (! rtc.begin()) {
Serial.println("Keine Echtzeituhr gefunden! ");
while (1);

lcd.init(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(1,0);
lcd.print("Hallo zusammen");
delay (5000);
lcd.clear();
}
}

void loop(){

DateTime now = rtc.now();

aktuellertag = (now.month()*100+now.day());
Serial.print(aktuellertag);

lcd.setCursor(1,0);
lcd.print(now.hour());
lcd.print("/");
lcd.print(now.minute());
lcd.print("/");
lcd.println(now.second());
lcd.setCursor(2,0);
lcd.print(now.day());
lcd.print(".");
lcd.print(now.month());
lcd.print(".");
lcd.print(now.year());
lcd.print(".");

if(aktuellertag==MamaGeb) {
lcd.setCursor(3,0);
lcd.print("Mama hat Geburtstag");
lcd.setCursor(4,0);
lcd.print("Mama wird heute ");
lcd.print(now.year()-MamaJahr);
}

if(aktuellertag==Ich) {
lcd.setCursor(3,0);
lcd.print("Alles Gute zum Geburtstag");
lcd.setCursor(4,0);
lcd.print("Du wirst heute ");
lcd.print(now.year()-IchJahr);
}
}

kennst du strukturen? Nein? Dann google mal ein wenig zu "struct c++"

gib alle deine Geburtsttage in eine Strutkur,
genauer in ein Array dieser Struktur.

Dann machst dir eine Funktion, die einfach jeden Eintrag durchgeht und die Differenz zwischen "Heute" und nächsten Geburtstag ermittelt. Wenn das Ergebnis besser ist als das vorherige, dann merkst du dir das.

dieser Code ist nicht fertig, aber er soll dir eine Idee geben wie man das machen könnte.

und PS... lies im Forum-HowTo nach, wie man Code wirklich postet.

ungeprüft, nur rein theoretisch:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display

RTC_DS3231 rtc; // Es wird eine Objekt rtc aus der Klasse RTC_3231 der RTClib.h erstellt

const int ldrPin = A0;

int aktuellertag;

int MamaGeb = 0323;
int MamaJahr = 1968;
int Ich = 0306;
int IchJahr = 1996;

struct Data {
  const byte day;
  const byte month;
  const uint16_t year;
  const char name[10];
};

Data geburtstag[] {
  {23, 3, 1968, "Mama"},  // der Erste Eintrag soll der erste Geburtstag im Jahr sein.
  {6, 3, 1996, "ich"},
  {8, 8, 2014, "Katz"},
  {7, 7, 2015, "Hund"},
};

int getIndex(byte day, byte month)
{
  int bestIndex = 0;
  int bestDiff = 367;
  int today = month * 100 + day;  // wir brauchen nur irgendwas um den gleichen oder nächstbesten zu finden
  for (size_t i = 0; i < sizeof(geburtstag) / sizeof(geburtstag[0]); i++)
  {
    int actualDays = geburtstag[i].month * 100 + geburtstag[i].day;
    if (actualDays > today && actualDays - today <= bestDiff)  // Geburtstag in der Zukunft und besser als der jetzt gemerkte...
    {
      bestDiff = actualDays - today;
      bestIndex = i;
    }
  }
  return bestIndex;
}

void output()
{
  DateTime now = rtc.now();
  int actual = getIndex(now.day(), now.month());
  //int actual = 0;
  lcd.setCursor(3, 0);
  lcd.print(geburtstag[actual].name);
  lcd.setCursor(4, 0);
  lcd.print(F("Alter: "));
  lcd.print(geburtstag[actual].year);
  lcd.print("-");
  lcd.print(geburtstag[actual].month);
  lcd.print("-");
  lcd.print(geburtstag[actual].day);
}


void setup()
{
  pinMode (ldrPin, INPUT);
  while (!Serial);
  Serial.begin(9600);

  if (! rtc.begin()) {
    Serial.println("Keine Echtzeituhr gefunden! ");
    while (1);

    lcd.init(); // initialize the lcd
    // Print a message to the LCD.
    lcd.backlight();
    lcd.setCursor(1, 0);
    lcd.print("Hallo zusammen");
    delay (5000);
    lcd.clear();
  }
}

void loop() {

  DateTime now = rtc.now();

  aktuellertag = (now.month() * 100 + now.day());
  Serial.print(aktuellertag);

  lcd.setCursor(1, 0);
  lcd.print(now.hour());
  lcd.print("/");
  lcd.print(now.minute());
  lcd.print("/");
  lcd.println(now.second());
  lcd.setCursor(2, 0);
  lcd.print(now.day());
  lcd.print(".");
  lcd.print(now.month());
  lcd.print(".");
  lcd.print(now.year());
  lcd.print(".");

  if (aktuellertag == MamaGeb) {
    lcd.setCursor(3, 0);
    lcd.print("Mama hat Geburtstag");
    lcd.setCursor(4, 0);
    lcd.print("Mama wird heute ");
    lcd.print(now.year() - MamaJahr);
  }

  if (aktuellertag == Ich) {
    lcd.setCursor(3, 0);
    lcd.print("Alles Gute zum Geburtstag");
    lcd.setCursor(4, 0);
    lcd.print("Du wirst heute ");
    lcd.print(now.year() - IchJahr);
  }
}

edit:
und das ist ein laufender Prototyp. Geht.

struct Data {
  const byte day;
  const byte month;
  const uint16_t year;
  const char name[10];
};

Data geburtstag[] {
  {6, 3, 1996, "ich"},     // der Erste Eintrag soll der erste Geburtstag im Jahr sein.
  {23, 3, 1968, "Mama"},  
  {8, 8, 2014, "Katz"},
  {11, 11, 2011, "Maus"},
  {7, 7, 2015, "Hund"},
};

int getIndex(byte day, byte month)
{
  int bestIndex = 0;
  int bestDiff = 367;
  int today = month * 100 + day;  // wir brauchen nur irgendwas um den gleichen oder nächstbesten zu finden
  for (size_t i = 0; i < sizeof(geburtstag) / sizeof(geburtstag[0]); i++)
  {
    int actualDays = geburtstag[i].month * 100 + geburtstag[i].day;
    if (actualDays > today && actualDays - today < bestDiff)  // Geburtstag in der Zukunft und besser als der jetzt gemerkte...
    {
      bestDiff = actualDays - today;
      bestIndex = i;
    }
  }
  return bestIndex;
}

void testOutput(int thisDay, int thisMonth)
{
  int actual = getIndex(thisDay, thisMonth);  
  Serial.print(F("Abfrage für "));
  Serial.print(thisDay);
  Serial.print(".");
  Serial.print(thisMonth);
  Serial.print(". "); 
  Serial.print(geburtstag[actual].name);
  Serial.print(F(" Alter: "));
  Serial.print(geburtstag[actual].year);
  Serial.print("-");
  Serial.print(geburtstag[actual].month);
  Serial.print("-");
  Serial.print(geburtstag[actual].day);
  Serial.println();
}


void setup()
{
  Serial.begin(115200);

  int tag = 13;
  int monat = 3;
  testOutput(tag, monat);
    
  tag = 4;
  monat = 4;
  testOutput(tag, monat);

  tag = 1;
  monat = 11;
  testOutput(tag, monat);

  tag = 12;
  monat = 12;
  testOutput(tag, monat);  // kein Geburtstag mehr in diesem Jahr
}

void loop() {

 
}

ergibt:
Abfrage für 13.3. Mama Alter: 1968-3-23
Abfrage für 4.4. Hund Alter: 2015-7-7
Abfrage für 1.11. Maus Alter: 2011-11-11
Abfrage für 12.12. ich Alter: 1996-3-6

Hallo, da stellt sich sofort die Frage, wie Du Deine Daten verwalten möchtest.

  1. Daten fest im Programm
  2. Daten auf einem Datenträger, z. B. SD-Karte, mit Veränderung in Excel oder einem anderen PC-Programm.

Daraus ergibt sich das weitere Vorgehen.

Hallo,

ich glaube sortieren ist die falsche Frage. So richtig sortieren musst du im Grunde nichts. Die Frage lautet eher wie du mit den Daten umgehst. Zum Bsp. könnte man wissen wollen welche Geburtstage in den nächsten 14 Tagen anstehen.
Dann muss man alle Daten mit den aktuellen Datum vergleichen. Alle Einträge die ins kommende 14 Tage Zeitfenster passen werden angezeigt. Alle Einträge die zurückliegen, vom aktuellen Datum im Jahr ausgesehen, werden nicht angezeigt bzw. nicht berücksichtigt.
Die Daten schreibste erstmal in eine Struktur wie von noisca gezeigt.
Wobei die Reihenfolge in geburtstag[] später keine Rolle spielt.

struct Data {
  const byte day;
  const byte month;
  const uint16_t year;
  const char name[10];
};

Data geburtstag[] {
  {23, 3, 1968, "Mama"},  // der Erste Eintrag soll der erste Geburtstag im Jahr sein.
  {6, 3, 1996, "ich"},
  {8, 8, 2014, "Katz"},
  {7, 7, 2015, "Hund"},
};

So als Grundüberlegung.

Zu überlegen ist ob man den Tag/Monat nicht in Tage umrechnen soll. Dann ist der Vergleich einfacher und auch "in den nächsten 7 Tagen" ist einfach durch dazuaddieren von 7 Tagen ab heute realisierbar.
"Nächste Woche" ist etwas schwieriger weil man den heutigen Wochentag ausrechnen muß und dann den Montag bestimmen und von da an 7 Tage.

Grüße Uwe

Ja, auch die Unix-Zeit, eventuell in Tage umgerechnet, wäre eine Möglichkeit.

Mama freut sich sicherlich, wenn sie nicht nur ihr Alter in Jahren sondern auch "Du bist 23 516 Tage alt" erfährt :rofl:

Vielen Dank für die vielen und schnellen Antworten :smiley: .
Das mit den Strukturen kenn ich bis jetzt noch nicht, werde ich mir aber auf jeden fall mal anschauen. Bin ja hier um von den Profis zu lernen :wink: .

Die Daten wollte ich erstmal nur auf dem Arduino speichern da es in erster Linie um Geburtstage gehen soll.

Welchen µC möchtest Du nutzen?

Wenn UNO oder dergleichen, dann lautet die von mir empfohlene Lösung, Strukturen im Progmem zu speichern, weil da mehr Platz ist.

Dann kanst Du aber auch erst sortieren und dann die Daten ins Programm schreiben. Nachträgliches Sortieren ist dann überflüssig.

Da der Speicher begrenzt ist, kannst Du nicht viele Geburtstage speichern, weshalb ein Durchsuchen vom Anfang bis zum Ende der Daten sehr schnell geht. Also um Mitternacht das aktuelle Datum mit den gespeicherten vergleichen, um dann den Jubilar anzuzeigen, geht fix.

Eine Anzeige "Geschenk besorgen, in 3 Tagen hat Mama Geburtstag" geht mit einer berechneten Unix-Zeit in Tagen.

Hallo,

agmue, schieß mal bitte nicht gleich wieder übers Ziel hinaus. Du weißt wohin das führt. Wegen paar Einträgen läuft der RAM nicht gleich voll. Der TO soll erstmal mit struct und array klar kommen und den Zugriff darauf. Progmem würde ich wenn überhaupt erst am Schluß machen. Soviel Daten werden das nicht sein.

Sortieren ist laut meiner Meinung nach auch nicht notwendig. Wenn die Reihenfolge aus irgendwelchen Gründen wichtig sein sollte, dann kann man das schon beim eintragen berücksichtigen. Ansonsten würde eine Sortierfunktionen die Daten auch immer nur einmal sortieren und im RAM halten. Man hätte nichts gewonnen.

Es werden wohl eher ständige Vergleiche gefordert sein, die man wie ihr schon sagt mit der Unixzeit machen kann. Aber alles zu seiner Zeit.

ElazarMutana? Er oder Sie?

Auf Basis ESP8266 gibt es einen Abfallkalender von Hotsystems. Evtl. könnte man sich da Anregungen für Teilprobleme holen.
(oder den MC wechseln)

Gruß Tommy

Ich finde, ein Ziel kann man anvisieren, ohne es in Kürze erreichen zu müssen.

Einzelne Variablen (Geburtstag_1, Geburtstag_2, ... Geburtstag_n), mehrere Felder, eine Feld aus Strukturen, prozedural oder objektorientiert, wo soll es losgehen? Eine generell schwierige Fragestellung.

Hallo, hier habe ich soetwas schon mal gemacht, vielleicht hilfts ja weiter. Müll und Geburtstagsdaten auf SD Karte:
https://forum.arduino.cc/t/vorstellung-arduino-mull-geburtstags-kalender/471797