Our clock project

Dependencies:   SPI_TFT_ILI9341 TFT_fonts Adafruit_RTCLib RTC-DS1307 TSI

IoT Clock

We have been given a task to design a clock with internet features, the 'Internet Clock'. First of all, we identified what features we want:

Display: Split into 4 parts:

  • Analogue clock - the good ol' fashioned circle display, complete with minute, hour and second hands.
  • Digital clock - equipped with date for the modern human.
  • Weather display - for those who cannot be bothered to look out of the window.
  • Alarm - just what you need when you have to get up or be somewhere.

Wifi module:

  • For collecting data for weather, alarm times and so it can be an 'Internet Clock'.

Speaker:

  • To make the annoying sound to let you know your alarm is going off.

Range finder:

  • To wave your hand in front of to turn the alarm off, because pressing a button is too last centurary.

The roles:

  • Soroush's first task was to get the LCD screen to work. Meanwhile Adam sorted out the speaker system.
  • When these were done, Adam worked on the screen to display a clock face and date/year. Soroush then connected the wifi module to extract data for weather, location and date. /media/uploads/amilner1/img_0285.jpg Connecting the wifi module.
  • The next part was to get the range-finder hooked up and responding to a hand passing, and switch the alarm off.
  • Finally, it was time for assembly.

Difficulties: There were many issues faced throughout the project. First of all, Adam's coding knowledge was a lot less than Soroush's which slowed down some completion of tasks. Although, this did help us sort out the roles. Next was the wifi connectivity which caused several problems during the project, and we couldn't get the connection or fetch data, which further slowed the process. Another difficulty was finding the range-finder's set-up page for mbed. However, when we got past these set backs we managed to put everything together quickly, /media/uploads/amilner1/img_0294.jpg All the hardware wired in.

Outcome:

  • Our LCD screen has 2 displays:
  1. 1 An analogue clock filling the screen.

/media/uploads/amilner1/img_0304.jpg

  1. 2 An analogue clock, date and year, weather and location, and alarm time.

/media/uploads/amilner1/img_0305.jpg

This is changed by holding (not passing quickly) your hand in front of the range-finder.

  • An RTC to keep track of the time rather than collecting the information from then internet. However, we have had a lot of problems setting this up, and it doesn't seem to respond.
  • Wifi is also not connected, so we have the default date, time, weather and location.
  • You are able to change the alarm time by swiping the touch pad on the back.

Perhaps given more time we'd be able to fix these problems. But a key point is that we have got all the other features working, except the correct time. /media/uploads/amilner1/img_0303.jpg

Display.cpp

Committer:
sfaghihi
Date:
2017-05-24
Revision:
14:85c51b4eff4b
Parent:
13:334c591a982b
Child:
15:452425c099ef

File content as of revision 14:85c51b4eff4b:

#include "Display.h"

Display::Display ()
    : myTFT(DISPLAY_MOSI_PIN, DISPLAY_MISO_PIN, DISPLAY_SCLK_PIN, DISPLAY_CS_PIN, DISPLAY_RST_PIN, DISPLAY_DC_PIN, "TFT")
{
    //myTFT = new SPI_TFT_ILI9341(DISPLAY_MOSI_PIN, DISPLAY_MISO_PIN, DISPLAY_SCLK_PIN, DISPLAY_CS_PIN, DISPLAY_RST_PIN, DISPLAY_DC_PIN,"TFT");
    myTFT.claim(stdout);        // send stdout to the TFT display
    myTFT.set_orientation(1);
    myTFT.background(Black);    // set background to black
    myTFT.foreground(White);    // set chars to white
    myTFT.cls();                // clear the screen
    myTFT.set_font((unsigned char*) Arial12x12);
    myTFT.locate(0,0);
    //LOG("O HOH O\r\n");
    //printf("O HOH O ");
}

