Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reptile Enclosure Controller

Author: Richard Simpson
License: MIT
Platform: Arduino Mega 2560 (PlatformIO)

An 8-zone temperature controller for reptile enclosures. Each zone runs an independent PID loop with a 30-second time-proportional relay window. All configuration and tuning is done from a front-panel LCD menu — no re-flashing required after initial setup.


Hardware

Component Quantity Notes
Arduino Mega 2560 1
DS18B20 temperature sensor 8 All on a single 1-Wire bus; 4.7 kΩ pull-up to 5 V required
DHT22 temperature/humidity sensor 2 Left and Right — optional, see ENABLE_DHT22
I²C 20×4 character LCD 1 Default address 0x27 (try 0x3F if blank)
Relay module (8-channel) 1 Active-LOW
Tactile buttons 4 UP / DOWN / SELECT / BACK
Alarm indicator (LED, buzzer, etc.) 1 Driven by PIN_ALARM

Zone layout

Zones Label Load
0 – 3 L1 – L4 Ceramic heat lamps (above)
4 – 7 M1 – M4 Heat mats (below)

Wiring (defaults — all pins in src/config.h)

Signal Pin
DS18B20 data (1-Wire) 2
DHT22 Left 3
DHT22 Right 4
Button UP 5
Button DOWN 6
Button SELECT 7
Button BACK 8
Alarm output 30
Relay L1 – L4 22 – 25
Relay M1 – M4 26 – 29

Buttons are wired between pin and GND (internal pull-up used).
All relay pins are active-LOW (RELAY_ACTIVE_HIGH false).
Alarm pin is active-HIGH (ALARM_ACTIVE_HIGH true) — blinks at 1 Hz when any alarm is active.


First-time setup

1. Flash and identify DS18B20 sensors

Flash the firmware with all sensor addresses left as 0x00 (the default). Open a serial monitor at 115200 baud. On boot the controller prints all discovered sensor addresses:

DS18B20 sensors found: 8
Copy into ZONE_ADDRS in config.h (then assign to zones):
  { 0x28, 0xFF, 0xA1, 0x2B, 0x4C, 0x1E, 0x00, 0xD3 },  // sensor 0
  { 0x28, 0xFF, 0x3C, 0x44, 0x7A, 0x02, 0x00, 0x91 },  // sensor 1
  ...

Identify which physical sensor is which by warming them one at a time and watching which address reports a temperature rise. Then fill in ZONE_ADDRS in src/config.h with each sensor assigned to the correct zone row (L1 → M4) and reflash.

2. Set setpoints and alarms

Navigate the front-panel menu → Edit Temps to set the target temperature and alarm thresholds for each zone. Settings are saved to EEPROM and survive power cycles.

3. Run autotune

Use Tune All Zones from the menu to run the relay feedback autotuner on all 8 zones simultaneously. The controller switches each zone to bang-bang mode, measures the natural oscillation, and calculates Ziegler-Nichols PID parameters automatically. Accept the results when prompted.


Normal operation — home screen

The home screen cycles automatically through all enabled screens every second:

Screen Content When shown
LAMPS L1–L4 current temp, setpoint, relay state (H = heating) Always
MATS M1–M4 current temp, setpoint, relay state Always
INFO Left/Right DHT22 temperature and humidity When ENABLE_DHT22 1
ALARM Zones in alarm or sensor fail, alarm count since boot When any alarm is active

Pressing any button stops the auto-cycle. It resumes when returning to the home screen from the menu.


Alarms and safety

Temperature alarms

Each zone has a configurable low and high alarm threshold (set via Edit Temps in the menu). An alarm activates the first time the temperature crosses the threshold and clears automatically once the temperature returns to within range.

The alarm output pin blinks at 1 Hz whenever any alarm is active and goes off once all alarms clear.

Sensor averaging

Each zone maintains a circular buffer of the last SENSOR_AVG_SAMPLES (default 4) raw DS18B20 readings. The running average is what the PID and alarm logic act on, smoothing out occasional noisy samples. On sensor fail the buffer is cleared so stale readings cannot pollute the first good reading after recovery.

Sensor fail

If a DS18B20 sensor returns an error reading:

  • The relay for that zone is forced off immediately (no minimum time guard)
  • The PID integral is reset so it restarts cleanly when the sensor recovers
  • Any autotune running on that zone is aborted
  • A sensor-fail alarm is raised (counted in the boot total, shown on the ALARM screen as L1: SENSOR FAIL)

Watchdog

A hardware watchdog timer resets the MCU if the main loop stalls for more than 8 seconds (e.g. I²C lockup). On reset all relays are initialised off.

Relay minimum on/off time

Relays will not change state more often than once per MIN_RELAY_MS (default 1 second) to prevent chatter. Sensor-fail forces the relay off immediately, bypassing this guard.


Menu navigation

Press SELECT from the home screen to enter the menu.

