Jayakarthigeyan Prabakar
Published © GPL3+

Smart Desk Clock - To Save Power Using IoT at Home & Office

Wi-Fi connected desk clock with RGB panel, controls IR and Wi-Fi based switches to control AC appliance via IR or Internet to save power.

AdvancedFull instructions provided2 days3,530

Things used in this project

Hardware components

DPS310
Infineon DPS310
×1
SENSE2GOL - 24GHz Radar kit
Infineon SENSE2GOL - 24GHz Radar kit
×1
WS2812B-5050-RGB-LED-4x4-16Bit-RGB-LED
×1
NodeMCU ESP8266 Breakout Board
NodeMCU ESP8266 Breakout Board
×1
Adafruit Super-bright 5mm IR LED - 940nm
×1
OLED Display
×1
Wi-Fi IoT Switches and IR Switches for Home Automation
×1

Software apps and online services

Arduino IDE
Arduino IDE
Infineon DAVE™ (Version 4) – Development Platform for XMC™ Microcontrollers
Cordova

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Top_Plate

Right_Plate

Left_Plate

Front_Plate

Base_Plate

Back_Plate

Enclosure Assembly

Enclosure Plot

Schematics

Full Schematic

Connect the components as shown in this schematic diagram

Code

Final Code

Arduino
Smart Desk Clock Code
///////////////////////////////////////////////////////////////////////
#include <ifx_dps310.h>
SlowSoftWire WireX = SlowSoftWire(4, 5);
/////////////////////////////////////////////////////////////////////////////////
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, 5, 4);
////////////////////////////////////////////////////////////////////////////////
int App = 14;
int Dep = 13;
String MStat = "";
unsigned long previousMillis = 0;
unsigned long prev = 0;
////////////////////////////////////////////////////////////////////////
#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRsend.h>
IRsend irsend(0);  // An IR LED is controlled by GPIO pin 0
/////////////////////////////////////////////////////////////////////////
String DoorStat = "";
String PrevDoorStat = "MainDoorClosed";
int32_t pressureCB = 0;
String LightFanStat = "";
String PLightFanStat = "";
String LavatoryStat = "LavatoryUnoccupied";
String MainRoomStat = "MainRoomUnoccupied";
/////////////////////////////////////////////////////////////////////////
int32_t temperature;
int32_t pressure;
int ret;
/////////////////////////////////////////////////////////////////////////
int IF = 0;
int ProxS = 0;
int CatProx = 0;
/////////////////////////////////////////////////////////////////////////
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIN            12
#define NUMPIXELS      16
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
//////////////////////////////////////////////////////////////////////////
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "*****************"; //Mention your Wi-Fi SSID Here
const char* password = "*****************"; //Mention your Wi-Fi Password Here
const char* mqtt_server = "*****************"; //Mention the your MQTT server details here
WiFiClient espClient;
PubSubClient client(espClient);
char msg[50];
String MssgF = "";
//////////////////////////////////////////////////////////////////////////////
#include <TimeLib.h>
#include <WiFiUdp.h>
static const char ntpServerName[] = "us.pool.ntp.org";
const int timeZone = +5;
WiFiUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets
time_t getNtpTime();
void digitalClockDisplay();
void printDigits(int digits);
void sendNTPpacket(IPAddress &address);
time_t prevDisplay = 0;
///////////////////////////////////////////////////////////////////////////////
void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  MssgF = "";
  for (int i = 0; i < length; i++) {
    //Serial.print((char)payload[i]);
    MssgF += (char)payload[i];
  }
  MssgF.trim();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("HacksterProjectTx", "Connected");
      // ... and resubscribe
      client.subscribe("HacksterProjectRx");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
////////////////////////////////////////////////////////////////////////////////
String OpMode = "NA";
////////////////////////////////////////////////////////////////////////////////
void setup()
{
  Serial.begin(9600);
  ////////////////////////////////////////////////////////////////////
  WireX.begin();
  ifxDps310.begin(WireX, 0x76);
  //ifxDps310.correctTemp();
  Serial.println("Init complete!");
  ////////////////////////////////////////////////////////////////////
  pinMode(App, INPUT);
  pinMode(Dep, INPUT);
  ////////////////////////////////////////////////////////////////////
  irsend.begin();
  ////////////////////////////////////////////////////////////////////
  pixels.begin();
  ////////////////////////////////////////////////////////////////////
  setup_wifi();
  ////////////////////////////////////////////////////////////////////
  Serial.println("Starting UDP");
  Udp.begin(localPort);
  Serial.print("Local port: ");
  Serial.println(Udp.localPort());
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  setSyncInterval(300);
  /////////////////////////////////////////////////////////////////////
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  ////////////////////////////////////////////////////////////////////
  irsend.sendRaw(ON, sizeof(ON) / sizeof(ON[0]), 38);
  ////////////////////////////////////////////////////////////////////
  u8g2.begin();
}

