Md. Khairul Alam
Published © Apache-2.0

Multi-Functional Magnetic Knob for Consumer Electronics

A magnetic rotary knob for consumer electronics and IoT products using Infineon 3D magnetic sensors.

AdvancedFull instructions provided15 hours1,413
Multi-Functional Magnetic Knob for Consumer Electronics

Things used in this project

Hardware components

3D Magnetic Sensor 2Go
Infineon 3D Magnetic Sensor 2Go
This sensor is required for the user interaction with the device. One sensor can be used for the different event like rotation, single press, double press, long press etc.
×1
NodeMCU ESP8266 Breakout Board
NodeMCU ESP8266 Breakout Board
The NodeMCU board is required to receive MQTT message sent from the device and to control AC appliances according to the received message.
×1
Wemos D1 Mini
Espressif Wemos D1 Mini
Wemos Di Mini is used as the main controller of the device. It is used to drive the tft display, receive sensor data, sent mqtt message, read time and weather update from the server.
×1
Adafruit 1.8" TFT Display Breakout
1.8 inch tft display is used to display time, weather update and state of the AC appliances.
×1
Relay Module (Generic)
Relay module is required to control AC appliances by NodeMCU board.
×1

Software apps and online services

Arduino IDE
Arduino IDE
All the sketch was developed in Arduino Environment.
Tinkercad
Autodesk Tinkercad
3D design was made on this web platform.

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

Complete Project

Box Top

This is the top part of the enclosure designed by Tinkercad.

Box Bottom

This is the bottom part of the enclosure.

Schematics

Eagle File

Pinout

Pinout of the Infineon Magnetic Sensor

Pinout WeMos D1 Mini

Pinout NodeMCU

Complete Schematics

Designed in Eagle

Code

Main-controller

Arduino
This sketch is for Wemos D1 Mini for driving display, receiving sensor data and sending MQTT message.
/*
 * The code is written for Multifunctional desk clock
 * Date: 23 August 2018
 * Md. Khairul Alam
 * Tested on Wemos D1 Mini
 * 
 */

#include <Adafruit_GFX.h>    // Core graphics library
#include <QDTech_8266.h>     // Hardware-specific tft library
#include <SPI.h>             // Required for tft library
#include <ESP8266WiFi.h>     // ESP8266 specific wifi library
#include <WiFiUdp.h>         // UDP library for NTP
#include <PubSubClient.h>    // This library is for implementing MQTT 


#define TFT_CS  15   // Chip select line for TFT display
#define TFT_DC   5   // Data/command line for TFT
#define TFT_RST  16  // Reset line for TFT (or connect to +5V)
#define BUFFPIXEL 20

// WiFi connection
const char ssid[] = "taifur&mafi";      // your wifi SSID
const char pass[] = "University";       //  Your WiFi password

// MQTT Configuration 
// You will get this info after creating a mqtt instance from www.cloudmqtt.com
const char* mqttServer = "m10.cloudmqtt.com";
const int mqttPort = 15373;
const char* mqttUser = "yataiehe";
const char* mqttPassword = "4ylvmEKxx2sR";


int hours_Offset_From_GMT = +6;  // Change it according to your location
const char tzone[] = "New York";

WiFiServer server(80);
WiFiClient espClient;

PubSubClient client(espClient);

// A UDP instance to let us send and receive packets over UDP
WiFiUDP udp;

unsigned int localPort = 2390;        // local port to listen for UDP packets

IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server

const int NTP_PACKET_SIZE = 48;       // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE];  //buffer to hold incoming and outgoing packets

//Unix time in seconds
unsigned long epoch = 0;
unsigned long LastNTP = 0;

int hour, hour1;
int minute;
int blink=0, PM=0;

int RequestedTime = 0;
int TimeCheckLoop = 0;

////////////////////////////////////////////////////
#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

// Option 2: must use the hardware SPI pins
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);


/**********variables for color***********************/
int BLACK = 100;
int BLUE = 200;
int WHITE = 0;
int RED = 336;
int GREEN = 264;
// custom color variable for menu
int button1 = 100, button2 = 264, button3 = 336, button4 = 500, button5 = 7500;

