Skocz do zawartości

ESP32 Zegarek do samochodu


Radek_sl

Pomocna odpowiedź

Witam !!

Zabrałem się za stworzenie kilku wskaźników do samochodu , zacząłem od zegarka. Udaało mi się uruchomić zegarek na ESP32 Devkit V1 w połaczeniu z wyświetlaczem 1.28" na GC9A01A, wszystko pieknie, wykorzytsałem example dostępne w Arduino IDE , a dokladnie TFT_eSPI -> TFT_Clock, zmieniłem kolorystykę, dodałem cyferki i wygląda to tak jak na zdjeciu, ale teraz w czym problem, otóż zegarek cyka, ale po kilku godzinach późni się o nawet 10 minut, moge dodać RTC, ale wpadlem na inny pomysł, którego nie potrafię zrealizowac ;), w samochodzie jest router WiFi, więc chciałbym żeby zegar synchronizował się z NTP np co pół godziny. dodałem do kodu wifi, NTP i w tym momencie napotkałem ścianę, dodam że jestem kompletnie ciemny w programowaniu po 30 letniej przerwie 😉 załączam kod jeśli ktoś miałby czas i ochotę podpowiedzieć jak zrobic aby czas synchronizował się z NTP zamiast pobierać dane z godziny kompilacji. Z góry dziękuję.



/*
 An example analogue clock using a TFT LCD screen to show the time
 use of some of the drawing commands with the library.

 For a more accurate clock, it would be better to use the RTClib library.
 But this is just a demo. 
 
 This sketch uses font 4 only.

 Make sure all the display driver and pin connections are correct by
 editing the User_Setup.h file in the TFT_eSPI library folder.

 #########################################################################
 ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
 #########################################################################
 
 Based on a sketch by Gilchrist 6/2/2014 1.0
 */

#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <NTPClient.h>
#include <WiFiProv.h>
#include <WiFiUdp.h>

const char *ssid     = "Pastelowa33";
const char *password = "KamRad123";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 7200, 60000);

#define TFT_GREY 0x5AEB

TFT_eSPI tft = TFT_eSPI();       // Invoke custom library

float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;    // Saved H, M, S x & y multipliers
float sdeg=0, mdeg=0, hdeg=0;
uint16_t osx=120, osy=120, omx=120, omy=120, ohx=120, ohy=120;  // Saved H, M, S x & y coords
uint16_t x0=0, x1=0, yy0=0, yy1=0;
uint32_t targetTime = 0;                    // for next 1 second timeout

static uint8_t conv2d(const char* p); // Forward declaration needed for IDE 1.6.x
uint8_t hh=conv2d(__TIME__), mm=conv2d(__TIME__+3), ss=conv2d(__TIME__+6);  // Get H, M, S from compile time

bool initial = 1;

void setup(void) {
  tft.init();
  tft.setRotation(0);

  /*Connect to the WiFi*/
  WiFi.begin(ssid, password);
  
  tft.fillScreen(TFT_BLACK);
  tft.fillScreen(TFT_RED);
  tft.fillScreen(TFT_GREEN);
  tft.fillScreen(TFT_BLUE);
  tft.fillScreen(TFT_BLACK);
  tft.fillScreen(TFT_GREY);
  
  tft.setTextColor(TFT_WHITE, TFT_BLACK);  // Adding a background colour erases previous text automatically
  
  // Draw clock face
  tft.fillCircle(120, 120, 118, TFT_BLUE);
  tft.fillCircle(120, 120, 110, TFT_BLACK);

  // Draw 12 lines
  for(int i = 0; i<360; i+= 30) {
    sx = cos((i-90)*0.0174532925);
    sy = sin((i-90)*0.0174532925);
    x0 = sx*114+120;
    yy0 = sy*114+120;
    x1 = sx*100+120;
    yy1 = sy*100+120;

    tft.drawLine(x0, yy0, x1, yy1, TFT_BLUE);
  }

  //Draw 60 dots
  for(int i = 0; i<360; i+= 6) {
    sx = cos((i-90)*0.0174532925);
    sy = sin((i-90)*0.0174532925);
    x0 = sx*102+120;
    yy0 = sy*102+120;
    // Draw minute markers
    tft.drawPixel(x0, yy0, TFT_WHITE); 
    
    // Draw main quadrant dots
    if(i==0 || i==180) tft.fillCircle(x0, yy0, 2, TFT_WHITE);
    if(i==90 || i==270) tft.fillCircle(x0, yy0, 2, TFT_WHITE);
  }

  tft.fillCircle(120, 121, 3, TFT_WHITE);

  // Draw text at position 120,260 using fonts 4
  // Only font numbers 2,4,6,7 are valid. Font 6 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : . - a p m
  // Font 7 is a 7 segment font and only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : .
  tft.drawCentreString("12",120,22,4);
  tft.drawCentreString("1",165,30,4);
  tft.drawCentreString("2",200,60,4);
  tft.drawCentreString("3",220,110,4);
  tft.drawCentreString("4",200,150,4);
  tft.drawCentreString("5",155,185,4);
  tft.drawCentreString("6",122,198,4);
  tft.drawCentreString("7",80,185,4);
  tft.drawCentreString("8",40,150,4);
  tft.drawCentreString("9",32,110,4);
  tft.drawCentreString("10",50,60,4);
  tft.drawCentreString("11",80,30,4);
  targetTime = millis() + 1000; 
}

