Forum: Mikrocontroller und Digitale Elektronik RTC DS3231 Frage zu Code


von Daniel S. (supernova01)


Lesenswert?

Hallo,

ich nutze einen ferigen Code für die o.g. RTC auf einem atmega168(Nano). 
Leider ist es in C++ geschrieben, etwas oversice für so eine kleine 
Sache, aber nun gut, der Code läuft, Uhr läuft auch, alles gut.

Die RTC ist mit TWI verbunden. (A4,A5)

Nun dachte ich mir, schauste mal rein was dort getrieben wird.

Momentan habe ich eigentlich nur eine Frage dazu:

MyDS3231::MyDS3231(byte I2CAdd)
{
  _I2CAdd  = I2CAdd;
  Wire.begin();
}
//****************************************************
//DS3231 vorhanden ?

bool MyDS3231::isReady()
{
  Wire.beginTransmission(_I2CAdd);
  if (Wire.endTransmission()== 0) return true;
  else return false;
}

_I2CAdd ist private byte.

  private:
  byte _I2CAdd;

Ich frage ich woher I2CAdd beim Konstruktor seinen Inhalt bekommt.

So wie ich verstanden habe, hat die Uhr eine feste Adresse von 0x68. 
Dieser Wert ist aber nirges zu finden, also nicht in der c++ oder header 
Datei. Er scheint auch nirgends gelesen zu werden.

Bin kein C++ provi, ist lange her zudem kenne den Umgang mit der DS3231 
kaum, ich hätte erwartet dass man sie mit der Adresse ansprechen muss, 
damit sie "antwortet", das scheint dort ja auch zu passieren, nur die 
Adresse müsste dann ja irgenwo festgelegt sein, das ist meine Frage, 
oder funktioniert die Uhr anders?

Danke

VG
DS

von Adam P. (adamap)


Lesenswert?

Dennis S. schrieb:
> Ich frage ich woher I2CAdd beim Konstruktor seinen Inhalt bekommt.

Hast du in deiner "Haupt Source Datei" nicht sowas wie
1
MyDS3231 RTC(0x68);

stehen?

Siehe dort Beispiel 1
https://arduino-projekte.webnode.at/meine-libraries/rtc-ds3231/

: Bearbeitet durch User
von Daniel S. (supernova01)


Lesenswert?

#include "MyDS3231.h"
MyDS3231 RTC(0x68);

ach was, nein es steht in dem Bereich wo die Dateien einegbunden werden, 
das ist doch aber sehr unschön...

von Adam P. (adamap)


Lesenswert?

Dennis S. schrieb:
> ach was, nein es steht in dem Bereich wo die Dateien einegbunden werden

Bei ihm zu 99% in der Hauptdatei.

Besser gesagt, dort wo das Objekt erzeugt wird.

: Bearbeitet durch User
von Daniel S. (supernova01)


Lesenswert?

Ich schreibe eigentlich alles selber, ich wundere mich hier aber warum 
für diese Adresse eine Übergabe gemacht wird, da man sie doch eh nicht 
ändern kann. Zudem wird ein Byte dafür vorgehalten. Dabei würde doch ein 
einfaches Define reichen.

#define    MYDS3231ADDR 0x68

MyDS3231::MyDS3231(void)
{
  Wire.begin();
}
//****************************************************
//DS3231 vorhanden ?

bool MyDS3231::isReady()
{
  Wire.beginTransmission(MYDS3231ADDR);
  if (Wire.endTransmission()== 0) return true;
  else return false;
}

von Daniel S. (supernova01)


Lesenswert?

Adam P. schrieb:
> Besser gesagt, dort wo das Objekt erzeugt wird.

danke. Mir scheint der Code sehr umständlich:

 for (byte i = 0; i < 7; i++)
  {
    x = Wire.read();
    dateTime[i] = bcd2Dec(x);
  }

So:

 for (byte i = 0; i < 7; i++)
  {
    dateTime[i] = bcd2Dec(Wire.read());
  }

Aber es soll wohl der Leserlichkeit dienen?

von Daniel S. (supernova01)


Lesenswert?

Hier:

