Zwei ähnliche Libraries machen Probleme

Bevor ich mein Problem erläutere, erkläre ich zuerst einmal, was ich machen möchte:

Einmalig soll beim beim Start des Arduino Mega die Uhrzeit vom NTP-Server geholt werden und in die RTC geschrieben werden. Das bekomme ich mit folgendem Sketch hin:

/*
 * NAME: NTP2RTC
 * DATE: 2012-02-19
 *  URL: http://playground.arduino.cc/Main/DS1307OfTheLogshieldByMeansOfNTP
 *
 * PURPOSE:
 * Get the time from a Network Time Protocol (NTP) time server
 * and store it to the RTC of the adafruit logshield
 *
 * NTP is described in:
 * http://www.ietf.org/rfc/rfc958.txt (obsolete)
 * http://www.ietf.org/rfc/rfc5905.txt
 *
 * based upon Udp NTP Client, by Michael Margolis, mod by Tom Igoe
 * uses the RTClib from adafruit (based upon Jeelabs)
 * Thanx!
 * mod by Rob Tillaart, 10-10-2010
 *
 * This code is in the public domain.
 *
 */


// libraries for ethershield
#include <SPI.h>        
#include <Ethernet.h>
#include <EthernetUdp.h>        // New from IDE 1.0
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 RTC;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Use your MAC address
byte ip[] = { 192, 168, 1, 121 };                      // no DHCP so we set our own IP address
byte subnet[] = { 255, 255, 255, 0 };                // subnet mask
byte gateway[] = { 192, 168, 1, 1 };                 // internet access via router
unsigned int localPort = 8888;             // local port to listen for UDP packets

byte timeServer[] = {192, 168, 1, 1};    // Fritzbox
const int NTP_PACKET_SIZE= 48;             // NTP time stamp is in the first 48 bytes of the message
byte pb[NTP_PACKET_SIZE];                  // buffer to hold incoming and outgoing packets
EthernetUDP Udp;                

///////////////////////////////////////////
//
// SETUP
//
void setup()
{
  Serial.begin(57600);
  Serial.println("NTP2RTC 0.5");

  // start Ethernet and UDP

  Ethernet.begin(mac, ip);         // For when you are directly connected to the Internet.
  Udp.begin(localPort);
  Serial.println("network ...");

  Wire.begin();
  RTC.begin();
  Serial.println("rtc ...");
  Serial.println();
}

///////////////////////////////////////////
//
// LOOP
//
void loop()
{
  Serial.print("RTC before: ");
  PrintDateTime(RTC.now());
  Serial.println();
  sendNTPpacket(timeServer);           // send an NTP packet to a time server
  delay(1000);                         // wait to see if a reply is available
  if ( Udp.parsePacket() ) {           
    // read the packet into the buffer
    Udp.read(pb, NTP_PACKET_SIZE);   

    // NTP contains four timestamps with an integer part and a fraction part
    // we only use the integer part here
    unsigned long t1, t2, t3, t4;
    t1 = t2 = t3 = t4 = 0;
    for (int i=0; i< 4; i++)
    {
      t1 = t1 << 8 | pb[16+i];      
      t2 = t2 << 8 | pb[24+i];      
      t3 = t3 << 8 | pb[32+i];      
      t4 = t4 << 8 | pb[40+i];
    }

    // part of the fractional part
    // could be 4 bytes but this is more precise than the 1307 RTC
    // which has a precision of ONE second
    // in fact one byte is sufficient for 1307
    float f1,f2,f3,f4;
    f1 = ((long)pb[20] * 256 + pb[21]) / 65536.0;      
    f2 = ((long)pb[28] * 256 + pb[29]) / 65536.0;      
    f3 = ((long)pb[36] * 256 + pb[37]) / 65536.0;      
    f4 = ((long)pb[44] * 256 + pb[45]) / 65536.0;

    // NOTE:
    // one could use the fractional part to set the RTC more precise
    // 1) at the right (calculated) moment to the NEXT second!
    //    t4++;
    //    delay(1000 - f4*1000);
    //    RTC.adjust(DateTime(t4));
    //    keep in mind that the time in the packet was the time at
    //    the NTP server at sending time so one should take into account
    //    the network latency (try ping!) and the processing of the data
    //    ==> delay (850 - f4*1000);
    // 2) simply use it to round up the second
    //    f > 0.5 => add 1 to the second before adjusting the RTC
    //   (or lower threshold eg 0.4 if one keeps network latency etc in mind)
    // 3) a SW RTC might be more precise, => ardomic clock :)


    // convert NTP to UNIX time, differs seventy years = 2208988800 seconds
    // NTP starts Jan 1, 1900
    // Unix time starts on Jan 1 1970.
    const unsigned long seventyYears = 2208988800UL;
    t1 -= seventyYears;
    t2 -= seventyYears;
    t3 -= seventyYears;
    t4 -= seventyYears;








    /*
    Serial.println("T1 .. T4 && fractional parts");
    PrintDateTime(DateTime(t1)); Serial.println(f1,4);
    PrintDateTime(DateTime(t2)); Serial.println(f2,4);
    PrintDateTime(DateTime(t3)); Serial.println(f3,4);
    */
    PrintDateTime(DateTime(t4)); Serial.println(f4,4);
    Serial.println();

    // Adjust timezone and DST... in my case substract 4 hours for Chile Time
    // or work in UTC?
    t4 += (2 * 3600L);     // Notice the L for long calculations!!
    t4 += 1;               // adjust the delay(1000) at begin of loop!
    if (f4 > 0.4) t4++;    // adjust fractional part, see above
    RTC.adjust(DateTime(t4));

    Serial.print("RTC after : ");
    PrintDateTime(RTC.now());
    Serial.println();

    Serial.println("done ...");
    // endless loop
    while(1);
  }
  else
  {
    Serial.println("No UDP available ...");
  }
  // wait 1 minute before asking for the time again
  // you don't want to annoy NTP server admin's
  delay(6000);
}