/**********variables for home screen***********************/
int x = 12;
int width = 105;
int height = 25;
int roundness = 10;
int offset = 30;
int count = 0;
int flag = 0;

// variables for analog clcok
//uint32_t targetTime = 0;                    // for next 1 second timeout
uint8_t hh, mm, ss;
float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;    // Saved H, M, S x & y multipliers
float sdeg=0, mdeg=0, hdeg=0;
uint16_t osx=64, osy=64, omx=64, omy=64, ohx=64, ohy=64;  // Saved H, M, S x & y coords
uint16_t x0=0, x1=0, yx = 0, yz = 0;
uint32_t targetTime = 0;    

// variable for buttons
int btnUP = 4;
int btnOK = 0;
int btnDOWN = 2;
int pressedTime = 0;

bool onOffFlag = 0;
int whichScreenFlag = 0;

// custom bitmap for on/off logo
static const uint8_t  PROGMEM onBitmap[] = {
0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x07, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x03, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x01, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x01, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x01, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x01, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x03, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x07,
0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x07, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const uint8_t  PROGMEM offBitmap[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x7f,
0xc0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xe0, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xe0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0xf8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7e,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x1f, 0x00,
0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x0f, 0xc0, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x01, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00
};


void setup(void) {
  Serial.begin(9600);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  tft.init();
  tft.setRotation(0);  // 0 - Portrait, 1 - Lanscape
  tft.fillScreen(WHITE);
  Serial.println("init");
  //button pins are define as input, internal pull up resistor are enabled
  pinMode(btnUP, INPUT_PULLUP);
  pinMode(btnOK, INPUT_PULLUP);
  pinMode(btnDOWN, INPUT_PULLUP);
  //connect to wifi
  ConnectToAP();
  //configure mqtt connection
  mqtt_config();
  //start udp communication
  udp.begin(localPort);
  //sent request to server for current time
  Request_Time();
  delay(2000);
  Check_Time();
  /*
  while (!Check_Time());
  {
    delay(2000);
    TimeCheckLoop++;
    if (TimeCheckLoop > 5)
    {
      Request_Time();
    }
  }
  */
  //update tft with default home screen with five menus
  updateHomeScreen();
  homeText();
  //this flag variable is used to detect active screen
  whichScreenFlag = 1; //1 means home screen
}

//callback function for mqtt data receive
//this function automatically invocked on mqtt message received
void callback(char* topic, byte* payload, unsigned int length) {
 
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
 
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
 
  Serial.println();
  Serial.println("-----------------------");
 
}

void loop (){
  client.loop(); //mqtt client
  if(digitalRead(btnUP)==0){
      // count variable set to max 5 for 5 menus
      count<=5?++count:count=0;
      // this delay is required to avoid multiple press or false trigger
      delay(1000);
    }
  if(digitalRead(btnDOWN)==0){
      count>=0?count--:count=5;
      delay(1000);
    }
  if(digitalRead(btnOK)==0){
      // this loop count how much time the button keep low
      // if it pass specific time, a long press is considered
      while(digitalRead(btnOK)==0){
        pressedTime++;
        if(pressedTime>110) break;
        delay(10);
        }
      //if time less than 100ms, a short press is considered
      if(pressedTime<100){
        shortPress();
        }
      else if(pressedTime>100){
        longPress();
        delay(2500);
        }
      pressedTime=0;
    }
  //up down arrow mark to select a menu
  //position updated automatically on button press   
  if(whichScreenFlag==1){
    noArrowMark();    
    arrowMark();
  }
  //this is the menu for home appliances control
  //same as home screen and arrow mark is required for selecting specific appliance
  if(whichScreenFlag==11){
    noArrowMark();    
    arrowMark();
  }
  //flag for internet clock
  if(whichScreenFlag==12){
    processTime();
    updateTime();
  }
}

void updateHomeScreen(){
  //draw menu option as home screen
  tft.drawRoundRect(x, 5, width, height, roundness, button1);
  tft.fillRoundRect(x, 5, width, height, roundness, button1);
  tft.drawRoundRect(x, 35, width, height, roundness, button2);
  tft.fillRoundRect(x, 35, width, height, roundness, button2);
  tft.drawRoundRect(x, 65, width, height, roundness, button3);
  tft.fillRoundRect(x, 65, width, height, roundness, button3);
  tft.drawRoundRect(x, 95, width, height, roundness, button4);
  tft.fillRoundRect(x, 95, width, height, roundness, button4);
  tft.drawRoundRect(x, 125, width, height, roundness, button5);
  tft.fillRoundRect(x, 125, width, height, roundness, button5);  
}

void automationScreen(){
  //menu option for home automation
  tft.drawRoundRect(x, 5, width, height, roundness, button3);
  tft.fillRoundRect(x, 5, width, height, roundness, button3);
  tft.drawRoundRect(x, 35, width, height, roundness, button4);
  tft.fillRoundRect(x, 35, width, height, roundness, button4);
  tft.drawRoundRect(x, 65, width, height, roundness, button1);
  tft.fillRoundRect(x, 65, width, height, roundness, button1);
  tft.drawRoundRect(x, 95, width, height, roundness, button2);
  tft.fillRoundRect(x, 95, width, height, roundness, button2);
  tft.drawRoundRect(x, 125, width, height, roundness, button5);
  tft.fillRoundRect(x, 125, width, height, roundness, button5);  
}

void homeText(){
  //show text on the menu option
  printText("Home Control", 50,25,13,1);
  printText("Internet Clock", 350,25,43,1);
  printText("Alarm Clock", 250,25,73,1);
  printText("Weather", 750,25,103,1);
  printText("Setting", 0,25,133,1);
}

void automationText(){
  printText("Bedroom Light", 50,25,13,1);
  printText("Bedroom Fan", 350,25,43,1);
  printText("Kitchen Light", 250,25,73,1);
  printText("Bathroom Light", 0,25,103,1);
  printText("Coffee Maker", 0,25,133,1);
}

void arrowMark(){
  //arrow position updated according to the count value
  //count value is updated on button press
  //means arrow position updated on button press
  tft.fillTriangle(0, 8+offset*count, 0, 24+offset*count, 12, 16+offset*count, 305);
}

void noArrowMark(){
  //erase previous arrow mark
  tft.fillTriangle(0, 8+offset*(count-1), 0, 24+offset*(count-1), 12, 16+offset*(count-1), 0);
  tft.fillTriangle(0, 8+offset*(count+1), 0, 24+offset*(count+1), 12, 16+offset*(count+1), 0);
}

void printText(char *text, uint16_t color, int x, int y,int textSize)
{
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextSize(textSize);
  tft.setTextWrap(true);
  tft.print(text);
}

void alarmScreen(){
  //this is for alarm screen
  tft.fillScreen (WHITE);
  printText("Set Alarm Time:", RED,20,20,1);

  printText("Set Alarm Date:", RED,20,65,1);

  tft.drawRoundRect(5, 120, 50, 30, roundness, button1);
  tft.fillRoundRect(5, 120, 50, 30, roundness, button1);
  tft.drawRoundRect(70, 120, 50, 30, roundness, button1);
  tft.fillRoundRect(70, 120, 50, 30, roundness, button1);
  printText("Set", GREEN,22,130,1);
  printText("Clear", GREEN,80,130,1);
  
  printText("07:25 AM", BLACK,17,35,2);
  printText("15/08/18", BLACK,17,80,2);
}

void ConnectToAP()
{
  // Serial.print("Connecting to wifi... ");
   WiFi.begin(ssid, pass);
   while (WiFi.status() != WL_CONNECTED) {
    delay(300);
   }
}

void DecodeEpoch(unsigned long currentTime)
{
  // print the hour, minute and second:
  //Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
  //Serial.println(epoch);
  //Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
  // Serial.print(':');
  if ( ((epoch % 3600) / 60) < 10 ) {
    // In the first 10 minutes of each hour, we'll want a leading '0'
    //  Serial.print('0');
  }
  // Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
  //  Serial.print(':');
  if ( (epoch % 60) < 10 ) {
    // In the first 10 seconds of each minute, we'll want a leading '0'
  //  Serial.print('0');
  }
  //Serial.println(epoch % 60); // print the second

  //Update for local zone
  currentTime = currentTime + (hours_Offset_From_GMT * 60 * 60);
  //Serial.print("The current local time is ");
  //Serial.print((currentTime  % 86400L) / 3600); // print the hour (86400 equals secs per day)
  //Serial.print(':');
  if ( ((currentTime % 3600) / 60) < 10 ) {
    // In the first 10 minutes of each hour, we'll want a leading '0'
    //   Serial.print('0');
  }
  // Serial.print((currentTime  % 3600) / 60); // print the minute (3600 equals secs per minute)
  // Serial.print(':');
  if ( (currentTime % 60) < 10 ) {
    // In the first 10 seconds of each minute, we'll want a leading '0'
    //  Serial.print('0');
  }
  //Serial.println(currentTime % 60); // print the second

  hour = (currentTime  % 86400L) / 3600;
  hh=hour;
  if(hour >= 12) {
    hour = hour-12;
    PM=1;
  }
  else {
    PM=0;
  }
  if(hour == 0) hour = 12;
  
  minute = (currentTime % 3600) / 60;
  mm=minute;
  ss=currentTime % 60;
    
}

void Request_Time()
{
 // Serial.println("Getting Time");
  sendNTPpacket(timeServer); // send an NTP packet to a time server
}

bool Check_Time()
{
  int cb = udp.parsePacket();
  if (!cb) {
   // Serial.println("no packet yet");
    return false;
  }
  else {
   // Serial.print("packet received, length=");
   // Serial.println(cb);
    // We've received a packet, read the data from it
    udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, extract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    //Serial.print("Seconds since Jan 1 1900 = " );
    // Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    //Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    epoch = secsSince1900 - seventyYears;
    LastNTP = millis();
    RequestedTime = 0;
    TimeCheckLoop = 0;
    return true;
  }
}

// send an NTP request to the time server at the given address
unsigned long sendNTPpacket(IPAddress & address)
{
 // Serial.println("sending NTP packet...");
  // 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();
}

void processTime(){
  int SecondsSinceLastNTP = (millis() - LastNTP) / 1000;
  //Update NTP every 2 minutes
  if (SecondsSinceLastNTP > 120 and RequestedTime == 0) {
    Request_Time();
    RequestedTime = 1;
  }

  if (RequestedTime == 1)
  {
    Check_Time();
    TimeCheckLoop++;
    if (TimeCheckLoop > 5)
    {
      RequestedTime = 0;
    }
  }

 //Only Check_Time() should update epoch
  DecodeEpoch(epoch + SecondsSinceLastNTP); 
    if (ss==60) {
      ss=0;
      mm++;            // Advance minute
      if(mm>59) {
        mm=0;
        hh++;          // Advance hour
        if (hh>23) {
          hh=0;
        }
      }
    }
 delay(1000);
 ss++;   
  
}

void updateTime(){
  //dt = clock.getDateTime();
  //mm = dt.minute;
  //ss = dt.second;
  //hh = dt.hour;
  if (targetTime < millis()) {
    targetTime = millis()+1000;    
    // Pre-compute hand degrees, x & y coords for a fast screen update
    sdeg = ss*6;                  // 0-59 -> 0-354
    mdeg = mm*6+sdeg*0.01666667;  // 0-59 -> 0-360 - includes seconds
    hdeg = hh*30+mdeg*0.0833333;  // 0-11 -> 0-360 - includes minutes and seconds
    hx = cos((hdeg-90)*0.0174532925);    hy = sin((hdeg-90)*0.0174532925);
    mx = cos((mdeg-90)*0.0174532925);    my = sin((mdeg-90)*0.0174532925);
    sx = cos((sdeg-90)*0.0174532925);    sy = sin((sdeg-90)*0.0174532925);

    // Erase just old hand positions
    tft.drawLine(ohx, ohy, 65, 65, BLACK);  
    tft.drawLine(omx, omy, 65, 65, BLACK);  
    tft.drawLine(osx, osy, 65, 65, BLACK);
    // Draw new hand positions  
    tft.drawLine(hx*33+65, hy*33+65, 65, 65, WHITE);
    tft.drawLine(mx*44+65, my*44+65, 65, 65, WHITE);
    tft.drawLine(sx*47+65, sy*47+65, 65, 65, RED);
    tft.fillCircle(65, 65, 3, RED);

    // Update old x&y coords
    osx = sx*47+65;    osy = sy*47+65;
    omx = mx*44+65;    omy = my*44+65;
    ohx = hx*33+65;    ohy = hy*33+65;
    
    watchMark();

    tft.drawRoundRect(0, 130, 128, 30, 1, WHITE);
    tft.fillRoundRect(0, 130, 128, 30, 1, WHITE);  
    // Update  AM/PM
    tft.drawCircle(63, 90, 9, GREEN); 
    if(PM==1)
      printText("PM", 50,58,87,1);
    else 
      printText("AM", 50,58,87,1);
    //Update digital time  
    tft.setCursor (15, 138);
    tft.setTextSize(2);
    if(hh>12) {
      if (hh<22) tft.print('0');      
      tft.print (hh-12);
    } else {
      if (hh<10) tft.print('0');
      tft.print (hh);
    }
    tft.print (':');
    if (mm<10) tft.print('0');
    tft.print (mm);
    tft.print (':');
    if (ss<10) tft.print('0');
    tft.print (ss);
    if (hh>12) ;//tft.print("PM"); else tft.print ("AM");
  }
  
}

//show 12, 3, 6, 9 on dial
void watchMark(){
  printText("3", 50,108,60,1);
  printText("9", 50,16,60,1);
  printText("12", 50,58,18,1);
  printText("6", 50,61,105,1);
}

void clockFace(){   //
  tft.fillScreen (WHITE);
    // Draw clock face
  tft.fillCircle(64, 64, 61, BLUE);
  tft.fillCircle(64, 64, 57, BLACK);

  // Draw 12 lines
  for(int i = 0; i<360; i+= 30) {
    sx = cos((i-90)*0.0174532925);
    sy = sin((i-90)*0.0174532925);
    x0 = sx*57+64;
    yx = sy*57+64;
    x1 = sx*50+64;
    yz = sy*50+64;
    
    tft.drawLine(x0, yx, x1, yz, BLUE);
    
  }
  tft.fillCircle(65, 65, 3, RED);
  tft.setCursor (34, 151);
  tft.print(__DATE__);
  targetTime = millis() + 1000; 
  flag = 0;
}

void shortPress(){
    //whichScreenFlag helps to determine the current screen and count value helps
    //to determine the selected nemu
    if(whichScreenFlag==1 && count==0){
      whichScreenFlag = 11;
      }
    else if(whichScreenFlag==1 && count==1){
      whichScreenFlag = 12;
      }
    else if(whichScreenFlag==1 && count==2){
      whichScreenFlag = 13;
      }
    else if(whichScreenFlag==1 && count==3){
      whichScreenFlag = 14;
      }
    else if(whichScreenFlag==1 && count==4){
      whichScreenFlag = 15;
      }
    else if(whichScreenFlag==11 && count==0){
      whichScreenFlag = 111;
      }
    else if(whichScreenFlag==11 && count==1){
      whichScreenFlag = 112;
      }
    else if(whichScreenFlag==11 && count==2){
      whichScreenFlag = 113;
      }
    else if(whichScreenFlag==11 && count==3){
      whichScreenFlag = 114;
      }
    else if(whichScreenFlag==11 && count==4){
      whichScreenFlag = 115;
      }
    else if(whichScreenFlag==111){
      if(onOffFlag==0){
        whichScreenFlag = 1110;
        
        }
      else if(onOffFlag==1){
        whichScreenFlag = 1111;
        
        }
      }
    else if(whichScreenFlag==112){
      if(onOffFlag==0){
        whichScreenFlag = 1120;
        
        }
      else if(onOffFlag==1){
        whichScreenFlag = 1121;
        
        }
      }
    else if(whichScreenFlag==113){
      if(onOffFlag==0){
        whichScreenFlag = 1130;
        
        }
      else if(onOffFlag==1){
        whichScreenFlag = 1131;
        
        }
      }
    else if(whichScreenFlag==114){
      if(onOffFlag==0){
        whichScreenFlag = 1140;
        
        }
      else if(onOffFlag==1){
        whichScreenFlag = 1141;
        
        }
      }
    else if(whichScreenFlag==115){
      if(onOffFlag==0){
        whichScreenFlag = 1150;
        
        }
      else if(onOffFlag==1){
        whichScreenFlag = 1151;
        
        }
      }
    if(whichScreenFlag==1110){
      whichScreenFlag=1111;
      //this flag helps to determine the current state of the device
      onOffFlag=1;
      //sent an MQTT message to the topic 
      client.publish("esp/test", "load1on");
      delay(200);
      }
    else if(whichScreenFlag==1111){
      whichScreenFlag=1110;
      onOffFlag=0;
      client.publish("esp/test", "load1off");
      delay(200);
      }
    if(whichScreenFlag==1120){
      whichScreenFlag=1121;
      onOffFlag=1;
      client.publish("esp/test", "load2on");
      delay(200);
      }
    else if(whichScreenFlag==1121){
      whichScreenFlag=1120;
      onOffFlag=0;
      client.publish("esp/test", "load2off");
      delay(200);
      }
    if(whichScreenFlag==1130){
      whichScreenFlag=1131;
      onOffFlag=1;
      client.publish("esp/test", "load3on");
      delay(200);
      }
    else if(whichScreenFlag==1131){
      whichScreenFlag=1130;
      onOffFlag=0;
      client.publish("esp/test", "load3off");
      delay(200);
      }
    if(whichScreenFlag==1140){
      whichScreenFlag=1141;
      onOffFlag=1;
      client.publish("esp/test", "load4on");
      delay(200);
      }
    else if(whichScreenFlag==1141){
      whichScreenFlag=1140;
      onOffFlag=0;
      client.publish("esp/test", "load4off");
      delay(200);
      }
    if(whichScreenFlag==1150){
      whichScreenFlag=1151;
      client.publish("esp/test", "load5on");
      delay(200);
      }
    else if(whichScreenFlag==1151){
      whichScreenFlag=1150;
      client.publish("esp/test", "load5off");
      delay(200);
      }
    
    Serial.println(whichScreenFlag);
    setScreen();
 }

void longPress(){
  //for long press it goes back to previous option
  if(whichScreenFlag==11||whichScreenFlag==12||whichScreenFlag==13||whichScreenFlag==14||whichScreenFlag==15){
    whichScreenFlag = 1;
    }
  else if(whichScreenFlag==111||whichScreenFlag==112||whichScreenFlag==113||whichScreenFlag==114||whichScreenFlag==115 || whichScreenFlag>115){
    whichScreenFlag = 11;
    }
  setScreen();
}

void onScreen(){
  //show the on status of the load
  tft.fillScreen(WHITE);
  tft.setTextSize(2);
  tft.setTextColor(GREEN);
  tft.setCursor(30, 20);
  tft.setTextWrap(true);
  tft.print("Status");
  tft.drawBitmap(4, 60, offBitmap, 120, 58, WHITE);
  tft.setCursor(10, 79);
  tft.setTextColor(WHITE);
  tft.setTextSize(3);
  tft.setTextWrap(true);
  tft.print("OFF");
  tft.drawBitmap(4, 60, onBitmap, 120, 58, RED);
  tft.setCursor(78, 78);
  tft.setTextColor(RED);
  tft.setTextSize(3);
  tft.setTextWrap(true);
  tft.print("ON");
}

void offScreen(){
  tft.fillScreen(WHITE);
  tft.setTextSize(2);
  tft.setTextColor(GREEN);
  tft.setCursor(30, 20);
  tft.setTextWrap(true);
  tft.print("Status");
  tft.drawBitmap(4, 60, onBitmap, 120, 58, WHITE);
  tft.setCursor(78, 78);
  tft.setTextColor(WHITE);
  tft.setTextSize(3);
  tft.setTextWrap(true);
  tft.print("ON");
  tft.drawBitmap(4, 60, offBitmap, 120, 58, RED);
  tft.setCursor(10, 79);
  tft.setTextColor(RED);
  tft.setTextSize(3);
  tft.setTextWrap(true);
  tft.print("OFF");
}

void setScreen(){
  //according to the flag appropriate screen shows on tft
  if(whichScreenFlag == 1){
    tft.fillScreen(WHITE);
    updateHomeScreen();
    homeText();
    }
  else if(whichScreenFlag == 11){
    tft.fillScreen(WHITE);
    automationScreen();
    automationText();
    }
  else if(whichScreenFlag == 12){
    tft.fillScreen(WHITE);
    clockFace();
    watchMark();
    }
  else if(whichScreenFlag == 13){
    tft.fillScreen(WHITE);
    alarmScreen();
    }
  else if(whichScreenFlag == 14){
    //tft.fillScreen(WHITE);
    //weatherScreen();
    }
  else if(whichScreenFlag == 15){
    //tft.fillScreen(WHITE);
    //settingScreen();
    }
  else if(whichScreenFlag == 111){
    tft.fillScreen(WHITE);
    if(whichScreenFlag == 1110)
      offScreen();
    else if(whichScreenFlag == 1111)
      onScreen();
    }
  else if(whichScreenFlag == 112){
    tft.fillScreen(WHITE);
    if(whichScreenFlag == 1120)
      offScreen();
    else if(whichScreenFlag == 1121)
      onScreen();
    }
  else if(whichScreenFlag == 113){
    tft.fillScreen(WHITE);
    if(whichScreenFlag == 1130)
      offScreen();
    else if(whichScreenFlag == 1131)
      onScreen();
    }
  else if(whichScreenFlag == 114){
    tft.fillScreen(WHITE);
    if(whichScreenFlag == 1140)
      offScreen();
    else if(whichScreenFlag == 1141)
      onScreen();
    }
  else if(whichScreenFlag == 1110 || whichScreenFlag == 1120 || whichScreenFlag == 1130 || whichScreenFlag == 1140 || whichScreenFlag == 1150){
    tft.fillScreen(WHITE);
    onScreen();
    }
  else if(whichScreenFlag == 1111 || whichScreenFlag == 1121 || whichScreenFlag == 1131 || whichScreenFlag == 1141 || whichScreenFlag == 1151){
    tft.fillScreen(WHITE);
    offScreen();
    }
}

void mqtt_config(){
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
 
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
 
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
 
      Serial.println("connected");  
 
    } else {
 
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
 
    }
  }
 
  client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
}

