RTC ds 1307: Berechnung der Uhrzeit

Hallo Zusammen,

ich versuche seit ein paar Tage eine Berechnung mit meinem Arduino und meinem RTC Modul zu machen. Die Berechnung funktioniert aber nicht vollständig.

Also zur Verfügung habe ich ein PmodRTCC modul, ein TFT LCD Display von Adafruit und ein Arduino Mega.
Ich möchte die Aktuelle Laufzeit eines Gerät berechnet. Dafür wenn ich auf dem Startknopf drücke wird die Startzeit gezeigt und in der SD-Karte gespeichert. Wenn ich auf dem Save-knopf drücke lese ich meine Startzeit aus und wenn ich auf dem Aktknopf lese ich dann die Aktuelle Laufzeit. Aber manchmal wird die Aktuelle Laufzeit mit einem Minuszeichen vor den Seconde und Minute. Vielleicht ist meine Berechnung falsch. So ist die Gleichung für die Berechnung : Aktuelle Laufzeit=Aktuelle zeit - Startzeit.

Könnt ihr mir bitte helfen!?

Ich danke euch schon im Voraus

Hier ist mein Code

void LZ_Aktuelle()
{ 
  DateTime now = rtc.now();
  
 int start_Std=now.hour(); int start_min=now.minute(); int start_sec=now.second();
  while(buttonLZ_Akt = true)
 {
  buttonFenster = false;
  
  //Darstellung des Fensters

  tft.drawLine(0, 200, 320, 200, ILI9341_BLACK);     //Draw first vertical line
  tft.drawLine(106, 200, 106, 240, ILI9341_BLACK);    //Draw first horizontal line
  tft.drawLine(212, 200, 212, 240, ILI9341_BLACK);    //Draw second horizontal line

  tft.setCursor(10,210);
  tft.setTextColor(ILI9341_RED,ILI9341_WHITE);
  tft.setTextSize(3);
  tft.println("Start");

  tft.setCursor(10,10);
  tft.setTextColor(ILI9341_RED,ILI9341_WHITE);
  tft.setTextSize(2);
  tft.println("<Back>");

  tft.setCursor(116,210);
  tft.setTextColor(ILI9341_RED,ILI9341_WHITE);
  tft.setTextSize(3);
  tft.println("Akt");

  tft.setCursor(222,210);
  tft.setTextColor(ILI9341_RED,ILI9341_WHITE);
  tft.setTextSize(3);
  tft.println("Save");
      
  digitalWrite(0, HIGH);
  TS_Point p = ts.getPoint();
  digitalWrite(0, LOW);
  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

   if(ts.touched())
   {
   p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
   p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());

      int y = tft.height() - p.x;
      int x = p.y; 
      tft.setRotation(1);
      
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
    // un REM next 2 lines when trying to fin coordinates for a switch etc
    //Serial.print("X = "); Serial.print(p.x);
    //Serial.print("\tY = "); Serial.println(p.y);
    
    // Checkto see if START pressed
   if (((x > 0) && (x <106)) && ((y > 200) && (y <240))) {
//     if(v)
//      {
        Timerfunktion();  // Nachdem Drücken des Startkopfs wird direkt die Start Uhrzeit gezeigt 
       /* tft.setTextSize(3);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(10, 80);
        tft.println(now.hour(), DEC);
        Serial.print(now.hour(), DEC);
    
        tft.setTextSize(3);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(50, 80);
        tft.println(':');
        Serial.print(':');
    
        tft.setTextSize(3);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(70, 80);
        tft.println(now.minute(), DEC);
        Serial.print(now.minute(), DEC);
    
        tft.setTextSize(3);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(110, 80);
        tft.println(':');
        Serial.print(':');
        
        tft.setTextSize(3);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.setCursor(130, 80);
        tft.println(now.second(), DEC);
        Serial.print(now.second(), DEC);
        Serial.println();*/

// Startzeit wird in der SD-Karte gespeichert
        File myFile = SD.open("Def_File.txt", FILE_WRITE); 
        
          // if the file opened okay, write to it:
          if (myFile) {
            sprintf(buf1, "%02d:%02d:%02d", start_Std, start_min, start_sec);
            myFile.println(buf1);
            myFile.close();
          } else {
            // if the file didn't open, print an error:
            Serial.println("error opening test.txt");
              }

         Serial.println(v);
         v=false;
     }
// Auslesen der gespeicherte Startzeit
     if (((x > 212) && (x <320)) && ((y > 200) && (y <240))) {

        myFile = SD.open("Def_File.txt");
        get_last_line(myFile);
      
        Serial.print(F("last line: "));
        Serial.println(buf1);
        tft.setCursor(10, 100); 
        tft.setTextSize(3);
        tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
        tft.print(buf1);
        
      
        parse();
      
        if (myFile)
          myFile.close(); 
        v=false;
        }
        
// Presst des Aktknopfs und Berechnung der Aktuelle laufzeit
     if (((x > 106) && (x <212)) && ((y > 200) && (y <240))) {   
      sprintf(buf, "%02d:%02d:%02d", rtc.now().hour()-start_Std, rtc.now().minute()-start_min, rtc.now().second()-start_sec);
      tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);  
      tft.setTextSize(3);
      tft.setCursor(10,160);
      tft.print(buf);
      //Serial.println(start_sec);
     }

//zurück zu dem Homepage
      if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
        if (((x < 50) && (x > 10)) && ((y < 25) && (y > 5))) (Back = 1);
        if (((x < 50) && (x > 10)) && ((y < 25) && (y > 5))){
          if (Back == 1) { 
            tft.fillScreen(ILI9341_WHITE);
              Homepage();
          }
       }
      }
     }
    }
   }
}

