Final version, with changing analogue clock colours, Friday 11:20am

Dependencies:   MMA8451Q SPI_TFT_ILI9341 TFT_fonts mbed

Smart clock by Duncan and Kieran

Photo

http://www.imgur.com/SiyOshx.jpg

Equipment

  • PCB: FRDM-KL25Z
  • TFT Color Display: MI0283QT-9A
  • Buzzer
  • 3 x buttons
  • 3 x 2kΩ resistors and 1 x 100Ω resistor
  • Stripboard
  • Wires (stranded is preferable due to their flexibility)
  • USB to Mini-USB cable, and computer

Setup

PCB to TFT (Output)

FRDM-KL25ZMI0283QT-9A
P3V33.3V, IM1, IM2, IM3
GNDRD, IM0, LEDK
PTD5CS
PTD1RS
PTD0RST
PTD2SDI
PTD3SDO
PTA13WR
P5V_USB through 100Ω resistor (approx. 20mA)LEDA

The buzzer should be connected between PTA12 and ground.

Note: The resistance between P5V_USB and LEDA can be reduced to increase the brightness of the screen. However, resistors lower than 30Ω have not been tested, and may result in the current causing damage to the PCB.

PCB to Buttons (Inputs)

FRDM-KL25ZInput
PTA5Minute button
PTC8Hour button
PTC9Time change button - toggles between changing the alarm time and the clock time

Each button should be connected in series with a 2kΩ resistor between 3.3V and 0V, so that pressing the button switches between these two voltages.

Features

  • A digital clock, displayed in 24-hour format
  • An analogue clock, displaying the time in standard 12-hour format
  • Alarm can be changed using the minute and hour buttons
  • Time can be changed by holding the third button
  • Alarm will sound for one minute at the displayed time
  • Putting the alarm on its side will snooze the alarm if the alarm is going off (or just disable it if the alarm is not sounding)
Committer:
scat6490
Date:
Fri May 26 10:20:25 2017 +0000
Revision:
9:d34cdff0205c
Parent:
8:6bd70a8697f4
Final version, with changing analogue clock colours, Friday 11:20am

Who changed what in which revision?

