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)

main.cpp

Committer:
scat6490
Date:
2017-05-26
Revision:
9:d34cdff0205c
Parent:
8:6bd70a8697f4

File content as of revision 9:d34cdff0205c:

#include "stdio.h" // Import libraries to use
#include "mbed.h"
#include "SPI_TFT_ILI9341.h"
#include "string"
#include "Arial12x12.h"
#include "Arial24x23.h"
#include "Arial28x28.h"
#include "font_big.h"
#include "MMA8451Q.h"

#define MMA8451_I2C_ADDRESS (0x1d<<1)

Ticker timer; // Set up a timer                         
DigitalOut buzzer(PTE30); // Set up inputs and outputs
DigitalIn input1(PTA5); // Input for the minute button
DigitalIn input60(PTC8); // Input for the hour button
DigitalIn input_time_change(PTC9); // Input for the button which switches from changing the alarm and changing the time
Serial pc(USBTX,USBRX); // Connection to the desktop, currently only used for debugging
SPI_TFT_ILI9341 TFT(PTD2, PTD3, PTD1, PTD5, PTD0, PTA13,"TFT"); // mosi, miso, sclk, cs, reset, dc for frdmkl25z

int clock_minutes, clock_hours, clock_seconds = 0; // Initialise clock at 00:00.00
int alarm_hours = 7; // Initialise alarm hours as 07
int alarm_minutes = 0; // Initialise alarm minutes as 00 so alarm is 07:00
int previous_state, enable; // Initialise the previous state and enable variables to detect changing rotation

void timeup(){ // Function to increment the clock every second
    clock_seconds++; // Increment the time
    clock_seconds %= 60; // Reset seconds to 0 if it gets to 60
    
    if (clock_seconds==0) 
    {
        clock_minutes++; // Add a minute if the seconds got reset
        clock_minutes %= 60; // Reset the minutes to 0 if it gets to 60
    }
    if (clock_minutes==0 && clock_seconds==0) 
    {
        clock_hours++; // Add an hour if the minutes got reset
        clock_hours %= 24; // Reset the hour to 0 if it gets to 24` 
    }
}

void drawclock() // Draws an analogue clock using the clock_minutes and clock_hours variables
{
    int hourX, hourY, minuteX, minuteY, secondX, secondY; // Initialise variables to be used
    int circleX = 250; // Circle centre X
    int circleY = 200; // Circle centre Y
    int circleRadius = 30; // Circle radius
    
    double factorH = (2 * 3.141) / 12; // Convert hour to radians
    double factorM = (2 * 3.141) / 60; // Convert minute to radians
    double factorS = (2 * 3.141) / 60; // Convert second to radians
    
    hourX = floor(0.6 * circleRadius * sin((double) (clock_hours * factorH))); // Calculate difference in X values of the two ends of the hour hand.
    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
    minuteX = floor(0.95 * circleRadius * sin((double) (clock_minutes * factorM))); // Same for X of minute hand
    minuteY = floor(0.95 * circleRadius * cos((double) (clock_minutes * factorM))); // Same for Y of minute hand
    secondX = floor(0.85 * circleRadius * sin((double) (clock_seconds * factorS))); // Same for X of second hand
    secondY = floor(0.85 * circleRadius * cos((double) (clock_seconds * factorS))); // Same for Y of second hand
    
    if (enable) // Checks if the alarm is enabled
    {
        TFT.fillcircle(circleX, circleY, circleRadius, Green); // Draws a green circle
        TFT.circle(circleX, circleY, circleRadius, Black); // Draws a white circle around the red circle
        TFT.line(circleX, circleY, circleX + hourX, circleY - hourY, Black); // Draws the hour hand
        TFT.line(circleX, circleY, circleX + minuteX, circleY - minuteY, Black); // Draws the minute hand
        TFT.line(circleX, circleY, circleX + secondX, circleY - secondY, White); // Draws the second hand
        
        for (int i = 0; i < 12; i++)
        {
            int timeX = floor(circleRadius * sin((double) (i * factorH))); // Calculate the X for the hour indicators around the edge
            int timeY = floor(circleRadius * cos((double) (i * factorH))); // Same for Y of the hour indicators
        
            TFT.line(circleX + 0.8 * timeX, circleY - 0.8 * timeY, circleX + timeX, circleY - timeY, Black); // Draws the hour indicators
        }
    } else
    {
        TFT.fillcircle(circleX, circleY, circleRadius, Red); // Draws a red circle
        TFT.circle(circleX, circleY, circleRadius, White); // Draws a white circle around the red circle
        TFT.line(circleX, circleY, circleX + hourX, circleY - hourY, White); // Draws the hour hand
        TFT.line(circleX, circleY, circleX + minuteX, circleY - minuteY, White); // Draws the minute hand
        TFT.line(circleX, circleY, circleX + secondX, circleY - secondY, Black); // Draws the second hand
        
        for (int i = 0; i < 12; i++)
        {
            int timeX = floor(circleRadius * sin((double) (i * factorH))); // Calculate the X for the hour indicators around the edge
            int timeY = floor(circleRadius * cos((double) (i * factorH))); // Same for Y of the hour indicators
        
            TFT.line(circleX + 0.8 * timeX, circleY - 0.8 * timeY, circleX + timeX, circleY - timeY, White); // Draws the hour indicators
        }
    }
}

