Unusual Led Ring Arduino Clock, Temperature, and Humidity meter
Although this is a very simple Arduino project, it contains more different options, as well as a very intuitive way to show a lot of information on the "Display" consisting of only 12 LEDs.
Components and supplies
1
Arduino Nano
1
Piezo Buzzer
1
Push Button
1
DHT11 Temperature & Humidity Sensor (4 pins)
1
Adafruit RTC DS3231 Real time clock
1
LED Ring
Tools and machines
1
Soldering kit
Apps and platforms
1
Arduino IDE
Project description
Code
code
cpp
...
1#include <Wire.h> 2//#include <Math.h> 3#include <RTClib.h> 4#include <Adafruit_NeoPixel.h> 5#include <SimpleDHT.h> 6 7//Pin setup 8const int DHT_PIN = 2; 9const int NEO_PIN = 6; 10const int BUZZER_PIN = 9; 11const int BTN_PIN = 4; //2.2kohm pullup 12 13//Pushbutton 14bool btn_down_short = false; 15bool btn_down_long = false; 16bool btn_ignore = false; 17bool btn_was_down = false; 18unsigned long btn_down_started = 0; 19 20//Temp and Humidity Sensor 21SimpleDHT11 dht11; 22byte temperature = 0; 23byte humidity = 0; 24 25//Neopixel Ring (12 LEDs) 26Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, 6, NEO_GRB + NEO_KHZ800); 27 28//RTC (Real Time Clock Breakout) 29RTC_DS3231 ds3231; 30 31//Keep track of milliseconds between seconds 32int last_sec_five = 0; 33unsigned long last_sec_five_millis = 0; 34 35//Needed to keep track of datetime editing 36unsigned long edit_date_blink_millis = 0; 37int edit_time_hour = 0; 38int edit_time_min = 0; 39 40//RTC time 41int rtc[7]; //sec,min,hour,dow,day,month,year 42unsigned long rtc_last_refreshed = 0; 43 44//The state to keep track of navigation 45String state = ""; 46 47//The default brightness level of the LEDs 48int brightness = 20; //1 - 255 49int edit_brightness_state = 1; 50 51void setup() 52{ 53 Serial.begin(9600); 54 55 delay(3000); 56 57 state = "setup_pins"; 58 setupPins(); 59 Serial.println("Pin setup done"); 60 61 state = "rtc_setup"; 62 setupRtc(); 63 Serial.println("RTC setup done."); 64 65 setupNeo(); 66 Serial.print("LED brightness defaulted to: "); 67 Serial.println(brightness); 68 69 state = "led_test"; 70 ledTest(); 71 Serial.println("LED test done."); 72 73 state = "show_time"; 74} 75 76void loop() 77{ 78 Serial.print(rtc[2]); Serial.print(":"); 79 Serial.print(rtc[1]); Serial.print(":"); 80 Serial.print(rtc[0]); Serial.print(" -- "); 81 Serial.print((int)(((int)temperature * 9)/5) + 32); Serial.print(" -- "); 82 Serial.print(humidity); Serial.print(" -- "); 83 Serial.println(brightness); 84 85 unsigned long current_millis = millis(); 86 87 checkButtonState(); 88 89 //Refresh RTC time buffer every second 90 if(millis() - rtc_last_refreshed > 1000 || rtc_last_refreshed > millis()) 91 { 92 rtc_last_refreshed = millis(); 93 getDateTime(); 94 getDhtData(); 95 } 96 97 //Keep track of milliseconds between each multiples of 5 seconds 98 if(rtc[0]/5 != last_sec_five) 99 { 100 last_sec_five = rtc[0]/5; 101 last_sec_five_millis = millis(); 102 } 103 104 if(state == "edit_time") 105 { 106 state = "edit_hour"; 107 } 108 else if(state == "edit_hour") 109 { 110 if(btn_down_long) 111 { 112 state = "edit_minute"; 113 } 114 else 115 { 116 editHour(); 117 } 118 } 119 else if(state == "edit_minute") 120 { 121 if(btn_down_long) 122 { 123 //User just finished editing the time, set the entered time in RTC 124 setDateTime(0, edit_time_min, edit_time_hour, rtc[3], rtc[4], rtc[5], rtc[6]); 125 printRtcToSerial(); 126 state = "show_time"; 127 } 128 else 129 { 130 editMinute(); 131 } 132 } 133 else if(state == "show_temperature") 134 { 135 if(btn_down_short) 136 { 137 state = "show_humidity"; 138 } 139 else if(btn_down_long) 140 { 141 142 } 143 else 144 { 145 showTemperature(); 146 } 147 } 148 else if(state == "show_humidity") 149 { 150 if(btn_down_short) 151 { 152 state = "show_brightness"; 153 } 154 else if(btn_down_long) 155 { 156 157 } 158 else 159 { 160 showHumidity(); 161 } 162 } 163 else if(state == "edit_brightness") 164 { 165 if(btn_down_long) 166 { 167 state = "show_brightness"; 168 } 169 else 170 { 171 editBrightness(); 172 } 173 } 174 else if(state == "show_brightness") 175 { 176 if(btn_down_short) 177 { 178 state = "show_time"; 179 } 180 if(btn_down_long) 181 { 182 state = "edit_brightness"; 183 } 184 else 185 { 186 showBrightness(); 187 } 188 } 189 else 190 { 191 if(btn_down_short) 192 { 193 state = "show_temperature"; 194 } 195 else if(btn_down_long) 196 { 197 state = "edit_time"; 198 } 199 else 200 { 201 showTime(rtc[2], rtc[1], rtc[0]); 202 } 203 } 204} 205 206void setupPins() 207{ 208 pinMode(BUZZER_PIN, OUTPUT); 209 pinMode(BTN_PIN, INPUT); 210} 211 212void setupRtc() 213{ 214 if(!ds3231.begin()) 215 { 216 Serial.println("Couldn't find RTC"); 217 while (1); 218 } 219 220 if(ds3231.lostPower()) 221 { 222 Serial.println("RTC lost power, lets set the time!"); 223 ds3231.adjust(DateTime(F(__DATE__), F(__TIME__))); 224 } 225 226 getDateTime(); 227 printRtcToSerial(); 228} 229 230void printRtcToSerial() 231{ 232 Serial.print("RTC set to: "); 233 Serial.print(rtc[5]); Serial.print("/"); 234 Serial.print(rtc[4]); Serial.print("/"); 235 Serial.print(rtc[6]); Serial.print(" "); 236 Serial.print(rtc[2]); Serial.print(":"); 237 Serial.print(rtc[1]); Serial.print(":"); 238 Serial.println(rtc[0]); 239} 240 241void setupNeo() 242{ 243 strip.begin(); 244 strip.show(); 245 strip.setBrightness(brightness); 246} 247 248void ledTest() 249{ 250 clearNeo(); 251 strip.setPixelColor(0, 255, 255, 255); 252 strip.show(); 253 delay(1000); 254 255 for(int p=0; p <= 11; p++) 256 { 257 clearNeo(); 258 strip.setPixelColor(p , 255, 0, 0); 259 strip.show(); 260 delay(50); 261 } 262 263 for(int p=0; p <= 11; p++) 264 { 265 clearNeo(); 266 strip.setPixelColor(p , 0, 255, 0); 267 strip.show(); 268 delay(50); 269 } 270 271 for(int p=0; p <= 11; p++) 272 { 273 clearNeo(); 274 strip.setPixelColor(p , 0, 0, 255); 275 strip.show(); 276 delay(50); 277 } 278} 279 280void getDateTime() 281{ 282 DateTime now = ds3231.now(); 283 rtc[0] = now.second(); 284 rtc[1] = now.minute(); 285 rtc[2] = now.hour(); 286 rtc[3] = now.dayOfTheWeek(); 287 rtc[4] = now.day(); 288 rtc[5] = now.month(); 289 rtc[6] = now.year(); 290} 291 292void setDateTime(int sec, int min, int hour, int dow, int day, int month, int year) 293{ 294 ds3231.adjust(DateTime(year, month, day, hour, min, sec)); 295 296 getDateTime(); 297 298 edit_time_hour = 0; 299 edit_time_min = 0; 300} 301 302void showTime(int show_hour, int show_minute, int show_second) 303{ 304 int five_millis = millis() - last_sec_five_millis; 305 five_millis = five_millis <= 5000 ? five_millis : 5000; 306 int second_ratio = map(five_millis, 0, 5000, 0, 255); 307 int second = (show_second/5)+1; 308 309 int minute_ratio = map(((show_minute % 5)*10), 0, 50, 0, 255); 310 int minute = (show_minute/5)+1; 311 312 int hour_ratio = map(show_minute, 0, 60, 0, 255); 313 int hour = (show_hour > 12 ? show_hour-12 : show_hour); 314 315 for(int x=0; x < 13; x++) 316 { 317 int r = 0; 318 int g = 0; 319 int b = 0; 320 321 if(second-1 == x) 322 { 323 g = 255-second_ratio; 324 } 325 if(second == x || (second == 12 && x == 0)) 326 { 327 g = second_ratio; 328 } 329 if(minute-1 == x) 330 { 331 b = 255-minute_ratio; 332 } 333 if(minute == x) 334 { 335 b = minute_ratio; 336 } 337 if(hour-1 == x) 338 { 339 r = 255-hour_ratio; 340 } 341 if(hour == x) 342 { 343 r = hour_ratio; 344 } 345 346 strip.setPixelColor(x, r, g, b); 347 } 348 349 strip.show(); 350 delay(40); 351} 352 353void editHour() 354{ 355 if(edit_time_hour == 0) 356 { 357 edit_time_hour = rtc[2]; 358 edit_time_hour = (edit_time_hour > 24 ? edit_time_hour-24 : edit_time_hour); 359 } 360 361 if(btn_down_short) 362 { 363 edit_time_hour = (edit_time_hour > 23 ? edit_time_hour = 1 : edit_time_hour + 1); 364 } 365 366 clearNeo(); 367 if(edit_time_hour > 12) 368 { 369 strip.setPixelColor(edit_time_hour-13 , 120, 0, 120); 370 } 371 else 372 { 373 strip.setPixelColor(edit_time_hour-1 , 255, 0, 0); 374 } 375 strip.show(); 376 delay(40); 377} 378 379void editMinute() 380{ 381 if(edit_time_min == 0) 382 { 383 edit_time_min = rtc[1]; 384 } 385 386 if(btn_down_short) 387 { 388 edit_time_min = (edit_time_min >= 59 ? edit_time_min = 1 : edit_time_min + 1); 389 } 390 391 int minute_ratio = map(((edit_time_min % 5)*10), 0, 50, 0, 255); 392 int minute = (edit_time_min/5); 393 394 clearNeo(); 395 strip.setPixelColor(minute-1, 0, 0, 255-minute_ratio); 396 strip.setPixelColor(minute , 0, 0, minute_ratio); 397 strip.show(); 398 delay(40); 399} 400 401void showBrightness() 402{ 403 clearNeo(); 404 strip.setPixelColor(0, 255, 0, 0); 405 strip.setPixelColor(1, 255, 0, 0); 406 strip.setPixelColor(2, 255, 0, 0); 407 strip.setPixelColor(3, 255, 0, 0); 408 strip.setPixelColor(4, 0, 255, 0); 409 strip.setPixelColor(5, 0, 255, 0); 410 strip.setPixelColor(6, 0, 255, 0); 411 strip.setPixelColor(7, 0, 255, 0); 412 strip.setPixelColor(8, 0, 0, 255); 413 strip.setPixelColor(9, 0, 0, 255); 414 strip.setPixelColor(10, 0, 0, 255); 415 strip.setPixelColor(11, 0, 0, 255); 416 strip.show(); 417 delay(100); 418} 419 420void editBrightness() 421{ 422 if(btn_down_short) 423 { 424 brightness = (brightness >= 236 ? brightness = 20 : brightness + 20); 425 strip.setBrightness(brightness); 426 } 427 428 429 edit_brightness_state = (edit_brightness_state >= 12 ? edit_brightness_state = 1 : edit_brightness_state + 1); 430 int p = edit_brightness_state; 431 432 clearNeo(); 433 strip.setPixelColor(0, (p == 1 ? 255 : 50), 0, 0); 434 strip.setPixelColor(1, (p == 2 ? 255 : 50), 0, 0); 435 strip.setPixelColor(2, (p == 3 ? 255 : 50), 0, 0); 436 strip.setPixelColor(3, (p == 4 ? 255 : 50), 0, 0); 437 strip.setPixelColor(4, 0, (p == 5 ? 255 : 50), 0); 438 strip.setPixelColor(5, 0, (p == 6 ? 255 : 50), 0); 439 strip.setPixelColor(6, 0, (p == 7 ? 255 : 50), 0); 440 strip.setPixelColor(7, 0, (p == 8 ? 255 : 50), 0); 441 strip.setPixelColor(8, 0, 0, (p == 9 ? 255 : 50)); 442 strip.setPixelColor(9, 0, 0, (p == 10 ? 255 : 50)); 443 strip.setPixelColor(10, 0, 0, (p == 11 ? 255 : 50)); 444 strip.setPixelColor(11, 0, 0, (p == 12 ? 255 : 50)); 445 strip.show(); 446 delay(50); 447} 448 449void showTemperature() 450{ 451 clearNeo(); 452 for(int x=0; x < 12; x++) 453 { 454 strip.setPixelColor(x, 15, 15, 0); 455 } 456 457 int temp = (int)(((int)temperature * 9)/5) + 32; 458 459 if(temp > 0 && temp <= 12) 460 { 461 strip.setPixelColor(temp, 255, 0, 0); 462 } 463 else if(temp > 12 && temp <= 99) 464 { 465 int first_int = nthDigit(temp, 1)-1; 466 int second_int = nthDigit(temp, 2)-1; 467 if(first_int == second_int) 468 { 469 strip.setPixelColor(nthDigit(temp, 1)-1, 255, 0, 255); 470 } 471 else 472 { 473 strip.setPixelColor(nthDigit(temp, 1)-1, 255, 0, 0); 474 strip.setPixelColor(nthDigit(temp, 2)-1, 0, 0, 255); 475 } 476 } 477 strip.show(); 478 delay(40); 479} 480 481void showHumidity() 482{ 483 clearNeo(); 484 for(int x=0; x < 12; x++) 485 { 486 strip.setPixelColor(x, 0, 0, 15); 487 } 488 489 int hum = (int)humidity; 490 491 if(hum > 0 && hum <= 12) 492 { 493 strip.setPixelColor(hum, 255, 0, 0); 494 } 495 else if(hum > 12 && hum <= 99) 496 { 497 int first_int = nthDigit(hum, 1)-1; 498 int second_int = nthDigit(hum, 2)-1; 499 if(first_int == second_int) 500 { 501 strip.setPixelColor(first_int, 255, 0, 255); 502 } 503 else 504 { 505 strip.setPixelColor(first_int, 255, 0, 0); 506 strip.setPixelColor(second_int, 0, 0, 255); 507 } 508 } 509 strip.show(); 510 delay(40); 511} 512 513int nthDigit(int x, int n) 514{ 515 if(x <= 0 || x >= 100) 516 { 517 return 0; 518 } 519 if(x > 0 && x < 10) 520 { 521 return x; 522 } 523 if(n == 2) 524 { 525 return x-floor(x/10)*10; 526 } 527 if(n == 1) 528 { 529 return floor(x/10); 530 } 531} 532 533void clearNeo() 534{ 535 strip.setPixelColor(0, 0, 0, 0); 536 strip.setPixelColor(1, 0, 0, 0); 537 strip.setPixelColor(2, 0, 0, 0); 538 strip.setPixelColor(3, 0, 0, 0); 539 strip.setPixelColor(4, 0, 0, 0); 540 strip.setPixelColor(5, 0, 0, 0); 541 strip.setPixelColor(6, 0, 0, 0); 542 strip.setPixelColor(7, 0, 0, 0); 543 strip.setPixelColor(8, 0, 0, 0); 544 strip.setPixelColor(9, 0, 0, 0); 545 strip.setPixelColor(10, 0, 0, 0); 546 strip.setPixelColor(11, 0, 0, 0); 547} 548 549void checkButtonState() 550{ 551 //Is the button being press right now 552 bool btn_is_pressed = digitalRead(BTN_PIN) == LOW ? false : true; 553 554 //If the button long press was registered in the last loop, stop it in this loop 555 if(btn_down_long) 556 { 557 btn_down_long = false; 558 } 559 560 //If a long press was registered in the last loop, and user is still pushing, ignore it 561 if(!btn_ignore) 562 { 563 //If the button is being pressed now and was not being pressed before, start counting press time 564 if(btn_is_pressed && !btn_was_down) 565 { 566 btn_down_started = millis(); 567 tone(BUZZER_PIN, 2000); delay(200); noTone(BUZZER_PIN); 568 } 569 570 //If button is not pressed now and was pressed before, register short press 571 if(!btn_is_pressed && btn_was_down) 572 { 573 btn_down_short = true; 574 } 575 else 576 { 577 btn_down_short = false; 578 } 579 580 //If button is pressed now and has been pressed for more than 2 sec, register long press 581 if(btn_is_pressed && btn_was_down && (millis() - btn_down_started) > 2000) 582 { 583 btn_down_long = true; 584 585 //Ignore the button press until the user lets go 586 btn_ignore = true; 587 tone(BUZZER_PIN, 2000); delay(200); noTone(BUZZER_PIN); 588 tone(BUZZER_PIN, 2000); delay(200); noTone(BUZZER_PIN); 589 } 590 else 591 { 592 btn_down_long = false; 593 } 594 } 595 596 //If the user last did a long press and now they have let go, do not ignore button press anymore 597 if(btn_was_down && !btn_is_pressed) 598 { 599 btn_ignore = false; 600 } 601 602 //Let this loops button state be known in the next loop 603 btn_was_down = btn_is_pressed; 604} 605 606void getDhtData() 607{ 608 dht11.read(DHT_PIN, &temperature, &humidity, NULL); 609}
Downloadable files
schematic
...
Schematic.jpg

Comments
Only logged in users can leave comments