{"id":348,"date":"2020-01-12T13:51:08","date_gmt":"2020-01-12T13:51:08","guid":{"rendered":"http:\/\/www.linuxsystems.ovh\/?p=348"},"modified":"2020-05-25T16:24:21","modified_gmt":"2020-05-25T16:24:21","slug":"samoregulujacy-sie-zegar-z-serwera-ntp","status":"publish","type":"post","link":"https:\/\/www.linuxsystems.ovh\/?p=348","title":{"rendered":"Samoreguluj\u0105cy si\u0119\u00a0zegar z serwera NTP"},"content":{"rendered":"\n<p>Do tego potrzebne nam bed\u0105:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Wy\u015bwietlacz LCD<\/li><li>Atmega (w moim przypadku by\u0142a to 328, jednak 88\/128 te\u017c powinny da\u0107 rad\u0119 )<\/li><li>ESP8266 ( ja u\u017cy\u0142em wersj\u0119 1 1MB)<\/li><li>Przej\u015bci\u00f3wka USB &lt;-> RS232<\/li><\/ul>\n\n\n\n<!--more-->\n\n\n\n<p>Schemat pod\u0142\u0105czenia:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/bucket.linuxsystems.ovh\/NTPTime\/ntptime.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>Na pocz\u0105tek instalujemy \u015brodowisko ArduinoIDE ( st\u0105d: <a href=\"https:\/\/www.arduino.cc\/en\/main\/software\">https:\/\/www.arduino.cc\/en\/main\/software<\/a> ) .<\/p>\n\n\n\n<p>Uruchamiamy ArduinoIDE i wybieramy z g\u00f3rnego menu PLIK -&gt; preferencje w polu &#8222;Dodatkowe adresy URL do menad\u017cera p\u0142ytek&#8221; wpisujemy: <a href=\"http:\/\/arduino.esp8266.com\/stable\/package_esp8266com_index.json\">http:\/\/arduino.esp8266.com\/stable\/package_esp8266com_index.json<\/a> i klikamy OK<\/p>\n\n\n\n<p>Nast\u0119pnie przechodzimy do &#8222;Narz\u0119dzia&#8221; -&gt; &#8222;P\u0142ytka &#8230;&#8221; -&gt; &#8222;Menad\u017cer p\u0142ytek&#8221; , w polu wyszukiwania wpisujemy esp8266 i naciskamy enter. Pojawia nam si\u0119 &#8222;esp8266 by ESP8266 Community&#8221; i klikamy instaluj. Czekamy a\u017c si\u0119 poprawnie si\u0119 pobierze i zainstaluje p\u0142ytka. <\/p>\n\n\n\n<p>Gdy to zostanie zrobione instalujemy potrzebne biblioteki, a wi\u0119c wchodzimy w &#8222;Narz\u0119dzia&#8221; -&gt; &#8222;Zarz\u0105dzaj bibliotekami&#8221; i instalujemy:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>NTPClient<\/li><li>Time<\/li><li>Timezone<\/li><\/ul>\n\n\n\n<p>Nast\u0119pnie wybieramy Narz\u0119dzia -&gt; P\u0142ytka -&gt; ESP8266 Generic .<\/p>\n\n\n\n<p>Wpisujemy taki kod:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;ESP8266WiFi.h>\n#include &lt;WiFiUdp.h>\n#include &lt;NTPClient.h>\n#include &lt;Time.h>\n#include &lt;TimeLib.h>\n#include &lt;Timezone.h>\n\n\/\/ W\u0142a\u015bciwo\u015bci NTP\n#define NTP_OFFSET   0\n#define NTP_INTERVAL 60 * 1000\n#define NTP_ADDRESS  \"time.coi.pw.edu.pl\"  \/\/adres serwera NTP, adresy innych serwer\u00f3w mo\u017cna znale\u017a\u0107 w internecie\n\n\nchar ssid&#91;] = \"********\";       \/\/ ssid\nchar pass&#91;] = \"********\";       \/\/ has\u0142o\n\n\/\/\/bufor ramki rs232\nbyte frame&#91;10];\nbyte frCnt = 0;\n\n\/\/flaga czekania na odbi\u00f3r ntp\nboolean waitForReply = 0;\nbyte attempt = 0;\n\n\/\/obiekty UDP i protoko\u0142u NTP\nWiFiUDP udp;\nNTPClient timeClient(udp, NTP_ADDRESS, NTP_OFFSET, NTP_INTERVAL);\n\nvoid setup()\n{\n  Serial.begin(9600);\n  \/\/Serial.println();\n  \/\/Serial.println();\n\n  \/\/ \u0141\u0105czenie\n  \/\/Serial.print(\"Connecting to \");\n  \/\/Serial.println(ssid);\n  WiFi.begin(ssid, pass);\n  \n  while (WiFi.status() != WL_CONNECTED) {\n    delay(500);\n    \/\/Serial.print(\".\");\n  }\n  \/\/Serial.println(\"\");\n  \n  \/\/Serial.println(\"WiFi connected\");\n  \/\/Serial.println(\"IP address: \");\n  \/\/Serial.println(WiFi.localIP());\n\n  \/\/Serial.println(\"Starting NTP Client\");\n  timeClient.begin();\n\n  \/\/komunikat o poprawnym po\u0142\u0105czeniu\n  Serial.print(\"ic!\\n\");\n\n}\n\nvoid loop()\n{\n  \/\/odbierz dane\n  if (Serial.available() > 0) {\n    frame&#91;frCnt] = Serial.read();\n    if (frame&#91;frCnt] == '\\n') {\n      \/\/odebrano komplern\u0105 ramk\u0119\n      if(frame&#91;2] == '?') {\n        \n        \/\/odebrano zapytanie\n        if (frame&#91;0] == 't' &amp;&amp; frame&#91;1] == 'i') {\n          \/\/odebrano zapytanie o NTP\n\n          \/\/aktualizuj dane\n          timeClient.update();\n\n          \/\/pobierz dane w formacie unix (liczba sekund od 1.01.1970, UTC)\n          unsigned long unix =  timeClient.getEpochTime();\n      \n          \/\/ biblitoeka time.h wymaga u\u017cywania formatu zmiennej time_t, dlatego tworzymy dwie zmienne (czas UTC i lokalny)...\n          time_t utc, ti;\n          \/\/..i rzutujemy czas z serwera do zmiennej\n          utc = unix;\n\n          \/\/Dane strefy czasowej wraz z regu\u0142ami zmiany czasu. W naszym przypadku b\u0119dzie to CET (zimowy) oraz CEST (letni).\n          TimeChangeRule CEST = {\"CEST\", Last, Sun, Mar, 2, 120};     \/\/Central European Summer Time\n          TimeChangeRule CET = {\"CET \", Last, Sun, Oct, 3, 60};       \/\/Central European Standard Time\n          Timezone LocalTime(CEST, CET);\n          \/\/konwersja czasu\n          ti = LocalTime.toLocal(utc);\n\n          \/\/wysy\u0142amy dane\n          Serial.print(\"ti=\");\n          Serial.print(year(ti));\n          Serial.print(\"-\");\n          if (month(ti) &lt; 10) Serial.print(\"0\");\n          Serial.print(month(ti));\n          Serial.print(\"-\");\n          if (day(ti) &lt; 10) Serial.print(\"0\");\n          Serial.print(day(ti));\n          Serial.print(\"-\");\n          \n          if (hour(ti) &lt; 10) Serial.print(\"0\");\n          Serial.print(hour(ti));\n          Serial.print(\"-\");\n          if (minute(ti) &lt; 10) Serial.print(\"0\");\n          Serial.print(minute(ti));\n          Serial.print(\"-\");\n          if (second(ti) &lt; 10) Serial.print(\"0\");\n          Serial.print(second(ti)); \n          Serial.print(\"\\n\");       \n        }\n      }\n      \/\/zeruj\n      frCnt = 0;\n    } else {\n      frCnt++;\n    }\n    \n  }\n}<\/code><\/pre>\n\n\n\n<p>(kod skopiowany z zegara nixie z majsterkowo <a href=\"https:\/\/majsterkowo.pl\/zegar-nixie-synchronizowany-z-ntp-cz-1\/\">https:\/\/majsterkowo.pl\/zegar-nixie-synchronizowany-z-ntp-cz-1\/<\/a> trzeba uzupe\u0142ni\u0107 o nazw\u0119 sieci i has\u0142o w\u0142asnej sieci Wi-Fi)<\/p>\n\n\n\n<p>Klikamy zweryfikuj, pod\u0142\u0105czamy GPIO0 do GND na esp8266 resetujemy go i klikamy wgraj.<\/p>\n\n\n\n<p>I to tyle od strony ESP8266 :).<\/p>\n\n\n\n<p>Teraz przechodzimy do Eclipse i programujemy nasz\u0105 atmeg\u0119 \ud83d\ude42<\/p>\n\n\n\n<p>tworzymy nowy projekt do kt\u00f3rego kopiujemy ju\u017c bibliotek\u0119 UART (np. z Peter Fleury), oraz do obs\u0142ugi LCD (ja u\u017cywam bibliotek\u0119 z niebieskiej ksi\u0105\u017cki Miros\u0142awa Kardasia ), jednak ta od Peter Fleury te\u017c powinna dzia\u0142a\u0107 poprawnie.<\/p>\n\n\n\n<p>Tworzymy main.c, wpisujemy:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Standard library:\n#include &lt;avr\/io.h>\n#include &lt;avr\/interrupt.h>\n#include &lt;util\/delay.h>\n#include &lt;stdlib.h>\n#include &lt;avr\/pgmspace.h>\n#include &lt;avr\/eeprom.h>\n#include &lt;string.h>\n\n\/\/ Own library\n#include \"uart\/uart.h\"\n#include \"lcd\/lcd44780.h\"\n\/\/ Global variables\n\nsigned char h;\nsigned char m;\nsigned char s;\nsigned char day;\nsigned char month;\nsigned char year;\nsigned char date&#91;15];\nvolatile uint16_t time;\nunsigned int get_data;\nchar buffor&#91;26];\nuint16_t counter = 0;\n\n#define UART_BAUD_RATE\t9600\n\n\/\/ Define functions:\nvoid initialize_screen();\nvoid initialize_wifi();\nvoid initialize_clock();\nvoid initialize_timer0();\nvoid print_time();\nvoid clock(char jumpDays);\nvoid get_uart_message();\nunsigned char computeDayNum(unsigned char y,unsigned char m);\n\n\/\/***************************** Main function: *******************************\/\nint main(void)\n{\n\t\/\/ Initialize functions\n\tinitialize_screen();\n\tinitialize_wifi();\n\tinitialize_clock();\n\tinitialize_timer0();\n\t_delay_ms(3000);\n\t\/\/ enable sei\n\tsei();\n\t\/\/ main loop\n\twhile(1)\n\t{\n\t\tget_uart_message();\n\t}\n}\n\n\/*************** Functions *******************\/\nvoid print_time(){\n\tlcd_cls();\n\tlcd_int(h);\n\tlcd_str(\":\");\n\tlcd_int(m);\n\tlcd_str(\":\");\n\tlcd_int(s);\n\tlcd_locate(1,0);\n\tlcd_int(day);\n\tlcd_str(\"-\");\n\tlcd_int(month);\n\tlcd_str(\"-20\");\n\tlcd_int(year);\n}\nvoid initialize_screen(){\n\tlcd_init();\n\tlcd_str(\"Uruchamiam\");\n}\n\nvoid initialize_wifi(){\n\tuart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));\n\tuart_puts(\"ti?\\r\\n\");\n}\n\nvoid initialize_clock(){\n\th = 0;\n\tm = 0;\n\ts = 0;\n\tyear = 19;\n\tday = 1;\n\tmonth = 1;\n}\n\nvoid initialize_timer0(){\n\t\/*\n\t * Init Timer0\n\t *\/\n\tTCCR0A |= (1&lt;&lt;WGM01);\n\tOCR0A = 77;\n\tTIMSK0 |= (1 &lt;&lt; OCIE0A);\n\tTCCR0B |= (1&lt;&lt;CS02) | (1&lt;&lt;CS00);\n}\n\nvoid clock(char jumpDays) {\n\n\tif (s >= 60) {\n\t\ts = 0;\n\t\tm++;\n\t}\n\n\tif (m >= 60) {\n\t\tm = 0;\n\t\th++;\n\t}\n\n\tif (h >= 24) {\n\t\th = 0;\n\t\tif (jumpDays) day++;\n\t}\n\n\tif (day > computeDayNum(year,month)) {\n\t\tday = 1;\n\t\tmonth++;\n\t}\n\n\tif (month > 12) {\n\t\tmonth = 1;\n\t\tif(jumpDays) year++;\n\t}\n\n\tif(year > 99) year = 0;\n\n\tif (s &lt; 0) {\n\t\ts = 59;\n\t\tm--;\n\t}\n\n\tif (m &lt; 0) {\n\t\tm = 59;\n\t\th--;\n\t}\n\n\tif (h &lt; 0) h = 23;\n\n\tif (day &lt; 1) {\n\t\tmonth--;\n\t\tday = computeDayNum(year,month);\n\t}\n\n\tif (month &lt; 1) month = 12;\n\tif (year &lt; 0) year = 99;\n}\n\nunsigned char computeDayNum(unsigned char y,unsigned char m) {\n\tif (m==4 || m==6 || m==9 || m==11) return 30;\n\telse if (m==2) {\n\t\tif (y % 4) {\n\t\t\treturn 28;\n\t\t} else {\n\t\t\treturn 29;\n\t\t}\n\t} else return 31;\n}\n\nvoid get_uart_message(){\n        do{\n                get_data = uart_getc();\n                if ( get_data &amp; UART_NO_DATA )  return;\n                else\n                {\n                        if ( get_data &amp; UART_FRAME_ERROR )      return;\n                        if ( get_data &amp; UART_OVERRUN_ERROR )    return;\n                        if ( get_data &amp; UART_BUFFER_OVERFLOW )  return;\n                }\n                buffor&#91;counter] = get_data;\n                counter++;\n        }while(get_data != '\\n');\n        counter = 0;\n\t\tyear  = (buffor&#91;5] - '0') * 10;\n\t\tyear  += buffor&#91;6] - '0';\n\n\t\tmonth = (buffor&#91;8] - '0') * 10;\n\t\tmonth += buffor&#91;9] - '0';\n\n\t\tday   = (buffor&#91;11] - '0') * 10;\n\t\tday   += buffor&#91;12] - '0';\n\n\t\th = (buffor&#91;14] - '0') * 10;\n\t\th += buffor&#91;15] - '0';\n\n\t\tm = (buffor&#91;17] - '0') * 10;\n\t\tm += buffor&#91;18] - '0';\n\n\t\ts = (buffor&#91;20] - '0') * 10;\n\t\ts += buffor&#91;21] - '0';\n}\n\n\/\/ ISR:\nISR(TIMER0_COMPA_vect){\n\ttime++;\n\tif((time%100)==0){\n\t\t\/\/ add seconds after 1 seconds\n\t\ts+=1;\n\t\tclock(1);\n\t\tprint_time();\n\t}\n\tif(time >=1000){\n\t\t\/\/ get new date after 10 seconds\n\t\tuart_puts(\"ti?\\r\\n\");\n\t\t\/\/ set time=0\n\t\ttime=0;\n\t}\n}<\/code><\/pre>\n\n\n\n<p>Kompilujemy i wgrywamy program do atmegi328 i na ekranie LCD powinien ukaza\u0107 si\u0119 aktualna data i godzina.<\/p>\n\n\n\n<p>w razie jakichkolwiek pyta\u0144, prosz\u0119 o komentarz.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Do tego potrzebne nam bed\u0105: Wy\u015bwietlacz LCD Atmega (w moim przypadku by\u0142a to 328, jednak 88\/128 te\u017c powinny da\u0107 rad\u0119 ) ESP8266 ( ja u\u017cy\u0142em wersj\u0119 1 1MB) Przej\u015bci\u00f3wka USB &lt;-> RS232<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32],"tags":[],"class_list":["post-348","post","type-post","status-publish","format-standard","hentry","category-atmega"],"_links":{"self":[{"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=\/wp\/v2\/posts\/348","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=348"}],"version-history":[{"count":7,"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=\/wp\/v2\/posts\/348\/revisions"}],"predecessor-version":[{"id":502,"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=\/wp\/v2\/posts\/348\/revisions\/502"}],"wp:attachment":[{"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.linuxsystems.ovh\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}