Back to homepage
  • Assignments
    • Project Management
    • Computer-aided design
    • Computer-controlled cutting
    • Electronics Production
    • 3D Scanning and Printing
    • Electronics Design
    • Computer-controlled machining
    • Embedded Programming
    • Mechanical Design
    • Machine Design
    • Input Devices
    • Molding and Casting
    • Output Devices
    • Composites
    • Networking and Communications
    • Interface and Application Programming
    • Applications and Implications
    • Invention, Intellectual Property and Income
    • Project Development
  • Final Project
    • The idea
    • The design
    • Electronics
    • Prototyping
    • Final Presentation
  • Fab Academy

Final Project

Step 5 : Final Presentation

Here is the presentation of the final prototype of my "Smart Clock" which I imagined, designed, fabricated, programmed during Fab Academy 2016. I am very proud of the result and I hope you will like it !

  • Presentation
  • Gallery
  • Code
  • Sources
  • Conclusions

Presentation of the project
This is the "board" I presented during my final project review :

And this is the video :

Final Project Presentation from Thomas Feminier on Vimeo.


Pictures of my final project
Some pictures of the final prototype :

Previous Next

Presention video

Final demo of the clock


Final code
Still in progress
The clock works with two devices : and SatshaKit board made during week10, which is the same as an Arduino Uno, and an ESP8266 Huzzah (see here). The two devices are connected through seriol ports.
I am using two separated sketches. The first one, for the ESP8266, connects to a server on which I installed the forecast.io API and requests the time and weather. Here is the complete sketch :

                            

      /*  SMART_CLOCK_MASTER BY THOMAS FEMINIER
       *   This sketch does the following actions :
       *   - Connects to the server where I installed the API
       *   - Calls for date, time and weather every now and then
       *   - Sends the information to the main controller using serial communication
       *  © Thomas Feminier - Licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
       */

      #include <ESP8266WiFi.h>
      #include <SoftwareSerial.h>
      #include <SPI.h>

      const char* ssid     = "*******";
      const char* password = "*******";
      const char* host = "www.tomfem.fr";

      byte current_temp;
      byte current_icon;
      byte date;
      byte hour, last_hour;
      byte minute, last_minute;
      byte second, last_second;

      void setup() {
        Serial.begin(9600);
        delay(100);

        WiFi.begin(ssid, password);

        while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          // Serial.print(".");
        }

      }

      int value = 0;

      void loop() {
        delay(5000);
        ++value;

        // Use WiFiClient class to create TCP connections
        WiFiClient client;
        const int httpPort = 80;
        if (!client.connect(host, httpPort)) {
          //Serial.println("connection failed");
          return;
        }

                                                                   /*///////////// Action to run every minute //////////////*/

        if(last_minute != minute) { // Partie à faire toutes les minutes
                                                                     ///////////// Request for the hour //////////////
        String url = "/php/weather.php?param=HOUR";
        //Serial.print("Requesting URL: ");
        //Serial.println(url);

        // This will send the request to the server
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");
        delay(2000);

        // Read all the lines of the reply from server and print them to Serial
        while(client.available()){
          String line = client.readStringUntil('\r');
          //Serial.print(line);
          hour = line.toInt();
        }

        // NOUVEAU CODE D'ENVOI DE VALEUR
        Serial.write("HOUR");
        Serial.write(hour); ////send param to slave
        // FIN DU NOUVEAU CODE

          last_minute = minute;
        }
                                                                   /*///////////// Action to run every hour //////////////*/
        if(last_hour != hour) {
                                                                    ///////////// Request for the date //////////////

        String url = "/php/weather.php?param=DATE";
        Serial.print("Requesting URL: ");
        Serial.println(url);

        // This will send the request to the server
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");
        delay(2000);

        // Read all the lines of the reply from server and print them to Serial
        while(client.available()){
          String line = client.readStringUntil('\r');
          Serial.print(line);
          date = line.toInt();
        }
         Serial.write("DATE");
         Serial.write(date);

                                                                  ///////////// Request for the current temperature //////////////
        url = "/php/weather.php?param=CURRENT_TEMP";
        Serial.print("Requesting URL: ");
        Serial.println(url);

        // This will send the request to the server
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");
        delay(2000);

        // Read all the lines of the reply from server and print them to Serial
        while(client.available()){
          String line = client.readStringUntil('\r');
          Serial.print(line);
          current_temp = line.toInt();
        }
         Serial.write("CURRENT_TEMP");
         Serial.write(current_temp);

                                                                    ///////////// Request for the current icon //////////////
        url = "/php/weather.php?param=CURRENT_ICON";
        Serial.print("Requesting URL: ");
        Serial.println(url);

        // This will send the request to the server
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");
        delay(2000);

        // Read all the lines of the reply from server and print them to Serial
        while(client.available()){
          String line = client.readStringUntil('\r');
          Serial.print(line);
          current_icon = line.toInt(); //// print param to monitor
        }

          Serial.write("CURRENT_ICON");
          Serial.write(current_icon);

          last_hour = hour;
        }


                                                                   /*///////////// Action to run every 5 sec //////////////*/
        if(last_second - second > 5000) { // Partie à faire toutes les 5 secondes

                                                                     ///////////// Request for the minutes //////////////
        String url = "/php/weather.php?param=MINUTE";
        Serial.print("Requesting URL: ");
        Serial.println(url);

        // This will send the request to the server
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");
        delay(2000);

        // Read all the lines of the reply from server and print them to Serial
        while(client.available()){
          String line = client.readStringUntil('\r');
          Serial.print(line);
          minute = line.toInt();
        }

          Serial.write("MINUTE");
          Serial.write(minute);

                                                                     ///////////// Request for the seconds //////////////
        url = "/php/weather.php?param=SECOND";
        Serial.print("Requesting URL: ");
        Serial.println(url);

        // This will send the request to the server
        client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                     "Connection: close\r\n\r\n");
        delay(2000);

        // Read all the lines of the reply from server and print them to Serial
        while(client.available()){
          String line = client.readStringUntil('\r');
          Serial.print(line);
          second = line.toInt();
          Serial.write(second); ////send param to slave
        }

          last_second = second;
        }


        Serial.println();
        Serial.println("closing connection");

      }
                            
                          
