ESP32 UNO - Smart Weather Station
Want a desk gadget that shows today's weather without a single sensor? Combine the ESP32 Uno form board with a 1.28 inch round GC9A01 TFT. The board asks the free Open-Meteo weather API for your city over WiFi, then draws temperature, wind, rain chance and a 3-day forecast on a live WiFi weather display.
By the end, you can:
- Connect a round TFT screen and one push button to the ESP32 Uno
- Fetch live weather from a web API over HTTPS
- Parse the JSON reply with ArduinoJson
- Keep a real-time clock with NTP
- Switch between eight screens with a single button

Components You Need
Pick one button part, not both. Each wiring option is shown below.
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (18 sensors/displays) |
Additionally, some of these links are for products from our own brand, DIYables .
What the Eight Screens Show
By the end of this part, you know what to expect on the display after the upload. One button steps through the pages in a loop.
| Page | Content |
|---|---|
| HOME | Sky icon, temperature, short sky text, and the NTP clock |
| TEMP | Air temperature and the "feels like" value on an arc gauge |
| HUMIDITY | A ring that fills with the humidity, plus the percent |
| WIND | Wind speed and an arrow on a small compass |
| RAIN | Rain chance and falling drops when rain is likely |
| NEXT HOURS | Five rows with time, sky, temperature and rain chance |
| FORECAST | Lowest and highest temperature for 3 days |
| SYSTEM | Link state, RSSI, API state, city name and data status |
New data arrives every 10 minutes. In between, the clock keeps counting, because the ESP32 Uno holds its own time after one NTP sync.
Good to know: the weather is for your city, not for the room. For indoor values you can add a sensor later.
The Open-Meteo Weather Service
By the end of this part, you know why this API fits a small board. Open-Meteo is a free web service, described at open-meteo.com.
| Item | Detail |
|---|---|
| Account | none, no sign-up |
| API key | not needed |
| Price | free for personal projects |
| Answer | plain JSON text |
| Location | latitude and longitude |
| Connection | HTTPS, port 443 |
A single request returns the current values, a list of hourly values and a short daily summary. Add a timezone value and the times arrive in local time instead of UTC.
ESP32 Uno Pinout
Every Uno header pin on the ESP32 Uno form board is tied to one GPIO number, and the sketch uses that number. Look at this map once before you push in any wire.

※ NOTE THAT:
The wiring diagram may not show the correct pin. On the ESP32 Uno, the display RST wire goes to D4 (GPIO17), not D8 as the picture may show. We will update the diagram soon. Until then, follow the wiring table and the code on this page, not the picture.
How to Connect
By the end of this part, the round display and the button are wired and ready. The display uses the hardware SPI bus, so D13 and D11 stay where they are.
| TFT LCD Pin | ESP32 Uno Pin | Role |
|---|---|---|
| VCC | 3.3V | Power |
| GND | GND | Ground |
| SCL | D13 (GPIO18) | Clock line of SPI (cannot move) |
| SDA | D11 (GPIO23) | Data line of SPI (cannot move) |
| DC | D9 (GPIO13) | Data or command |
| CS | D10 (GPIO5) | Selects the display |
| RST | D4 (GPIO17) | Reset |
WARNING
The CS wire uses D10 (GPIO5), which is a boot strapping pin. The chip reads this pin at power-up. The display normally does not pull CS the wrong way, so the board boots fine. If the board will not boot or upload with the display plugged in, unplug the CS wire, upload, and plug it in again.
Good to know: the display only receives signals from the board, so no 5V signal goes into an ESP32 Uno pin. Power it from 3.3V to match the board logic.
Wire the button to header D2 (GPIO26). A bare push button or a ready-made button module both work, as long as the code line matches your part.
Option 1 - Plain Push Button
A push button has no resistor. Wire one leg to D2 and the other to GND. The internal pull-up of the ESP32 Uno keeps the pin HIGH at rest, and it drops to LOW while you press.

This image is created using Fritzing. Click to enlarge image
| Button Pin | ESP32 Uno Pin | Role |
|---|---|---|
| Pin 1 | D2 (GPIO26) | Input with internal pull-up |
| Pin 2 | GND | Ground |
The default sketch matches this wiring, with this line:
Option 2 - Button Module
A button module has a pull-down resistor on its board and needs power. Its OUT pin rests at LOW and goes HIGH on a press, the opposite of the bare button.