void Display::drawClock(TimeClass *time, bool face, TimeClass *prevTime)
{
    //LOG("Small\r\n");
    /*myTFT.circle(70, 70, 60, 0xFFFFFF);                 // clock circle
    myTFT.line(70, 10, 70, 20, 0xFFFFFF);               // 12 oclock
    myTFT.line(70, 130, 70, 120, 0xFFFFFF);             // 6 oclock
    myTFT.line(10, 70, 20 , 70, 0xFFFFFF);              // 3 oclock
    myTFT.line(120, 70, 130 , 70, 0xFFFFFF);            // 9 oclock
    myTFT.line(100, 121.9615, 95, 113.301, 0xFFFFFF);   // 7 oclock
    myTFT.line(40, 18.0385, 45, 26.699, 0xFFFFFF);      // 1 oclock
    myTFT.line(121.9615, 100, 113.301, 95, 0xFFFFFF);   // 8 oclock
    myTFT.line(18.0385, 40, 26.699, 45, 0xFFFFFF);      // 2 oclock
    myTFT.line(121.9615,40,113.301,45, 0xFFFFFF);       // 4 oclock
    myTFT.line(18.0385,100,26.699,95, 0xFFFFFF);        // 10 oclock
    myTFT.line(100,18.0385,95,26.699, 0xFFFFFF);        // 5 oclock
    myTFT.line(40,121.9615,45,113.301, 0xFFFFFF);       // 11 olcock
    //LOG("SO Near: %x\r\n", (void *)time);
    float h = time->hour % 12;
    float m = time->minute;
    float s = time->second;
    float htheta = (M_PI/6.0)*(h + (m/60.0) + (s/3600.0));            // hour hand angle
    float mtheta = (M_PI/6.0)*(m + (s/60.0))/5.0;            // minute hand angle
    float stheta = (M_PI/6.0)*s/5.0;                       // second hand angle
    float hx = 70.0 + 15.0*sin(htheta);                     // hour hand position
    float hy = 70.0 - 15.0*cos(htheta);                     //
    float mx = 70.0 + 30.0*sin(mtheta);                     // minute hand position
    float my = 70.0 - 30.0*cos(mtheta);                     //
    float sx = 70.0 + 50.0*sin(stheta);                     // second hand position
    float sy = 70.0 - 50.0*cos(stheta);                     //
    //LOG("SO Far: %f, %f\r\n", sx, sy);
    if (cls) {
        myTFT.line(70, 70, hx, hy, Black);   // hour hand plot
        myTFT.line(70, 70, mx, my, Black);   // minute hand plot
        myTFT.line(70, 70, sx, sy, Black);   // second hand plot
    } else {
        myTFT.line(70, 70, hx, hy, Yellow);   // hour hand plot
        myTFT.line(70, 70, mx, my, White);   // minute hand plot
        myTFT.line(70, 70, sx, sy, DarkCyan);   // second hand plot
    }*/
    int xc = 80;
    int yc = 90;
    int r = 80;
    if (face) {
        myTFT.circle(xc, yc, r, White);                 // clock circle
        for (int i = 0; i < 12; i++)
            myTFT.line(xc+6*r/7*sin((float)i*M_PI/6.0), yc-6*r/7*cos((float)i*M_PI/6.0), 
            xc + r*sin((float)i*M_PI/6.0), yc-r*cos((float)i*M_PI/6.0), 0xFFFFFF);
    }
    
    //LOG("SO Near: %x\r\n", (void *)time);
    float h = time->hour % 12;
    float m = time->minute;
    float s = time->second;
    float htheta = (M_PI/6.0)*(h + (m/60.0) + (s/3600.0));            // hour hand angle
    float mtheta = (M_PI/6.0)*(m + (s/60.0))/5.0;            // minute hand angle
    float stheta = (M_PI/6.0)*s/5.0;                       // second hand angle
    int hx = xc + r*sin(htheta)/4.5;                     // hour hand position
    int hy = yc - r*cos(htheta)/4.5;                     //
    int mx = xc + r*sin(mtheta)/1.9;                     // minute hand position
    int my = yc - r*cos(mtheta)/1.9;                     //
    int sx = xc + r*sin(stheta)/1.5;                     // second hand position
    int sy = yc - r*cos(stheta)/1.5;                     //
    
    float ps = prevTime->second;
    float pm = prevTime->minute;
    float ph = prevTime->hour % 12;
    float hp_the = (M_PI/6.0)*(ph + (pm/60.0) + (ps/3600.0));
    float mp_the = (M_PI/6.0)*(pm + (ps/60.0))/5.0;
    float sp_the = (M_PI/6.0)*ps/5.0;
    int hxp = xc + r*sin(hp_the)/4.0;
    int hyp = yc - r*cos(hp_the)/4.0;                     //
    int mxp = xc + r*sin(mp_the)/1.9;                     // minute hand position
    int myp = yc - r*cos(mp_the)/1.9;                     //
    int sxp = xc + r*sin(sp_the)/1.5;                     // second hand position
    int syp = yc - r*cos(sp_the)/1.5;
    
    if (syp != sy || sxp != sx || face) {
        myTFT.line(xc, yc, sxp, syp, Black);
    }
    
    if (myp != my || mxp != mx || face) {
        myTFT.line(xc, yc, mxp, myp, Black);
    }
    
    if (hyp != hy || hxp != hx || face) {
        myTFT.line(xc, yc, hxp, hyp, Black);
    }
    
    myTFT.line(xc, yc, hx, hy, Yellow);
    myTFT.line(xc, yc, mx, my, White);
    myTFT.line(xc, yc, sx, sy, Orange);
   
    
}

