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,697

Things used in this project

Hardware components

DPS310XTSA1 Pressure Sensor
Infineon DPS310XTSA1 Pressure Sensor
×1
Infineon DAVE software developement
×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
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
3 projects • 17 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