IOT-2020-Efrei-M1-Clock

My goal for this project was to make a connected alarm clock.

For those of us who still use traditional clock radios, we know how impractical it can be to only be able to settle one alarm at a time. (maybe two if we chose a good one)
Every night, we have to check if the settled alarm is right for the next day, the risk being to forget and not to wake up in time.
For those who are not morning persons, putting several alarms is not really an option, and increasing or decreasing the time by pushing two buttons to settle our alarm is not the fastest method, we may loose a lot of time if we have to change our wake-up time often.
My project was to make an alarm clock that could solve all these inconveniences.

Slides & Videos

Members

NameContribution
Jade MorinBecause of COVID-19, I could not come on the school's campus and was not allowed to have a partner on this project.
I had to do the whole project by myself.
It may not seem as evolved as some of my classmates projects, but it is fully operational, it meets all the expectations I wanted to fulfill with my project, and I had to do it all alone and from a far.

State of the Art

Business Aspect

Assistant vocal Amazon Echo Show 8 Anthracite

When we search “connected alarm clock” on Internet, the first result is an article that compares 10 connected alarm clock to help us chosse the best one.

According to the article, the best one on the market, and the one with the best price/performance ratio is the “Assistant vocal Amazon Echo Show 8 Anthracite”. But when we take a closer look at the main features that all these products offer, we realize that they have a completely different purpose, and just happen to also give time. Most of them are voice assistant and are used as a communication interface with connected objects such as Alexa, or Google Home. They may be really usefull, but their technology level impact their prices. As an example, the Assistant vocal Amazon Echo Show 8 Anthracite is sold for 130euros, when my connected alarm clock has a “production cost” of approximately 50 euros.

When we look closer, we can see that nothing in the business field has actually the same purpose than the project I made, for the same price.

Technical Aspect

Arduino Clock

When we search “Arduino connected alarm clock” on Internet, there are a few interesting results. The first one is an article explaining how to make your own alarm clock using Arduino. The ones that follows are often by the same person, and they are all very interesting, but when we take a closer look and read them all, we realize that none of them is actually connected.

It would seem that the project I wanted to make has not been made often, or if so, that the people who made it did not share their experience yet.

Project Description

Problem Definition
As I explained in the introduction, alarm clocks are sometimes not very practical. Not being able to put several alarms and having to push two buttons until the alarm is at the right time may not be the best use of an alarm clock.
So I decided to make my own connected alarm clock that would solve all these inconvenience.
Challenges &Β Motivation
The challenge in this project was that I had never worked with Arduino before, and I had never build anything myself with electronic stuff.
Also, I had to build a whole website as an interface to settle all the alarms the user could want, and being able to activate them or not.
My motivations were that this object is an object that is usefull everyday, but nothing on the market proposes something like what I imagined.
Real and Complete Usecases

Example of Use Case :

-The user sets all the alarms he wants on the website.

-With several WiFi libraries, the computer collects all the alarms that are activated (because if the user does not want an alarm to ring he can deactivate it)

-The computer reads and stores the time that he must ring to

-When it is time, the connected alarm clock rings

-The user push the button and it stops the alarm

UseCase

Technical Description

In terms of connections, the system is relatively simple. Here is the schematic of the project. I used the Arduino Uno WiFi Rev2 so i did not have to buy a WiFi module to add on my breadboard. With the module RTC and the Wifi module, I connect to a server which gives me the number of seconds since the 1st January of 1900 and converts it in Unix time. Since I get the UTC time, i add 3600 seconds to get the local time.

With an HTTP GET, I recuperate all the alarms that the user has activated as a String. (For example, if there are two alarms activated, 12:00 and 13:32, I recuperate “12:0013:32”) Then I parse it for the system to be able to “read” it. When the hour is the same that the alarms the computer stores, the alarm rings.

The Arduino system is not too complex, but it was not easy to build a whole website, and to connect to it to only get the alarms.

Here are 2 images, one of the website, and one of the output I get when I run my code.

Β 

Hardware

Materials
ImageNamePart NumberPriceCountLink
Arduino UNO WiFi Rev2138.90 euros1πŸ›’
Breadboard25.67 euros1πŸ›’
Arduino LCD 160234.50 euros1πŸ›’
RTC DS323144.99 euros1πŸ›’
Potentiometer50.89 euros1πŸ›’
Push Button60.35 euros1πŸ›’
Resistor 220 OHM70.05 euros2πŸ›’
Active Buzzer80.70 euros1πŸ›’
Fils connecteurs92.57 eurosAbout 30πŸ›’
Schematic

Software

Arduino Code

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "LiquidCrystal.h"
#include "arduino_secrets.h" 

char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
int status = WL_IDLE_STATUS;
unsigned int localPort = 2390;
IPAddress timeServer(129, 6, 15, 28);
const int NTP_PACKET_SIZE = 48;
byte packetBuffer[ NTP_PACKET_SIZE];
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0E, 0xA5, 0x7E };
IPAddress ip(192,168,0,143);
WiFiClient client;
WiFiUDP Udp;
DS3231 Clock;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

time_t present;

const int broBuzzer = 9;

volatile int alarm = 0;
String current_alarm="";

