Build a Mini Earth That Shows You the Weather Anywhere!
Meet Terra — a mini spinning Earth globe. Touch a continent, and Terra spins to face it while an ESP32 downloads that region's live temperature, rain, UV index, and humidity, showing it all on a bright OLED screen.
🌦️ Say hi to Terra, your mini weather globe!
What Is a Touch-Controlled Weather Globe, Anyway?
Terra combines a spinning globe with a live connection to the internet. Touch sensors placed at five continents let you "pick" a place just by touching it. The ESP32 then spins a servo to rotate the globe toward that region, downloads real live weather data over WiFi, and shows the temperature, rain, UV index, and humidity right on its OLED screen.
What You'll Need
Gather these parts before you start building Terra!
ESP32 Development Board
Has built-in WiFi to fetch live weather for any city.
TTP223 Touch Sensor Modules
One mounted at each continent on the globe's surface.
SG90 Micro Servo
Rotates the whole globe to face the chosen continent.
0.96" I2C OLED Display
Shows temperature, rain, UV, and humidity.
Small Buzzer (optional)
Confirms each touch with a short beep.
Foam or 3D-Printed Globe
Painted with continents, mounted on the servo shaft.
Small Stand
Holds the servo and globe upright.
Free Weather API Key
Lets your ESP32 request real temperature, rain, and UV data.
Jumper Wires
Connects all five touch sensors, the OLED, and the servo.
The Circuit Diagram
Five touch sensors, a servo, an OLED, and a buzzer all connect to one ESP32 — WiFi needs no extra wiring since it's built in.
Step-by-Step Build Instructions
Ask an adult to help you sign up for a free weather API key. Let's build Terra!
Get a free weather API key
Sign up for a free account at a weather data provider like OpenWeatherMap, and copy your personal API key.
💡 Tip: New API keys can take up to an hour to activate, so set this up first!Paint or print your globe
Paint continents onto a foam ball, or use a 3D-printed globe, then mount it firmly onto the servo's shaft so it rotates smoothly.
Attach the five touch sensors
Mount one TTP223 touch sensor at each of five continents on the globe's surface — North America, Europe, Africa, Asia, and Australia.
Build the stand and mount the servo
Fix the servo inside a small stand so the globe sits upright and can rotate freely without wobbling.
Add the OLED and buzzer
Mount the OLED on the stand where it's easy to read, and place the buzzer nearby for touch confirmations.
Install the libraries and upload the code
Install ESP32Servo, ArduinoJson, and Adafruit_SSD1306, fill in your WiFi and API details in the code below, then upload it.
Touch a continent and check the weather!
Touch any of the five sensor spots, and watch Terra spin toward it while the OLED fills in with that region's live weather.
The ESP32 Code
Fill in your WiFi details and API key, then upload with your ESP32 board selected in the Arduino IDE.
// 🌍🤖 Terra the Mini Earth Weather Globe — ESP32 Robotics Project // Touch a continent to spin the globe and download its live weather #include <WiFi.h> #include <HTTPClient.h> #include <ArduinoJson.h> #include <ESP32Servo.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> // ---- Fill in your own details ---- const char* ssid = "YOUR_WIFI_NAME"; const char* password = "YOUR_WIFI_PASSWORD"; String apiKey = "YOUR_WEATHER_API_KEY"; // ---- 5 touch zones, one per continent ---- const int touchPins[5] = {13, 12, 14, 27, 26}; const char* cityNames[5] = {"New York", "London", "Cairo", "Tokyo", "Sydney"}; const int rotationAngles[5] = {0, 45, 90, 135, 180}; Servo globeServo; const int servoPin = 18; const int buzzerPin = 19; Adafruit_SSD1306 display(128, 64, &Wire, -1); void setup() { Serial.begin(115200); for (int i = 0; i < 5; i++) pinMode(touchPins[i], INPUT); pinMode(buzzerPin, OUTPUT); globeServo.attach(servoPin); globeServo.write(90); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); showMessage("Connecting WiFi..."); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) delay(300); showMessage("Touch a continent!"); } void loop() { for (int i = 0; i < 5; i++) { if (digitalRead(touchPins[i]) == HIGH) { selectLocation(i); delay(1000); // avoid re-triggering instantly } } } // Spins the globe toward the touched continent, then fetches its weather void selectLocation(int index) { tone(buzzerPin, 1200, 150); showMessage("Spinning to " + String(cityNames[index]) + "..."); globeServo.write(rotationAngles[index]); delay(600); fetchWeather(cityNames[index]); } // Downloads temperature, humidity, and rain for the chosen city void fetchWeather(String city) { showMessage("Checking sky..."); HTTPClient http; String url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "&appid=" + apiKey + "&units=metric"; http.begin(url); int httpCode = http.GET(); if (httpCode == 200) { String payload = http.getString(); StaticJsonDocument<1024> doc; deserializeJson(doc, payload); float temp = doc["main"]["temp"]; float humidity = doc["main"]["humidity"]; String condition = doc["weather"][0]["main"].as<String>(); float rain = doc["rain"]["1h"] | 0.0; // defaults to 0 if not raining // A separate UV index lookup (many weather providers offer one) — adjust // the URL and field names to match whichever service you signed up for float uvIndex = fetchUVIndex(doc["coord"]["lat"], doc["coord"]["lon"]); showWeather(city, temp, humidity, condition, rain, uvIndex); } else { showMessage("Weather fetch failed"); } http.end(); } // Looks up the UV index for a given latitude/longitude float fetchUVIndex(float lat, float lon) { HTTPClient http; String url = "http://api.openweathermap.org/data/2.5/uvi?lat=" + String(lat) + "&lon=" + String(lon) + "&appid=" + apiKey; http.begin(url); int httpCode = http.GET(); float uvi = -1; if (httpCode == 200) { String payload = http.getString(); StaticJsonDocument<256> doc; deserializeJson(doc, payload); uvi = doc["value"]; } http.end(); return uvi; } // Shows all four weather values on the OLED void showWeather(String city, float temp, float humidity, String condition, float rain, float uvi) { display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.println(city); display.setCursor(0, 14); display.print("Temp: "); display.print(temp, 1); display.println(" C"); display.setCursor(0, 26); display.print("Humidity: "); display.print(humidity, 0); display.println("%"); display.setCursor(0, 38); display.print("Sky: "); display.println(condition); display.setCursor(0, 50); display.print("Rain: "); display.print(rain, 1); display.print("mm UV: "); display.println(uvi, 0); display.display(); } // Shows a short status message on the OLED void showMessage(String msg) { display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 25); display.println(msg); display.display(); }
How Does Terra Actually Work?
Here are the big ideas hiding inside this project:
Capacitive Touch Sensing
A TTP223 module detects the tiny change in electrical charge when your finger touches it — no button press needed, just a light touch.
Location as Data
Each touch pin is linked to a city name and a servo angle in matching arrays — touching a pin looks up everything needed in one step, no separate logic per continent.
Chaining Two API Calls
The code calls the weather API once for temperature and rain, then uses the returned coordinates to make a second call for UV index — a common pattern when one API doesn't have everything you need.
Physical Feedback for Digital Data
Rotating the globe toward the selected continent turns an abstract choice (a touch) into something you can actually see and feel — making the data feel real.
🧑🔬 Safety First!
- Build with an adult, especially when wiring the touch sensors and setting up WiFi credentials.
- Never share your WiFi password or API key publicly.
- Keep fingers clear of the servo while the globe is rotating.
- This project only displays weather information — always check official sources for real safety decisions during severe weather.
Frequently Asked Questions
Why does UV index need a separate API call?
Many weather services keep UV index in a different part of their API than basic weather, since it depends on additional calculations. Check your specific provider's documentation for the exact endpoint and field names to use.
Can I add more continents or cities?
Yes! Add more entries to the touchPins, cityNames, and rotationAngles arrays, add a matching touch sensor, and increase the loop limit from 5 to your new total.
The touch sensors trigger by themselves — what's wrong?
This is usually caused by loose wiring or sensitivity that's set too high. Double-check your connections, and check your specific TTP223 module for a sensitivity adjustment pad.
What age group is this project good for?
This project is great for kids around age 10+ working with an adult, and makes a fun way to combine geography with real-time data and electronics.

Comments
Post a Comment