Cześć , od dawna czytam poradniki na majsterkowie i sam uczę się o arduino najczęściej stąd. Chciałbym podzielić się z wami projektem zegarka opartego na najdokładniejszym układzie RTC (Real Time Clock) a mianowicie DS3231, wyświetlać będzie czas na wyświetlaczu LCD 16×2 sterowanym przez konwerter na magistrali I2C. Powiem też o podstawach pracy ze stringami ;).
Co nam będzie potrzebne :
-Arduino (ja używam Leonardo ale może być jakiekolwiek, lub sama Atmega np 328) link
-Wyświetlacz z konwerterem I2C link
-Moduł ds3231 link
-Płytka stykowa link
-Kabelki/zworki
Podłączenie jest banalnie proste, piny SDA i SCL obu modułów podłaczamy do SDA i SCL w Arduino, to samo z zasilaniem, VCC do 5V a GND do GND w Arduino. Do magistrali I2C możemy podłączać wiele urządzeń gdyż każde ma swój własny adres.
Poniżej kod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
#include <LiquidCrystal_I2C.h> // biblioteka do obsługi wyświetlacza na I2C #include <Wire.h> #include <DS3231.h> // biblioteka do obsługi zegara ds3231 LiquidCrystal_I2C lcd(0x27,16,2); // adres wyświetlacza,liczbę kolumn,wierszy DS3231 clock; RTCDateTime dt; int jo=0; //zmienna pierwszej cyfry int oj=0; //zmienna drugiej cyfry int io=0; //zmienna trzeciej cyfry int oi=0; //zmienna czwartej cyfry int ioo=0; //zmienna pierwszej cyfry dnia roku int oio=0; //zmienna drugiej cyfry dnia roku int ooi=0; //zmienna trzeciej cyfry dnia roku long startowa = 0; // zmienna "startowa" long ileczasu = 10000; // ilość w milisekundach int tryb = 0; // zmienna tryb // kody poszczególnych dużych znaków byte bar1[8] = { B11100, B11110, B11110, B11110, B11110, B11110, B11110, B11100 }; byte bar2[8] = { B00111, B01111, B01111, B01111, B01111, B01111, B01111, B00111 }; byte bar3[8] = { B11111, B11111, B00000, B00000, B00000, B00000, B11111, B11111 }; byte bar4[8] = { B11110, B11100, B00000, B00000, B00000, B00000, B11000, B11100 }; byte bar5[8] = { B01111, B00111, B00000, B00000, B00000, B00000, B00011, B00111 }; byte bar6[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111 }; byte bar7[8] = { B00000, B00000, B00000, B00000, B00000, B00000, B00111, B01111 }; byte bar8[8] = { B11111, B11111, B00000, B00000, B00000, B00000, B00000, B00000 }; void setup() { lcd.init(); // inicjalizujemy pracę wyświetlacza lcd.backlight(); // włączamy podświetlenie clock.begin(); // inicjalizujemy zegar lcd.createChar(1,bar1); lcd.createChar(2,bar2); lcd.createChar(3,bar3); lcd.createChar(4,bar4); lcd.createChar(5,bar5); lcd.createChar(6,bar6); lcd.createChar(7,bar7); lcd.createChar(8,bar8); } void custom0(int col) { // uses segments to build the number 0 lcd.setCursor(col, 0); lcd.write(2); lcd.write(8); lcd.write(1); lcd.setCursor(col, 1); lcd.write(2); lcd.write(6); lcd.write(1); } void custom1(int col) { lcd.setCursor(col,0); lcd.write(32); lcd.write(32); lcd.write(1); lcd.setCursor(col,1); lcd.write(32); lcd.write(32); lcd.write(1); } void custom2(int col) { lcd.setCursor(col,0); lcd.write(5); lcd.write(3); lcd.write(1); lcd.setCursor(col, 1); lcd.write(2); lcd.write(6); lcd.write(6); } void custom3(int col) { lcd.setCursor(col,0); lcd.write(5); lcd.write(3); lcd.write(1); lcd.setCursor(col, 1); lcd.write(7); lcd.write(6); lcd.write(1); } void custom4(int col) { lcd.setCursor(col,0); lcd.write(2); lcd.write(6); lcd.write(1); lcd.setCursor(col, 1); lcd.write(32); lcd.write(32); lcd.write(1); } void custom5(int col) { lcd.setCursor(col,0); lcd.write(2); lcd.write(3); lcd.write(4); lcd.setCursor(col, 1); lcd.write(7); lcd.write(6); lcd.write(1); } void custom6(int col) { lcd.setCursor(col,0); lcd.write(2); lcd.write(3); lcd.write(4); lcd.setCursor(col, 1); lcd.write(2); lcd.write(6); lcd.write(1); } void custom7(int col) { lcd.setCursor(col,0); lcd.write(2); lcd.write(8); lcd.write(1); lcd.setCursor(col, 1); lcd.write(32); lcd.write(32); lcd.write(1); } void custom8(int col) { lcd.setCursor(col, 0); lcd.write(2); lcd.write(3); lcd.write(1); lcd.setCursor(col, 1); lcd.write(2); lcd.write(6); lcd.write(1); } void custom9(int col) { lcd.setCursor(col, 0); lcd.write(2); lcd.write(3); lcd.write(1); lcd.setCursor(col, 1); lcd.write(7); lcd.write(6); lcd.write(1); } void custom11(int col) { lcd.setCursor(col,0); lcd.write(6); lcd.setCursor(col, 1); lcd.write(8); } void printNumber(int value, int col) { if (value == 0) { custom0(col); } if (value == 1) { custom1(col); } if (value == 2) { custom2(col); } if (value == 3) { custom3(col); } if (value == 4) { custom4(col); } if (value == 5) { custom5(col); } if (value == 6) { custom6(col); } if (value == 7) { custom7(col); } if (value == 8) { custom8(col); } if (value == 9) { custom9(col); } if (value == 11) { custom11(col); } } void loop() { unsigned long czas = millis(); // ustala zmienną czas w milisekundach if(czas - startowa > ileczasu) { // jeśli czas jaki upłynął od włączenia arduino jest większy niż zadeklarowaliśmy w "ileczasu" lcd.clear(); // czyści ekran przed każdą zmianą napisu żeby nic się nie nakładało startowa = czas; // zrównuje start z czasem który się nalicza w milisekundach tryb = tryb+1; // przełącza ekran na następny } dt = clock.getDateTime(); // pobiera czas z zegara if(tryb==0) { pokaczas(); // funkcja wyświetlająca czas } if(tryb==1) { pokadzien(); // funkcja wyświetlająca dzień roku } if(tryb==2){ // powraca do pierwszego ekranu tryb=0; } } void pokaczas(){ String czas=(clock.dateFormat("H:i:s", dt)); // tworzymy stringa z odczytu godziny:minuty:sekundy z zegara i zapisujemy do stringa "czas" jo=czas[0]-48; oj=czas[1]-48; io=czas[3]-48; oi=czas[4]-48; printNumber(jo, 0); // wyświetlamy po kolei każdą liczbę godziny i minuty printNumber(oj, 3); printNumber(11, 6); // wyświetlamy dwukropek printNumber(io, 7); printNumber(oi, 10); lcd.setCursor(14,1); lcd.print(clock.dateFormat("s", dt)); // wyświetlamy sekundy } void pokadzien(){ String dzien=(clock.dateFormat("z", dt)); // pobieramy dzień roku ioo=dzien[0]-48; oio=dzien[1]-48; ooi=dzien[2]-48; printNumber(ioo, 0); // wyświetlamy po kolei każdą cyfrę dnia roku printNumber(oio, 3); printNumber(ooi, 6); lcd.setCursor(10,0); lcd.print("DZIEN"); lcd.setCursor(10,1); lcd.print("ROKU"); } |
Potrzeba jeszcze aby wyjaśnić operacje na stringu :
dzien[0] –> wyświetla pierwszy znak stringa “dzien”
ioo=dzien[0]-48 –> przyrównuje zmienną “ioo” typu int do pierwszego znaku stringa “dzien” pomniejszonego o 48 gdyż string zapisuje się w kodzie ASCII a INTa chcemy w DEC.
Na wyświetlaczu pokaże się na czas godzina:minuta w dużej czcionce oraz mała sekunda, po 10 sekundach ekran wyczyści się i pokaże się dużą czcionką aktualny dzień roku i po 10 sekundach ekran wróci na czas i tak w kółko :)
Aby wszystko działało poprawnie musimy posiadać bibliotekę DS3231, przygotował ją Pan Korneliusz Jarzębski strona.
Ja ją delikatnie przerobiłem i można pobrać poniżej :
Arduino-DS3231-master
Należy dodać również bibliotekę LiquidCrystalI2C :
LiquidCrystal_I2C
Jeśli będą jakieś pytania to proszę zadawać pod wpisem lub na pw, jeśli się spodobało proszę o ocenę :)
Pozdrawiam
5 dla Kolegi
Zmiana czasu Lato/Zima czy korekta zegara – niemożliwe. Projekt prosty by nie powiedzieć banalny. Ciekawy i interesujący dla początkującego.
Jeżeli o początkujących chodzi, to oni oczekują informacji. Tych tu brak. Jest prosty kod gdzie nie jest wytłumaczona każda linijka, jest artykuł który nic nie mówi.
Są też biblioteki których arduino nie posiada, to też taki żółtodziób nie poradzi sobie z LCD na I2C – gdyż bibliotekę trzeba “dograć”, a szkoda że tu nie jest ona dostępna.
Pomysł – pewne 5
Wykonanie – 3-
poradników o podłączeniu lcd na i2c jest multum więc nie widziałem potrzeby opisywania tego, pracuję nad rozwiązaniem czasu lato zima jakoś sensownie oraz roku przestępnego, a co do korekty zegarka to inny na ds3231 działa u mnie w domu już ponad rok i nawet o minutę się nie “rozklekotał” ale dzięki za konstruktywną krytykę :)
Co do czasu lato/zima oglądnij sobie na yt poradniki Mirka Kardasia, przy omówieniu rtc z NTP jest to pokazane.
Dzięki, sprawdzę na 100% :)
Jakbym miał syna to bym mu kupił taki na Pierwszą Komunię Świętą ;]
Super zawsze chciałem taki zrobić! Można by jeszcze prosić o jakiś filmik jak to działa? Pozdrawiam!
PS
Można by wyświetlać też temperaturę? :)
Działa to tak że 10 sekund pokazuje czas potem 10 sekund dzien roku i tak w kółko, można też temperaturę, nawet moduł ds3231 ma wbudowany czujnik temperatury.
Witam, zrobiłem sobie ten projekt, działa super, lecz pozmieniałem sobie czcionkę na taką co mi się podoba. I teraz mam problem bo z niej się nie da zrobić dwukropka pomiędzy godzinami a minutami. Gdy dodaje nowe Char’y i próbuje je inicjalizować i dodać jako dwukropek to na całym wyświetlaczu robią sie krzaczki. Jak wymyślić dwukropek?
Wyślij mi ten kod na pw, spróbuje pomóc :)
Zastanawiam się gdzie tu napisać na pw.. i nie znalazłem..
Dobra ale ok. poradziłem sobie jako tako z dwukropkiem, ale mam inny problem. Jak już pisałem zmieniłem sobie czcionkę. Dodałem też temperaturę. I ogólnie to działa dobrze, godzinę i temperaturę pokazuje ale problem mam z tym że czasami tak jakby liczby się nie odświeżają i nachodzi 1 na 2, czy 3 na 4. Zastanawiam się ale nie umiem do tego dojść dlaczego.
Ogólnie kod jest praktycznie taki sam tylko ta czcionka zmieniona a u Ciebie liczby się nie nachodzą..
wrzucam kod tutaj: http://wklejaj.pl/lziOP2Pk8QXX
Pozdrawiam i z góry dzięki
Nie widzę błędu u Ciebie w kodzie, masz przy zmianie ekranu lcd.clear() więc nie powinno się nic nakładać :) co do temperatury, zrób może na 3 albo 4 znaki będzie fajniej wyglądać
Bez problemu pokazuję Tobie temperaturę ? Mi wskazuje 0* co może być nie tak ? Kod wgrywa się prawidłowo.
Jak za pomocą DS3231 odczytać i pokazać na tym temperaturę? Wolałbym temperaturę zamiast dni :)
http://www.jarzebski.pl/arduino/komponenty/zegar-czasu-rzeczywistego-rtc-ds3231.html
tu jest wszystko wytłumaczone :)
Ok tylko jak to teraz wyświetlić? Trzeba by przekonwertowac float na string tylko jak?
Tak samo jak z godziną konwertujesz na stringa fukcję clock.readTemperature()
i wyświetlasz po jednej liczbie jak godzinę :)
ioo=dzien[0]-48 –> przyrównuje zmienną “ioo” typu int do pierwszego znaku stringa “dzien”
Polecam: ikony dzien[0]-‘0’
Witam, mam problem z wyświetleniem temperatury pobranej z modułu RTC rtc ds3231, a konkretnie to mam problem z konwersją clock.readTemperature() do String’a.
Szukałem już rozwiązania w sieci niestety z marnym skutkiem ;/
Liczę na Wasza pomoc!
Ok fajnie, tylko mały pytanko. Nie widzę nigdzie kodu, odpowiedzialnego za czas letni i zimowy.
Cześć, podoba mi się bardzo pomysł na wyświetlanie dużych cyfr. Natomiast kod jest straszny. Polecam bardziej rozsądne nazywanie zmiennych, wtedy 90% komentarzy byłoby zbędnych a czytelność kodu wzrosłaby znacznie. To razi najbardziej. Jest też dużo zduplikowanego kodu. Można byłoby go sporo skrócić.
Dzięki, będę starał się poprawić czytelność kodu ! :D
Witam czy mogę prosic o skompilowany kod
Kod jest zamieszczony we wpisie. Jeśli zostaną zainstalowane załączone biblioteki, kod skompiluje się prawidłowo. Sprawdzałem przed chwilą w Arduino IDE 1.6.13.
Witam. Zegar działa fajnie z małym ale… Nie mam drugiej cyfry sekund a w dniu roku tylko D i R… Co może być powodem?
Pozdrawiam
Andrzej
Super wydaje się proste do zrobienia ale nie będę ryzykował, mam pytanko kończę budować automat arcade i szukam kogoś kto mógłby zrobić coś podobnego co Pan z tym żeby można było podłączyć pod wrzutnik monet ch923 procesorowy (z Botland.pl) + Pc + pod minipaca, żeby wyświetlało godzinę i ile kasy zostało już wrzucone taka mini prywatna skarbonka z aktualnym czasem ;)
Ktoś jest w stanie się podjąć takiego bajeru ?
Wywala mi taki bład: Arduino:1.8.11 (Windows 10), Płytka:”Arduino Nano, ATmega328P”
zegar:6:1: error: ‘RTCDateTime’ does not name a type; did you mean ‘DateTime’?
RTCDateTime dt;
^
~~DateTime
E:\1Arduino\zegar\zegar.ino: In function ‘void setup()’:
zegar:116:9: error: ‘class DS3231’ has no member named ‘begin’
clock.begin(); // inicjalizujemy zegar
^
E:\1Arduino\zegar\zegar.ino: In function ‘void loop()’:
zegar:294:3: error: ‘dt’ was not declared in this scope
dt = clock.getDateTime(); // pobiera czas z zegara
^~
zegar:294:14: error: ‘class DS3231’ has no member named ‘getDateTime’; did you mean ‘getDate’?
dt = clock.getDateTime(); // pobiera czas z zegara
^
~~getDate
E:\1Arduino\zegar\zegar.ino: In function ‘void pokaczas()’:
zegar:309:24: error: ‘class DS3231’ has no member named ‘dateFormat’
String czas = (clock.dateFormat(“H:i:s”, dt)); // tworzymy stringa z odczytu godziny:minuty:sekundy z zegara i zapisujemy do stringa “czas”
^
~zegar:309:44: error: ‘dt’ was not declared in this scope
String czas = (clock.dateFormat(“H:i:s”, dt)); // tworzymy stringa z odczytu godziny:minuty:sekundy z zegara i zapisujemy do stringa “czas”
^~
zegar:322:19: error: ‘class DS3231’ has no member named ‘dateFormat’
lcd.print(clock.dateFormat(“s”, dt)); // wyświetlamy sekundy
^
~E:\1Arduino\zegar\zegar.ino: In function ‘void pokadzien()’:
zegar:325:25: error: ‘class DS3231’ has no member named ‘dateFormat’
String dzien = (clock.dateFormat(“z”, dt)); // pobieramy dzień roku
^
~zegar:325:41: error: ‘dt’ was not declared in this scope
String dzien = (clock.dateFormat(“z”, dt)); // pobieramy dzień roku
^~
Znaleziono wiele bibliotek w “LiquidCrystal_I2C.h”
Wykorzystane: E:\1Arduino\libraries\LiquidCrystal_I2C-1.1.2
Niewykorzystane: E:\1Arduino\libraries\Newliquidcrystal_1.3.5
exit status 1
‘RTCDateTime’ does not name a type; did you mean ‘DateTime’?
Ten raport powinien zawierać więcej informacji jeśli w
File -> Preferencje zostanie włączona opcja “Pokaż
szczegółowe informacje podczas kompilacji”
Masz coś z bibliotekami namieszane
Ma po prostu wiele bibliotek i Arduino nie wie którą załadować. Są 2 sposoby rozwiązania tego problemu. Albo pokazać fizycznie arduino gdzie ma tą konkretną bibliotekę wraz ze ścieżką dostępu, albo wywalić wszystkie zdublowane i w starych wersjach. Nie wiem jak to jest w Arduino IDE bo nie korzystałem z niego od 6 lat. Obecnie programuję tylko w Eclipse i C. Polecam.
Witam,
A ja mam inny problem z tym kodem:
Po edycji
LiquidCrystal_I2C lcd(0x27,16,2); // adres wyświetlacza,liczbę kolumn,wierszy
na
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlightpin, polarity
oraz
lcd.init();
na
lcd.begin(20,4);
nie wyświetla mi nic poza dwukropkiem oraz “dzień rok”
co może być przyczyną?