Problem's with the RTC

25 Sep 2012

Hey, I have a problem. I want to program a data logger for a time switch.

I always want when the temperature is too high to enable an LED,... that works. And then when the output is set to be simultaneously written purely unique in a file, the time, date and action. And because the temperature is not bound to specific times, I have to use the RTC. But it does not work the way I thought.

This is a part of the code (which works not)

                        led1temp = 1;

                        fp = fopen("/local/schalten.txt", "a");

                        *t = localtime(&seconds);

                        fprintf(fp, "T - Time: %02d:%02d   Date: %02d.%02d.%04d   Action: LED1 on\r\n",
                                t.tm_hour, t.tm_min,t.tm_mday,t.tm_mon,t.tm_year);

                        fclose(fp);
                    

Sorry for my bad English ;)

25 Sep 2012

The error message: "no operator "*" matches these operands" in file "/main.cpp", Line: 256, Col: 48

25 Sep 2012

Hello,

The problem is in the localtime function, from the API:

Quote:

returns - Pointer to the (statically allocated) tm structure

So the function returns a pointer to a tm structure. Now I guess you defined your 't' variable as:

struct tm t;

Then your assignment by localtime makes not much sense ;). Easiest option is to just define 't' right there, as showed in the example from the documentation:

struct tm *t = localtime(&seconds);

Or the equivalent, for example if 't' needs to be a global variable:

struct tm *t;
t = localtime(&seconds);

In both cases now 't' is a pointer to a tm structure. Since localtime returns a pointer to a tm structure, this works good. Only thing you have to take into account is that your fprintf doesn't work anymore and needs some slight modifications. Since 't' is a pointer and not an object you have to address it either with t->tm_hour, or with (*t).tm_hour. (First one is the default when using pointers, second one first takes the object 't' points to).

25 Sep 2012

Oh, thank you. It (t->tm_hour) works. :)

25 Sep 2012

But one more question. I'm writing this on an SD card in a file. But if the temperature is too high, then it print the fprintf line 10 times in a second. How can I get only one output?

25 Sep 2012

One could either put an if to check if the second has changed or fix whatever is causing it. We'd more code to offer any more help..

25 Sep 2012

Indeed for that we would need to see how your code works. The straight forward way would probably be to store the time of the last time it happened, then compare the current time to that time. If the difference is less than a certain amount you specify it ignores it.

25 Sep 2012

@Erik: How can I write this? Because if I write for example if(seconds == seconds + 1000) or if(seconds != seconds), then the RTC stops.

This is the whole code:

#include "mbed.h"
#include "TextLCD.h"
#include "SDFileSystem.h"

TextLCD lcd(p26, p25, p24, p23, p22, p20, p19, TextLCD::LCD20x4);
SDFileSystem sd(p11, p12, p13, p14, "sd");
LocalFileSystem local("local");
Serial pc(USBTX,USBRX);
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
AnalogIn temp(p15);

FILE *fp;

// Variablen fuer die Temperaturmessung
float it    = 0;
int toowarm = 0;

// Variablen fuer die Ueberpruefung der Zeit- und Temperaturuebereinstimmungen
int time_u[16] = {0};
int temp_u[16] = {0};

// Variablen zum hochzaehlen der Schaltevent-Variablen
int y = 0;
int z = 0;

// Variablen fuer die Zeitbasierte Schaltzeitenerfassung
int led1time = 0;
int led2time = 0;
int led3time = 0;
int led4time = 0;

// Variablen fuer die Temperaturbasierte Schaltzeitenerfassung
int led1temp = 0;
int led2temp = 0;
int led3temp = 0;
int led4temp = 0;

// Struktur mit den Variablen fuer die Zeiten und Daten der Schaltzeiten
typedef struct chart {
    int function;
    int hour;
    int min;
    int start_day;
    int start_mon;
    int start_year;
    int stop_day;
    int stop_mon;
    int stop_year;
    int repeat;
    int action;
    int exit;
    float temperatur;
} SCHALTTABELLE;

