This shows you the differences between two versions of the page.
pm:prj2023:tmiu:digitalclock [2023/05/27 21:29] sajjad.al [Hardware Design] |
pm:prj2023:tmiu:digitalclock [2023/05/30 16:58] (current) sajjad.al [Introduction] |
||
---|---|---|---|
Line 7: | Line 7: | ||
| | ||
- | • The goal and purpose of this project is to build and design a simple Digital Clock with Alarm and LED Matrix Display, to displays the current time on LED display and it also can be set to sound an Alarm on a specific time. The clock uses an LED matrix to display the time, and a buzzer to sound the alarm. | + | • The goal and purpose of this project is to build and design a simple Digital Clock with Alarm and LED Matrix Display, to displays the current time and date on LED display and it also can be set to sound an Alarm on a specific time. The clock uses an LED matrix to display the time, and a buzzer to sound the alarm. |
- | • The idea of this project comes from an actual Digital clock but I added the Alarm function. | ||
Line 22: | Line 22: | ||
- | {{:pm:prj2023:tmiu:pic.jpg?200|}}===== Hardware Design ===== | + | |
+ | |||
+ | {{:pm:prj2023:tmiu:1.jpg?200|}}===== Hardware Design ===== | ||
Line 28: | Line 30: | ||
The following components are required for this project: | The following components are required for this project: | ||
- | • RTC module with I2C interface | + | • Tiny RTC module with I2C interface |
• LED matrix (8x8 or higher) | • LED matrix (8x8 or higher) | ||
- | • Push buttons for setting the timer | + | • 3 Push buttons |
• Buzzer for alarm sound | • Buzzer for alarm sound | ||
Line 39: | Line 41: | ||
• Breadboard | • Breadboard | ||
+ | |||
+ | * 3 Resistors | ||
• Wires | • Wires | ||
- | https://ocw.cs.pub.ro/courses/_media/pm/prj2023/tmiu/pic.jpg?w=90&h=120&t=1685211678&tok=02fe06 | + | |
Line 53: | Line 57: | ||
The following software requirements are necessary for this project: | The following software requirements are necessary for this project: | ||
- | • RTC library (e.g., DS1307) | + | • Libraries ( MD_Parola.h, RTClib.h, toneAC.h ) |
- | • GPIO library for controlling LED matrix | ||
- | • Timer function to update the time and trigger the alarm | ||
- | • Button input and buzzer output code | ||
- | + | #include <MD_Parola.h> | |
+ | |||
+ | |||
+ | #include "RTClib.h" | ||
+ | |||
+ | |||
+ | #include <toneAC.h> | ||
+ | |||
+ | |||
+ | |||
+ | RTC_DS1307 RTC; | ||
+ | |||
+ | DateTime now; | ||
+ | |||
+ | #define HARDWARE_TYPE MD_MAX72XX::FC16_HW | ||
+ | |||
+ | #define MAX_DEVICES 4 | ||
+ | |||
+ | #define CLK_PIN 13 | ||
+ | |||
+ | #define DATA_PIN 11 | ||
+ | |||
+ | #define CS_PIN 10 | ||
+ | |||
+ | int i = 9; | ||
+ | |||
+ | int Animation; | ||
+ | |||
+ | String RandAn; | ||
+ | |||
+ | MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); | ||
+ | |||
+ | // Brightness variables | ||
+ | |||
+ | int brightness = 5; // Initial brightness level | ||
+ | |||
+ | const int brightnessStep = 1; // Step to increase/decrease brightness | ||
+ | |||
+ | const int brightnessMin = 0; // Minimum brightness level | ||
+ | |||
+ | const int brightnessMax = 15; // Maximum brightness level | ||
+ | |||
+ | // Button pin numbers | ||
+ | |||
+ | const int brightnessUpPin = 2; | ||
+ | |||
+ | const int brightnessDownPin = 3; | ||
+ | |||
+ | const int alarmButtonPin = 4; // Alarm button pin | ||
+ | |||
+ | const int alarmBuzzerPin = 9; // Alarm buzzer pin | ||
+ | |||
+ | bool isAlarmEnabled = false; | ||
+ | |||
+ | bool isAlarmOn = false; | ||
+ | |||
+ | char daysOfTheWeek[7][12] = {"sun", "mon", "tues", "wedn", "thur", "fri", "sat"}; | ||
+ | |||
+ | char monthOfTheYear[12][12] = {"Jan", "Feb", "Mar", "April", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}; | ||
+ | |||
+ | struct sCatalog | ||
+ | |||
+ | { | ||
+ | |||
+ | textEffect_t effect; | ||
+ | |||
+ | const char * psz; | ||
+ | |||
+ | uint16_t speed; | ||
+ | |||
+ | uint16_t pause; | ||
+ | }; | ||
+ | |||
+ | |||
+ | sCatalog catalog[] = | ||
+ | |||
+ | { | ||
+ | { PA_PRINT,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_UP,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_DOWN,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_LEFT,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_RIGHT,"",80,3000 }, | ||
+ | |||
+ | { PA_SPRITE,"",80,3000 }, | ||
+ | |||
+ | { PA_SLICE,"",15,3000 }, | ||
+ | |||
+ | { PA_MESH,"",150,3000 }, | ||
+ | |||
+ | { PA_FADE,"",250,3000 }, | ||
+ | |||
+ | { PA_DISSOLVE,"",500,3000 }, | ||
+ | |||
+ | { PA_BLINDS,"",120,3000 }, | ||
+ | |||
+ | { PA_RANDOM,"",50,3000 }, | ||
+ | |||
+ | { PA_WIPE,"",80,3000 }, | ||
+ | |||
+ | { PA_WIPE_CURSOR,"",80,3000 }, | ||
+ | |||
+ | { PA_SCAN_HORIZ,"",80,3000 }, | ||
+ | |||
+ | { PA_SCAN_HORIZX,"",80,3000 }, | ||
+ | |||
+ | { PA_SCAN_VERT,"",80,3000 }, | ||
+ | |||
+ | { PA_SCAN_VERTX,"",80,3000 }, | ||
+ | |||
+ | { PA_OPENING,"",80,3000 }, | ||
+ | |||
+ | { PA_OPENING_CURSOR,"",80,3000 }, | ||
+ | |||
+ | { PA_CLOSING,"",80,3000 }, | ||
+ | |||
+ | { PA_CLOSING_CURSOR,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_UP_LEFT,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_UP_RIGHT,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_DOWN_LEFT,"",80,3000 }, | ||
+ | |||
+ | { PA_SCROLL_DOWN_RIGHT,"",80,3000 }, | ||
+ | |||
+ | { PA_GROW_UP,"",80,3000 }, | ||
+ | |||
+ | { PA_GROW_DOWN,"",80,3000 }, | ||
+ | |||
+ | }; | ||
+ | |||
+ | |||
+ | // Sprite Definitions | ||
+ | const uint8_t F_PMAN1 = 6; | ||
+ | const uint8_t W_PMAN1 = 8; | ||
+ | static const uint8_t PROGMEM pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation | ||
+ | { | ||
+ | 0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, | ||
+ | 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, | ||
+ | 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, | ||
+ | 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, | ||
+ | 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, | ||
+ | 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, | ||
+ | }; | ||
+ | |||
+ | const uint8_t F_PMAN2 = 6; | ||
+ | const uint8_t W_PMAN2 = 18; | ||
+ | static const uint8_t PROGMEM pacman2[F_PMAN2 * W_PMAN2] = // ghost pursued by a pacman | ||
+ | { | ||
+ | 0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, | ||
+ | 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, | ||
+ | 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe, | ||
+ | 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, | ||
+ | 0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, | ||
+ | 0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe, | ||
+ | }; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Serial.begin(9600); | ||
+ | P.begin(); | ||
+ | P.setInvert(false); | ||
+ | P.setIntensity(0); | ||
+ | Wire.begin(); | ||
+ | RTC.begin(); | ||
+ | |||
+ | //if (! RTC.isrunning()) | ||
+ | //{ | ||
+ | //Serial.println("RTC is NOT running!"); | ||
+ | RTC.adjust(DateTime(2023, 5, 30, 15, 15, 0)); | ||
+ | //} | ||
+ | #if ENA_SPRITE | ||
+ | P.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2); | ||
+ | #endif | ||
+ | P.displayText("Digital clock ARDUINO - BY- ALNASER SAJJAD" , PA_CENTER, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT); | ||
+ | while (!P.displayAnimate()); | ||
+ | |||
+ | pinMode(brightnessUpPin, INPUT_PULLUP); | ||
+ | pinMode(brightnessDownPin, INPUT_PULLUP); | ||
+ | pinMode(alarmButtonPin, INPUT_PULLUP); | ||
+ | pinMode(alarmBuzzerPin, OUTPUT); | ||
+ | } | ||
+ | |||
+ | const char *ZiuaCurenta = " "; | ||
+ | |||
+ | String Hour; | ||
+ | String TIMP=" "; | ||
+ | String ORA=" "; | ||
+ | String MINUT=" "; | ||
+ | String SECUNDA=" "; | ||
+ | String DATA=""; | ||
+ | |||
+ | String Day; | ||
+ | String Month; | ||
+ | String Year; | ||
+ | String HumSTR; | ||
+ | String CelSTR; | ||
+ | String FarSTR; | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | |||
+ | String DayOfWeek = daysOfTheWeek[now.dayOfTheWeek()]; | ||
+ | String MonthOfYear = monthOfTheYear[now.month() - 1]; | ||
+ | const char *DayOfWeekC = DayOfWeek.c_str(); | ||
+ | const char *MonthOfYearC = MonthOfYear.c_str(); | ||
+ | |||
+ | ORA = (now.hour()); | ||
+ | if (ORA.length() < 2) | ||
+ | { | ||
+ | ORA = "0"+ ORA; | ||
+ | } | ||
+ | |||
+ | MINUT = (now.minute()); | ||
+ | if (MINUT.length() < 2) | ||
+ | { | ||
+ | MINUT = "0"+ MINUT; | ||
+ | } | ||
+ | |||
+ | TIMP = ORA + ":" + MINUT; | ||
+ | |||
+ | const char *Timp = TIMP.c_str(); | ||
+ | |||
+ | Day = now.day(); | ||
+ | Month = now.month(); | ||
+ | Year = now.year(); | ||
+ | |||
+ | const char *Ziua = Day.c_str(); | ||
+ | const char *Luna = Month.c_str(); | ||
+ | const char *Anul = Year.c_str(); | ||
+ | |||
+ | String Date = Day + "/" + Month + "/" + Year; | ||
+ | const char *Data = Date.c_str(); | ||
+ | |||
+ | |||
+ | if (i == 1) | ||
+ | { | ||
+ | Animation = random(1, 29); | ||
+ | P.displayText(DayOfWeekC, PA_CENTER, catalog[Animation].speed, catalog[Animation].pause, catalog[Animation].effect, catalog[Animation].effect); | ||
+ | while (!P.displayAnimate()); | ||
+ | } | ||
+ | if (i == 2) | ||
+ | { | ||
+ | Animation = random(1, 29); | ||
+ | P.displayText(Ziua, PA_CENTER, catalog[Animation].speed, catalog[Animation].pause, catalog[Animation].effect, catalog[Animation].effect); | ||
+ | while (!P.displayAnimate()); | ||
+ | } | ||
+ | if (i == 3) | ||
+ | { | ||
+ | Animation = random(1, 29); | ||
+ | P.displayText(MonthOfYearC, PA_CENTER, catalog[Animation].speed, catalog[Animation].pause, catalog[Animation].effect, catalog[Animation].effect); | ||
+ | while (!P.displayAnimate()); | ||
+ | } | ||
+ | if (i == 4) | ||
+ | { | ||
+ | Animation = random(1, 29); | ||
+ | P.displayText(Anul, PA_CENTER, catalog[Animation].speed, catalog[Animation].pause, catalog[Animation].effect, catalog[Animation].effect); | ||
+ | while (!P.displayAnimate()); | ||
+ | } | ||
+ | |||
+ | if (i == 5) | ||
+ | { | ||
+ | Animation = random(1, 29); | ||
+ | P.displayText(Timp, PA_CENTER, catalog[Animation].speed, catalog[Animation].pause, catalog[Animation].effect, catalog[Animation].effect); | ||
+ | while (!P.displayAnimate()); | ||
+ | } | ||
+ | |||
+ | //Serial.println(Animation); | ||
+ | i= i+1; | ||
+ | if (i > 5) | ||
+ | { | ||
+ | i=1; | ||
+ | }; | ||
+ | |||
+ | // Button handling | ||
+ | if (digitalRead(brightnessUpPin) == LOW) { | ||
+ | increaseBrightness(); | ||
+ | delay(200); // Add a small delay to avoid button bouncing | ||
+ | } | ||
+ | |||
+ | if (digitalRead(brightnessDownPin) == LOW) { | ||
+ | decreaseBrightness(); | ||
+ | delay(200); // Add a small delay to avoid button bouncing | ||
+ | } | ||
+ | if (digitalRead(alarmButtonPin) == LOW) { | ||
+ | delay(200); // Add a small delay to avoid button bouncing | ||
+ | } | ||
+ | // Check for alarm condition | ||
+ | if (isAlarmEnabled && isAlarmTime()) { | ||
+ | activateAlarm(); | ||
+ | } | ||
+ | } | ||
+ | void increaseBrightness() { | ||
+ | brightness += brightnessStep; | ||
+ | if (brightness > brightnessMax) { | ||
+ | brightness = brightnessMax; | ||
+ | } | ||
+ | P.setIntensity(brightness); | ||
+ | } | ||
+ | |||
+ | void decreaseBrightness() { | ||
+ | brightness -= brightnessStep; | ||
+ | if (brightness < brightnessMin) { | ||
+ | brightness = brightnessMin; | ||
+ | } | ||
+ | P.setIntensity(brightness); | ||
+ | } | ||
+ | |||
+ | bool isAlarmTime() { | ||
+ | // Get the current time | ||
+ | now = RTC.now(); | ||
+ | |||
+ | // Define the alarm time (hours and minutes) | ||
+ | int alarmHour = 8; | ||
+ | int alarmMinute = 30; | ||
+ | |||
+ | // Compare the current time with the alarm time | ||
+ | if (now.hour() == alarmHour && now.minute() == alarmMinute) { | ||
+ | return true; // It's alarm time | ||
+ | } else { | ||
+ | return false; // It's not alarm time | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void activateAlarm() { | ||
+ | digitalWrite(alarmBuzzerPin, HIGH); // Turn on the buzzer | ||
+ | delay(1000); // Adjust the delay as needed | ||
+ | digitalWrite(alarmBuzzerPin, LOW); // Turn off the buzzer | ||
+ | } | ||
+ | |||
+ | // Function to deactivate the alarm | ||
+ | void deactivateAlarm() { | ||
+ | digitalWrite(alarmBuzzerPin, LOW); // Turn off the buzzer | ||
+ | } | ||
===== Results Obtained ===== | ===== Results Obtained ===== | ||
+ | After i built the Hardware components and wrote the Software (CODE): | ||
- | | + | * The digital clock should display the current time in hours and minutes using the LED matrix. |
- | What were the results obtained after the realization of your project. | + | |
+ | * The clock should retrieve the time from the Tiny RTC module using the I2C interface. | ||
+ | |||
+ | * The clock should display the current day of the week, date, month, and year on the LED matrix. | ||
+ | |||
+ | * The clock should support different text effects and animations for displaying the time and date. | ||
+ | |||
+ | * The clock should have three push buttons for controlling the brightness of the LED matrix and activating/deactivating the alarm. | ||
+ | |||
+ | * The clock should activate an alarm sound using the buzzer at a predefined alarm time (8:30 AM). | ||
Line 73: | Line 423: | ||
===== Conclusions ===== | ===== Conclusions ===== | ||
+ | |||
+ | the project demonstrates the ability to create a digital clock using an Arduino Uno, LED matrix, Tiny RTC module, push buttons, and a buzzer. The project combines both hardware and software components to deliver a functional and interactive digital clock. | ||
===== Download ===== | ===== Download ===== | ||
Line 94: | Line 446: | ||
- | + | **Software Resources** | |
- | List of documents, datasheets, Internet resources used, possibly grouped by **Software Resources** and **Hardware Resources**. | + | |
+ | https://mytectutor.com/ds1307-real-time-clock-with-arduino-including-digital-clock-using-max7219-led-matrix/ | ||
+ | |||
+ | |||
+ | https://pastebin.com/EkX8aJvc | ||
+ | |||
+ | |||
+ | https://lastminuteengineers.com/ds1307-rtc-arduino-tutorial/ | ||