3D magnetic sensors

Arduino
This sketch is for the magnetic sensor
/*
 * Md. Khairul Alam
 * Date: 24 August 2018
 * Modified from example code provided with library
 * Download library from https://github.com/Infineon/TLE493D-3DMagnetic-Sensor
 */
#include <Tle493d.h>

Tle493d Tle493dMagnetic3DSensor = Tle493d();

float azimuthValue = 0;
int xValue = 0;
int previousValue = 0;
int currentValue = 0;
int previousXValue = 0;
int currentXValue = 0;

long counter;
int counterValue;
long previousTime = millis();
long pressTime = millis();
int pressCount = 0;

const int switchUP = 5;
const int switchDOWN = 3;
const int switchOK = 4;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Tle493dMagnetic3DSensor.begin();
  pinMode(switchUP, OUTPUT);
  pinMode(switchDOWN, OUTPUT);
  pinMode(switchOK, OUTPUT);
  digitalWrite(switchUP, LOW);
  digitalWrite(switchDOWN, LOW);
  digitalWrite(switchOK, LOW);
}

void loop() {
  Tle493dMagnetic3DSensor.updateData();
  //Serial.println(Tle493dMagnetic3DSensor.getAzimuth());
  //the actual value may be less than 1 (one)
  //so the value is multiplied by 100 to make it grater than 1
  //than the value is converted to int to use in if statement
  azimuthValue = Tle493dMagnetic3DSensor.getAzimuth() * 100;
  xValue = int(Tle493dMagnetic3DSensor.getX());
  xValue = abs(xValue);
  currentXValue = xValue;
  //Serial.println(xValue);
  delay(10);
  int currentValue = int(azimuthValue);
  //the aximuth value increase on counter clockwise rotation
  if((currentValue-previousValue)>=20){
    //make it high for 200ms to generate button press
    digitalWrite(switchUP, HIGH);
    delay(200);
    digitalWrite(switchUP, LOW);
    //delay(1000);
    Serial.println("CCW\n");
  }
  //the aximuth value decrease on clockwise rotation
  else if((currentValue-previousValue)<=-20){
    digitalWrite(switchDOWN, HIGH);
    delay(200);
    digitalWrite(switchDOWN, LOW);
    //delay(1000);
    Serial.println("CW\n");    
  }
  if((currentXValue - previousXValue)>15){
    pressTime = millis();
    pressCount++;
    }
  if((millis()-pressTime)>600){
      if(pressCount==1){
        digitalWrite(switchOK, HIGH);
        delay(100);
        digitalWrite(switchOK, LOW);
        //delay(1000);
        Serial.println("Short Press\n");        
        }
      else if(pressCount==2){
        //keep it high for enough time to detect long press from other side (wemos mini)
        digitalWrite(switchOK, HIGH);
        delay(2000);
        digitalWrite(switchOK, LOW);
        //delay(1000);
        Serial.println("Double Press\n");        
        }
      pressCount=0;
      pressTime = millis();
      } 
  /*
  //can be implimented as double press if required
  counter = millis();
  counterValue = currentXValue;
   
  if((currentXValue - counterValue)>-20){
    if((millis() - counter)>1000){
      if((millis() - previousTime)>7000){
      Serial.println("Long Press\n");
      previousTime = millis();
        }
      }
    }
  counterValue = 100;
  */
  previousValue = currentValue;
  previousXValue = currentXValue;
  delay(100); 
}