//********************************************************************** 
***
//Setzen der Uhrzeit

void MyDS3231::setTime(byte h, byte m, byte s)
{
  byte _h = h;
  byte _m = m;
  byte _s = s;

  byte time[3];

  time[0] = dec2Bcd(_s);
  time[1] = dec2Bcd(_m);
  time[2] = dec2Bcd(_h);

  Wire.beginTransmission(_I2CAdd);
  Wire.write(DS3231_dateTime_Register);
  for (byte i = 0; i < 3; i++)
  {
    Wire.write(time[i]);
  }
  Wire.endTransmission();
}

Bin ich da völlig raus!?


//********************************************************************** 
***
//Setzen der Uhrzeit

void MyDS3231::setTime(byte h, byte m, byte s)
{

  byte time[3];

  time[0] = dec2Bcd(s);
  time[1] = dec2Bcd(m);
  time[2] = dec2Bcd(h);

Warum die Kopien über Kopien???

oder:

  Wire.beginTransmission(MYDS3231ADDR);
  Wire.write(DS3231_dateTime_Register);
  Wire.write(dec2Bcd(s));
  Wire.write(dec2Bcd(m));
  Wire.write(dec2Bcd(h));
  Wire.endTransmission();

von Adam P. (adamap)


Lesenswert?

Klar könntest du es mit deinem define machen.
Aber dann eher in der Datei wo du das Objekt erzeugst.

Packst du das mit in die LIB, ist die Klasse nicht mehr "dynamisch".
Bzw. wird in die LIB wohl nie ein "0815 Arudino User" reinschauen
um evtl. die Adresse anzupassen.

Kommt immer auf den Anwendungsfall drauf an.

von Adam P. (adamap)


Lesenswert?

Die Adresse ist ja eine Eigenschaft von dem erzeugten Objekt.
Eine Eigenschaft sollte halt gesetzt werden können.

Warum da nun kopiert wird oder auch nicht, kann ich dir nicht sagen.
Ist dann wohl eher eine Designfrage des Programmierers.

von Daniel S. (supernova01)


Lesenswert?

Adam P. schrieb:
> Ist dann wohl eher eine Designfrage des Programmierers.

okay, hätte ja sein können das es bestimmte Gründe gibt in c++ das so zu 
machen.... nur deswegen auch die Fragen hier.

Ich finde es ja gut das einfach nutzen zu können und auch das es zur 
verfühgung gestellt wird, es geht mir nur ums Verständnis, da ich da 
einfach mal etwas stöbern wollte und recht schnell gestolpert bin...

Gruß

von Joachim B. (jar)


Lesenswert?

Adam P. schrieb:
> Die Adresse ist ja eine Eigenschaft von dem erzeugten Objekt.
> Eine Eigenschaft sollte halt gesetzt werden können.
>
> Warum da nun kopiert wird oder auch nicht, kann ich dir nicht sagen.
> Ist dann wohl eher eine Designfrage des Programmierers.

aber das genau die Adresse von der DS3231 (genau wie der DS1307) fest 
ist sehe ich in dieser Routine keinen Sinn sie variabel zu setzen!
Wer kann den Code für die DS denn anderweitig nutzen?

ausser I2C start und stop ist da nichts übertragbar.

von Daniel S. (supernova01)


Lesenswert?

Joachim B. schrieb:
> ausser I2C start und stop ist da nichts übertragbar.

Sehe ich auch so, aber ich kann mir das dann ja ändern, wenn ich möchte.

Mir brennt noch eine Frage zu diesem "Aufruf" auf der Seele:

#include "MyDS3231.h"
MyDS3231 RTC(0x68);

Zu welchem Zeitpunkt wird der Code ausgeführt, eingebunden? vor dem 
setup () bei Arduino?

Wäre es sinnvoll das in Setup aufzurufen? Oder wäre das dann nur 
innerhalb von Setup() vorhanden?

Danke.

VG

von Falk B. (falk)


Lesenswert?

Dennis S. schrieb:

> Mir brennt noch eine Frage zu diesem "Aufruf" auf der Seele:

Seelenfragen beantworten dir deine spirituellen Führer.

> #include "MyDS3231.h"
> MyDS3231 RTC(0x68);
>
> Zu welchem Zeitpunkt wird der Code ausgeführt, eingebunden? vor dem
> setup () bei Arduino?

Ja.

> Wäre es sinnvoll das in Setup aufzurufen?

Nö.

> Oder wäre das dann nur
> innerhalb von Setup() vorhanden?

JA! Aka lokale Variablen.

von Daniel S. (supernova01)


Lesenswert?

Falk B. schrieb:
> spirituellen Führer.

Falk, wer ist das bei dir? Oder hast du den "Funken" in dir bereits 
entdeckt? Um mal im E-Forum Sprache zu fragen.

Falk B. schrieb:
> JA! Aka lokale Variablen.

Jup. Dann habe ich es.

Danke

von Adam P. (adamap)


Lesenswert?

Joachim B. schrieb:
> aber das genau die Adresse von der DS3231 (genau wie der DS1307) fest
> ist sehe ich in dieser Routine keinen Sinn sie variabel zu setzen!

Ja...das hier ist echt nen schlechts Bsp.

Ich hab aber direkt daran gedacht, falls es von der DS3231 eine 
"Familie" gibt, hätte man die Grundlegenden Dinge in die Basisklasse 
packen können usw.

Evtl. haben die anderen RTC aus der Familie eine andere Adr.

Oder man packt noch eine andere Klasse mit rein, z.B. ein Interface zu 
einem  I2C Multiplexer.

Hier ist es auf den einen Typ nicht notwendig.

edit:

Dennis S. schrieb:
> Ich finde es ja gut das einfach nutzen zu können und auch das es zur
> verfühgung gestellt wird, es geht mir nur ums Verständnis, da ich da
> einfach mal etwas stöbern wollte

und genau so lernt man es auch nur,
schauen, nachlesen, ausprobieren und verstehen ;)

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