The second one is uploaded on the Satshakit (or Arduino Uno). It sends the data from the ESP to the Uno which uses it to display the hours on the LED rings and the weather and date on the LED matrix :

                            
        /*  SMART_CLOCK_SLAVE BY THOMAS FEMINIER
         *   This sketch does the following actions :
         *   - Reads the date send through serial by the EPS8266
         *   - Interprets this data
         *   - Prints them using the LED rings and the LED matrix
         *  © Thomas Feminier - Licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
         */

        #include <Adafruit_GFX.h>
        #include <RGBmatrixPanel.h>
        #include <Adafruit_NeoPixel.h>
        #include <SoftwareSerial.h>
        #include <SPI.h>

        #define CLK 8  // MUST be on PORTB! (Use pin 11 on Mega)
        #define LAT A3
        #define OE  9
        #define A   A0
        #define B   A1
        #define C   A2
        RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);

        #define MIN 11
        #define HOURS 10

        Adafruit_NeoPixel stripmin = Adafruit_NeoPixel(60, MIN, NEO_GRB + NEO_KHZ800); //defines neopixel ring for min
        Adafruit_NeoPixel striphours = Adafruit_NeoPixel(12, HOURS, NEO_GRB + NEO_KHZ800);

        uint32_t ledscolor = stripmin.Color(0, 233,255); //defines the default color for the time
        uint8_t r=0, g=5, b=7; //defines the default color for the matrix (r,g and b from 0 to 7)
        const char current_icon;
        const char date;
        byte hour;
        byte minute;
        float current_temp;

        // Similar to F(), but for PROGMEM string pointers rather than literals
        #define F2(progmem_ptr) (const __FlashStringHelper *)progmem_ptr


        //defining all the weather icons

        const unsigned char PROGMEM clearday[] =
        // CLEAR DAY
        {
        0x0, 0x8, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x1c, 0x0,
        0x0, 0x0, 0x3e, 0x0, 0x0, 0x1, 0x7f, 0x40, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x1c,
        0x0, 0x0, 0x0, 0x49, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
        };

        const unsigned char PROGMEM clearnight[] =
        // CLEAR NIGHT
        {
        0x0, 0x30, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0x0, 0xf0, 0x0,
        0x0, 0x0, 0xf8, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x7f,
        0x0, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
        };
        const unsigned char PROGMEM rain[] =
        // RAIN
        {
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x1, 0xfc,
        0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x1f,
        0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x22, 0x48, 0x0, 0x0, 0x66, 0xd8, 0x0, 0x0, 0x4c, 0x90, 0x0,
        0x0, 0x8, 0x0, 0x0,
         };

        const unsigned char PROGMEM snow[] =
        // SNOW
        {
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x1, 0xfc,
        0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x1f,
        0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x8, 0xa0, 0x0, 0x0, 0x14, 0x44, 0x0, 0x0, 0x8, 0xa, 0x0,
        0x0, 0x0, 0x4, 0x0,
        };

        const unsigned char PROGMEM wind[] =
        // WIND
        {
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0xf8, 0x0, 0xf, 0xf1, 0xfc,
        0x0, 0x0, 0x3, 0xfe, 0x0, 0x3f, 0xc7, 0xff, 0x0, 0x0, 0x7, 0xff, 0x0, 0xf, 0x9f,
        0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
        };

        const unsigned char PROGMEM fog[] =
        // fog
        {
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x3f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0, 0x3, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
        };

        const unsigned char PROGMEM sleet[] =
        // SLEET
        {
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x1, 0xfc,
        0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x1f,
        0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x30, 0x6c, 0x0, 0x0, 0x33, 0xc, 0x0,
        0x0, 0x3, 0x0, 0x0,
        };

        const unsigned char PROGMEM cloudy[] =
        // CLOUDY
        {
        0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x0, 0xf8, 0x0, 0x0, 0x1, 0xfc,
        0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x1f,
        0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
         };

        const unsigned char PROGMEM partlycloudyday[] =
        // SUN AND CLOUD DURING DAY
        {
        0x0, 0x8, 0x0, 0x0, 0x0, 0x80, 0x70, 0x0, 0x0, 0x48, 0xf8, 0x0, 0x0, 0x1d, 0xfc,
        0x0, 0x0, 0x3f, 0xfe, 0x0, 0x1, 0x7f, 0xff, 0x0, 0x0, 0x3f, 0xff, 0x0, 0x0, 0x1f,
        0xff, 0x80, 0x0, 0x7f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
         };

        const unsigned char PROGMEM partlycloudynight[] =
        // SUN AND CLOUD DURING NIGHT
        {
        0x0, 0x30, 0x0, 0x0, 0x0, 0x70, 0x70, 0x0, 0x0, 0xf0, 0xf8, 0x0, 0x0, 0xf1, 0xfc,
        0x0, 0x0, 0xfb, 0xfe, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x7f,
        0xff, 0x80, 0x0, 0x3f, 0xff, 0x80, 0x0, 0xff, 0xff, 0x80, 0x1, 0xff, 0xff, 0x80, 0x1,
        0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
        0x0, 0x0, 0x0, 0x0,
        };

        void setup()
        {
        Serial.begin(9600);
        stripmin.begin(); // This initializes the NeoPixel library for the two rings
        striphours.begin();
        matrix.begin(); // This initializes the led matrix
        matrix.setTextWrap(false); // Allow text to run off right edge
        matrix.setTextSize(1); // sets text size on the matrix to one (smaller)
        }
        //// read the value of the params through serial ////

        void loop() {

           matrix.fillScreen(0);

           while(Serial.available() > 0){
        //// reads the value through serial and converts to variables

          if(Serial.readString() == "HOUR") {
            delay(500);
            while(Serial.available() > 0){
              String line = Serial.readString();
              hour = line.toInt();
            }
          }
            else if(Serial.readString() == "MINUTE") {
              delay(500);
            while(Serial.available() > 0){
              String line = Serial.readString();
              minute = line.toInt();
            }
           }
           else if(Serial.readString() == "CURRENT_TEMP") {
              delay(500);
            while(Serial.available() > 0){
              String line = Serial.readString();
              current_temp = line.toInt();
            }
           }
           else if(Serial.readString() == "DATE") {
              delay(500);
            while(Serial.available() > 0){
              String line = Serial.readString();
              date = line.toInt();
            }
           }
           else if(Serial.readString() == "CURRENT_ICON") {
              delay(500);
            while(Serial.available() > 0){
              String line = Serial.readString();
              current_icon = line.toInt();
            }
           }
           }

        ///Define which icon to display according to the value of current_icon
          switch (current_icon) {
          case 'clear-day':
            if (Serial.readString() == "clear-day") {
            current_icon = clearday;
            }
            break;
          case 'clear-night':
            if (Serial.readString() == "clear-night") {
            current_icon = clearnight;
            }
            break;
          case 'rain':
            if (Serial.readString() == "rain") {
            current_icon = rain;
            }
            break;
          case 'snow':
            if (Serial.readString() == "snow") {
            current_icon = snow;
            }
            break;
          case 'sleet':
            if (Serial.readString() == "sleet") {
            current_icon = sleet;
            }
            break;
          case 'fog':
            if (Serial.readString() == "fog") {
            current_icon = fog;
            }
            break;
          case 'cloudy':
            if (Serial.readString() == "cloudy") {
            current_icon = cloudy;
            }
            break;
          case 'partly-cloudy-day':
            if (Serial.readString() == "partly-cloudy-day") {
            current_icon = partlycloudyday;
            }
            break;
          case 'partly-cloudy-night':
            if (Serial.readString() == "partly-cloudy-night") {
            current_icon = partlycloudynight;
            }
            break;
          default:
            current_icon = clearday;
          break;
        }


          //display the hours on striphour
            for(int i=0;i<=hour;i++){
            striphours.setPixelColor(i,ledscolor);
            striphours.show();
            }

          //display the minutes on stripmin
            for(int j=0;j<=minutes;j++){
            stripmin.setPixelColor(j,ledscolor);
            stripmin.show();
            }

          //write the date
            matrix.setCursor(3,4);
            matrix.setTextColor(matrix.Color333(r,g,b));
            matrix.print(date);
            delay(3000);

            matrix.fillScreen(0);
            delay(0);

          // draw the weather icon
            matrix.drawBitmap(0, 0,  current_icon, 32, 16, matrix.Color333(r,g,b));
            delay (2000);
          // clear matrix
            matrix.fillScreen(0);
            delay (0);


          //write the temperature
            matrix.setCursor(8, 4);
            matrix.setTextColor(matrix.Color333(r,g,b));
            matrix.print(current_temp);
            matrix.drawCircle(21, 5, 1, matrix.Color333(r,g,b));
            delay (2000);
            matrix.fillScreen(0);
            delay (0);

        }
                            
                          