///////////////////////////////////////////
//
// MISC
//
void PrintDateTime(DateTime t)
{
    char datestr[24];
    sprintf(datestr, "%04d-%02d-%02d  %02d:%02d:%02d  ", t.year(), t.month(), t.day(), t.hour(), t.minute(), t.second());
    Serial.print(datestr);  
}


// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(byte *address)
{
  // set all bytes in the buffer to 0
  memset(pb, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  pb[0] = 0b11100011;   // LI, Version, Mode
  pb[1] = 0;     // Stratum, or type of clock
  pb[2] = 6;     // Polling Interval
  pb[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  pb[12]  = 49;
  pb[13]  = 0x4E;
  pb[14]  = 49;
  pb[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
//#if ARDUINO >= 100
  // IDE 1.0 compatible:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(pb,NTP_PACKET_SIZE);
  Udp.endPacket();
//#else
//  Udp.sendPacket( pb,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
//#endif   

}
///////////////////////////////////////////
//
// End of program
//

Danach soll der Arduino innerhalb der Loop die Zeit (Stunde, Minute, Datum) aus der RTC auslesen und auf einem LCD Display ausgeben. Der Teil des Sketches, mit dem das funktioniert, sieht so aus:

//************************************************************************************************************

// Uhr
  {
  int nHour = RTC.get(DS1307_HR,true);
  int nMinute = RTC.get(DS1307_MIN,false);
  int nDate = RTC.get(DS1307_DATE,false);
  int nMTH = RTC.get(DS1307_MTH,false);
    lcd1.setCursor(0, 4);
    
    if (nHour < 10)
       lcd1.print("0");
    lcd1.print(nHour);
    lcd1.print(":");
    if (nMinute < 10)
       lcd1.print("0");
    lcd1.print(nMinute);
//    lcd1.print(":");
//    lcd1.print(RTC.get(DS1307_SEC,false));
    lcd1.print("  ");    
 
// Kein Platz mehr auf dem Display 
 
//    byte dayofweek = weekday(); // Der Wochentag soll mit ausgegeben werden, allerdings in der deutschen Version
//  switch(dayofweek)           //Vorgesehen ist nur eine Ausgabe oder Zahlen 01 - 07 (Sonntag-Samstag)

//{
//   case 01:
//    lcd1.print("So. ");
//     break;
//   case 02:
//    lcd1.print("Mo. ");
//     break;
//   case 03:
//     lcd1.print("Di. ");
//     break;
//   case 04:
//     lcd1.print("Mi. ");
//     break;  
//   case 05:
//     lcd1.print("Do. ");
//     break;
//   case 06:
//    lcd1.print("Fr. ");
//     break;
//   case 07:
//     lcd1.print("Sa. ");
//     break;
//}
    if (nDate < 10)
      lcd1.print("0");
    lcd1.print(RTC.get(DS1307_DATE,false));
    lcd1.print(".");
    if (nMTH < 10)
      lcd1.print("0");    
    lcd1.print(RTC.get(DS1307_MTH,false));
    lcd1.print(".");
    lcd1.print(RTC.get(DS1307_YR,false));
//    lcd1.println();
 
   
  }
 
//************************************************************************************************************

Es passte nicht in einen Post, hier nun “Teil 2” meines Posts:

Das Problem ist, dass die beiden Sketche dazu unterschiedliche Libraries benutzen. Wenn ich den ersten Sketch in den “großen” Sketch einbinde, in dem unter anderem der Teil mit der “Uhr” steht, dann bleibt der Arduino beim Starten schon hängen.

Jeder der beiden Sketche für sich läuft einwandfrei, nur gemeinsam wollen sie nicht.

Zu Beginn des Sketches sieht es so aus:

//************************************************************************************************************

#include <SPI.h>        
#include <Ethernet.h>
#include <EthernetUdp.h>        // New from IDE 1.0
#include <Wire.h>
#include <RTClib.h>

#include <OneWire.h>  
#include <DallasTemperature.h>

#include <LCD.h>
#include <LiquidCrystal_I2C.h> 
#include <Time.h>
#include <DS1307.h>

//************************************************************************************************************

Daher nun meine Idee, #include <DS1307.h> auszukommentieren und das Abholen der Uhrzeit aus der RTC so wie die Ausgabe der Uhrzeit auf dem LCD Display nur über die <RTClib.h> laufen zu lassen.

Ein Auskommentieren bringt leider einige Fehler mit sich:

Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2.ino: In function ‘void loop()’:
Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2:514: error: ‘RTC’ was not declared in this scope
Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2:514: error: ‘DS1307_HR’ was not declared in this scope
Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2:515: error: ‘DS1307_MIN’ was not declared in this scope
Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2:516: error: ‘DS1307_DATE’ was not declared in this scope
Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2:517: error: ‘DS1307_MTH’ was not declared in this scope
Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_NTP_2:567: error: ‘DS1307_YR’ was not declared in this scope

Da ich vom Programmieren keine Ahung habe, kann ich nur raten, was das Problem ist. Ich nehme an, dass der Befehl zum Abholen und Darstellen der Uhrzeit in der RTClib.h anders aufzurufen ist als in der DS1307.h

Wo kann ich nachlesen, wie die Befehle für das Auslesen und die Ausgabe lauten?

Ich nehme an, dass der Befehl zum Abholen und Darstellen der Uhrzeit in der RTClib.h anders aufzurufen ist als in der DS1307.h

Wo kann ich nachlesen, wie die Befehle für das Auslesen und die Ausgabe lauten?

→ In RTClib.h und in DS1307.h

Das ist der Zweck dieser sogenannten include-Dateien: Sie definieren, welche Funktionen mit welchen Parametern existieren, damit der Compiler deinen Sketch richtig übersetzen kann und evtl. Fehler finden kann.

Das sind allerdings eher formale Deklarationen, in der Praxis helfen oft die beigefügten Example-Sketche weiter.

In deinem Fall musst du “raten”, welches die entsprechende Funktion in RTCLib.h sind, die dasselbe machen wie die in DS1307.h
Die eine nutzt ein DateTime - Objekt, die andere liefert einzelne Werte (sec, min, h, tag, mon, jahr) mit RTC.get()
In der Praxis lernst du notgedrungen selber programmieren :wink:

Was meinst du mit “Darstellen der Uhrzeit” ? Das ist eigentlich nicht Sache der RTC Libraries…

Dein letzter Satz hat mich auf eine Idee gebracht. Ich habe die DS1307.h auskommentiert. Genau so habe ich den ganzen Teil meines “großen” Sketches auskommentiert, der die Uhrzeit auf das LCD ausgibt. Statt dessen habe ich den Sketch, der die Uhrzeit ja erfolgreich im SerialMonitor anzeigt ein wenig ergänzt. Das sieht jetzt so aus:

void PrintDateTime(DateTime t)
{
    char datestr[24];
    sprintf(datestr, "%04d-%02d-%02d  %02d:%02d:%02d  ", t.year(), t.month(), t.day(), t.hour(), t.minute(), t.second());
   
    char datestr1[24]; // von mir
    sprintf(datestr1, "%02d:%02d   %02d.%02d.%04d", t.hour(), t.minute(), t.day(), t.month(), t.year()); // von mir
   
    Serial.print(datestr); 
      lcd1.setCursor(0, 4); // von mir 
      lcd1.print(datestr1); // von mir
   

}

Jetzt wird schon mal erfolgreich die ermittelte Uhrzeit im LCD angezeigt. Bleibt noch das Problem, dass ich die beiden Sketche zusammenfügen muss. Das bekomme ich nicht erfolgreich hin. Ich habe die Includes kopiert. Ebenso den darunter stehenden Teil, so wie alles, was unter “void setup” gehört. Aber alles was dann kommt, soll eigentlich nicht in die Loop hinein, denn es muss nur ein einziges Mal aufgerufen werden. Was in die Loop kommt, ist die von mir oben geänderte Ausgabe auf das LCD. Nach einiger Recherche müsste das mit Boolean gehen. Aber das will bei mir einfach nicht klappen :frowning:

Würde sich jemand bereit erklären und mir die Sketche so zusammenführen, wie ich es erläutert habe? Die aktuelle Version hänge ich mal an. Da gibt es mit Sichheit eine Menge, was man “schöner” machen könnte. Aber wie schon erwähnt, bin ich ein Programmierer. “Schön machen” kommt zum Schluss.

Frank

Temperatur_Spannung_Strom_I2C_LCD_Uhr_LED_LV2_3_NTP.ino (15 KB)