es gibt ja noch andere Libs für RTC, für Arduino würde ich zuerst hier 
suchen:
https://www.arduino.cc/reference/en/libraries/
da ist dann die
https://github.com/adafruit/RTClib
zu finden, mit mehr Beschreibung und auch welche Targets abgedeckt 
werden.

Generell würde ich Libs nur noch verwenden wenn sie auf github/lab 
gehostet sind, hingeworfene Zips sind letztes Jahrtausend. Und auch von 
github nicht als zip laden sondern klonen, nur so lassen sich Änderungen 
und Historie ordentlich verfolgen. Mag man für eine überschaubare Lib 
nicht für nötig halten, aber je größer eine Lib oder ein Projekt ist, 
umso mehr wird man git schätzen lernen.

Bei Adafruit oder anderen hat man auf die wählbare, aber eigentlich fixe 
I2C Adresse auch verzichtet. Ich hätte zumindest in der 
Konstruktordeklaration einen default eingetragen.
Die temporären Variablen wird der Compiler zwar wegfegen, aber schön 
oder sinnvoll finde ich die auch nicht.

von Daniel S. (supernova01)


Lesenswert?

Johannes S. schrieb:
> zu finden, mit mehr Beschreibung und auch welche Targets abgedeckt
> werden.

danke!

Johannes S. schrieb:
> Generell würde ich Libs nur noch verwenden wenn sie auf github/lab
> gehostet sind

okay. Ichj werde mir die paar code Schnipsel raus picken und denr rest 
streiche ich raus. Die ganzen String Operationen usw. brauche ich 
wirklich komplett nicht.

Bei dieser Zeile Code:

while (Wire.available() == 0);

gehen bei mir auch alle Lampen an. Dafür müsste es auch eine andere 
Lösung geben.

 Wire.requestFrom(int(_I2CAdd), 7);
  while (Wire.available() == 0);
  for (byte i = 0; i < 7; i++)
  {
    x = Wire.read();
    dateTime[i] = bcd2Dec(x);
  }

Und irgendwie scheint mir die ANwendung fragwürdig, müsste ja eigentlich 
Wire.datacomplete() heißen und eine 1 zurückgeben wenn der Lesevorgang 
abgeschlossen ist.

Gruß

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.