Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.
Brooder Controller: the finished build
ESP32India utility230 V

Poultry brooder temperature controller for chicks (ESP32 + DS18B20)

Holds the brooder at 33 °C for day-old chicks and steps down 3 °C every week.

Difficulty
Medium
Build time
2.5 h
Parts cost
₹1,795 · $21
Verified — core esp32 3.3.12, OneWire 2.3.8, 3 Nov 2026Compile-only

Community draft — report a mistake

Mains voltage (230 V) — can kill. The low-voltage side (board, sensors, display, relay module) is safe to build yourself. The mains side must be wired by a licensed electrician, and tested with the circuit switched off at the MCB.

  • Never switch a motor with a relay module. Motors pull several times their running current at start-up; hobby relay contacts weld or overheat. The relay only drives a contactor’s coil (or your pump starter’s coil input).
  • Contactor rated for motors (AC-3) at or above the load’s nameplate current.
  • Protect and earth: MCB on live, RCCB/ELCB on the circuit, metal bodies earthed. Switch live only — never neutral or earth.
  • Keep the two worlds apart: mains and low-voltage wiring in separate compartments of a closed, non-metallic enclosure; no bare 230 V terminals.
  • Fail safe: the code switches the load off when a sensor stops answering. Still fit a manual override at the starter.

Parts list

PartQtyApprox.Buy
ESP32 DevKit V1 (30-pin)1₹380Buy ESP32 DevKit V1 (30-pin)
DS18B20 waterproof probe (1 m) + 4.7 kΩ resistor1₹120Buy DS18B20 waterproof probe (1 m) + 4.7 kΩ resistor
0.96" SSD1306 I2C OLED (4-pin)1₹220Buy 0.96" SSD1306 I2C OLED (4-pin)
1-channel relay module, 5 V coil, 3.3 V-trigger, contacts 10 A 250 V1₹70Buy 1-channel relay module, 5 V coil, 3.3 V-trigger, contacts 10 A 250 V
Push button1₹10Buy Push button
Active buzzer module (or a louder 5 V buzzer)1₹25Buy Active buzzer module (or a louder 5 V buzzer)
Brooder lamps: 2 × 100 W infrared/incandescent with ceramic holders and guards1₹600Buy Brooder lamps: 2 × 100 W infrared/incandescent with ceramic holders and guards
IP54 enclosure, mounted outside the brooder ring1₹250Buy IP54 enclosure, mounted outside the brooder ring
5 V 1 A USB adapter + cable1₹120Buy 5 V 1 A USB adapter + cable
Total₹1,795

Affiliate disclosure: “Buy” links may earn FlashReady a small commission at no extra cost to you. Prices are indicative.

Wiring

ESP32 DevKit V1Only the pins used are shown · 3.3 V logicBrooder lamp circuit, 230 V (electrician)DS18B20 (1-Wire)SSD1306 OLED 0.96″ (128×64, I2C)1-channel relay module (5 V coil)Push button (6 mm tactile switch)Active buzzer module (high-level trigger)4.7k → 3V3LLamp LD25D26D27GNDVIND22D21D43V3GNDDQVDDGNDVCCSCLSDADC+DC−INCOMNONC (not connected)12I/OVCCGND
Every connection
ESP32 DevKit V1Part · pinWireNotes
D4DS18B20 (1-Wire) · DQyellow
3V3DS18B20 (1-Wire) · DQredVia 4.7 kΩ — Pull-up from DQ to 3.3 V
3V3DS18B20 (1-Wire) · VDDred
GNDDS18B20 (1-Wire) · GNDblack
D21SSD1306 OLED 0.96″ (128×64, I2C) · SDAblue
D22SSD1306 OLED 0.96″ (128×64, I2C) · SCLyellow
3V3SSD1306 OLED 0.96″ (128×64, I2C) · VCCred
GNDSSD1306 OLED 0.96″ (128×64, I2C) · GNDblack
D261-channel relay module (5 V coil) · INorangeActive-LOW; written HIGH (off) before it becomes an output
VIN1-channel relay module (5 V coil) · DC+red5 V for the relay coil
GND1-channel relay module (5 V coil) · DC−black
Brooder lamp circuit, 230 V (electrician) · L1-channel relay module (5 V coil) · COMbrownLive from the MCB to COM — 230 V, electrician only
Brooder lamp circuit, 230 V (electrician) · Lamp L1-channel relay module (5 V coil) · NObrownNO to the lamps’ live; neutral and earth go straight to the lamp holders
D27Push button (6 mm tactile switch) · 1purpleChick age in weeks, INPUT_PULLUP
GNDPush button (6 mm tactile switch) · 2black
D25Active buzzer module (high-level trigger) · I/Oorange
3V3Active buzzer module (high-level trigger) · VCCred
GNDActive buzzer module (high-level trigger) · GNDblack