int main()
{
    MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); // Set up the accelerometer connection
    wait(0.5); // Just wait for set up
    previous_state = acc.getAccX() >= 0.5; // Initialise the previous state variable
     
    TFT.set_orientation(3); // Make the display horizontal
    TFT.background(Black); // Set background to black
    TFT.foreground(White); // Set text to white
    TFT.cls(); // Clear screen
    
    TFT.set_font((unsigned char*) Arial12x12); // Set the font to Arial 12x12
    TFT.fillrect(0, 0, 320, 32, Red); // Draw a red rectangle at the top
    TFT.locate(10, 10); // Move the text location
    TFT.printf("Clock by Duncan and Kieran"); // Write some text in the box at the top
    
    TFT.background(Black); // Set background to black
    TFT.set_font((unsigned char*) Arial28x28); // Set the font to Arial 28x28
    TFT.locate(30, 70); // Move the text location
    TFT.printf("Time:"); // Display some text
    
    timer.attach(&timeup, 1); // Set up the timer so it increments every second
    
    while(1) {
        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)
        {
            switch(input1){ // Check if the minute button is pressed
                case 1:
                    clock_minutes++; // Increment the time minutes
                    clock_minutes %= 60; // Set the minutes back to 0 if it's 60
                    wait(0.2); // Wait so the time doesn't increase too fast
                    break;
                case 0:
                    break;
            }
            switch(input60){ // Check if the hour button is pressed
                case 1:
                    clock_hours++; // Increment the time hours
                    clock_hours %= 24; // Set the hours back to 0 if it's 24
                    wait(0.2); // Wait so the time doesn't increase too fast
                    break;
                case 0:
                    break;
            }
        } else
        {
            switch(input1){ // Check if the minute button is pressed
                case 1:
                    alarm_minutes++; // Increment the alarm minutes
                    alarm_minutes %= 60; // Set the minutes back to 0 if it's 60
                    wait(0.2); // Wait so the alarm time doesn't increase too fast
                    break;
                case 0:
                    break;
            }
            switch(input60){ // Check if the hour button is pressed
                case 1:
                    alarm_hours++; // Increment the alarm hours
                    alarm_hours %= 24; // Set the hours back to 0 if it's 24
                    wait(0.2); // Wait so the alarm time doesn't increase too fast
                    break;
                case 0:
                    break;
            }
        }
        
        float x = acc.getAccX(); // Check the x-orientation
        enable = 1; // Initialise the enable variable
        
        if (x < 0.5){ // Check if the clock is tilted
          enable = 0; // Disable the alarm
        }
        if (enable != previous_state && !enable && clock_hours == alarm_hours && clock_minutes == alarm_minutes) // If the clock is tilted while the alarm is going off
        {
            alarm_minutes += 5; // Add 5 minutes (snooze)        
        }
        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
        {
            buzzer = 1; // Buzz
            wait(0.2); // Wait
            buzzer = 0; // Don't buzz
            wait(0.2); // Wait
        } else
        {
            buzzer = 0; // Don't buzz  
        }
        
        TFT.foreground(White); // Set text to white
        TFT.locate(120, 70); // Move the text location
        TFT.printf("%02d:%02d.%02d", clock_hours, clock_minutes, clock_seconds); // Write the time to the TFT
        
        if (enable){ // Check if the alarm is enabled
            TFT.foreground(Green); // Write the alarm text in green
        } else {
            TFT.foreground(Red); // Write the alarm text in red
        }
        TFT.locate(30, 120); // Move the text location
        TFT.printf("Alarm: %02d:%02d", alarm_hours, alarm_minutes); // Write the alarm time to the TFT
        
        drawclock(); // Call a function to draw the analogue clock
        previous_state = enable; // Update the state to changes can be detected
    }

}