Ceas GPS cu TM1637 / GPS clock with TM1637



#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <TM1637Display.h>

// Pinii pentru display TM1637
#define CLK 13
#define DIO 12
TM1637Display mydisplay(CLK, DIO);

// Pinii pentru GPS Neo6m (RX, TX) pe D1 Mini
// GPS TX -> D2(GPIO4) pe D1 Mini (RX ESP8266 pentru SoftwareSerial)
// GPS RX -> D1(GPIO5) - nefolosit în acest caz, poți lăsa neconectat
SoftwareSerial ss(4, 5); // RX = GPIO4 (D2), TX = GPIO5 (D1)

TinyGPSPlus gps;

void setup() {
  Serial.begin(115200);
  ss.begin(9600);

  mydisplay.setBrightness(7);
  mydisplay.clear();

  mydisplay.showNumberDec(0, false, 4, 0); // afișare inițială "0000"
}

void loop() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
  }

  if (gps.time.isValid() && gps.date.isValid()) {
    int rawHour = gps.time.hour();
    int minute = gps.time.minute();
    int year = gps.date.year();
    int month = gps.date.month();
    int day = gps.date.day();

    int hour = adjustHourForRomania(rawHour, year, month, day);

    displayTime(hour, minute);
  } else {
    // Dacă GPS-ul nu are timp valid, afișăm "----"
    mydisplay.showNumberDecEx(0xFFFF, 0, false, 4, 0);
  }
}

void displayTime(int h, int m) {
  int displayValue = h * 100 + m;

  uint8_t dots = 0b01000000; // punct la poziția digitului al doilea

  mydisplay.showNumberDecEx(displayValue, dots, true, 4, 0);
}

int adjustHourForRomania(int gpsHour, int year, int month, int day) {
  int hour = gpsHour + 2;  // fus România UTC+2 standard
  if (hour >= 24) hour -= 24;

  if (isDST(year, month, day)) {
    hour += 1;
    if (hour >= 24) hour -= 24;
  }

  return hour;
}

bool isDST(int year, int month, int day) {
  if (month < 3 || month > 10) return false;
  if (month > 3 && month < 10) return true;

  int lastSundayMarch = lastSunday(year, 3);
  int lastSundayOctober = lastSunday(year, 10);

  if (month == 3) {
    return day >= lastSundayMarch;
  }
  if (month == 10) {
    return day < lastSundayOctober;
  }
  return false;
}

int lastSunday(int year, int month) {
  int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  if (isLeapYear(year)) daysInMonth[1] = 29;
  int lastDay = daysInMonth[month - 1];

  int wday = dayOfWeek(year, month, lastDay);

  int lastSunday = lastDay - wday;
  return lastSunday;
}

int dayOfWeek(int year, int month, int day) {
  if (month < 3) {
    month += 12;
    year--;
  }
  int K = year % 100;
  int J = year / 100;
  int f = day + 13*(month + 1)/5 + K + K/4 + J/4 + 5*J;
  int d = f % 7;
  return ((d + 6) % 7);
}

bool isLeapYear(int year) {
  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}

Postări populare de pe acest blog

Vitezometru OLED / Speedometer GPS