void loop()
{
  ///////////////////////////////////////////////////////////////////////
  ret = ifxDps310.measureTempOnce(temperature);
  if (ret != 0)
  {
    Serial.print("FAIL! ret = ");
    Serial.println(ret);
  }
  else
  {
    //Serial.print("Temperature: ");
    int32_t tempA = 57;
    int32_t tempB = 63;
    if (temperature > tempA && temperature < tempB) {
      ifxDps310.correctTemp();
    }
    //Serial.print(temperature);
    //Serial.print(" ");
    //Serial.println(" degrees of Celsius");
  }
  ret = ifxDps310.measurePressureOnce(pressure);
  if (ret != 0)
  {
    Serial.print("FAIL! ret = ");
    Serial.println(ret);
  }
  else
  {
    //Serial.print("Pressure: ");
    //Serial.println(pressure);
    //Serial.println(" Pascal");
  }
  ///////////////////////////////////////////////////////////////////////
  if (timeStatus() != timeNotSet) {
    if (now() != prevDisplay) { //update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();
    }
  }
  ///////////////////////////////////////////////////////////////////////
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  ///////////////////////////////////////////////////////////////////////
  unsigned long currentMillis = millis();
  ///////////////////////////////////////////////////////////////////////
  if (MssgF != "") {
    Serial.print("MssgF: ");
    Serial.println(MssgF);
    if (MssgF.indexOf("RGBM") != -1) {
      OpMode = "RGBM";
      client.publish("HacksterProjectTx", String(OpMode).c_str());
    }
    else if (MssgF.indexOf("CABINM") != -1) {
      OpMode = "CABINM";
      pressureCB = pressure;
      PrevDoorStat = "MainDoorClosed";
      client.publish("HacksterProjectTx", String(OpMode).c_str());
    }
    else if (MssgF.indexOf("NIGHTM") != -1) {
      OpMode = "NIGHTM";
      client.publish("HacksterProjectTx", String(OpMode).c_str());
    }
    else if (MssgF.indexOf("LIVINGM") != -1) {
      OpMode = "LIVINGM";
      client.publish("HacksterProjectTx", String(OpMode).c_str());
    }
    else if (MssgF.indexOf("SURVEILLANCEM") != -1) {
      OpMode = "SURVEILLANCEM";
      pressureCB = pressure;
      PrevDoorStat = "MainDoorClosed";
      client.publish("HacksterProjectTx", String(OpMode).c_str());
    }
    else if (MssgF.indexOf("RGB:") != -1 && OpMode == "RGBM") {
      int FOB = MssgF.indexOf(':');
      int FCB = MssgF.indexOf(',', FCB + 1);
      int SOB = MssgF.indexOf(',', FCB + 1);
      int SCB = MssgF.indexOf('.', SOB + 1);
      String StrR = MssgF.substring(FOB + 1, FCB);
      String StrG = MssgF.substring(FCB + 1, SOB);
      String StrB = MssgF.substring(SOB + 1, SCB);
      int R = StrR.toInt();
      int G = StrG.toInt();
      int B = StrB.toInt();
      /*Serial.print(R);
        Serial.print(".");
        Serial.print(G);
        Serial.print(".");
        Serial.println(B);*/
      for (int i = 0; i < NUMPIXELS; i++) {
        pixels.setPixelColor(i, pixels.Color(R, G, B)); // RGB Color
        pixels.show(); // This sends the updated pixel color to the hardware
      }
    }
    MssgF = "";
  }
  ///////////////////////////////////////////////////////////////////////
  int Aps = digitalRead(App);
  int Dps = digitalRead(Dep);
  if (Aps == HIGH && Dps == HIGH) {
    MStat = "No motion";
    if (OpMode == "NIGHTM") {
      if (currentMillis - previousMillis >= 10000) {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // RGB Color
          pixels.show(); // This sends the updated pixel color to the hardware
        }
      }
      prev = millis();
    }
    else if (OpMode == "LIVINGM") {
      prev = millis();
    }
  }
  else if (Aps == HIGH && Dps == LOW) {
    MStat = "Departing";
    if (OpMode == "NIGHTM" && (millis() - prev) > 1500) {
      for (int i = 0; i < NUMPIXELS; i++) {
        pixels.setPixelColor(i, pixels.Color(255, 255, 255)); // RGB Color
        pixels.show(); // This sends the updated pixel color to the hardware
      }
      previousMillis = currentMillis;
    }
    else if (OpMode == "LIVINGM" && (millis() - prev) > 2500) {
      LightFanStat = "BedRoomLightOff";
      prev = millis();
    }
  }
  else if (Aps == LOW && Dps == HIGH) {
    MStat = "Approaching";
    if (OpMode == "NIGHTM" && (millis() - prev) > 1500) {
      for (int i = 0; i < NUMPIXELS; i++) {
        pixels.setPixelColor(i, pixels.Color(255, 255, 255)); // RGB Color
        pixels.show(); // This sends the updated pixel color to the hardware
      }
      previousMillis = currentMillis;
    }
    else if (OpMode == "LIVINGM" && (millis() - prev) > 2500) {
      LightFanStat = "BedRoomLightOn";
      prev = millis();
    }
  }
  //Serial.println(MStat);
  ///////////////////////////////////////////////////////////////////////
  if (PLightFanStat != LightFanStat) {
    if (LightFanStat == "BedRoomLightOn") {
      Serial.println(LightFanStat);
      client.publish("HacksterProjectTx", String(LightFanStat).c_str());
      irsend.sendNEC(0x8F751AE, 32); // 3
    }
    else if (LightFanStat == "BedRoomLightOff") {
      Serial.println(LightFanStat);
      client.publish("HacksterProjectTx", String(LightFanStat).c_str());
      irsend.sendNEC(0x8F751AE, 32); // 3
    }
    PLightFanStat = LightFanStat;
  }
  ///////////////////////////////////////////////////////////////////////
  if (OpMode == "CABINM" || OpMode == "SURVEILLANCEM") {
    int32_t pressureHM = pressureCB + 3;
    int32_t pressureLM = pressureCB - 3;
    if (pressure > pressureHM) {
      if (OpMode == "CABINM") {
        if (PrevDoorStat == "MainDoorClosed" || PrevDoorStat == "LavatoryDoorClosed") {
          DoorStat = "MainDoorOpened";
          delay(1000);
        }
        else if (PrevDoorStat == "LavatoryDoorOpened") {
          DoorStat = "LavatoryDoorClosed";
          delay(1000);
        }
      }
      else if (OpMode == "SURVEILLANCEM") {
        client.publish("HacksterProjectTx", "INTRUSION ALERT");
      }
    }
    else if (pressure < pressureLM) {
      if (OpMode == "CABINM") {
        if (PrevDoorStat == "MainDoorClosed" || PrevDoorStat == "LavatoryDoorClosed") {
          DoorStat = "LavatoryDoorOpened";
          delay(1000);
        }
        else if (PrevDoorStat == "MainDoorOpened") {
          DoorStat = "MainDoorClosed";
          delay(1000);
        }
      }
      else if (OpMode == "SURVEILLANCEM") {
        client.publish("HacksterProjectTx", "INTRUSION ALERT");
      }
    }
  }
  if (DoorStat != "" && OpMode == "CABINM") {
    if ((PrevDoorStat == "LavatoryDoorClosed" || PrevDoorStat == "MainDoorClosed") && DoorStat == "LavatoryDoorOpened") {
      if (LavatoryStat == "LavatoryUnoccupied") {
        LavatoryStat = "SomeoneEnteringLavatory";
      }
      else if (LavatoryStat == "LavatoryOccupied") {
        LavatoryStat = "SomeoneExitingLavatory";
      }
    }
    else if (PrevDoorStat == "LavatoryDoorOpened" && DoorStat == "LavatoryDoorClosed") {
      if (LavatoryStat == "SomeoneExitingLavatory") {
        LavatoryStat = "LavatoryUnoccupied";
      }
      else if (LavatoryStat == "SomeoneEnteringLavatory") {
        LavatoryStat = "LavatoryOccupied";
      }
    }
    else if ((PrevDoorStat == "LavatoryDoorClosed" || PrevDoorStat == "MainDoorClosed") && DoorStat == "MainDoorOpened") {
      if (MainRoomStat == "MainRoomUnoccupied") {
        MainRoomStat = "SomeoneEnteringMainRoom";
      }
      else if (MainRoomStat == "MainRoomOccupied") {
        MainRoomStat = "SomeoneExitingMainRoom";
      }
    }
    else if (PrevDoorStat == "MainDoorOpened" && DoorStat == "MainDoorClosed") {
      if (MainRoomStat == "SomeoneExitingMainRoom") {
        MainRoomStat = "MainRoomUnoccupied";
      }
      else if (MainRoomStat == "SomeoneEnteringMainRoom") {
        MainRoomStat = "MainRoomOccupied";
      }
    }
    String S  = String(DoorStat) + " " + String(LavatoryStat) + " " + String(MainRoomStat);
    //Serial.println(S);
    /////////////////////////////Send your commands to turn on and turn off the Wi-Fi based devices or IR devices on the section below
    if (DoorStat == "MainDoorOpened" && MainRoomStat == "SomeoneEnteringMainRoom") {
      String S  = String(DoorStat) + " " + String(MainRoomStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      irsend.sendNEC(0x8F751AE, 32); // 3
    }
    else if (DoorStat == "MainDoorClosed" && MainRoomStat == "MainRoomOccupied") {
      String S  = String(DoorStat) + " " + String(MainRoomStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      irsend.sendRaw(ON, sizeof(ON) / sizeof(ON[0]), 38);  // Send a raw data at 38kHz.
    }
    else if (DoorStat == "MainDoorClosed" && MainRoomStat == "MainRoomUnoccupied") {
      String S  = String(DoorStat) + " " + String(MainRoomStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      client.publish("TSwtAin", String("LIGHTFANOFF").c_str());
      delay(1000);
      irsend.sendNEC(0x8F751AE, 32); // 3
    }
    else if (DoorStat == "LavatoryDoorOpened" && LavatoryStat == "SomeoneEnteringLavatory") {
      String S  = String(DoorStat) + " " + String(LavatoryStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      client.publish("SmartSwTin", String("LIGHTON").c_str());
    }
    else if (DoorStat == "LavatoryDoorClosed" && LavatoryStat == "LavatoryOccupied") {
      String S  = String(DoorStat) + " " + String(LavatoryStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      irsend.sendNEC(0x8F751AE, 32); // 3
    }
    else if (DoorStat == "LavatoryDoorClosed" && LavatoryStat == "LavatoryUnoccupied") {
      String S  = String(DoorStat) + " " + String(LavatoryStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      client.publish("SmartSwTin", String("LIGHTOFF").c_str());
    }
    else if (DoorStat == "LavatoryDoorOpened" && LavatoryStat == "SomeoneExitingLavatory") {
      String S  = String(DoorStat) + " " + String(LavatoryStat);
      Serial.println(S);
      client.publish("HacksterProjectTx", String(S).c_str());
      irsend.sendNEC(0x8F751AE, 32); // 3
    }
    PrevDoorStat = DoorStat;
    DoorStat = "";
  }
  ////////////////////////////////////////////////////////////////////////
  IF = analogRead(A0);
  //Serial.println(IF);
  if (IF > 980) {
    CatProx = CatProx + 1;
    if (CatProx == 3) {
      snprintf (msg, 75, "ProximitySwitch");
      Serial.println("ProximitySwitch");
      irsend.sendNEC(0x8F751AE, 32); // 3
      client.publish("HacksterProjectTx", msg);
      delay(3000);
    }
  }
  else {
    CatProx = 0;
  }
  ////////////////////////////////////////////////////////////////////////
}
void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(".");
  Serial.print(month());
  Serial.print(".");
  Serial.print(year());
  Serial.println();
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_profont22_mn);
    String K = "";
    char charBuf[20];
    K += day();
    K += "-";
    K += month();
    K += "-";
    K += year();;
    K.toCharArray(charBuf, 20);
    u8g2.drawStr(12, 20, charBuf);
    K = "";
    K += hour();
    K += ":";
    K += minute();
    K += ":";
    K += second();
    K.toCharArray(charBuf, 20);
    u8g2.drawStr(20, 52, charBuf);
  } while ( u8g2.nextPage() );
}

void printDigits(int digits)
{
  // utility for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  IPAddress ntpServerIP; // NTP server's ip address

  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  // get a random server from the pool
  WiFi.hostByName(ntpServerName, ntpServerIP);
  Serial.print(ntpServerName);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return (secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR) + 1800;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

Credits

Jayakarthigeyan Prabakar

Jayakarthigeyan Prabakar

3 projects • 16 followers
Rapid Prototyper | Product Developer | Systems Designer | IoT Specialist | Hardware Design Team Leader | Author | Web and App Developer
Thanks to Hariharan Prabhakar, Bhanu Chander, and Shivaranjani.

Comments