[HOME — auto-cycles through active screens]
  UP/DOWN: manual screen select

SELECT → [ZONE SELECT]
           UP/DOWN: choose zone or "Tune All Zones"

           SELECT (on a zone) → [ZONE ACTION]
             > Edit Temps     → [ZONE EDIT — TEMPS]
                                 Setpoint / Alarm Lo / Alarm Hi
                                 UP/DN: adjust   SEL: next field / commit
                                 BACK: discard

             > Edit PID       → [ZONE EDIT — PID]
                                 Kp / Ki / Kd
                                 UP/DN: adjust   SEL: next field / commit
                                 BACK: discard

             > Start Autotune → [SINGLE-ZONE AUTOTUNE]
                                 Shows: temp, setpoint, cycles done, elapsed
                                 BACK: cancel
                                 SEL (when done): accept result

           SELECT (Tune All)  → [TUNE ALL — all 8 zones simultaneously]
                                 Grid: each zone shows cycles/DONE/FAIL
                                 BACK: cancel all
                                 SEL (when all done): accept successful results

Configuration reference (src/config.h)

All hardware pin assignments and tunable constants are in one file.

Pins

Constant Default Description
PIN_ONE_WIRE 2 DS18B20 1-Wire data pin
PIN_DHT_LEFT / PIN_DHT_RIGHT 3, 4 DHT22 data pins
PIN_BTN_UP/DOWN/SELECT/BACK 5–8 Button pins
PIN_ALARM 30 Alarm output pin
RELAY_PINS[8] 22–29 Relay output pins, zones L1–M4 in order
RELAY_ACTIVE_HIGH false Set true for active-HIGH relay modules
ALARM_ACTIVE_HIGH true Set false for active-LOW alarm hardware
LCD_I2C_ADDR 0x27 I²C address of the LCD
ZONE_ADDRS[8][8] all zeros DS18B20 addresses — fill in after first flash

Control

Constant Default Description
PID_WINDOW_MS 30000 Time-proportional relay window (ms)
MIN_RELAY_MS 1000 Minimum time a relay stays on or off (ms)
AUTOTUNE_CYCLES 5 Oscillation cycles averaged during autotune
AUTOTUNE_NOISEBAND 0.5 °C Relay hysteresis during autotune
DEFAULT_SETPOINT 28.0 °C Setpoint used before first EEPROM write
DEFAULT_KP/KI/KD 2.0 / 0.5 / 0.1 PID gains used before autotune
DEFAULT_ALARM_LOW 10.0 °C Alarm threshold — adjust per enclosure
DEFAULT_ALARM_HIGH 45.0 °C Alarm threshold — adjust per enclosure
SENSOR_AVG_SAMPLES 4 Readings averaged before feeding the PID (1 = no averaging)
DS18B20_POLL_MS 2000 Temperature reading interval (ms)

Display / UI

Constant Default Description
TEMP_UNIT_F 0 0 = Celsius, 1 = Fahrenheit (display only — PID stays in °C)
ENABLE_DHT22 1 0 = disable DHT22; removes INFO screen from rotation
HOME_CYCLE_MS 1000 Home screen auto-cycle interval (ms)
ALARM_BLINK_MS 500 Alarm pin half-period (500 ms on + 500 ms off = 1 Hz)
DISPLAY_REFRESH_MS 500 Live data refresh interval on home screens (ms)

Building and flashing

Requires PlatformIO.

# Build for hardware
pio run

# Flash
pio run --target upload

# Serial monitor (115200 baud — shows DS18B20 addresses on boot)
pio device monitor

# Run native unit tests (no hardware required)
pio test -e native

Project structure

src/
  config.h                 All pin assignments and tunable constants
  main.cpp                 Setup, main loop, watchdog
  sensors/
    ds18b20.h/cpp          Non-blocking 1-Wire reading + address scanner
    dht22.h/cpp            DHT22 humidity/temperature (optional, display only)
  control/
    pid.h/cpp              Discrete PID — derivative on measurement, anti-windup
    zone.h                 Zone data structure (PID, relay, alarms, sensor state)
    zone_manager.h/cpp     8-zone relay driver, PID orchestration, alarm checking,
                           sensor-fail safety, autotune routing, alarm pin blink
    autotune.h/cpp         Relay feedback autotuner (Åström-Hägglund method)
  storage/
    settings.h/cpp         EEPROM load/save — setpoints, PID gains, alarm thresholds
  ui/
    buttons.h/cpp          Debounced input with auto-repeat on UP/DOWN
    display.h/cpp          LCD screen rendering (all screens including alarm)
    menu.h/cpp             Menu state machine + home screen auto-cycle
test/
  mocks/                   Arduino library stubs for native builds
  test_pid/                9 PID unit tests
  test_menu/               24 menu state machine tests
  test_zone_manager/       23 zone manager tests (averaging, sensor fail, alarms, relay timing)
  test_settings/           7 EEPROM persistence tests

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages