The ESP-01 is one of the smallest ways to add Wi-Fi to a project. It contains an ESP8266, a small amount of flash, and just enough exposed pins to build useful connected devices. Its limited pin count makes it less convenient than a NodeMCU for prototyping, but it is inexpensive and easy to hide inside a small enclosure.

In this project, an ESP-01 reads a DS18B20 digital temperature sensor and serves the result over the local network. Open its IP address in any browser to check a room, refrigerator, network cabinet, aquarium, or greenhouse. No cloud account, mobile application, or external server is required.

What we are building

The finished device provides two local endpoints:

The browser talks directly to the ESP-01:

DS18B20 ──GPIO2── ESP-01 ──Wi-Fi── Phone or computer
                                     ├── /             dashboard
                                     └── /temperature  JSON

This is intentionally a small project. It teaches the parts that make many IoT devices work: reading a sensor, joining Wi-Fi, exposing data over HTTP, and handling a disconnected sensor.

Parts

Use a three-wire DS18B20 connection rather than parasite power. Bare TO-92 sensors and waterproof probes use the same protocol, but probe wire colors are not guaranteed. Check the seller’s datasheet before connecting one.

Wire the sensor and ESP-01

Connect the circuit as follows:

ESP-01 / supply Connect to
VCC Regulated 3.3 V
GND Ground
EN / CH_PD 3.3 V
GPIO2 DS18B20 data pin
3.3 V DS18B20 VDD pin
Ground DS18B20 GND pin

Place the 4.7 kΩ resistor between GPIO2 and 3.3 V. Put the 100 µF and 0.1 µF capacitors across 3.3 V and ground, close to the ESP-01.

GPIO2 is a boot-strapping pin and must be high when the ESP8266 starts. The sensor’s pull-up resistor keeps it in the correct state. Avoid adding anything that pulls GPIO2 low during reset.

The ESP-01 is a 3.3 V device. Do not connect its VCC or GPIO pins to 5 V. Wi-Fi transmission causes short current spikes, so the 3.3 V output on some USB-to-serial adapters is not a reliable power supply.

Prepare the Arduino IDE

Install ESP8266 board support in Arduino IDE, then select Generic ESP8266 Module. From Library Manager, install these two libraries:

Create a new sketch and replace YOUR_WIFI_NAME and YOUR_WIFI_PASSWORD in the following code:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>

const char* WIFI_SSID = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

constexpr uint8_t ONE_WIRE_PIN = 2; // ESP-01 GPIO2

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
ESP8266WebServer server(80);

float readTemperatureC() {
  sensors.requestTemperatures();
  return sensors.getTempCByIndex(0);
}

void sendDashboard() {
  const char page[] PROGMEM = R"HTML(
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Room temperature</title>
  <style>
    body { font: 18px system-ui; margin: 0; display: grid; min-height: 100vh;
           place-items: center; background: #eef2f6; color: #17202a; }
    main { text-align: center; background: white; padding: 2.5rem;
           border-radius: 1rem; box-shadow: 0 8px 30px #0002; }
    #value { font-size: 4rem; font-weight: 700; margin: .5rem; }
    #status { color: #5d6d7e; }
  </style>
</head>
<body>
  <main>
    <h1>Temperature</h1>
    <p id="value">--.- &deg;C</p>
    <p id="status">Reading sensor...</p>
  </main>
  <script>
    async function update() {
      try {
        const response = await fetch('/temperature', { cache: 'no-store' });
        if (!response.ok) throw new Error('Sensor unavailable');
        const data = await response.json();
        document.querySelector('#value').textContent =
          `${data.celsius.toFixed(1)} °C`;
        document.querySelector('#status').textContent = 'Updated just now';
      } catch (error) {
        document.querySelector('#status').textContent = error.message;
      }
    }
    update();
    setInterval(update, 5000);
  </script>
</body>
</html>
)HTML";

  server.send_P(200, "text/html; charset=utf-8", page);
}

void sendTemperature() {
  const float temperature = readTemperatureC();

  if (temperature == DEVICE_DISCONNECTED_C) {
    server.send(503, "application/json", "{\"error\":\"sensor disconnected\"}");
    return;
  }

  const String json =
    "{\"celsius\":" + String(temperature, 2) +
    ",\"fahrenheit\":" + String(temperature * 1.8f + 32.0f, 2) + "}";
  server.send(200, "application/json", json);
}

void setup() {
  Serial.begin(115200);
  sensors.begin();

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print('.');
  }

  Serial.println();
  Serial.print("Open http://");
  Serial.println(WiFi.localIP());

  server.on("/", HTTP_GET, sendDashboard);
  server.on("/temperature", HTTP_GET, sendTemperature);
  server.onNotFound([]() {
    server.send(404, "text/plain", "Not found");
  });
  server.begin();
}

void loop() {
  server.handleClient();
}

The HTML lives in flash through PROGMEM, preserving the ESP8266’s limited working memory. The temperature endpoint returns both common units, so a client can use the data without repeating the conversion.

Upload the sketch

Disconnect the sensor while programming if that makes the header easier to reach. Connect the USB-to-serial adapter with crossed serial lines:

To enter the bootloader, connect GPIO0 to ground and then power or reset the module. Upload the sketch. After the upload completes, remove the GPIO0-to-ground connection and reset the module again so it starts normally.

Open Serial Monitor at 115200 baud. Once connected, the ESP-01 prints an address similar to http://192.168.1.42. Open that address from a device on the same Wi-Fi network.

To see the machine-readable response, open /temperature:

{"celsius":23.56,"fahrenheit":74.41}

Make the address easier to find

The router may give the ESP-01 a different IP address after a restart. The most reliable fix is a DHCP reservation in the router: reserve an address for the MAC address printed by WiFi.macAddress().

This is preferable to hard-coding an address in the sketch because the router remains the source of truth and can prevent address conflicts.

Troubleshooting

The module repeatedly resets

The usual cause is weak 3.3 V power. Use a proper regulator, keep the wires short, add the decoupling capacitors, and make sure all components share ground.

Uploading fails

Confirm that GPIO0 was low during reset, TX and RX are crossed, the adapter uses 3.3 V logic, and no other program has the serial port open. Lowering the upload speed can help with long or poor-quality wires.

The API reports that the sensor is disconnected

Check the DS18B20 pinout, common ground, and 4.7 kΩ pull-up. A genuine reading of -127 °C from the DallasTemperature library indicates a communication failure, not an extremely cold room.

The module runs only while connected to the programmer

Make sure EN is held at 3.3 V and GPIO0 is no longer grounded. GPIO0 low at reset selects the serial bootloader instead of the uploaded application.

Useful next steps

This small server is a good base for a larger project. You could:

Keep the device on a trusted local network. This example has no login or TLS, so do not forward port 80 from the internet. If remote access is needed, connect to the home network through a VPN or let an authenticated home-automation system relay the data.

Takeaways

The ESP-01 looks constrained, but one GPIO and a tiny HTTP server are enough for a useful device. The DS18B20’s single-wire interface leaves the circuit simple, and its pull-up also satisfies GPIO2’s boot requirement. With stable 3.3 V power, the result can run quietly on a shelf and make its measurements available to every browser on the local network.

Sources