Alarm Clock with Stopwatch
Yet another clock, with 12 and 24 hour mode, alarm and stopwatch using my own library (included) for controlling a 4x7 segment display.
Components and supplies
4-digit 7-segment LED display
Buzzer
Arduino UNO
Pushbutton switch 12mm
Resistor 10k ohm
Resistor 100 ohm
Resistor 330 ohm
Project description
Code
ShiftReg.zip
arduino
ShiftReg library as a zip file
1inary file (no preview
Display library
arduino
Library for controlling the 4-digit 7-segment LED display, used by the clock code
1inary file (no preview
Clock.ino
snippets
1/* 2 Digital alarm clock with stopwatch function 3*/ 4 5#include 6 <Display4x7.h> // Display library is required 7 8/* 9 Define 10 ports to control the 4x7 segment display 11*/ 12const int digit[] = {13, 12, 11, 13 10}; 14const int segment[] = {2, 3, 4, 5, 6, 7, 8, 9}; 15const int BuzzerPin = 16 A4; 17const int ButtonPin = A5; 18 19/* 20 Other definitions 21*/ 22const 23 unsigned int OnTime = 250; // When blinking, this is the time the display is 24 on 25const unsigned int OffTime = 250; // When blinking, this is the time the 26 display is off 27const int Step = 10; // Milliseconds resolution 28 of the clock (1/100 sec) 29const unsigned int Refresh = 6500; // Display refresh 30 rate in microseconds 31unsigned long MaxSec = 86400U; // Seconds in a day 32 33const 34 unsigned int am_pattern = 0x02; // AM indicated by top left segment 35const unsigned 36 int pm_pattern = 0x04; // PM indicated by lower left segment 37const unsigned int 38 h_pattern = 0x2EU; // Smaal 'h' in clock mode setting 39const unsigned int r_pattern 40 = 0x0AU; // Small 'r' in clock mode setting 41 42/* 43 Button settings 44 45 Using a 4 resistor ladder, 1 pin can read 3 buttons 46 Nominal values: 47 48 - button 1: 0V (read value: 0) 49 - button 2: 2.5V (read value: 50 512) 51 - button 3: 3.33V (read value: 682) 52 - No button: 3.75V (read 53 value: 768) 54*/ 55unsigned long debounceTime = 500; // millisec before new 56 button input is scanned 57const int Button1 = 256; // Threshold for 58 button 1 59const int Button2 = 597; // Threshold for button 2 60const 61 int Button3 = 725; // Threshold for button 3 62 63/* 64 The clock 65 has different modes, switched by the "Mode" button. 66 Button actions depend 67 on the clock's current mode 68*/ 69enum Mode { Clock, 70 ClockSet, 71 ClockModeSet, 72 AlarmSet, 73 Stopwatch 74 }; 75 76/* 77 78 Action resulting from button presses during clock/alarm time set 79*/ 80enum 81 SetAction { None, NextMode, Increment, Shift, Accept }; 82 83/* 84 The clock's 85 operating modes 86*/ 87enum Mode mode = Clock; // Current clock 88 mode 89bool Hr24 = true; // 24-hour mode, false for 12-hour 90bool 91 Seconds = false; // Showing hours.minutes, true if showing minutes.seconds 92 instead 93bool AlarmOn = false; // Alarm on 94unsigned AlarmFreq 95 = 400; // Alarm sound frequency 96unsigned long SnoozeTime = 420UL; 97 // Snooze time (7 minutes = 420 seconds) 98unsigned long MaxAlarmMs = 600000UL; 99 // Max alarm time (10 minutes = 600000 millisecs) 100 101/* 102 Variables that 103 hold the clock's actual state 104*/ 105Display4x7 d(digit, segment, Refresh);// 106 The display 107unsigned long sc = 0; // The clock's value 108unsigned 109 long alarm = 0; // The alarm time in seconds 110bool alarmSounding 111 = false; // True if the buzzer is on 112unsigned long alarmAutoOff = 0; 113 // Indicates when the alarm automatically switches off 114unsigned long snooze 115 = 0; // Time to end snooze period 116unsigned long stopwatch = 0; // 117 Stopwatch time 118bool stopwatchRunning = false; // Indicates that the stopwatch 119 is running 120unsigned long laptime; // Lap time when using stopwatch 121bool 122 showLapTime = false; // Show lap time 123unsigned long clockset = 0; 124 // Used for setting the clock 125unsigned long alarmset = 0; // 126 Used for setting the alarm 127bool setMin = false; // During time 128 set: changing hours, true if changing minutes 129int hs = 0; // 130 1/100 seconds counter 131unsigned long count = 0; // Next 1/100 slice 132 counter 133unsigned long debounce = 0; // Debounce button counter 134 135void 136 setup() 137{ 138 pinMode(ButtonPin, INPUT); 139 pinMode(BuzzerPin, OUTPUT); 140 141 142 d.setup(); // Set-up display stuff 143 144 d.setDot(0, 145 AlarmOn); 146} 147 148/* 149 Show the time in hours and minutes on the display, 150 taking 12/24 151 hour mode into account 152*/ 153void showTime(unsigned int hours, 154 unsigned int minutes, bool isAm) 155{ 156 int h = hours % (Hr24 ? 24 : 12); // 157 Convert to 12 or 24 hours 158 159 h = (!Hr24 && h == 0 ? 12 : h); // 0 becomes 160 12 in 12-hr mode 161 162 d.setPair(h, minutes); // Display values 163 164 if (h < 10 || !Hr24) // Blank leading zero and set AM/PM 165 { 166 167 d.setSegments(3, // This concerns digit 3 (leftmost) 168 (h 169 > 9 ? Display4x7::Digit[1] // 1 170 : 0x00) // 171 else blank 172 | // combine 173 with 174 (Hr24 ? 0x00 : (isAm ? am_pattern // AM 175 : 176 0x04))); // else PM 177 } 178} 179 180/* 181 Set time using buttons: 182 183 - Mode button (1): change mode, setting cancelled 184 - Set button (2): 185 increment time by 1 minute or 1 hour 186 - Function button (3): accept input, 187 set next 188 189 Blinking digits show hours/minutes change 190*/ 191enum SetAction 192 setTime(bool& min, int button, unsigned long& set) 193{ 194 enum SetAction action 195 = None; // Action taken based on button press 196 197 switch (button) 198 199 { 200 case 1: // Mode button 201 action = NextMode; 202 203 break; 204 case 2: // Set button 205 set 206 += min ? 60UL : 3600UL; // Increment by 1 hour or 1 minute 207 if (set 208 > MaxSec) 209 { 210 set -= MaxSec; // Roll-over to zero 211 212 } 213 action = Increment; 214 break; 215 case 3: // 216 Function button 217 action = min ? Accept : Shift; // If changing hours, shift 218 to minutes 219 min = !min; // Shift to minutes and adjust 220 blinking digits 221 d.setBlink(0, min ? OnTime : 0, min ? OffTime : 0); 222 223 d.setBlink(1, min ? OnTime : 0, min ? OffTime : 0); 224 d.setBlink(2, 225 !min ? OnTime : 0, min ? OffTime : 0); 226 d.setBlink(3, !min ? OnTime : 0, 227 min ? OffTime : 0); 228 break; 229 } 230 showTime(set / 3600UL, (set / 60) 231 % 60, set < MaxSec / 2); 232 return action; 233} 234 235/* 236 * Switch the alarm 237 sound on and off 238 */ 239void switchAlarm(bool on, unsigned long currentMs) 240{ 241 242 alarmSounding = on; 243 if (on) 244 { 245 alarmAutoOff = currentMs + MaxAlarmMs; 246 // Alarm stops automatically after predefined time 247 } 248 else 249 { 250 251 noTone(BuzzerPin); 252 } 253} 254 255void loop() 256{ 257 unsigned long tm 258 = millis(); // Current time in milliseconds 259 int button = 0; // 260 Button pressed 261 262 d.update(); // Display update in 263 every loop 264 265 if (tm > debounce) // Prevent button read twice 266 very fast 267 { 268 int buttonVal = analogRead(ButtonPin); 269 270 debounce 271 = tm + 2UL; // Give the ADC time to settle 272 273 if (buttonVal 274 < Button1) // Convert button voltage to button number 275 { 276 button 277 = 1; 278 } 279 else if (buttonVal < Button2) 280 { 281 button = 2; 282 283 } 284 else if (buttonVal < Button3) 285 { 286 button = 3; 287 } 288 289 if (button > 0) 290 { 291 debounce = tm + debounceTime; // Stop reading 292 buttons for some time 293 } 294 } 295 296 unsigned int mn = (sc / 60) % 60; 297 // Calculate hours and minutes from time in seconds 298 unsigned int hr = (sc 299 / 3600U) % (Hr24 ? 24 : 12); 300 bool am = sc < MaxSec / 2; // AM is first 301 half of 24 hours 302 int hrsmode; // Used in setting 12/24 303 hours mode 304 unsigned int p[] = { 0, 0, 0, 0 }; // Used to display 12/24 hr 305 306 int dot; // Dot to show in stopwatch 307 bool dotOn; 308 // Dot state (true is on, false is off) 309 unsigned long 310 st; // Stopwatch time to display, adjusted to display size 311 312 313 hr = (!Hr24 && hr == 0 ? 12 : hr); // In 12 hour clock mode 0 is set to 12 314 315 316 if (tm > count) // The next 1/100 time slice is reached 317 318 { 319 hs++; // Next 1/100 second 320 if (stopwatchRunning) 321 // Stopwatch is also increased by 1/100 second when running 322 { 323 324 stopwatch++; 325 } 326 count += Step; // Set the 327 value for the next 1/100 second 328 if (hs == 100) // Next 329 second reached 330 { 331 sc++; // Increment time 332 with 1 second 333 if (sc >= MaxSec) 334 { 335 sc = 0; // 336 Roll-over to zero at midnight 337 } 338 hs = 0; // 339 Reset 1/100 second counter 340 341 if (AlarmOn && sc == snooze) // Alarm 342 should sound now 343 { 344 switchAlarm(true, tm); // ... 345 so switch it on 346 } 347 348 } 349 } 350 351 if (alarmSounding) // 352 The buzzer is on, make it beep 353 { 354 if (hs == 0) 355 { 356 tone(BuzzerPin, 357 AlarmFreq, 500); 358 } 359 if (tm > alarmAutoOff) // Auto off time 360 reached? 361 { 362 switchAlarm(false, tm); // If yes, switch off 363 the alarm 364 AlarmOn = false; 365 } 366 } 367 368 switch (mode) // 369 Determine display based on clock's current mode 370 { 371 case Clock: // 372 Regular clock mode 373 if (Seconds) 374 { 375 d.setPair(mn, sc 376 % 60); // Show minutes/seconds 377 } 378 else 379 { 380 showTime(hr, 381 mn, am); // Show hours/minutes 382 } 383 d.setDot(2, hs < 50); 384 // Blink dot between hours and minutes, 1 time/second 385 386 switch 387 (button) // Handle buttons in clock mode 388 { 389 case 390 1: 391 clockset = sc; // Clock set starts at current time 392 393 setMin = false; // Start setting the hours and make hours 394 blink 395 d.setBlink(2, OnTime, OffTime); 396 d.setBlink(3, OnTime, 397 OffTime); 398 d.setDot(0, false); // Alarm indicator is off when 399 setting clock time 400 d.setDot(2, true); // Hour/minute separator 401 is on 402 mode = ClockSet; // Next mode is clock set 403 break; 404 405 case 2: // Set button 406 if (alarmSounding) 407 // If the alarm is on, 408 { 409 switchAlarm(false, 410 tm); 411 snooze = sc + SnoozeTime; // New alarm time is SnoozeTime later 412 413 if (snooze > MaxSec) 414 { 415 snooze -= MaxSec; 416 // Roll-over 417 } 418 } 419 else 420 { 421 422 Seconds = !Seconds; // Toggle between hours/minutes and minutes/seconds 423 display 424 } 425 break; 426 case 3: // 427 Function button 428 if (alarmSounding) // If the alarm is on, 429 430 { 431 switchAlarm(false, tm); // ... switch it off now 432 433 AlarmOn = false; 434 } 435 else 436 { 437 438 AlarmOn = !AlarmOn; // ... otherwise toggle alarm on/off 439 } 440 441 d.setDot(0, AlarmOn); // Update alarm indicator 442 break; 443 444 } 445 break; 446 case ClockSet: // Clock time set 447 mode 448 switch (setTime(setMin, button, clockset)) // Handle time set 449 450 { 451 case NextMode: // Mode button pressed, ignore 452 new time 453 setMin = false; // Adjust digit blinking to hours 454 (for alarm set) 455 d.setBlink(2, OnTime, OffTime); 456 d.setBlink(3, 457 OnTime, OffTime); 458 d.setDot(0, true); // Alarm indicator is 459 on when setting alarm time 460 d.setDot(2, true); // Hour/minute 461 separator is on 462 mode = AlarmSet; // Next mode is alarm set 463 464 break; 465 case Accept: // New time set 466 d.setBlinkAll(OnTime, 467 OffTime); // Switch on blinking for clock mode set 468 sc = clockset; 469 // Current time becomes the time set 470 mode = ClockModeSet; 471 // Now move to 12/24-hour mode selction 472 break; 473 } 474 475 break; 476 case ClockModeSet: // Clock mode (12/24-hour) 477 setting 478 hrsmode = (Hr24 ? 2 : 1); // Set-up pattern to display "12hr" 479 or "24hr" 480 p[3] = (Display4x7::Digit[hrsmode] << 1); 481 p[2] = (Display4x7::Digit[2 482 * hrsmode] << 1); 483 p[1] = h_pattern; 484 p[0] = r_pattern; 485 486 487 d.setPatterns(p); // Display the current clock mode 488 switch 489 (button) // Handle buttons for clock mode set 490 { 491 case 492 1: // Mode or function button do not change current setting 493 494 case 3: 495 setMin = false; // Reset time set to hours 496 497 d.setBlinkAll(); // Switch off all blinking 498 d.setDot(0, 499 AlarmOn); // Update alarm indicator 500 mode = Clock; // 501 Back to clock mode 502 break; 503 case 2: // 504 The set button toggles the clock mode between 12 and 24 hours 505 Hr24 506 = !Hr24; 507 break; 508 } 509 break; 510 case AlarmSet: // 511 Alarm time set mode 512 switch (setTime(setMin, button, alarmset)) // Handle 513 time set 514 { 515 case NextMode: // Mode button pressed, 516 ignore new alarm time 517 d.setBlinkAll(); // Blinking off 518 519 setMin = false; // Reset time set to hours 520 mode 521 = Stopwatch; // Next mode is stopwatch 522 break; 523 case 524 Accept: // New alarm time set 525 d.setBlinkAll(); // 526 Blinking off 527 snooze = alarm = alarmset; // Set alarm and snooze times 528 to new time 529 AlarmOn = true; // Alarm is switched on 530 531 d.setDot(0, AlarmOn); // Update alarm indicator 532 mode 533 = Clock; // Back to clock mode 534 break; 535 } 536 537 break; 538 case Stopwatch: // Stopwatch mode 539 dot 540 = 2; // Determine where to place decimal point, start with 541 1/100 seconds 542 st = (showLapTime ? laptime : stopwatch); 543 dotOn 544 = stopwatchRunning ? (hs < 50) : true; // DP is only on in the first half second 545 546 if (st > 9999) // If stopwatch time goes beyond 9999/100 547 seconds... 548 { 549 dot = 1; // ... show only 550 1/10 of seconds 551 st /= 10UL; 552 } 553 if (st > 9999) // 554 If stopwatch time goes beyond 9999/10 seconds... 555 { 556 dot = 0; 557 // ... show seconds 558 st /= 10UL; 559 } 560 561 d.setNumber(st, false); // Show the stopwatch time 562 if (st 563 < 10) // If still under 0.1 seconds... 564 { 565 d.setDigit(1, 566 0); // ... set digit after DP to 0 567 } 568 d.setDot(2, dotOn 569 && dot == 2); // Show the decimal point at the right place 570 d.setDot(1, 571 dotOn && dot == 1); 572 d.setDot(0, dotOn && dot == 0); 573 switch (button) 574 575 { 576 case 1: // Mode button pressed 577 d.setDot(1, 578 false); // Update DP and alarm indicator for clock mode 579 d.setDot(0, 580 AlarmOn); 581 mode = Clock; // Back to clock mode (stopwatch 582 keeps running if on) 583 break; 584 case 2: // 585 Set button pressed 586 stopwatchRunning = !stopwatchRunning; // Start/stop 587 the stopwatch 588 break; 589 case 3: // Function 590 button pressed 591 if (stopwatchRunning || showLapTime) 592 { 593 594 laptime = stopwatch; // When running or showing lap time, 595 596 showLapTime = !showLapTime; // ... toggle lap time/stopwatch time 597 598 } 599 else 600 { 601 stopwatch = laptime 602 = 0; // When showing stopped time, reset stopwatch 603 } 604 break; 605 606 } 607 break; 608 } 609} 610
Display4x7.cpp
c_cpp
Display4x7 library code file. Save to your local Arduino/libraries/Display4x7/src folder
1#include <Display4x7.h> 2 3const unsigned int Display4x7::Digit[] = 4{ 5 0x7EU, // 0 6 0x30U, // 1 7 0x6DU, // 2 8 0x79U, // 3 9 0x33U, // 4 10 0x5BU, // 5 11 0x5FU, // 6 12 0x70U, // 7 13 0x7FU, // 8 14 0x7BU, // 9 15 0x77U, // A 16 0x1FU, // b 17 0x4EU, // C 18 0x3DU, // d 19 0x4FU, // E 20 0x47U // F 21}; 22bool Display4x7::_buf[][8] = 23{ 24 { false, false, false, false, false, false, false, false}, 25 { false, false, false, false, false, false, false, false}, 26 { false, false, false, false, false, false, false, false}, 27 { false, false, false, false, false, false, false, false} 28}; 29 30// Display4x7::Display4x7(const int digitPorts[], const int segmentPorts[], int onTime, bool commonCathode) 31// { 32 // int d; 33 // int s; 34 35 // for (d = 0; d < 4; d++) 36 // { 37 // _dgt[d] = digitPorts[d]; 38 // } 39 // for (s = 0; s < 8; s++) 40 // { 41 // _seg[s] = segmentPorts[s]; 42 // } 43 44 // for (d = 0; d < 4; d++) 45 // { 46 // for (s = 0; s < 8; s++) 47 // { 48 // _buf[d][s] = false; 49 // } 50 // } 51 52 // _onTime = onTime; 53 54 // _segOn = _dgtOff = commonCathode ? HIGH : LOW; 55 // _segOff = _dgtOn = commonCathode ? LOW : HIGH; 56// } 57 58Display4x7::Display4x7(const int digitPorts[], const int segmentPorts[], int onTime, bool commonCathode) 59{ 60 int d; 61 int s; 62 63 // for (d = 0; d < 4; d++) 64 // { 65 // _dgt[d] = digitPorts[d]; 66 // } 67 for (s = 0; s < 8; s++) 68 { 69 _seg[s] = segmentPorts[s]; 70 } 71 72 init(digitPorts, onTime, commonCathode); 73 // for (d = 0; d < 4; d++) 74 // { 75 // for (s = 0; s < 8; s++) 76 // { 77 // _buf[d][s] = false; 78 // } 79 // } 80 81 // _onTime = onTime; 82 83 // _segOn = _dgtOff = commonCathode ? HIGH : LOW; 84 // _segOff = _dgtOn = commonCathode ? LOW : HIGH; 85} 86 87Display4x7::Display4x7(const int digitPorts[], const ShiftReg& shift, int onTime, bool commonCathode) 88{ 89 _shift = &shift; 90 init(digitPorts, onTime, commonCathode); 91} 92 93void Display4x7::init(const int digitPorts[], int onTime, bool commonCathode) 94{ 95 int d; 96 int s; 97 98 for (d = 0; d < 4; d++) 99 { 100 _dgt[d] = digitPorts[d]; 101 } 102 // for (s = 0; s < 8; s++) 103 // { 104 // _seg[s] = segmentPorts[s]; 105 // } 106 107 for (d = 0; d < 4; d++) 108 { 109 for (s = 0; s < 8; s++) 110 { 111 _buf[d][s] = false; 112 } 113 } 114 115 _onTime = onTime; 116 117 _segOn = _dgtOff = commonCathode ? HIGH : LOW; 118 _segOff = _dgtOn = commonCathode ? LOW : HIGH; 119} 120 121void Display4x7::setDigit(int digit, unsigned int number) 122{ 123 setSegments(digit, Digit[number]); 124} 125 126void Display4x7::doNum(bool sign, unsigned int num, unsigned int base, bool leading) 127{ 128 unsigned int n = num; 129 int i; 130 131 for (i = 0; i < 4 && (i == 0 || n > 0); i++) 132 { 133 int d = n % base; 134 n /= base; 135 setSegments(i, Digit[d]); 136 } 137 for (; leading && i < (sign ? 3 : 4); i++) 138 { 139 setDigit(i, 0); 140 } 141 if (sign) 142 { 143 setPattern(i++, MinusPattern); 144 } 145 for (; i < 4; i++) 146 { 147 setSegments(i, 0x00); 148 } 149} 150 151void Display4x7::setNumber(long number, bool leadingZeroes) 152{ 153 int n = number < 0 ? -number : number; 154 int i; 155 156 doNum(number < 0, n, 10, leadingZeroes); 157} 158 159void Display4x7::setNumber(unsigned int number, unsigned int base, bool leadingZeroes) 160{ 161 doNum(false, number, base, leadingZeroes); 162} 163 164void Display4x7::setPair(unsigned int x, unsigned int y, unsigned int base) 165{ 166 int xy[] = { 0,0,0,0 }; 167 168 xy[0] = y % base; 169 xy[1] = y / base; 170 xy[2] = x % base; 171 xy[3] = x / base; 172 173 setDigits(xy); 174} 175 176void Display4x7::setDigits(const int digits[]) 177{ 178 for (int d = 0; d < 4; d++) 179 { 180 setSegments(d, Digit[digits[d]]); 181 } 182} 183 184void Display4x7::setSegments(int digit, unsigned int segments) 185{ 186 unsigned int p = segments; 187 188 for (int s = 0; s < 7; s++) 189 { 190 _buf[digit][6 - s] = ((p & 0x0001) > 0); 191 p >>= 1; 192 } 193} 194 195void Display4x7::setPattern(int digit, const bool pattern[]) 196{ 197 for (int s = 0; s < 8; s++) 198 { 199 _buf[digit][s] = pattern[s]; 200 } 201} 202 203void Display4x7::setPattern(int digit, unsigned int pattern) 204{ 205 unsigned int p = pattern; 206 207 for (int s = 0; s < 8; s++) 208 { 209 _buf[digit][7 - s] = ((p & 0x0001) > 0); 210 p >>= 1; 211 } 212} 213 214void Display4x7::setPatterns(unsigned int pattern[]) 215{ 216 for (int d = 0; d < 4; d++) 217 { 218 setPattern(d, pattern[d]); 219 } 220} 221void Display4x7::setDot(int digit, bool on) 222{ 223 _buf[digit][7] = on; 224} 225 226void Display4x7::setBlink(int digit, unsigned int onTime, unsigned int offTime) 227{ 228 _blinkOn[digit] = onTime * 1000UL; // usec 229 _blinkOff[digit] = offTime * 1000UL; 230 if (onTime == 0UL || offTime == 0UL) 231 { 232 _blinkOn[digit] = 0UL; // Blinking off 233 } 234 _blinkTimer[digit] = 0; 235 _blinkState[digit] = true; 236} 237 238void Display4x7::setBlinkAll(unsigned int onTime, unsigned int offTime) 239{ 240 for (int digit = 0; digit < 4; digit++) 241 { 242 setBlink(digit, onTime, offTime); 243 } 244} 245 246void Display4x7::setup() 247{ 248 int i; 249 250 for (i = 0; i < 4; i++) 251 { 252 pinMode(_dgt[i], OUTPUT); 253 } 254 if (_shift == NULL) 255 { 256 for (i = 0; i < 8; i++) 257 { 258 pinMode(_seg[i], OUTPUT); 259 } 260 } 261 else 262 { 263 _shift->setup(); 264 _shift->reset(); 265 _shift->enableOutput(); 266 } 267 setBlinkAll(); 268 _currentDigit = 0; 269 _refresh = 0; 270} 271 272void Display4x7::update() 273{ 274 unsigned long time = micros(); 275 276 for (int d = 0; d < 4; d++) 277 { 278 if (_blinkOn[d] > 0) 279 { 280 if (time >= _blinkTimer[d]) 281 { 282 _blinkState[d] = !_blinkState[d]; 283 _blinkTimer[d] = time + (_blinkState[d] ? _blinkOn[d] : _blinkOff[d]); 284 } 285 } 286 } 287 288 if (time >= _refresh) 289 { 290 digitalWrite(_dgt[_currentDigit], _dgtOff); 291 _currentDigit++; 292 if (_currentDigit >= 4) 293 { 294 _currentDigit = 0; 295 } 296 for (int s = 0; s < 8; s++) 297 { 298 if (_shift == NULL) 299 { 300 digitalWrite(_seg[s], Display4x7::_buf[_currentDigit][s] ? _segOn : _segOff); 301 } 302 else 303 { 304 _shift->loadBit(Display4x7::_buf[_currentDigit][7 - s]); 305 } 306 } 307 if (_shift != NULL) 308 { 309 _shift->latch(); 310 } 311 digitalWrite(_dgt[_currentDigit], _blinkState[_currentDigit] ? _dgtOn : _dgtOff); 312 _refresh += _onTime; 313 } 314}
Display4x7.h
h
Display4x7 library header file. Save to your local Arduino/libraries/Display4x7/src folder
1#ifndef _display4x7_h_ 2#define _display4x7_h_ 3 4#include <Arduino.h> 5#include 6 <ShiftReg.h> 7 8#define DfltOnTime 5500 9 10#define MinusPattern 0x02 11 12class 13 Display4x7 14{ 15 public: 16 static const unsigned int Digit[]; 17 18 Display4x7(const 19 int digitPorts[], const int segmentPorts[], int onTime = DfltOnTime, bool commonCathode 20 = true); 21 Display4x7(const int digitPorts[], const ShiftReg& shift, int onTime 22 = DfltOnTime, bool commonCathode = true); 23 24 void setDigit(int digit, unsigned 25 int number); 26 void setNumber(long number, bool leadingZeroes); 27 void 28 setNumber(unsigned int number, unsigned int base = 10, bool leadingZeroes = false); 29 void 30 setPair(unsigned int x, unsigned int y, unsigned int base = 10); 31 void setDigits(const 32 int digits[]); 33 34 void setSegments(int digit, unsigned int segments); 35 void 36 setPattern(int digit, unsigned int pattern); 37 void setPatterns(unsigned int 38 pattern[]); 39 void setPattern(int digit, const bool pattern[]); 40 void 41 setDot(int digit, bool on); 42 43 void setBlink(int digit, unsigned int onTime 44 = 0, unsigned int offTime = 0); 45 void setBlinkAll(unsigned int onTime = 0, 46 unsigned int offTime = 0); 47 48 void setup(); 49 void update(); 50 51 protected: 52 void 53 init(const int digitPorts[], int onTime, bool commonCathode); 54 void doNum(bool 55 sign, unsigned int num, unsigned int base, bool leading); 56 57 int _currentDigit 58 = 0; 59 unsigned long _refresh = 0UL; 60 61 int _onTime; 62 int 63 _segOn; 64 int _segOff; 65 int _dgtOn; 66 int _dgtOff; 67 68 int 69 _seg[8]; 70 int _dgt[4]; 71 static bool _buf[][8]; 72 unsigned long 73 _blinkOn[4]; 74 unsigned long _blinkOff[4]; 75 bool _blinkState[4]; 76 unsigned 77 long _blinkTimer[4]; 78 79 const ShiftReg* _shift = NULL; 80}; 81 82#endif 83
library.properties
properties
Display4x7 library properties file. Save to your local Arduino/libraries/Display4x7 folder
1name=Display4x7 2version=1.0.0 3author=Qixaz 4maintainer=Qixaz (www.qixaz.com) 5sentence=4x7 6 segment display control 7paragraph=Library to send numbers and other patterns 8 to a 4x7 segment display 9category=Communication 10url=http://www.qixaz.com 11architectures=* 12dot_a_linkage=true 13
Display4x7.cpp
c_cpp
Display4x7 library code file. Save to your local Arduino/libraries/Display4x7/src folder
1#include <Display4x7.h> 2 3const unsigned int Display4x7::Digit[] = 4{ 5 0x7EU, // 0 6 0x30U, // 1 7 0x6DU, // 2 8 0x79U, // 3 9 0x33U, // 4 10 0x5BU, // 5 11 0x5FU, // 6 12 0x70U, // 7 13 0x7FU, // 8 14 0x7BU, // 9 15 0x77U, // A 16 0x1FU, // b 17 0x4EU, // C 18 0x3DU, // d 19 0x4FU, // E 20 0x47U // F 21}; 22bool Display4x7::_buf[][8] = 23{ 24 { false, false, false, false, false, false, false, false}, 25 { false, false, false, false, false, false, false, false}, 26 { false, false, false, false, false, false, false, false}, 27 { false, false, false, false, false, false, false, false} 28}; 29 30// Display4x7::Display4x7(const int digitPorts[], const int segmentPorts[], int onTime, bool commonCathode) 31// { 32 // int d; 33 // int s; 34 35 // for (d = 0; d < 4; d++) 36 // { 37 // _dgt[d] = digitPorts[d]; 38 // } 39 // for (s = 0; s < 8; s++) 40 // { 41 // _seg[s] = segmentPorts[s]; 42 // } 43 44 // for (d = 0; d < 4; d++) 45 // { 46 // for (s = 0; s < 8; s++) 47 // { 48 // _buf[d][s] = false; 49 // } 50 // } 51 52 // _onTime = onTime; 53 54 // _segOn = _dgtOff = commonCathode ? HIGH : LOW; 55 // _segOff = _dgtOn = commonCathode ? LOW : HIGH; 56// } 57 58Display4x7::Display4x7(const int digitPorts[], const int segmentPorts[], int onTime, bool commonCathode) 59{ 60 int d; 61 int s; 62 63 // for (d = 0; d < 4; d++) 64 // { 65 // _dgt[d] = digitPorts[d]; 66 // } 67 for (s = 0; s < 8; s++) 68 { 69 _seg[s] = segmentPorts[s]; 70 } 71 72 init(digitPorts, onTime, commonCathode); 73 // for (d = 0; d < 4; d++) 74 // { 75 // for (s = 0; s < 8; s++) 76 // { 77 // _buf[d][s] = false; 78 // } 79 // } 80 81 // _onTime = onTime; 82 83 // _segOn = _dgtOff = commonCathode ? HIGH : LOW; 84 // _segOff = _dgtOn = commonCathode ? LOW : HIGH; 85} 86 87Display4x7::Display4x7(const int digitPorts[], const ShiftReg& shift, int onTime, bool commonCathode) 88{ 89 _shift = &shift; 90 init(digitPorts, onTime, commonCathode); 91} 92 93void Display4x7::init(const int digitPorts[], int onTime, bool commonCathode) 94{ 95 int d; 96 int s; 97 98 for (d = 0; d < 4; d++) 99 { 100 _dgt[d] = digitPorts[d]; 101 } 102 // for (s = 0; s < 8; s++) 103 // { 104 // _seg[s] = segmentPorts[s]; 105 // } 106 107 for (d = 0; d < 4; d++) 108 { 109 for (s = 0; s < 8; s++) 110 { 111 _buf[d][s] = false; 112 } 113 } 114 115 _onTime = onTime; 116 117 _segOn = _dgtOff = commonCathode ? HIGH : LOW; 118 _segOff = _dgtOn = commonCathode ? LOW : HIGH; 119} 120 121void Display4x7::setDigit(int digit, unsigned int number) 122{ 123 setSegments(digit, Digit[number]); 124} 125 126void Display4x7::doNum(bool sign, unsigned int num, unsigned int base, bool leading) 127{ 128 unsigned int n = num; 129 int i; 130 131 for (i = 0; i < 4 && (i == 0 || n > 0); i++) 132 { 133 int d = n % base; 134 n /= base; 135 setSegments(i, Digit[d]); 136 } 137 for (; leading && i < (sign ? 3 : 4); i++) 138 { 139 setDigit(i, 0); 140 } 141 if (sign) 142 { 143 setPattern(i++, MinusPattern); 144 } 145 for (; i < 4; i++) 146 { 147 setSegments(i, 0x00); 148 } 149} 150 151void Display4x7::setNumber(long number, bool leadingZeroes) 152{ 153 int n = number < 0 ? -number : number; 154 int i; 155 156 doNum(number < 0, n, 10, leadingZeroes); 157} 158 159void Display4x7::setNumber(unsigned int number, unsigned int base, bool leadingZeroes) 160{ 161 doNum(false, number, base, leadingZeroes); 162} 163 164void Display4x7::setPair(unsigned int x, unsigned int y, unsigned int base) 165{ 166 int xy[] = { 0,0,0,0 }; 167 168 xy[0] = y % base; 169 xy[1] = y / base; 170 xy[2] = x % base; 171 xy[3] = x / base; 172 173 setDigits(xy); 174} 175 176void Display4x7::setDigits(const int digits[]) 177{ 178 for (int d = 0; d < 4; d++) 179 { 180 setSegments(d, Digit[digits[d]]); 181 } 182} 183 184void Display4x7::setSegments(int digit, unsigned int segments) 185{ 186 unsigned int p = segments; 187 188 for (int s = 0; s < 7; s++) 189 { 190 _buf[digit][6 - s] = ((p & 0x0001) > 0); 191 p >>= 1; 192 } 193} 194 195void Display4x7::setPattern(int digit, const bool pattern[]) 196{ 197 for (int s = 0; s < 8; s++) 198 { 199 _buf[digit][s] = pattern[s]; 200 } 201} 202 203void Display4x7::setPattern(int digit, unsigned int pattern) 204{ 205 unsigned int p = pattern; 206 207 for (int s = 0; s < 8; s++) 208 { 209 _buf[digit][7 - s] = ((p & 0x0001) > 0); 210 p >>= 1; 211 } 212} 213 214void Display4x7::setPatterns(unsigned int pattern[]) 215{ 216 for (int d = 0; d < 4; d++) 217 { 218 setPattern(d, pattern[d]); 219 } 220} 221void Display4x7::setDot(int digit, bool on) 222{ 223 _buf[digit][7] = on; 224} 225 226void Display4x7::setBlink(int digit, unsigned int onTime, unsigned int offTime) 227{ 228 _blinkOn[digit] = onTime * 1000UL; // usec 229 _blinkOff[digit] = offTime * 1000UL; 230 if (onTime == 0UL || offTime == 0UL) 231 { 232 _blinkOn[digit] = 0UL; // Blinking off 233 } 234 _blinkTimer[digit] = 0; 235 _blinkState[digit] = true; 236} 237 238void Display4x7::setBlinkAll(unsigned int onTime, unsigned int offTime) 239{ 240 for (int digit = 0; digit < 4; digit++) 241 { 242 setBlink(digit, onTime, offTime); 243 } 244} 245 246void Display4x7::setup() 247{ 248 int i; 249 250 for (i = 0; i < 4; i++) 251 { 252 pinMode(_dgt[i], OUTPUT); 253 } 254 if (_shift == NULL) 255 { 256 for (i = 0; i < 8; i++) 257 { 258 pinMode(_seg[i], OUTPUT); 259 } 260 } 261 else 262 { 263 _shift->setup(); 264 _shift->reset(); 265 _shift->enableOutput(); 266 } 267 setBlinkAll(); 268 _currentDigit = 0; 269 _refresh = 0; 270} 271 272void Display4x7::update() 273{ 274 unsigned long time = micros(); 275 276 for (int d = 0; d < 4; d++) 277 { 278 if (_blinkOn[d] > 0) 279 { 280 if (time >= _blinkTimer[d]) 281 { 282 _blinkState[d] = !_blinkState[d]; 283 _blinkTimer[d] = time + (_blinkState[d] ? _blinkOn[d] : _blinkOff[d]); 284 } 285 } 286 } 287 288 if (time >= _refresh) 289 { 290 digitalWrite(_dgt[_currentDigit], _dgtOff); 291 _currentDigit++; 292 if (_currentDigit >= 4) 293 { 294 _currentDigit = 0; 295 } 296 for (int s = 0; s < 8; s++) 297 { 298 if (_shift == NULL) 299 { 300 digitalWrite(_seg[s], Display4x7::_buf[_currentDigit][s] ? _segOn : _segOff); 301 } 302 else 303 { 304 _shift->loadBit(Display4x7::_buf[_currentDigit][7 - s]); 305 } 306 } 307 if (_shift != NULL) 308 { 309 _shift->latch(); 310 } 311 digitalWrite(_dgt[_currentDigit], _blinkState[_currentDigit] ? _dgtOn : _dgtOff); 312 _refresh += _onTime; 313 } 314}
ShiftReg.zip
arduino
ShiftReg library as a zip file
1inary file (no preview
Display library
arduino
Library for controlling the 4-digit 7-segment LED display, used by the clock code
1inary file (no preview
library.properties
properties
Display4x7 library properties file. Save to your local Arduino/libraries/Display4x7 folder
1name=Display4x7 2version=1.0.0 3author=Qixaz 4maintainer=Qixaz (www.qixaz.com) 5sentence=4x7 segment display control 6paragraph=Library to send numbers and other patterns to a 4x7 segment display 7category=Communication 8url=http://www.qixaz.com 9architectures=* 10dot_a_linkage=true 11
keywords.txt
text
Display4x7 library keywords file. Save to your local Arduino/libraries/Display4x7 folder
1####################################### 2# Syntax Coloring Map For Display4x7 3####################################### 4 5####################################### 6# Class (KEYWORD1) 7####################################### 8 9Display4x7 KEYWORD1 Display4x7Library 10 11####################################### 12# Methods and Functions (KEYWORD2) 13####################################### 14 15# method names in Display4x7 16setDigit KEYWORD2 17setNumber KEYWORD2 18setPair KEYWORD2 19setDigits KEYWORD2 20setSegments KEYWORD2 21setPattern KEYWORD2 22setPatterns KEYWORD2 23setDot KEYWORD2 24setBlink KEYWORD2 25setBlinkAll KEYWORD2 26setup KEYWORD2 27update KEYWORD2 28 29####################################### 30# Constants (LITERAL1) 31####################################### 32 33DfltOnTime LITERAL1 34MinusPattern LITERAL1 35
Clock.ino
snippets
1/* 2 Digital alarm clock with stopwatch function 3*/ 4 5#include <Display4x7.h> // Display library is required 6 7/* 8 Define ports to control the 4x7 segment display 9*/ 10const int digit[] = {13, 12, 11, 10}; 11const int segment[] = {2, 3, 4, 5, 6, 7, 8, 9}; 12const int BuzzerPin = A4; 13const int ButtonPin = A5; 14 15/* 16 Other definitions 17*/ 18const unsigned int OnTime = 250; // When blinking, this is the time the display is on 19const unsigned int OffTime = 250; // When blinking, this is the time the display is off 20const int Step = 10; // Milliseconds resolution of the clock (1/100 sec) 21const unsigned int Refresh = 6500; // Display refresh rate in microseconds 22unsigned long MaxSec = 86400U; // Seconds in a day 23 24const unsigned int am_pattern = 0x02; // AM indicated by top left segment 25const unsigned int pm_pattern = 0x04; // PM indicated by lower left segment 26const unsigned int h_pattern = 0x2EU; // Smaal 'h' in clock mode setting 27const unsigned int r_pattern = 0x0AU; // Small 'r' in clock mode setting 28 29/* 30 Button settings 31 Using a 4 resistor ladder, 1 pin can read 3 buttons 32 Nominal values: 33 - button 1: 0V (read value: 0) 34 - button 2: 2.5V (read value: 512) 35 - button 3: 3.33V (read value: 682) 36 - No button: 3.75V (read value: 768) 37*/ 38unsigned long debounceTime = 500; // millisec before new button input is scanned 39const int Button1 = 256; // Threshold for button 1 40const int Button2 = 597; // Threshold for button 2 41const int Button3 = 725; // Threshold for button 3 42 43/* 44 The clock has different modes, switched by the "Mode" button. 45 Button actions depend on the clock's current mode 46*/ 47enum Mode { Clock, 48 ClockSet, ClockModeSet, 49 AlarmSet, 50 Stopwatch 51 }; 52 53/* 54 Action resulting from button presses during clock/alarm time set 55*/ 56enum SetAction { None, NextMode, Increment, Shift, Accept }; 57 58/* 59 The clock's operating modes 60*/ 61enum Mode mode = Clock; // Current clock mode 62bool Hr24 = true; // 24-hour mode, false for 12-hour 63bool Seconds = false; // Showing hours.minutes, true if showing minutes.seconds instead 64bool AlarmOn = false; // Alarm on 65unsigned AlarmFreq = 400; // Alarm sound frequency 66unsigned long SnoozeTime = 420UL; // Snooze time (7 minutes = 420 seconds) 67unsigned long MaxAlarmMs = 600000UL; // Max alarm time (10 minutes = 600000 millisecs) 68 69/* 70 Variables that hold the clock's actual state 71*/ 72Display4x7 d(digit, segment, Refresh);// The display 73unsigned long sc = 0; // The clock's value 74unsigned long alarm = 0; // The alarm time in seconds 75bool alarmSounding = false; // True if the buzzer is on 76unsigned long alarmAutoOff = 0; // Indicates when the alarm automatically switches off 77unsigned long snooze = 0; // Time to end snooze period 78unsigned long stopwatch = 0; // Stopwatch time 79bool stopwatchRunning = false; // Indicates that the stopwatch is running 80unsigned long laptime; // Lap time when using stopwatch 81bool showLapTime = false; // Show lap time 82unsigned long clockset = 0; // Used for setting the clock 83unsigned long alarmset = 0; // Used for setting the alarm 84bool setMin = false; // During time set: changing hours, true if changing minutes 85int hs = 0; // 1/100 seconds counter 86unsigned long count = 0; // Next 1/100 slice counter 87unsigned long debounce = 0; // Debounce button counter 88 89void setup() 90{ 91 pinMode(ButtonPin, INPUT); 92 pinMode(BuzzerPin, OUTPUT); 93 94 d.setup(); // Set-up display stuff 95 96 d.setDot(0, AlarmOn); 97} 98 99/* 100 Show the time in hours and minutes on the display, taking 12/24 101 hour mode into account 102*/ 103void showTime(unsigned int hours, unsigned int minutes, bool isAm) 104{ 105 int h = hours % (Hr24 ? 24 : 12); // Convert to 12 or 24 hours 106 107 h = (!Hr24 && h == 0 ? 12 : h); // 0 becomes 12 in 12-hr mode 108 109 d.setPair(h, minutes); // Display values 110 if (h < 10 || !Hr24) // Blank leading zero and set AM/PM 111 { 112 d.setSegments(3, // This concerns digit 3 (leftmost) 113 (h > 9 ? Display4x7::Digit[1] // 1 114 : 0x00) // else blank 115 | // combine with 116 (Hr24 ? 0x00 : (isAm ? am_pattern // AM 117 : 0x04))); // else PM 118 } 119} 120 121/* 122 Set time using buttons: 123 - Mode button (1): change mode, setting cancelled 124 - Set button (2): increment time by 1 minute or 1 hour 125 - Function button (3): accept input, set next 126 127 Blinking digits show hours/minutes change 128*/ 129enum SetAction setTime(bool& min, int button, unsigned long& set) 130{ 131 enum SetAction action = None; // Action taken based on button press 132 133 switch (button) 134 { 135 case 1: // Mode button 136 action = NextMode; 137 break; 138 case 2: // Set button 139 set += min ? 60UL : 3600UL; // Increment by 1 hour or 1 minute 140 if (set > MaxSec) 141 { 142 set -= MaxSec; // Roll-over to zero 143 } 144 action = Increment; 145 break; 146 case 3: // Function button 147 action = min ? Accept : Shift; // If changing hours, shift to minutes 148 min = !min; // Shift to minutes and adjust blinking digits 149 d.setBlink(0, min ? OnTime : 0, min ? OffTime : 0); 150 d.setBlink(1, min ? OnTime : 0, min ? OffTime : 0); 151 d.setBlink(2, !min ? OnTime : 0, min ? OffTime : 0); 152 d.setBlink(3, !min ? OnTime : 0, min ? OffTime : 0); 153 break; 154 } 155 showTime(set / 3600UL, (set / 60) % 60, set < MaxSec / 2); 156 return action; 157} 158 159/* 160 * Switch the alarm sound on and off 161 */ 162void switchAlarm(bool on, unsigned long currentMs) 163{ 164 alarmSounding = on; 165 if (on) 166 { 167 alarmAutoOff = currentMs + MaxAlarmMs; // Alarm stops automatically after predefined time 168 } 169 else 170 { 171 noTone(BuzzerPin); 172 } 173} 174 175void loop() 176{ 177 unsigned long tm = millis(); // Current time in milliseconds 178 int button = 0; // Button pressed 179 180 d.update(); // Display update in every loop 181 182 if (tm > debounce) // Prevent button read twice very fast 183 { 184 int buttonVal = analogRead(ButtonPin); 185 186 debounce = tm + 2UL; // Give the ADC time to settle 187 188 if (buttonVal < Button1) // Convert button voltage to button number 189 { 190 button = 1; 191 } 192 else if (buttonVal < Button2) 193 { 194 button = 2; 195 } 196 else if (buttonVal < Button3) 197 { 198 button = 3; 199 } 200 if (button > 0) 201 { 202 debounce = tm + debounceTime; // Stop reading buttons for some time 203 } 204 } 205 206 unsigned int mn = (sc / 60) % 60; // Calculate hours and minutes from time in seconds 207 unsigned int hr = (sc / 3600U) % (Hr24 ? 24 : 12); 208 bool am = sc < MaxSec / 2; // AM is first half of 24 hours 209 int hrsmode; // Used in setting 12/24 hours mode 210 unsigned int p[] = { 0, 0, 0, 0 }; // Used to display 12/24 hr 211 int dot; // Dot to show in stopwatch 212 bool dotOn; // Dot state (true is on, false is off) 213 unsigned long st; // Stopwatch time to display, adjusted to display size 214 215 hr = (!Hr24 && hr == 0 ? 12 : hr); // In 12 hour clock mode 0 is set to 12 216 217 if (tm > count) // The next 1/100 time slice is reached 218 { 219 hs++; // Next 1/100 second 220 if (stopwatchRunning) // Stopwatch is also increased by 1/100 second when running 221 { 222 stopwatch++; 223 } 224 count += Step; // Set the value for the next 1/100 second 225 if (hs == 100) // Next second reached 226 { 227 sc++; // Increment time with 1 second 228 if (sc >= MaxSec) 229 { 230 sc = 0; // Roll-over to zero at midnight 231 } 232 hs = 0; // Reset 1/100 second counter 233 234 if (AlarmOn && sc == snooze) // Alarm should sound now 235 { 236 switchAlarm(true, tm); // ... so switch it on 237 } 238 239 } 240 } 241 242 if (alarmSounding) // The buzzer is on, make it beep 243 { 244 if (hs == 0) 245 { 246 tone(BuzzerPin, AlarmFreq, 500); 247 } 248 if (tm > alarmAutoOff) // Auto off time reached? 249 { 250 switchAlarm(false, tm); // If yes, switch off the alarm 251 AlarmOn = false; 252 } 253 } 254 255 switch (mode) // Determine display based on clock's current mode 256 { 257 case Clock: // Regular clock mode 258 if (Seconds) 259 { 260 d.setPair(mn, sc % 60); // Show minutes/seconds 261 } 262 else 263 { 264 showTime(hr, mn, am); // Show hours/minutes 265 } 266 d.setDot(2, hs < 50); // Blink dot between hours and minutes, 1 time/second 267 268 switch (button) // Handle buttons in clock mode 269 { 270 case 1: 271 clockset = sc; // Clock set starts at current time 272 setMin = false; // Start setting the hours and make hours blink 273 d.setBlink(2, OnTime, OffTime); 274 d.setBlink(3, OnTime, OffTime); 275 d.setDot(0, false); // Alarm indicator is off when setting clock time 276 d.setDot(2, true); // Hour/minute separator is on 277 mode = ClockSet; // Next mode is clock set 278 break; 279 case 2: // Set button 280 if (alarmSounding) // If the alarm is on, 281 { 282 switchAlarm(false, tm); 283 snooze = sc + SnoozeTime; // New alarm time is SnoozeTime later 284 if (snooze > MaxSec) 285 { 286 snooze -= MaxSec; // Roll-over 287 } 288 } 289 else 290 { 291 Seconds = !Seconds; // Toggle between hours/minutes and minutes/seconds display 292 } 293 break; 294 case 3: // Function button 295 if (alarmSounding) // If the alarm is on, 296 { 297 switchAlarm(false, tm); // ... switch it off now 298 AlarmOn = false; 299 } 300 else 301 { 302 AlarmOn = !AlarmOn; // ... otherwise toggle alarm on/off 303 } 304 d.setDot(0, AlarmOn); // Update alarm indicator 305 break; 306 } 307 break; 308 case ClockSet: // Clock time set mode 309 switch (setTime(setMin, button, clockset)) // Handle time set 310 { 311 case NextMode: // Mode button pressed, ignore new time 312 setMin = false; // Adjust digit blinking to hours (for alarm set) 313 d.setBlink(2, OnTime, OffTime); 314 d.setBlink(3, OnTime, OffTime); 315 d.setDot(0, true); // Alarm indicator is on when setting alarm time 316 d.setDot(2, true); // Hour/minute separator is on 317 mode = AlarmSet; // Next mode is alarm set 318 break; 319 case Accept: // New time set 320 d.setBlinkAll(OnTime, OffTime); // Switch on blinking for clock mode set 321 sc = clockset; // Current time becomes the time set 322 mode = ClockModeSet; // Now move to 12/24-hour mode selction 323 break; 324 } 325 break; 326 case ClockModeSet: // Clock mode (12/24-hour) setting 327 hrsmode = (Hr24 ? 2 : 1); // Set-up pattern to display "12hr" or "24hr" 328 p[3] = (Display4x7::Digit[hrsmode] << 1); 329 p[2] = (Display4x7::Digit[2 * hrsmode] << 1); 330 p[1] = h_pattern; 331 p[0] = r_pattern; 332 333 d.setPatterns(p); // Display the current clock mode 334 switch (button) // Handle buttons for clock mode set 335 { 336 case 1: // Mode or function button do not change current setting 337 case 3: 338 setMin = false; // Reset time set to hours 339 d.setBlinkAll(); // Switch off all blinking 340 d.setDot(0, AlarmOn); // Update alarm indicator 341 mode = Clock; // Back to clock mode 342 break; 343 case 2: // The set button toggles the clock mode between 12 and 24 hours 344 Hr24 = !Hr24; 345 break; 346 } 347 break; 348 case AlarmSet: // Alarm time set mode 349 switch (setTime(setMin, button, alarmset)) // Handle time set 350 { 351 case NextMode: // Mode button pressed, ignore new alarm time 352 d.setBlinkAll(); // Blinking off 353 setMin = false; // Reset time set to hours 354 mode = Stopwatch; // Next mode is stopwatch 355 break; 356 case Accept: // New alarm time set 357 d.setBlinkAll(); // Blinking off 358 snooze = alarm = alarmset; // Set alarm and snooze times to new time 359 AlarmOn = true; // Alarm is switched on 360 d.setDot(0, AlarmOn); // Update alarm indicator 361 mode = Clock; // Back to clock mode 362 break; 363 } 364 break; 365 case Stopwatch: // Stopwatch mode 366 dot = 2; // Determine where to place decimal point, start with 1/100 seconds 367 st = (showLapTime ? laptime : stopwatch); 368 dotOn = stopwatchRunning ? (hs < 50) : true; // DP is only on in the first half second 369 if (st > 9999) // If stopwatch time goes beyond 9999/100 seconds... 370 { 371 dot = 1; // ... show only 1/10 of seconds 372 st /= 10UL; 373 } 374 if (st > 9999) // If stopwatch time goes beyond 9999/10 seconds... 375 { 376 dot = 0; // ... show seconds 377 st /= 10UL; 378 } 379 d.setNumber(st, false); // Show the stopwatch time 380 if (st < 10) // If still under 0.1 seconds... 381 { 382 d.setDigit(1, 0); // ... set digit after DP to 0 383 } 384 d.setDot(2, dotOn && dot == 2); // Show the decimal point at the right place 385 d.setDot(1, dotOn && dot == 1); 386 d.setDot(0, dotOn && dot == 0); 387 switch (button) 388 { 389 case 1: // Mode button pressed 390 d.setDot(1, false); // Update DP and alarm indicator for clock mode 391 d.setDot(0, AlarmOn); 392 mode = Clock; // Back to clock mode (stopwatch keeps running if on) 393 break; 394 case 2: // Set button pressed 395 stopwatchRunning = !stopwatchRunning; // Start/stop the stopwatch 396 break; 397 case 3: // Function button pressed 398 if (stopwatchRunning || showLapTime) 399 { 400 laptime = stopwatch; // When running or showing lap time, 401 showLapTime = !showLapTime; // ... toggle lap time/stopwatch time 402 } 403 else 404 { 405 stopwatch = laptime = 0; // When showing stopped time, reset stopwatch 406 } 407 break; 408 } 409 break; 410 } 411} 412
Display4x7.h
h
Display4x7 library header file. Save to your local Arduino/libraries/Display4x7/src folder
1#ifndef _display4x7_h_ 2#define _display4x7_h_ 3 4#include <Arduino.h> 5#include <ShiftReg.h> 6 7#define DfltOnTime 5500 8 9#define MinusPattern 0x02 10 11class Display4x7 12{ 13 public: 14 static const unsigned int Digit[]; 15 16 Display4x7(const int digitPorts[], const int segmentPorts[], int onTime = DfltOnTime, bool commonCathode = true); 17 Display4x7(const int digitPorts[], const ShiftReg& shift, int onTime = DfltOnTime, bool commonCathode = true); 18 19 void setDigit(int digit, unsigned int number); 20 void setNumber(long number, bool leadingZeroes); 21 void setNumber(unsigned int number, unsigned int base = 10, bool leadingZeroes = false); 22 void setPair(unsigned int x, unsigned int y, unsigned int base = 10); 23 void setDigits(const int digits[]); 24 25 void setSegments(int digit, unsigned int segments); 26 void setPattern(int digit, unsigned int pattern); 27 void setPatterns(unsigned int pattern[]); 28 void setPattern(int digit, const bool pattern[]); 29 void setDot(int digit, bool on); 30 31 void setBlink(int digit, unsigned int onTime = 0, unsigned int offTime = 0); 32 void setBlinkAll(unsigned int onTime = 0, unsigned int offTime = 0); 33 34 void setup(); 35 void update(); 36 37 protected: 38 void init(const int digitPorts[], int onTime, bool commonCathode); 39 void doNum(bool sign, unsigned int num, unsigned int base, bool leading); 40 41 int _currentDigit = 0; 42 unsigned long _refresh = 0UL; 43 44 int _onTime; 45 int _segOn; 46 int _segOff; 47 int _dgtOn; 48 int _dgtOff; 49 50 int _seg[8]; 51 int _dgt[4]; 52 static bool _buf[][8]; 53 unsigned long _blinkOn[4]; 54 unsigned long _blinkOff[4]; 55 bool _blinkState[4]; 56 unsigned long _blinkTimer[4]; 57 58 const ShiftReg* _shift = NULL; 59}; 60 61#endif 62
Downloadable files
Clock.fzz
Friting file including breadboard, schematic and code
Clock.fzz
Clock.fzz
Friting file including breadboard, schematic and code
Clock.fzz
Comments
Only logged in users can leave comments