ESP32 for Beginners: From Blink to Connected
A practical path from your first blinking LED to a Wi-Fi ESP32 device with a local web dashboard, saved settings and safe relay control, based on projects I have built.
The ESP32 is the board I reach for first. For a few hundred rupees it gives you a dual-core processor, Wi-Fi, Bluetooth and plenty of pins, and the Arduino tools you may already know work with it. This guide follows the order I actually learned things in, ending with the pieces I now put into every device I build: a local web dashboard, settings that survive a power cut, and safety rules in code.
The examples come from a smart air cooler controller I built for my own home. It runs a fan, a water pump and a valve through relays, reads temperature and humidity, checks the water level and is controlled from a phone browser, with no cloud service at all.
Step 1: Blink, to prove your setup works
Every ESP32 project should start with blinking an LED. It proves that the board, the USB cable, the driver and the Arduino IDE board settings all work together. When something fails later you will know the problem is in your code, not your setup.
Two things trip up most beginners. First, many cheap USB cables carry power only, not data, so the board never shows up as a port; keep one known-good data cable aside. Second, some boards need you to hold the BOOT button while the upload starts. If the upload stops at 'Connecting…', that is usually why.
Step 2: Read a sensor and print it
Next, read something real. A DHT22 temperature and humidity sensor is a good first sensor: one data pin, a library that handles the timing, and values you can check against the room. Print the readings to the Serial Monitor every few seconds.
Do not read sensors inside a tight loop with delay() everywhere. Use millis() to run each job on its own schedule, for example read the sensor every 5 seconds and check Wi-Fi every 10. This habit matters later, because a device that blocks for seconds at a time also stops answering its web page and its buttons.
Step 3: Join Wi-Fi without freezing
Connecting to Wi-Fi takes a few lines of code. The real work is coping with routers that reboot, signals that drop and passwords that change. My rule is that the device must keep doing its main job even with no Wi-Fi: the cooler keeps its timer and safety rules running whether or not a phone is connected.
- Start the connection and carry on, then check the status later instead of waiting in a loop
- Reconnect automatically when the connection drops
- Keep the Wi-Fi password in flash storage rather than in the source code, so it can change without reflashing
Step 4: Give it a local web dashboard
The ESP32 can host its own web page. With the built-in WebServer library, the board serves an HTML page with buttons and live readings, and any phone on the same Wi-Fi can open it. No app to install, no account and no internet needed.
Add mDNS so you can open it by name. My cooler answers at cooler.local, which is much easier than remembering an IP address that the router may change. For the page, keep the HTML small and fetch the live values as JSON every few seconds. I drew the countdown timer as an SVG arc, which looks good and costs almost nothing in memory.
Step 5: Remember settings across power cuts
Power cuts are common, and a device that forgets its settings every time is annoying. The ESP32 has a small key-value store in flash, called NVS, that you use through the Preferences library. Save things like fan speed, timer length and thresholds there, and load them at start-up.
Only write when a value actually changes. Flash memory wears out after many writes, so saving the same value every second will shorten its life.
Step 6: Put safety rules in code
Once relays switch real loads, mistakes cost money. In the cooler, the pump must never run without the fan, or water pools without evaporating. So the code enforces an interlock: turning the fan off also turns the pump off, and the pump cannot start while the fan is off, whatever button is pressed.
The water probe taught me another lesson. Two bare wires in water with steady DC on them corrode within weeks. Powering the probe only for a short pulse when taking a reading, and checking the level about once an hour instead of constantly, makes the probe last far longer.
- Use relay modules with optocouplers, and keep mains wiring away from the low-voltage side
- Make the safe state the default after a reboot: relays off until the code decides otherwise
- Write each interlock as a single function that every control path goes through
Step 7: Update it without a cable
When a board is inside an enclosure, plugging in a USB cable for every fix gets old fast. Over-the-air (OTA) updates let you upload new firmware over Wi-Fi from the Arduino IDE. Add it early, protect it with a password, and keep the USB route working as a backup in case an update goes wrong.
What to build next
Once these pieces work, most home projects are variations on them. An IR blaster can control a fan or AC that only has a remote; I ended up decoding my ceiling fan's remote and replaying its codes from the ESP32. An INA226 current sensor and a real-time clock turn the same board into a solar or battery monitor. For many devices in one home, MQTT and a hub like Home Assistant tie everything together.
Start small, get each step working before adding the next, and write down the pin numbers as you go. That habit has saved me more hours than any library.
Frequently asked questions
Do I need the internet for an ESP32 project?
No. An ESP32 can run its own web page on your home Wi-Fi and be controlled from any phone on that network, with no cloud service or internet connection.
Arduino IDE or ESP-IDF for beginners?
Start with the Arduino IDE and the ESP32 board package. It is simpler, has more examples, and is enough for most home projects. ESP-IDF is worth learning later for advanced features.
Why does my ESP32 upload stop at 'Connecting'?
Usually the board needs the BOOT button held while the upload starts, or the USB cable is power-only. Try a different cable and hold BOOT until the upload begins.