UserRevisionLine numberNew contents of line
scat6490 6:d80627e78bfd 1 #include "stdio.h" // Import libraries to use
scat6490 0:4fd6c8718206 2 #include "mbed.h"
scat6490 0:4fd6c8718206 3 #include "SPI_TFT_ILI9341.h"
scat6490 0:4fd6c8718206 4 #include "string"
scat6490 0:4fd6c8718206 5 #include "Arial12x12.h"
scat6490 0:4fd6c8718206 6 #include "Arial24x23.h"
scat6490 0:4fd6c8718206 7 #include "Arial28x28.h"
scat6490 0:4fd6c8718206 8 #include "font_big.h"
scat6490 7:007d23438920 9 #include "MMA8451Q.h"
scat6490 7:007d23438920 10
scat6490 7:007d23438920 11 #define MMA8451_I2C_ADDRESS (0x1d<<1)
scat6490 0:4fd6c8718206 12
scat6490 6:d80627e78bfd 13 Ticker timer; // Set up a timer
scat6490 6:d80627e78bfd 14 DigitalOut buzzer(PTE30); // Set up inputs and outputs
scat6490 6:d80627e78bfd 15 DigitalIn input1(PTA5); // Input for the minute button
scat6490 5:f5fa116b57a1 16 DigitalIn input60(PTC8); // Input for the hour button
scat6490 5:f5fa116b57a1 17 DigitalIn input_time_change(PTC9); // Input for the button which switches from changing the alarm and changing the time
scat6490 5:f5fa116b57a1 18 Serial pc(USBTX,USBRX); // Connection to the desktop, currently only used for debugging
scat6490 0:4fd6c8718206 19 SPI_TFT_ILI9341 TFT(PTD2, PTD3, PTD1, PTD5, PTD0, PTA13,"TFT"); // mosi, miso, sclk, cs, reset, dc for frdmkl25z
scat6490 0:4fd6c8718206 20
scat6490 5:f5fa116b57a1 21 int clock_minutes, clock_hours, clock_seconds = 0; // Initialise clock at 00:00.00
scat6490 6:d80627e78bfd 22 int alarm_hours = 7; // Initialise alarm hours as 07
scat6490 6:d80627e78bfd 23 int alarm_minutes = 0; // Initialise alarm minutes as 00 so alarm is 07:00
scat6490 9:d34cdff0205c 24 int previous_state, enable; // Initialise the previous state and enable variables to detect changing rotation
scat6490 1:a33f6ca5a5b3 25
scat6490 5:f5fa116b57a1 26 void timeup(){ // Function to increment the clock every second
scat6490 5:f5fa116b57a1 27 clock_seconds++; // Increment the time
scat6490 5:f5fa116b57a1 28 clock_seconds %= 60; // Reset seconds to 0 if it gets to 60
scat6490 4:2013f3158cc6 29
scat6490 4:2013f3158cc6 30 if (clock_seconds==0)
scat6490 4:2013f3158cc6 31 {
scat6490 5:f5fa116b57a1 32 clock_minutes++; // Add a minute if the seconds got reset
scat6490 5:f5fa116b57a1 33 clock_minutes %= 60; // Reset the minutes to 0 if it gets to 60
scat6490 4:2013f3158cc6 34 }
scat6490 4:2013f3158cc6 35 if (clock_minutes==0 && clock_seconds==0)
scat6490 4:2013f3158cc6 36 {
scat6490 5:f5fa116b57a1 37 clock_hours++; // Add an hour if the minutes got reset
scat6490 6:d80627e78bfd 38 clock_hours %= 24; // Reset the hour to 0 if it gets to 24`
scat6490 4:2013f3158cc6 39 }
scat6490 4:2013f3158cc6 40 }
scat6490 4:2013f3158cc6 41
scat6490 4:2013f3158cc6 42 void drawclock() // Draws an analogue clock using the clock_minutes and clock_hours variables
scat6490 4:2013f3158cc6 43 {
scat6490 5:f5fa116b57a1 44 int hourX, hourY, minuteX, minuteY, secondX, secondY; // Initialise variables to be used
scat6490 5:f5fa116b57a1 45 int circleX = 250; // Circle centre X
scat6490 4:2013f3158cc6 46 int circleY = 200; // Circle centre Y
scat6490 4:2013f3158cc6 47 int circleRadius = 30; // Circle radius
scat6490 4:2013f3158cc6 48
scat6490 4:2013f3158cc6 49 double factorH = (2 * 3.141) / 12; // Convert hour to radians
scat6490 4:2013f3158cc6 50 double factorM = (2 * 3.141) / 60; // Convert minute to radians
scat6490 5:f5fa116b57a1 51 double factorS = (2 * 3.141) / 60; // Convert second to radians
scat6490 4:2013f3158cc6 52
scat6490 5:f5fa116b57a1 53 hourX = floor(0.6 * circleRadius * sin((double) (clock_hours * factorH))); // Calculate difference in X values of the two ends of the hour hand.
scat6490 5:f5fa116b57a1 54 hourY = floor(0.6 * circleRadius * cos((double) (clock_hours * factorH))); // Same for Y of hour hand. The 0.9 means the hands are smaller than the circle
scat6490 5:f5fa116b57a1 55 minuteX = floor(0.95 * circleRadius * sin((double) (clock_minutes * factorM))); // Same for X of minute hand
scat6490 5:f5fa116b57a1 56 minuteY = floor(0.95 * circleRadius * cos((double) (clock_minutes * factorM))); // Same for Y of minute hand
scat6490 5:f5fa116b57a1 57 secondX = floor(0.85 * circleRadius * sin((double) (clock_seconds * factorS))); // Same for X of second hand
scat6490 5:f5fa116b57a1 58 secondY = floor(0.85 * circleRadius * cos((double) (clock_seconds * factorS))); // Same for Y of second hand
scat6490 4:2013f3158cc6 59
scat6490 9:d34cdff0205c 60 if (enable) // Checks if the alarm is enabled
scat6490 5:f5fa116b57a1 61 {
scat6490 9:d34cdff0205c 62 TFT.fillcircle(circleX, circleY, circleRadius, Green); // Draws a green circle
scat6490 9:d34cdff0205c 63 TFT.circle(circleX, circleY, circleRadius, Black); // Draws a white circle around the red circle
scat6490 9:d34cdff0205c 64 TFT.line(circleX, circleY, circleX + hourX, circleY - hourY, Black); // Draws the hour hand
scat6490 9:d34cdff0205c 65 TFT.line(circleX, circleY, circleX + minuteX, circleY - minuteY, Black); // Draws the minute hand
scat6490 9:d34cdff0205c 66 TFT.line(circleX, circleY, circleX + secondX, circleY - secondY, White); // Draws the second hand
scat6490 9:d34cdff0205c 67
scat6490 9:d34cdff0205c 68 for (int i = 0; i < 12; i++)
scat6490 9:d34cdff0205c 69 {
scat6490 9:d34cdff0205c 70 int timeX = floor(circleRadius * sin((double) (i * factorH))); // Calculate the X for the hour indicators around the edge
scat6490 9:d34cdff0205c 71 int timeY = floor(circleRadius * cos((double) (i * factorH))); // Same for Y of the hour indicators
scat6490 5:f5fa116b57a1 72
scat6490 9:d34cdff0205c 73 TFT.line(circleX + 0.8 * timeX, circleY - 0.8 * timeY, circleX + timeX, circleY - timeY, Black); // Draws the hour indicators
scat6490 9:d34cdff0205c 74 }
scat6490 9:d34cdff0205c 75 } else
scat6490 9:d34cdff0205c 76 {
scat6490 9:d34cdff0205c 77 TFT.fillcircle(circleX, circleY, circleRadius, Red); // Draws a red circle
scat6490 9:d34cdff0205c 78 TFT.circle(circleX, circleY, circleRadius, White); // Draws a white circle around the red circle
scat6490 9:d34cdff0205c 79 TFT.line(circleX, circleY, circleX + hourX, circleY - hourY, White); // Draws the hour hand
scat6490 9:d34cdff0205c 80 TFT.line(circleX, circleY, circleX + minuteX, circleY - minuteY, White); // Draws the minute hand
scat6490 9:d34cdff0205c 81 TFT.line(circleX, circleY, circleX + secondX, circleY - secondY, Black); // Draws the second hand
scat6490 9:d34cdff0205c 82
scat6490 9:d34cdff0205c 83 for (int i = 0; i < 12; i++)
scat6490 9:d34cdff0205c 84 {
scat6490 9:d34cdff0205c 85 int timeX = floor(circleRadius * sin((double) (i * factorH))); // Calculate the X for the hour indicators around the edge
scat6490 9:d34cdff0205c 86 int timeY = floor(circleRadius * cos((double) (i * factorH))); // Same for Y of the hour indicators
scat6490 9:d34cdff0205c 87
scat6490 9:d34cdff0205c 88 TFT.line(circleX + 0.8 * timeX, circleY - 0.8 * timeY, circleX + timeX, circleY - timeY, White); // Draws the hour indicators
scat6490 9:d34cdff0205c 89 }
scat6490 5:f5fa116b57a1 90 }
scat6490 1:a33f6ca5a5b3 91 }
scat6490 1:a33f6ca5a5b3 92
scat6490 0:4fd6c8718206 93 int main()
scat6490 0:4fd6c8718206 94 {
scat6490 7:007d23438920 95 MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); // Set up the accelerometer connection
scat6490 7:007d23438920 96 wait(0.5); // Just wait for set up
scat6490 7:007d23438920 97 previous_state = acc.getAccX() >= 0.5; // Initialise the previous state variable
scat6490 3:6a328c7e9b1c 98
scat6490 6:d80627e78bfd 99 TFT.set_orientation(3); // Make the display horizontal
scat6490 5:f5fa116b57a1 100 TFT.background(Black); // Set background to black
scat6490 5:f5fa116b57a1 101 TFT.foreground(White); // Set text to white
scat6490 5:f5fa116b57a1 102 TFT.cls(); // Clear screen
scat6490 0:4fd6c8718206 103
scat6490 5:f5fa116b57a1 104 TFT.set_font((unsigned char*) Arial12x12); // Set the font to Arial 12x12
scat6490 5:f5fa116b57a1 105 TFT.fillrect(0, 0, 320, 32, Red); // Draw a red rectangle at the top
scat6490 5:f5fa116b57a1 106 TFT.locate(10, 10); // Move the text location
scat6490 5:f5fa116b57a1 107 TFT.printf("Clock by Duncan and Kieran"); // Write some text in the box at the top
scat6490 0:4fd6c8718206 108
scat6490 5:f5fa116b57a1 109 TFT.background(Black); // Set background to black
scat6490 5:f5fa116b57a1 110 TFT.set_font((unsigned char*) Arial28x28); // Set the font to Arial 28x28
scat6490 8:6bd70a8697f4 111 TFT.locate(30, 70); // Move the text location
scat6490 8:6bd70a8697f4 112 TFT.printf("Time:"); // Display some text
scat6490 0:4fd6c8718206 113
scat6490 5:f5fa116b57a1 114 timer.attach(&timeup, 1); // Set up the timer so it increments every second
scat6490 1:a33f6ca5a5b3 115
scat6490 3:6a328c7e9b1c 116 while(1) {
scat6490 6:d80627e78bfd 117 if (!input_time_change) // Check if the toggle switch is pressed to change which time the other buttons adjust (pressed changes the time, unpressed changes the alarm)
scat6490 3:6a328c7e9b1c 118 {
scat6490 5:f5fa116b57a1 119 switch(input1){ // Check if the minute button is pressed
scat6490 3:6a328c7e9b1c 120 case 1:
scat6490 5:f5fa116b57a1 121 clock_minutes++; // Increment the time minutes
scat6490 5:f5fa116b57a1 122 clock_minutes %= 60; // Set the minutes back to 0 if it's 60
scat6490 5:f5fa116b57a1 123 wait(0.2); // Wait so the time doesn't increase too fast
scat6490 5:f5fa116b57a1 124 break;
scat6490 3:6a328c7e9b1c 125 case 0:
scat6490 5:f5fa116b57a1 126 break;
scat6490 3:6a328c7e9b1c 127 }
scat6490 5:f5fa116b57a1 128 switch(input60){ // Check if the hour button is pressed
scat6490 3:6a328c7e9b1c 129 case 1:
scat6490 5:f5fa116b57a1 130 clock_hours++; // Increment the time hours
scat6490 5:f5fa116b57a1 131 clock_hours %= 24; // Set the hours back to 0 if it's 24
scat6490 5:f5fa116b57a1 132 wait(0.2); // Wait so the time doesn't increase too fast
scat6490 3:6a328c7e9b1c 133 break;
scat6490 3:6a328c7e9b1c 134 case 0:
scat6490 3:6a328c7e9b1c 135 break;
scat6490 3:6a328c7e9b1c 136 }
scat6490 3:6a328c7e9b1c 137 } else
scat6490 3:6a328c7e9b1c 138 {
scat6490 5:f5fa116b57a1 139 switch(input1){ // Check if the minute button is pressed
scat6490 3:6a328c7e9b1c 140 case 1:
scat6490 5:f5fa116b57a1 141 alarm_minutes++; // Increment the alarm minutes
scat6490 5:f5fa116b57a1 142 alarm_minutes %= 60; // Set the minutes back to 0 if it's 60
scat6490 5:f5fa116b57a1 143 wait(0.2); // Wait so the alarm time doesn't increase too fast
scat6490 3:6a328c7e9b1c 144 break;
scat6490 3:6a328c7e9b1c 145 case 0:
scat6490 3:6a328c7e9b1c 146 break;
scat6490 3:6a328c7e9b1c 147 }
scat6490 5:f5fa116b57a1 148 switch(input60){ // Check if the hour button is pressed
scat6490 3:6a328c7e9b1c 149 case 1:
scat6490 5:f5fa116b57a1 150 alarm_hours++; // Increment the alarm hours
scat6490 5:f5fa116b57a1 151 alarm_hours %= 24; // Set the hours back to 0 if it's 24
scat6490 5:f5fa116b57a1 152 wait(0.2); // Wait so the alarm time doesn't increase too fast
scat6490 3:6a328c7e9b1c 153 break;
scat6490 3:6a328c7e9b1c 154 case 0:
scat6490 3:6a328c7e9b1c 155 break;
scat6490 3:6a328c7e9b1c 156 }
scat6490 1:a33f6ca5a5b3 157 }
scat6490 7:007d23438920 158
scat6490 7:007d23438920 159 float x = acc.getAccX(); // Check the x-orientation
scat6490 9:d34cdff0205c 160 enable = 1; // Initialise the enable variable
scat6490 7:007d23438920 161
scat6490 7:007d23438920 162 if (x < 0.5){ // Check if the clock is tilted
scat6490 7:007d23438920 163 enable = 0; // Disable the alarm
scat6490 7:007d23438920 164 }
scat6490 7:007d23438920 165 if (enable != previous_state && !enable && clock_hours == alarm_hours && clock_minutes == alarm_minutes) // If the clock is tilted while the alarm is going off
scat6490 7:007d23438920 166 {
scat6490 7:007d23438920 167 alarm_minutes += 5; // Add 5 minutes (snooze)
scat6490 7:007d23438920 168 }
scat6490 8:6bd70a8697f4 169 if (clock_hours == alarm_hours && clock_minutes == alarm_minutes && enable) // Check if the time is equal to the alarm time, and the seconds is even
scat6490 2:21c4f254786f 170 {
scat6490 5:f5fa116b57a1 171 buzzer = 1; // Buzz
scat6490 8:6bd70a8697f4 172 wait(0.2); // Wait
scat6490 8:6bd70a8697f4 173 buzzer = 0; // Don't buzz
scat6490 8:6bd70a8697f4 174 wait(0.2); // Wait
scat6490 2:21c4f254786f 175 } else
scat6490 2:21c4f254786f 176 {
scat6490 5:f5fa116b57a1 177 buzzer = 0; // Don't buzz
scat6490 2:21c4f254786f 178 }
scat6490 1:a33f6ca5a5b3 179
scat6490 6:d80627e78bfd 180 TFT.foreground(White); // Set text to white
scat6490 8:6bd70a8697f4 181 TFT.locate(120, 70); // Move the text location
scat6490 8:6bd70a8697f4 182 TFT.printf("%02d:%02d.%02d", clock_hours, clock_minutes, clock_seconds); // Write the time to the TFT
scat6490 7:007d23438920 183
scat6490 7:007d23438920 184 if (enable){ // Check if the alarm is enabled
scat6490 7:007d23438920 185 TFT.foreground(Green); // Write the alarm text in green
scat6490 7:007d23438920 186 } else {
scat6490 7:007d23438920 187 TFT.foreground(Red); // Write the alarm text in red
scat6490 7:007d23438920 188 }
scat6490 5:f5fa116b57a1 189 TFT.locate(30, 120); // Move the text location
scat6490 5:f5fa116b57a1 190 TFT.printf("Alarm: %02d:%02d", alarm_hours, alarm_minutes); // Write the alarm time to the TFT
scat6490 3:6a328c7e9b1c 191
scat6490 5:f5fa116b57a1 192 drawclock(); // Call a function to draw the analogue clock
scat6490 7:007d23438920 193 previous_state = enable; // Update the state to changes can be detected
scat6490 0:4fd6c8718206 194 }
scat6490 0:4fd6c8718206 195
scat6490 0:4fd6c8718206 196 }