Components and supplies
Arduino Nano R3
Gravity: I2C BME280 Environmental Sensor
Alphanumeric LCD, 20 x 4
Photo resistor
Rotary Encoder with Push-Button
High Accuracy Pi RTC (DS3231)
Apps and platforms
Arduino IDE
Project description
Code
Big Font Weather Clock
arduino
20x4 LCD Big Font Clock, interior/exterior weather information
1/* 2 * Racov feb.2021 3 -- 20x4 LCD (paralel) display 4 -- clock with big numbers and I2C-DS3231 Real Time clock 5 -- temperature and hunidity interior/exterior with I2C-BMP280 6 -- rotary encoder for TIME set 7 8 The circuit: 9 * LCD RS - D12 10 * LCD Enable - D11 11 * LCD D4 - D8 12 * LCD D5 - D7 13 * LCD D6 - D6 14 * LCD D7 - D5 15 * LCD R/W - GND 16 * LED A - D9 17 * 10K resistor-ends to +5V and GND 18 * wiper to LCD VO(pin 3) 19 20 Encoder: 21 * A - D2 22 * B - D3 23 * Push1 - D4 24 * Push2, C - GND 25 26 racov.ro 27 28*/ 29 30// include the library code: 31#include <LiquidCrystal.h> //LCD 32#include <Wire.h> 33#include <Adafruit_Sensor.h> 34#include <Adafruit_BME280.h> //BME280 temp-hum-pres sensor, 35#include <RTClib.h> //DS3231 Real Time Clock 36RTC_DS3231 rtc; //declare RTC 37Adafruit_BME280 bme1; //declare BME interior 38Adafruit_BME280 bme2; //declare BME exterior 39 40// initialize the library by associating any needed LCD interface pin 41// with the arduino pin number it is connected to 42const int rs = 12, en = 11, d4 = 8, d5 = 7, d6 = 6, d7 = 5, LED = 9; 43LiquidCrystal lcd(rs, en, d4, d5, d6, d7); 44 45// usually the rotary encoders three pins have the ground pin in the middle 46int encoderPinA = 2; // encoder right 47int encoderPinB = 3; // encoder left 48int clearButton = 4; // encoder push 49 50// variables for automatic brightness 51int light; 52 53// interior environment variables 54int intemp = 0; 55int inhum = 0; 56int pres = 0; 57// exterior environment variables 58int hum = 0; 59int temp = 0; 60 61int h,m,s,yr,mt,dt,dy,olds; // hous, minutes, seconds, year, month, date of the month, day, previous second 62char *DOW[]={"MAR","MIE","JOI","VIN","SAM","DUM","LUN"}; //define day of the week 63char *MTH[]={"ian","feb","mar","apr","mai","iun","iul","aug","sep","oct","nov","dec"}; //define month 64int EncoderMax; // varialbe for h, m, s, ... max value 65 66int encoderPos = 0; // a counter for the dial 67unsigned int lastReportedPos = 1; // change management 68static boolean rotating = false; // debounce management 69 70// interrupt service routine vars 71boolean A_set = false; 72boolean B_set = false; 73 74// varialbe to know if we are in time setting mode 75boolean set_h = false; //hours 76boolean set_m = false; //minutes 77boolean set_s = false; //seconds 78boolean set_yr = false; //year 79boolean set_mt = false; //month 80boolean set_dt = false; //date of the month 81 82boolean intbme = true; 83boolean extbme = true; 84///////////////////////////////////////////////////// 85 86void setup() { 87 Serial.begin(9600); 88 // set up the LCD's number of columns and rows: 89 lcd.begin(20, 4); 90 lcd.clear(); 91 // set up the encoder 92 pinMode(encoderPinA, INPUT); 93 pinMode(encoderPinB, INPUT); 94 pinMode(clearButton, INPUT); 95 // encoder pin on interrupt 0 (pin 2) 96 attachInterrupt(0, doEncoderA, CHANGE); 97 // encoder pin on interrupt 1 (pin 3) 98 attachInterrupt(1, doEncoderB, CHANGE); 99 100 // *******DEFINE CUSTOM CHARACTERS FOR BIG FONT***************** 101 byte A[8] = 102 { 103 B00011, 104 B00111, 105 B01111, 106 B01111, 107 B01111, 108 B01111, 109 B01111, 110 B01111 111 }; 112 byte B[8] = 113 { 114 B11111, 115 B11111, 116 B00000, 117 B00000, 118 B00000, 119 B00000, 120 B00000, 121 B11111 122 }; 123 byte C[8] = 124 { 125 B11000, 126 B11100, 127 B11110, 128 B11110, 129 B11110, 130 B11110, 131 B11110, 132 B11110 133 }; 134 byte D[8] = 135 { 136 B01111, 137 B01111, 138 B01111, 139 B01111, 140 B01111, 141 B01111, 142 B00111, 143 B00011 144 }; 145 byte E[8] = 146 { 147 B11111, 148 B00000, 149 B00000, 150 B00000, 151 B00000, 152 B00000, 153 B11111, 154 B11111 155 }; 156 byte F[8] = 157 { 158 B11110, 159 B11110, 160 B11110, 161 B11110, 162 B11110, 163 B11110, 164 B11100, 165 B11000 166 }; 167 byte G[8] = 168 { 169 B11111, 170 B11111, 171 B11111, 172 B00000, 173 B00000, 174 B00000, 175 B00000, 176 B00000 177 }; 178 byte H[8] = 179 { 180 B00000, 181 B00000, 182 B00000, 183 B00000, 184 B00000, 185 B11111, 186 B11111, 187 B11111 188 }; 189 190 lcd.createChar(8,A); 191 lcd.createChar(6,B); 192 lcd.createChar(2,C); 193 lcd.createChar(3,D); 194 lcd.createChar(7,E); 195 lcd.createChar(5,F); 196 lcd.createChar(1,G); 197 lcd.createChar(4,H); 198 199 // Print a message to the LCD. 200 // lcd.setCursor(col, row); 201 // lcd.print("text"); 202 lcd.setCursor(6, 0); 203 lcd.print("WEATHER"); 204 lcd.setCursor(7, 1); 205 lcd.print("CLOCK"); 206 lcd.setCursor(5, 2); 207 lcd.print("**RACOV**"); 208 lcd.setCursor(6, 3); 209 lcd.print("Feb.2021"); 210 // slowly increase display backlighting brightness 211 for (int i = 0; i <= 4; i++) { 212 analogWrite(LED, (i*50)); 213 delay(500); 214 } 215 delay(1000); 216 217 // initializing the modules 218 analogWrite(LED, 50); 219 lcd.setCursor(0, 0); 220 lcd.print("CHECKING MODULES...."); 221 delay(100); 222 223 analogWrite(LED, 100); 224 lcd.setCursor(0, 1); 225 lcd.print("1.REAL CLOCK......OK"); 226 if (! rtc.begin()) { 227 lcd.setCursor(16, 1); 228 lcd.print("FAIL"); 229 delay(5000); 230 } 231 delay(500); 232 233 analogWrite(LED, 150); 234 lcd.setCursor(0, 2); 235 lcd.print("2.INSIDE TEMP.....OK"); 236 if (!bme1.begin(0x76)) { 237 lcd.setCursor(16, 2); 238 lcd.print("FAIL"); 239 intbme = false; 240 } 241 delay(500); 242 243 analogWrite(LED, 200); 244 lcd.setCursor(0, 3); 245 lcd.print("3.OUTSIDE TEMP....OK"); 246 if (!bme2.begin(0x77)) { 247 lcd.setCursor(16, 3); 248 lcd.print("FAIL"); 249 extbme = false; 250 } 251 delay(2000); 252 253 // print all the fix text - never changes 254 lcd.setCursor(0, 0); 255 lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __"); // char(165) is big point symbol 256 lcd.setCursor(0, 1); 257 lcd.print(" "+String(char(165))+" "+(char(165))+" "); 258 lcd.setCursor(0, 2); 259 lcd.print("LUN-01-ian [--"+String(char(223))+" --%]"); // char(223) is degree symbol 260 lcd.setCursor(0, 3); 261 lcd.print(" ----hPa --"+String(char(223))+" --% "); 262 263// set a particular date and time if you want (yyyy,mm,dd,hh,mm,ss) 264// rtc.adjust(DateTime(2021, 2, 16, 11, 00, 00)); 265 266// read all time and date and display 267 DateTime now = rtc.now(); 268 h = now.hour(); 269 m = now.minute(); 270 s = now.second(); 271 yr = now.year(); 272 mt = now.month(); 273 dt = now.day(); 274 dy = now.dayOfTheWeek(); 275 olds = s; 276 277// fill the display with all the data 278 printbig((h%10),3); 279 printbig((h/10),0); 280 printbig((m%10),10); 281 printbig((m/10),7); 282 printbig((s%10),17); 283 printbig((s/10),14); 284 285 lcd.setCursor(0, 2); 286 lcd.print(DOW[dy]); 287 lcd.setCursor(4, 2); 288 lcd.print(dt/10); 289 lcd.print(dt%10); 290 lcd.setCursor(7, 2); 291 lcd.print(MTH[mt]); 292 293} 294 295void loop() { 296 DateTime now = rtc.now(); 297 s = now.second(); // read seconds 298 if (olds != s) { // if seconds changed 299/* Serial.println(dy); 300 Serial.println(mt); 301 Serial.println(dt); 302 Serial.println(yr); */ 303 printbig((s%10),17); // display seconds 304 printbig((s/10),14); 305 olds = s; 306 timeset(); // verify if user wants to set time 307 if ( s == 0 ) { // minutes change 308 m = now.minute(); // read minutes 309 printbig((m%10),10); // display minutes 310 printbig((m/10),7); 311 if (m == 0) { // hours change 312 h = now.hour(); // read hours 313 printbig((h%10),3); // dislay hours 314 printbig((h/10),0); 315 if (h == 0) { // day change 316 dt = now.day(); // read day 317 dy = now.dayOfTheWeek(); 318 mt = now.month(); // read month 319 yr = now.year(); // read year 320 lcd.setCursor(0, 2); // display date full 321 lcd.print(DOW[dy]); 322 lcd.setCursor(4, 2); 323 lcd.print(dt/10); 324 lcd.print(dt%10); 325 lcd.setCursor(7, 2); 326 lcd.print(MTH[mt]); 327 } 328 } 329 } 330 // set screen brightness 331 light = (analogRead(A6)); 332 analogWrite(LED, 2+(light/4.2)); 333 334 // interior temperature/humidity/pression 335 if (intbme){ 336 intemp = round(bme1.readTemperature() - 1); 337 inhum = round(bme1.readHumidity()); 338 pres = round(bme1.readPressure() / 100.0F); 339 lcd.setCursor(11,2); 340 if (intemp>=0) { 341 lcd.print("["); 342 if (intemp<10) {lcd.print(" ");} 343 } 344 else { 345 if (intemp>(-10)) {lcd.print("[");} 346 } 347 lcd.print(intemp); 348 lcd.setCursor(15,2); 349 if (inhum<100) {lcd.print(" ");} 350 lcd.print(inhum); 351 lcd.setCursor(2,3); 352 if (pres < 1000) {lcd.print(" "); 353 if (pres < 100) {lcd.print(" ");} 354 } 355 lcd.print(pres); 356 } 357 // exterior temperature/humidity 358 if (extbme){ 359 temp = round(bme2.readTemperature()); 360 lcd.setCursor(11,3); 361 if (temp>=0) { 362 lcd.print(" "); 363 if (temp<10) {lcd.print(" ");} 364 } 365 else { 366 if (temp>(-10)) {lcd.print(" ");} 367 } 368 lcd.print(temp); 369 hum = round(bme2.readHumidity()); 370 lcd.setCursor(15,3); 371 if (hum<100) {lcd.print(" ");} 372 if (hum<10) {lcd.print(" ");} 373 lcd.print(hum); 374 } 375 // do other things every second 376 } 377 delay (100); 378} 379 380void timeset() 381{ 382 // set year 383 if (digitalRead(clearButton) == LOW ) { 384 delay (10); 385 analogWrite(LED, 150); 386 if (digitalRead(clearButton) == LOW ) { // debounce switch set year 387 set_yr = true; // set year 388 set_mt = false; 389 set_dt = false; 390 set_h = false; 391 set_m = false; 392 set_s = false; 393 encoderPos = yr; 394 // blanks the time munbers 395 lcd.setCursor(0, 0); 396 lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __"); // char(165) is big point symbol 397 lcd.setCursor(0, 1); 398 lcd.print(" "+String(char(165))+" "+(char(165))+" "); 399 lcd.setCursor(0, 2); 400 lcd.print("Year: "); 401 delay (500); 402 while (digitalRead(clearButton) == HIGH ) { 403 yr = encoderPos; 404 lcd.setCursor(6, 2); 405 lcd.print(yr); 406 rotating = true; // reset the debouncer 407 if (lastReportedPos != encoderPos) { 408 lastReportedPos = encoderPos; 409 } 410 delay (100); // debounce again 411 } 412 rtc.adjust(DateTime(yr, mt, dt, h, m, s)); //write the RTC memory (YYYY, M, D, H, M, s) 413 analogWrite(LED, 0); // blink screen 414 delay(200); 415 analogWrite(LED, 150); 416 } 417 } 418 419 // set month 420 if (digitalRead(clearButton) == LOW ) { 421 delay (10); 422 if (digitalRead(clearButton) == LOW ) { // debounce switch set month 423 set_yr = false; // set month 424 set_mt = true; 425 set_dt = false; 426 set_h = false; 427 set_m = false; 428 set_s = false; 429 lcd.setCursor(0, 2); 430 lcd.print("___-__-___"); 431 encoderPos = mt; 432 delay (500); 433 while (digitalRead(clearButton) == HIGH ) { 434 mt = encoderPos; 435 lcd.setCursor(7, 2); 436 lcd.print(MTH[mt]); 437 rotating = true; // reset the debouncer 438 if (lastReportedPos != encoderPos) { 439 lastReportedPos = encoderPos; 440 } 441 delay (100); // debounce again 442 } 443 rtc.adjust(DateTime(yr, mt, dt, h, m, s)); 444 analogWrite(LED, 0); 445 delay(200); 446 analogWrite(LED, 150); 447 } 448 } 449 450 // set day of month 451 if (digitalRead(clearButton) == LOW ) { 452 delay (10); 453 if (digitalRead(clearButton) == LOW ) { // debounce switch set day of month 454 set_yr = false; // set day of month 455 set_mt = false; 456 set_dt = true; 457 set_h = false; 458 set_m = false; 459 set_s = false; 460 encoderPos = dt; 461 lcd.setCursor(0, 2); 462 lcd.print("___-__-___"); 463 delay (500); 464 while (digitalRead(clearButton) == HIGH ) { 465 dt = encoderPos+1; 466 lcd.setCursor(4, 2); 467 lcd.print(dt/10); 468 lcd.print(dt%10); 469 rotating = true; // reset the debouncer 470 if (lastReportedPos != encoderPos) { 471 lastReportedPos = encoderPos; 472 } 473 delay (100); // debounce again 474 } 475 rtc.adjust(DateTime(yr, mt, dt, h, m, s)); 476 analogWrite(LED, 0); 477 delay(200); 478 // fill the date 479 analogWrite(LED, 150); 480 lcd.setCursor(0, 2); 481 lcd.print(DOW[dy]); 482 lcd.setCursor(4, 2); 483 lcd.print(dt/10); 484 lcd.print(dt%10); 485 lcd.setCursor(7, 2); 486 lcd.print(MTH[mt]); 487 } 488 } 489 490 // set hours 491 if (digitalRead(clearButton) == LOW ) { 492 delay (10); 493 if (digitalRead(clearButton) == LOW ) { // debounce switch set hours 494 set_h = true; // set hours 495 set_m = false; 496 set_s = false; 497 encoderPos = h; 498 delay (500); 499 while (digitalRead(clearButton) == HIGH ) { 500 h = encoderPos; 501 lcd.setCursor(0, 0); 502 lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __"); // char(165) is big point symbol 503 lcd.setCursor(0, 1); 504 lcd.print(" "+String(char(165))+" "+(char(165))+" "); 505 printbig((h/10),0); 506 printbig((h%10),3); 507 rotating = true; // reset the debouncer 508 if (lastReportedPos != encoderPos) { 509 lastReportedPos = encoderPos; 510 } 511 delay (100); // debounce again 512 } 513 rtc.adjust(DateTime(yr, mt, dt, h, m, s)); 514 analogWrite(LED, 0); 515 delay(200); 516 analogWrite(LED, 150); 517 } 518 } 519 520 // set minutes 521 if (digitalRead(clearButton) == LOW ) { 522 delay (10); 523 if (digitalRead(clearButton) == LOW ) { // debounce switch set minutes 524 set_h = false; // set minutes 525 set_m = true; 526 set_s = false; 527 encoderPos = m; 528 delay (500); 529 while (digitalRead(clearButton) == HIGH ) { 530 m = encoderPos; 531 lcd.setCursor(0, 0); 532 lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __"); // char(165) is big point symbol 533 lcd.setCursor(0, 1); 534 lcd.print(" "+String(char(165))+" "+(char(165))+" "); 535 printbig(m/10,7); 536 printbig(m%10,10); 537 rotating = true; // reset the debouncer 538 if (lastReportedPos != encoderPos) { 539 lastReportedPos = encoderPos; 540 } 541 delay (100); // debounce again 542 } 543 rtc.adjust(DateTime(yr, mt, dt, h, m, s)); 544 analogWrite(LED, 0); 545 delay(200); 546 analogWrite(LED, 150); 547 } 548 } 549 550 // set seconds 551 if (digitalRead(clearButton) == LOW ) { 552 delay (10); 553 if (digitalRead(clearButton) == LOW ) { // debounce switch set seconds 554 set_h = false; // set seconds 555 set_m = false; 556 set_s = true; 557 encoderPos = s; 558 delay (500); 559 while (digitalRead(clearButton) == HIGH ) { 560 s = encoderPos; 561 lcd.setCursor(0, 0); 562 lcd.print(" __ __"+String(char(165))+" __ __"+(char(165))+" __ __"); // char(165) is big point symbol 563 lcd.setCursor(0, 1); 564 lcd.print(" "+String(char(165))+" "+(char(165))+" "); 565 printbig(s/10,14); 566 printbig(s%10,17); 567 rotating = true; // reset the debouncer 568 if (lastReportedPos != encoderPos) { 569 lastReportedPos = encoderPos; 570 } 571 delay (100); // debounce again 572 } 573 rtc.adjust(DateTime(yr, mt, dt, h, m, s)); 574 analogWrite(LED, 0); 575 delay(200); 576 analogWrite(LED, 150); 577 } 578 } 579 580 //fill in the clock numbers 581 printbig((h%10),3); 582 printbig((h/10),0); 583 printbig((m%10),10); 584 printbig((m/10),7); 585 printbig((s%10),17); 586 printbig((s/10),14); 587 588 // fill in the date 589 lcd.setCursor(0, 2); 590 lcd.print(DOW[dy]); 591 lcd.setCursor(4, 2); 592 lcd.print(dt/10); 593 lcd.print(dt%10); 594 lcd.setCursor(7, 2); 595 lcd.print(MTH[mt]); 596 597 DateTime now = rtc.now(); // read again the time 598} 599 600// Interrupt on A changing state 601void doEncoderA() { 602 // debounce 603 if (set_h) EncoderMax = 24; 604 else if (set_m) EncoderMax = 60; 605 else if (set_s) EncoderMax = 60; 606 else if (set_yr) EncoderMax = 3000; 607 else if (set_mt) EncoderMax = 12; 608 else if (set_dt) EncoderMax = 31; 609 if ( rotating ) delay (1); // wait a little until the bouncing is done 610 // Test transition, did things really change? 611 if ( digitalRead(encoderPinA) != A_set ) { // debounce once more 612 A_set = !A_set; 613 // adjust counter + if A leads B 614 if ( A_set && !B_set ) 615 encoderPos += 1; 616 encoderPos = (EncoderMax+encoderPos) % EncoderMax; 617 rotating = false; // no more debouncing until loop() hits again 618 } 619} 620 621// Interrupt on B changing state, same as A above 622void doEncoderB() { 623 if (set_h) EncoderMax = 24; 624 else if (set_m) EncoderMax = 60; 625 else if (set_s) EncoderMax = 60; 626 else if (set_yr) EncoderMax = 3000; 627 else if (set_mt) EncoderMax = 12; 628 else if (set_dt) EncoderMax = 31; 629 if ( rotating ) delay (1); 630 if ( digitalRead(encoderPinB) != B_set ) { 631 B_set = !B_set; 632 // adjust counter - 1 if B leads A 633 if ( B_set && !A_set ) 634 encoderPos -= 1; 635 encoderPos = (EncoderMax+encoderPos) % EncoderMax; 636 rotating = false; 637 } 638} 639 640 641void printbig(int i, int x) 642{ 643 // prints each segment of the big numbers 644 645 if (i == 0) { 646 lcd.setCursor(x,0); 647 lcd.write(8); 648 lcd.write(1); 649 lcd.write(2); 650 lcd.setCursor(x, 1); 651 lcd.write(3); 652 lcd.write(4); 653 lcd.write(5); 654 } 655 else if (i == 1) { 656 lcd.setCursor(x,0); 657 lcd.write(8); 658 lcd.write(255); 659 lcd.print(" "); 660 lcd.setCursor(x, 1); 661 lcd.print(" "); 662 lcd.write(255); 663 lcd.print(" "); 664 } 665 666 else if (i == 2) { 667 lcd.setCursor(x,0); 668 lcd.write(1); 669 lcd.write(6); 670 lcd.write(2); 671 lcd.setCursor(x, 1); 672 lcd.write(3); 673 lcd.write(7); 674 lcd.write(4); 675 } 676 677 else if (i == 3) { 678 lcd.setCursor(x,0); 679 lcd.write(1); 680 lcd.write(6); 681 lcd.write(2); 682 lcd.setCursor(x, 1); 683 lcd.write(4); 684 lcd.write(7); 685 lcd.write(5); 686 } 687 688 else if (i == 4) { 689 lcd.setCursor(x,0); 690 lcd.write(3); 691 lcd.write(4); 692 lcd.write(2); 693 lcd.setCursor(x, 1); 694 lcd.print(" "); 695 lcd.write(5); 696 } 697 698 else if (i == 5) { 699 lcd.setCursor(x,0); 700 lcd.write(255); 701 lcd.write(6); 702 lcd.write(1); 703 lcd.setCursor(x, 1); 704 lcd.write(7); 705 lcd.write(7); 706 lcd.write(5); 707 } 708 709 else if (i == 6) { 710 lcd.setCursor(x,0); 711 lcd.write(8); 712 lcd.write(6); 713 lcd.print(" "); 714 lcd.setCursor(x, 1); 715 lcd.write(3); 716 lcd.write(7); 717 lcd.write(5); 718 } 719 720 else if (i == 7) { 721 lcd.setCursor(x,0); 722 lcd.write(1); 723 lcd.write(1); 724 lcd.write(5); 725 lcd.setCursor(x, 1); 726 lcd.print(" "); 727 lcd.write(8); 728 lcd.print(" "); 729 } 730 731 else if (i == 8) { 732 lcd.setCursor(x,0); 733 lcd.write(8); 734 lcd.write(6); 735 lcd.write(2); 736 lcd.setCursor(x, 1); 737 lcd.write(3); 738 lcd.write(7); 739 lcd.write(5); 740 } 741 742 else if (i == 9) { 743 lcd.setCursor(x,0); 744 lcd.write(8); 745 lcd.write(6); 746 lcd.write(2); 747 lcd.setCursor(x, 1); 748 lcd.print(" "); 749 lcd.write(4); 750 lcd.write(5); 751 } 752 753 }
Downloadable files
Electric Diagram
Electric diagram - modules connection
Electric Diagram
Electric Diagram
Electric diagram - modules connection
Electric Diagram
Documentation
Big Characters Map
Custom characters for big font
Big Characters Map
Big Characters Map
Custom characters for big font
Big Characters Map
Comments
Only logged in users can leave comments