void loop() {
  timeClient.update();
  
  if (targetTime < millis()) {
    targetTime += 1000;
    ss++;              // Advance second
    if (ss==60) {
      ss=0;
      mm++;            // Advance minute
      if(mm>59) {
        mm=0;
        hh++;          // Advance hour
        if (hh>23) {
          hh=0;
        }
      }
    }

    // Pre-compute hand degrees, x & y coords for a fast screen update
    sdeg = ss*6;                  // 0-59 -> 0-354
    mdeg = mm*6+sdeg*0.01666667;  // 0-59 -> 0-360 - includes seconds
    hdeg = hh*30+mdeg*0.0833333;  // 0-11 -> 0-360 - includes minutes and seconds
    hx = cos((hdeg-90)*0.0174532925);    
    hy = sin((hdeg-90)*0.0174532925);
    mx = cos((mdeg-90)*0.0174532925);    
    my = sin((mdeg-90)*0.0174532925);
    sx = cos((sdeg-90)*0.0174532925);    
    sy = sin((sdeg-90)*0.0174532925);

    if (ss==0 || initial) {
      initial = 0;
      // Erase hour and minute hand positions every minute
      tft.drawLine(ohx, ohy, 120, 121, TFT_BLACK);
      ohx = hx*54+121;    
      ohy = hy*54+121;
      tft.drawLine(omx, omy, 120, 121, TFT_BLACK);
      omx = mx*79+120;    
      omy = my*79+121;
    }

      // Redraw new hand positions, hour and minute hands not erased here to avoid flicker
      tft.drawLine(osx, osy, 120, 121, TFT_BLACK);
      osx = sx*79+121;    
      osy = sy*79+121;
      tft.drawLine(osx, osy, 120, 121, TFT_WHITE);
      tft.drawLine(ohx, ohy, 120, 121, TFT_BLUE);
      tft.drawLine(omx, omy, 120, 121, TFT_BLUE);
      tft.drawLine(osx, osy, 120, 121, TFT_WHITE);

    tft.fillCircle(120, 121, 3, TFT_RED); 
  }
}

static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}

 

20230129_114311.jpg

Edytowano przez Radek_sl
  • Lubię! 2
Link do komentarza
Share on other sites

Synchronizację czasu z serwerem NTP załatwia w ESP jedna komenda:

  configTime("CET-1CEST,M3.5.0,M10.5.0/3", "tempus1.gum.gov.pl", "pl.pool.ntp.org");

Errata:

powyższa składnia jest właściwa dla ESP8266, natomiast dla ESP32 jest to:

  configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "tempus1.gum.gov.pl", "pl.pool.ntp.org");

 

gdzie pierwszy parametr to "przepis" na zmianę czasu letni/zimowy, dwa pozostałe to adresy dowolnie wybranych serwerów NTP.

Sychronizacja odbywa się w tle; po pewnym czasie (potrzebnym na sychronizację) bieżacy czas jest dostępny poprzez standardową funkcję time().

Informację, czy czas jest zsynchronizowany można otrzymać przez callback, albo sprawdzając, czy funkcja time() zwraca sensowny wynik.

Jest to jednak "Epoch time", aby uzyskać czas lokalny, uwzględniający strefę caszową, czas letni zimowy, trzeba go "przepuścić" przez funkcję localtime().

  //dla sprawdzenia działania pobieramy i drukujemy aktualny czas
  time_t rawtime;
  struct tm* timeinfo;
  time (&rawtime);
  timeinfo = localtime ( &rawtime );
  Serial.printf( "Bieżący czas i data to: %s\n", asctime(timeinfo) );

Proces działający w tle sychronizuje czas automatycznie co godzinę.

Edytowano przez jand
Errata
Link do komentarza
Share on other sites

Dzięki spróbuje to dziś wdrożyć, ale pojawia się kolejne pytanie, zegarek będzie w aucie, byłoby super gdyby jeszcze dopasował strefę czasową do miejsca w którym się znajduje, bo rozumiem funkcję localtime, ale skąd wiadomo gdzie jesteśmy?