Finally, here is the .php code which talks to the API :

                            
    <html><body>
    <?php
            include('lib/forecast.io.php');
            $param = $_GET[param];
            $apiKeyParam = "541288a68a7158ad6065fe8c0102123e";
            $latParam = "48.868438";
            $lonParam = "2.348573";
            $units = 'auto';  // Can be set to 'us', 'si', 'ca', 'uk' or 'auto' (see forecast.io API); default is auto
            $lang = 'en'; // Can be set to 'en', 'de', 'pl', 'es', 'fr', 'it', 'tet' or 'x-pig-latin' (see forecast.io API); default is 'en'

            //error_log(date(DATE_RFC822)." -- api=".$apiKeyParam.",lat=".$latParam.",lon=".$lonParam.",units=".$units.",lang=".$lang."\n", 3, '/home/weather.log');
            if($param != "MINUTE" && $param != "HOUR" && $param != "DATE" ) {
              $forecast = new ForecastIO($apiKeyParam, $units, $lang);
              $condition = $forecast->getCurrentConditions($latParam, $lonParam);
              $conditions_week = $forecast->getForecastWeek($latParam, $lonParam);
            }

          switch($param) {
            case "DATE":
              echo date('d')." ".date('M');
              break;
            case "HOUR":
              echo date('h');
              break;
            case "MINUTE":
              echo date('i');
              break;
            case "SECOND":
              echo date('s');
              break;
            case "CURRENT_TEMP":
              echo round($condition->getTemperature());
              break;
            case "CURRENT_ICON":
              echo $condition->getIcon();
              break;
            case "MAX_TEMP_TOMORROW":
              echo "MAX_TEMP_TOMORROW=" . round($conditions_week[1]->getMaxTemperature());
              //echo round($conditions_week[1]->getMaxTemperature());
              break;
            case "ICON_TOMORROW":
              echo $conditions_week[1]->getIcon();
              break;
            default:
              echo date('d')." ".date('M').":".date('h').":".date('i').":".date('s').":".round($condition->getTemperature()).":".$condition->getIcon();
              break;
          }

    ?>
    </body>
    </html>
                            
                          
