Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Teensy 4.0 RTC with battery doesn't save correct time after power loss

  1. #1

    Teensy 4.0 RTC with battery doesn't save correct time after power loss

    The attached sketch shows the time on a display, allows it to be updated, and attempts to save any time updates. While everything seems to work okay while it is running, when power is removed the time is restored to the original time settings, not the updated time settings. There is a good battery connected to the teensy 4.

    I tried loading the Teensy Arduino IDE software again, but that doesn't help.

    What am I doing wrong?

    Code:
    // designed for for teensy 4.0
    
    #include <TimeLib.h>
    #include "Adafruit_HX8357.h"
    #include <Adafruit_GFX.h>    // Core graphics library
    #include "TouchScreen.h"
    
    // These are the four touchscreen analog pins
    #define YP A2  // must be an analog pin, use "An" notation!
    #define XM A3  // must be an analog pin, use "An" notation!
    #define YM 7   // can be a digital pin
    #define XP 8   // can be a digital pin
    TouchScreen tscr = TouchScreen(XP, YP, XM, YM, 500);
    
    #define MINPRESSURE 300
    #define MAXPRESSURE 1000
    
    // The display uses hardware SPI, plus #9 & #10
    #define TFT_RST 15  // if you dont want to use a reset pin, tie this to arduino RST if you like
    #define TFT_DC 9
    #define TFT_CS 10
    
    // This is calibration data for the raw touch data to the screen coordinates
    #define TS_MINX 110
    #define TS_MINY 80
    #define TS_MAXX 900
    #define TS_MAXY 940
    
    Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
    
    // Colors
    #define BACKGROUNDCLR 0xA514
    #define TEXTCLR       0x0000
    #define BUTTONCLR     0xAD75
    #define REDCLR        0xA800
    
    struct Button
    {
      public:
        int x;
        int y;
        int buttonHeight;
        int buttonLength;
        void (*funct)(int n);
        int arg;
    };
    
    Button myArray[12];
    Button item;
    
    boolean AM = true;                          // true for AM false for PM
    int buttonCount = 0;                        // keeps track of # of buttons on screen
    int zIdx = 1, stIdx = 1;                    // indexes zone = 1-ZONECOUNT, start time = 1-3
    
    /***************************************************************************************************************/
    void CreateButton(int txSize, int x, int y, String txt, int bgClr, int txClr, void (funct)(int n), int arg)
    {
      float charWidth[6]  = {6, 6, 12, 18, 24, 28};
      float charHeight[6] = {7, 7, 14, 22, 30, 36};
      float rectWidth, rectHeight;
    
      rectWidth = (txt.length() + 1) * charWidth[txSize];
      rectHeight = charHeight[txSize] + 20;
    
      tft.drawRoundRect(x, y, rectWidth, rectHeight,  10, TEXTCLR);
      tft.fillRoundRect(x + 1, y + 1, rectWidth - 2, rectHeight - 2, 10, bgClr);
    
      int txtStartX = x + (charWidth[txSize] / 2) + 1;                         // Center the TEXTCLR;
      int txtStartY = y + 10;                                                  // TEXTCLR in the middle
    
      tft.setCursor(txtStartX, txtStartY);
      tft.setTextColor(txClr);
      tft.setTextSize(txSize);
      tft.print(txt);
    
      item.x = x;
      item.y = y;
      item.buttonLength =  rectWidth;
      item.buttonHeight = rectHeight;
      item.funct = funct;
      item.arg = arg;
    
      myArray[buttonCount++] = item;
    }
    
    /***************************************************************************************************************/
    void setup(void)
    {
      Serial.begin(115200);
      delay(500);
      pinMode(15, OUTPUT);                            // TFT Display reset pin
      digitalWrite(15, HIGH);
    
      setSyncProvider(getTeensy3Time);                // use the Teensy 4.0 RTC timer
    
      StartDisplay();                                 // start the 3.5" display
    
      if (timeStatus() != timeSet)
        Serial.println(F("Unable to sync with RTC"));
      else
        Serial.println(F("RTC has set system time"));
    
      if (hour() > 12)                                // set AM/PM
        AM = false;
      else
        AM = true;
    
      DrawTimeSetPage(0);
    }
    
    /***************************************************************************************************************/
    void loop(void)
    {
      GetTouch();                       // See if a button is touched
      CheckTimeDisplay();               // update the time once per minute
    }
    
    time_t getTeensy3Time()
    {
      return Teensy3Clock.get();
    }
    
    /***************************************************************************************************************/
    void CheckTimeDisplay()  // display the clock time every minute
    {
      static int nMin, oMin;
      nMin = minute();
    
      if (oMin != nMin)
      {
        DisplayTime();
        oMin = nMin;
      }
    }
    
    /***************************************************************************************************************/
    void Rotation(int n)
    {
      tft.setRotation(n);
    }
    
    /***************************************************************************************************************/
    void StartDisplay()
    {
      tft.begin();
      delay(200);
      Rotation(1);
      tft.fillScreen(BACKGROUNDCLR);
      tft.setTextColor(TEXTCLR);
      tft.setTextSize(3);
    }
    
    /***************************************************************************************************************/
    void SwitchAMPM(int n)
    {
      if (AM == true) AM = false; else  AM = true;
      DisplayTime();
    }
    
    
    
    /***************************************************************************************************************/
    void WriteText(String txt, int txtSize, int x, int y, int clr)
    {
      Rotation(1);
      tft.setTextColor(clr);
      tft.setTextSize(txtSize);
      tft.setCursor(x, y);
      tft.print(txt);
    }
    
    /***************************************************************************************************************/
    void DisplayTime()
    {
      int hr = hour(), mn = minute();
      String strHr, strMin;
    
      if (hr > 12)
        hr = hr - 12;
    
      if (hr < 10)
        strHr = "0" + String(hr);
      else
        strHr = String(hr);
    
      if (mn < 10)
        strMin = "0" + String(mn);
      else
        strMin = String(mn);
    
      Rotation(1);
      tft.fillRect(284, 5, 90, 21, BACKGROUNDCLR);
      WriteText("Current Time " + strHr + ":" + strMin, 3, 50, 5, TEXTCLR);
    
      if (AM)
      {
        WriteText("PM", 3, 390, 5, BACKGROUNDCLR);
        WriteText("AM", 3, 390, 5, TEXTCLR);
      }
      else
      {
        WriteText("AM", 3, 390, 5, BACKGROUNDCLR);
        WriteText("PM", 3, 390, 5, TEXTCLR);
      }
    }
    
    /***************************************************************************************************************/
    void HourUp(int n)
    {
      int hr = hour() % 12;
    
      hr += 1;
      if (hr > 12)
      {
        hr = 1;
      }
      setTime(hr, minute(), 0, 1, 1, 2021);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void HourDown(int n)
    {
      int hr = hour() % 12;
      hr -= 1;
      if (hr < 1)
      {
        hr = 12;
      }
    
      setTime(hr, minute(), 0, 1, 1, 2020);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void MinuteUp(int n)
    {
      int mn;
      mn = minute() + 1;
      if (mn > 59)
        mn = 0;
      setTime(hour(), mn, 0, 1, 1, 2020);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void MinuteDown(int n)
    {
      int mn;
    
      mn = minute() - 1;
      if (mn < 0)
        mn = 59;
      setTime(hour(), mn, 0, 1, 1, 2020);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void ClearScreen()
    {
      Rotation(1);
      tft.fillRoundRect(10, 5, 460, 315, 10, BACKGROUNDCLR);
    }
    
    /***************************************************************************************************************/
    void Press(int x, int y)
    {
      int cnt = buttonCount;
      for (int i = 0; i < cnt; i++)
      {
        if (x >= myArray[i].x && x <= myArray[i].x + myArray[i].buttonLength)
          if (y >= myArray[i].y && y <= myArray[i].y + myArray[i].buttonHeight)
          {
            myArray[i].funct(myArray[i].arg);  // call the button's function
            break;
          }
      }
      delay(150);
    }
    
    /***************************************************************************************************************/
    void GetTouch()
    {
      TSPoint p;
      Rotation(0);
      p.z = 0;
    
      // get a point
      p  = tscr.getPoint();
      if (p.z < MINPRESSURE || p.z > MAXPRESSURE)
      {
        return;
      }
    
      // Scale from ~0->1000 to tft.width using the calibration #'s
      p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
      p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
    
      int s = p.x;
      p.x = p.y;
      p.y = s;
    
      Press(p.x, p.y);
      Rotation(1);
    }
    
    /***************************************************************************************************************/
    void DrawTimeSetPage(int n)
    {
      buttonCount = 0;
      ClearScreen();
      Rotation(1);
      DisplayTime();
      WriteText("TIME SET", 2, 190, 40, REDCLR);
      CreateButton(2, 150, 80, "Hour", BUTTONCLR, TEXTCLR, HourUp, 0);
      CreateButton(2, 230, 80, "Minute", BUTTONCLR, TEXTCLR, MinuteUp, 0);
      CreateButton(2, 340, 80, "AMPM", BUTTONCLR, TEXTCLR, SwitchAMPM, 0);
    }

  2. #2
    Senior Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    121
    Your code never sets the RTC with a call to Teensy3Clock.set(time).

    Honestly, the only thing I ever use the stuff in TimeLib for is formatting the time I get from the RTC. Having library routines to keep time is fine for chips that don't have an always available accurate time, but just confuses the issue when you're using something that has an RTC.

  3. #3
    Thank you. I was confused by the timelib and teensy3clock. I'll remove the timelib stuff.
    I will also figure out how to use the Teensy3Clock.set(time)

  4. #4
    Senior Member
    Join Date
    Oct 2019
    Location
    Calgary
    Posts
    121
    On the T4, TimeLib is really handy for extracting values out of the timestamp that the RTC returns, and for formatting time strings, and lots of auxiliary stuff like that. But that's about all I use it for; the RTC's already keeping the time.

    No guarantee that this will actually run correctly, but I took a quick stab at converting your program to let the RTC do the timekeeping and just use TimeLib for extracting hours and minutes, and converting the various time fields back into the RTC timestamp.

    Code:
    // designed for for teensy 4.0
    
    #include <TimeLib.h>
    #include "Adafruit_HX8357.h"
    #include <Adafruit_GFX.h>    // Core graphics library
    #include "TouchScreen.h"
    
    // These are the four touchscreen analog pins
    #define YP A2  // must be an analog pin, use "An" notation!
    #define XM A3  // must be an analog pin, use "An" notation!
    #define YM 7   // can be a digital pin
    #define XP 8   // can be a digital pin
    TouchScreen tscr = TouchScreen(XP, YP, XM, YM, 500);
    
    #define MINPRESSURE 300
    #define MAXPRESSURE 1000
    
    // The display uses hardware SPI, plus #9 & #10
    #define TFT_RST 15  // if you dont want to use a reset pin, tie this to arduino RST if you like
    #define TFT_DC 9
    #define TFT_CS 10
    
    // This is calibration data for the raw touch data to the screen coordinates
    #define TS_MINX 110
    #define TS_MINY 80
    #define TS_MAXX 900
    #define TS_MAXY 940
    
    Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
    
    // Colors
    #define BACKGROUNDCLR 0xA514
    #define TEXTCLR       0x0000
    #define BUTTONCLR     0xAD75
    #define REDCLR        0xA800
    
    struct Button
    {
      public:
        int x;
        int y;
        int buttonHeight;
        int buttonLength;
        void (*funct)(int n);
        int arg;
    };
    
    Button myArray[12];
    Button item;
    
    boolean AM = true;                          // true for AM false for PM
    int buttonCount = 0;                        // keeps track of # of buttons on screen
    int zIdx = 1, stIdx = 1;                    // indexes zone = 1-ZONECOUNT, start time = 1-3
    
    /***************************************************************************************************************/
    void CreateButton(int txSize, int x, int y, String txt, int bgClr, int txClr, void (funct)(int n), int arg)
    {
      float charWidth[6]  = {6, 6, 12, 18, 24, 28};
      float charHeight[6] = {7, 7, 14, 22, 30, 36};
      float rectWidth, rectHeight;
    
      rectWidth = (txt.length() + 1) * charWidth[txSize];
      rectHeight = charHeight[txSize] + 20;
    
      tft.drawRoundRect(x, y, rectWidth, rectHeight,  10, TEXTCLR);
      tft.fillRoundRect(x + 1, y + 1, rectWidth - 2, rectHeight - 2, 10, bgClr);
    
      int txtStartX = x + (charWidth[txSize] / 2) + 1;                         // Center the TEXTCLR;
      int txtStartY = y + 10;                                                  // TEXTCLR in the middle
    
      tft.setCursor(txtStartX, txtStartY);
      tft.setTextColor(txClr);
      tft.setTextSize(txSize);
      tft.print(txt);
    
      item.x = x;
      item.y = y;
      item.buttonLength =  rectWidth;
      item.buttonHeight = rectHeight;
      item.funct = funct;
      item.arg = arg;
    
      myArray[buttonCount++] = item;
    }
    
    /***************************************************************************************************************/
    void setup(void)
    {
      Serial.begin(115200);
      delay(500);
      pinMode(15, OUTPUT);                            // TFT Display reset pin
      digitalWrite(15, HIGH);
    
      StartDisplay();                                 // start the 3.5" display
    
      time_t now = Teensy3Clock.get();
      if (hour(now) > 12)                                // set AM/PM
        AM = false;
      else
        AM = true;
    
      DrawTimeSetPage(0);
    }
    
    /***************************************************************************************************************/
    void loop(void)
    {
      GetTouch();                       // See if a button is touched
      CheckTimeDisplay();               // update the time once per minute
    }
    
    /***************************************************************************************************************/
    void CheckTimeDisplay()  // display the clock time every minute
    {
      time_t now = Teensy3Clock.get();
      static int nMin, oMin;
      nMin = minute(now);
    
      if (oMin != nMin)
      {
        DisplayTime();
        oMin = nMin;
      }
    }
    
    /***************************************************************************************************************/
    void Rotation(int n)
    {
      tft.setRotation(n);
    }
    
    /***************************************************************************************************************/
    void StartDisplay()
    {
      tft.begin();
      delay(200);
      Rotation(1);
      tft.fillScreen(BACKGROUNDCLR);
      tft.setTextColor(TEXTCLR);
      tft.setTextSize(3);
    }
    
    /***************************************************************************************************************/
    void SwitchAMPM(int n)
    {
      if (AM == true) AM = false; else  AM = true;
      DisplayTime();
    }
    
    
    
    /***************************************************************************************************************/
    void WriteText(String txt, int txtSize, int x, int y, int clr)
    {
      Rotation(1);
      tft.setTextColor(clr);
      tft.setTextSize(txtSize);
      tft.setCursor(x, y);
      tft.print(txt);
    }
    
    /***************************************************************************************************************/
    void DisplayTime()
    {
      time_t now = Teensy3Clock.get();
      int hr = hour(now), mn = minute(now);
      String strHr, strMin;
    
      if (hr > 12)
        hr = hr - 12;
    
      if (hr < 10)
        strHr = "0" + String(hr);
      else
        strHr = String(hr);
    
      if (mn < 10)
        strMin = "0" + String(mn);
      else
        strMin = String(mn);
    
      Rotation(1);
      tft.fillRect(284, 5, 90, 21, BACKGROUNDCLR);
      WriteText("Current Time " + strHr + ":" + strMin, 3, 50, 5, TEXTCLR);
    
      if (AM)
      {
        WriteText("PM", 3, 390, 5, BACKGROUNDCLR);
        WriteText("AM", 3, 390, 5, TEXTCLR);
      }
      else
      {
        WriteText("AM", 3, 390, 5, BACKGROUNDCLR);
        WriteText("PM", 3, 390, 5, TEXTCLR);
      }
    }
    
    /***************************************************************************************************************/
    void HourUp(int n)
    {
      time_t now = Teensy3Clock.get();
      int hr = hour(now) % 12;
    
      hr += 1;
      if (hr > 12)
      {
        hr = 1;
      }
    
      setTeensyTime(hr, minute(now), 0, 1, 1, 2021);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void HourDown(int n)
    {
      time_t now = Teensy3Clock.get();
      int hr = hour(now) % 12;
    
      hr -= 1;
      if (hr < 1)
      {
        hr = 12;
      }
    
      setTeensyTime(hr, minute(now), 0, 1, 1, 2021);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void MinuteUp(int n)
    {
      time_t now = Teensy3Clock.get();
      int mn;
    
      mn = minute(now) + 1;
      if (mn > 59)
        mn = 0;
    
      setTime(hour(now), mn, 0, 1, 1, 2020);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void MinuteDown(int n)
    {
      time_t now = Teensy3Clock.get();
      int mn;
    
      mn = minute(now) - 1;
      if (mn < 0)
        mn = 59;
    
      setTime(hour(now), mn, 0, 1, 1, 2020);
      DisplayTime();
    }
    
    /***************************************************************************************************************/
    void ClearScreen()
    {
      Rotation(1);
      tft.fillRoundRect(10, 5, 460, 315, 10, BACKGROUNDCLR);
    }
    
    /***************************************************************************************************************/
    void Press(int x, int y)
    {
      int cnt = buttonCount;
      for (int i = 0; i < cnt; i++)
      {
        if (x >= myArray[i].x && x <= myArray[i].x + myArray[i].buttonLength)
          if (y >= myArray[i].y && y <= myArray[i].y + myArray[i].buttonHeight)
          {
            myArray[i].funct(myArray[i].arg);  // call the button's function
            break;
          }
      }
      delay(150);
    }
    
    /***************************************************************************************************************/
    void GetTouch()
    {
      TSPoint p;
      Rotation(0);
      p.z = 0;
    
      // get a point
      p  = tscr.getPoint();
      if (p.z < MINPRESSURE || p.z > MAXPRESSURE)
      {
        return;
      }
    
      // Scale from ~0->1000 to tft.width using the calibration #'s
      p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
      p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
    
      int s = p.x;
      p.x = p.y;
      p.y = s;
    
      Press(p.x, p.y);
      Rotation(1);
    }
    
    /***************************************************************************************************************/
    void DrawTimeSetPage(int n)
    {
      buttonCount = 0;
      ClearScreen();
      Rotation(1);
      DisplayTime();
      WriteText("TIME SET", 2, 190, 40, REDCLR);
      CreateButton(2, 150, 80, "Hour", BUTTONCLR, TEXTCLR, HourUp, 0);
      CreateButton(2, 230, 80, "Minute", BUTTONCLR, TEXTCLR, MinuteUp, 0);
      CreateButton(2, 340, 80, "AMPM", BUTTONCLR, TEXTCLR, SwitchAMPM, 0);
    }
    
    /***************************************************************************************************************/
    void setTeensyTime(int hr,int mn,int sec,int dom, int mon, int yr) {
      tmElements_t tm;
    
      tm.Year = CalendarYrToTm(yr);
      tm.Month = mon;
      tm.Day = dom;
      tm.Hour = hr;
      tm.Minute = mn;
      tm.Second = sec;
      Teensy3Clock.set(makeTime(tm));
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •