1. Home
  2. Projects
  3. Lion’s mane fruiting chamber
Under development

Embedded · Control systems

Lion’s mane fruiting chamber

A sensor-driven fruiting chamber for growing lion’s mane mushrooms, using PID control to hold temperature, humidity, and CO₂ at the conditions the mushrooms need.

Role
Solo — electronics, firmware, build
Timeline
Fall 2026 – present
Tools
[ESP32], SHT31, MH-Z19E, PID control
Status
Under development
The mushroom fruiting chamber
[Photo of the chamber.]

Overview

This project is in progress. The sensors and most of the control hardware are in hand; the humidifier is next.

Lion’s mane is picky about where it fruits. It wants cool air, very high humidity, and fresh air with low CO₂. Miss any of those and you get small, dry, or oddly shaped fruiting bodies. Instead of misting by hand and hoping, I'm building a chamber that measures its own environment and corrects it continuously.

65 °Ftarget temperature
90%target relative humidity
650 ppmtarget CO₂

Hardware

PartRole
SHT31Temperature and humidity sensor (I²C)
MH-Z19ENDIR CO₂ sensor
128×32 I²C OLEDLive readout of all three conditions
Enclosed IoT relaySwitches the mains-powered humidifier safely
IRF3205 MOSFET Drives the 5 V fan for fresh-air exchange
5 V relay Switches the grow light
Blue COB LED stripGrow light; blue light helps trigger fruiting
HumidifierStill to buy

Control approach

Each condition has its own loop:

  • Humidity is the tightest target. A humidifier behind a relay can only be on or off, so the PID output is turned into a duty cycle over a fixed window (time-proportioning). If the controller asks for 30%, the humidifier runs 3 seconds out of every 10.
  • CO₂ is controlled by fresh-air exchange. When CO₂ rises above 650 ppm, the fan brings in outside air; the PID sets how hard it runs.
  • Temperature is monitored and displayed.
  • Light runs on a daily schedule.

The loops interact: running the fan to clear CO₂ also pulls out humid air. Tuning the humidity loop so it recovers quickly after each air exchange, without overshooting into condensation, is the main controls problem.

Code

A sketch of the time-proportioning PID planned for the humidifier.

chamber/humidity.cpp
// PID on relative humidity, converted to on/off time for a relay.
const float    RH_SETPOINT = 90.0f;   // percent
const uint32_t WINDOW_MS   = 10000;   // relay decision window
float kp = 8.0f, ki = 0.05f, kd = 0.0f;  // untuned starting guesses

float integral = 0, lastErr = 0;
uint32_t windowStart = 0, lastUpdate = 0;

float pidDuty(float rh) {
  uint32_t now = millis();
  float dt  = (now - lastUpdate) / 1000.0f;
  lastUpdate = now;
  float err = RH_SETPOINT - rh;
  integral  = constrain(integral + err * dt, -100.0f / ki, 100.0f / ki);
  float d   = dt > 0 ? (err - lastErr) / dt : 0;
  lastErr   = err;
  return constrain(kp * err + ki * integral + kd * d, 0.0f, 100.0f);
}

void updateHumidifier(float rh) {
  float duty = pidDuty(rh);                     // 0-100 %
  if (millis() - windowStart >= WINDOW_MS) windowStart = millis();
  bool on = (millis() - windowStart) < duty / 100.0f * WINDOW_MS;
  digitalWrite(HUMIDIFIER_RELAY_PIN, on ? HIGH : LOW);
}

Next steps

  • Buy and install the humidifier.
  • Tune the humidity and CO₂ loops against each other.
  • Log sensor data so I can plot how well the chamber holds its targets.
  • Grow the first flush and document the results here.