Board quirks: Two 100 W lamps draw under 1 A at 230 V — well inside a 10 A relay contact. For a bigger shed with 1–2 kW of heaters, the relay must switch a <strong>contactor coil</strong> instead, and the contactor switches the heaters. Either way the 230 V wiring, MCB, RCCB and earth are an electrician’s job. Hang the probe at <strong>chick height</strong> (5–8 cm above the litter) at the edge of the warm zone, not right under the lamp — that is the temperature the chicks feel. If the probe fails, the lamps switch <strong>off</strong> and the buzzer sounds. A lamp stuck on can overheat the chicks or set dry litter alight; a cold brooder gives you time to respond to the alarm. Press the button to step the chick age through weeks 1–5. It is stored in flash, so a power cut doesn’t reset it to week 1.

Code

poultry-brooder-controller.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// Poultry brooder temperature controller — ESP32 DevKit V1 + DS18B20 + OLED + relay + buzzer
// DS18B20 on D4 (4.7 kΩ pull-up to 3V3) hung at chick height. OLED on D21/D22.
// Relay module IN on D26 (active-LOW): COM/NO switch the brooder lamps (within the relay's rating).
// Push button D27 to GND: chick age in weeks (1-5), saved across power cuts. Buzzer module on D25.
// Target: 33 °C in week 1, 3 °C less each week, 21 °C from week 5.
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Preferences.h>

constexpr uint8_t TEMP_PIN = 4;
constexpr uint8_t RELAY_PIN = 26;
constexpr uint8_t BUTTON_PIN = 27;
constexpr uint8_t BUZZER_PIN = 25;
constexpr bool RELAY_ACTIVE_LOW = true;
constexpr float HYST = 0.5;                       // lamps on below target-0.5, off above target+0.5
constexpr float ALARM_BAND = 4.0;                 // alarm when this far from the target...
constexpr uint32_t ALARM_AFTER_MS = 5UL * 60UL * 1000UL;  // ...for 5 minutes

OneWire bus(TEMP_PIN);
DallasTemperature probe(&bus);
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
Preferences prefs;
uint8_t week = 1;
bool heater = false;
uint32_t outOfBandSince = 0;

float targetFor(uint8_t w) { return max(21.0f, 33.0f - 3.0f * (w - 1)); }

void setHeater(bool on) {
  heater = on;
  digitalWrite(RELAY_PIN, (on != RELAY_ACTIVE_LOW) ? HIGH : LOW);
}

void setup() {
  digitalWrite(RELAY_PIN, RELAY_ACTIVE_LOW ? HIGH : LOW);  // lamps off before the pin becomes an output
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT);
  Serial.begin(115200);
  prefs.begin("brooder", false);
  week = constrain(prefs.getUChar("week", 1), 1, 5);
  probe.begin();
  Wire.begin(21, 22);
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println("OLED not found at 0x3C");
  oled.setTextColor(SSD1306_WHITE);
  Serial.printf("Brooder: week %u, target %.1f C\n", week, targetFor(week));
}