This image is created using Fritzing. Click to enlarge image
| Button Module Pin | ESP32 Uno Pin | Role |
|---|---|---|
| VCC | 3.3V | Power |
| GND | GND | Ground |
| OUT | D2 (GPIO26) | LOW at rest, HIGH when pressed |
WARNING
Give the button module 3.3V only. OUT swings up to the VCC level, and the pins of this board do NOT tolerate 5V. Five volts on D2 may burn out GPIO26.
The resistor is already on the module, so leave the internal pull-up off. Change one line:
Code Building Blocks
By the end of this part, you can read the main pieces of the sketch before you open the full listing.
Step 1 - Libraries
Four headers are built into the board package: WiFi.h, WiFiClientSecure.h, HTTPClient.h and time.h. You add just ArduinoJson, DIYables_TFT_Round and ezButton from the Library Manager.
Step 2 - Display object
The constructor wants reset, data/command and chip select, in that order. This board maps them to D4 as GPIO17, D9 as GPIO13 and D10 as GPIO5.
Step 3 - WiFi name and city
Step 4 - Join WiFi
Step 5 - Set the clock over NTP
GMT_OFFSET_SEC is the distance from UTC in seconds.
Step 6 - Send the HTTPS request
setInsecure() turns off the certificate check. That keeps the sketch short and is fine for a hobby build.
Step 7 - Pick a value from the JSON
Step 8 - Draw on the round screen
ESP32 Uno Smart Weather Station Sketch
The full sketch joins WiFi, sets the clock, loads the weather every 10 minutes and paints the eight pages. The button picks the page.
Upload and Test
- First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
- Build the circuit by following the wiring tables above.
- Plug in the USB Type-C cable between the ESP32 Uno and your computer.
- Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
- Go to the libraries. Click the Libraries icon in the IDE side bar.
- Add the display driver. Type “DIYables TFT Round” in the search field, choose the entry from DIYables, then press Install.
- Search for DIYables TFT Round created by DIYables.io and click the Install button.
- Take the extra packages. If a dialog offers dependencies, press Install All.
- Add the JSON reader. Look for “ArduinoJson” from Benoit Blanchon and press Install.
- Add the button helper. Look for “ezButton” from ArduinoGetStarted and press Install.
- Paste the sketch from the listing above into a new IDE window.
- Type your network. Put your router name in WIFI_SSID and its key in WIFI_PASSWORD.
- Choose the place. Five constants name your town: LATITUDE, LONGITUDE, LOCATION_NAME, TIMEZONE and GMT_OFFSET_SEC. The city section explains each one.
- Send it to the board using the Upload arrow.
- Open the Serial Monitor at 115200 baud.
- Watch the display. You see the splash screen, the WiFi screen, then the HOME page.
- Tap the button to move through the pages.
- Pro tip: if the upload ends with "sketch too big", open Tools > Partition Scheme and choose Huge APP.
Video Tutorial
See the ESP32 Uno build in action in the video below.
Code Explanation
By the end of this part, you know how the sketch is organized. Each line also has a comment in the code above.
| Code Part | What It Does |
|---|---|
| Settings block | Holds WiFi, city, time zone and clock offset values |
| connectWiFi() | Joins the network and shows an animated signal icon |
| setupTime() | Sets the clock from the NTP servers |
| fetchWeather() | Sends the HTTPS request and passes the answer to the parser |
| parseWeather() | Copies current, hourly and daily values into one struct |
| renderPage() | Draws the selected page when the screen needs a refresh |
| handleButton() | Times each press and picks the action |
The loop calls these small functions again and again, so the display, the clock and the button never wait for each other.
ESP32 Uno vs UNO R4 for This Project
By the end of this part, you know what changes when you move this station from the UNO R4 WiFi to the ESP32 Uno.
| Item | Arduino UNO R4 | ESP32 Uno |
|---|---|---|
| Logic voltage | 5V | 3.3V |
| WiFi library | WiFiS3.h | WiFi.h |
| HTTPS client | WiFiSSLClient with ArduinoHttpClient | WiFiClientSecure with HTTPClient |
| Clock | Time taken from the API answer | NTP over WiFi |
| Button | D2 | D2 (GPIO26) |
| Display RST, DC, CS | D8, D9, D10 | D4 (GPIO17), D9 (GPIO13), D10 (GPIO5) |
| Arduino IDE board | Arduino UNO R4 WiFi | ESP32 Dev Module |
Display RST goes to D4 (GPIO17) here, not D8 as the UNO R4 picture shows, because GPIO12 on D8 is a boot strapping pin. Watch the boot strapping pin D10, and keep every module signal at 3.3V.
Show Your Own City
By the end of this part, the display shows your hometown. Five lines at the top of the sketch control this.
| Setting | How to Fill It |
|---|---|
| LATITUDE, LONGITUDE | Copy the numbers for your city from any map website |
| LOCATION_NAME | A short label so it fits the round screen |
| TIMEZONE | The zone name with each "/" written as %2F, like Europe%2FBerlin |
| GMT_OFFSET_SEC | Hours from UTC times 3600, like (1 * 3600) for Berlin in winter |
| DST_OFFSET_SEC | 3600 where summer time applies, otherwise 0 |
※ NOTE THAT:
The API sends Celsius and km/h. Want imperial units? Find temperature_unit and wind_speed_unit in getWeatherURL() and set them to fahrenheit and mph.
Troubleshooting
| Problem | Possible Cause | Solution | |
|---|---|---|---|
| No COM port appears or the upload does not start | The CH340 driver is missing, or the USB cable is charge-only | Install the CH340 driver and use a data USB cable. If you see "Failed to connect" or "Waiting for download", hold the BOOT button while the upload starts | |
| Display is dark | The clock or data wire sits on the wrong header, or VCC/GND is loose | Move SCL to D13 (GPIO18) and SDA to D11 (GPIO23), then re-seat the power jumpers | |
| Board will not boot or upload with the display connected | CS on D10 (GPIO5) is a boot strapping pin pulled the wrong way | Unplug the CS wire while you upload, then plug it in again, or use another pin | |
| WiFi screen never finishes | Typo in the credentials, or the router is 5 GHz only | Re-type WIFI_SSID and WIFI_PASSWORD, and switch the router to 2.4 GHz | |
| HTTP CODE is negative | The secure connection failed | Check that your WiFi has Internet access and is not a captive portal | |
| Clock shows -- | -- | The NTP sync did not finish | Some networks block UDP port 123, so try another network and restart the board |
| Pages jump by themselves or the button does nothing | The code does not match the button type | Use EXTERNAL_PULLDOWN only with a button module, and power that module from 3.3V | |
| Upload ends with "sketch too big" | The default partition is too small | Choose Tools > Partition Scheme > Huge APP | |
| Colors or text look wrong on the round screen | Wrong rotation or loose data wire | Check the SDA wire and keep tft.setRotation(2) in setup() |
FAQ
Does this weather station need a temperature or humidity sensor?
No. The ESP32 Uno reads all values from the Open-Meteo API over WiFi. They describe the weather in your city, not the air in your room. You can add a sensor later for indoor readings.
Do I need an API key for Open-Meteo?
No. Open-Meteo is free for personal use and works without sign-up. The only inputs are your coordinates and time zone.
How often does the ESP32 Uno update the weather?
Every 10 minutes by default. Hold the button for 0.6 to 2 seconds to load new data right away. Change API_UPDATE_INTERVAL in the code for another period.
Why does the sketch use setInsecure() for HTTPS?
It skips the certificate check, so you do not paste a root certificate into the code. This is fine for a hobby display. For a product, load the real certificate with client.setCACert().
Can I move the button or the display control wires to other pins?
Yes. The button, DC, CS and RST wires can go to other free pins if you change PIN_BUTTON, PIN_DC, PIN_CS and PIN_RST. SCL and SDA are fixed to D13 (GPIO18) and D11 (GPIO23), since the library uses the default SPI pins.
Is it safe to feed the button module 5V here, as on the UNO R4?
No. This board works at 3.3V, and its pins are NOT 5V tolerant. A module powered from 5V would put 5V on D2 when you press it. Use the 3.3V pin.
Does the UNO R4 code run on the ESP32 Uno without changes?
Not quite. WiFiS3.h becomes WiFi.h, the HTTPS client changes to WiFiClientSecure with HTTPClient, and the pins become GPIO numbers. The sketch on this page already has these changes.
Why is D10 marked as a warning pin here?
D10 is GPIO5, which is a boot strapping pin. The chip reads it at power-up. A device that pulls it the wrong way can stop the board from starting or uploading. If that happens, unplug the wire during upload.
My build needs extra pins beyond the Uno headers. What are my options?
The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they also work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Add pin headers by soldering, then type the GPIO number in your sketch. A second button or a buzzer for alerts would suit GPIO32 or GPIO33 here. Two warnings: (1) GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32 and GPIO33 first; (2) never use the six holes under the digital header (SD0 to SD3, CMD, CLK = GPIO6 to GPIO11), because they are wired to the flash chip and using them crashes the board.
Why is the clock wrong when the weather looks right?
Time is read from NTP servers, and the weather answer plays no part in it. Compare GMT_OFFSET_SEC and DST_OFFSET_SEC with your city, and let TIMEZONE name the same place.
Can I see the same weather on my phone with the ESP32 Uno?
Yes. The board already has WiFi, so you can serve the values on a web page with a DIYables web app. Start with ESP32 Uno - Web Monitor and send the temperature and humidity text to it.