MQTT-Receiver

Arduino
Code for NodeMCU connected to the load
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
 
const char* ssid = "taifur&mafi";
const char* password =  "University";
const char* mqttServer = "m10.cloudmqtt.com";
const int mqttPort = 15373;
const char* mqttUser = "yataiehe";
const char* mqttPassword = "4ylvmEKxx2sR";

String msg = "";

int load1 = 14;
int load2 = 12;
int load3 = 13;

const int off = 0;
const int on = 1;
 
WiFiClient espClient;
PubSubClient client(espClient);
 
void setup() {
 
  Serial.begin(115200);

  pinMode(load1, OUTPUT);
  pinMode(load2, OUTPUT);
  pinMode(load3, OUTPUT);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
 
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
 
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
 
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
 
      Serial.println("connected");  
 
    } else {
 
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
 
    }
  }
 
  //client.publish("esp/test", "Hello from ESP8266");
  client.subscribe("esp/test");
 
}
 
void callback(char* topic, byte* payload, unsigned int length) {
 
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
 
  //Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    msg += (char)payload[i];
  }
  Serial.print("Msg = ");
  Serial.println(msg);
  //Serial.println("-----------------------");
  if(msg=="load1off"){
    Serial.println("Load 1 is off");
    digitalWrite(load1, off);
    }
  if(msg=="load1on"){
    Serial.println("Load 1 is on");
    digitalWrite(load1, on);
    }
  if(msg=="load2off"){
    Serial.println("Load 2 is off");
    digitalWrite(load2, off);
    }
  if(msg=="load2on"){
    Serial.println("Load 2 is on");
    digitalWrite(load2, on);
    }
  if(msg=="load3off"){
    Serial.println("Load 3 is off");
    digitalWrite(load3, off);
    }
  if(msg=="load3on"){
    Serial.println("Load 3 is on");
    digitalWrite(load3, on);
    }
  msg = "";
  delay(200);
}
 
void loop() {
  client.loop();
}

Credits

Md. Khairul Alam

Md. Khairul Alam

64 projects • 569 followers
Developer, Maker & Hardware Hacker. Currently working as a faculty at the University of Asia Pacific, Dhaka, Bangladesh.

Comments