#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <math.h>
// ESP32 and ILI9341 pins
#define TFT_CS 15
#define TFT_DC 2
#define TFT_MOSI 13
#define TFT_MISO 12
#define TFT_SCK 14
#define LED_R 4
#define LED_G 16
#define LED_B 17
struct ClockTime {
int h, m, s;
int day, month, year;
};
Adafruit_ILI9341 tft(TFT_CS, TFT_DC);
const int SW = 240;
const int SH = 320;
unsigned long startMillis = 0;
unsigned long lastDraw = 0;
const char* months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
void setRGB(bool r, bool g, bool b) {
digitalWrite(LED_R, r ? LOW : HIGH);
digitalWrite(LED_G, g ? LOW : HIGH);
digitalWrite(LED_B, b ? LOW : HIGH);
}
bool leapYear(int y) {
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
int monthDays(int m, int y) {
const int d[] = {
31,28,31,30,31,30,31,31,30,31,30,31
};
if (m == 2 && leapYear(y)) return 29;
return d[m - 1];
}
ClockTime getTimeNow() {
unsigned long total =
(millis() - startMillis) / 1000UL
+ 10UL * 3600UL + 10UL * 60UL;
ClockTime c;
c.s = total % 60;
c.m = (total / 60) % 60;
c.h = (total / 3600) % 24;
unsigned long days = total / 86400UL;
c.day = 26;
c.month = 10;
c.year = 2026;
while (days > 0) {
int remain = monthDays(c.month, c.year) - c.day + 1;
if (days < (unsigned long)remain) {
c.day += days;
days = 0;
} else {
days -= remain;
c.day = 1;
c.month++;
if (c.month > 12) {
c.month = 1;
c.year++;
}
}
}
return c;
}
void print2(int n) {
if (n < 10) tft.print('0');
tft.print(n);
}
void header(const char* title, uint16_t color) {
tft.fillScreen(ILI9341_BLACK);
tft.fillRect(0, 0, SW, 36, 0x18C3);
tft.setTextColor(color);
tft.setTextSize(2);
tft.setCursor(8, 10);
tft.print(title);
}
void footer() {
tft.drawFastHLine(10, 291, 220, 0x7BEF);
tft.setTextColor(ILI9341_YELLOW);
tft.setTextSize(2);
tft.setCursor(43, 300);
tft.print("ARVIND PATIL");
}
void drawHand(int cx, int cy, float angle, int len,
uint16_t color, int width) {
float rad = angle * PI / 180.0;
int x = cx + (int)(sin(rad) * len);
int y = cy - (int)(cos(rad) * len);
for (int i = -width / 2; i <= width / 2; i++) {
tft.drawLine(cx + i, cy, x + i, y, color);
}
}
void analogClock(ClockTime c) {
header("ANALOG CLOCK", ILI9341_CYAN);
int cx = 120, cy = 157, r = 91;
tft.drawCircle(cx, cy, r, ILI9341_WHITE);
tft.drawCircle(cx, cy, r - 2, ILI9341_CYAN);
for (int i = 0; i < 60; i++) {
float a = i * 6.0 * PI / 180.0;
int inner = (i % 5 == 0) ? r - 12 : r - 5;
tft.drawLine(
cx + sin(a) * inner,
cy - cos(a) * inner,
cx + sin(a) * (r - 3),
cy - cos(a) * (r - 3),
(i % 5 == 0) ? ILI9341_YELLOW : 0x7BEF
);
}
tft.setTextSize(1);
tft.setTextColor(ILI9341_WHITE);
for (int i = 1; i <= 12; i++) {
float a = i * 30.0 * PI / 180.0;
int x = cx + sin(a) * (r - 23);
int y = cy - cos(a) * (r - 23);
tft.setCursor(x - 3, y - 3);
tft.print(i);
}
drawHand(cx, cy, (c.h % 12) * 30.0 + c.m * 0.5,
48, ILI9341_YELLOW, 5);
drawHand(cx, cy, c.m * 6.0 + c.s * 0.1,
67, ILI9341_GREEN, 3);
drawHand(cx, cy, c.s * 6.0,
78, ILI9341_RED, 1);
tft.fillCircle(cx, cy, 4, ILI9341_WHITE);
tft.setTextSize(2);
tft.setTextColor(ILI9341_CYAN);
tft.setCursor(62, 264);
print2(c.h); tft.print(':');
print2(c.m); tft.print(':');
print2(c.s);
footer();
}
void digitalClock(ClockTime c) {
header("DIGITAL CLOCK", ILI9341_GREEN);
tft.setTextColor(ILI9341_CYAN);
tft.setTextSize(3);
tft.setCursor(25, 86);
print2(c.h); tft.print(':');
print2(c.m);
tft.setTextColor(ILI9341_YELLOW);
tft.setTextSize(2);
tft.setCursor(73, 132);
print2(c.s); tft.print(" SEC");
tft.drawRoundRect(15, 175, 210, 55, 8, ILI9341_GREEN);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(28, 194);
print2(c.day);
tft.print(' ');
tft.print(months[c.month - 1]);
tft.print(' ');
tft.print(c.year);
tft.setTextSize(1);
tft.setTextColor(ILI9341_MAGENTA);
tft.setCursor(51, 252);
tft.print("ESP32 VIRTUAL IoT");
footer();
}
void sensorDashboard(ClockTime c) {
header("IoT ENVIRONMENT", ILI9341_YELLOW);
// Simulated sensor readings
float temp = 28.0 + 2.0 * sin(millis() / 5000.0);
float hum = 55.0 + 10.0 * sin(millis() / 7000.0);
tft.fillRoundRect(12, 51, 216, 88, 9, 0x2104);
tft.setTextColor(ILI9341_ORANGE);
tft.setTextSize(2);
tft.setCursor(24, 62);
tft.print("TEMPERATURE");
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.setCursor(35, 96);
tft.print(temp, 1);
tft.print(" C");
tft.fillRoundRect(12, 148, 216, 88, 9, 0x2104);
tft.setTextColor(ILI9341_CYAN);
tft.setTextSize(2);
tft.setCursor(24, 159);
tft.print("HUMIDITY");
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.setCursor(49, 193);
tft.print(hum, 1);
tft.print("%");
tft.setTextColor(ILI9341_GREEN);
tft.setTextSize(1);
tft.setCursor(20, 249);
print2(c.h); tft.print(':');
print2(c.m); tft.print(':');
print2(c.s); tft.print(" ");
print2(c.day); tft.print('/');
print2(c.month); tft.print('/');
tft.print(c.year);
footer();
}
void setup() {
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
setRGB(false, false, false);
SPI.begin(TFT_SCK, TFT_MISO, TFT_MOSI, TFT_CS);
tft.begin();
tft.setRotation(0);
startMillis = millis();
}
void loop() {
unsigned long phase = millis() % 25000UL;
if (millis() - lastDraw >= 1000UL) {
lastDraw = millis();
ClockTime c = getTimeNow();
if (phase < 10000UL) {
setRGB(false, true, true);
analogClock(c);
} else if (phase < 20000UL) {
setRGB(true, false, true);
digitalClock(c);
} else {
setRGB(true, true, false);
sensorDashboard(c);
}
}
}
Loading
esp32-2432s028r
esp32-2432s028r
https://wokwi.com/projects/478915170158239745