An ESP32 home dashboard with a TFT display showing live weather data is one of the most visually impressive smart home projects you can build. Imagine a wall-mounted screen next to your front door showing the current time, indoor temperature, outdoor weather forecast, and your home’s automation status — all from a single compact ESP32 and TFT display costing under Rs 800. This guide walks you through building a complete home dashboard using an ESP32 with a colour TFT screen, fetching real-time weather data for your Indian city.
Table of Contents
- Hardware Selection
- Required Libraries
- Weather API Setup for India
- Dashboard Layout Design
- Complete Code
- Connecting to Home Assistant
- Enclosure and Mounting
- Frequently Asked Questions
Hardware Selection
The best TFT displays for an ESP32 home dashboard are:
- 2.4 inch ILI9341 (240×320): Most popular choice. Good for wall-mounted info panels. Available for Rs 200-350.
- 3.5 inch ILI9488 (320×480): Larger, better readability from a distance. Rs 400-600.
- 2.8 inch ILI9341 with touch: Touch interface for interactive dashboard. Rs 300-450.
The 2.4 inch ILI9341 is the sweet spot for a bedside or hallway dashboard. Pair it with an ESP32-S3 for the best performance.
Required Libraries
Install these via the Arduino Library Manager or PlatformIO:
TFT_eSPI— Optimised TFT driver with ESP32 hardware SPI supportArduinoJson— JSON parsing for weather API responsesNTPClient— Network time protocol for accurate clock displayHTTPClient— HTTP requests to weather APIWiFiClientSecure— HTTPS support for API calls
Weather API Setup for India
OpenWeatherMap provides free weather data for all Indian cities. Sign up for a free API key at openweathermap.org. The free tier allows 1000 calls/day.
Indian City IDs for Common Cities
// Mumbai: 1275339
// Delhi: 1273294
// Bengaluru: 1277333
// Chennai: 1264527
// Hyderabad: 1269843
// Pune: 1259229
// Ahmedabad: 1279233
// Kolkata: 1275004
// Jaipur: 1269515
// Surat: 1255364
const String city_id = "1275339"; // Mumbai
const String api_key = "YOUR_API_KEY";
String url = "http://api.openweathermap.org/data/2.5/weather?id=" +
city_id + "&appid=" + api_key + "&units=metric";
Dashboard Layout Design
A practical 240×320 TFT dashboard layout for Indian homes:
---------------------------------
| MON 11 MAR 12:34:56 |
| Indian Standard Time |
|---------------------------------|
| MUMBAI WEATHER |
| [ICON] 32 C |
| Partly Cloudy |
| Humidity: 78% |
|---------------------------------|
| INDOOR |
| Temp: 29.4 C Humidity: 62% |
|---------------------------------|
| [Light ON] [AC OFF] [Fan ON] |
| Door: Closed Motion: Clear |
---------------------------------
Complete Code
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <TFT_eSPI.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Configuration
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASS";
const String cityId = "1275339"; // Change to your city
const String apiKey = "YOUR_OWM_KEY";
TFT_eSPI tft = TFT_eSPI();
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800); // IST = UTC+5:30
struct WeatherData {
float temp;
int humidity;
String description;
String icon;
};
WeatherData fetchWeather() {
WeatherData data;
HTTPClient http;
String url = "http://api.openweathermap.org/data/2.5/weather?id=" +
cityId + "&appid=" + apiKey + "&units=metric";
http.begin(url);
if (http.GET() == 200) {
StaticJsonDocument<1024> doc;
deserializeJson(doc, http.getString());
data.temp = doc["main"]["temp"];
data.humidity = doc["main"]["humidity"];
data.description = doc["weather"][0]["description"].as<String>();
}
http.end();
return data;
}
void drawDashboard(WeatherData weather) {
tft.fillScreen(TFT_BLACK);
// Header - Time
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
String timeStr = timeClient.getFormattedTime();
tft.drawString(timeStr, 120, 20, 2); // Center
// Weather section
tft.setTextColor(TFT_ORANGE);
tft.drawString("WEATHER", 10, 60, 2);
tft.setTextColor(TFT_WHITE);
tft.drawString(String(weather.temp, 1) + "C", 100, 90, 4);
tft.drawString(weather.description, 10, 130, 1);
tft.drawString("Humidity: " + String(weather.humidity) + "%", 10, 150, 1);
// Indoor section placeholder
tft.setTextColor(TFT_GREEN);
tft.drawString("INDOOR", 10, 190, 2);
// Add DHT22 readings here
}
void setup() {
tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_BLACK);
tft.drawString("Connecting...", 10, 10, 2);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
timeClient.begin();
}
void loop() {
timeClient.update();
static unsigned long lastWeatherFetch = 0;
WeatherData weather;
if (millis() - lastWeatherFetch > 300000) { // Every 5 minutes
weather = fetchWeather();
lastWeatherFetch = millis();
}
drawDashboard(weather);
delay(1000); // Update every second for clock
}
Connecting to Home Assistant
Extend the dashboard to show live Home Assistant entity states via MQTT or HTTP API:
// Fetch HA entity state
String getHAState(String entity_id) {
WiFiClientSecure client;
client.setInsecure();
HTTPClient https;
String url = "https://192.168.30.100:8123/api/states/" + entity_id;
https.begin(client, url);
https.addHeader("Authorization", "Bearer YOUR_HA_TOKEN");
https.addHeader("Content-Type", "application/json");
if (https.GET() == 200) {
StaticJsonDocument<512> doc;
deserializeJson(doc, https.getString());
return doc["state"].as<String>();
}
return "unknown";
}
// Display in drawDashboard:
String lightState = getHAState("light.living_room");
tft.setTextColor(lightState == "on" ? TFT_YELLOW : TFT_DARKGREY);
tft.drawString("LIGHT", 10, 250, 2);
Enclosure and Mounting
A 3D-printed wall-mount frame is the cleanest option for Indian homes. Alternative approaches:
- Repurpose an old photo frame (10x15cm size fits a 2.4 inch TFT with Wemos D1 Mini)
- Use a small Tupperware container with a cutout for the display
- 3D print a flush-mount frame that sits behind a switch plate hole
Mount near the main entrance or in the kitchen. Power via a 5V USB charger tucked behind the wall plate. Run the cable through the false ceiling or along a cable duct for a clean finish.
Frequently Asked Questions
Which TFT library works best with ESP32 and ILI9341?
TFT_eSPI by Bodmer is the definitive choice for ESP32 TFT projects. It uses hardware SPI acceleration, supports sprites for flicker-free animation, and includes a comprehensive font library. Configure the User_Setup.h file to match your display’s pinout before compiling.
How accurate is OpenWeatherMap for Indian cities?
OpenWeatherMap uses IMD (India Meteorological Department) data and global weather models. Accuracy is good for major cities (Mumbai, Delhi, Bengaluru) and acceptable for smaller cities. For monsoon predictions, the data is particularly useful as it shows hourly rainfall probability — helping you decide whether to carry an umbrella.
Can I display Indian languages on the TFT?
Hindi and other Indian scripts require custom fonts. TFT_eSPI supports custom VLW fonts generated from any TTF file using the Processing IDE font converter. Generate a Devanagari (Hindi) font at 16-24pt and include it as a binary array in your sketch for native Hindi text display.
How do I prevent screen burn-in on the TFT?
Implement a screen dimmer using PWM on the TFT backlight pin. Dim the display after 5 minutes of no interaction (use a PIR sensor to detect presence). Go completely dark between midnight and 6 AM. This extends TFT lifespan significantly for always-on dashboard applications.
Add comment