void loop() {
  if (digitalRead(BUTTON_PIN) == LOW) {
    week = week % 5 + 1;
    prefs.putUChar("week", week);
    Serial.printf("Week %u -> target %.1f C\n", week, targetFor(week));
    while (digitalRead(BUTTON_PIN) == LOW) delay(10);
  }

  probe.requestTemperatures();
  float t = probe.getTempCByIndex(0);
  float target = targetFor(week);
  bool probeOk = t > -50 && t < 85;  // -127 = no probe, 85 = a reset/glitch reading
  bool alarm;

  if (!probeOk) {
    setHeater(false);  // never run the lamps blind: they can overheat the chicks or start a fire
    alarm = true;
  } else {
    if (!heater && t < target - HYST) setHeater(true);
    if (heater && t > target + HYST) setHeater(false);
    if (fabs(t - target) > ALARM_BAND) {
      if (!outOfBandSince) outOfBandSince = millis();
    } else {
      outOfBandSince = 0;
    }
    alarm = outOfBandSince && millis() - outOfBandSince > ALARM_AFTER_MS;
  }
  digitalWrite(BUZZER_PIN, alarm ? HIGH : LOW);

  oled.clearDisplay();
  oled.setCursor(0, 0);
  oled.setTextSize(1);
  oled.printf("Week %u  set %.1f C\n", week, target);
  oled.setTextSize(3);
  if (probeOk) oled.printf("%.1f", t);
  else oled.print("--.-");
  oled.setTextSize(1);
  oled.setCursor(0, 44);
  oled.println(heater ? "LAMPS ON" : "lamps off");
  if (!probeOk) oled.print("PROBE FAULT!");
  else if (alarm) oled.print(t > target ? "TOO HOT!" : "TOO COLD!");
  oled.display();

  Serial.printf("t=%.1f target=%.1f heater=%d week=%u alarm=%d\n", t, target, heater, week, alarm);
  delay(2000);
}

Compiled for esp32 on esp32 3.3.12 with OneWire 2.3.8 · 3 Nov 2026

How it works

Day-old chicks can’t keep themselves warm for their first weeks. Too cold and they huddle, stop eating and die; too hot and they pant and dehydrate. Small poultry farmers across India brood batches of 100–500 chicks under bulbs and adjust them by guesswork — and a cold night or a hot afternoon can cost a large part of a batch.

How it works

A DS18B20 waterproof probe hangs at chick height. Every 2 seconds the ESP32 reads it and compares it with the target for the chicks’ age: 33 °C in week 1, then 3 °C less each week, and 21 °C from week 5. You set the week with the push button.

The relay switches the brooder lamps with ±0.5 °C hysteresis: on below target − 0.5 °C, off above target + 0.5 °C. That stops the relay chattering when the temperature sits right on the line.

If the temperature stays more than 4 °C away from the target for 5 minutes, the buzzer sounds and the OLED says TOO HOT or TOO COLD. A missing or faulty probe (it reads −127 °C or the 85 °C power-on value) turns the lamps off and sounds the buzzer at once.

Why these parts

  • DS18B20 probe — waterproof, digital (no calibration drift on a long cable), and accurate to ±0.5 °C.
  • Relay within rating — 200 W of lamps is about 0.9 A. Check your relay module’s contact rating printed on the blue relay (10 A 250 V AC is common).
  • ESP32 — stores the week in flash and leaves room for a phone alert later.

Calibration

Put the probe next to a good thermometer in a glass of water at room temperature; they should agree within 0.5 °C. Then watch the chicks for the first day — the temperature table is a starting point, and every breed and shed is a bit different.

India notes

North Indian winter nights fall below 5 °C and summer afternoons above 40 °C — in summer the controller may keep the lamps off all day and you’ll need shade and ventilation instead. Use an RCCB on the brooder circuit: sheds are damp, and lamp holders get splashed when drinkers are refilled.

Troubleshooting

The OLED shows --.- and PROBE FAULT

The DS18B20 doesn’t answer. Check the 4.7 kΩ pull-up between DQ and 3V3 and the three probe wires (red VDD, black GND, yellow DQ). Long probe leads (over 5 m) need a lower pull-up, around 2.2 kΩ.

The lamps switch on and off every few seconds

The probe is too close to a lamp, so it heats and cools faster than the brooder air. Move it to the edge of the warm zone, or raise HYST to 1.0 °C.

The chicks crowd under the lamp even at the set temperature

Watch the chicks, not just the number: crowding means cold, spreading to the walls and panting means hot. Draughts at chick level make them feel colder — raise the brooder guard.

Upgrades

  • Send a phone alert through ntfy.sh on an alarm — useful at night.
  • Add a DHT22 to watch humidity and ammonia-wet litter, and an exhaust fan through a contactor.
  • Use a dimmer-friendly heater with an SSR and PID control for a steadier temperature.

↑↓ to move · Enter to open