void setup() {
  
  pinMode(broBuzzer, OUTPUT);
  attachInterrupt (13, stopAlarm, CHANGE);

  Serial.begin(57600);
  lcd.begin(16,2);
  while (!Serial) {
  }

  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }

  Serial.print("You're connected to the network");
  printCurrentNet();
  printWifiData();

  Serial.println("\nStarting connection to server...");
  Udp.begin(localPort);

  sendNTPpacket(timeServer);
  delay(1000);
  if (Udp.parsePacket()) {
    Serial.println("packet received");
    Udp.read(packetBuffer, NTP_PACKET_SIZE);
    
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = ");
    Serial.println(secsSince1900);
    Serial.print("Unix time = ");
    const unsigned long seventyYears = 2208988800UL;
    unsigned long epoch = secsSince1900 - seventyYears + 3600L;
    Serial.println(epoch);

    Serial.print("The local time is ");
    Serial.print((epoch  % 86400L) / 3600);
    Serial.print(':');
    if (((epoch % 3600) / 60) < 10) {
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60);
    Serial.print(':');
    if ((epoch % 60) < 10) {
      Serial.print('0');
    }
    Serial.println(epoch % 60);
    setTime(epoch);
  }
}

void loop() {
  
  int x=0;
  char body_start='[';
  char body_end=']';
  String HTTPoutputString = "";
  
  int    HTTP_PORT   = 80;
  String HTTP_METHOD = "GET";
  char   HOST_NAME[] = "alarmes.jademorin.fr";
  String PATH_NAME   = "/alarms.json";

  if(client.connect(HOST_NAME, HTTP_PORT)) {
    Serial.println("Connected to server");
    client.println(HTTP_METHOD + " " + PATH_NAME + " HTTP/1.1");
    client.println("Host: " + String(HOST_NAME));
    client.println("Connection: close");
    client.println();

    while(client.connected()) {
      if(client.available()){
        char c = client.read();
        if (c==body_start) x=(x+1);
        if (x==1 && c!=body_start && c!=body_end && c!='"' && c!=',') HTTPoutputString += c;
        if (c==body_end) x=(x+1);
      }
    }

    Serial.println(HTTPoutputString);

      int stockage_len = HTTPoutputString.length()/5;
      String stockage[stockage_len];

      for(int i=0 ; HTTPoutputString[i] != '\0'; i=i+5) {
        String time="";
        for(int j=0 ; j<5; j++) {
          time = time + char(HTTPoutputString[i+j]);
        }
        stockage[i/5]= time;
      }

    
    String current_time = time_format(hour()) + ":" + time_format(minute());
    for (int i = 0; i < stockage_len; i++) {
      Serial.println(stockage[i]);
      if (current_time == stockage[i] && stockage[i]!=current_alarm) {
        current_alarm=stockage[i];
        alarm = 1;
      }
    }
    
    sonnerAlarme();
          
    if(!client.connected())
    {
      Serial.println("disconnected");
      client.stop();
    }

  } else {
    Serial.println("connection failed");
  }

  time_t tm;
  tm = now();
  if (tm) {
    Serial.print("Ok, Time = ");
    print2digits(hour());
    Serial.write(':');
    print2digits(minute());
    Serial.write(':');
    print2digits(second());
    Serial.print(", Date (D/M/Y) = ");
    Serial.print(day());
    Serial.write('/');
    Serial.print(month());
    Serial.write('/');
    Serial.print(year());
    Serial.println();
  } 
  delay(500);
  present = now();
  reafficher();
}

void printWifiData() {
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  Serial.println(ip);

  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  printMacAddress(mac);
}

void printCurrentNet() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  printMacAddress(bssid);

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);

  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 5; i >= 0; i--) {
    if (mac[i] < 16) {
      Serial.print("0");
    }
    Serial.print(mac[i], HEX);
    if (i > 0) {
      Serial.print(":");
    }
  }
  Serial.println();
}


unsigned long sendNTPpacket(IPAddress& address) {
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  packetBuffer[0] = 0b11100011;
  packetBuffer[1] = 0;
  packetBuffer[2] = 6;
  packetBuffer[3] = 0xEC;
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  Udp.beginPacket(address, 123);
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

String time_format(int number) {
  String number_format = "";
  if (number >= 0 && number < 10) {
    number_format = "0"+String(number);
  }
  else {
    number_format = String(number);
    }
  return number_format;
}

void reafficher(){
    int h = hour();
    int m = minute();
    int s = second();

    lcd.setCursor(2, 0);
    lcd.print("Horloge Jade"); 
    lcd.setCursor(4, 1);
    if (h<10){
      lcd.print(0); 
    }  
    lcd.print(h);    
    lcd.setCursor(6, 1);  
    lcd.print(":");
    lcd.setCursor(7, 1);
    if (m<10){
      lcd.print(0); 
    }  
    lcd.print(m);       
    lcd.setCursor(9, 1); 
    lcd.print(":");     
    lcd.setCursor(10, 1);
    if (s<10){
      lcd.print(0);
    }  
    lcd.print(s);
}

void sonnerAlarme() {
  float frequenceAL=1400;
  float periodeAL = (1.0 / frequenceAL) * 1000000;
  long  dureeBip = 50000;
  long  tempsPasse = 0;

  while (tempsPasse < dureeBip && alarm == 1) {
    digitalWrite(broBuzzer,HIGH);
    delayMicroseconds(periodeAL / 2);
    digitalWrite(broBuzzer, LOW);
    delayMicroseconds(periodeAL / 2);
    tempsPasse += (periodeAL);
  }
  delayMicroseconds(dureeBip);

}

void stopAlarm() {
  Serial.println("Interruption en cours");
  alarm = 0;
}

External Services

Alarm Website

I built an entire website for the user to settle every alarm he wants.

He can either activate or deactivate them, depending on if he wants them to ring or not, and he can put as many alarms as he wants.

He can put an alarm whenever he wants, from wherever he wants, for whenever he wants.

To see the website, you can go to alarmes.jademorin.fr