//Zum Auslesen eine Zeile in der SD-karte
bool read_line(File& myFile)
{
  static unsigned int index;

  while (myFile.available())
  {
    char c = myFile.read();

    if (c > 21 && index < 20 - 1)
    {
      buf1[index++] = c;
    }
    else if (c == '\n')
    {
      buf1[index] = '\0';
      index = 0;
      return true;
    }
  }

  return false;
}

bool get_last_line(File& myFile)
{
  if (myFile) //wenn Datei geöffnet
  {
    while (read_line(myFile)) //Zeile auslesen. Gibt false zurück wenn am Ende der Datei
      ;

    return true;
  }
  return false;
}


void parse()
{
  int value1 = atoi(strtok(buf1, ","));
//  int value2 = atoi(strtok(NULL, ","));
//  int value3 = atoi(strtok(NULL, ","));
//  int value4 = atoi(strtok(NULL, ","));

  Serial.println(F("\nvalues:"));
  Serial.println(value1);
//  Serial.println(value2);
//  Serial.println(value3);
//  Serial.println(value4);
}

Und warum zeigst du uns nicht den kompletten Sketch ?
Meist liegen die Fehler im geheimen Teil.

Mein code ist zu viel, Weil ich noch viele andere Sache mit meinem Display, RTC modul und Arduino gemacht habe. Weißt du wie ich das als Zip datei hochladen kannst?

Nein keine zip.

Dann teile es in Steps auf, anders können viele mobile User den nicht lesen.

Kurzer Denkanstoss, was würdest Du nach Deinem Beispiel ausrechnen:

Startzeit: 15:15:07
Endzeit: 16:07:02

Ich erechne: 01:-08:-05

Du musst die Berechnung andres machen: entweder in Unixtimestamp umrechnen, subtrahieren und dann wieder in "lesbare" Zeit umrechnen,
oder z.B:
Startzeit= Start.Stunden3600+Start.Minuten60+Start.Sekunden
Endzeit=End.Stunden3600+End.Minuten60+End.Sekunden
und das dann wieder in "lesbare" Zeit zurück rechnen.

Andere haben bestimmt auch noch andere Ideen.

[edit]Typos[/edit]

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
//#include <tsScreen.h>
#include <Adafruit_STMPE610.h>

#include <SD.h>
#include <Arduino.h>
#include <Wire.h>         // this #include still required because the RTClib depends on it
#include "RTClib.h"

Adafruit_STMPE610 touch = Adafruit_STMPE610();

int Prozent = 0;
int Prozentbalken = 2; 

//tsscreen X+ X- Y+ Y- pins
#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 5   // can be a digital pin
#define XP 4   // can be a digital pin

// This is calibration data for the raw ts data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

#define MINPRESSURE 10
#define MAXPRESSURE 1000

#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);  //


#define FRAME_X 60
#define FRAME_Y 180
#define FRAME_W 201
#define FRAME_H 40


#define REDBUTTON_X FRAME_X
#define REDBUTTON_Y FRAME_Y
#define REDBUTTON_W FRAME_W
#define REDBUTTON_H FRAME_H

bool cleared=false;

//bool buttonStart = true;
bool buttonUhrzeit = true;
bool buttonFenster = true;
bool buttonHomepage = true;
bool buttonFenster1 = true;
bool buttonFenster2 = true;
bool buttonEinstellungseite = true;
bool buttonZeit_bis_ende = true;
bool buttonLZ_Akt = true;

int setminute = 0;
char buf[20];
char buf1[20];
char buf2[20];
int minute;
int second;
int hour;
int year;
int month;
int day;
int Raus;
int Back;
bool s=true;//for timer
bool v=true;

// for Stopwatch
unsigned long previousMillis = 0; // will store last time LED was updated
int secs;
int mins;
int hrs;
const long interval = 1000; // 1 second
boolean runClock = false;
boolean reset = false;

const int chipSelect = 4;
File myFile;

/*void drawFrame()
{
  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);
}*/


#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif

RTC_Millis rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void StartBtn()
{
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_RED);
  tft.setCursor(REDBUTTON_X + 50 , REDBUTTON_Y + (REDBUTTON_H/3));
  tft.setTextColor(ILI9341_BLACK);
  tft.setTextSize(3);
  tft.println("Start");
 
}

void setup () {
  Serial.begin(9600);
    // following line sets the RTC to the date & time this sketch was compiled
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

    while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  if (!ts.begin()) {
    Serial.println("Couldn't start tsscreen controller");
  }
  else {
  Serial.println("tsscreen started");
  }
  
  tft.begin();  // this returns the above results. below you can see how I replaced all this once i know which one I have... 
  tft.fillScreen(ILI9341_WHITE);  //Set's LCD Back Ground as ILI9341_BLACK
  tft.setRotation(1); // 3=landscape mode -w- row pins on right...
  ts.begin();
 
 while(Prozent < 100)
    {
    Prozentbalken = Prozentbalken + 2;
    Prozent = Prozent + 1;//Create Red Button
    tft.fillRect(60,180, Prozentbalken, 40, ILI9341_BLUE);
    tft.fillRect(61 + Prozentbalken,180,203 - Prozentbalken ,40, ILI9341_WHITE);
    tft.drawRect(59,179,203,42, ILI9341_BLACK);
    tft.setCursor(138,188);
    tft.setTextColor(ILI9341_BLACK);
    tft.setTextSize(3);
    tft.print(Prozent);
    tft.print("%");
    }
    
  delay(500);
  //StartBtn();
  delay(10);

}


void loop () {

  if(!cleared){
      tft.fillScreen(ILI9341_WHITE); 
       cleared=true;
        }
  Homepage();
  /* TS_Point p = ts.getPoint(); 
      // Scale using the calibration #'s
      // and rotate coordinate system
  
      p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
      p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());

      int y = tft.height() - p.x;
      int x = p.y;

  if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
        if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
          if(buttonStart){
          if(!cleared){
            tft.fillScreen(ILI9341_WHITE); 
            cleared=true;
            }
              Homepage();
          }
        }
      }
   delay(10);*/
      
}
void Timerfunktion(){
  
    DateTime now = rtc.now();
    
    
    tft.setTextSize(3);
    sprintf(buf,"%04d/%2d/%2d", now.year(), now.month(), now.day());
    day=now.day();month=now.month(); year=now.year();
    tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
    tft.setCursor(10, 50);
    tft.print(buf);
   
    
    tft.setTextSize(3);
    sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    hour=now.hour(); minute=now.minute(); second=now.second();
    tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE);
    tft.setCursor(10, 100);
    tft.print(buf);
    Serial.println(buf);
    delay(0);
    
   
}

Moko:
Kurzer Denkanstoss, was würdest Du nach Deinem Beispiel ausrechnen:

Startzeit: 15:15:07
Endzeit: 16:07:02

Ich erechne: 01:-08:-05

Man kann auch durch Addition von 60min bzw. 60s. und Modulo 60 die Berechnung korrigieren.

Für die Minuten: ((07+60)-15) modulo 60 = 52

Startzeit: 15:15:07
Endzeit: 16:27:02

((27+60)-15) modulo 60 = 72%60 = 12

Im Programmcode:

// Presst des Aktknopfs und Berechnung der Aktuelle laufzeit
     if (((x > 106) && (x <212)) && ((y > 200) && (y <240))) {   
      sprintf(buf, "%02d:%02d:%02d", ((rtc.now().hour()+24)-start_Std)%24, ((rtc.now().minute()+60)-start_min)%60, ((rtc.now().second()+60)-start_sec)%60);

Vielen Dank für eure Antwort.

@Theseus ich habe deine Gleichung verwendet und kriege ich kein Minus mehr. Aber ich habe bemerkt, dass die Übertragung von Seconde zu Minute fehlt und auch von Minute zu Stunde.
Ich habe ein test gemacht:

Startzeit: 10:13:04
Endzeit : 11:03:30
Ergebnis der Berechnung: 01:51:24 (Das ist falsch. Normalerweise muss ich 00:51:24 bekommen)

Hab ihr eine Idee wie ich die Berechnung verbessert kann?

Hier ist meine Gedanke: [Endminute+int (((Endseconde+60)-Startseconde)%60)]-[Startminute+60]

Danke im voraus

Pass6:
@Theseus ich habe deine Gleichung verwendet und kriege ich kein Minus mehr. Aber ich habe bemerkt, dass die Übertragung von Seconde zu Minute fehlt und auch von Minute zu Stunde.

Asche über mein Haupt. Das hatte ich verübersehen.

// Presst des Aktknopfs und Berechnung der Aktuelle laufzeit
     if (((x > 106) && (x <212)) && ((y > 200) && (y <240))) {   
      sprintf(buf, "%02d:%02d:%02d", ((rtc.now().hour()+24)-start_Std-(rtc.now().minute()<start_min))%24, ((rtc.now().minute()+60)-start_min-(rtc.now().second()<start_sec))%60, ((rtc.now().second()+60)-start_sec)%60);

Ein Vergleich ergibt 1, wenn er erfüllt wird.

Irgendwann wird es aber einfacher die beiden Zeiten in Sekunden seit Tagesanfang umzurechnen, die Differenz zu bilden und dann wieder zurückzurechnen. Dafür kann man gut Modulo und Ganzzahlendivision gebrauchen.

Krass!!!
@Thesus vielen Danke. Deine Gleichungen funktionieren vollkommen und sind auch sehr einfach nachzuvollziehen. Noch einmal Danke

Hallo Zusammen,

ich bin wieder zurück mit einem Berechnungsproblem. Also ich habe eine Soll Laufzeit, eine Aktuelle Laufzeit und ich möchte die Restlaufzeit berechnen.
Restlaufzeit=Soll Laufzeit - Aktuelle Laufzeit

Meine Soll Laufzeit ist 500:00:00 Std und die Aktuelle Zeit kann 00:10:25 sein.
Das ist was ich gemacht habe:

          //Berechnung der Aktuelle Restlaufzeit
          LZ_Rest_Std = ((LZ_soll_Std ) - LZ_Ak_Std - (LZ_soll_min < LZ_Ak_min)) % 24;
          LZ_Rest_min = ((LZ_soll_min + 60) - LZ_Ak_min - (LZ_soll_sec < LZ_Ak_sec)) % 60;
          LZ_Rest_sec = ((LZ_soll_sec + 60) - LZ_Ak_sec) % 60;
          sprintf(buf3, "%04d:%02d:%02d", LZ_Rest_Std,  LZ_Rest_min, LZ_Rest_sec);

Es ist fast ähnlich wie die Berechnung der Aktuelle Laufzeit aber die Ergebnisse, die ich bekommt habe sind falsch. Könnt ihr bitte mir helfen!?

Ak=Aktuelle.

Danke schön im Voraus.

Hi

Würde den Umweg über Sekunden gehen, so bekommst Du keine Überläufe (also z.B. Minus-Minuten).
Die berechneten Rest-Sekunden ganz normal in Stunden/Minuten/Sekunden umrechnen.

sollSekunden=sollStd*3600+sollMin*60+sollSek;
aktSekunden=aktStd*3600+aktMin*60+aktSek;
restlaufzeit=sollSekunden-aktSekunden;
restStunden=restlaufzeit/3600
restMinuten=(restlaufzeit-restStunden*3600)/60
restSekunden=restlaufzeit%60;

+1
ja, eine Umrechnung in Sekunden (oder Minuten - je nachdem was "genau genug" ist) mach ich auch immer, wenn es um Uhrzeiten geht.
Die Time-Library macht das für dich (was praktisch ist, wenn auch Datumsangaben mit unterschiedlichen Monatslängen, Schaltjahren etc. im Spiel sind).