Link do komentarza
Share on other sites

4 minuty temu, Radek_sl napisał:

ale skąd wiadomo gdzie jesteśmy?

Sprzętowo to gps.

Programowo - gdzieś widziałem kod znajdujący przybliżoną lokalizację na podstawie adresu IP przydzielonego do routera. Do strefy czasowej w zupełności wystarcza.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)
1 godzinę temu, jand napisał:

Synchronizację czasu z serwerem NTP załatwia w ESP jedna komenda:

  configTime("CET-1CEST,M3.5.0,M10.5.0/3", "tempus1.gum.gov.pl", "pl.pool.ntp.org");

 

Jak pisałem początkuję... wrzucić to do void setup? czy void loop

 

Aktualnie jest to:

uint8_t hh=conv2d(__TIME__), mm=conv2d(__TIME__+3), ss=conv2d(__TIME__+6);  // Get H, M, S from compile time

zdaje się że ta komenda pobiera czas z kompilacji. Czyli może wrzucić tam?

Edytowano przez Radek_sl
Link do komentarza
Share on other sites

Funkcję configTzTime() wywołujemy jeden raz (zamiast pobierania czasu  kompilacji), czyli w setup(), natomiat bieżące godzinę, minutę i sekundę wydłubujemy ze struktury tm przed każdorazowym wyświetleniem wskazówek zegara. Zwiększanie wartości zmiennych hh, mm, ss nie jet już oczywiście potrzebne.

Zamiast tego odczytujemy czas z systemu, np.

int hh = timeinfo->tm_hour;

i tak dalej.

Edytowano przez jand
Link do komentarza
Share on other sites

Dnia 29.01.2023 o 14:07, kostuch napisał:

Sprzętowo to gps.

Programowo - gdzieś widziałem kod znajdujący przybliżoną lokalizację na podstawie adresu IP przydzielonego do routera. Do strefy czasowej w zupełności wystarcza.

Hej, spróbujesz sobie przypomnieć gdzie to widziałeś;)?

Link do komentarza
Share on other sites

Dane dotyczące czasu lokalnego dla miejsca rejestracji naszego publicznego adresu IP są dostępne w wielu serwisach.

Jednym z prostszych (nie wymaga wcześniejszej rejestracji) jest http://worldtimeapi.org

Wysyłając zapytanie http://worldtimeapi.org/api/ip.txt   otrzymujemy tekst zawierający dane dot. czasu, z których można "wydłubać" to, co nas interesuje (np. informacje dot. strefy czasowej). Jest tam również podany bieżący czas dla naszej lokalizacji - czyli jest to jakaś alternatywa dla usług serwera NTP.

Inne serwisy (np. https://ipgeolocation.io) mogą podawać więcej danych - np. podają współrzędne geograficzne "naszego" routera (oczywiście tego u ISP, a nie w domu)

Edytowano przez jand
  • Lubię! 1
Link do komentarza
Share on other sites

kurcze, przemyślałem sprawę i jednak przeprogramuję układ, rzecz w tym że zegarek będzie w aucie, auto ma tę przypadłość że jeździ, a jak jeździ to router LTE lubi zgubić sygnał , braknie zasilania, kto wie co jeszcze, zdecydowałem że dołożę do układu RTC, i GPS, RTC będzie pilnował stabilności , a strefy i czas łykniemy z GPS, tak bedzie pewniej.... chyba. Niech mnie ktoś sprowadzi na ziemię jeśli się mylę.

 

P.S. zegarek jest maleńką częścią dużego projektu związanego z renowacją i unowocześnieniem mojego 30 letniego auta, ale to wszystko na bieżąco, zakładam że wszystko zajmie mi okolo roku, bo trzeba jeszcze w międzyczasie zarobić ecipeci;)

Link do komentarza
Share on other sites

Jak ma być GPS to inne rozwiązania rozważane powyżej (RTC, NTP itd.) stają się zbyteczne - sygnał GPS zawiera w sobie bardzo dokładny czas.

Link do komentarza
Share on other sites

GPS dostarcza czasu UTC.

Po zastanowieniu się uważam, że w Twojej sytuacji (zegar zainstalowany w samochodzie zmieniajacym strefy czasowe) najłatwiej jest skorzystać z portali dostarczaących dane geolokalizacyjne, o których pisałem poprzednio. Dostajesz gotowy czas, już uwzględniajacy lokalizację i ew. czas letni i zimowy. Sychronizacja miałaby miejsce po włączeniu zasilania i potem, co np. 1 godzinę.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.