Saturday, 26 June 2021

Arduino Clock






 Initial code using a 120x120 TFT display and a realtime clock module.






/*****************************************************************************
   The ST7789 IPS SPI display.is a 3.3v Device, do not use with a 5v Arduino
    unless you level shift.

    Display          |    Arduino
    -------------------------------------------
    VCC              |    3.3v
    GND              |    Gnd
    SCL              |    Pin 13 (SCK)
    SDA              |    Pin 11 (MOSI)
    RES              |    Pin 9
    DC               |    Pin 8
    BLK              |    Leave disconnected
 *****************************************************************************/

#include <Adafruit_GFX.h>
#include <Arduino_ST7789.h>
#include <SPI.h>
#include "RTClib.h"

#define TFT_DC    8
#define TFT_RST   9
#define TFT_MOSI  11
#define TFT_SCLK  13
#define DAYLIGHT_SAVING_PIN  5

// Clock Variables
int _Day, _OldDay = 0;
int _Hours, _OldHours = 0;
int _Minutes, _OldMinutes = 0;
int _DaylightSaving = 0;
int _xH, _yH, _OldxH, _OldyH = 0;
int _xM, _yM, _OldxM, _OldyM = 0;

Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK);   //No CS pin
RTC_DS3231 rtc;

void setup(void)
{
  pinMode(DAYLIGHT_SAVING_PIN, INPUT);                            // Setup daylight saving sw port
  digitalWrite(DAYLIGHT_SAVING_PIN, HIGH);

  // initialize the realtime clock
  rtc.begin();

  // initialize the display
  tft.init(240, 240);
  tft.setRotation(3);
  tft.fillScreen(BLACK);
  tft.setTextSize(2);
  DrawClockFace();
  DrawClockNumbers();
}

void loop()
{
  DateTime now = rtc.now();
  _Day = now.day();
  _Hours = now.hour();
  _Minutes = now.minute();

  if (digitalRead(DAYLIGHT_SAVING_PIN) == 0)
    delay(50);
  if (digitalRead(DAYLIGHT_SAVING_PIN) == 0)
    _DaylightSaving = !_DaylightSaving;

  if (_DaylightSaving == 1)
    _Hours++;

  if ((_Hours != _OldHours) || (_Minutes != _OldMinutes))
  {
    UpdateHands();
    DrawClockNumbers();
    _OldHours = _Hours;
    _OldMinutes = _Minutes;
  }

  if (_Day != _OldDay)
  {
    UpdateDate();
    _OldDay = _Day;
  }

  delay(1000);
}

void UpdateHands()
{
  //x = x0 + r * Math.Cos(theta * Math.PI / 180);
  //y = y0 + r * Math.Sin(theta * Math.PI / 180);

  //Hours hands (erase old hours hand then redraw new one)
  tft.drawLine((tft.width() / 2), (tft.height() / 2), _OldxH, _OldyH, BLACK);

  _xH = (tft.width() / 2) + 70 * cos((((30 * _Hours) + (0.5 * _Minutes)) - 90) * PI / 180);
  _yH = (tft.height() / 2) + 70 * sin((((30 * _Hours) + (0.5 * _Minutes)) - 90) * PI / 180);
  tft.drawLine((tft.width() / 2), (tft.height() / 2), _xH, _yH, WHITE);
  _OldyH = _yH;
  _OldxH = _xH;

  //Minutes hands (erase old minutes hand then redraw new one)
  tft.drawLine((tft.width() / 2), (tft.height() / 2), _OldxM, _OldyM, BLACK);

  _xM = (tft.width() / 2) + 95 * cos(((6 * _Minutes) - 90) * PI / 180);
  _yM = (tft.height() / 2) + 95 * sin(((6 * _Minutes) - 90) * PI / 180);
  tft.drawLine((tft.width() / 2), (tft.height() / 2), _xM, _yM, WHITE);
  _OldxM = _xM;
  _OldyM = _yM;

  tft.fillCircle((tft.width() / 2), (tft.height() / 2), 3, WHITE);
}

void UpdateDate()
{
  tft.setTextColor(BLACK);
  tft.setCursor(210, 220);
  tft.print(_OldDay);

  tft.setTextColor(GREEN);
  tft.setCursor(210, 220);
  tft.print(_Day);

  tft.setTextColor(WHITE);
}

void DrawClockFace()
{
  int _x1, _y1 = 0;

  //x = x0 + r * Math.Cos(theta * Math.PI / 180);
  //y = y0 + r * Math.Sin(theta * Math.PI / 180);

  tft.drawCircle((tft.width() / 2), (tft.height() / 2), 119, WHITE);
  tft.drawCircle((tft.width() / 2), (tft.height() / 2), 118, WHITE);

  // Minute marks
  for (int x = 0; x <= 60; x++)
  {
    _x1 = (tft.width() / 2) + 118 * cos(((6 * x) - 90) * PI / 180);
    _y1 = (tft.height() / 2) + 118 * sin(((6 * x) - 90) * PI / 180);
    tft.drawLine((tft.width() / 2), (tft.height() / 2), _y1, _x1, WHITE);
  }
  tft.fillCircle((tft.width() / 2), (tft.height() / 2), 110, BLACK);

  // 5 minute marks
  for (int x = 0; x <= 12; x++)
  {
    _x1 = (tft.width() / 2) + 118 * cos(((30 * x) - 90) * PI / 180);
    _y1 = (tft.height() / 2) + 118 * sin(((30 * x) - 90) * PI / 180);
    tft.drawLine((tft.width() / 2), (tft.height() / 2), _y1, _x1, WHITE);
  }
  tft.fillCircle((tft.width() / 2), (tft.height() / 2), 105, BLACK);
}

void DrawClockNumbers()
{
  tft.setTextColor(WHITE);
  tft.setCursor(163, 32);
  tft.print("1");

  tft.setCursor(196, 65);
  tft.print("2");

  tft.setCursor(210, 113);
  tft.print("3");

  tft.setCursor(199, 160);
  tft.print("4");

  tft.setCursor(164, 193);
  tft.print("5");

  tft.setCursor(115, 207);
  tft.print("6");

  tft.setCursor(70, 195);
  tft.print("7");

  tft.setCursor(35, 160);
  tft.print("8");

  tft.setCursor(20, 113);
  tft.print("9");

  tft.setCursor(33, 66);
  tft.print("10");

  tft.setCursor(66, 34);
  tft.print("11");

  tft.setCursor(109, 20);
  tft.print("12");
}