SCHALTTABELLE schaltevent[16];

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Hautpfunktion
int main()
{
    struct tm t;

    // fopen oeffnet die Textdatei "tabelle.txt" um Sie auszulesen
    fp = fopen("/local/tabelle.txt", "r");

    // wenn fp NULL ist, konnte die Datei nicht geoeffnet werden, der Fehler wird ausgegeben
    if(fp == NULL) {
        pc.printf("Datei konnte nicht geoeffnet werden.\n");
    } else {
        // Ueberschrift fuer die Ausgabe im HyperTerminal wird ausgegeben
        pc.printf("------------------------- [ Schaltuhr ] -------------------------\r\n\n\n");

        // Inhalt der in die Textdatei gespeichert wurde (manuell) wird ausgelesen
        // 1. Funktion, 2. Zeit, 3. Startdatum, 4. Enddatum, 5. taeglich, 6. Aktion, 7. Ausgang, 8. Temperatur
        // Lese den Inhalt der Datei formatiert ein, speichere die Werte in Variablen und wiederhole es bis zum EOF
        while((fscanf(fp,"%d %d:%d %d.%d.%d %d.%d.%d %d %d %d %f\r\n",
                      &schaltevent[y].function,&schaltevent[y].hour,&schaltevent[y].min,&schaltevent[y].start_day,&schaltevent[y].start_mon,&schaltevent[y].start_year,
                      &schaltevent[y].stop_day, &schaltevent[y].stop_mon, &schaltevent[y].stop_year, &schaltevent[y].repeat,&schaltevent[y].action,
                      &schaltevent[y].exit,&schaltevent[y].temperatur)) != EOF )

            y++;

        for(z=0; z<16; z++) {
            // Gebe die eingelesenen Daten formatiert im HyperTerminal aus
            fprintf(stdout,"Funktion:   %d\r\nZeit:       %02d:%02d\r\nStartdatum: %02d.%02d.%04d\r\nEnddatum:   %02d.%02d.%04d\r\ntaeglich:   %d\r\nAktion:     %d\r\nAusgang:    %d\r\n"
                    "Temperatur: %.1f\r\n\n\n", schaltevent[z].function, schaltevent[z].hour,schaltevent[z].min,schaltevent[z].start_day,schaltevent[z].start_mon,schaltevent[z].start_year,
                    schaltevent[z].stop_day, schaltevent[z].stop_mon, schaltevent[z].stop_year, schaltevent[z].repeat,schaltevent[z].action,schaltevent[z].exit,schaltevent[z].temperatur);
        }
        // Datei wird geschlossen
        fclose(fp);
    }

// Entnehme die Sekunden der RTC des mbed's zum stellen der aktuellen Uhrzeit
    void set_time(time_t t);



    // Das Programm wiederholt ab hier alles unendlich (bis die Bedingung nicht mehr erf�st)
    while (1) {

        // Temperatur "messen" und in eine Variable speichern
        float tmp = temp.read();

        time_t seconds = time(NULL);

        // Gebe die Zeit, das Datum und die Temperatur auf dem LCD-Display aus
        char buffer[32];
        strftime(buffer, 32, "     %H:%M:%S\n%a, %d/%m/%Y\n", localtime(&seconds));
        lcd.locate(0,0);
        lcd.printf("%s", buffer);
        lcd.locate(0,2);
        lcd.printf("     %2.1f C", tmp);
        lcd.locate(0,3);
        lcd.printf("BBR Verkehrstechnik");

        // Vergleiche alle Schaltevents, ob sie jetzt ausgefuehrt werden sollen
        // Unterscheide zwischen Zeit und Temperaturevent
        for (z=0; z<16; z++) {

            // Zeitevent
            if(schaltevent[z].function == 1) {

                // aus dem Zeitevent eine Angabe in Sekunden bilden
                t.tm_sec = 0;
                t.tm_min = schaltevent[z].min;
                t.tm_hour = schaltevent[z].hour;
                t.tm_mday = schaltevent[z].start_day;
                t.tm_mon = schaltevent[z].start_mon-1;
                t.tm_year = schaltevent[z].start_year-1900;

                // in Sekunden konvertieren
                time_t event_seconds = mktime(&t);


                // Zeitueberpruefung
                // Bei Ueberweinstimmung setze time_u[z] auf 1
                if((event_seconds) == (seconds)) {

                    time_u[z] = 1;

                    // wenn es taeglich ausgefuehrt werden soll (repeat == 1), zaehle den Starttag und den Endtag hoch
                    if(schaltevent[z].repeat == 1) {
                        schaltevent[z].start_day++;
                        schaltevent[z].stop_day++;
                    }

                    // wenn der Starttag noch kleiner ist als der Endtag, dann fuehre die Aktion weiterhin taeglich um die selbe Uhrzeit aus
                    if((schaltevent[z].start_day) <= (schaltevent[z].stop_day)) {
                        schaltevent[z].start_day++;
                    }
                }

                // Gibt es eine zeitliche Uebereinstimmungen
                if (time_u[z]==1) {
                    // Unterscheide zwischen den auszufuehrenden Aktionen
                    if (schaltevent[z].action == 1) {
                        // Merker Einschalten setzen
                        if(schaltevent[z].exit == 1) {
                            led1time = 1;

                            // Beziehe die SD-Karte als Datenlogger mit ein
                            mkdir("/sd/mydir", 0777);

                            // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                            fp = fopen("/sd/mydir/Zeiten.txt", "a");

                            fprintf(fp,"[ Z ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED1 an\r\n"
                                    ,schaltevent[z].hour,schaltevent[z].min,schaltevent[z].start_day,schaltevent[z].start_mon,schaltevent[z].start_year);

                            // Datei wird geschlossen
                            fclose(fp);
                        }
                        if(schaltevent[z].exit == 2) {
                            led2time = 1;

                            // Beziehe die SD-Karte als Datenlogger mit ein
                            mkdir("/sd/mydir", 0777);

                            // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                            fp = fopen("/sd/mydir/Zeiten.txt", "a");

                            fprintf(fp,"[ Z ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED2 an\r\n"
                                    ,schaltevent[z].hour,schaltevent[z].min,schaltevent[z].start_day,schaltevent[z].start_mon,schaltevent[z].start_year);

                            // Datei wird geschlossen
                            fclose(fp);
                        }
                        if(schaltevent[z].exit == 3) {
                            led3time = 1;

                            // Beziehe die SD-Karte als Datenlogger mit ein
                            mkdir("/sd/mydir", 0777);

                            // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                            fp = fopen("/sd/mydir/Zeiten.txt", "a");

                            fprintf(fp,"[ Z ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED3 an\r\n"
                                    ,schaltevent[z].hour,schaltevent[z].min,schaltevent[z].start_day,schaltevent[z].start_mon,schaltevent[z].start_year);

                            // Datei wird geschlossen
                            fclose(fp);
                        }
                        if(schaltevent[z].exit == 4) {
                            led4time = 1;

                            // Beziehe die SD-Karte als Datenlogger mit ein
                            mkdir("/sd/mydir", 0777);

                            // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                            fp = fopen("/sd/mydir/Zeiten.txt", "a");

                            fprintf(fp,"[ Z ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED4 an\r\n"
                                    ,schaltevent[z].hour,schaltevent[z].min,schaltevent[z].start_day,schaltevent[z].start_mon,schaltevent[z].start_year);

                            // Datei wird geschlossen
                            fclose(fp);
                        }
                    } else {
                        if(schaltevent[z].exit == 1) {
                            led1time = 0;
                        }
                        if(schaltevent[z].exit == 2) {
                            led2time = 0;
                        }
                        if(schaltevent[z].exit == 3) {
                            led3time = 0;
                        }
                        if(schaltevent[z].exit == 4) {
                            led4time = 0;
                        }
                    }
                    time_u[z]=0;
                }
            }



            // Temperaturevent
            if(schaltevent[z].function == 2) {

                // Temperaturueberpruefung
                // Bei zu hoher Temperatur setze temp_u auf 1
                it = 0;
                it = it + tmp;

                if(it > schaltevent[z].temperatur)  toowarm = 1;
                if(it < schaltevent[z].temperatur)  toowarm = 0;

                if(toowarm == 1) {
                    temp_u[z] = 1;
                }

                if(toowarm == 0) {
                    temp_u[z] = 0;
                }

                if(temp_u[z] == 1) {
                    // Unterscheide zwischen den auszufuehrenden Aktionen
                    // Merker Einschalten setzen
                    if(schaltevent[z].exit == 1) {
                        led1temp = 1;

                        // Beziehe die SD-Karte als Datenlogger mit ein
                        mkdir("/sd/mydir", 0777);

                        // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                        fp = fopen("/sd/mydir/Zeiten.txt", "a");

                        // Zeitpunkt holen bzw. den bereits geholten Wert umwandeln
                        struct tm *t;
                        t = localtime(&seconds);

                        fprintf(fp, "[ T ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED1 an\r\n",
                                t->tm_hour, t->tm_min,t->tm_mday,t->tm_mon,t->tm_year);
                 
                        // Datei wird geschlossen
                        fclose(fp);
                        
                    }
                    if(schaltevent[z].exit == 2) {
                        led2temp = 1;

                        // Beziehe die SD-Karte als Datenlogger mit ein
                        mkdir("/sd/mydir", 0777);

                        // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                        fp = fopen("/sd/mydir/Zeiten.txt", "a");

                        // Zeitpunkt holen bzw. den bereits geholten Wert umwandeln
                        struct tm *t;
                        t = localtime(&seconds);

                        fprintf(fp, "[ T ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED1 an\r\n",
                                t->tm_hour, t->tm_min,t->tm_mday,t->tm_mon,t->tm_year);

                        // Datei wird geschlossen
                        fclose(fp);
                    }
                    if(schaltevent[z].exit == 3) {
                        led3temp = 1;

                        // Beziehe die SD-Karte als Datenlogger mit ein
                        mkdir("/sd/mydir", 0777);

                        // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                        fp = fopen("/sd/mydir/Zeiten.txt", "a");

                        // Zeitpunkt holen bzw. den bereits geholten Wert umwandeln
                        struct tm *t;
                        t = localtime(&seconds);

                        fprintf(fp, "[ T ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED1 an\r\n",
                                t->tm_hour, t->tm_min,t->tm_mday,t->tm_mon,t->tm_year);
                        // Datei wird geschlossen
                        fclose(fp);
                    }
                    if(schaltevent[z].exit == 4) {
                        led4temp = 1;

                        // Beziehe die SD-Karte als Datenlogger mit ein
                        mkdir("/sd/mydir", 0777);

                        // Oeffne die Datei Zeiten.txt um die Schaltzeit einmalig oder bei jedem neuen Event abzuspeichern
                        fp = fopen("/sd/mydir/Zeiten.txt", "a");

                        // Zeitpunkt holen bzw. den bereits geholten Wert umwandeln
                        struct tm *t;
                        t = localtime(&seconds);

                        fprintf(fp, "[ T ] - Uhrzeit: %02d:%02d   Datum: %02d.%02d.%04d   Aktion: LED1 an\r\n",
                                t->tm_hour, t->tm_min,t->tm_mday,t->tm_mon,t->tm_year);
                        // Datei wird geschlossen
                        fclose(fp);
                    }
                } else {
                    if(schaltevent[z].exit == 1) {
                        led1temp = 0;
                    }
                    if(schaltevent[z].exit == 2) {
                        led2temp = 0;
                    }
                    if(schaltevent[z].exit == 3) {
                        led3temp = 0;
                    }
                    if(schaltevent[z].exit == 4) {
                        led4temp = 0;
                    }

                }
            }


            // Abgleich ob der jeweilige Ausgang ueber die Temperatur oder die Zeit geschaltet wird
            if ((led1time == 1)||(led1temp == 1)) {
                myled1 = 1;
            } else {
                myled1 = 0;
            }
            if ((led2time == 1)||(led2temp == 1)) {
                myled2 = 1;
            } else {
                myled2 = 0;
            }
            if ((led3time == 1)||(led3temp == 1)) {
                myled3 = 1;
            } else {
                myled3 = 0;
            }
            if ((led4time == 1)||(led4temp == 1)) {
                myled4 = 1;
            } else {
                myled4 = 0;
            }


        }

    }
}
25 Sep 2012

Quote:

Because if I write for example if(seconds == seconds + 1000) or if(seconds != seconds), then the RTC stops.

Those are both situations that can (obviously) never happen, seconds can never be equal to seconds + 1000, and it also cannot be unequal to itself.

I hadn't used the RTC myself before, so had to figure it a bit out with the documentation, but something like this seems to work:

#include "mbed.h"

int main() {
    set_time(0);  
    time_t seconds;
    time_t seconds_prev = 0;

    while(1) {
        seconds = time(NULL);
        if (seconds>=seconds_prev+5) {        
        
            printf("Time since start = %d\n\r", seconds);

            wait(.1);
            
            seconds_prev = seconds;
         }
    }
}

Its output is:

Time since start = 5
Time since start = 10
Time since start = 15
Time since start = 20
Time since start = 25
Time since start = 30
Time since start = 35
Time since start = 40