You can download those from the sources section.

Sources
You can download the sources below :

  • Arduino code and PHP script 
  • 3D model of the clock 
  • Weather icons 32x16px 
  • Eagle files (LED boards & powerboard) 

Please note that my work is licensed under the Creative Commons. See footer for details.

Conclusions
Like I said, I am very proud to have accomplished all this work, and to have learn so much ! Although at the moment I could not finish the Internet connection part, my clock works and is very close to the original design I imagined at the begining of the Fab Academy. Of course, there are still a lot of improvements to be made for my clock to really be perfect, and maybe marketable. Here is a list of what I achieved, and of what is still to be improved :

Achieved To be improved
Make a translucent wood pannel for the front of my clock

Make the wood appear normal when the LEDs are turned off

Create fab-made LED rings to fit my project

Create a gage effect for the minutes : a continuous circle of light which fills itself up as the time passes

Find a way to isolate each pixel of the LED matrix on the front of the clock

Create fab-made LED rings to fit my project

Make my own microcontroller board to pilot the clock

Make the clock easy to read (time-wise)

Make my own microcontroller board to pilot the clock

Link the clock to Internet - Ongoing process

Use the same technique for the hour ring as for the minutes one : mill segments of circles rather than connecting small PCBs with wires

Add connector pins to the PCBs rather than using wires soldered on the : they keep falling appart

Modify the internal structure of the clock to have a better nesting of all the components

Improve the code to allow animations on the clock, more visual effects

Change the colors according to the temperature
Develop an interface to be able to change the settings of the clock : colors, icons, information displayed on it...

Add a GPS device, to allow the clock to update the weather information according to the location

Improve the powering cable hole in the casing to make it less visible


Acknowledgements
I would like to thank all the people who helped me during the realization of this project !
My tutors, of course : Aldo Sollazzo, Saverio Silli, Matthieu Laverne, Fabien Bogni, and also my co-students Guillaume, Frédéric, Ludovic, Roman, Phonesavanth, and Vincent.
Also a big thank you to all the people at WoMa who where there when we needed help : Alex, Arnaud, Clément, Rémi, Guillaume.
And a special thanks to Roman and Fabien for their help on the programmation part of my project : I could not have done it without you !

Powered by Forecast.io

Creative Commons License
Contents are Licensed under a Creative Commons Attribution-NonCommercial 4.0 International License