{"id":723,"date":"2016-08-23T13:32:16","date_gmt":"2016-08-23T11:32:16","guid":{"rendered":"http:\/\/ignus.co.pl\/blog\/?p=723"},"modified":"2016-08-23T13:37:40","modified_gmt":"2016-08-23T11:37:40","slug":"arduino-budujemy-zegarek-z-budzikiem-i-pomiarem-temperatury","status":"publish","type":"post","link":"http:\/\/ignus.co.pl\/blog\/?p=723","title":{"rendered":"Budujemy zegarek z budzikiem i pomiarem temperatury z pomoc\u0105 Arduino"},"content":{"rendered":"<h3><strong>Wst\u0119p<\/strong><\/h3>\n<p>W tym artykule dowiemy si\u0119 jak zbudowa\u0107 z pomoc\u0105 p\u0142ytki Arduino cyfrowy zegarek, kt\u00f3ry b\u0119dzie spe\u0142nia\u0142 nast\u0119puj\u0105ce za\u0142o\u017cenia:<\/p>\n<ul>\n<li>odmierzanie czasu\u00a0po od\u0142\u0105czeniu zasilania (zegar RTC z bateri\u0105)<\/li>\n<li>sygna\u0142 d\u017awi\u0119kowy co godzin\u0119<\/li>\n<li>wy\u015bwietlanie daty<\/li>\n<li>funkcjonalno\u015b\u0107 budzika<\/li>\n<li>mierzenie\u00a0temperatury otoczenia<\/li>\n<li>r\u00f3\u017cne ekrany do wy\u015bwietlania (data + czas + temperatura, du\u017cy zegar itp.)<\/li>\n<li>zapisywanie ustawie\u0144 w pami\u0119ci (w tym wypadku wolne miejsce w zegarze RTC)<\/li>\n<li>mo\u017cliwo\u015b\u0107 r\u0119cznego ustawienia zegarka<\/li>\n<li>mo\u017cliwo\u015b\u0107 wybrania melodyjki alarmu \/ budzika<\/li>\n<li>wy\u015bwietlacz alfanumeryczny<\/li>\n<li>funkcjonalne menu do wyboru wszystkich ustawie\u0144<\/li>\n<\/ul>\n<p>Wydaje si\u0119 sporo, ale projekt taki jest idealn\u0105 okazj\u0105 do po\u0107wiczenia platformy Arduino, czujnik\u00f3w cyfrowych, optymalizacji oprogramowania, obs\u0142ugi wy\u015bwietlaczy LCD.<\/p>\n<h3>Co b\u0119dzie potrzebne?<\/h3>\n<p>Z powodu oszcz\u0119dno\u015bci czasu jak i poziomu nadmiernej kabelkologii zdecydowa\u0142em si\u0119 w wi\u0119kszo\u015bci na gotowe modu\u0142y.<\/p>\n<ul>\n<li>Arduino Uno &#8211; orygina\u0142 lub klon, wa\u017cne \u017ceby mia\u0142 wyj\u015bcia \/ wej\u015bcia w tych samym miejscu co orygina\u0142, wraz kablem USB do wgrania software&#8217;u i ewentualnym zasilaczem.<\/li>\n<li>LCD Keypad Shield &#8211; widzia\u0142em kilka odmian, wi\u0119kszo\u015b\u0107 jest niemal\u017ce identyczna, najpopularniejsza jest wersja od DFROBOT &#8211; do kupienia oficjalnie <a href=\"http:\/\/www.dfrobot.com\/index.php?route=product\/product&amp;product_id=51#.V6Rt_9KLRQI\">TUTAJ<\/a>, ja u\u017cywam chi\u0144skiego zamiennika znalezionego na Allegro (pod has\u0142em &#8222;lcd keypad&#8221;).\u00a0Jest to bardzo fajny shield do Arduino posiadaj\u0105cy dok\u0142adnie takie rzeczy, kt\u00f3re s\u0105 potrzebne do projektu &#8211; wy\u015bwietlacz 2&#215;16 znak\u00f3w, zestaw przycisk\u00f3w to nawigacji po menu, zajmuje niewiele we \/ wy \u00a0w Arduino i co najwa\u017cniejsze udost\u0119pnia wolne piny na zewn\u0105trz shielda<\/li>\n<li>Obudowa &#8211; nie jest niezb\u0119dna, ale dzi\u0119ki temu mo\u017cna zegarek postawi\u0107 pionowo, chroni przed upadkami i s\u0142u\u017cy jako miejsce zaczepu czujnik\u00f3w. Jedyna rzecz, kt\u00f3ra nie pasowa\u0142a w obudowie do mojej wersji shielda to dolna jej cz\u0119\u015b\u0107 (prostok\u0105tna wk\u0142adka), kt\u00f3ra nie pasowa\u0142a ze wzgl\u0119du na wystaj\u0105ce elementy. Nie jest ona potrzebna, ca\u0142o\u015b\u0107 trzyma si\u0119 bez problemu na pozosta\u0142ych bokach. Obudowa dla Arduino z tym shieldem dost\u0119pna jest <a href=\"https:\/\/botland.com.pl\/obudowy-do-arduino\/3850-obudowa-do-arduino-uno-z-lcd-keypad-shield.html?search_query=lcd+keypad+obudowa&amp;results=1\">TUTAJ<\/a><\/li>\n<li>Przyciski (tact switch) analogowe, sto\u017ckowe, sztuk 6. W swoim shieldzie podmieni\u0142em wszystkie fabryczne przyciski na d\u0142u\u017csze odpowiedniki. Fabryczne s\u0105 za kr\u00f3tkie \u017ceby je wcisn\u0105\u0107 palcem, przeszkadza obudowa. Ewentualnie 6 sztuk cienkich nasadek, kt\u00f3re b\u0119d\u0105 pasowa\u0107\u00a0(6&#215;6 mm). Oczywi\u015bcie do wymiany potrzebna b\u0119dzie lutownica i spoiwo.<\/li>\n<li>Modu\u0142 RTC z zasilaniem bateryjnym &#8211; b\u0119dzie podtrzymywa\u0107 godzin\u0119 nawet po od\u0142\u0105czeniu od zasilania, a gdy pod\u0142\u0105czy\u0107 ca\u0142y projekt pod zasilanie bateryjne, b\u0119dzie s\u0142u\u017cy\u0142 nawet w wypadku braku pr\u0105du. Postanowi\u0142em r\u00f3wnie\u017c u\u017cy\u0107 go jako miejsce przechowywania ustawie\u0144 (jest troch\u0119 miejsca dost\u0119pnego w uk\u0142adzie na w\u0142asne dane). Ja u\u017cy\u0142em gotowego modu\u0142u z uk\u0142adem DS1307 , dost\u0119pnego <a href=\"https:\/\/botland.com.pl\/moduly-rtc\/2717-modul-rtc-ds1307-bateria-msx.html?search_query=rtc&amp;results=57\">TUTAJ<\/a><\/li>\n<li>Zestaw kabelk\u00f3w po\u0142\u0105czeniowych, \u017ce\u0144sko &#8211; \u017ce\u0144skich (lub jakichkolwiek innych, mo\u017cna lutowa\u0107 bezpo\u015brednio do pin\u00f3w), 9 sztuk<\/li>\n<li>Czujnik temperatury i wilgotno\u015bci DHT22. Do po\u0142\u0105czenia go z Arduino b\u0119dzie potrzebny dodatkowo jeden rezystor w przedziale\u00a04.7K &#8211; 10K\u03a9<\/li>\n<li>Buzzer &#8211; najzwyklejszy &#8222;brz\u0119czyk&#8221; 2 pinowy<\/li>\n<\/ul>\n<h3>FAQ<\/h3>\n<p>Przed przyst\u0105pieniem do w\u0142a\u015bciwego projektu par\u0119 odpowiedzi:<\/p>\n<p>Czemu gotowe rozwi\u0105zania, a nie na przyk\u0142ad pod\u0142\u0105czanie LCD bezpo\u015brednio do Arduino?<\/p>\n<ul>\n<li>oszcz\u0119dno\u015b\u0107\u00a0czasu<\/li>\n<\/ul>\n<p>Czemu kabelki s\u0105 nie wierzchu i nie s\u0105 polutowane do p\u0142ytek?<\/p>\n<ul>\n<li>ze wzgl\u0119du na eksperymenty chcia\u0142em mie\u0107 mo\u017cliwo\u015b\u0107 szybkiego demonta\u017cu obudowy, wyj\u0119cia ich w razie potrzeby, podmiany<\/li>\n<\/ul>\n<h3>Krok 1. LCD.<\/h3>\n<p>Wsadzamy shielda do Arduino i testujemy czy wy\u015bwietlacz oraz przyciski dzia\u0142aj\u0105 bez problemu. Po wsadzeniu shielda, wgrywamy prosty program \u017ceby si\u0119 upewni\u0107 czy droga wolna:<\/p>\n<pre class=\"lang:c++ decode:true\">#include &lt;LiquidCrystal.h&gt;\r\n \r\nLiquidCrystal lcd(8, 9, 4, 5, 6, 7);           \/\/ select the pins used on the LCD panel\r\n \r\n\/\/ define some values used by the panel and buttons\r\nint lcd_key     = 0;\r\nint adc_key_in  = 0;\r\n \r\n#define btnRIGHT  0\r\n#define btnUP     1\r\n#define btnDOWN   2\r\n#define btnLEFT   3\r\n#define btnSELECT 4\r\n#define btnNONE   5\r\n \r\nint read_LCD_buttons(){               \/\/ read the buttons\r\n    adc_key_in = analogRead(0);       \/\/ read the value from the sensor \r\n \r\n    \/\/ my buttons when read are centered at these valies: 0, 144, 329, 504, 741\r\n    \/\/ we add approx 50 to those values and check to see if we are close\r\n    \/\/ We make this the 1st option for speed reasons since it will be the most likely result\r\n \r\n    if (adc_key_in &gt; 1000) return btnNONE; \r\n \r\n    \/\/ For V1.1 us this threshold\r\n    if (adc_key_in &lt; 50)   return btnRIGHT;  \r\n    if (adc_key_in &lt; 250)  return btnUP; \r\n    if (adc_key_in &lt; 450)  return btnDOWN; \r\n    if (adc_key_in &lt; 650)  return btnLEFT; \r\n    if (adc_key_in &lt; 850)  return btnSELECT;  \r\n \r\n   \/\/ For V1.0 comment the other threshold and use the one below:\r\n   \/*\r\n     if (adc_key_in &lt; 50)   return btnRIGHT;  \r\n     if (adc_key_in &lt; 195)  return btnUP; \r\n     if (adc_key_in &lt; 380)  return btnDOWN; \r\n     if (adc_key_in &lt; 555)  return btnLEFT; \r\n     if (adc_key_in &lt; 790)  return btnSELECT;   \r\n   *\/\r\n \r\n    return btnNONE;                \/\/ when all others fail, return this.\r\n}\r\n \r\nvoid setup(){\r\n   lcd.begin(16, 2);               \/\/ start the library\r\n   lcd.setCursor(0,0);             \/\/ set the LCD cursor   position \r\n   lcd.print(\"Push the buttons\");  \/\/ print a simple message on the LCD\r\n}\r\n  \r\nvoid loop(){\r\n   lcd.setCursor(9,1);             \/\/ move cursor to second line \"1\" and 9 spaces over\r\n   lcd.print(millis()\/1000);       \/\/ display seconds elapsed since power-up\r\n \r\n   lcd.setCursor(0,1);             \/\/ move to the begining of the second line\r\n   lcd_key = read_LCD_buttons();   \/\/ read the buttons\r\n \r\n   switch (lcd_key){               \/\/ depending on which button was pushed, we perform an action\r\n \r\n       case btnRIGHT:{             \/\/  push button \"RIGHT\" and show the word on the screen\r\n            lcd.print(\"RIGHT \");\r\n            break;\r\n       }\r\n       case btnLEFT:{\r\n             lcd.print(\"LEFT   \"); \/\/  push button \"LEFT\" and show the word on the screen\r\n             break;\r\n       }    \r\n       case btnUP:{\r\n             lcd.print(\"UP    \");  \/\/  push button \"UP\" and show the word on the screen\r\n             break;\r\n       }\r\n       case btnDOWN:{\r\n             lcd.print(\"DOWN  \");  \/\/  push button \"DOWN\" and show the word on the screen\r\n             break;\r\n       }\r\n       case btnSELECT:{\r\n             lcd.print(\"SELECT\");  \/\/  push button \"SELECT\" and show the word on the screen\r\n             break;\r\n       }\r\n       case btnNONE:{\r\n             lcd.print(\"NONE  \");  \/\/  No action  will show \"None\" on the screen\r\n             break;\r\n       }\r\n   }\r\n}<\/pre>\n<p><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/lcd_keypad_test.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-744 size-large\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/lcd_keypad_test-700x394.jpg\" alt=\"lcd_keypad_test\" width=\"700\" height=\"394\" srcset=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/lcd_keypad_test-700x394.jpg 700w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/lcd_keypad_test-250x141.jpg 250w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/lcd_keypad_test-768x432.jpg 768w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/lcd_keypad_test-120x68.jpg 120w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/a><\/p>\n<p>Je\u017celi wszystkie przyciski oraz wy\u015bwietlacz dzia\u0142aj\u0105 prawid\u0142owo, mo\u017cemy wst\u0119pnie zamontowa\u0107 obudow\u0119 (nie dokr\u0119caj\u0105c wszystkie do ko\u0144ca. Mo\u017cna r\u00f3wnie\u017c dostosowa\u0107 kontrast wy\u015bwietlacza do naszych wymaga\u0144. S\u0142u\u017cy do tego potencjometr w lewym g\u00f3rnym rogu p\u0142ytki (p\u0142aski i cienki \u015brubokr\u0119t powinie sobie poradzi\u0107).<\/p>\n<h3>Krok 2. RTC.<\/h3>\n<p>Sw\u00f3j zegar czasu rzeczywistego pod\u0142\u0105czy\u0142em\u00a0wed\u0142ug schematu:<\/p>\n\n<table id=\"tablepress-6\" class=\"tablepress tablepress-id-6\">\n<thead>\n<tr class=\"row-1 odd\">\n\t<th class=\"column-1\">Pin LCD Shield \/ Arduino<\/th><th class=\"column-2\">Pin RTC<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-hover\">\n<tr class=\"row-2 even\">\n\t<td class=\"column-1\">A5 (SCL)<\/td><td class=\"column-2\">3 (SCL)<\/td>\n<\/tr>\n<tr class=\"row-3 odd\">\n\t<td class=\"column-1\">A4 (SDA)<\/td><td class=\"column-2\">2 (SDA)<\/td>\n<\/tr>\n<tr class=\"row-4 even\">\n\t<td class=\"column-1\">GND<\/td><td class=\"column-2\">1 (GND)<\/td>\n<\/tr>\n<tr class=\"row-5 odd\">\n\t<td class=\"column-1\">5V<\/td><td class=\"column-2\">5 (5V)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<!-- #tablepress-6 from cache -->\n<p>Po zamontowaniu uk\u0142adu, testujemy czy wszystko dzia\u0142a poprzez kod:<\/p>\n<pre class=\"lang:c++ decode:true\">    #include \"RTClib.h\"        \/\/ biblioteka uk\u0142adu RTC DS1307\r\n    #include &lt;Wire.h&gt;\r\n    RTC_DS1307    RTC;\r\n     \r\n    void setup()\r\n    {\r\n       Serial.begin(9600);  \/\/ otworzenie portu szeregowego     \r\n       RTC.begin();         \/\/ inicjalizujemy zegar RTC\r\n       RTC.adjust(DateTime(__DATE__, __TIME__)); \/\/ pierwsze ustawienie zegarka, jezeli bateria dziala dobrze wystarczy zrobi\u0107 to raz\r\n    }\r\n     \r\n    void loop()\r\n    {\r\n      DateTime now = RTC.now();\r\n    \r\n      Serial.print(now.year(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(now.month(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(now.day(), DEC);\r\n      Serial.print(' ');\r\n      Serial.print(now.hour(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(now.minute(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(now.second(), DEC);\r\n      Serial.println();\r\n    \r\n      Serial.print(F(\" since 1970 = \"));\r\n      Serial.print(now.unixtime());\r\n      Serial.print(F(\"s = \"));\r\n      Serial.print(now.unixtime() \/ 86400L);\r\n      Serial.println(F(\"d\"));\r\n    \r\n      DateTime future (now.unixtime() + 7 * 86400L + 30);\r\n    \r\n      Serial.print(F(\" now + 7d + 30s: \"));\r\n      Serial.print(future.year(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(future.month(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(future.day(), DEC);\r\n      Serial.print(' ');\r\n      Serial.print(future.hour(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(future.minute(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(future.second(), DEC);\r\n      Serial.println();\r\n\r\n      delay(1000);\r\n    }<\/pre>\n<p><span style=\"color: #ff0000;\">Do poprawnego dzia\u0142ania modu\u0142u RTC\u00a0potrzebna jest zewn\u0119trzna biblioteka opisana w kroku 5.<\/span><\/p>\n<p>Uruchamiamy szeregowy monitor i powinni\u015bmy zobaczy\u0107:<\/p>\n<p><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_arduino_studio.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-733 size-full\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_arduino_studio.jpg\" alt=\"rtc_arduino_studio\" width=\"659\" height=\"475\" srcset=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_arduino_studio.jpg 659w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_arduino_studio-250x180.jpg 250w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_arduino_studio-120x86.jpg 120w\" sizes=\"(max-width: 659px) 100vw, 659px\" \/><\/a><\/p>\n<p>Przyk\u0142adowe zamontowanie:<\/p>\n<p><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_montaz.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-742 size-large\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_montaz-700x394.jpg\" alt=\"dht22_montaz\" width=\"700\" height=\"394\" srcset=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_montaz-700x394.jpg 700w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_montaz-250x141.jpg 250w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_montaz-768x432.jpg 768w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_montaz-120x68.jpg 120w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/a><\/p>\n<p>Z ca\u0142\u0105 pewno\u015bci\u0105 mo\u017cna to zrobi\u0107 lepiej, czujnik DHT22 jest przyczepiony za pomoc\u0105 \u015br\u00f3bki do wycietego otw\u00f3ru na doln\u0105 cz\u0119\u015b\u0107 obudowy.<\/p>\n<h3>Krok 3. Temperatura.<\/h3>\n<p>Modu\u0142 DHT22 pod\u0142\u0105czamy jak na schemacie:<\/p>\n\n<table id=\"tablepress-7\" class=\"tablepress tablepress-id-7\">\n<thead>\n<tr class=\"row-1 odd\">\n\t<th class=\"column-1\">Pin Shield \/ Arduino<\/th><th class=\"column-2\">Pin DHT22<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-hover\">\n<tr class=\"row-2 even\">\n\t<td class=\"column-1\">5V (kt\u00f3rykolwiek pin w g\u00f3rnym rz\u0119dzie, w prawej dolnej cz\u0119\u015bci shielda)<\/td><td class=\"column-2\">1 (VCC)<\/td>\n<\/tr>\n<tr class=\"row-3 odd\">\n\t<td class=\"column-1\">D2 (g\u00f3rny rz\u0105d pin\u00f3w na shieldzie, 5 od prawej)<\/td><td class=\"column-2\">2 (Data)<\/td>\n<\/tr>\n<tr class=\"row-4 even\">\n\t<td class=\"column-1\">GND (kt\u00f3rykolwiek pin w \u015brodkowym rz\u0119dzie, w prawej dolnej cz\u0119\u015bci shielda)<\/td><td class=\"column-2\">4 (GND)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<!-- #tablepress-7 from cache -->\n<p><span style=\"color: #ff0000;\">UWAGA: Pomi\u0119dzy pinem zasilaj\u0105cym i pinem od przesy\u0142u danych nale\u017cy zamontowa\u0107 rezystor z przedzia\u0142u\u00a04.7K &#8211; 10K\u03a9<\/span><\/p>\n<p>Testujemy kodem:<\/p>\n<pre class=\"lang:c++ decode:true\">    #include \"DHT.h\"          \/\/ biblioteka sensor\u00f3w DHTxx\r\n     \r\n    #define DHTPIN 2          \/\/ pin do komunikacji\r\n     \r\n    DHT dht;\r\n     \r\n    void setup()\r\n    {\r\n      Serial.begin(9600);     \/\/ otworzenie portu szeregowego\r\n      dht.setup(DHTPIN);           \/\/ inicjalizacja czujnika\r\n    }\r\n     \r\n    void loop()\r\n    {\r\n        float t = dht.getTemperature();  \/\/ odczyt temperatury\r\n        float h = dht.getHumidity();     \/\/ odczyt wilgotno\u015bci powietrza\r\n     \r\n      \/\/ czy odczytano warto\u015bci?\r\n      if (isnan(t) || isnan(h))\r\n      {\r\n        \/\/ NIE -&gt; informacja o b\u0142\u0119dzie\r\n        Serial.println(\"&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;Blad odczytu danych z czujnika!\");\r\n      }\r\n      else\r\n      {\r\n        \/\/ TAK -&gt; wysy\u0142amy wyniki przez port szeregowy\r\n        Serial.print(\"Wilgotnosc: \");\r\n        Serial.print(h);\r\n        Serial.print(\" % \");\r\n        Serial.print(\"Temperatura: \");\r\n        Serial.print(t);\r\n        Serial.println(\" *C\");\r\n      }\r\n      \r\n      delay(1000);    \/\/ op\u00f3\u017anienie\r\n    }<\/pre>\n<p><span style=\"color: #ff0000;\">Do poprawnego dzia\u0142ania czujnika potrzebna jest zewn\u0119trzna biblioteka opisana w kroku 5.<\/span><\/p>\n<p>Je\u017celi wszystko pod\u0142\u0105czyli\u015bmy dobrze to w monitorze szeregowym w Arduino Studio powinni\u015bmy otrzyma\u0107:<\/p>\n<p><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_arduino_studio.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-731 size-full\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_arduino_studio.jpg\" alt=\"dht22_arduino_studio\" width=\"655\" height=\"472\" srcset=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_arduino_studio.jpg 655w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_arduino_studio-250x180.jpg 250w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/dht22_arduino_studio-120x86.jpg 120w\" sizes=\"(max-width: 655px) 100vw, 655px\" \/><\/a><\/p>\n<p>Przyk\u0142ad monta\u017cu (zdj\u0119cie od g\u00f3ry):<\/p>\n<p><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_montaz.jpg\"><img loading=\"lazy\" class=\"alignnone wp-image-745 size-large\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_montaz-700x394.jpg\" alt=\"rtc_montaz\" width=\"700\" height=\"394\" srcset=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_montaz-700x394.jpg 700w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_montaz-250x141.jpg 250w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_montaz-768x432.jpg 768w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/rtc_montaz-120x68.jpg 120w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/a><\/p>\n<h3>Krok 4. Buzzer.<\/h3>\n<p>N\u00f3\u017ck\u0119 oznaczon\u0105 minusem na buzzerze pod\u0142\u0105czamy do jakiegolwiek pinu GND na shieldzie (prawy dolny r\u00f3g shielda &#8211; \u015brodkowy rz\u0105d), natomiast t\u0105 z plusem do pinu D13 (g\u00f3rny rz\u0105d pin\u00f3w, 9 od prawej, przy przerwie mi\u0119dzy rz\u0119dami pin\u00f3w)<\/p>\n<p>Przy ka\u017cdym w\u0142\u0105czeniu \/ resecie arduino, przy poprawnym pod\u0142\u0105czeniu, buzzer powinien wyda\u0107 kr\u00f3tki d\u017awi\u0119k.<\/p>\n<h3>Krok 5. W\u0142a\u015bciwe oprogramowanie.<\/h3>\n<p>Kod przez wszystkie funkcjonalno\u015bci jest do\u015b\u0107 d\u0142ugi, ale stara\u0142em si\u0119 komentowa\u0107 wszystkie wa\u017cniejsze rzeczy. Nie b\u0119d\u0119 przez to opisywa\u0107 poszczeg\u00f3lnych sk\u0142adowych, zapraszam do eksperymentowania. Do poprawnego dzia\u0142ania skryptu potrzebne s\u0105 biblioteki:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/adafruit\/DHT-sensor-library\">DHT-sensor-library<\/a>\u00a0(wrzucamy katalog &#8222;DHT&#8221; do &#8222;sketchfolder\/libraries\/&#8221; w miejscu gdzie Arduino Studio przechowuje dane lub bezpo\u015brednio poprzez IDE &#8211; Sketch -&gt; Include library -&gt; Add .zip library)<\/li>\n<li><a href=\"https:\/\/github.com\/adafruit\/RTClib\">RTClib<\/a>\u00a0(wrzucamy katalog &#8222;RTClib-master&#8221; do &#8222;sketchfolder\/libraries\/&#8221; w miejscu gdzie Arduino Studio przechowuje dane lub bezpo\u015brednio poprzez IDE &#8211; Sketch -&gt; Include library -&gt; Add .zip library)<\/li>\n<\/ul>\n<p>Biblioteki &#8222;LiquidCrystal&#8221; i &#8222;Wire&#8221; s\u0105 dost\u0119pne domy\u015blnie.<\/p>\n<p>Stara\u0142em si\u0119 zoptymalizowa\u0107 kod jak tylko si\u0119 da (funkcja &#8222;F()&#8221; w outputach stringowych itp.), ale na Arduino UNO jest ju\u017c do\u015b\u0107 blisko limitu 32 KB.<\/p>\n<p>G\u0142\u00f3wny szkic:<\/p>\n<pre class=\"lang:c++ decode:true\">\/*\r\n * Za\u0142\u0105czamy wszystkie potrzebne biblioteki\r\n *\/\r\n\r\n#include \"DHT.h\"           \/\/ biblioteka sensora DHT22\r\n#include \"RTClib.h\"        \/\/ biblioteka uk\u0142adu RTC DS1307\r\n#include \"bigfont.h\"       \/\/ nasza biblioteka z fontami potrzebnymi do du\u017cego zegarka\r\n#include &lt;LiquidCrystal.h&gt; \/\/ biblioteka do sterowania LCD\r\n#include &lt;Wire.h&gt;          \/\/ biblioteka u\u017cywana m. in. przez sensor DHT22\r\n\r\n\/*\r\n * Sta\u0142e wykorzystywane w programie\r\n *\/\r\n\r\n#define DHTPIN        2     \/\/ pin od czujnika temperatury\r\n#define BUZZERPIN     13    \/\/ pin od brz\u0119czyka\r\n#define BACKLIGHTPIN  10    \/\/ pin od pod\u015bwietlania LCD\r\n#define VERSION       \"1.0\" \/\/ wersja skryptu\r\n#define MENUITEMS     8     \/\/ ilo\u015b\u0107 opcji menu g\u0142\u00f3wnego do wyboru\r\n\r\n\/*\r\n * Definicje przycisk\u00f3w na shieldzie\r\n *\/\r\n\r\n#define btnRIGHT  0\r\n#define btnUP     1\r\n#define btnDOWN   2\r\n#define btnLEFT   3\r\n#define btnSELECT 4\r\n#define btnNONE   5\r\n\r\n\/*\r\n * Dwie dodatkowe metody steruj\u0105ce pod\u015bwietleniem\r\n *\/\r\n\r\n#define LCDbacklight() pinMode(BACKLIGHTPIN, INPUT)    \/\/ w\u0142\u0105cz pod\u015bwietlanie\r\n#define LCDnoBacklight() pinMode(BACKLIGHTPIN, OUTPUT) \/\/ wy\u0142\u0105cz pod\u015bwietlanie\r\n\r\n\/*\r\n * Inicjalizacja potrzebnych bibliotek\r\n *\/\r\n \r\nRTC_DS1307    RTC;\r\nDHT           dht;\r\nLiquidCrystal lcd(8, 9, 4, 5, 6, 7);\r\n\r\n\/*\r\n * Zmienne globalne u\u017cywane przez program\r\n *\/\r\n\r\nint analogKeyValue   = 0;     \/\/ Warto\u015b\u0107 analogowa po wci\u015bni\u0119ciu danego przycisku\r\nint pressedKey       = 0;     \/\/ Wci\u015bniety przycisk\r\nint currentMenuItem  = 0;     \/\/ Obecnie wybrana pozycja menu g\u0142\u00f3wnego\r\nchar lastState       = 0;     \/\/ Poprzedni status menu g\u0142\u00f3wnego\r\nchar customDigitX    = 0;     \/\/ Pozycja kursora u\u017cywana w przypadku du\u017cego zegarka\r\nboolean showJukebox  = false; \/\/ Czy pokazywa\u0107 odtwarzacz melodyjek\r\nuint8_t defaultPreferences[10] = { 0x01, 0x01, 0xA, 0x16, 0x00, 0xC, 0x00, 0x00, 0x01, 0x01 }; \/\/ Domy\u015blne ustawienia, wysy\u0142ane do NVRAM podczas przywracania domy\u015bnych preferencji z menu\r\n\r\n\/*\r\n * Zmienne odczytywane z NVRAM uk\u0142adu RTC DS1307\r\n *\/\r\n\r\nchar keySounds = 0;           \/\/ D\u017awi\u0119k klawiszy w\u0142\u0105czony (1 - Tak, 0 - Nie)\r\nchar hourlyAlarmEnabled = 0;  \/\/ D\u017awi\u0119k co godzin\u0119 w\u0142\u0105czony (1 - Tak, 0 - Nie)\r\nchar hourlyAlarmFrom = 0;     \/\/ D\u017awi\u0119k co godzin\u0119 od godziny (0 - 23)\r\nchar hourlyAlarmTo = 0;       \/\/ D\u017awi\u0119k co godzin\u0119 do godziny (0 - 23)\r\nchar alarmEnabled = 0;        \/\/ Budzik w\u0142\u0105czony (1 - Tak, 0 - Nie)\r\nchar alarmHour = 0;           \/\/ Godzina alarmu budzika (0 - 23)\r\nchar alarmMinute = 0;         \/\/ Minuta alarmu budzika (0 - 59)\r\nchar debug = 0;               \/\/ Pokazuj dodatkowe informacje w serial monitorze (1 - Tak, 0 - Nie)\r\nchar showIntro = 0;           \/\/ Pokazuj ekran powitalny (1 - Tak, 0 - Nie)\r\nchar alarmMelody = 0;         \/\/ Wybierz melodyjk\u0119 budzika (0 - X)\r\n\r\n\/*\r\n * Nazwy dnia tygodnia potrzebny przy opcji \"Czas i data\"\r\n *\/\r\n\r\nchar daysOfTheWeek[7][12] = {\"Nie\", \"Pon\", \"Wt\", \"Sr\", \"Czw\", \"Pt\", \"Sb\"};\r\n\r\n\/*\r\n * Zmienna steruj\u0105ca wy\u015bwietlaniem intra\r\n *\/\r\n\r\nboolean splash = true;\r\n\r\n\/*\r\n * Zmienne potrzebne do odtwarzania melodyjek alarmowych. Domy\u015blnie ustawiona\r\n * melodia \"Twinkle, twinkle...\"\r\n *\/\r\n\r\nchar notes[] = \"ccggaag ffeeddc ggffeed ggffeed ccggaag ffeeddc \";\r\nint beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };\r\nint tempo = 300;\r\nchar length = 15; \/\/ the number of notes\r\n\r\nvoid setup() {\r\n\r\n  \/*\r\n   * Tworzymy fonty potrzebne do du\u017cego zegarka\r\n   *\/\r\n   \r\n   lcd.createChar(0,LT);\r\n   lcd.createChar(1,UB);\r\n   lcd.createChar(2,RT);\r\n   lcd.createChar(3,LL);\r\n   lcd.createChar(4,LB);\r\n   lcd.createChar(5,LR);\r\n   lcd.createChar(6,UMB);\r\n   lcd.createChar(7,LMB);\r\n   \r\n   Serial.begin(9600);\r\n   lcd.begin(16, 2);    \/\/ Inicjalizujemy wy\u015bwietlacz 16x2\r\n   Wire.begin();         \r\n   RTC.begin();         \/\/ Inicjalizujemy zegar RTC\r\n\r\n  \/*\r\n   * Je\u017celi ustawili\u015bmy w menu g\u0142\u00f3wnym aktualizacj\u0119 zegarka z komputera\r\n   * to odczytujemy konkretn\u0105 warto\u015b\u0107 odpowiedzialn\u0105 za ten fakt, ustawiamy\r\n   * zegarek i ustawiamy flag\u0119 na 0, \u017ceby po kolejnym restarcie zegarek nam\r\n   * si\u0119 nie ustawia\u0142\r\n   *\/\r\n\r\n   if (RTC.readnvram(50) == 1) {\r\n    Serial.println(F(\"Nastawiam zegarek\"));\r\n    RTC.adjust(DateTime(__DATE__, __TIME__));\r\n    RTC.writenvram(50, 0);\r\n   }\r\n    \r\n   pinMode(BUZZERPIN, OUTPUT); \/\/ Inicjalizacja buzzera\r\n   readPreferences();          \/\/ Odczytujemy ustawienia z NVRAMu zegarka\r\n\r\n   \/*\r\n    * Sprawdzamy czy uk\u0142ad RTC dzia\u0142a poprawnie\r\n    *\/\r\n\r\n   if (! RTC.isrunning() &amp;&amp; debug == 1) {\r\n    Serial.println(F(\"RTC is NOT running!\"));\r\n   }\r\n\r\n   \/*\r\n    * Je\u017celi mamy w\u0142\u0105czone debugowanie to wy\u015bwietl wszystkie ustawienia\r\n    * pobrane z NVRAMu zegarka oraz obecny czas\r\n    *\/\r\n\r\n   if (debug == 1) {\r\n      Serial.println(F(\"Obecne wartosci ds1307 NVRAM:\"));\r\n        for (int i = 0; i &lt; 56; ++i) {\r\n         printnvram(i);\r\n        }\r\n     \r\n      DateTime now = RTC.now();\r\n    \r\n      Serial.print(now.year(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(now.month(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(now.day(), DEC);\r\n      Serial.print(' ');\r\n      Serial.print(now.hour(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(now.minute(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(now.second(), DEC);\r\n      Serial.println();\r\n    \r\n      Serial.print(F(\" since 1970 = \"));\r\n      Serial.print(now.unixtime());\r\n      Serial.print(F(\"s = \"));\r\n      Serial.print(now.unixtime() \/ 86400L);\r\n      Serial.println(F(\"d\"));\r\n    \r\n      DateTime future (now.unixtime() + 7 * 86400L + 30);\r\n    \r\n      Serial.print(F(\" now + 7d + 30s: \"));\r\n      Serial.print(future.year(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(future.month(), DEC);\r\n      Serial.print('\/');\r\n      Serial.print(future.day(), DEC);\r\n      Serial.print(' ');\r\n      Serial.print(future.hour(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(future.minute(), DEC);\r\n      Serial.print(':');\r\n      Serial.print(future.second(), DEC);\r\n      Serial.println();\r\n    \r\n      Serial.println();\r\n   }\r\n\r\n   dht.setup(DHTPIN);\r\n}\r\n\r\nvoid loop() {\r\n  \r\n  \/*\r\n   * Sprawdzamy czy wy\u015bwietli\u0107 intro\r\n   *\/\r\n\r\n  if (splash == true) {\r\n    showSplash();\r\n  }\r\n  \r\n  mainMenu();   \/\/ G\u0142\u00f3wna funkcja wy\u015bwietlaj\u0105ca menu\r\n}\r\n\r\n\/*\r\n * Pokazujemy ekran powitalny\r\n *\/\r\n\r\nvoid showSplash() {\r\n    if (debug == 0  &amp;&amp; showIntro == 1) {\r\n      lcd.setCursor(0,0);\r\n      lcd.print(\"Zegarek\");\r\n      lcd.setCursor(0,1);\r\n      lcd.print(\"Wersja: \");\r\n      lcd.print(VERSION);\r\n      delay(400);\r\n      for (int positionCounter = 0; positionCounter &lt; 4; positionCounter++) {\r\n        lcd.scrollDisplayRight();\r\n        delay(400);\r\n      }\r\n  \r\n      \/\/playMelody(0);\r\n  \r\n      for (int positionCounter = 0; positionCounter &lt; 12; positionCounter++) {\r\n        lcd.scrollDisplayRight();\r\n        delay(400);\r\n      }\r\n    }\r\n    \r\n    \/\/ Pierwszy widoczny komunikat informacyjny\r\n    lcd.clear();\r\n    lcd.setCursor(0,0);\r\n    lcd.print(F(\"Wybierz opcje\"));\r\n    lcd.setCursor(0,1);\r\n    lcd.print(F(\"Klaw. Gora\/Dol\"));\r\n    splash = false;\r\n}\r\n\r\n\/*\r\n * Odczytujemy warto\u015bci ustawie\u0144 z NVRAM uk\u0142adu (celowo pomijamy warto\u015b\u0107 odpowiedzialn\u0105\r\n * za ustawienie zegarka w segmencie 50)\r\n *\/\r\n\r\nvoid readPreferences() {\r\n   keySounds = RTC.readnvram(0);\r\n   hourlyAlarmEnabled = RTC.readnvram(1);\r\n   hourlyAlarmFrom = RTC.readnvram(2);\r\n   hourlyAlarmTo = RTC.readnvram(3);\r\n   alarmEnabled = RTC.readnvram(4);\r\n   alarmHour = RTC.readnvram(5);\r\n   alarmMinute = RTC.readnvram(6);\r\n   debug = RTC.readnvram(7);\r\n   showIntro = RTC.readnvram(8);\r\n   alarmMelody = RTC.readnvram(9);\r\n}\r\n\r\n\/*\r\n * Wyrzucenie do konsoli ustawie\u0144\r\n *\/\r\n\r\nvoid printnvram(uint8_t address) {\r\n  String optionType = \"\";\r\n\r\n  switch (address) {\r\n      case 0:\r\n        optionType = \"Dzwieki klawiszy\";\r\n        break;\r\n      case 1:\r\n        optionType = \"Alarm co godzine wlaczony\";\r\n        break;\r\n       case 2:\r\n        optionType = \"Alarm co godzine od godziny\";\r\n        break;\r\n      case 3:\r\n        optionType = \"Alarm co godzine do godziny\";\r\n        break;\r\n      case 4:\r\n        optionType = \"Budzik wlaczony\";\r\n        break;\r\n      case 5:\r\n        optionType = \"Budzik godzina\";\r\n        break;\r\n      case 6:\r\n        optionType = \"Budzik minuta\";\r\n        break;\r\n      case 7:\r\n        optionType = \"Debug\";\r\n        break;\r\n      case 8:\r\n        optionType = \"Splash wlaczony\";\r\n        break;\r\n      case 9:\r\n        optionType = \"Melodyjka budzika\";\r\n        break;\r\n      case 50:\r\n        optionType = \"Ustaw zegarek przy wlaczeniu\";\r\n        break;\r\n      default:\r\n        optionType = \"Brak funkcjonalnosci\";\r\n    }\r\n  \r\n  Serial.print(F(\"Address 0x\"));\r\n  Serial.print(address, HEX);\r\n  Serial.print(F(\" = \"));\r\n  Serial.print(RTC.readnvram(address), HEX);\r\n  Serial.print(F(\" (HEX) = \"));\r\n  Serial.print(RTC.readnvram(address), DEC);\r\n  Serial.print(F(\" (DEC) (\"));\r\n  Serial.print(optionType);\r\n  Serial.println(F(\")\"));\r\n}\r\n\r\n\/*\r\n * Odtw\u00f3rz prosty d\u017awi\u0119k\r\n *\/\r\n\r\nvoid playSound(int refreshDelay, int signal) {\r\n  tone(BUZZERPIN, signal); \/\/ Send 1KHz sound signal...\r\n  delay(refreshDelay);\r\n  noTone(BUZZERPIN);     \/\/ Stop sound...\r\n}\r\n\r\n\/*\r\n * Funkcje odpowiedzialne za odtwarzanie melodyjek\r\n *\/\r\n\r\nvoid playTone(int tone, int duration) {\r\n  for (long i = 0; i &lt; duration * 1000L; i += tone * 2) {\r\n    digitalWrite(BUZZERPIN, HIGH);\r\n    delayMicroseconds(tone);\r\n    digitalWrite(BUZZERPIN, LOW);\r\n    delayMicroseconds(tone);\r\n  }\r\n}\r\n\r\nvoid playNote(char note, int duration) {\r\n  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };\r\n  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };\r\n  \r\n  \/\/ play the tone corresponding to the note name\r\n  for (int i = 0; i &lt; 8; i++) {\r\n    if (names[i] == note) {\r\n      playTone(tones[i], duration);\r\n    }\r\n  }\r\n}\r\n\r\n\r\nvoid playMelody(char index) {\r\n\r\n  switch (index) {\r\n      case 1:\r\n        strcpy(notes,\"ccggaag ffeeddc ggffeed ggffeed ccggaag ffeeddc \");\r\n        lcd.setCursor(3,1);\r\n        lcd.print(F(\"Twinkle\"));\r\n        break;\r\n      case 2:\r\n        strcpy(notes,\"dgggabbbagabg bbcddcbcdb ggabbagabgdd gggabbbagabg\");\r\n        lcd.setCursor(3,1);\r\n        lcd.print(F(\"Spider\"));\r\n        break;\r\n      case 3:\r\n        strcpy(notes,\"cccgaag e e d d c ggccc ggccc                    \");\r\n        lcd.setCursor(3,1);\r\n        lcd.print(F(\"Old McDonald\"));\r\n        break;\r\n      case 4:\r\n        strcpy(notes,\"dd deffefga ddd aaa fff ddd agfed                 \");\r\n        lcd.setCursor(3,1);\r\n        lcd.print(F(\"Row boat\"));\r\n        break;\r\n      default:\r\n        strcpy(notes,\"ccggaag ffeeddc ggffeed ggffeed ccggaag ffeeddc \");\r\n        lcd.setCursor(3,1);\r\n        lcd.print(F(\"Twinkle\"));\r\n        break;      \r\n  }\r\n  \r\n  for (int i = 0; i &lt; length; i++) {\r\n    if (notes[i] == ' ') {\r\n      delay(beats[i] * tempo); \/\/ rest\r\n    } else {\r\n      playNote(notes[i], beats[i] * tempo);\r\n    }\r\n    \r\n    \/\/ pause between notes\r\n    delay(tempo \/ 2); \r\n  }\r\n}\r\n\r\n\/*\r\n * Wybieranie i odtwarzanie wszystkich melodyjek z poziomu menu g\u0142\u00f3wnego\r\n *\/\r\n\r\nvoid jukebox() {\r\n    int index = 1;\r\n    int numberOfMelodies = 4;\r\n    showJukebox = true;\r\n\r\n    lcd.clear();\r\n    lcd.print(F(\"-&gt; Zm. Pra\/Lewo\"));\r\n    lcd.setCursor(0,1);\r\n    lcd.print(index);\r\n    \r\n    while (showJukebox) {\r\n      delay(300);\r\n      \r\n      lcd.setCursor(0,1);\r\n\r\n      \/\/ Je\u017celi wciskamy prawo wybieramy nast\u0119pna melodyjk\u0119\r\n      \r\n      if (analogRead (0) &lt; 50 &amp;&amp; index &lt; numberOfMelodies) {\r\n        index = index + 1;\r\n        lcd.print(index);\r\n        lcd.setCursor(3,1);\r\n        lcd.print(F(\"            \"));\r\n      }\r\n\r\n      \/\/ Je\u017celi wciskamy lewo wybieramy poprzedni\u0105 melodyjk\u0119\r\n      \r\n      if (analogRead (0) &gt; 380 &amp;&amp; analogRead (0) &lt; 555 &amp;&amp; index &gt; 1) {\r\n        index = index - 1;\r\n        lcd.print(index);\r\n        lcd.print(F(\"            \"));\r\n      }\r\n\r\n      \/\/ Je\u017celi wciskamy select to odtwarzamy melodyjk\u0119\r\n      \r\n      if (analogRead (0) &gt; 555 &amp;&amp; analogRead (0) &lt; 790) {\r\n        playMelody(index);\r\n      }\r\n\r\n      \/\/ Je\u017celi wciskamy d\u00f3\u0142 lub g\u00f3r\u0119, wychodzimy\r\n\r\n      if (analogRead (0) &gt; 50 &amp;&amp; analogRead (0) &lt; 380) {\r\n        showJukebox = false;\r\n      }\r\n    }\r\n}\r\n\r\n\/*\r\n * Po spe\u0142nieniu odpowiednich warunk\u00f3w, co ka\u017cd\u0105 pe\u0142n\u0105 godzin\u0119, odtw\u00f3rz sygna\u0142 d\u017awi\u0119kowy\r\n *\/\r\n\r\nvoid hourlyAlarm(int hour, int minute, int second) {\r\n  if (minute == 0 &amp;&amp; second == 0 &amp;&amp; (hour &gt;= hourlyAlarmFrom &amp;&amp; hour &lt;= hourlyAlarmTo) &amp;&amp; (hourlyAlarmFrom &gt;= 0 &amp;&amp; hourlyAlarmFrom &lt;= 23) &amp;&amp; (hourlyAlarmTo &gt;= 0 &amp;&amp; hourlyAlarmTo &lt;= 23) &amp;&amp; hourlyAlarmEnabled == 1) {\r\n    playSound(10,1000);\r\n  }\r\n}\r\n\r\n\/*\r\n * Po spe\u0142nieniu odpowiednich warunk\u00f3w, co dan\u0105 godzin\u0119, w\u0142\u0105cz budzik\r\n *\/\r\n\r\nvoid alarm(int hour, int minute) {\r\n  if (hour == alarmHour &amp;&amp; minute == alarmMinute &amp;&amp; hour &gt;= 0 &amp;&amp; hour &lt;= 23 &amp;&amp; minute &gt;= 0 &amp;&amp; minute &lt;= 59 &amp;&amp; alarmEnabled == 1) {\r\n    playMelody(alarmMelody);\r\n  }\r\n}\r\n\r\n\/*\r\n * Odczyt klawiszy na shieldzie\r\n *\/\r\n\r\nint read_LCD_buttons(){\r\n    analogKeyValue = analogRead(0);\r\n\r\n     if (analogKeyValue &lt; 50)   return btnRIGHT;  \r\n     if (analogKeyValue &lt; 195)  return btnUP; \r\n     if (analogKeyValue &lt; 380)  return btnDOWN; \r\n     if (analogKeyValue &lt; 555)  return btnLEFT; \r\n     if (analogKeyValue &lt; 790)  return btnSELECT;   \r\n \r\n    return btnNONE;\r\n}\r\n\r\n\/*\r\n * Pokazywanie menu g\u0142\u00f3wnego\r\n *\/\r\n\r\nvoid mainMenu() {\r\n  int state = 0;\r\n  lcd.setCursor(0,0);\r\n  pressedKey = read_LCD_buttons();\r\n    \r\n   switch (pressedKey){\r\n       case btnRIGHT:{\r\n             break;\r\n       }\r\n       case btnLEFT:{\r\n             break;\r\n       }    \r\n       case btnUP:{\r\n             state = 1;\r\n             break;\r\n       }\r\n       case btnDOWN:{\r\n             state = 2;\r\n             break;\r\n       }\r\n       case btnSELECT:{\r\n             state = 3;\r\n             break;\r\n       }\r\n       case btnNONE:{\r\n\r\n             break;\r\n       }\r\n   }\r\n\r\n  \/\/ Je\u017celi jeste\u015bmy poza dost\u0119pnymi elementami menu, to resetujemy\r\n  if (currentMenuItem &lt; 0 || currentMenuItem &gt; 8) {\r\n   currentMenuItem = 0; \r\n  }\r\n\r\n   \/\/Je\u017celi zmieni\u0142 si\u0119 indeks\r\n   if (state != lastState) {\r\n      if (state == 1) {\r\n         \/\/ G\u00f3ra\r\n          if (keySounds == 1) {\r\n            playSound(200,500);\r\n          }\r\n          currentMenuItem = currentMenuItem - 1; \r\n          displayMenu(currentMenuItem);\r\n      } else if (state == 2) {\r\n         \/\/ D\u00f3\u0142\r\n          if (keySounds == 1) {\r\n            playSound(200,500);\r\n          }\r\n          currentMenuItem = currentMenuItem + 1;  \r\n          displayMenu(currentMenuItem);\r\n      } else if (state == 3) {\r\n         \/\/ Select\r\n          if (keySounds == 1) {\r\n            playSound(200,500);\r\n          }\r\n         selectMenu(currentMenuItem); \r\n      }\r\n      \/\/ Zapisz ostatni status do por\u00f3wnania\r\n      lastState = state;\r\n   } \r\n  delay(5);\r\n}\r\n\r\n\/*\r\n * Wy\u015bwietl wybran\u0105 opcj\u0119\r\n *\/\r\n  \r\nvoid displayMenu(int x) {\r\n     switch (x) {\r\n      case 1:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Temperatura\"));\r\n        break;\r\n      case 2:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Czas i data\"));\r\n        break;\r\n      case 3:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Duzy zegar\"));\r\n        break;\r\n      case 4:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Melodyjka\"));\r\n        break;\r\n      case 5:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Ustawienia\"));\r\n        break;\r\n      case 6:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Resetuj ust.\"));\r\n        break;\r\n      case 7:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Godzina z PC\"));\r\n        break;\r\n      case 8:\r\n        clearPrintTitle();\r\n        lcd.print (F(\"-&gt; Ustaw zegar\"));\r\n        break;  \r\n    }\r\n}\r\n\r\n\/*\r\n *  Wy\u015bwietl nag\u0142\u00f3wek\r\n *\/\r\n \r\nvoid clearPrintTitle() {\r\n  lcd.clear();\r\n  lcd.setCursor(0,0);\r\n  lcd.print(F(\"Wyb. opcje (\"));\r\n  lcd.print(currentMenuItem);\r\n  lcd.print(F(\"\/\"));\r\n  lcd.print(MENUITEMS);\r\n  lcd.print(F(\")\"));\r\n  lcd.setCursor(0,1); \r\n}\r\n\r\n\/*\r\n * Pokazujemy temperatur\u0119 i wilgotno\u015b\u0107\r\n *\/\r\n\r\nvoid showTemperature() {\r\n  lcd.clear();\r\n  lcd.setCursor(0,0);\r\n\r\n  do {\r\n    delay(dht.getMinimumSamplingPeriod());\r\n    float t = dht.getTemperature();\r\n    float h = dht.getHumidity();\r\n  \r\n    if (dht.getStatus()) {\r\n      lcd.clear();\r\n      lcd.print(F(\"Blad czujnika\"));\r\n      if (debug == 1) {\r\n        Serial.println(F(\"Blad odczytu danych z czujnika\"));\r\n      }\r\n    } else {\r\n      if (debug == 1) {\r\n        Serial.print(F(\"Wilgotnosc: \"));\r\n        Serial.print(h);\r\n        Serial.print(\" % \");\r\n        Serial.print(F(\"Temperatura: \"));\r\n        Serial.print(t);\r\n        Serial.print(F(\" *C \/ \"));\r\n        Serial.print(dht.toFahrenheit(t));\r\n        Serial.println(F(\" *F \"));\r\n      }\r\n      lcd.print(F(\"Temp: \"));\r\n      lcd.print(t);\r\n      lcd.print(F(\" *C\"));\r\n      lcd.setCursor(0,1);\r\n      lcd.print(F(\"Wilgotn: \"));\r\n      lcd.print(h);\r\n      lcd.print(F(\" % \"));\r\n    }\r\n  } while (analogRead (0) &gt; 500);\r\n\r\n}\r\n\r\n\/*\r\n * Wy\u015bwietlanie cyfr do du\u017cego zegarka\r\n *\/\r\n\r\nvoid customDigits(int digit) {\r\nswitch (digit) {\r\n    case 0:\r\n       lcd.setCursor(customDigitX, 0);\r\n       lcd.write((byte)0);\r\n       lcd.write((byte)1);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX, 1);\r\n       lcd.write((byte)3);\r\n       lcd.write((byte)4);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 1:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)1);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX+1,1);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 2:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX, 1);\r\n       lcd.write((byte)3);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)7);\r\n      break;\r\n    case 3:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX, 1);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 4:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)3);\r\n       lcd.write((byte)4);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX+2, 1);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 5:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)0);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)6);\r\n       lcd.setCursor(customDigitX, 1);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 6:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)0);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)6);\r\n       lcd.setCursor(customDigitX, 1);\r\n       lcd.write((byte)3);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 7:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)1);\r\n       lcd.write((byte)1);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX+1, 1);\r\n       lcd.write((byte)0);\r\n      break;\r\n    case 8:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)0);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX, 1);\r\n       lcd.write((byte)3);\r\n       lcd.write((byte)7);\r\n       lcd.write((byte)5);\r\n      break;\r\n    case 9:\r\n       lcd.setCursor(customDigitX,0);\r\n       lcd.write((byte)0);\r\n       lcd.write((byte)6);\r\n       lcd.write((byte)2);\r\n       lcd.setCursor(customDigitX+2, 1);\r\n       lcd.write((byte)5);\r\n      break;\r\n  }\r\n}\r\n\r\n\/*\r\n * Pokazywanie daty oraz godziny w formacie\r\n * \r\n * dd.mm.yyyy (DT)\r\n *    gg:mm:ss\r\n *\/\r\n\r\nvoid showTimeAndDate() {\r\n    lcd.clear();\r\n\r\n    while (analogRead (0) &gt; 500) {\r\n      DateTime now = RTC.now();\r\n      lcd.setCursor(0,0);\r\n      if (now.day() &lt; 10) {\r\n        lcd.print(\"0\" + String(now.day()));\r\n      } else {\r\n        lcd.print(now.day(), DEC);\r\n      }\r\n      lcd.print('.');\r\n      if (now.month() &lt; 10) {\r\n        lcd.print(\"0\" + String(now.month()));\r\n      } else {\r\n        lcd.print(now.month(), DEC);\r\n      }\r\n      lcd.print('.');\r\n      lcd.print(now.year(), DEC);\r\n      lcd.print(\" (\");\r\n      lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);\r\n      lcd.print(\") \");\r\n      lcd.setCursor(4,1);\r\n\r\n      if (now.hour() &lt; 10) {\r\n        lcd.print(\"0\" + String(now.hour()));\r\n      } else {\r\n        lcd.print(now.hour(), DEC);\r\n      }\r\n      \r\n      lcd.print(':');\r\n      if (now.minute() &lt; 10) {\r\n        lcd.print(\"0\" + String(now.minute()));\r\n      } else {\r\n        lcd.print(now.minute(), DEC);\r\n      }\r\n      lcd.print(':');\r\n      if (now.second() &lt; 10) {\r\n        lcd.print(\"0\" + String(now.second()));\r\n      } else {\r\n        lcd.print(now.second(), DEC);\r\n      }\r\n\r\n      alarm(now.hour(),now.minute());                     \/\/ sprawd\u017a czy nie w\u0142\u0105czy\u0107 budzika\r\n      hourlyAlarm(now.hour(),now.minute(),now.second());  \/\/ sprawd\u017a czy nie w\u0142\u0105czy\u0107 godzinnego alarmu\r\n    }\r\n}\r\n\r\n\/*\r\n * Pokazywanie du\u017cego zegarka\r\n *\/\r\n\r\nvoid showBigClock() {\r\n  lcd.clear();\r\n  int digitArray[4] = {0,0,0,0}; \/\/ Tablica z poszczeg\u00f3lnymi sk\u0142adowymi zegarka\r\n  while (analogRead (0) &gt; 500) {\r\n\r\n     DateTime now = RTC.now();\r\n     customDigitX = 0;\r\n\r\n     if (now.minute() % 10 != digitArray[3]) {\r\n        lcd.clear();\r\n     }\r\n\r\n     if (now.hour() &lt; 10) {\r\n        digitArray[0] = 0;\r\n        digitArray[1] = now.hour();\r\n     } else {\r\n        digitArray[0] = now.hour() % 100 \/ 10;\r\n        digitArray[1] = now.hour() % 10;\r\n     }\r\n\r\n     if (now.minute() &lt; 10) {\r\n        digitArray[2] = 0;\r\n        digitArray[3] = now.minute();\r\n     } else {\r\n        digitArray[2] = now.minute() % 100 \/ 10;\r\n        digitArray[3] = now.minute() % 10;\r\n     }\r\n\r\n     for (int i = 0; i &lt; sizeof(digitArray); i++){      \r\n        customDigits(digitArray[i]);\r\n        customDigitX += 4;\r\n\r\n        if (i == 1) {\r\n           lcd.setCursor(7,0);\r\n           lcd.print('.');\r\n           lcd.setCursor(7,1);\r\n           lcd.print('.');\r\n        }\r\n     }\r\n\r\n     alarm(now.hour(),now.minute());                    \/\/ sprawd\u017a czy nie w\u0142\u0105czy\u0107 budzika\r\n     hourlyAlarm(now.hour(),now.minute(),now.second()); \/\/ sprawd\u017a czy nie w\u0142\u0105czy\u0107 godzinnego sygna\u0142u\r\n  }\r\n}\r\n\r\n\/*\r\n * Wy\u015bwietlanie ustawie\u0144\r\n *\/\r\n\r\nvoid showPreferences() {\r\n  int numberOfOptions = 10;\r\n  int currentOption = 1;\r\n  int value = 0;\r\n  int minimumValue = 0;\r\n  int maximumValue = 0;\r\n  int state = 0;\r\n  boolean showOption = true;\r\n\r\n  while (currentOption &lt;= numberOfOptions + 1) {  \r\n     switch (currentOption) {\r\n      case 1:\r\n        \/\/ D\u017awi\u0119k klawiszy w\u0142\u0105czony\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Dzw. klaw.\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"wlaczony\"));\r\n        minimumValue = 0;\r\n        maximumValue = 1; \r\n        break;\r\n      case 2:\r\n        \/\/ Sygna\u0142 godzinny w\u0142\u0105czony\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Sygn. godz.\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"wlaczony\"));\r\n        minimumValue = 0;\r\n        maximumValue = 1;\r\n        break;\r\n      case 3:\r\n        \/\/ Sygna\u0142 godzinny od godziny\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Sygn. godz.\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"od godziny\"));\r\n        minimumValue = 1;\r\n        maximumValue = 24;\r\n        break;\r\n      case 4:\r\n        \/\/ Sygna\u0142 godzinny do godziny\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Sygn. godz.\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"do godzinny\"));\r\n        minimumValue = 1;\r\n        maximumValue = 24;\r\n        break;\r\n      case 5:\r\n        \/\/ Budzik w\u0142\u0105czony\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Budzik\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"wlaczony\"));\r\n        minimumValue = 0;\r\n        maximumValue = 1;\r\n        break;\r\n      case 6:\r\n        \/\/ Budzik godzina\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Budzik\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"godzina\"));\r\n        minimumValue = 0;\r\n        maximumValue = 23;\r\n        break;\r\n      case 7:\r\n        \/\/ Budzik minuta\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Budzik\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"minuta\"));\r\n        minimumValue = 0;\r\n        maximumValue = 59;\r\n        break;\r\n      case 8:\r\n        \/\/ Debug w\u0142\u0105czony\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Debug\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"wlaczony\"));\r\n        minimumValue = 0;\r\n        maximumValue = 1;\r\n        break;\r\n      case 9:\r\n        \/\/ Ekran tytu\u0142owy w\u0142\u0105czony\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Splash\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"wlaczony\"));\r\n        minimumValue = 0;\r\n        maximumValue = 1;\r\n        break;\r\n      case 10:\r\n        \/\/ Wybierz melodyjk\u0119 budzika\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Melodyjka\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"budzika\"));\r\n        minimumValue = 1;\r\n        maximumValue = 99;\r\n        break;\r\n      default:\r\n        \/\/ Opcja wy\u015bwietlana po wyborze pozosta\u0142ych\r\n        lcd.clear();\r\n        lcd.setCursor(0,0);\r\n        lcd.print(F(\"Zapisano.\"));\r\n        lcd.setCursor(0,1);\r\n        lcd.print(F(\"Gora\/Dol Powrot\"));\r\n        showOption = false;\r\n        readPreferences();\r\n        currentOption = currentOption + 1;\r\n        break;\r\n    }\r\n\r\n    if (showOption) {\r\n      value = RTC.readnvram(currentOption - 1);\r\n      \r\n      lcd.setCursor(14,1);\r\n      lcd.print(value);\r\n      lcd.setCursor(11,0);\r\n      lcd.print(currentOption);\r\n      lcd.print(\"\/\");\r\n      lcd.print(numberOfOptions);\r\n\r\n      \/*\r\n       * Zmiena warto\u015bci poprzez wciskanie d\u00f3\u0142 \/ g\u00f3ra lub opcj poprzez lewo \/ prawo\r\n       *\/\r\n       \r\n      while (showOption) {\r\n          if (analogRead (0) &gt; 50 &amp;&amp; analogRead (0) &lt; 195 &amp;&amp; value &lt; maximumValue) {\r\n             value = value + 1;\r\n             lcd.setCursor(14,1);\r\n             lcd.print(value);\r\n  \r\n          }\r\n        \r\n          if (analogRead (0) &gt; 195 &amp;&amp; analogRead (0) &lt; 380 &amp;&amp; value &gt; minimumValue) {\r\n             value = value - 1;\r\n             lcd.setCursor(14,1);\r\n             lcd.print(value);\r\n          }\r\n  \r\n          if (analogRead (0) &lt; 50) {\r\n             RTC.writenvram(currentOption - 1, value); \/\/ zapisywanie warto\u015bci    \r\n             value = 0;\r\n             currentOption = currentOption + 1;\r\n             showOption = false;\r\n          }\r\n\r\n          if (analogRead (0) &gt; 380 &amp;&amp; analogRead (0) &lt; 555 &amp;&amp; currentOption &gt; 1) {       \r\n             currentOption = currentOption - 1;\r\n             showOption = false;\r\n          }\r\n          \r\n          delay(300);\r\n        }\r\n     }\r\n\r\n     if (currentOption &lt;= numberOfOptions) {\r\n        showOption = true;\r\n     }\r\n  }\r\n}\r\n\r\n\/*\r\n *  Ustaw zegarek r\u0119cznie\r\n *\/\r\n\r\n void manualSetClock() {\r\n\r\n  int digitArray[4] = {0,0,0,0}; \/\/ Tablica z poszczeg\u00f3lnymi sk\u0142adowymi zegarka\r\n  int minutes = 0;\r\n  int hours = 0;\r\n  int years = 2015;\r\n  int months = 1;\r\n  int days = 1;\r\n\r\n  delay(200);\r\n  lcd.clear();\r\n  \r\n   while (analogRead (0) &lt; 555 || analogRead (0) &gt; 790) {\r\n       delay(300);\r\n       \r\n      \/\/ Je\u017celi wciskamy prawo dodajemy minuty\r\n      \r\n      if (analogRead (0) &lt; 50 &amp;&amp; minutes &lt; 59) {\r\n        minutes = minutes + 1;\r\n        lcd.clear();\r\n      }\r\n\r\n      \/\/ Je\u017celi wciskamy lewo odejmujemy minuty\r\n      \r\n      if (analogRead (0) &gt; 380 &amp;&amp; analogRead (0) &lt; 555 &amp;&amp; minutes &gt; 0) {\r\n        minutes = minutes - 1;\r\n        lcd.clear();\r\n      }\r\n\r\n      \/\/ Je\u017celi wciskamy d\u00f3\u0142 odejmujemy godzin\u0119\r\n\r\n      if (analogRead (0) &gt; 195 &amp;&amp; analogRead (0) &lt; 380 &amp;&amp; hours &gt; 0) {\r\n         hours = hours - 1;\r\n         lcd.clear();\r\n      }\r\n\r\n      \/\/ Je\u017celi wciskamy g\u00f3r\u0119 dodajemy godzin\u0119\r\n\r\n      if (analogRead (0) &gt; 50 &amp;&amp; analogRead (0) &lt; 195 &amp;&amp; hours &lt; 23) {\r\n         hours = hours + 1;\r\n         lcd.clear();\r\n      }\r\n\r\n     customDigitX = 0;\r\n\r\n     if (hours &lt; 10) {\r\n        digitArray[0] = 0;\r\n        digitArray[1] = hours;\r\n     } else {\r\n        digitArray[0] = hours % 100 \/ 10;\r\n        digitArray[1] = hours % 10;\r\n     }\r\n\r\n     if (minutes &lt; 10) {\r\n        digitArray[2] = 0;\r\n        digitArray[3] = minutes;\r\n     } else {\r\n        digitArray[2] = minutes % 100 \/ 10;\r\n        digitArray[3] = minutes % 10;\r\n     }\r\n\r\n     for (int i = 0; i &lt; sizeof(digitArray); i++){      \r\n        customDigits(digitArray[i]);\r\n        customDigitX += 4;\r\n\r\n        if (i == 1) {\r\n           lcd.setCursor(7,0);\r\n           lcd.print('.');\r\n           lcd.setCursor(7,1);\r\n           lcd.print('.');\r\n        }\r\n     }\r\n\r\n      delay(100);\r\n   }\r\n\r\n   \/\/ Setting the date here\r\n\r\n   RTC.adjust(DateTime(years, months, days, hours, minutes));\r\n }\r\n\r\n\/*\r\n *  Wyb\u00f3r odpowiedniej pozycji w menu \r\n *\/\r\n \r\nvoid selectMenu(int x) {\r\n   switch (x) {\r\n      case 1:\r\n        clearPrintTitle();\r\n        showTemperature();\r\n        break;\r\n      case 2:\r\n        clearPrintTitle();\r\n        showTimeAndDate();\r\n        break;\r\n      case 3:\r\n        clearPrintTitle();\r\n        showBigClock();\r\n        break;\r\n      case 4:    \r\n        jukebox();\r\n        break;\r\n      case 5:\r\n        showPreferences();\r\n        break;\r\n      case 6:\r\n        RTC.writenvram(0, defaultPreferences, 9); \/\/ Przywracamy domy\u015blne ustawienia\r\n        lcd.setCursor(0,1);\r\n        lcd.print (F(\"-&gt; Przywrocono!\"));\r\n        break;\r\n      case 7:\r\n        if (Serial) {\r\n          RTC.writenvram(50, 1); \r\n          lcd.setCursor(0,1);\r\n          lcd.print (F(\"-&gt; Restart wym.!\"));\r\n        } else {\r\n          lcd.setCursor(0,1);\r\n          lcd.print (F(\"-&gt; Brak polacz. \"));\r\n        }\r\n        break;\r\n      case 8:\r\n        manualSetClock();\r\n        break;\r\n    }\r\n}<\/pre>\n<p>Dodatkowo w katalogu z powy\u017cszym szkicem nale\u017cy utworzy\u0107 plik &#8222;bigfont.h&#8221; z zawarto\u015bci\u0105:<\/p>\n<pre class=\"lang:c++ decode:true\">byte LT[8] =\r\n{\r\n B00111,\r\n B01111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111\r\n};\r\nbyte UB[8] =\r\n{\r\n B11111,\r\n B11111,\r\n B11111,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B00000\r\n};\r\nbyte RT[8] =\r\n{\r\n B11100,\r\n B11110,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111\r\n};\r\nbyte LL[8] =\r\n{\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B01111,\r\n B00111\r\n};\r\nbyte LB[8] =\r\n{\r\n B00000,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B11111,\r\n B11111,\r\n B11111\r\n};\r\nbyte LR[8] =\r\n{\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11111,\r\n B11110,\r\n B11100\r\n};\r\nbyte UMB[8] =\r\n{\r\n B11111,\r\n B11111,\r\n B11111,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B11111,\r\n B11111\r\n};\r\nbyte LMB[8] =\r\n{\r\n B11111,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B00000,\r\n B11111,\r\n B11111,\r\n B11111\r\n};<\/pre>\n<p>Jak mo\u017cna si\u0119 zorientowa\u0107 &#8211; s\u0105 to definicje &#8222;du\u017cych&#8221; cyfr do wy\u015bwietlania zegarka.<\/p>\n<h3>6. Prezentacja<\/h3>\n<p><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/clock_final_front.jpg\"><img loading=\"lazy\" width=\"700\" height=\"394\" class=\"alignnone size-large wp-image-747\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/clock_final_front-700x394.jpg\" alt=\"clock_final_front\" srcset=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/clock_final_front-700x394.jpg 700w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/clock_final_front-250x141.jpg 250w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/clock_final_front-768x432.jpg 768w, http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/clock_final_front-120x68.jpg 120w\" sizes=\"(max-width: 700px) 100vw, 700px\" \/><\/a><\/p>\n<p>Zegarek w akcji:<\/p>\n<div style=\"width: 640px;\" class=\"wp-video\"><!--[if lt IE 9]><script>document.createElement('video');<\/script><![endif]-->\n<video class=\"wp-video-shortcode\" id=\"video-723-1\" width=\"640\" height=\"360\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/Arduino_Clock.mp4?_=1\" \/><a href=\"http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/Arduino_Clock.mp4\">http:\/\/ignus.co.pl\/blog\/wp-content\/uploads\/2016\/08\/Arduino_Clock.mp4<\/a><\/video><\/div>\n","protected":false},"excerpt":{"rendered":"Wst\u0119p W tym artykule dowiemy si\u0119 jak zbudowa\u0107 z pomoc\u0105 p\u0142ytki Arduino cyfrowy zegarek, kt\u00f3ry b\u0119dzie spe\u0142nia\u0142 nast\u0119puj\u0105ce za\u0142o\u017cenia: odmierzanie czasu\u00a0po od\u0142\u0105czeniu zasilania (zegar RTC z bateri\u0105) sygna\u0142 d\u017awi\u0119kowy co godzin\u0119 wy\u015bwietlanie daty funkcjonalno\u015b\u0107 budzika mierzenie\u00a0temperatury otoczenia r\u00f3\u017cne ekrany do wy\u015bwietlania (data + czas + temperatura, du\u017cy zegar itp.) zapisywanie ustawie\u0144 w pami\u0119ci (w tym&#8230; <\/div><a class=\"view-article\" href=\"http:\/\/ignus.co.pl\/blog\/?p=723\">Zobacz wpis<\/a>","protected":false},"author":1,"featured_media":727,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,16,10],"tags":[96,123,121,124,122],"_links":{"self":[{"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts\/723"}],"collection":[{"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=723"}],"version-history":[{"count":18,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts\/723\/revisions"}],"predecessor-version":[{"id":755,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/posts\/723\/revisions\/755"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=\/wp\/v2\/media\/727"}],"wp:attachment":[{"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=723"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ignus.co.pl\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}