void Display::drawClockBig(TimeClass *time, bool face, TimeClass *prevTime)
{
    int xc = myTFT.width()/2;
    int yc = myTFT.height()/2;
    int r = (myTFT.height()*5)/12;
    if (face) {
        myTFT.circle(xc, yc, r, White);                 // clock circle
        for (int i = 0; i < 12; i++)
            myTFT.line(xc+6*r/7*sin((float)i*M_PI/6.0), yc-6*r/7*cos((float)i*M_PI/6.0), 
            xc + r*sin((float)i*M_PI/6.0), yc-r*cos((float)i*M_PI/6.0), 0xFFFFFF);
    }
    
    //LOG("SO Near: %x\r\n", (void *)time);
    float h = time->hour % 12;
    float m = time->minute;
    float s = time->second;
    float htheta = (M_PI/6.0)*(h + (m/60.0) + (s/3600.0));            // hour hand angle
    float mtheta = (M_PI/6.0)*(m + (s/60.0))/5.0;            // minute hand angle
    float stheta = (M_PI/6.0)*s/5.0;                       // second hand angle
    int hx = xc + r*sin(htheta)/4.5;                     // hour hand position
    int hy = yc - r*cos(htheta)/4.5;                     //
    int mx = xc + r*sin(mtheta)/1.9;                     // minute hand position
    int my = yc - r*cos(mtheta)/1.9;                     //
    int sx = xc + r*sin(stheta)/1.5;                     // second hand position
    int sy = yc - r*cos(stheta)/1.5;                     //
    
    float ps = prevTime->second;
    float pm = prevTime->minute;
    float ph = prevTime->hour % 12;
    float hp_the = (M_PI/6.0)*(ph + (pm/60.0) + (ps/3600.0));
    float mp_the = (M_PI/6.0)*(pm + (ps/60.0))/5.0;
    float sp_the = (M_PI/6.0)*ps/5.0;
    int hxp = xc + r*sin(hp_the)/4.5;
    int hyp = yc - r*cos(hp_the)/4.5;                     //
    int mxp = xc + r*sin(mp_the)/1.9;                     // minute hand position
    int myp = yc - r*cos(mp_the)/1.9;                     //
    int sxp = xc + r*sin(sp_the)/1.5;                     // second hand position
    int syp = yc - r*cos(sp_the)/1.5;
    
    if (syp != sy || sxp != sx || face) {
        myTFT.line(xc, yc, sxp, syp, Black);
    }
    
    if (myp != my || mxp != mx || face) {
        myTFT.line(xc, yc, mxp, myp, Black);
    }
    
    if (hyp != hy || hxp != hx || face) {
        myTFT.line(xc, yc, hxp, hyp, Black);
    }
    
    myTFT.line(xc, yc, hx, hy, Yellow);
    myTFT.line(xc, yc, mx, my, White);
    myTFT.line(xc, yc, sx, sy, Orange);
    
}

char *month_names[] = 
{
    "Jan.", "Feb.", "Mar.", "Apr.", "May", "Jun.", 
    "Jul.", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."
};
char *dow_names[] = 
{
    "Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"
};

void Display::cls()
{
    myTFT.fillrect(0, 0, myTFT.width(), myTFT.height(), Black);
}

void Display::drawDate(DateClass *date)
{
    /*int d = date->day;
    int m = date->month;
    int y = date->year;*/
    //LOG("IN Date\r\n");
    //myTFT.set_font((unsigned char*)Arial28x28);
    myTFT.fillrect(0, 185, 50, myTFT.height(), Black);
    myTFT.foreground(Orange);
    myTFT.locate(20,190);
    printf("%s\n", dow_names[date->dow]);
    //LOG("OUTDATE\r\n");
    //myTFT.set_font((unsigned char*)Arial12x12);
    myTFT.locate(20,210);
    printf("%d %s %d\n", date->day, month_names[(date->month)-1], date->year);
    myTFT.foreground(White);
}

void Display::drawImg(int x, int y, const unsigned char *img, int w, int h)
{
    for (int i = 0; i < w; i++)
        for (int j = 0; j < h; j++)
            myTFT.pixel(x+i, y+j, (int)((((int)img[2*(w*j+i)]) << 8) & 0xff00) | ((int)img[2*(w*j+i)+1]&0xff));
}

void Display::drawWeather(WeatherClass *data, bool draw_img)
{
    if (draw_img)
        if (data->type == sunny)
            drawImg(200, 10, sunny_pic.pixel_data, sunny_pic.width, sunny_pic.height);
    myTFT.fillrect(200, 115, 200+70, 115+70, Black);
    //myTFT.set_font((unsigned char*)Arial12x12);
    myTFT.foreground(Yellow);
    myTFT.locate(210, 120);
    printf("%s\n", data->place);
    myTFT.locate(220, 140);
    myTFT.set_font((unsigned char*)Arial28x28);
    printf("%d %s\n", data->temp, data->isCelsius ? "C" : "F");
    myTFT.foreground(White);
    myTFT.set_font((unsigned char*)Arial12x12);
    
}

void Display::drawAlarm(TimeClass *alarmTime)
{
    
}

void Display::drawAll(StateClass *state, bool doCls)
{
    if (doCls)
        cls();
    if (!(state->screenActive))
        return;
    if (state->screenState == 0) {
        drawClock(state->time, true, state->prevTime);
        drawDate(state->date);
        drawWeather(state->weather, true);
        if (state->alarm)
            drawAlarm(state->alarm);
    } else if (state->screenState == 1) {
        drawClockBig(state->time, true, state->prevTime);
    }
}