Terarii
MICROCOSM — Technical and Educational Plan
Project: MICROCOSM — nine student-built instrumented ecosystems at Ioanid school, Bucharest
Funder: ARCUB (approved equipment list, Annex 2) · Technical partner: Alacrity
Document: v1.0, 2026-10-20 · Status: proposal for discussion with the school and reconciliation with procurement
Replaces: "MICROCOSM — Alacrity Education, Ecosystems & Approved Technical Equipment" (5 pages, undated)
How to read this document: Chapter 0 is the two-page summary. Chapter 1 explains what was wrong with the proposal and what changed. Chapters 2–4 fix the platform every ecosystem shares. Chapter 5 is the core: one detailed design per ecosystem, written so that a team of students with a teacher-coach can build it. Chapter 6 is the priced budget and the line-by-line reconciliation with the approved list. Chapter 7 is the schedule to 2026-12-18 and beyond, the people, the workshops and the risks. Chapter 8 answers the proposal's open questions. Diagrams are in Mermaid and render on GitHub, GitLab, Obsidian, VS Code and most Markdown viewers.
0. Executive summary
Nine living, instrumented ecosystems on one shared platform (an ESP32 node per ecosystem running ESPHome, a Raspberry Pi 5 hub running Home Assistant on the school's existing Wi-Fi), each with a written science track (question, hypotheses, variables, controls, replication, analysis) and an engineering track (requirements, prototype, test, iterate), at least two weeks of data, one chart per team at the showcase, and a Time Capsule designed to run for ten years without depending on its electronics.
Safety is designed in. No student or teacher ever builds, wires or switches 230 V. Mains exists only inside certified products on a shelf, on RCD-protected strips, switched only through smart plugs. Everything in water, substrate or inside an enclosure is 12 V DC or less. Safety interlocks (heater cut-offs, pump limits, dry-run guards) live in the node firmware and in hardware thermal fuses, not in the hub.
Budget. The recommended plan costs about 20 989 RON (4 115 EUR) for equipment, enclosures, hub, network and biology, or 24 137 RON with a 15 % contingency. Of this, about 7 263 RON is biology, substrates and consumables that the proposal did not budget at all, and about 961 RON is the hub and network it did not list. The approved list, priced as written, would have cost about 8 500 RON and would not have produced a working project.
| Group | RON | EUR |
|---|---|---|
| A. Controllers and sensors | 4 615 | 905 |
| B. Automation and power | 4 064 | 797 |
| C. Enclosures and construction | 4 086 | 801 |
| D. Hub and network | 961 | 188 |
| E. Biology and consumables per ecosystem | 7 263 | 1 424 |
| Total (recommended) | 20 989 | 4 115 |
| Total with 15 % contingency | 24 137 | 4 733 |
Schedule. Orders go out 2026-10-21 to 10-23. Hub and standard node are built during the autumn break. Teams assemble nodes 2026-11-10, enclosures 11-09 to 11-20, biology is established by 11-20 to 12-04, treatments run 12-01 to 12-18, Time Capsule is built 12-01 to 12-11, showcase 12-15 to 12-17, ARCUB report 12-18. The interesting biology (decomposition, blooms, restoration, harvests) is expected January to June 2027; the plan schedules those rounds too.
1. Review of the current proposal
The proposal ("MICROCOSM — Alacrity Education, Ecosystems & Approved Technical Equipment", 5 pages) has a good skeleton: nine distinct ecosystems, a clear science/engineering split per ecosystem, a paired 2026/2056 experiment, a ten-year Time Capsule, and the right priority (educational outcomes before scientific results). Everything below the skeleton is missing or inconsistent. The equipment list reads as a generic "IoT terrarium" shopping list that was never checked against the nine ecosystems it is supposed to serve.
1.1 What is sound and is kept
| Kept from the proposal | Why |
|---|---|
| Nine ecosystems with the stated themes | Diverse, teachable, and each maps to a real scientific method |
| One ESP32 per ecosystem, 12 boards (9 + 3 spares) | Correct choice and correct quantity |
| DS18B20 waterproof probes, BH1750 lux sensors, SSD1306 OLEDs | Cheap, robust, well supported |
| "Real CO2" sensors (NDIR) rather than eCO2 estimates | Correct instinct; quantity and placement fixed below |
| Capacitive (not resistive) soil moisture probes | Correct type; the specific v2.0 board needs mitigation |
| 2026 vs 2056 as a matched pair | The only ecosystem in the proposal with a built-in control |
| Time Capsule as a collaborative, decade-long closing project | Strong idea; it only needs a design that survives without electronics |
| "Educational outcomes are more important than scientific results" | Drives every simplification in this plan |
1.2 Structural problems
| # | Problem | Consequence |
|---|---|---|
| S1 | No prices anywhere. The "approved budget" is a quantity list. | Nobody can tell whether the project is affordable or where the money goes. Chapter 6 supplies a full priced BOM. |
| S2 | No schedule. The ARCUB year ends in December; biology needs weeks to show anything. | Without a plan, biology starts too late and the showcase shows empty tanks. Chapter 7 supplies a week-by-week schedule; biology must be established by 2026-11-20. |
| S3 | No science design. Each ecosystem says "investigate X" with no question, hypothesis, variables, control or replication. | Students would collect data with no way to interpret it. Every ecosystem section now has a Science track with hypotheses, variables, controls, replication and analysis. |
| S4 | No safety content at all. Relays, pumps, misters, heaters and water in a classroom, and the word "safety" does not appear. | Chapter 2 sets hard rules: mains only inside certified COTS products, 12 V DC maximum in or near water, no student-built mains wiring. |
| S5 | No biology budget. Not one plant, seed, organism, substrate or nutrient is listed. | The living part of nine living systems was unfunded. Chapter 6 adds a biology and consumables budget per ecosystem. |
| S6 | No hub. A "microSD card for Raspberry Pi" is listed; the Raspberry Pi, its power supply and case are not. | Nine loggers with no dashboard, no alerts, no shared dataset. Chapter 3 defines the hub on the school's existing Wi-Fi. |
| S7 | Ten-year requirement has no design consequence. | The Time Capsule section now designs for longevity: sealed glass, external sensor pod, light independent of the hub, a maintenance calendar and a data custody plan. |
| S8 | Items are listed per "ecosystem count", not per need. 9 BME680, 9 DS18B20, 9 BH1750, 9 SD modules, 9 cards. | The hydroponics unit gets a soil probe it cannot use and the EcoColumn gets one water sensor where it needs five. Chapter 4 allocates by need. |
1.3 Component-level problems
| # | Item in proposal | Problem | Fix in this plan |
|---|---|---|---|
| C1 | BME680 ×9 "temperature/humidity/VOC" | The gas output is a resistance proxy for VOCs, not CO2. The humidity element drifts and saturates in closed terrariums at >90 % RH. Over-specified and wrong tool for 7 of 9 ecosystems. | 2× BME680 (both in Rot, before and after the carbon filter, where "smell" is the science); 8× SHT31 with PTFE membrane for all other air T/RH. |
| C2 | CO2 breakouts ×3, type unspecified | Four ecosystems need real CO2 (Rot, Living Earth, 2026, 2056) and the paired experiment needs two identical sensors. | 4× Sensirion SCD41 (NDIR, I2C, also T/RH): Rot, Living Earth, 2026, 2056. The Time Capsule's sensor is deferred to 2027 as a cost cut. Automatic self-calibration must be disabled in sealed tanks. |
| C3 | Capacitive soil probes v2 ×12 | Known batch defects (wrong timer IC on clones), unsealed top edge corrodes, output depends on substrate, needs per-probe calibration. 12 is too few for replicated plots. | 22 probes (TL555 version), conformal-coated, two-point calibrated per probe per substrate. |
| C4 | Water-level sensors ×3, type unspecified | A float gives one bit; a level gives a curve. Both are needed in different places. | 10× float switches (low/high per reservoir, 2 spare) + 2× JSN-SR04T waterproof ultrasonic for continuous level (EcoColumn pond, hydroponics reservoir). |
| C5 | Water-flow sensors ×2, type unspecified | The usual YF-S201 starts reading at 1 L/min; the 12 V pumps in this project deliver 0.2–0.4 L/min through a rain bar. | YF-S401 (0.3–6 L/min). Even so, rain-event volume is better computed from pump run time and a one-off calibration. |
| C6 | pH/EC calibration solutions listed, no pH/EC probes | Solutions without probes. | 2× analog pH kits (Hydroponics, EcoColumn pond), 1× TDS module (Hydroponics), 2× handheld pH pens, 2× TDS pens for soil-extract measurements in every ecosystem. |
| C7 | No turbidity sensor | The EcoColumn science is literally sediment transport and algal blooms. | 2× analog turbidity modules (one in the pond, one bench probe for runoff and jar samples). |
| C8 | Relay modules ×4 | In a school, a bare relay module invites switching 230 V. | 6 relay modules, only for low-voltage loads (24 V misters, probe power selection, LED fail-safe path). Mains switched only through 2 certified smart plugs. |
| C9 | Grow lights ×4 at 5–10 W | 5–10 W lights a 12 L tank; the hydroponics unit alone needs 30–45 W; seven ecosystems have plants and Bucharest classrooms in November–February have almost no usable daylight. | 4× 5 m reels of 12 V LED strip (4000 K white COB, in stock in Romania; full-spectrum from AliExpress as an option) in 16 aluminium profiles (cut to length, PWM-dimmable, SELV) for eight enclosures + 1× COTS 230 V 36 W panel for hydroponics only. |
| C10 | Power supplies ×4 | Nine nodes, five pumps, six fans, three heat pads, ten metres of LED strip and a Raspberry Pi cannot run on four adapters. | 9× 12 V 5 A certified bricks + 2× 5 V USB adapters + 10 buck modules + Pi PSU. |
| C11 | "Heating" in the 2056 automation, no heater listed | The treatment that defines the experiment has no hardware. | 4× 12 V silicone heat pads (10–25 W: 2056, 2026 for identical hardware, Brownfield, 1 spare) with DS18B20 thermostat loop, 45 °C thermostat and one-shot thermal fuse. |
| C12 | Peristaltic pumps ×2, no sensing | Dosing without pH/EC feedback is dosing blind. | 3 (hydroponics nutrient A, B and pH-down) with the pH/TDS kit, dose caps and daily pen cross-checks. |
| C13 | Ultrasonic misters ×2 | Most COTS mist modules run on 24 V DC and need their own adapter. | Kept at 2, each with its own 24 V adapter, switched through a relay module (low voltage). |
| C14 | Hydroponics: no air pump, no media, no nutrients | A "hydroponic jungle" without aeration or nutrient solution does not grow. | 1× COTS 230 V aquarium air pump (shelf-mounted, air line only in water) + nutrients, plugs, net pots. |
| C15 | microSD modules ×9 + cards ×9 + RTC ×2 | Nine loggers but two clocks: seven loggers would write timestamps from a reset counter. | Hub logging is primary. Local SD + RTC only on the Time Capsule node and two advanced spare boards (3 sets). |
| C16 | OLED ×12 | Fine. | Kept. |
| C17 | "Glass-panel construction packs" ×9 | Undefined item; implies students cutting and gluing float glass: cut hazards, leaks, lost weeks. COTS aquariums are leak-tested and cost about the same. | 8 COTS glass aquariums (1× 25 L, 3× 45 L, 4× 54 L) plus the hydroponics unit in an opaque food-grade box. Students design and build lids, vents, mounts, dividers and internal structures from polycarbonate and acrylic (6 panels of 50×100 cm, approved 3), mesh, hinges, PVC and silicone. |
| C18 | Electronics cases ×6 | Nine nodes need nine boxes plus one for the hub. | 9× IP65 junction boxes with 80 cable glands (approved 20). |
| C19 | SG90 servos ×4, no stated use | Harmless; a use is now defined (EcoColumn rain gate, Living Earth chamber lid, vents). | 8 (Rot intake flap, EcoColumn rain valve, 2026 and 2056 CO2 and vent gates, Living Earth lid, 1 spare). |
| C20 | Fans ×4 | Six enclosures need ventilation control. | 6× 12 V 80 mm PC fans. |
| C21 | Water reservoirs ×4, "sprayers, nozzles" | Fine as a lot, but needs sizes and food-grade material. | 5× 10–20 L food-grade containers with lids + 3 opaque storage boxes. |
| C22 | Nothing about the network | ESP32 joins only 2.4 GHz WPA2-PSK networks; school Wi-Fi is often enterprise-only or captive-portal. | Use the existing school Wi-Fi: ask IT for a 2.4 GHz WPA2-PSK SSID with 12 DHCP reservations and the Pi reachable from student devices. A fallback router (≈ 160 RON) is listed as optional, not bought. |
| C23 | Nothing for electrical protection | Water and 230 V adapters on the same bench. | 2× RCD (30 mA) adapters, one per shelf power group. |
1.4 Net effect of the fixes
The nine ecosystems keep their identity. The equipment list changes in three directions: fewer of the wrong sensors (BME680, SD modules), more of the cheap right ones (soil probes, DS18B20, floats, LED strip), and the addition of everything the proposal forgot (hub, network, power, protection, heaters, air pumps, enclosures as COTS tanks, and the entire biology budget). The full reconciliation, line by line against the approved list, is in Chapter 6.
2. Design principles and hard rules
Every decision in this plan follows from seven rules. Where a later chapter deviates, it says so and why.
2.1 Hard safety rules (non-negotiable)
- Mains (230 V AC) is never built, wired, modified or switched by students or teachers. All 230 V exists only inside certified COTS products with their own cord and plug: 12 V power bricks, the Raspberry Pi power supply, the hydroponics LED panel, the aquarium air pumps, the mister adapters.
- Nothing mains-powered is ever inside an enclosure, in water, or in substrate. Everything that touches water, substrate or the inside of an enclosure is SELV: sensors at 3.3 V or 5 V; pumps, fans, LED strips and heat pads at 12 V DC; misters at 24 V DC from their own adapter.
- Mains devices live on the shelf or wall, above and away from water, with a drip loop on every cable, on an RCD-protected (30 mA) power strip. Mains is switched only through certified COTS smart plugs, never through relay modules.
- Node boxes mount outside the enclosure, above the water line. Cables enter through glands. Every 12 V brick is a certified adapter.
- Simulated contamination only. Salinity is table salt, pH is vinegar or baking soda, disturbance is compaction, paving and heat. No heavy metals, no real pollutants, no vertebrates, no toxic plants. Gloves for soil and compost work, FFP2 masks when sieving mineral dust.
2.2 Engineering principles
- COTS first. Complete, cased, cabled modules over loose parts: waterproof DS18B20, cased SHT31, Gravity-style sensors with cables, pre-made MOSFET and buck modules, ESP32 screw-terminal breakouts, pre-crimped cables, COTS glass aquariums, COTS pumps, COTS LED strips and profiles, COTS smart plugs, COTS junction boxes. Breadboards are for the 3.3 V / 5 V sensor side during prototyping only. Final assemblies use screw terminals or JST connectors, with no loose jumper wires.
- Safety logic lives in the node, not in the hub. Heat-pad cut-offs, pump run-time limits and reservoir-low interlocks are implemented in ESPHome firmware on the ESP32 and backed by hardware thermal fuses. Home Assistant adds schedules, dashboards and alerts on top, so a hub outage never creates a hazard.
- One platform, nine configurations. Every node is the same box, same pin map, same base firmware. A team configures, it does not re-invent. Spare nodes are interchangeable with any ecosystem.
- Education before results. A well-documented failed experiment is a full success. Each ecosystem has a Science track (question, hypothesis, variables, control, replication, analysis) and an Engineering track (requirements, prototype, test, iterate). Adults set up the mains side and cut glass; students do everything else.
- Design for December first, for spring second, for 2036 last. By 2026-12-18 all nine ecosystems must be alive, instrumented and reporting with at least two weeks of data. The interesting biology (decomposition, blooms, restoration, harvests) is expected in January–June 2027. The Time Capsule is designed so that the living system never depends on the electronics.
2.3 Fixed platform decisions
| Decision | Choice | Rationale |
|---|---|---|
| Controller | ESP32-WROOM-32 DevKitC, 38-pin, one per ecosystem, 3 spares | Approved quantity; Wi-Fi, enough ADC1 pins, ESPHome support |
| Firmware | ESPHome (YAML) | No code needed for the base; OTA updates; students extend by editing YAML; advanced track can use Arduino on spare boards |
| Hub | Raspberry Pi 5 (4 GB), Home Assistant OS, add-ons: ESPHome, Mosquitto, InfluxDB, Grafana | Turnkey dashboards, automations, alerts, long-term storage, CSV export |
| Network | The school's existing Wi-Fi: a 2.4 GHz WPA2-PSK SSID for the project, 12 DHCP reservations, Pi on Ethernet or Wi-Fi | No new hardware; ESP32 needs 2.4 GHz PSK; a 160 RON fallback router is listed as optional if IT cannot provide this |
| Sampling | Every sensor every 60 s; soil moisture averaged over 10 samples | Enough for daily cycles; small dataset (about 1.5 million rows per year for all nodes) |
| Time | NTP from the hub; DS3231 RTC + microSD only on the Time Capsule node and two advanced spare boards | Hub logging is primary; local logging where independence matters |
| Power | 12 V 5 A certified brick per automated node, LM2596 buck to 5 V for the ESP32; 5 V USB adapter for passive nodes | Single SELV rail per ecosystem; all actuators 12 V |
| Switching | D4184-type MOSFET modules for 12 V PWM loads; relay modules for 24 V misters only; smart plugs for mains | Rule 1 and 3 |
| Enclosures | COTS glass aquariums (12, 25, 45, 63 L); students build lids, vents, dividers, mounts | Leak-tested, cheap, safe; the engineering is in the lids and internals |
| Naming | Nodes mc-01-rot … mc-09-capsule; entities <node>_<quantity>_<position> |
One convention for dashboards, CSV columns and lab notebooks |
2.4 Standard pin map
Every node uses the same map, so any node YAML differs only in which packages are enabled and which setpoints apply.
| Function | GPIO | Notes |
|---|---|---|
| I2C SDA / SCL | 21 / 22 | SHT31 0x44, SCD41 0x62, BH1750 0x23, BME680 0x76 or 0x77, SSD1306 0x3C |
| 1-Wire bus (DS18B20) | 4 | 4.7 kΩ pull-up to 3.3 V; several probes on one bus |
| Analog A–D (soil moisture) | 32, 33, 34, 35 | ADC1 only (ADC2 is unusable while Wi-Fi is on); 34 and 35 are input-only |
| Analog E / F (pH, TDS boards) | 36, 39 | Input-only, 11 dB attenuation |
| PWM out 1–4 (MOSFET modules) | 16, 17, 18, 19 | Light, fan, pump, heater or mister, always in this order |
| Relay 1–2 | 23, 25 | Low-voltage loads only |
| Servo 1–2 | 26, 27 | SG90 at 50 Hz |
| Digital in 1–2 (float switches) | 13, 14 | Internal pull-up, switch to GND |
| Pulse counter (flow sensor) | 5 | YF-S401 signal through a level check or divider |
| Ultrasonic TRIG / ECHO | 15 / 12 | JSN-SR04T; ECHO through a 1 kΩ / 2 kΩ divider |
| Reserved | 0, 2 | Boot button, onboard LED |
3. Common platform
Architecture overview
Nine identical ESP32 nodes ("MICROCOSM node v1") talk over the project's own 2.4 GHz Wi-Fi to one Raspberry Pi 5 running Home Assistant OS (HAOS). The Pi stores the data, serves the dashboards and builds/flashes the firmware. The school network is optional: it gives Internet for NTP, remote access and off-site backup, and the lab keeps working without it.
flowchart LR
subgraph NODES["9 ESP32 nodes - ESPHome - Wi-Fi 2.4 GHz"]
N1["mc-01-rot"]
N2["mc-02-ecocolumn"]
N3["mc-03-brownfield"]
N4["mc-04-future2026"]
N5["mc-05-future2056"]
N6["mc-06-regolith"]
N7["mc-07-hydro"]
N8["mc-08-soil"]
N9["mc-09-capsule"]
end
SP["Smart plugs - hydro LED panel, air pump"]
R["School Wi-Fi - 2.4 GHz WPA2-PSK SSID for the project"]
subgraph PI["Raspberry Pi 5 - Home Assistant OS - 192.168.50.10"]
HA["HA Core - recorder SQLite 30 d"]
EH["ESPHome Device Builder"]
MQ["Mosquitto MQTT"]
IDB["InfluxDB 1.8 - keep forever"]
GF["Grafana"]
end
C["Student laptops and phones on MICROCOSM Wi-Fi"]
W["School network and Internet"]
X["NTP - Tailscale or Nabu Casa - Google Drive backup"]
N1 & N2 & N3 & N4 & N5 & N6 & N7 & N8 & N9 -->|"native API"| R
SP -->|"API or MQTT"| R
R ---|"Ethernet"| PI
HA --> IDB
IDB --> GF
EH -->|"OTA firmware"| R
MQ -.->|"advanced track"| R
C -->|"HA and Grafana dashboards"| R
R -->|"WAN optional"| W
W --> X
One measurement, end to end:
sequenceDiagram
participant S as Sensor (SHT31)
participant E as ESPHome node
participant H as HA Core
participant R as Recorder (SQLite)
participant I as InfluxDB
participant G as Grafana or CSV export
E->>S: I2C read every 60 s
S-->>E: raw temperature and RH
E->>E: filters - average, calibrate_linear, range check
E->>H: native API push (Noise-encrypted protobuf)
H->>R: state row, purged after 30 days
H->>I: point - measurement = unit, tag entity_id, field value
G->>I: InfluxQL query per node
I-->>G: time series to panel, CSV download or nightly file
Why the ESPHome native API for the base, not raw MQTT
| Need | Native API | Raw MQTT |
|---|---|---|
| Entities appear in HA with name, unit, device class | automatic | needs a discovery payload per entity |
| Firmware update | OTA from the ESPHome dashboard, one click | separate OTA mechanism |
| Students write code | no; YAML only | topic design, payloads, retained flags |
| Time sync, HA → node actions (buttons, numbers) | built in | hand-built topics |
| Security | per-node 32-byte encryption key | broker users + ACLs, TLS rarely used |
| Broker outage risk | none (no broker) | Mosquitto is a single point of failure |
Mosquitto stays installed for three uses: (1) the advanced track (Arduino/PlatformIO on the spare boards with PubSubClient, topics microcosm/<node>/<quantity>, HA MQTT discovery as a learning task); (2) Tasmota-flashed smart plugs, if those are bought instead of ESPHome-flashable ones; (3) third-party devices. ESPHome nodes may also add an mqtt: block as an Engineering-track exercise. The base firmware does not depend on it.
The standard node ("MICROCOSM node v1")
Specification
| Item | Spec |
|---|---|
| Controller | ESP32 ESP32-WROOM-32 DevKitC, 38-pin, plugged into a TERMBOARD 38-pin screw-terminal breakout. Buy the breakout for the same pin-row width as the DevKitC (25.4 mm, i.e. "1 inch", is the common one). Check this before ordering 12 of each. |
| Enclosure | BOX IP65 ABS, ≈150×110×70 mm, clear or grey lid (OLED behind a clear lid or a 30×15 mm acrylic window siliconed in), on a 3 mm acrylic back plate with M3 nylon standoffs. Mounted outside the ecosystem enclosure, above the highest water level, glands facing down. |
| Cable entry | 6× GLAND (4× PG7 for 3–6.5 mm sensor cables, 2× PG9 for 4–8 mm 12 V load cables). Unused glands are closed with a blank or a short rod. |
| Power in | PSU12 certified 12 V 5 A desktop brick → 5.5/2.1 mm DC jack (centre +) on the box → inline 5 A blade fuse → 12 V terminal bus. |
| Logic power | BUCK LM2596, set to 5.1 V before anything is connected → TERMBOARD 5V/VIN terminal. Do not feed 12 V into the breakout's own DC jack: it uses an AMS1117 linear regulator that dissipates ≈2 W at 12 V and overheats. Nodes without 12 V loads (spares, bench) use PSU5 into the DevKitC USB. |
| 12 V loads | MOSFET single-channel PWM modules, D4184 (AOD4184A) type only. IRF520 modules are not logic-level and only half-switch on at 3.3 V gate drive. One module per load, GPIO 16/17/18/19. Schottky diode (SS34/1N5819) across every motor/pump/fan terminal if the module has none. |
| Isolated LV loads | RELAY (GPIO 23/25), 3.3 V-trigger compatible, only for the 24 V mister. Never mains. |
| I2C | GPIO21 SDA / GPIO22 SCL, 3.3 V, 100 kHz. Each breakout carries its own 4.7–10 kΩ pull-ups; up to 5 boards in parallel (≈2 kΩ) is fine. With more boards, remove pull-up resistors from the extras. Total bus cable < 1 m. Above 50 cm, use twisted pairs (SDA twisted with GND, SCL twisted with 3.3 V) or shielded cable and drop to 50 kHz. Otherwise, put the I2C sensors close to the box (box on the enclosure side wall, sensors through the lid, ≤ 40 cm). |
| 1-Wire | GPIO4, 4.7 kΩ pull-up to 3.3 V (2.2 kΩ if total cable > 5 m). Daisy-chain or short star (≤ 3 probes × 1 m stock cables). Fine to 5–10 m total. Every probe is labelled with the last 4 hex digits of its ROM address. |
| Analog | ADC1 only: GPIO32–35 (soil A–D), GPIO36/39 (pH/TDS). Attenuation 12 dB (formerly called "11 dB"): usable ≈0.15–3.1 V. 10-sample average per reported value. ADC2 pins are unusable while Wi-Fi is on. |
| 5 V signals | ESP32 GPIOs are not 5 V tolerant. JSN-SR04T ECHO → 1 kΩ series / 2 kΩ to GND (5 V → 3.33 V). YF-S401 signal → 10 kΩ / 20 kΩ. Analog boards: power the Gravity pH/TDS boards at 3.3 V (output ≤ 3.0 V). A PH-4502C at 5 V can output > 3.3 V, so give it a 10k/20k divider or use the Gravity pH v2 instead. Soil probes v2.0 are powered at 3.3 V (output ≈1.1–2.7 V). |
| Strapping pins | GPIO12 (ECHO) must be low at boot. The 2 kΩ to GND guarantees this; never add a pull-up there. GPIO0/2 are kept free. GPIO5/15 are fine as wired. |
| Display | OLED SSD1306 0.96" I2C 0x3C, shows node name, Wi-Fi/HA status + RSSI, air T/RH, two team-selected values. |
Power budget (worst case per node)
| Load | Rail | Typical | Peak | At 12 V input (peak) |
|---|---|---|---|---|
| ESP32 (Wi-Fi TX) | 5 V → 3.3 V | 80 mA | 250 mA | 0.13 A |
| SCD41 (during measurement) | 3.3 V | 15 mA | 200 mA | 0.10 A |
| OLED + SHT31 + BH1750 + 3 DS18B20 + 4 soil probes | 3.3 V | 40 mA | 50 mA | 0.03 A |
| JSN-SR04T + YF-S401 | 5 V | 35 mA | 50 mA | 0.03 A |
| 2× SG90 servo | 5 V | 10 mA | 1.2 A (stall) | 0.60 A |
| LED strip, 1.2 m full-spectrum (≈12 W/m) | 12 V PWM | 0.8 A | 1.2 A | 1.20 A |
| 80 mm fan | 12 V PWM | 0.10 A | 0.20 A | 0.20 A |
| Submersible pump 3–5 W | 12 V PWM | 0.30 A | 0.45 A | 0.45 A |
| Heat pad 20 W | 12 V on/off | 0–1.7 A | 1.7 A | 1.70 A |
| Total (Future 2056, the heaviest node) | ≈4.4 A worst case, ≈3.2 A realistic |
Rules: the 5 V rail via the LM2596 stays ≤ 2 A (no heatsink), so at most 2 servos per node. The sum of 12 V loads that can be on at the same time is ≤ 4 A (80 % of the 5 A brick). If a node exceeds this (e.g. a 25 W pad plus 2 m of LED), split it: the LED strip gets its own PSU12, with grounds joined at the box. Misters run from their own 24 V adapter through the relay. Wire: 0.75 mm² for the 12 V input, 0.5 mm² for 12 V loads ≤ 2 A, 0.25 mm² (stock sensor leads) for signals.
Block / wiring diagram
flowchart TB
PSU["PSU12 brick 12 V 5 A - 230 V side on the RCD shelf"] -->|"P1 DC jack 5.5/2.1, centre +"| F
subgraph BOX["IP65 node box - outside the enclosure, above water line, glands down"]
F["Inline fuse 5 A"] --> B12["12 V terminal bus + GND bus"]
B12 --> BK["LM2596 set to 5.1 V"]
BK -->|"5 V to VIN"| ESP["ESP32 DevKitC on TERMBOARD"]
ESP -->|"3.3 V"| BUS["I2C GPIO21/22 and 1-Wire GPIO4 with 4.7k"]
OLED["OLED 0x3C behind lid window"]
DIV["Dividers - 1k/2k ECHO, 10k/20k flow"]
M1["MOSFET 1 - GPIO16"]
M2["MOSFET 2 - GPIO17"]
M3["MOSFET 3 - GPIO18"]
M4["MOSFET 4 - GPIO19"]
RL["Relay 1/2 - GPIO23/25"]
B12 --> M1
B12 --> M2
B12 --> M3
B12 --> M4
ESP --> M1
ESP --> M2
ESP --> M3
ESP --> M4
ESP --> RL
ESP --> DIV
end
BUS --> OLED
BUS -->|"S1 JST-XH 4p"| I2CS["SHT31 / SCD41 / BH1750 / BME680"]
BUS -->|"S2 JST-XH 3p"| DS["DS18B20 probes"]
ESP -->|"S3-S6 JST-XH 3p, GPIO32-35"| SOIL["Soil probes A-D"]
ESP -->|"S7 JST-XH 3p, GPIO36/39"| AN["pH / TDS boards"]
ESP -->|"S8 JST-XH 2p, GPIO13/14"| FL["Float switches"]
DIV -->|"S9 JST-XH 4p"| JSN["JSN-SR04T level"]
DIV -->|"S10 JST-XH 3p"| FLOW["YF-S401 flow"]
ESP -->|"S11/S12 JST-XH 3p, GPIO26/27"| SV["SG90 servos"]
M1 -->|"A1 screw terminal"| LED["12 V LED strip in profile"]
M2 -->|"A2"| FAN["12 V fan"]
M3 -->|"A3"| PUMP["12 V pump"]
M4 -->|"A4, via 72 C thermal fuse"| HEAT["12 V heat pad"]
RL -->|"A5"| MIST["24 V mister - own adapter"]
Connectors, colours, labels
| Port | Connector | Pin order (pin 1 = marked side) | Use |
|---|---|---|---|
| P1 | 5.5/2.1 mm DC jack, panel mount | centre +12 V | power in |
| S1 | JST-XH 2.54, 4-pin | GND, 3.3 V, SDA, SCL | I2C sensor (daisy-chain via a 4-way JST hub board or a terminal block) |
| S2 | JST-XH 3-pin | GND, 3.3 V, DATA | 1-Wire (DS18B20) |
| S3–S7 | JST-XH 3-pin | GND, 3.3 V, SIG | analog: soil A–D, pH, TDS |
| S8 | JST-XH 2-pin ×2 | GND, SIG | float low / float high |
| S9 | JST-XH 4-pin | GND, 5 V, TRIG, ECHO | JSN-SR04T |
| S10–S12 | JST-XH 3-pin | GND, 5 V, SIG | flow sensor, servos |
| A1–A4 | 2-way screw terminal on the MOSFET module (+12 V, LOAD−) | + then − | 12 V PWM loads |
| A5 | relay COM/NO screw terminal | — | 24 V mister loop |
Wire colours (all nodes, all harnesses): red = 12 V, black = GND, orange = 5 V, yellow = 3.3 V, blue = signal (second signal in the same cable: green, e.g. SCL). Loads switched by a MOSFET: red to +12 V, black to LOAD−; the load's black wire is never connected to the GND bus directly.
Labels: printed heat-shrink or flag labels at both ends of every cable, format <node#>-<port> <device> <position>, e.g. 04-S3 SOIL A, 04-A3 PUMP. The box lid carries a port map sticker (copy of the table above with the node's actual devices) and the node name + IP.
BOM for one node (Future 2026 example, 3 PWM loads)
| ID | Qty | Est. RON each | RON | Basis |
|---|---|---|---|---|
| ESP32 | 1 | 43 | 43 | sigmanortec.ro ESP32-DevKitC 38P, 42.56 RON (checked 2026-10) |
| TERMBOARD | 1 | 30 | 30 | optimusdigital/emag "ESP32 38P expansion board", estimate |
| BOX | 1 | 35 | 35 | dedeman/emag IP65 150×110×70, estimate |
| GLAND | 6 | 2 | 12 | PG7/PG9 nylon, bag price |
| BUCK | 1 | 10 | 10 | emag LM2596 module 6–15 RON (checked) |
| MOSFET | 3 | 15 | 45 | D4184 module ≈ €3.20 (checked, ebay.de); RO shops similar |
| OLED | 1 | 20 | 20 | SSD1306 0.96" I2C, estimate |
| PSU12 | 1 | 60 | 60 | 12 V 5 A brick + DC jack, emag, estimate |
| Free: node cable kit | 1 | 40 | 40 | JST-XH pre-crimped pigtails 2/3/4-pin, 0.5/0.75 mm² red/black, ferrules, heat-shrink |
| Free: inline fuse holder + 5 A fuse | 1 | 8 | 8 | auto blade type |
| Free: backplate, M3 nylon standoffs, dividers (1k/2k, 10k/20k), SS34 diodes, labels | 1 | 15 | 15 | consumables |
| Node core total | 318 (≈ €62) | sensors and actuators are in the ecosystem chapters |
Assembly session (one team, 90 min, checklist)
Prerequisites (done by Alacrity/teacher beforehand): kits bagged per node; glands holes pre-marked from a paper template; firmware compiled and flashed once via USB to each ESP32 (so on the day the board only needs OTA); multimeter per team.
| Time | Step | Done |
|---|---|---|
| 0–10 | Check the bag against the BOM; write the node name on the box with a marker; photograph the parts. | ☐ |
| 10–20 | Drill gland holes with a step drill (PG7 = 12.5 mm, PG9 = 15.5 mm), all on the bottom face. Wear goggles, box clamped. Fit glands. | ☐ |
| 20–30 | Mount backplate: TERMBOARD (without the ESP32), buck, MOSFET modules, fuse holder, terminal bus. Nothing powered. | ☐ |
| 30–40 | Set the buck: brick → jack → fuse → buck input only. Turn the trimmer until the output reads 5.05–5.15 V. Unplug. | ☐ |
| 40–55 | Wire 12 V bus → MOSFET V+, buck → TERMBOARD 5V/VIN, GND star, MOSFET signal inputs → GPIO16/17/18/19, using ferrules in all screw terminals. | ☐ |
| 55–70 | Fit the sensor harness: JST-XH tails to TERMBOARD terminals per the port table. Fit dividers on the ECHO/flow lines if used. Fit labels at both ends. | ☐ |
| 70–80 | Run the QA checklist below. Then insert the ESP32 (USB port towards the lid opening), power on, and check that the OLED shows the node name and "HA ok". | ☐ |
| 80–90 | Connect each actuator and dry-run it from the HA page. Close the lid, tighten glands (pull test), take a photo of the inside for the logbook, sign the QA sheet. | ☐ |
QA checklist (before the ESP32 goes in, then with it)
| # | Test | Pass criterion | Result |
|---|---|---|---|
| 1 | Continuity/short, unpowered: 12V↔GND, 5V↔GND, 3V3↔GND | > 1 kΩ (no short) | |
| 2 | Brick polarity at the jack terminals | +12.0–12.6 V on red | |
| 3 | Buck output, no load | 5.05–5.15 V | |
| 4 | 5 V at TERMBOARD VIN, ESP32 not inserted | 5.0–5.15 V, 3.3 V absent | |
| 5 | ESP32 inserted, 3.3 V rail | 3.25–3.35 V | |
| 6 | Smoke test: 60 s powered, hand above parts | no heat, smell or noise; buck and AMS1117 lukewarm only | |
| 7 | OLED | node name + "HA ok" + RSSI | |
| 8 | ESPHome log I2C scan | expected addresses only (0x3C, 0x44, 0x62, 0x23, 0x76/77) | |
| 9 | 1-Wire | expected number of ROM addresses found | |
| 10 | Each MOSFET channel 0 → 100 % with its real load | load follows, module < 40 °C after 5 min at 100 % | |
| 11 | Gland pull test | cable does not move with a 2 kg pull | |
| 12 | Labels both ends, port sticker, photo in logbook | present |
Hard safety rules restated for the node
- The node and everything connected to it is SELV ≤ 12 V DC (24 V for the mister loop only). No mains conductor ever enters a node box.
- 230 V exists only inside certified bricks/adapters, the Pi PSU, the COTS LED panel and the air pump, all plugged into the RCD-protected strip on the shelf. Mains loads are switched only by certified smart plugs, never by a relay module.
- The box hangs outside the enclosure, above the water line, glands down, with a drip loop on every cable.
- The heat pad is wired through MOSFET 4 and a 72 °C thermal fuse taped to the pad, and its firmware interlock is enabled (see Firmware).
- Unplug the brick before opening the box or (dis)connecting anything.
Firmware (ESPHome)
File layout (in /config/esphome/ on the Pi, edited from the ESPHome Device Builder or Studio Code Server)
/config/esphome/
secrets.yaml # Wi-Fi, OTA, one API key per node; admin-only
mc-01-rot.yaml ... mc-09-capsule.yaml # one ~25-line file per node, owned by the team
common/
mc-base.yaml # Wi-Fi, API, OTA, time, I2C, 1-Wire, OLED, diagnostics
sens-sht31.yaml sens-bme680.yaml sens-scd41.yaml sens-bh1750.yaml
sens-ds18b20.yaml # vars: sid, label, addr, offset (one include per probe)
sens-soil.yaml # vars: pos, pin, dry_v, wet_v (one include per probe)
sens-analog.yaml # vars: aid, pin, label, unit, v1, y1, v2, y2 (pH, TDS)
act-light.yaml # PWM1 GPIO16 + local photoperiod
act-fan.yaml # PWM2 GPIO17
act-pump.yaml # vars: pid, pin, label, max_s (PWM3 GPIO18 by default)
act-heater.yaml # PWM4 GPIO19 + thermostat + latched interlock
act-relay.yaml # vars: rid, pin, label, max_s (GPIO23/25)
act-servo.yaml # vars: sid, pin, label (GPIO26/27)
in-floats.yaml guard-dryrun.yaml in-flow.yaml in-level.yaml
The common/ files are owned by Alacrity and changed only by pull request/teacher. Teams edit only their node file. Every file below passed esphome config, and both the example node and a test node with every package enabled compiled cleanly (ESPHome 2026.9.1, ESP-IDF 5.5.5). Node-level substitutions override the defaults in the packages.
ESPHome components used: sht3xd, scd4x, bh1750, bme680, one_wire + dallas_temp, adc, copy, ledc, monochromatic light, speed fan, output/template switch, servo, pulse_counter, ultrasonic, gpio/template/status binary_sensor, ssd1306_i2c + font, sntp + homeassistant time, wifi_signal, uptime, script, interval, globals, template number/button.
secrets.yaml (template; the real file stays on the Pi)
wifi_ssid: "MICROCOSM"
wifi_password: "<WPA2 key, 16+ chars>"
fallback_ap_password: "<12+ chars>"
ota_password: "<random 20 chars>"
mc00_api_key: "<32-byte base64>" # generate: openssl rand -base64 32
mc01_api_key: "<...>"
mc04_api_key: "<...>"
# ... one per node incl. spares mc-10..mc-12
Base firmware and packages
The full listing of common/mc-base.yaml, the sensor packages, the actuator packages and the heater safety interlock is in Appendix B. All files compiled cleanly with esphome config and esphome compile on ESPHome 2026.9.1 and are delivered alongside this document in the microcosm-firmware/ folder.
Example node: mc-04-future2026.yaml
# mc-04-future2026.yaml — Future 2026 (paired with mc-05). Only this file is edited by the team.
substitutions:
node_name: mc-04-future2026
friendly_name: "MC 04"
area: "Future 2026"
api_key: !secret mc04_api_key
user1_src: soil_a
user1_label: "Soil A pct"
user2_src: co2
user2_label: "CO2 ppm"
light_on_min: "420" # 07:00 (identical in mc-05!)
light_off_min: "1260" # 21:00
packages:
base: !include common/mc-base.yaml
sht31: !include common/sens-sht31.yaml
scd41: !include common/sens-scd41.yaml
bh1750: !include common/sens-bh1750.yaml
t_sub_a: !include
file: common/sens-ds18b20.yaml
vars: {sid: t_sub_a, label: "Substrate temp A", addr: "0x5a3c01f0956e2b28", offset: "0.0"}
soil_a: !include
file: common/sens-soil.yaml
vars: {pos: a, pin: GPIO32, dry_v: "2.62", wet_v: "1.31"}
soil_b: !include
file: common/sens-soil.yaml
vars: {pos: b, pin: GPIO33, dry_v: "2.58", wet_v: "1.27"}
light: !include common/act-light.yaml
fan: !include common/act-fan.yaml
pump: !include
file: common/act-pump.yaml
vars: {pid: pump, pin: GPIO18, label: "Irrigation pump", max_s: "60"}
The resulting HA entities are sensor.mc_04_air_temp, sensor.mc_04_air_rh, sensor.mc_04_co2, sensor.mc_04_illuminance, sensor.mc_04_substrate_temp_a, sensor.mc_04_soil_moisture_a/_b (+ diagnostic sensor.mc_04_soil_raw_a/_b), light.mc_04_grow_light, switch.mc_04_grow_light_schedule, fan.mc_04_fan, fan.mc_04_irrigation_pump, sensor.mc_04_wifi_rssi and binary_sensor.mc_04_status. HA builds the id from the device's friendly name MC 04 plus the entity name. Check the ids once after adoption: they are frozen at first registration, and renaming later breaks the InfluxDB series.
mc-05-future2056 uses the same file plus act-heater.yaml (heat_probe: t_sub_a) and act-relay.yaml (mister, max_s: "30"), with identical light_on_min/light_off_min, so the only differences between 04 and 05 are the experimental variables.
Firmware rules
| Rule | Why |
|---|---|
| Safety logic (heater interlock, pump max-run, dry-run guard, mister timeout, photoperiod) lives in the node. | It keeps working when HA, Wi-Fi or the Pi is down. |
api.reboot_timeout: 0s and wifi.reboot_timeout: 0s |
The default makes nodes reboot every 15 min without HA, which resets actuator states. |
Actuators restore_mode: ALWAYS_OFF (light: RESTORE_DEFAULT_OFF, then the schedule turns it on) |
After a power cut nothing starts unattended except the photoperiod. |
| All sensors 60 s. Exceptions: flow and level at 10 s internally (reported every 60 s for level) | Matches the brief's sampling policy; flow events are short. |
No % character in OLED labels |
The label is inserted into a printf format string. |
| Spare boards mc-10…mc-12: advanced track (Arduino/PlatformIO, MQTT, RTC + SD logging) | Never on a production node without teacher review. |
Hub (Raspberry Pi 5 + Home Assistant OS)
Install (≈ 90 min, teacher + Alacrity)
| # | Step |
|---|---|
| 1 | On a laptop: Raspberry Pi Imager → Choose device: Raspberry Pi 5 → Choose OS: Other specific-purpose OS → Home assistants and home automation → Home Assistant → Home Assistant OS (RPi 5) → Storage: the SD64 card (or the NVMe drive in a USB adapter, see the deviation below) → Write. |
| 2 | Fit the RTC battery on the Pi 5's J5 connector (keeps the clock through power cuts without Internet). Insert the card, connect Ethernet to router LAN port 1 and the 27 W PSU. |
| 3 | Wait 5–20 min. Open http://homeassistant.local:8123 (or http://192.168.50.10:8123 after the DHCP reservation). |
| 4 | Onboarding: owner account alacrity-admin (strong password, stored in the school's password manager); home name MICROCOSM Ioanid; location Bucharest; time zone Europe/Bucharest; metric; analytics off. Skip discovered devices for now. |
| 5 | Profile → enable Advanced mode. Settings → System → Updates: update HAOS and Core. Settings → System → Network: hostname microcosm-hub. |
| 6 | Install add-ons (Settings → Add-ons → Add-on store), all with Start on boot + Watchdog: see the table. |
| 7 | Configure the InfluxDB add-on (Chronograf UI → InfluxDB Admin): database homeassistant, user homeassistant (write), user grafana (read). Default retention autogen = infinite. |
| 8 | Paste the configuration.yaml blocks below; Developer tools → YAML → Check configuration → Restart. |
| 9 | ESPHome Device Builder: copy common/, secrets.yaml, node files; flash each node once by USB (or the browser at web.esphome.io), then OTA. HA → Settings → Devices → ESPHome → Configure each discovered node with its API key; assign the Area. |
| 10 | Backups: Settings → System → Backups → add the Google Drive location (HA built-in integration). Schedule daily 03:00, keep 14, encrypted; store the backup emergency kit (encryption key) offline with the teacher. |
Storage: HAOS boots from the 64 GB A2 microSD card. SD wear is the usual hub failure, so the nightly backup below is mandatory and a second card with a restored image is kept in the hub box. An NVMe drive was considered and dropped as a cost cut; it can be added later without reinstalling.
Add-ons and roles
| Add-on | Role | Notes |
|---|---|---|
| ESPHome Device Builder | edit, compile, OTA-flash node firmware | admin users only; compile needs Internet once to fetch toolchains and fonts |
| Mosquitto broker | MQTT for the advanced track, Tasmota plugs | user mc-mqtt, no anonymous access |
| InfluxDB (1.8, includes Chronograf) | long-term time-series store, query UI with CSV download | keep forever; ≈ 0.5 GB/year for 9 nodes |
| Grafana | per-ecosystem analysis dashboards | port 3000 exposed on LAN, anonymous Viewer for students |
| Studio Code Server | YAML editing with validation (teacher, advanced students) | admin only |
| File editor | quick edits | admin only |
| Samba share | \\192.168.50.10\share → CSV exports on teacher laptop |
own user, LAN only |
| Tailscale | remote access without port forwarding | optional, needs a WAN |
| (built-in) Backups → Google Drive | nightly full backup off-site | encrypted |
| rclone (community add-on), optional | sync /share/microcosm/csv → Google Drive folder |
alternative: Google Drive for Desktop on the teacher laptop syncing the Samba share |
configuration.yaml blocks
recorder:
purge_keep_days: 30 # short-term SQLite for HA history graphs
commit_interval: 5
exclude:
entity_globs:
- sensor.*_uptime
influxdb:
host: a0d7b954-influxdb # InfluxDB add-on hostname
port: 8086
database: homeassistant
username: homeassistant
password: !secret influxdb_password
max_retries: 3
default_measurement: state # unit-less entities (switches, binary sensors)
tags:
project: microcosm
include:
entity_globs:
- sensor.mc_*
- binary_sensor.mc_*
- switch.mc_*
- light.mc_*
- fan.mc_*
- number.mc_*
- input_boolean.mc_* # mc_XX_maintenance flags -> quality = MAINT
exclude:
entity_globs:
- sensor.mc_*_uptime
input_boolean: # one per node; set before hands-on work
mc_04_maintenance:
name: "MC 04 maintenance"
icon: mdi:wrench
# ... mc_01 ... mc_09
shell_command:
mc_export_csv: "python3 /config/scripts/mc_export.py"
automation:
- id: mc_nightly_csv
alias: "MC nightly CSV export 02:15"
triggers:
- trigger: time
at: "02:15:00"
actions:
- action: shell_command.mc_export_csv
InfluxDB writes one measurement per unit (°C, %, ppm, lx, L/min, m, state, …), tag entity_id (without the domain), field value.
Nightly CSV export: /config/scripts/mc_export.py
Writes yesterday (UTC) as microcosm_YYYY-MM-DD.csv to the USB stick (label it MCBACKUP; HAOS mounts it under /media/MCBACKUP) and to /share/microcosm/csv (Samba share, rclone). The InfluxDB password goes in /config/.influx_pass. Re-export any day with python3 /config/scripts/mc_export.py 2026-11-03 from the Studio Code Server terminal. Tested against a mock InfluxDB response.
#!/usr/bin/env python3
"""MICROCOSM nightly export: one UTC day from InfluxDB 1.8 -> long-format CSV.
Usage: python3 /config/scripts/mc_export.py [YYYY-MM-DD] (default: yesterday UTC)
Columns: timestamp_utc,node,entity,value,unit,quality
"""
import base64, csv, datetime as dt, json, os, re, sys, urllib.parse, urllib.request
INFLUX = "http://a0d7b954-influxdb:8086/query"
DB, USER = "homeassistant", "homeassistant"
PASS = open("/config/.influx_pass").read().strip()
OUTDIRS = [("/media/MCBACKUP", "microcosm/csv"), ("/share", "microcosm/csv")] # (mount, subdir)
# physical plausibility per unit -> quality RANGE outside it
LIMITS = {"°C": (-10, 60), "%": (0, 100), "ppm": (300, 10000), "lx": (0, 70000),
"L/min": (0, 10), "m": (-0.05, 1.0), "pH": (2, 12), "µS/cm": (0, 5000)}
day = dt.date.fromisoformat(sys.argv[1]) if len(sys.argv) > 1 else \
dt.datetime.now(dt.timezone.utc).date() - dt.timedelta(days=1)
t0, t1 = f"{day}T00:00:00Z", f"{day + dt.timedelta(days=1)}T00:00:00Z"
def query(q):
url = INFLUX + "?" + urllib.parse.urlencode({"db": DB, "q": q, "epoch": "s"})
req = urllib.request.Request(url)
tok = base64.b64encode(f"{USER}:{PASS}".encode()).decode()
req.add_header("Authorization", "Basic " + tok)
with urllib.request.urlopen(req, timeout=120) as r:
return json.load(r)["results"][0].get("series", [])
series = query(f"SELECT value FROM /.*/ WHERE entity_id =~ /^mc_/ "
f"AND time >= '{t0}' AND time < '{t1}' GROUP BY entity_id")
def node_of(ent):
return re.match(r"mc_\d+b?", ent).group(0) # mc_04, mc_08b
# maintenance windows: input_boolean.mc_XX_maintenance (1 = on)
maint = {}
for s in series:
e = s["tags"]["entity_id"]
if e.endswith("_maintenance"):
maint[node_of(e)] = sorted((int(t), v) for t, v in s["values"])
def in_maint(node, t):
state = 0
for ts, v in maint.get(node, []):
if ts > t:
break
state = v
return state == 1
rows = []
for s in series:
unit, ent = s["name"], s["tags"]["entity_id"]
node = node_of(ent)
for t, v in s["values"]:
if v is None:
continue
lo, hi = LIMITS.get(unit, (float("-inf"), float("inf")))
q = "MAINT" if in_maint(node, t) else ("RANGE" if not lo <= v <= hi else "OK")
ts = dt.datetime.fromtimestamp(t, dt.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
rows.append((ts, node, ent, v, "" if unit == "state" else unit, q))
rows.sort()
for root, sub in OUTDIRS:
if not os.path.isdir(root):
continue # USB stick not mounted -> skip
d = os.path.join(root, sub)
os.makedirs(d, exist_ok=True)
with open(os.path.join(d, f"microcosm_{day}.csv"), "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["timestamp_utc", "node", "entity", "value", "unit", "quality"])
w.writerows(rows)
print(f"{day}: {len(rows)} rows")
Grafana (one template dashboard for all nine)
- Data source: InfluxDB, URL
http://a0d7b954-influxdb:8086, databasehomeassistant, usergrafana, InfluxQL. - Dashboard
MICROCOSM node, variablenode(Custom:mc_01,mc_02,mc_03,mc_04,mc_05,mc_06,mc_07,mc_08,mc_09), time range default 7 days. - Panels (one query each, legend
$tag_entity_id):
| Panel | InfluxQL |
|---|---|
| Temperatures | SELECT mean("value") FROM "°C" WHERE "entity_id" =~ /^${node}_/ AND $timeFilter GROUP BY time($__interval), "entity_id" fill(null) |
| Moisture and RH | same, FROM "%" |
| CO2 | same, FROM "ppm" |
| Light | same, FROM "lx" |
| Actuators (state timeline) | SELECT last("value") FROM "state" WHERE "entity_id" =~ /^${node}_(grow_light|fan|.*pump|heater_on|mister)$/ AND $timeFilter GROUP BY time(1m), "entity_id" |
| Data health | SELECT mean("value") FROM "dBm" WHERE "entity_id" =~ /^${node}_wifi_rssi/ AND $timeFilter GROUP BY time(10m) |
- An extra dashboard
Future 2026 vs 2056overlaysmc_04_*andmc_05_*for the same quantity (one panel per quantity, two queries, plus a difference panel using a Grafana Transform → Add field from calculation → Binary operation).
CSV export methods for students
| Method | Steps | Best for |
|---|---|---|
| Grafana | panel menu → Inspect → Data → options "Series joined by time", "Formatted data" off → Download CSV | a figure's exact data, wide format |
| Chronograf (InfluxDB add-on, teacher session) | Explore → SELECT "value" FROM "%" WHERE "entity_id"='mc_04_soil_moisture_a' AND time > now() - 14d → CSV |
raw values, any range |
| Flux (only if Flux is enabled, or after a later InfluxDB 2 migration) | from(bucket:"homeassistant/autogen") \|> range(start:-7d) \|> filter(fn:(r) => r.entity_id =~ /^mc_04_/ and r._field == "value") \|> aggregateWindow(every:10m, fn:mean) |
aggregated series |
| HA History | History → pick entities and dates → ⋮ → Download data | quick look, last 30 days only |
| Nightly files | Samba share or Google Drive folder microcosm/csv/ |
the official dataset, long format with quality flags |
Naming conventions
| Thing | Pattern | Example |
|---|---|---|
| ESPHome device / hostname | mc-NN-<shortname> |
mc-04-future2026 |
| HA device name (friendly_name) | MC NN |
MC 04 |
| Entity id | <domain>.mc_NN_<quantity>[_<position>] |
sensor.mc_04_soil_moisture_a, sensor.mc_07_water_temp |
| Quantities | air_temp, air_rh, co2, illuminance, substrate_temp_<pos>, water_temp, soil_moisture_<pos>, soil_raw_<pos>, water_level, flow_rate, flow_total, ph, ec, level_low_alarm, level_high_alarm, gas_resistance, air_pressure |
|
| Positions | a–d = probe/plot, documented on the ecosystem map; top/bottom allowed for columns |
substrate_temp_bottom |
| HA area | ecosystem name | Future 2026 |
| Probe labels | <node>-<port> <type> <pos> #<last4 ROM or serial> |
04-S2 DS18B20 A #2B28 |
Home Assistant dashboards
| Dashboard | Content | Who |
|---|---|---|
MICROCOSM overview |
9 tile cards (one per ecosystem: status colour, key value, last update), plus a "problems" card filtering binary_sensor.mc_* with device class problem that are on |
everyone, wall display |
One view per ecosystem (/microcosm/mc-04) |
gauges (air T, RH, CO2, soil A/B), history graphs 24 h/7 d, actuator card (light, fan, pump with sliders), heater setpoint + enable + interlock state, experiment-mode buttons (HA scripts), maintenance toggle, link to the Grafana dashboard with ?var-node=mc_04 |
team + teacher |
| Admin | node diagnostics (RSSI, uptime, FRC buttons, restart), backup status | teacher/Alacrity |
Experiment-mode buttons are HA scripts. The node firmware still enforces the limits (pump max-run, heater interlock):
script:
mc_05_rain_event:
alias: "MC 05 rain event (2 min at 60 %)"
sequence:
- action: fan.turn_on
target:
entity_id: fan.mc_05_rain_pump
data:
percentage: 60
- delay: "00:02:00"
- action: fan.turn_off
target:
entity_id: fan.mc_05_rain_pump
mc_05_heatwave_on:
alias: "MC 05 heatwave (+5 C setpoint)"
sequence:
- action: number.set_value
target:
entity_id: number.mc_05_heater_setpoint
data:
value: "{{ states('number.mc_05_heater_setpoint') | float(25) + 5 }}"
- action: switch.turn_on
target:
entity_id: switch.mc_05_heater_enable
Add a logbook.log step (name, message) to every experiment-mode script so interventions appear in the event log that teams export with their data.
Alerting (Telegram group "MICROCOSM staff"; e-mail via the SMTP integration as fallback)
Set up Settings → Integrations → Telegram bot (polling), with the bot added to the staff group. Alerts go to staff, not to students' private phones.
automation:
- id: mc_node_offline
alias: "MC node offline > 15 min"
triggers:
- trigger: state
entity_id:
- binary_sensor.mc_01_status
- binary_sensor.mc_02_status
- binary_sensor.mc_03_status
- binary_sensor.mc_04_status
- binary_sensor.mc_05_status
- binary_sensor.mc_06_status
- binary_sensor.mc_07_status
- binary_sensor.mc_08_status
- binary_sensor.mc_09_status
to:
- "off"
- "unavailable"
for: "00:15:00"
actions:
- action: telegram_bot.send_message
data:
message: "MICROCOSM: {{ trigger.to_state.name }} offline for 15 min"
- id: mc_sensor_nan
alias: "MC sensor unknown > 10 min"
triggers:
- trigger: template
value_template: >
{{ states.sensor | selectattr('entity_id', 'match', 'sensor\.mc_')
| selectattr('state', 'in', ['unknown', 'unavailable']) | list | count > 0 }}
for: "00:10:00"
actions:
- action: telegram_bot.send_message
data:
message: >
MICROCOSM sensors without data:
{{ states.sensor | selectattr('entity_id', 'match', 'sensor\.mc_')
| selectattr('state', 'in', ['unknown', 'unavailable'])
| map(attribute='entity_id') | join(', ') }}
- id: mc_thresholds
alias: "MC threshold / interlock"
triggers:
- trigger: state
entity_id:
- binary_sensor.mc_03_heater_interlock
- binary_sensor.mc_05_heater_interlock
- binary_sensor.mc_07_level_low_alarm
to: "on"
- trigger: numeric_state
entity_id:
- sensor.mc_04_air_temp
- sensor.mc_05_air_temp
above: 38
for: "00:10:00"
- trigger: numeric_state
entity_id: sensor.mc_07_water_temp
above: 28
for: "00:30:00"
actions:
- action: telegram_bot.send_message
data:
message: "MICROCOSM alert: {{ trigger.to_state.name }} = {{ trigger.to_state.state }}"
User accounts
| Account | Type | Use |
|---|---|---|
alacrity-admin |
owner/admin | platform maintenance |
teacher-<name> (1–2) |
admin | daily operation, ESPHome edits, backups |
mc-team-01 … mc-team-09 |
user (non-admin), "local network only" | team dashboards, actuator control, experiment buttons |
mc-display |
user, local only | wall-screen kiosk (overview dashboard) |
HA has no per-entity permissions, so a team account can technically switch another team's pump. This is acceptable because every safety limit is in node firmware; misuse is a classroom-rule matter. Add-on panels (ESPHome, InfluxDB, terminals) are admin-only.
Data pipeline, retention and backup
flowchart LR
N["9 nodes - 60 s values"] -->|"native API"| HA["HA Core"]
HA --> REC["Recorder SQLite - 30 days"]
HA --> IDB["InfluxDB - autogen, keep forever"]
IDB --> GF["Grafana dashboards"]
IDB --> EXP["02:15 mc_export.py - yesterday UTC"]
EXP --> USB["USB stick MCBACKUP - CSV per day"]
EXP --> SH["/share/microcosm/csv - Samba"]
SH --> GD["Google Drive folder - rclone or Drive for Desktop"]
HA --> BK["03:00 HA full backup, encrypted - incl. InfluxDB add-on data"]
BK --> GDB["Google Drive backups - keep 14"]
BK --> LOC["Local copy on the Pi"]
Restore test: once per term, restore the latest backup onto the spare SD64 in a second Pi (or the same Pi with a swapped card), check that dashboards and the last 24 h of InfluxDB data are present, then swap back.
Hub BOM
| ID | Qty | Est. RON each | RON | Basis |
|---|---|---|---|---|
| PI5 | 1 | 560 | 560 | Pi 5 4 GB ≈ €60–85 board (EU listings checked 2026-10) + official 27 W PSU ≈ 65 + active cooler/case ≈ 60, RO resellers (optimusdigital/robofun) |
| SD64 | 2 | 45 | 90 | A2 64 GB (SanDisk Extreme class), emag; 1 boot/rescue, 1 spare |
| Free: M.2 HAT+ + 256 GB NVMe (recommended) | 1 | 200 | 200 | RO resellers, estimate |
| Free: Pi 5 RTC battery | 1 | 30 | 30 | official ML-2020 battery |
| ROUTER | 1 | 160 | 160 | TP-Link Archer C6/C54 class, emag |
| Free: Cat6 patch cable 1 m | 2 | 10 | 20 | |
| Free: USB stick 64 GB (MCBACKUP) | 2 | 35 | 70 | one in the Pi, one rotated home by the teacher monthly |
| Hub subtotal | 1 130 |
Network
The nodes use the school's existing Wi-Fi. No router is bought. What the project needs from school IT, in writing, by 2026-10-23:
| Requirement | Why |
|---|---|
| A 2.4 GHz SSID with WPA2-PSK (a plain password), visible in the lab | ESP32 has no 5 GHz radio and cannot do WPA2-Enterprise or captive portals |
| 12 DHCP reservations (9 nodes + 3 spares) and one for the Pi, by MAC address | Stable addresses for ESPHome and the dashboards |
| The Pi reachable from student laptops and phones on the school network (port 8123) | Dashboards; if client isolation is on, ask for an exception for the Pi's address |
| Pi on Ethernet if a socket exists in the lab, otherwise Wi-Fi | Reliability |
| NTP and outbound HTTPS allowed for the Pi | Time, updates, backups to Google Drive |
Setup checklist (30 min): put the SSID and password in secrets.yaml; set manual_ip in each node YAML from the reservation list; check RSSI on every node after placement (acceptance: better than −75 dBm; move the node box or add a 2 m antenna extension if not); label each node box with its name and address.
What happens offline: nodes keep running their own automations and safety logic (heater interlock, pump limits, dry-run guard, light schedule all live in the firmware). Home Assistant schedules and alerts stop until the network returns. Design rule: safety logic is never in the hub. ESPHome's default reboot-on-no-connection is disabled so that a long outage does not restart the nodes.
Fallback: if IT cannot provide the SSID by 2026-10-27, buy a cheap 2.4 GHz router (≈ 160 RON) the same day and run an isolated "MICROCOSM" network with the Pi on its LAN port; the rest of this chapter is unchanged. Remote access, if wanted, is Tailscale (free) on the Pi.
Security basics: the Wi-Fi password may be given to students; the Home Assistant admin password and the ESPHome API keys are not. Students have non-admin Home Assistant accounts. Passwords are rotated at the start of each school year.
Calibration & metrology
General policy
| Item | Policy |
|---|---|
| Sampling | every sensor read every 60 s (soil: 10 reads at 6 s, averaged; level: median of 6 at 10 s; analog water probes: median of 10 at 6 s) |
| Stored values | the calibrated value and the raw value (soil V, pH V, TDS V) are both stored, so data can be re-calibrated later |
| Time | UTC in all exported data; HA dashboards display local time |
| Calibration log | every calibration goes on a record sheet (below) and in calibration_log.csv (shared folder), and the node is put in maintenance mode while it happens |
| Re-calibration | soil: each new substrate or after 3 months; pH: monthly; TDS: monthly; SCD41: monthly FRC check + after transport; DS18B20 and SHT31: at commissioning and each term |
M1. Capacitive soil probes (per probe, per substrate)
- Seal first: conformal coating or clear nail varnish over the PCB edge cut and components, heat-shrink over the electronics, mark the max insertion line.
- Flash the node; watch
sensor.mc_XX_soil_raw_<pos>(V, 60 s average). - Air: probe dry, held in air, 3 min → record V_air (sanity check only, ≈ 2.6–2.8 V at 3.3 V supply).
- Dry substrate: 500 mL of the actual substrate, air-dried 3 days on a tray (or 105 °C for 24 h in an oven where available), lightly packed to the planned density in a beaker. Insert to the line, 3 min → V_dry.
- Saturated substrate: add water until free water appears at the surface, wait 30 min, re-insert at the same depth, 3 min → V_wet.
- Enter
dry_v/wet_vin the node YAML (sens-soil.yamlinclude) → OTA. - Optional (Science track, gravimetric curve): from the dry sample, add water in 4 steps (e.g. 10/20/30/40 % of dry mass), mix, record V and the gravimetric water content (g water/g dry substrate). Fit a curve; this turns "% of saturation" into a real water content.
Output meaning: soil_moisture = relative saturation, 0 % = air-dry, 100 % = saturated, for that substrate. It is not volumetric water content and cannot be compared across substrates unless the gravimetric curve is done.
Record sheet M1
| Node | Pos | Probe label | Substrate | Date | V_air | V_dry | V_wet | Optional points (V : g/g) | By |
|---|---|---|---|---|---|---|---|---|---|
M2. SHT31 cross-check: saturated salt (NaCl) at 75.3 % RH
- Small cup with ≈ 30 g table salt (NaCl, no iodine/anti-caking is best) + water dropwise until it is a wet slurry, like wet sand, with undissolved crystals always present.
- Cup + sensor (on its cable through the lid, sealed with Blu-Tack) in a 0.5–1 L airtight glass jar. The sensor must not touch the slurry.
- Stable room temperature (± 1 °C), out of sunlight, 12–24 h (overnight).
- Read
air_rh: expected 75.3 % at 20–25 °C. SHT31 spec ±2 % RH → accept 73–78 %. Offset > 3 % → replace or note an offset filter. Also note T vs the reference thermometer. - Optional second point: potassium carbonate K₂CO₃ slurry = 43 % RH.
Record sheet M2
| Sensor (node/label) | Jar start | Read time | T (°C) | RH read (%) | Expected (%) | Error | Pass? |
|---|---|---|---|---|---|---|---|
| 75.3 |
M3. DS18B20 ice-water 0 °C check
- 1 L insulated cup packed full of crushed ice, filled with cold tap water to just below the ice top, stirred, 5 min.
- All probes in together (tips mid-depth, not touching the walls), plus the reference thermometer. 5 min, stirring every minute.
- Expected 0.0 °C; spec ±0.5 °C → pass. Write the offset
-readinginto the probe'soffsetvar only if |error| > 0.2 °C. - Second point: all probes + reference in a stirred room-temperature water bucket, to cross-check that probes agree within 0.3 °C.
Record sheet M3
| Probe label | ROM last4 | Ice reading (°C) | Room bath (°C) | Reference (°C) | Offset set | Pass? |
|---|---|---|---|---|---|---|
M4. SCD41 CO₂: forced recalibration (FRC), and why ASC is off
- ASC (automatic self-calibration) assumes that the sensor sees fresh air (≈ 420 ppm) at least once every 7 days and treats the lowest reading of the week as 400 ppm. In a closed tank with soil, compost or plants, CO₂ rarely drops to outdoor level. ASC then silently shifts the baseline, readings drift low over weeks, and respiration data become meaningless. ASC is disabled in firmware (
automatic_self_calibration: false) on every node. - FRC procedure: take the node (on a USB power bank via
PSU5cable, or the whole box on a long USB lead) outdoors to the school courtyard or a park, ≥ 10 m from traffic and people (your breath is ≈ 40 000 ppm), sensor in shade, 5 min stable readings (periodic mode). Then pressbutton.mc_XX_co2_frc_425_ppm. Bucharest urban background is ≈ 425–450 ppm; we use 425 ppm and accept ±30 ppm residual uncertainty. - Inter-sensor check (important for paired 04/05): put all four SCD41 nodes side by side in one closed box for 1 h. The four readings should agree within ±(40 ppm + 5 %). Record the offsets and repeat each term.
Record sheet M4
| Node | Date | Location | Reading before FRC | FRC value | Reading after 10 min | Side-by-side offset vs mean | By |
|---|---|---|---|---|---|---|---|
| 425 |
M5. pH probe: 2-point (7, then 4), slope check at 10
- Rinse the probe in distilled water, blot (don't wipe). Buffers at room temperature, note T.
- pH 7.00 buffer, stir gently, wait for stable V (2 min) → V7. Rinse.
- pH 4.00 buffer → V4. Rinse. (pH 10 → V10 for a slope check only.)
- Set
v1: V7, y1: "7.0", v2: V4, y2: "4.0"in thesens-analog.yamlinclude. Slope should be ≈ 0.17–0.18 V/pH for a Gravity v2 board (≈ 59 mV/pH at the electrode, amplified). - Store the probe in KCl storage solution, never in distilled water. Recalibrate monthly. If pH and TDS probes sit in the same water, read them alternately or fit a galvanic isolator: they interfere.
M6. TDS/EC: 1413 µS/cm standard
- 1413 µS/cm solution at 25 °C (or note T); rinse, immerse, 2 min.
- The Gravity TDS conversion is EC = (133.42·V³ − 255.86·V² + 857.39·V) × K, with temperature compensation EC25 = EC / (1 + 0.02·(T − 25)) using the water DS18B20 (template sensor in the Hydro node). Adjust K until the reading is 1413 ± 2 %. TDS (ppm) = EC25 × 0.5.
- Monthly; probe rinsed and dried after use when not permanently installed.
M7. BH1750 plausibility vs phone lux app
- Same position, same angle: BH1750 vs phone app (front camera/ambient light sensor) under (a) room light, (b) the grow light at canopy height, (c) daylight at the window.
- Phones are uncalibrated: accept ±30 %. Purpose: catch a dead, saturated (> 54 000 lx default range) or shaded sensor.
- Limitation to teach: lux is weighted to the human eye, not PAR. For a white full-spectrum LED, PPFD (µmol·m⁻²·s⁻¹) ≈ lux / 70 is a rough guide only, and only valid for comparing the same light type.
Record sheets M5–M7 use the same layout: node, probe label, date, standard/condition, raw V or reading, set value, pass, by.
Dataset structure
Nightly files microcosm_YYYY-MM-DD.csv, long format, UTF-8, comma-separated:
| Column | Type | Example | Meaning |
|---|---|---|---|
timestamp_utc |
ISO 8601, Z | 2026-11-03T14:05:00Z |
time HA received the value |
node |
text | mc_04 |
ecosystem node |
entity |
text | mc_04_soil_moisture_a |
full entity object id |
value |
float | 41.0 |
calibrated value (on/off = 1/0) |
unit |
text | % |
unit of measurement (empty for on/off) |
quality |
enum | OK |
OK; RANGE = outside physical limits; MAINT = node in maintenance mode (hands in tank, calibration); CAL and SUSPECT set manually by teams during data review |
Companion files in the same shared folder: sensors.csv (entity, probe label, ROM/serial, position, install date, calibration ref), calibration_log.csv (sheet rows M1–M7), events_log.csv (timestamp_utc, node, event, by: watering, feeding, salt added, experiment start/stop. HA logbook entries are exported here as well).
Data dictionary (base entities)
| Entity suffix | Unit | Sensor | Resolution / accuracy | Valid range |
|---|---|---|---|---|
air_temp |
°C | SHT31 (BME680 in Rot) | 0.01 / ±0.3 °C | −10…60 |
air_rh |
% | SHT31 (BME680) | 0.01 / ±2 % RH | 0…100 |
co2 |
ppm | SCD41 | 1 / ±(40 ppm + 5 %) | 400…5000 spec |
co2_sensor_temp, co2_sensor_rh |
°C, % | SCD41 (diagnostic; self-heated) | — | — |
illuminance |
lx | BH1750 | 1 / ±20 % | 0…54 612 |
substrate_temp_<pos>, water_temp |
°C | DS18B20 | 0.0625 / ±0.5 °C | −10…85 |
soil_moisture_<pos> |
% rel. saturation | capacitive v2.0 | 1 / see M1 | 0…100 |
soil_raw_<pos> |
V | ADC1 | 0.001 | 0.15…3.1 |
water_level |
m | JSN-SR04T | 0.005 / ±1 cm | 0…tank depth |
flow_rate, flow_total |
L/min, L | YF-S401 | ±10 % uncalibrated, ±3 % calibrated | 0.3…6 L/min |
ph |
pH | Gravity pH v2 / PH-4502C | 0.01 / ±0.1 after cal. | 2…12 |
ec |
µS/cm | Gravity TDS | ±10 % | 0…5000 |
gas_resistance |
Ω | BME680 | relative only | — |
level_low_alarm, level_high_alarm |
on/off | float switches | — | — |
grow_light |
on/off (brightness in HA history) | MOSFET PWM1 | — | — |
fan, *_pump |
on/off (+ speed %) | MOSFET PWM2/3 | — | — |
heater_on, heater_interlock |
on/off | template | — | — |
wifi_rssi |
dBm | ESP32 | — | −100…−30 |
Commissioning & acceptance
Per-node checklist (sign-off by teacher + team)
| # | Check | Pass criterion | ☐ |
|---|---|---|---|
| 1 | QA checklist of the assembly session | all 12 items passed | ☐ |
| 2 | Power | brick on the RCD strip, drip loop, box above water line, glands down | ☐ |
| 3 | Wi-Fi | RSSI > −75 dBm at the final position (OLED), reserved IP | ☐ |
| 4 | Entities | every expected entity in HA reports a plausible value within 2 min; ids match the naming table | ☐ |
| 5 | OLED | name, "HA ok", T/RH, two team values | ☐ |
| 6 | Actuators dry-run | each actuator on/off and 30/60/100 % from HA; direction/flow correct; no water spilled | ☐ |
| 7 | Interlocks tested | heater: unplug the DS18B20 → heater_interlock on and pad off within 10 s; warm the probe in hand-hot water (> 45 °C) → trip. Pump: max-run timer stops it; float low → dry-run guard stops it. Mister timeout. |
☐ |
| 8 | Offline test | unplug the Pi Ethernet 20 min: photoperiod and thermostat continue, the node does not reboot, data gap only | ☐ |
| 9 | Calibrations | records M1–M4 (and M5/M6 where fitted) filled | ☐ |
| 10 | 24 h soak | 24 h with the full biology/water: no gaps > 5 min in Grafana, no NaN, no alert except expected, box interior dry | ☐ |
| 11 | Documentation | port sticker, photo, sensors.csv rows, YAML committed/backed up |
☐ |
Per-hub checklist
| # | Check | ☐ |
|---|---|---|
| 1 | HAOS/Core/add-ons updated; all add-ons start on boot and have the watchdog on | ☐ |
| 2 | Pi on Ethernet, .10 reserved, RTC battery fitted (clock correct after 5 min unplugged from WAN and power) |
☐ |
| 3 | InfluxDB receiving all mc_* entities (Chronograf: SHOW TAG VALUES FROM "°C" WITH KEY = "entity_id") |
☐ |
| 4 | Grafana template dashboard works for all 9 node values; anonymous viewer works from a student laptop |
☐ |
| 5 | Nightly CSV produced on the USB stick and the share; opened in a spreadsheet; quality flags present | ☐ |
| 6 | Backup to Google Drive succeeded; restore test done on the spare SD | ☐ |
| 7 | Alerts: test message reaches the Telegram group; node-offline alert fires after 15 min | ☐ |
| 8 | Accounts: admins with 2FA, 9 team accounts + display, local-only | ☐ |
| 9 | Power-cut test: switch off the RCD strip 1 min → everything returns unattended within 5 min, actuators in safe state | ☐ |
"Day-one data review" session (45 min, the day after each 24 h soak; repeat weekly in the first month)
| Min | Activity |
|---|---|
| 0–5 | Each team opens its Grafana dashboard for the last 24 h. |
| 5–20 | Checklist per team: (1) any gaps? (2) does each value make physical sense (T vs room, RH vs watering, CO₂ day/night, light matches schedule)? (3) do replicate probes agree? (4) do actuator events match changes in sensors (pump on → moisture up)? |
| 20–30 | Each team marks up to 3 anomalies in events_log.csv / sets SUSPECT flags, and writes one hypothesis for each anomaly (sensor fault vs real biology). |
| 30–40 | 2-min report per team; teacher collects hardware issues into the fault log. |
| 40–45 | Decide fixes, assign owners, re-check at the next session. |
Spare-parts policy
| Item | Spares held | Rule |
|---|---|---|
| ESP32 | 3 (mc-10…12, pre-flashed with a base test config) | a failed node is swapped in < 15 min: move the YAML name/key, OTA, re-adopt |
| Each sensor type (SHT31, SCD41, BH1750, BME680, JSN, FLOW) | 1 | DS18B20, SOIL, FLOAT, SERVO: 2 each |
| PSU12 | 1 | plus 2 × PSU5 for bench work |
| BUCK, MOSFET, RELAY | 3, 5, 2 | in the spares box |
| SD64, USB stick | 1, 1 | cloned rescue card |
| Restock | when a spare is used, reorder within 1 week (fault log entry) |
Safety
Lab wall sheet: "MICROCOSM electrical & water safety rules" (print A4, laminate)
- Only 12 V (24 V for misters) inside or near the ecosystems. Nothing that plugs into a wall socket goes into an enclosure, into water or into soil.
- 230 V devices are only certified, closed products (power bricks, Pi charger, LED panel, air pump, smart plugs). Never open, cut, extend or repair them. No relay modules on 230 V, ever.
- All 230 V plugs live on the RCD-protected strip on the high shelf. Only the teacher plugs or unplugs at that strip.
- Every cable has a drip loop (a U-shaped dip below the socket/box) so water runs off the bottom of the loop, not into the plug or box.
- Before hands go into water or substrate: turn on maintenance mode in HA, unplug that node's 12 V DC jack at the box, switch the smart-plugged devices off at the plug, and hang the "OFF – working" tag on it.
- Dry hands, dry bench. No drinks on the electronics bench. Wipe spills before touching anything electrical.
- Node boxes stay closed, glands tight, above the water line. Open a box only after unplugging its brick.
- Power off before connecting or disconnecting anything. Check polarity, and check 5 V before inserting an ESP32.
- Heaters only through the node (interlock on, thermal fuse fitted). Never cover a heat pad or run one outside the enclosure.
- Smell, heat, smoke, a tingle, a warm brick or a cracked cable: stop, step back, call the teacher. The teacher switches off the RCD strip and logs the incident.
RCD and power distribution
- One portable RCD adapter, 30 mA, type A (certified, 16 A) between the wall socket and each power strip, even if the room circuit has an RCD. Press TEST every Monday and tick the log.
- Max. two strips, each fed directly from a wall socket (no daisy-chaining), mounted on the shelf, switch facing the front. Estimated total load ≈ 300 W typical, < 700 W worst case (9 × 12 V bricks, 2 mister adapters, Pi, router, LED panel 45 W, air pump 5 W).
Mains device list and placement
| Device | Qty | Location | Switched by |
|---|---|---|---|
PSU12 12 V 5 A bricks |
9 (+1 spare) | shelf; low-voltage lead down to the node box with a drip loop | not switched (always on) |
| Mister 24 V adapters | 2 | shelf | 24 V side via node relay |
| Pi 5 27 W PSU | 1 | shelf, next to the Pi | — |
LEDPANEL 30–45 W (Hydro) |
1 | hanging ≥ 30 cm above the open hydro top, cord routed up to the shelf | SMARTPLUG (own timer) |
AIRPUMP (Hydro, EcoColumn if used) |
1–2 | shelf above the water level, with an anti-siphon loop/check valve in the air line | SMARTPLUG |
| Smart plugs | 2–3 | on the RCD strip | HA + local timer |
Shelf: wall-mounted, top surface ≥ 40 cm above the tops of the tanks, front edge set back so that no open water is directly beneath it, bricks fixed with velcro or cable ties so they cannot fall. Cables run along the wall in a trunking/cable tray, never across walkways or over tank openings, and are fixed every 30 cm.
Who may plug and unplug what
| Action | Students | Teacher |
|---|---|---|
| Plug/unplug at the 230 V strip, RCD test | no | yes |
| Toggle smart plugs from HA | yes (own ecosystem) | yes |
| 12 V DC jack at the node box, JST/sensor connectors (power off) | yes, after the maintenance-mode step | yes |
| Open a node box | with teacher present, brick unplugged | yes |
| Change firmware | via teacher/admin session | yes |
Platform BOM
The platform parts (nodes, hub, power, spares, tools) are priced in Chapter 6 together with everything else; the quantities there are the ones to order. One node core (ESP32, breakout, box, glands, buck, OLED, cable kit) costs about 250 RON; the hub (Pi 5 kit, SD cards, backup stick) about 700 RON.
4. Sensor and actuator policy
The proposal asked: "useful vs unnecessary sensors". The answer depends on what each ecosystem is trying to measure, so this chapter allocates by need, not by headcount.
4.1 Useful, unnecessary, and wrong
| Sensor or actuator | Verdict | Where it earns its place | Notes |
|---|---|---|---|
| SHT31 air T/RH (PTFE-membrane breakout) | Useful, core | Every enclosure with air to measure except Rot and EcoColumn | Survives weeks at 95–100 % RH; BME280/BME680 humidity elements do not |
| BME680 | Useful only for "smell" | Rot (before and after the carbon filter) | Gas resistance is a VOC proxy, not CO2; its T/RH drifts in wet air |
| SCD41 NDIR CO2 | Useful, high value | Rot, Living Earth (respiration tests), 2026 and 2056 (paired), Time Capsule (optional, recommended) | Disable automatic self-calibration in sealed tanks; forced recalibration outdoors at 420 ppm |
| DS18B20 waterproof | Useful, core | Substrate core, water, under paving, thermostat feedback | Cheap enough to put two where one would do |
| BH1750 lux | Useful | Every enclosure with plants or algae | Lux, not PAR; fine for relative comparisons and for proving the LED schedule ran |
| Capacitive soil moisture v2.0 | Useful with mitigation | Every substrate | Coat the top edge, calibrate per probe per substrate, average 10 samples; 24 units for replicates and spares |
| Float switch | Useful, essential interlock | Every reservoir (low), every pond (high) | One bit, but it is the bit that stops a pump from running dry or flooding a desk |
| JSN-SR04T ultrasonic level | Useful | EcoColumn pond, hydroponics reservoir | Mount in a PVC stilling tube; ignore out-of-range readings |
| YF-S401 flow | Marginal | EcoColumn rain line | Starts at 0.3 L/min; rain volume is better computed from pump run time after a bucket calibration. Kept at 2 because approved and cheap |
| Analog pH kit | Useful, needs care | Hydroponics, EcoColumn pond | Drifts; 2-point calibration weekly; storage solution; cross-check with pen |
| TDS/EC module | Useful | Hydroponics | Never read at the same instant as the pH probe in the same water (ground loop); alternate readings |
| Turbidity module | Useful | EcoColumn pond | The science is sediment and algae; this is the sensor for it |
| Handheld pH pen and TDS pen | Useful, best value | All ecosystems (soil 1:5 extract) | More reliable than continuous probes everywhere; teaches the method |
| Dissolved oxygen probe | Unnecessary | – | 1 000+ RON; aeration is verified by behaviour and by air pump power monitoring |
| Water-flow sensor on hydroponics | Unnecessary | – | Circulation pump duty cycle is logged instead |
| Soil probe in hydroponics | Wrong | – | Proposal implied one per ecosystem |
| Lux sensor in Rot | Unnecessary | – | Decomposition is dark; the lid is opaque |
| OLED SSD1306 | Useful | Every node | Students see the numbers at the tank, not only on a screen |
| SD card + RTC on every node | Unnecessary | Time Capsule node and two advanced spare boards only | Hub logging is primary; local logging where independence from the hub matters |
| Relay module | Low-voltage only | 24 V mister switching | Never on mains |
| Smart plug (COTS) | Useful, the only mains switch | Hydroponics LED panel and air pump; optional on any 12 V brick | Reports power, which doubles as a "is the air pump running" sensor |
| 12 V PC fan | Useful | Rot (filtered exhaust), Brownfield, 2026, 2056, Hydroponics, Bog | Quiet, cheap, PWM-dimmable |
| 12 V submersible pump | Useful | EcoColumn rain, 2026 and 2056 irrigation, Hydroponics circulation, Time Capsule sump | 3–5 W; 12 V only |
| 12 V peristaltic pump | Useful | Hydroponics dosing (nutrient, pH-down) | With daily pen cross-checks and dose caps |
| 12 V silicone heat pad | Useful, with cut-offs | 2056 (+3.5 °C), Brownfield (heat island), 1 spare | DS18B20 loop in firmware, 45 °C thermostat, one-shot thermal fuse |
| Ultrasonic mister | Useful, limited | Rot, 2056 (or Bog) | 24 V adapter; distilled water only; weekly cleaning |
| Aquarium air pump (230 V COTS) | Useful | Hydroponics (DWC), EcoColumn pond (optional) | On the shelf, through a smart plug; only the air line enters the water |
| SG90 servo | Useful, small | Rot intake flap, EcoColumn rain gate, Living Earth chamber lid (phase 2), spare | 4 approved, 4 used |
| 12 V full-spectrum LED strip in profile | Useful, core | Every enclosure with plants or algae | SELV, PWM-dimmable, cut to length; replaces "grow lights 5–10 W" |
| 230 V LED grow panel | Useful, one only | Hydroponics, hung at 30 cm or more above the open top | Own cord, smart plug, RCD strip |
4.2 Allocation matrix
The matrix below is the result of the nine ecosystem designs in Chapter 5 after the cost-cut pass of 2026-10-20. "Spare" is the project-wide spare pool.
| ID | 1 Rot | 2 Eco | 3 Brown | 4–5 Future | 6 Regolith | 7 Hydro | 8 Soil | 9 Capsule | Used | Spare | Buy |
|---|---|---|---|---|---|---|---|---|---|---|---|
| ESP32 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 9 | 3 | 12 |
| TERMBOARD | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 9 | 1 | 10 |
| OLED | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 9 | 3 | 12 |
| SHT31 | 1 | 2 | 1 | 1 | 1 | 1 | 7 | 1 | 8 | ||
| BME680 | 2 | 2 | 0 | 2 | |||||||
| SCD41 | 1 | 2 | 1 | 4 | 0 | 4 | |||||
| DS18B20 | 1 | 1 | 2 | 4 | 1 | 1 | 2 | 2 | 14 | 1 | 15 |
| SOIL | 2 | 2 | 4 | 4 | 3 | 3 | 2 | 20 | 2 | 22 | |
| BH1750 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 8 | 1 | 9 | |
| FLOAT | 2 | 4 | 2 | 8 | 2 | 10 | |||||
| JSN | 1 | 1 | 2 | 0 | 2 | ||||||
| FLOW | 1 | 1 | 1 | 2 | |||||||
| PHKIT | 1 | 1 | 2 | 0 | 2 | ||||||
| TDS | 1 | 1 | 0 | 1 | |||||||
| TURB | 2 | 2 | 0 | 2 | |||||||
| CALSOL | 1 | 1 | 2 | 0 | 2 | ||||||
| FAN | 1 | 1 | 2 | 1 | 1 | 6 | 0 | 6 | |||
| PUMP | 1 | 2 | 2 | 5 | 0 | 5 | |||||
| PERI | 3 | 3 | 0 | 3 | |||||||
| HEATPAD | 1 | 2 | 3 | 1 | 4 | ||||||
| MIST | 1 | 1 | 2 | 0 | 2 | ||||||
| AIRPUMP | 1 | 1 | 0 | 1 | |||||||
| LEDSTRIP | 1 | 0.25 | 1 | 1 | 0.25 | 1 | 4.5 | 0 | 4 | ||
| LEDPROFILE | 5 | 2 | 3 | 2 | 2 | 2 | 16 | 0 | 16 | ||
| LEDPANEL | 1 | 1 | 0 | 1 | |||||||
| SERVO | 1 | 1 | 4 | 1 | 7 | 1 | 8 | ||||
| MOSFET | 1 | 3 | 3 | 8 | 2 | 4 | 2 | 2 | 25 | 2 | 27 |
| RELAY | 1 | 2 | 2 | 1 | 6 | 0 | 6 | ||||
| PSU12 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 9 | 0 | 9 |
| PSU5 | 1 | 1 | 1 | 2 | |||||||
| BUCK | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 8 | 2 | 10 | |
| SMARTPLUG | 2 | 2 | 0 | 2 | |||||||
| BOX | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 9 | 0 | 9 |
| GLAND | 14 | 10 | 6 | 22 | 6 | 12 | 6 | 6 | 82 | 0 | 80 |
| TANK25 | 1 | 1 | 0 | 1 | |||||||
| TANK45 | 1 | 2 | 3 | 0 | 3 | ||||||
| TANK63 | 1 | 1 | 1 | 1 | 4 | 0 | 4 | ||||
| ACRYLIC | 0.6 | 1 | 1 | 1 | 1 | 1 | 0.25 | 5.85 | 0 | 6 | |
| MESH | 0.25 | 0.25 | 0.1 | 0.25 | 0.1 | 0.25 | 0.25 | 1.45 | 0.8 | 3 | |
| SILICONE | 1 | 1 | 1 | 1 | 1 | 1 | 6 | 0 | 6 | ||
| TUBING | 1 | 5 | 8 | 6 | 2 | 22 | 0 | 22 | |||
| RESERVOIR | 1 | 1 | 2 | 1 | 5 | 0 | 5 | ||||
| BOXPLASTIC | 2 | 1 | 3 | 0 | 3 | ||||||
| SD64 | 1 | 1 | 0 | 2 | |||||||
| RTC | 1 | 1 | 1 | 2 | |||||||
| SDMOD | 1 | 1 | 1 | 2 | |||||||
| PI5 | hub | – | 1 | ||||||||
| PHPEN / TDSPEN | shared | shared | shared | shared | shared | shared | shared | shared | – | – | 2 / 1 |
Notes: LEDSTRIP is in 5 m reels (fractions are shares of a reel; about 14 m are actually cut, so 4 reels suffice); ACRYLIC in 50×100 cm panels (1 polycarbonate sheet gives 4, plus 2 acrylic panels); MESH in m²; TUBING in m; GLAND 80 covers 82 planned holes because several designs over-counted spares. The Carnivorous Bog alternative (Section 5.8b) is not counted; if chosen instead of Living Earth, its sub-BOM replaces that column. The Time Capsule's SCD41 is deferred to 2027 and not in the Buy column.
4.3 Automation policy
Automation is applied only where it serves a hypothesis or protects the system. Everything else stays manual and measured, because a student pouring 150 mL from a measuring cylinder and writing it down learns more than a pump that runs on a schedule.
| Ecosystem | Automated | Manual by design |
|---|---|---|
| Rot | Filtered exhaust fan on humidity and VOC; mister on humidity; nightly automatic respiration test (servo closes intake) | Feeding, litter-bag harvest, moisture samples |
| EcoColumn | Rain events (pump run with flow count, floats as interlocks); LED schedule | Fertiliser dosing, sediment collection, filter swaps |
| Brownfield | Heat island (heat pad thermostat with cut-offs); fan; LED schedule | Watering with measured volumes, salt and pH treatments, soil extracts |
| 2026 | Steady irrigation schedule; fan; LED schedule | Observations, harvests |
| 2056 | Heating loop; drought and extreme-rain calendar; CO2 vent and seal logic; humidity fan; LED schedule | CO2 generator refresh, observations, harvests |
| Forests in Space | LED schedule only | Watering with measured volumes, everything else |
| Hydroponics | Light, air pump (via smart plug), circulation duty, pH and nutrient dosing with caps and lockouts, level top-up | Reservoir changes, pen cross-checks, harvests |
| Living Earth | LED schedule; respiration-test mode (button starts, slope computed, alert when done) | Tea-bag burial, Berlese extraction, rhizotron photos |
| Time Capsule | LED 12 h/day with a timer-plug fallback; alerts; optional sump top-up | Everything else, by design, for ten years |
4.4 Spare capacity
After the cost-cut pass the spare pool is deliberately thin. It covers the failures that are common and cheap; anything else is a same-week purchase from a Romanian shop.
| Spare | Qty | Purpose |
|---|---|---|
| ESP32 boards | 3 | Approved quantity; any node swap in minutes; advanced Arduino track |
| SHT31, BH1750, DS18B20 | 1 each | One failure never stops an experiment |
| Soil probes | 2 | The most failure-prone sensor |
| Float switches, MOSFET modules, buck modules | 2 each | Power-side and interlock failures are the most common |
| Heat pad | 1 | 2–3 week lead time from AliExpress justifies one spare |
| 5 V USB adapter, servo, flow sensor, RTC, SD module | 1 each | Cheap |
| Not held | – | CO2 sensors, pumps, 12 V bricks, fans, air pump, tanks: buy on failure (all in stock in Bucharest shops) |
5. Ecosystem designs
Each design follows the same template: concept, science track, engineering track, enclosure and build, biology, instrumentation, automation, operations, safety, educational outcomes, sub-BOM, timeline. Catalog IDs refer to the parts catalog in Chapter 6.
1. The Orchestra of Rot
Concept (refined)
A 45 L glass tank (TANK45) holds a living decomposer community: compost worms, two woodlouse species, springtails, oyster-mushroom mycelium and a compost/leaf-mould microbial inoculum. It sits on a moist, layered bed with a randomised grid of labelled litter bags buried in it. Each bag holds 3.00 g of one dry material (lime leaves, cardboard, cotton, bread, orange peel, or PE plastic as the control). Students measure how fast each material disappears, whether the animals speed it up (coarse- vs fine-mesh bags), and how the community "breathes" (CO2 production rate from a closed-lid test) and "smells" (BME680 gas resistance before and after an activated-carbon filter). Over the 8 weeks they will see bread and orange peel moulder and collapse, white mycelium spreading through cardboard, worms and isopods moving into coarse bags, and a measurable daily respiration curve. Leaves, cardboard and cotton are slow, so the clear differences between those materials and between mesh sizes only show up in the spring 2027 runs.
Node: mc-01-rot. Team: 3–4 students (one each for biology lead, data lead, engineering lead and logbook/QA).
Science track
Driving question: Which everyday materials does a decomposer community recycle fastest, which members of the "orchestra" do the work, and how do moisture and temperature change the tempo?
Hypotheses (testable)
- H1 – Material: mass-loss rate ranks bread > orange peel > lime leaves (Tilia) > cotton ≈ cardboard > PE plastic (≈ 0 %). Reason: more sugar/starch and less lignin means faster loss.
- H2 – Macrofauna access: for leaves, cardboard and cotton, coarse-mesh bags (5 mm, which worms and isopods can enter) lose ≥ 1.5× more mass than fine-mesh bags (≈ 1 mm, which only microbes, fungi, springtails and mites can enter) over the same period.
- H3 – Respiration & conditions: (a) adding 100 g of fresh food scraps raises the CO2 production rate by ≥ 50 % within 48 h and lowers headspace gas resistance (more VOCs), with both returning to baseline within 7 days; (b) the nightly CO2 production rate rises with core temperature, giving Q10 ≈ 2 over the natural Dec–Feb temperature swings.
Variables
| Type | H1 | H2 | H3 |
|---|---|---|---|
| Independent | material (6 levels) | mesh size (5 mm vs 1 mm) | feeding event (before/after); core temperature |
| Dependent | % dry-mass loss, decay constant k, Visual Decomposition Index (VDI 0–5) | % mass loss, animals counted inside bags | CO2 rate (ppm/min → mg CO2/h), gas resistance ratio R/R0 |
| Controlled | 3.00 ± 0.02 g dry material per bag, bag size 6×6 cm, burial depth 5 cm, same tank/substrate, same duration, randomised positions | same as H1 | test length 30 min, fan/mister off, intake closed, same time of day (02:00 automatic + 12:00 manual) |
Replication & controls (litter-bag method)
- Bags: 6×6 cm finished, sewn with nylon fishing line (no metal staples). Each bag is tethered by 20 cm of line to a numbered plastic tag at the surface. Material is dried at 60 °C for 24 h (kitchen oven, teacher-supervised) or air-dried on a radiator to constant mass (± 0.02 g on 2 consecutive days), then weighed to 0.01 g.
- Run 1 (16 Nov → 14 Dec 2026, 28 days), 27 bags: 6 materials × coarse mesh × 3 replicates = 18, plus 3 slow materials (leaves, cardboard, cotton) × fine mesh × 3 = 9. Positions are randomised on a 7 × 4 grid (row pitch 6.5 cm, column pitch 7 cm). Students roll dice or use random.org and record the map in the logbook.
- Handling-loss ("travel") bags: 1 per material (6). Each is buried and dug out immediately, then dried and reweighed. The mean loss is subtracted from every result in that material.
- PE plastic is the negative control. It is expected to show 0 ± 2 % loss, which measures the method's error (soil left stuck to the bag, weighing error).
- Window bags: 6 extra coarse bags (one per material) pressed against the front glass at 5 cm depth in a 3 cm strip in front of the grid. Students photograph them through the glass for VDI scoring without disturbing the bed. They are not weighed.
- Run 2 (15 Dec 2026 → 15 Mar 2027, 90 days): same 27-bag design in fresh bags, adding a 7th treatment: Pleurotus-pre-colonised cardboard (coarse, ×3). Run 3 (22 Mar → 7 Jun 2027): students design it (e.g. a wet vs dry half using the divider, or PLA "compostable" plastic vs PE).
Sampling schedule
| What | When | How |
|---|---|---|
| Sensors (CO2, T, RH, gas resistance ×2, core T, soil A/B) | every 60 s, automatic | ESPHome → Home Assistant → InfluxDB |
| Automatic respiration test | nightly 02:00–02:30 | servo closes intake, fan and mister off, CO2 slope computed on the node |
| Manual respiration test | Tue + Fri 12:00 | protocol below, logged on paper and in Grafana |
| Window-bag VDI photo | Mon/Wed/Fri | phone on a fixed cardboard jig 20 cm from glass, same lamp |
| Substrate pH (1:5 extract) | weekly, Monday | 10 g fresh substrate + 50 mL distilled water, shake 1 min, settle 30 min, shared PHPEN |
| Gravimetric moisture | weekly | 20 g sample from 2–4 cm and 9–11 cm depth, dried 60 °C 24 h → % water (wet basis) |
| Invertebrate bait count | weekly, Thursday | 3 carrot slices (3×3 cm) on the surface, lifted after 24 h; count springtails, isopods and worms under each |
| Isopod hide count | weekly | lift both cork pieces, count Porcellio / Armadillidium |
| Sniff panel | weekly, Friday | 3 students, blind, rate odour 0–3 at 30 cm from the lid and at the exhaust |
| Litter-bag harvest | Run 1: 14 Dec; Run 2: 15 Mar | lift bag, count animals inside, rinse over a 2 mm sieve, dry, weigh |
Visual Decomposition Index (VDI): 0 = intact; 1 = discoloured or mould visible; 2 = softened, < 25 % fragmented; 3 = 25–50 % fragmented or holes; 4 = > 50 % gone, shape lost; 5 = unrecognisable or gone.
Analysis
- % mass loss = (M0 − Mt − handling loss) / M0 × 100. Decay constant (Olson): k = −ln(Mt/M0) / t, in day⁻¹. Compare Run 1 k with Run 2 k.
- H1: mean ± SD per material (n = 3), bar chart with error bars. Kruskal–Wallis test (or one-way ANOVA for older students) in Google Sheets/LibreOffice. Rank order is compared with the predicted one.
- H2: coarse vs fine per material, ratio of means. Run 1 alone gives n = 3, which is low power, so it is reported as an effect size. Pool Run 1 and Run 2 for a t-test.
- Organism preference: animals counted per coarse bag at harvest (worms/isopods per bag by material), plus the isopod choice arena: a 2 L food box with 4 food discs (leaf, cardboard, carrot, peel), 10 Porcellio, counted every 15 min for 1 h, 3 trials. χ² against an equal split.
- H3: respiration rate (method below) is plotted against days since feeding and against core temperature. Q10 = (R2/R1)^(10/(T2−T1)) is fitted from nightly tests. Gas ratio R/R0 is plotted in Grafana as a 24 h median, with feeding events marked as HA annotations.
- Carbon budget (liceu extension): mg C respired per day (CO2 × 12/44) compared with g C lost from the bags plus the food added.
Expected outcomes and when
| Material (coarse) | by 14 Dec (28 d) | by March (Run 2, 90 d) |
|---|---|---|
| Bread | 40–80 % loss, heavy mould, VDI 4–5 | gone |
| Orange peel | 20–50 %, VDI 3 | 60–90 % |
| Lime leaves | 8–20 % (fine mesh 5–12 %) | 30–60 % |
| Cardboard | 10–25 % | 40–80 % |
| Cotton | 5–25 % (very variable) | 30–80 % |
| PE | 0 ± 2 % | 0 ± 2 % |
These are planning estimates for 20–23 °C and moist substrate. By mid-December, H1 is supported at the fast end only (bread and peel versus the rest). H2 will probably not be significant after 28 days and needs Run 2. H3a should be visible within 2 weeks of starting feeding. H3b needs the winter temperature range, so it shows by February. Expected respiration: 5–60 ppm/min headspace rise, i.e. roughly 10–100 mg CO2/h for the whole tank.
Engineering track
Problem statement: Design an indoor biological recycling unit, no bigger than a 50×30 cm shelf footprint, that processes the most class fruit/vegetable scraps per week. Along the way it must not release noticeable odour, must not let fungus gnats escape, and must keep the community aerobic and alive with ≤ 10 min of student work per school day.
Requirements and constraints
| # | Requirement | Measure | Target |
|---|---|---|---|
| R1 | Throughput | g fresh scraps fully processed per week (no recognisable food after 7 days) | ≥ 200 g/week by week 8 |
| R2 | Odour outside | sniff score at 30 cm; post-filter BME680 ratio R_out/R_room | ≤ 1 of 3; ≥ 0.85 |
| R3 | Aerobic | headspace CO2 median; H2S/sour smell | < 2000 ppm, never > 5000; none |
| R4 | Moisture | substrate water, wet basis (gravimetric); headspace RH | 60–75 %; 80–92 % |
| R5 | Temperature | core DS18B20 | 15–28 °C |
| R6 | Containment | gnats on the external yellow sticky card per week | ≤ 3 |
| R7 | Energy/noise | fan Wh/day; noise at 1 m | ≤ 15 Wh/day; ≤ 35 dB(A) (phone app) |
| C | Constraints | SELV inside only (12 V fan/servo, 24 V mister); mains only as COTS bricks on the shelf; budget = sub-BOM; no change to the bag grid during a run | – |
Candidate solutions (students compare these, not just build them)
| Sub-problem | Option A | Option B | Option C |
|---|---|---|---|
| Odour | passive vent: Ø 50 mm hole + mesh | activated-carbon tube (75 g, 10 cm bed) + 12 V 80 mm fan running continuously at 30 % | carbon tube + fan triggered by VOC/CO2 (state machine below) |
| Moisture | hand spray bottle, mL logged | 24 V ultrasonic mister in an external reservoir, fog drawn through the intake by the exhaust fan, RH loop | wick/drip from reservoir (rejected for v1: risk of waterlogging) |
| Aeration | 2 perforated Ø 20 mm PVC aeration tubes (passive chimney) | weekly hand-turning of the feeding zone only, with a fork, to 8 cm depth (never the bag grid) | scheduled fan exchange: 5 min every 30 min |
| Compartments | single bed | perforated acrylic divider (29×16 cm, Ø 10 mm holes on a 3 cm grid): left = feeding zone, right = undisturbed bag field | stacked migration tray for harvesting vermicompost (spring v4, in a BOXPLASTIC) |
Test criteria and methods
- Carbon-filter efficiency: E = 1 − (1 − R_out/R_room) / (1 − R_in/R_room), from the two BME680s during a fan-on period after feeding. Repeat at bed depths of 5 cm and 10 cm.
- Moisture stability: SD of soil A over 7 days, plus the number of manual waterings needed.
- Throughput: weigh the food added; check the feeding pocket after 7 days (food recognisable: yes/no).
- Odour: blind sniff panel. Containment: count the sticky card. Energy: fan duty-cycle minutes per day from HA history × 12 V × 0.12 A.
Iteration plan
| Version | Dates | Change | Data used to decide |
|---|---|---|---|
| v1 baseline | 16–22 Nov | passive vent, hand spray, fan off | sniff score, R_in, RH, CO2 |
| v2 | 23 Nov–2 Dec | carbon + fan: continuous 30 % (odd days) vs VOC-triggered (even days) | E, Wh/day, sniff score, RH drop |
| v3 | 3–11 Dec | mister RH loop + servo intake damper, enabling automatic nightly respiration test | RH SD, soil A trend, test success rate |
| v4 | Jan–Mar 2027 | student choice: carbon bed depth, divider feeding regime (chopped < 1 cm vs whole scraps), raising throughput to 300 g/week | R1–R6 |
Enclosure & build
Tank: TANK45, glass 50×30×30 cm (≈ 45 L), internal floor ≈ 49×29 cm. It sits on a bench at 75 cm height. Directly above it, on a wall shelf at ≥ 120 cm, are the RCD (30 mA) power strip, PSU12 and the mister's 24 V adapter, with a drip loop on every cable.
Layers (bottom → top)
| Layer | Depth | Volume | Material |
|---|---|---|---|
| Drainage / leachate sump | 3 cm | 4.3 L | LECA (expanded clay) 8–16 mm, rinsed |
| Separator | – | 50×30 cm | fibreglass MESH (stops worms entering the sump) |
| Substrate, lower | 7 cm | 10 L | substrate recipe (see Biology) |
| Litter-bag plane | at 5 cm below the surface | – | 27 grid bags + 6 window bags, tags on lines to the surface |
| Substrate, upper | 5 cm | 7 L | same recipe |
| Leaf-litter top | 2–3 cm | 2 L | whole dry lime/maple leaves, 2 cork-bark hides 10×10 cm |
| Headspace | ≈ 12 cm | ≈ 17 L | air, sensors under the lid |
Two aeration tubes (Ø 20 mm PVC conduit, 25 cm long, 5 mm holes every 2 cm on the lower 15 cm, bottom capped, mesh-covered top) stand in the rear corners, touching the LECA. They double as leachate check and siphon ports: a 6 mm TUBING line and a 60 mL syringe go down one tube.
Lid (from ACRYLIC 3 mm): 50×30 cm in two pieces, sitting on 9×6 mm EPDM foam tape stuck around the rim (this seal makes the respiration test possible).
- Fixed rear strip, 50×10 cm, siliconed to two acrylic cleats inside the rim. It carries:
- Exhaust port (right): Ø 50 mm hole → 15 cm PVC pipe with a perforated end cap at the bottom, a mesh disc, 75 g activated-carbon pellets (10 cm bed) and a top mesh disc. An 8×8 cm acrylic adapter plate holds the 12 V 80 mm FAN on top, blowing out. BME680 #2 (0x76) sits in a perforated cap 3 cm above the fan outlet (post-filter air).
- Intake port (left): Ø 20 mm hole fed by a 16 mm ID hose from the mister reservoir, covered with stainless MESH. An SG90 servo mounted on top of the lid drives an acrylic flap over the port: open = 90°, closed = 0° onto a foam pad.
- 4 × PG7 glands: soil A, soil B, DS18B20, and one I2C cable to the under-lid sensor pair.
- Under the strip: SCD41 and BME680 #1 (0x77) on a 6×4 cm acrylic plate, 2 cm below the lid, sensor faces pointing sideways (not up, to avoid drips). Their PCBs are conformal-coated with the sensor openings masked.
- Hinged front panel, 50×20 cm: 2 × 40 mm hinges with M3 stainless bolts and nylock nuts, a knob, and a self-adhesive 0.5 mm stainless MESH patch over a 4×8 cm slot for passive-vent tests in v1 (taped shut from v2 on).
- Divider: acrylic 29×16 cm, perforated (see Engineering), pushed into the substrate at 20 cm from the left wall. Feeding zone = left 20 cm; bag field = right 29 cm. The bag grid is then 4 columns × 4 rows in the right zone plus 3 columns × 4 rows in the left zone, with feeding pockets kept to the top 3 cm and rotated among 4 spots in the left zone.
Node box: BOX (IP65, 150×110×70 mm) on an acrylic L-bracket screwed to the bench back wall, its bottom 10 cm above the tank rim, right side. Glands on the underside, cables with drip loops. The box holds the TERMBOARD + ESP32, BUCK (12 → 5 V), MOSFET (fan), RELAY (24 V mister) and the OLED behind a siliconed clear-acrylic window in the box lid.
Mister reservoir: RESERVOIR 10 L on the bench, left of the tank, below the node box. MIST float inside. Two holes in the reservoir lid: a 10 mm meshed fresh-air inlet and a 20 mm fog outlet → 60 cm of 16 mm hose → tank intake. Fog is drawn in by the exhaust fan running at 25–30 %.
flowchart TB
subgraph SHELF["Wall shelf above, mains zone, RCD 30 mA strip"]
PSU["PSU12 12 V 5 A brick"]
AD24["Mister 24 V adapter"]
end
subgraph NODE["Node box mc-01-rot IP65"]
ESP["ESP32 on TERMBOARD + OLED"]
BUCK["BUCK 12 to 5 V"]
MOS["MOSFET fan GPIO17"]
REL["RELAY mister GPIO23"]
end
subgraph LID["Acrylic lid with EPDM gasket"]
EXH["Exhaust tube with 75 g carbon"]
FAN["FAN 80 mm 12 V"]
BME2["BME680 no.2 post-filter 0x76"]
SERVO["SG90 intake damper GPIO26"]
UNDER["SCD41 and BME680 no.1 under lid"]
end
subgraph TANK["TANK45 50x30x30 cm"]
HEAD["Headspace about 17 L"]
LITTER["Leaf litter 2-3 cm, cork hides"]
BAGS["Litter-bag plane at 5 cm, 27 + 6 window bags"]
SOILA["SOIL A feeding zone GPIO32"]
SOILB["SOIL B bag field GPIO33"]
DS["DS18B20 core at 8 cm GPIO4"]
LECA["LECA sump 3 cm"]
AER["2 aeration and leachate tubes"]
end
RES["RESERVOIR 10 L with MIST float"]
PSU --> BUCK --> ESP
PSU --> MOS --> FAN
AD24 --> REL --> RES
RES -- "fog hose 16 mm" --> SERVO --> HEAD
HEAD --> EXH --> FAN --> BME2
UNDER --> ESP
BME2 --> ESP
SOILA --> ESP
SOILB --> ESP
DS --> ESP
ESP --> SERVO
Step-by-step build (≈ 14 h of team time over weeks 1–3)
| # | Step | Time | Tools |
|---|---|---|---|
| 1 | Clean the tank (water + vinegar, no detergent), dry, check the rim is flat | 20 min | cloth, spirit level |
| 2 | Mark and cut the lid: 50×10 and 50×20 cm, plus the divider 29×16 cm and an 8×8 cm fan plate. Score 8–10 times, snap over the bench edge | 60 min | acrylic scoring knife, steel ruler, clamps, safety glasses |
| 3 | Drill: Ø 50 mm (hole saw, slow, wood backing), Ø 20 mm, 4 × Ø 12.5 mm (PG7), M3 hinge holes, divider Ø 10 mm holes | 75 min | cordless drill (teacher), step drill, hole saw, deburring tool |
| 4 | Glue the cleats under the fixed strip, apply EPDM tape to the rim, fit the hinges and knob. Silicone cures 24 h | 45 min | SILICONE, gun, screwdriver |
| 5 | Build the exhaust tube: drill the end cap with 15 × Ø 6 mm holes, add mesh discs, rinse and dry the carbon, fill 75 g, fit the fan plate and fan, BME680 #2 cap | 60 min | hacksaw, file, scale |
| 6 | Make 2 aeration tubes (drill holes, cap the bottoms, mesh the tops) | 30 min | drill 5 mm |
| 7 | Fit the servo damper: flap 3×3 cm acrylic on the servo horn, foam pad on the port, servo screwed to the lid | 40 min | M2 screws, hot-melt glue (outside only) |
| 8 | Node box: drill 10 × PG7 holes, mount TERMBOARD, BUCK (set to 5.0 V before connecting the ESP32), MOSFET, RELAY, OLED window. Wire with ferrules and label every cable | 2.5 h | multimeter, ferrule crimper, wire stripper, label tape |
| 9 | Flash ESPHome, bench-test every sensor and actuator, run BME680 burn-in for 48 h on the bench | 2 h + 48 h | laptop, USB cable |
| 10 | Seal the soil probes (conformal coat + heat-shrink over the top edge), calibrate soil probes and DS18B20 (see Instrumentation) | 90 min | heat gun, cups, oven-dried substrate |
| 11 | Make litter bags: cut mesh 13×7 cm, fold, sew 3 sides, fill 3.00 g, sew shut, attach the tag line. 33 grid/window bags + 6 travel bags, plus 27 for Run 2 later | 3 h (whole team) | scissors, needle, fishing line, 0.01 g scale |
| 12 | Layer the tank: LECA, mesh, lower substrate, aeration tubes, divider, probes, rest 3 days to settle | 60 min | gloves, trowel, measuring jug |
| 13 | Mount the node box and reservoir, route cables (drip loops, no cable over the open lid edge), connect the fog hose | 45 min | cable ties, adhesive cable clips |
Biology
Organisms and Romanian sourcing
| Organism | Common name (EN / RO) | Qty | Role | Source in Romania |
|---|---|---|---|---|
| Eisenia fetida | red wiggler / râmă roșie californiană | 150 g (≈ 300–400 worms) | shred and digest scraps, mix the bed | vermicompost (lombricultură) farms and OLX ads for "râme californiene"; fishing-bait shops sell small boxes (check the species is E. fetida, not Dendrobaena) |
| Porcellio scaber | common rough woodlouse / porcușor de pământ | 15–20 | shred leaf litter, cardboard | collect free from under logs/bark in the school garden (uncontaminated site), or buy a culture from terraristics shops/OLX ("izopode") |
| Armadillidium vulgare | pill woodlouse / porcușor ghem | 15–20 | same, more drought-tolerant; easy to tell apart for counting | as above (common in Bucharest gardens) |
| Folsomia candida | white springtail / colembole | 1 culture (≈ 200 mL) | graze fungi and mould, suppress mould blooms | terrarium/bioactive shops and OLX ("colembole") |
| Pleurotus ostreatus | oyster mushroom / păstrăv de fag | 500 g grain spawn (100 g used, the rest for Run 2 and spares) | white-rot fungus that breaks down lignin and cellulose | mushroom-growing suppliers / agro shops and eMAG ("miceliu pleurotus") |
| Microbes | compost and leaf-mould bacteria/fungi | 1 L mature compost + 0.5 L leaf mould | inoculum | school garden compost or the worm supplier's vermicompost; leaf mould from under the school's trees |
No vertebrates. Isopods and worms are invertebrates, which is compliant with the brief.
Substrate recipe (≈ 17 L, made in a 30–60 L tub; wear gloves)
- 6 L coco coir (one 650 g brick hydrated with 3 L water, squeezed)
- 6 L sieved (10 mm) school-garden soil and mature compost, 1:1. Commercial "compost/humus" only if it has no added fertiliser.
- 3 L brown corrugated cardboard (≈ 250 g dry), shredded into 1–2 cm pieces, no glossy or coloured print
- 2 L shredded dry leaves (lime/maple)
- 1 L mature compost + 0.5 L leaf mould (the inoculum)
- 100 g eggshell (boiled 5 min, dried, crushed) for calcium for isopods and as a pH buffer
- Water to "wrung-out sponge" moisture: a hard squeeze gives 1–3 drops (≈ 65–70 % water, wet basis). Record the total water added.
- Weigh a 200 g sample, dry it, and record the dry fraction to estimate the bed's dry mass (expected ≈ 4 kg) for the mass-specific respiration rate.
Establishment and acclimation
- Day 0 (Nov 9): layer the bed, insert the probes, close the lid, run the fan base schedule. Watch CO2, T and soil for 3 days. The core must stay < 30 °C; if it heats up, the bed is too rich, so mix in 1 L dry cardboard.
- Day 0: start a Pleurotus pocket in a separate 2 L lidded box. 200 g cardboard is soaked in boiling water for 1 h (pasteurisation), cooled and drained, then layered with 50 g spawn. It sits in the dark at room temperature for 2–3 weeks until white. Half goes into the tank on Dec 1 (rear-right corner, 5 cm deep); the rest makes the Run 2 "pre-colonised cardboard" bags.
- Day 3 (Nov 12): add the worms on the surface under room light. They burrow in within 30 min; any that stay on the surface after 2 h mean conditions are wrong (check moisture and pH). Day 4: add the springtail culture and the isopods under the cork hides.
- Days 3–7: no feeding beyond the bed's own cardboard and leaves. Weekly checks start.
- Nov 16: bury the Run 1 bags in the randomised map, then start feeding.
Feeding (left feeding zone only, rotate among 4 pockets, bury 2–3 cm under the litter)
- Weeks 4–5: 50 g twice a week. Weeks 6–8: up to 100 g twice a week if the previous food has gone. Always add an equal volume of shredded cardboard ("browns").
- Freeze all scraps for ≥ 48 h, then thaw. This kills gnat and fruit-fly eggs and softens tissue. Chop to < 2 cm.
- OK: carrot, cucumber, lettuce, squash/pumpkin, apple/pear cores, banana peel, melon rind, coffee grounds (≤ 20 % of a feed), loose tea leaves, eggshell.
- NOT allowed: meat, fish, bones, dairy, eggs (other than shell), oily/fried/salty/cooked sauced food, bread and pasta in bulk (bread only inside test bags), citrus, onion, garlic and chilli beyond the 3 g orange-peel test bags, pet faeces, glossy or coloured paper, treated or painted wood, pesticide-sprayed plants, any "compostable" plastic outside test bags.
Hygiene
- Nitrile gloves for every hand contact; wash hands afterwards. Lid opened ≤ 10 min. No eating or drinking at the bench.
- Mould: white mycelium and pale mould are normal and tolerated. Green, black or pink fuzzy mould on the surface: cover it with 1 cm of dry leaves or remove it with tongs into a sealed bag. Never shake mouldy material. Students with asthma or a known mould allergy do not do harvests or sieving. Harvest and sieving are done with FFP2 masks, next to an open window, with no fans blowing toward people.
- Fungus gnats: frozen food, food always buried, 0.5 mm mesh on every vent, a yellow sticky card outside the lid and one inside on the litter. If more than 10 per week on the inside card: let the top 2 cm dry for 3 days and add BTI (Bacillus thuringiensis israelensis) granules to the misting reservoir/top watering at the label dose.
- Odour: sour or rotten-egg smell means anaerobic conditions. Stop feeding, turn the feeding zone, add 1 L dry cardboard, run the fan at 60 % for 24 h.
Instrumentation
| Catalog ID | Qty | Placement (exact) | Interval | Purpose |
|---|---|---|---|---|
| SCD41 | 1 | under the fixed lid strip, centre, 2 cm below the lid (≈ 10 cm above the litter) | 60 s (periodic mode) | headspace CO2 = community respiration; also T/RH for the humidity loop |
| BME680 | 2 | #1 (0x77): next to the SCD41, raw headspace air. #2 (0x76): 3 cm above the fan outlet, post-carbon air | 60 s (heater 320 °C / 150 ms) | "smell" (VOC proxy) in and out of the filter; P, T, RH |
| DS18B20 | 1 | vertical, tip at 8 cm depth, centre of the bag field (between grid cells) | 60 s | compost core temperature (Q10, overheating alarm) |
| SOIL | 2 | A: feeding zone, 10 cm from the left wall, vertical to the probe line (senses ≈ 0–6 cm). B: bag field, 12 cm from the right wall, same depth | 60 s, mean of 10 reads | moisture in the fed vs undisturbed compartment |
| OLED | 1 | node box lid window | 5 s refresh | live CO2, R/R0, core T, soil A/B, mode, Wi-Fi |
| FAN | 1 | top of the exhaust tube | PWM | odour venting, aeration, drawing fog in |
| MIST | 1 | in the 10 L reservoir | relay on/off | headspace RH |
| SERVO | 1 | top of the lid, intake damper | on demand | seals the intake for respiration tests |
| Shared | – | PHPEN (team pool), 0.01 g scale | weekly | substrate pH, bag masses |
What the BME680 does and does not measure. Its gas channel is a heated metal-oxide (MOX) film whose electrical resistance drops when reducing gases are present: ethanol, acetone, aldehydes, esters, terpenes (limonene from orange peel), H2S and amines from rotting food. It gives one number for the total of all of them. It does not identify which gas is present, does not give ppm, does not measure CO2 (the SCD41 does), and responds weakly to ammonia. It is affected by humidity and temperature and drifts over days. Therefore:
- Run a 48 h burn-in first.
- Use the ratio R/R0, where R0 is the 24 h median in the clean classroom before installation, re-checked monthly with the lid open for 30 min.
- Compare the two sensors under identical conditions (#1 vs #2) rather than absolute values.
- Validate against the blind sniff panel.
We use the raw bme680 ESPHome platform (gas resistance in Ω). Bosch's BSEC "IAQ" index is an optional extra for advanced students, with the caveat that it was tuned for living rooms, not compost. The BME680 RH reading is unreliable above 90 % RH, so the humidity loop uses the SCD41's RH.
Pin assignment (standard map only)
| Function | GPIO | Device |
|---|---|---|
| I2C SDA / SCL | 21 / 22 | SCD41 0x62, BME680 #1 0x77, BME680 #2 0x76 (SDO to GND), SSD1306 0x3C. Bus at 50 kHz; total cable ≤ 1.5 m, 4-core shielded |
| 1-Wire | 4 | DS18B20 (4.7 kΩ pull-up to 3.3 V on TERMBOARD) |
| Analog A | 32 | SOIL A (feeding zone) |
| Analog B | 33 | SOIL B (bag field) |
| PWM out 2 (fan) | 17 | MOSFET module → FAN, ledc 25 kHz |
| Relay 1 | 23 | RELAY → switches the 24 V DC output of the mister adapter (low-voltage side only) |
| Servo 1 | 26 | SG90 intake damper, 50 Hz, powered from 5 V BUCK |
| Unused | 16, 18, 19, 25, 27, 34, 35, 36, 39, 13, 14, 5, 15, 12 | free for student extensions (e.g. a FLOAT on GPIO13 for the reservoir) |
| Reserved | 0, 2 | boot / LED |
Entity ids: mc_01_co2, mc_01_air_temp, mc_01_air_rh, mc_01_gas_res_in, mc_01_gas_res_out, mc_01_gas_ratio_in, mc_01_core_temp, mc_01_soil_moisture_a, mc_01_soil_moisture_b, mc_01_resp_rate, mc_01_fan, mc_01_mister, mc_01_intake.
Calibration
- SOIL A/B: in the real substrate, record raw volts in (1) air, (2) oven-dried substrate in a 500 mL cup, (3) saturated substrate. Then make 3 intermediate mixes, measure them gravimetrically, and fit a line →
calibrate_linearto % water (wet basis). Re-check monthly with the weekly gravimetric samples. - DS18B20: ice-water slurry (0.0 °C) and room water against a reference glass/digital thermometer; set an
offsetif > 0.3 °C. - SCD41:
automatic_self_calibration: false, because the tank never sees fresh air for long enough. Forced recalibration to 420 ppm: hold it at an open window outdoors for 5 min after a 3 min warm-up, monthly. Cross-check side by side with the Living Earth SCD41 for 1 h (should agree within ± 50 ppm). - BME680: 48 h burn-in; R0 baseline as above; check that #1 and #2 agree within 15 % in the same air before installing #2 in the exhaust.
- Scale: check with a 100 g calibration weight before each weighing session.
Respiration test protocol (30 min, manual version; the automatic nightly version is identical)
- Do not open the lid or feed for ≥ 2 h beforehand. Note the time, core T and air T.
- In HA, press "Start respiration test". The node turns the fan and mister off and the servo closes the intake. Cap the exhaust outlet with the rubber cap (manual tests only).
- Log CO2 every 60 s for 30 min. Discard minutes 0–5 (mixing). Abort if CO2 > 4500 ppm (sensor limit 5000).
- Slope s (ppm/min) = linear regression of minutes 5–30 (Sheets
SLOPE). The node also publishes (C25 − C5)/20. - CO2 production = s × 10⁻⁶ × V / Vm, where V = headspace 17 L (measure the actual headspace height) and Vm = 24.2 L/mol at 22 °C (scale by (273 + T)/295). Example: s = 20 ppm/min → 1.4 × 10⁻⁵ mol/min = 14 µmol/min → × 44 = 0.62 mg CO2/min = 37 mg CO2/h → ÷ 4 kg dry bed = 9 mg CO2/h/kg.
- Re-open the intake and run the fan at 60 % for 10 min. Record any leak notes (the gasket condition is checked monthly with a smoke/incense test held outside the gasket).
- Known bias: some CO2 leaks through the gasket and carbon tube, so rates are slight underestimates. Use them for comparisons, not absolutes.
Automation
All logic runs on the ESP32 (it keeps working if Wi-Fi or HA is down). HA provides visibility, override and alerts.
Setpoints
| Parameter | Value |
|---|---|
| Base aeration | fan 40 % for 5 min every 30 min |
| Odour/CO2 vent trigger | gas ratio R/R0 (#1) < 0.60 or CO2 > 2500 ppm |
| Vent exit | R/R0 > 0.75 and CO2 < 1500 ppm, min 5 min |
| Vent duty limit | max 20 min continuous at 100 %, then 10 min at 40 %; max 6 h at 100 % per day. If RH < 75 %, vent capped at 60 % |
| Humidify trigger | SCD41 RH < 82 % and soil A < 70 % (calibrated); not during a test |
| Humidify action | mister on + fan 25 % (draws fog), max 90 s per burst, min 10 min between bursts, max 6 bursts per hour |
| Humidify stop | RH ≥ 90 % or burst timer |
| Too dry / too wet alerts (HA notification) | soil A or B < 55 %: "add 200 mL water by hand, evenly". > 80 %: "stop misting, add 1 L dry cardboard" |
| Core temperature alert | < 10 °C or > 30 °C |
| Respiration test | daily 02:00, 30 min, abort at CO2 > 4500 ppm or R/R0 < 0.4; hard timeout 35 min → intake opens |
| Fail-safe | SCD41 missing > 5 min: fan fixed 60 %, 10 min on / 20 min off; mister disabled; tests disabled. BME680 #1 missing: VOC trigger off, CO2 trigger remains. Soil A missing: mister uses RH only, max 3 bursts per hour. On boot: intake opens, mister off, fan 40 % for 2 min |
stateDiagram-v2
[*] --> Boot
Boot --> Base: intake open, mister off, fan 40 pct 2 min
Base --> Vent: gas ratio below 0.60 or CO2 above 2500
Vent --> Base: ratio above 0.75 and CO2 below 1500
Vent --> VentRest: 20 min at full speed
VentRest --> Vent: after 10 min at 40 pct
Base --> Humidify: RH below 82 and soil A below 70
Humidify --> Base: RH at least 90 or 90 s elapsed
Base --> RespTest: 02.00 schedule or HA button
RespTest --> Base: 30 min done, slope published
RespTest --> Vent: CO2 above 4500 or timeout 35 min
Base --> FailSafe: SCD41 missing 5 min
Vent --> FailSafe: SCD41 missing 5 min
Humidify --> FailSafe: sensor missing
FailSafe --> Base: sensor back for 5 min
Base --> Manual: HA override
Manual --> Base: Auto selected or 2 h timeout
ESPHome implementation outline (students fill in the full YAML)
sensor: scd4x(update_interval 60s,automatic_self_calibration: false).sensor: bme680×2 (addresses 0x77/0x76,heater: {temperature: 320, duration: 150ms}).dallas_tempon GPIO4.adcon GPIO32/33 withattenuation: 12db, asliding_window_moving_average(window 10) andcalibrate_linear.output: ledcGPIO17 at 25 kHz →fan: speed"Rot fan".switch: gpioGPIO23 "Rot mister".servoonledcGPIO26 at 50 Hz.- A
templateR/R0 sensor (R0 is anumberentity set from HA).select"Mode" with options Auto / Manual / Test.button"Start respiration test" →script(fan off, mister off, servo 0°, delays, publishesmc_01_resp_rate). - Triggers via
on_value_range, for example:sensor: - platform: scd4x co2: name: "mc_01_co2" on_value_range: - above: 2500 then: - if: condition: lambda: 'return id(mode).state == "Auto";' then: - script.execute: vent_cycle - Duty limits and timeouts use
scriptwithmode: single,delay, and aninterval: 60ssupervisor that checkshas_state()on every sensor for the fail-safe. - Manual override in Home Assistant: dashboard card with Mode select, fan speed slider (0–100 %), mister toggle, intake open/close, test button. Manual mode auto-reverts to Auto after 2 h (template script on the node). Mains is not involved anywhere: the fan and servo are 12/5 V, the mister is 24 V DC switched on its low-voltage side, and no smart plug is needed for this ecosystem.
Operations
Daily (school days, ≤ 10 min, task rota on the tank)
- Glance at the OLED and HA dashboard: Mode = Auto; CO2 < 2000; soil A/B 60–75 %; core T 15–28 °C; no alerts.
- Check the reservoir level (refill to 8 L with tap water that has stood 24 h; never above the MIST float limit).
- Look through the glass: worms on the glass or surface? sour smell? standing water in the LECA? Note it in the logbook.
- Count gnats on the outside sticky card (tally).
Weekly
- Mon: window-bag photos + VDI; pH 1:5 extract; gravimetric samples (2 depths).
- Tue/Fri: feed per plan (weigh food and cardboard), manual respiration test (Tue 12:00 is the pre-feed test, Fri 12:00 is ≈ 72 h after feeding).
- Thu: carrot bait slices out. Fri: count bait slices + cork hides; sniff panel; review the Grafana week and annotate events.
- Fri: empty the mister reservoir, rinse, wipe with 3 % hydrogen peroxide or dilute vinegar, rinse, refill (stops biofilm/Legionella-type growth).
- Check leachate: if > 1 cm of water stands in the LECA, siphon it out via an aeration tube; dilute 1:10 and use it on school plants (not on food crops).
Lab notebook (paper, numbered pages, plus the shared sheet)
- Date, time, initials; food type and mass in; cardboard mass in; water added (mL); lid-open minutes.
- Observations (mould colour and location, animals seen, smell), VDI scores, counts, pH, gravimetric values.
- Respiration test raw values (C5, C25, slope, T) and any deviations (lid opened, test aborted).
- Any firmware or setpoint change (version, reason). The litter-bag map and bag mass table, with M0 to 0.01 g.
Maintenance
- Activated carbon: replace (75 g) when R_out/R_room < 0.85 during venting or every 8 weeks.
- Mesh and sticky cards: replace cards every 2 weeks.
- Re-coat soil probe tops if bare copper or swelling is visible; recalibrate monthly.
- SCD41 FRC monthly; BME680 R0 monthly; gasket check monthly.
- Thin the worm population if it exceeds ≈ 300 g (estimated from the March harvest), giving the extras to the Living Earth team or the school compost.
End-of-term plan (14–18 Dec)
- Dec 14: harvest Run 1 (count animals in bags, rinse, dry). Dec 15: insert Run 2 bags (new randomised map). Dec 16–18: final weighing, first results poster.
- Before winter break (approx. Dec 19 – Jan 10): one feed of 150 g frozen scraps + 1 L cardboard on Dec 17. Reservoir full. Mode Auto. HA alerts to the teacher's phone (core T, CO2, soil, node offline).
- If the school heating drops below 10 °C, decomposition just slows. E. fetida tolerates ≥ 5 °C, so no heater is added (keeps the design SELV-simple). The data becomes a natural low-temperature treatment for the Q10 analysis.
- If the node is offline for > 24 h over the break, the teacher checks the room. The bed is safe for 3 weeks unattended.
- End of school year (June 2027): Run 3 harvest, vermicompost harvested by light migration (food on one side for 2 weeks, scoop the other side), organisms rehomed to the school compost bin, tank cleaned and stored, data archived (InfluxDB + CSV).
Safety & risks
The general rules still apply: no 230 V anywhere inside or near the tank. The fan and servo are 12/5 V. The mister is 24 V DC with its own certified adapter. All bricks sit on the shelf above, on the RCD strip, with drip loops. The node box is outside the tank, above the rim, with cables entering through glands. Students never open or modify mains devices.
| Risk | Specific cause here | Mitigation |
|---|---|---|
| Mould spores / allergens | bread and peel bags, surface mould | bread only in buried bags; lid open ≤ 10 min; FFP2 + window open for harvest/sieving; asthma/allergy students excluded from harvest; no shaking; springtails graze mould |
| Fungus gnats / fruit flies | soft food, wet surface | freeze food 48 h, bury it, 0.5 mm mesh on all vents, inside and outside sticky cards, BTI if needed |
| Odour in the classroom | VOCs, H2S if anaerobic | carbon filter + VOC-triggered fan, feeding limits, sniff panel, alerts |
| Anaerobic bed | overfeeding, > 80 % moisture, compaction | aeration tubes, base fan schedule, CO2 alert, soil > 80 % alert, add dry cardboard, turn the feeding zone only |
| Leachate | over-watering, wet food | 3 cm LECA sump, weekly check, siphon via tube with a syringe (no mouth siphoning), dispose diluted on plants |
| Mister water hygiene | warm standing water, biofilm, aerosol | weekly empty/clean/dry; tap water changed weekly; mister off during lid-open; fog goes only into the closed tank |
| Electrical / water | condensation on the lid, refilling the reservoir | node box above the rim with glands; reservoir lid kept closed; refill with the MIST adapter unplugged at the strip (teacher) or the mister switched off in HA; MIST checked for a built-in low-water cut-off (if absent, add a FLOAT on GPIO13 as a student mod) |
| Sharp tools / acrylic | build phase | teacher operates drill/hole saw; safety glasses; deburr edges |
| Pathogens | soil, compost | gloves, handwashing, no food or drink, no meat/dairy/pet waste in the system |
| Organism welfare | drying, overheating, escape | RH/soil loop, core T alerts, gasket + mesh, divider holes only 10 mm, release only to the school compost (never to the wild: E. fetida is non-native to soils) |
| Glass tank | knock or drop (≈ 30 kg filled) | on a stable bench, front 5 cm from the bench edge, never moved full |
Educational outcomes & assessment
| # | Outcome | Track | Evidence produced |
|---|---|---|---|
| 1 | Formulate testable hypotheses and identify independent/dependent/controlled variables for decomposition | Science | written experimental plan with a variables table and randomised bag map (assessed before burial) |
| 2 | Run a replicated, controlled field method (litter bags, travel bags, PE control) and quantify uncertainty | Science | bag mass table (M0, Mt, handling correction), mean ± SD, k values, error bars |
| 3 | Convert sensor data into a physical rate (CO2 production in mg/h) and relate it to conditions (feeding, temperature, Q10) | Science | respiration test sheets, Grafana screenshots with annotations, slope calculation, Q10 graph (Feb) |
| 4 | Explain what a sensor does and does not measure (BME680 vs SCD41) and validate it against human observation | Science + Engineering | short report: R/R0 vs sniff-panel scatter plot, discussion of limits |
| 5 | Define requirements, compare candidate solutions and iterate with data (odour, moisture, aeration) | Engineering | requirements table, A/B test results (continuous vs triggered fan), filter efficiency E, decision log v1→v3 |
| 6 | Operate a living system responsibly and safely over months | Both | logbook completeness, maintenance checklist sign-offs, end-of-term poster and 5-min presentation |
Sub-BOM
Cost-cut 2026-10-20: BTI granules removed (buy only if fungus gnats appear). PPE, pens and calibration solutions are shared project items.
Price basis: Romanian retail incl. VAT, Oct 2026 estimates. Electronics: optimusdigital.ro / sigmanortec.ro / cleste.ro (SCD41 modules are listed at sigmanortec.ro). Hardware: dedeman.ro / leroymerlin.ro. Organisms: OLX / vermiculture and terrarium sellers. Fallback: AliExpress.
| ID / item | Qty | Unit RON | Line RON | Basis |
|---|---|---|---|---|
| ESP32 | 1 | 45 | 45 | Optimus/Sigmanortec DevKitC 38-pin |
| TERMBOARD | 1 | 35 | 35 | screw-terminal expansion board |
| OLED | 1 | 22 | 22 | SSD1306 0.96" I2C |
| BME680 | 2 | 85 | 170 | breakout, Sigmanortec/Optimus |
| SCD41 | 1 | 250 | 250 | Sensirion SCD41 module (≈ 49 EUR) |
| DS18B20 | 1 | 15 | 15 | waterproof 1 m |
| SOIL | 2 | 12 | 24 | capacitive v2.0 (TL555 version) |
| FAN | 1 | 30 | 30 | 80 mm 12 V quiet PC fan |
| MIST | 1 | 75 | 75 | 24 V ultrasonic mist maker + adapter |
| MOSFET | 1 | 10 | 10 | D4184 module |
| RELAY | 1 | 8 | 8 | 1-ch 5 V relay (switches 24 V DC) |
| SERVO | 1 | 12 | 12 | SG90 |
| PSU12 | 1 | 60 | 60 | 12 V 5 A certified brick + DC jack |
| BUCK | 1 | 12 | 12 | LM2596 |
| BOX | 1 | 40 | 40 | IP65 150×110×70 |
| GLAND | 14 | 1.5 | 21 | PG7 (10 box + 4 lid) |
| TANK45 | 1 | 180 | 180 | glass aquarium 50×30×30, pet shop |
| ACRYLIC | 0.6 | 120 | 72 | 0.6 of a 50×100 3 mm sheet (lid, divider, plates) |
| MESH | 0.25 | 30 | 8 | m²; separator + vents + fine bags |
| SILICONE | 1 | 35 | 35 | aquarium-safe tube |
| TUBING | 1 | 5 | 5 | m, leachate siphon |
| RESERVOIR | 1 | 30 | 30 | 10 L food-grade with lid |
| BIO: Eisenia fetida 150 g | 1 | 65 | 65 | incl. courier |
| BIO: isopod cultures (P. scaber, A. vulgare) | 2 | 35 | 70 | buy; 0 RON if collected locally |
| BIO: Folsomia candida culture | 1 | 35 | 35 | terrarium seller |
| BIO: Pleurotus ostreatus grain spawn 500 g | 1 | 30 | 30 | mushroom supplier/eMAG |
| SUB: coco coir brick 650 g | 1 | 15 | 15 | Dedeman |
| SUB: organic compost 20 L, no fertiliser | 1 | 25 | 25 | Dedeman/Hornbach |
| SUB: LECA 10 L | 1 | 25 | 25 | Dedeman |
| SUB: cork bark pieces | 1 | 20 | 20 | pet/terrarium shop |
| CONS: activated carbon pellets 1 kg | 1 | 45 | 45 | aquarium carbon (≈ 13 refills of 75 g) |
| HW: PVC pipe 50 mm 1 m + 2 end caps | 1 | 20 | 20 | Dedeman |
| HW: PVC conduit 20 mm 2 m + caps | 1 | 12 | 12 | Dedeman |
| HW: hose 16 mm ID, 1.5 m (fog duct) | 1 | 18 | 18 | Dedeman |
| HW: EPDM foam gasket 9×6 mm, 5 m | 1 | 25 | 25 | Dedeman |
| HW: 2 hinges + M3 stainless bolts/nylocks + knob | 1 | 20 | 20 | Dedeman |
| CONS: garden netting 5 mm, 1 m² | 1 | 15 | 15 | coarse bags |
| CONS: fishing line + 50 plant labels + marker | 1 | 25 | 25 | bag tethers/tags |
| TOOL: pocket scale 0.01 g / 200 g + 100 g weight | 1 | 50 | 50 | eMAG |
| CONS: yellow sticky traps, 20 | 1 | 20 | 20 | garden shop |
| CONS: nitrile gloves, 100 | 1 | 40 | 40 | pharmacy/eMAG |
| CONS: FFP2 masks, 10 | 1 | 25 | 25 | pharmacy |
| TOOL: stainless sieve 2 mm, 20 cm | 1 | 30 | 30 | kitchen/lab |
| CONS: distilled water 5 L | 2 | 7.5 | 15 | supermarket |
| CONS: 4-core shielded cable 5 m, Qwiic/JST leads, ferrules, heat-shrink | 1 | 35 | 35 | Optimus |
| CONS: conformal coating (share of 1 can) | 0.25 | 40 | 10 | shared with other teams |
| TOOL: 2 L food box (choice arena) | 1 | 15 | 15 | supermarket |
| CONS: spray bottle 500 mL | 1 | 10 | 10 | supermarket |
| Subtotal | 1 874 RON (≈ 367 EUR) | electronics + enclosure 1 159; bio/consumables 715 |
PHPEN, CALSOL, the hub (PI5, ROUTER) and the RCD power strip are project-wide shared items and are not counted here.
8-week timeline (Oct 26 – Dec 18, 2026)
Check the 2026/27 school calendar. If a holiday falls in this window, shift by one week; Dec 1 (Romania's national day) is a public holiday.
gantt
title Orchestra of Rot - build and Run 1
dateFormat YYYY-MM-DD
axisFormat %d %b
section Prepare
Order parts and organisms :p1, 2026-10-26, 5d
Collect leaves and isopods :p2, 2026-10-27, 8d
Lid and vent design review :p3, 2026-10-29, 2d
section Build
Cut and drill lid and vent tube :b1, 2026-11-02, 4d
Node box wiring and ESPHome :b2, 2026-11-03, 4d
BME680 burn-in and calibrations :b3, 2026-11-06, 4d
Sew and weigh litter bags :b4, 2026-11-04, 6d
section Establish
Layer substrate and settle :e1, 2026-11-09, 3d
Pleurotus cardboard colonisation :e2, 2026-11-09, 21d
Add worms springtails and isopods :e3, 2026-11-12, 2d
section Run 1
Bury Run 1 bags and start feeding :milestone, r0, 2026-11-16, 0d
v1 passive vent baseline :r1, 2026-11-16, 7d
v2 carbon fan AB test :r2, 2026-11-23, 10d
Isopod choice arena trials :r3, 2026-11-24, 8d
v3 mister loop and auto resp test :r4, 2026-12-03, 9d
Harvest Run 1 bags :milestone, r5, 2026-12-14, 0d
Dry weigh analyse and poster :r6, 2026-12-14, 5d
Insert Run 2 bags :milestone, r7, 2026-12-15, 0d
Winter break preparation :r8, 2026-12-17, 2d
2. The Domino Effect — EcoColumn
Node: mc-02-ecocolumn · Team of 3–4 · Footprint 90×40 cm, 180 cm tall rack · Water on board ≤ 35 L, all 12 V DC.
Concept (refined)
A four-level column on a boltless metal rack: a tilting "field" of two removable soil cassettes (lanes A/B) receives metered artificial rain; runoff carrying sediment and fertiliser drops through swappable filter cartridges into a 25 L "pond" with plants, snails and algae. Rain comes from a separate clean reservoir, so the only nutrient input to the pond is what washes off the field (closed nutrient accounting). The A/B lanes and interchangeable cassettes give every erosion experiment its own side-by-side control. An array of twelve 0.5 L jars beside the pond runs a fast fertiliser-dose bioassay, so eutrophication results exist by mid-December, while the pond itself is the slow, whole-system experiment that runs to June 2027.
Science track
Driving question: How much soil and fertiliser leaves a field during a storm, and what does it do to the pond downstream?
Hypotheses (testable by the team)
| # | Hypothesis | Comparison | Primary measure |
|---|---|---|---|
| H1 | A vegetated slope (≥ 80 % cover ryegrass/wheat) loses ≥ 70 % less sediment per storm than a bare slope at the same angle. Sub-question H1b: sediment from bare soil rises steeply with angle (5 → 20°). | Vegetated vs bare cassette, side by side; bare cassettes at 5/10/15/20° | Sediment yield, g/m² per event |
| H2 | Algal growth rises with nutrient dose: jars at 0 / 1 / 4 / 16 mg N/L (NPK 20-20-20) turn green in dose order within 14 days. | 4 doses × 3 replicate jars | Bench turbidity, photo green index, Secchi-card depth |
| H3 | A grass buffer strip on the bottom 20 % (8 cm) of a bare slope cuts sediment ≥ 50 % but cuts dissolved nitrate much less (dissolved N passes through, particle-bound P is trapped). | Bare vs bare + buffer strip | Sediment g/m²; NO3 and PO4 in runoff |
Variables
| H1 | H2 | H3 | |
|---|---|---|---|
| Independent | Cover (bare / vegetated); angle (H1b) | NPK dose | Buffer strip present / absent |
| Dependent | Runoff volume (mL), sediment mass (g), turbidity | Turbidity (bench TURB), green index, Secchi depth, pH | Sediment mass, NO3/PO4 (mg/L) in runoff |
| Controlled | Rain volume 10 mm and intensity 60 mm/h (FLOW metered), angle 10°, soil mix and depth 5 cm, antecedent soil moisture (SOIL within ±3 % of target before every event), surface raked to 1 cm on bare cassettes, room temp | Jar size 500 mL, inoculum 50 mL, light (same LED strip, positions randomised and rotated), temperature, start date | As H1, plus fertiliser 2 g NPK 15-15-15 per cassette applied 24 h before event |
Replication strategy
- Bare-vs-bare calibration first (3 events, both lanes bare): measures the natural lane-to-lane difference. A later treatment effect only counts if it is ≥ 2× this calibration difference.
- Four interchangeable cassettes (2 vegetated, 2 bare): every comparison is run once, then the cassettes are swapped left↔right and run again, cancelling position bias (rain bar uneven, light gradient).
- Repeat rain events: ≥ 3 events per condition (2 per week, ≥ 48 h apart).
- Before/after on the pond: 2-week baseline with unfertilised runoff, then fertilised runoff; compare weekly means.
- Jars: 3 replicates per dose, positions assigned by dice, rotated one place every 2 days.
Sampling schedule
| What | When | Who/how |
|---|---|---|
| All automated sensors | Every 60 s (FLOW every 5 s during events) | Node → Home Assistant → InfluxDB |
| Rain events | Tue + Thu at start of lab session (button in HA), weeks 4–8; later 1/week | Students present to collect runoff |
| Runoff volume, sediment, bench turbidity | Every event, each lane | Graduated jug, filter/dry/weigh |
| NO3, PO4 in runoff (filter in / out) | 1 event per week | Test strips + drop tests |
| Pond: Secchi card, photo green index, NO3, PO4, pH pen check, duckweed fronds | Weekly (Monday) | Manual log |
| Jars: photo, bench turbidity, pH pen | Mon / Wed / Fri for 21 days | Manual log |
Manual measurements (methods)
- Sediment mass (TSS method): collect the whole event's runoff per lane in a 1 L graduated jug; read total volume V. Stir hard, immediately pour 100 mL into a measuring cylinder; filter through a pre-weighed coffee filter (weigh dry filter on 0.01 g scale). Dry 48 h on a radiator shelf or 2 h at 105 °C in an oven (teacher). Weigh. TSS (g/L) = (dry filter − filter) / 0.1 L; sediment yield = TSS × V; per area = yield / 0.048 m². For bare lanes with heavy loads, also let the remaining jug settle 24 h, decant and dry the whole sediment in a pre-weighed foil tray (cross-check).
- Turbidity: the second TURB probe in a black-sleeved 250 mL bench cup (see Instrumentation), converted to "g/L kaolin-equivalent" via the calibration curve. Backup with no electronics: a 60 cm clear transparency tube with a Secchi pattern on the bottom (depth at which pattern disappears, cm).
- pH: continuous PHKIT in pond; PHPEN (shared pool) for jars and runoff.
- Nitrate/phosphate: aquarium 6-in-1 strips for quick NO3 (0–250 mg/L, coarse); JBL-type NO3 and PO4 drop tests (colour card, ~0.05–1.8 mg/L PO4) for weekly pond and filter in/out samples. Always test tap water once as baseline (Bucharest tap water contains some nitrate).
- Algae: (a) Secchi card: a 5 cm black/white quadrant disc on a stick, lowered in the pond, depth of disappearance (cm); (b) photo green index: phone on a fixed stand, jar in front of a white card, LED light only, fixed exposure (pro mode or lock AE); in a free app (ImageJ/Fiji, or a spreadsheet of RGB values from a colour-picker app) compute G/(R+G+B) on a centre patch; (c) Lemna minor frond count inside a floating 10 cm PVC ring.
Analysis
- Per event: sediment yield (g/m²), runoff coefficient = runoff volume / rain volume, filter efficiency = (C_in − C_out)/C_in for turbidity and TSS.
- H1/H3: paired differences (A − B) per event; mean ± SD; ratio vegetated/bare; check effect ≥ 2× calibration difference. Liceu: paired t-test or sign test in a spreadsheet; gimnaziu: bar chart with min–max whiskers.
- H1b: scatter sediment vs angle, fit a line or power curve.
- H2: line chart turbidity and green index vs day per dose (mean of 3 jars); dose–response at day 14; rank order test.
- Pond: Grafana time series of pH (daily max − min = photosynthesis swing, a productivity proxy), turbidity, temperature, level; before/after weekly means.
Mid-December vs. spring
| By mid-December (observable) | Spring 2027 (needs weeks of light + nutrients) |
|---|---|
| H1, H1b, H3 sediment results (≥ 3 events each) | Pond bloom trajectory after repeated fertilised runoff (weeks 7 → 20) |
| H2 jar bioassay: high-dose jars visibly green in 7–14 days at 20 °C, 14 h light | Diurnal pH swing growing as biomass rises; Secchi depth falling |
| Filter v1/v2 removal efficiencies | Filter clogging and lifetime (efficiency vs number of events) |
| Pond baseline + first 1–2 weeks of fertilised inflow; duckweed growth rate | Duckweed vs submerged plants competition; snail population counts; light (window, day length) as a seasonal factor; clover vs ryegrass cover |
Design consequence: the pond is started in week 2 (not week 6) so it is biologically stable before the first nutrients arrive, and the jars carry the eutrophication result for the December presentation.
Engineering track
Problem statement: Design a field-edge system that keeps soil and fertiliser on the field and out of the pond, using only cheap natural materials, without flooding during a 20 mm storm, and that a farmer (a student) can service in under 2 minutes.
Requirements
| ID | Requirement | Verification |
|---|---|---|
| R1 | Rain simulator delivers a set volume ±5 % and mean intensity 30–120 mm/h, repeatable between events | FLOW pulses vs graduated jug, 3 repeats |
| R2 | Rain uniformity across each lane: Christiansen CU ≥ 80 % | 8 catch cups per lane, 5 min |
| R3 | Slope angle adjustable 5/10/15/20° ±1°, repeatable | Prop blocks + phone inclinometer |
| R4 | Filter cartridge swappable in < 2 min, no tools, identical outer size | Stopwatch test |
| R5 | Filter passes 0.25 L/min without overflowing; detention ≥ 0.6 L | 20 mm storm test, no water in catch tray |
| R6 | Filter removes ≥ 80 % of turbidity/TSS; report NO3/PO4 change | In/out samples |
| R7 | No water can reach the pond above 21 cm; pump cannot run dry or overfill | Interlock tests (see Automation) |
| R8 | Cost per filter cartridge ≤ 30 RON, materials non-toxic | BOM |
Candidate solutions
- Rain bar: (a) PVC 16 mm pipe with 2 rows × 8 holes Ø 0.8 mm (pin vice) per lane; (b) same pipe with 23G blunt dispensing needles (more uniform drops); (c) holes + a fine mesh 5 cm below to break drops into a wider pattern.
- Filter cartridges (2.5 L PP boxes, 20×14×10 cm, outlet in bottom under mesh): gravel 4–8 mm; pool-filter sand 0.4–0.8 mm over gravel; layered gravel/sand/activated charcoal; plant biofilter = sand + 3-week ryegrass mat on top; student-invented (e.g. coir, straw, biochar).
- On-field measures (tested on cassettes): grass buffer strip, straw mulch, contour ridges (3 acrylic strips across the slope), coir mat, check dams of gravel.
Test criteria: sediment removal (%), turbidity removal (%), NO3/PO4 change, overflow (yes/no, volume in catch tray), clogging (outflow rate at event 1 vs event 5), swap time, cost.
Iteration plan
- v0 (week 3): rain bar (a), measure CU; if < 80 %, build (b) and retest.
- v1 filters (week 5): build 3 cartridges (gravel, sand, layered); run inline on bare-lane runoff; rank with the criteria above.
- v2 (week 7): redesign the best one (e.g. thicker sand, plant mat on top, coarser layer against clogging); retest; compare v1 vs v2 on the same event type.
- Spring: lifetime test (10 events), cleaning method, combine best on-field measure + best filter ("whole-catchment solution") and measure pond impact.
Every iteration is logged in the design notebook: requirement → change → test result → decision.
Enclosure & build
Layout (boltless metal rack 180×90×40 cm, 5 shelves, anchored to the wall with an anti-tip strap; shelves lined with PP sheet)
| Level | Height (shelf top) | Contents |
|---|---|---|
| L4 Field | 125 cm | 12 mm plywood tilt platform 60×40 cm, hinged at the front edge, prop blocks at the back (h = 40 cm × sin θ: 3.5 / 6.9 / 10.4 / 13.7 cm for 5 / 10 / 15 / 20°). Two cassettes side by side in rail stops. Rain bars + slope LED profiles on two PVC 16 mm uprights screwed to the platform, 25 cm above the soil, so drop height stays constant when tilting. Two 12 cm kitchen funnels on brackets under the open front ends. |
| L3 Filter | 95 cm | Catch tray (spare BOXPLASTIC lid or 40×30 cm PP tray) holding 2 filter cartridges A/B. Each cartridge outlet → 16 mm clear hose → pond. Catch tray drain (overflow only) → separate hose → pond. JSN on a bracket under this shelf, on top of the stilling tube. |
| L2 Pond | 40 cm | BOXPLASTIC low box 60×40×15 cm (≈ 36 L, holds the whole pond if the glass fails) containing TANK25 (40×25×25 cm, water at 18 cm = 18 L) on 1 cm foam, plus 12 × 0.5 L jars. Pond/jar LED profiles hang from L3 on chains, 15 cm above water (adjustable 10–30 cm). Hose ends clipped 3 cm above the water surface (air gap = sampling point). |
| L1 Supply | 5 cm | Second BOXPLASTIC spill box containing RESERVOIR 15 L (lid drilled for pump cable, tubing, float) and a 5 L drawdown jug. |
| Node | 110 cm on the rack's side upright, outside the shelf footprint | BOX with ESP32 + TERMBOARD + OLED + BUCK + 3 MOSFET + PH-4502C board; glands pointing down; every cable with a drip loop below the box. |
| Mains | Wall shelf ≥ 40 cm to the side of the rack, ≥ 150 cm high | RCD (30 mA) power strip + PSU12 brick only. Only the 12 V DC lead crosses to the node box, with a drip loop. |
Soil cassettes (×4): 3 mm ACRYLIC, inner 40 × 12 × 6 cm; base, two sides, back wall; front end open with a 1 cm sill and a 2 cm strip of MESH below the sill so seepage also exits. Fill 5 cm soil mix (2 parts garden topsoil : 1 part washed sand, sieved 5 mm) = 2.4 L per cassette. Lane area 0.048 m² → 1 mm of rain = 48 mL per lane.
Rain rate (computed): pump flow is trimmed (PWM + bypass valve) to Q = 0.40 L/min, split equally to both lanes (servo valve "both") = 0.20 L/min per lane = 4.2 mm/min instantaneous. Rain is pulsed (like oscillating-nozzle field simulators): each 15 s pulse = 100 mL total = ~1 mm per lane.
| Storm preset | Pulses | Pulse/pause | Depth | Duration | Mean intensity | Total water |
|---|---|---|---|---|---|---|
| S10 standard | 10 | 15 s / 45 s | 10 mm | 10 min | 60 mm/h | 1.0 L |
| S20 extreme | 20 | 15 s / 15 s | 20 mm | 10 min | 120 mm/h | 2.0 L |
| D2 drizzle (irrigation) | 2 | 15 s / 105 s | 2 mm | 4 min | 30 mm/h | 0.2 L |
Pulsing keeps the FLOW sensor inside its accurate range (≥ 0.3 L/min). Limitation to discuss with students: 25 cm drops have far less impact energy than real rain, so absolute erosion is underestimated; comparisons remain valid.
Water path
flowchart TD
R["RESERVOIR 15 L dechlorinated water"] --> P["PUMP 12 V via MOSFET PWM3"]
P --> BV["Bypass ball valve back to reservoir"]
BV --> R
P --> F["FLOW YF-S401"]
F --> NRV["Non-return valve"]
NRV --> V["3-way valve on SERVO, A / both / B"]
V --> RA["Rain bar A"]
V --> RB["Rain bar B"]
RA --> CA["Cassette A on tilt platform"]
RB --> CB["Cassette B on tilt platform"]
CA --> GA["Funnel A, hose"]
CB --> GB["Funnel B, hose"]
GA --> JA["Optional 1 L sample jug A"]
GB --> JB["Optional 1 L sample jug B"]
GA --> FA["Filter cartridge A"]
GB --> FB["Filter cartridge B"]
FA --> PD["Pond TANK25, 18 L"]
FB --> PD
FA --> CT["Catch tray overflow"]
FB --> CT
CT --> PD
PD --> DD["Weekly drawdown to 5 L jug, max level 21 cm"]
S1(["FLOAT reservoir low"]) -.-> R
S2(["SOIL A and SOIL B"]) -.-> CA
S2 -.-> CB
S3(["BH1750 at water surface"]) -.-> PD
S4(["JSN in stilling tube"]) -.-> PD
S5(["FLOAT pond high"]) -.-> PD
S6(["TURB, PHKIT, DS18B20"]) -.-> PD
Overflow policy: no siphon overflow on the glass tank (siphons can fail and drain or flood). Instead: 7 cm freeboard (18 → 25 cm = 7 L spare), FLOAT high at 21 cm blocks all events, JSN level > 20 cm blocks events, weekly manual drawdown to 18 cm (this is also the pond sample), spill box under the tank holds > 25 L. One S20 storm adds ≤ 2 L (≈ 2 cm).
Build steps
| # | Step | Time | Tools |
|---|---|---|---|
| 1 | Assemble rack, set shelf heights, anchor to wall, line shelves with PP sheet | 1.5 h | Rubber mallet, drill, wall plugs |
| 2 | Cut acrylic for 4 cassettes (score-and-snap), glue with aquarium silicone, cure 24 h, test-fill with water for leaks | 3 h + cure | Acrylic scoring knife, steel rule, clamps, silicone gun |
| 3 | Tilt platform: cut plywood 60×40, varnish 2 coats, 2 hinges (approved lot), rail stops, prop blocks cut to 3.5/6.9/10.4/13.7 cm | 2 h | Saw, drill, sandpaper, brush |
| 4 | Rain bars: 2 × 40 cm PVC 16 mm, end caps, drill holes Ø 0.8 mm at 5 cm pitch, T-pieces, uprights and pipe clips | 2 h | Pin vice, hacksaw, PVC glue |
| 5 | Supply line: pump in reservoir, 6 mm tubing, bypass ball valve, FLOW (arrow = flow direction, mounted horizontal), non-return valve, 3-way aquarium valve on SERVO with acrylic coupler | 2 h | Scissors, cable ties, hot glue |
| 6 | Filter cartridges: drill 6 PP boxes for 16 mm barbed bulkhead, silicone, mesh over outlet; build catch tray drain | 2 h | Step drill, silicone |
| 7 | Pond: TANK25 in spill box on foam; stilling tube (PVC 75 mm × 50 cm, 6 slots 5 mm near bottom) vertical in a back corner; float, pH and TURB holders on acrylic hang-over clips | 1.5 h | Hacksaw, file |
| 8 | Node box: TERMBOARD, BUCK set to 5.0 V before connecting ESP32, MOSFETs, dividers, PH-4502C; glands; label every wire | 3 h | Screwdriver, multimeter, crimper, heat-shrink |
| 9 | LED strips in profiles (slope 3 × 45 cm, pond 3 × 60 cm), JST leads, chains | 1.5 h | Soldering iron (teacher) or solderless clips |
| 10 | Flash ESPHome, adopt in HA, dashboard + rain-event script; run calibration and interlock tests | 3 h | Laptop |
Total ≈ 22 student-hours + cure times.
Biology
Pond (TANK25, 18 L)
| Item | Species | Qty | Source (Romania) |
|---|---|---|---|
| Water | Bucharest tap water + dechlorinator (e.g. Tetra AquaSafe), or stood 48 h | 18 L | — |
| Substrate | 3 cm washed sand + 1 cm garden soil under it (nutrient-poor start) | ~2 L | Dedeman / garden |
| Submerged plant | Ceratophyllum demersum (hornwort, native) | 2 bunches | Aquarium shops (Aquaristica, Zoomania, local "acvaristică"), OLX hobbyists |
| Submerged plant | Egeria densa (Brazilian waterweed) or Elodea canadensis | 2 bunches | Aquarium shops |
| Floating plant | Lemna minor (common duckweed, native) | ~100 fronds | Aquarium shops / hobbyists |
| Grazer | Planorbarius corneus (great ramshorn snail, native), fixed at 5 individuals | 5 | Aquarium shops |
| Inoculum | 0.5 L pond water from a garden pond or a lake edge (Herăstrău/Văcărești, with teacher, gloves), sieved through 0.5 mm mesh to exclude larger animals | 0.5 L | Field |
Do not buy Elodea nuttallii or Lagarosiphon major (EU invasive species of Union concern). Prefer Planorbarius over Physa acuta (invasive). No organism or water from this system is ever released outdoors: plant waste is dried and binned, water goes down the sink.
Field (cassettes): 2 vegetated cassettes sown densely with Lolium perenne (perennial ryegrass, 5 g per cassette) + 2 g wheat (Triticum aestivum, germinates in 3–5 days, fast cover) — one cassette may be ryegrass + white clover (Trifolium repens, 1 g) for spring comparison. 2 bare cassettes = control. Buffer strip: a 8 × 12 cm sod of ryegrass grown in a separate small tray, cut and inserted at the low end of a bare cassette for H3. Seeds from agricultural/garden shops (Dedeman, Agroland, eMAG).
Establishment timeline: sow week 1 (Oct 26–30) under the slope LED (or a windowsill), keep moist with a spray bottle; ≥ 80 % cover at day 18–21 (by Nov 16–20). Pond filled week 2, plants week 2, snails and inoculum week 3 (after 7 days of plant settling). Jars started Nov 18.
Fertiliser (measured doses)
- Field: granular NPK 15-15-15, 2.0 g per cassette (= 42 g/m², ≈ 63 kg N/ha, a realistic field rate), sprinkled evenly 24 h before a "fertilised" event.
- Jars: stock solution 10 g soluble NPK 20-20-20 in 1.00 L water (10 mg/mL; label, store dark, 4 weeks). Per 500 mL jar (450 mL dechlorinated water + 50 mL sieved pond water): 0 / 0.25 / 1.0 / 4.0 mL stock by syringe → 0 / 1 / 4 / 16 mg N/L and 0 / 0.44 / 1.7 / 7 mg P/L. Jars covered with cling film with pin holes; topped up to the mark with dechlorinated water.
Avoid: fish or any vertebrate (brief rule; also adds nutrients); mosquito risk — check weekly for larvae, cover the pond with a MESH frame lid if seen; peat-based potting compost on the slope (floats, unrealistic erosion); copper-containing products; pesticides.
Instrumentation
| Catalog ID | Qty | Placement | Interval | Purpose / entity |
|---|---|---|---|---|
| DS18B20 | 1 | Pond, mid-depth, clipped to stilling tube | 60 s | Water temperature; pH temperature context. mc_02_water_temp_pond |
| SOIL | 2 | One per cassette, vertical, 8 cm from the high end, top edge sealed | 60 s (mean of 10) | Antecedent moisture control + infiltration response during events. mc_02_soil_moisture_a/_b |
| BH1750 | 1 | Pond/jar level facing up, in a clear sealed sandwich box 5 cm above water | 60 s | Light dose for algae (lux, not PAR — relative comparisons only). mc_02_illuminance_pond |
| JSN | 1 | On top of PVC 75 mm stilling tube, face 52 cm above tank bottom (outside 25 cm blind zone at max level 21 cm) | 60 s (median of 12 pings at 5 s) | Pond level → inflow volume per event (1 cm ≈ 1.0 L). mc_02_water_level_pond |
| FLOAT | 2 | (1) Reservoir, switch point at 3 L; (2) pond, switch point at 21 cm | On change + 60 s | Interlocks (fail-safe wiring, see below). mc_02_float_reservoir_low, mc_02_float_pond_high |
| FLOW | 1 | Rain line after pump, horizontal | 5 s during events, else 60 s | Event volume and rate. mc_02_rain_flow, mc_02_rain_volume_event |
| TURB | 2 | (1) Pond: in an opaque PVC sleeve clipped to the glass, head 3 cm under water, top of probe body dry; (2) bench cup: black 250 mL cup with lid holding the probe | 60 s (pond); 5 s on demand (bench) | Pond turbidity trend; sample turbidity for runoff, filter in/out, jars. mc_02_turbidity_pond, mc_02_turbidity_bench |
| PHKIT | 1 | Pond, probe in a hang-over holder, tip 5 cm below surface, ≥ 3 cm from glass | 60 s (mean of 20) | pH and diurnal swing (photosynthesis proxy). mc_02_ph_pond |
| SERVO | 1 | Coupled to 3-way aquarium valve on rain line | Event-driven | Route rain to A / both / B |
| PUMP | 1 | In RESERVOIR | Event-driven | Rain |
| LEDSTRIP + LEDPROFILE | 3.2 m, 5 profiles | Slope: 3 × 45 cm on uprights; pond/jars: 3 × 60 cm on chains | Schedule | Grass growth; algae light treatment |
TURB notes: SEN0189-type sensors measure light transmitted across a 1 cm gap (IR LED → phototransistor); output 0–4.5 V, falls as turbidity rises. The "NTU" formula in the datasheet is approximate — we calibrate in g/L kaolin-equivalent instead. Limitations: sensitive to ambient light (hence the opaque sleeve and black cup), bubbles and algal film on the window (wipe weekly with soft cloth), not accurate below ~0.05 g/L, and the probe top is not waterproof (keep top 2 cm dry; seal cable entry with heat-shrink).
PHKIT notes: the glass probe must never dry out; out of water store it in its cap with 3 M KCl storage solution (never distilled water). Drift ~0.05–0.1 pH/week: check weekly in pH 7, recalibrate 2-point monthly or when drift > 0.1. Algal film on the bulb: rinse with tap water, soak 10 min in vinegar if fouled. Probe lifetime in continuous immersion 6–12 months: budget a replacement probe in spring. Ground-loop check: read pH with pump/LEDs on and off; if the reading jumps > 0.05, add an analog signal isolator.
Pin assignment (standard pin map only)
| GPIO | Standard function | Connected here |
|---|---|---|
| 21 / 22 | I2C | OLED 0x3C, BH1750 0x23 |
| 4 | 1-Wire | DS18B20 pond (4.7 kΩ pull-up) |
| 32 | Analog A | SOIL A |
| 33 | Analog B | SOIL B |
| 34 | Analog C | TURB bench (10 k / 20 k divider, 0–4.5 V → 0–3.0 V) |
| 35 | Analog D | free |
| 36 (VP) | Analog E | PHKIT Po output (10 k / 20 k divider) |
| 39 (VN) | Analog F | TURB pond (10 k / 20 k divider) |
| 16 | PWM 1 | MOSFET → slope LED strip |
| 17 | PWM 2 ("fan" slot, no fan on this node) | MOSFET → pond/jar LED strip |
| 18 | PWM 3 (pump) | MOSFET → rain PUMP (PWM 1 kHz) |
| 19 | PWM 4 | free |
| 23 / 25 | Relay 1–2 | free |
| 26 | Servo 1 | SG90 rain valve (5 V from BUCK, 470 µF across supply) |
| 27 | Servo 2 | free |
| 13 | Digital in 1 | FLOAT reservoir low |
| 14 | Digital in 2 | FLOAT pond high |
| 5 | Pulse counter | FLOW signal (10 k / 20 k divider from 5 V) |
| 15 / 12 | Ultrasonic TRIG / ECHO | JSN (ECHO via 1 k / 2 k divider; the 2 k to GND also keeps strapping pin GPIO12 low at boot) |
Power: PSU12 → MOSFET loads (LEDs ≤ 10 W/m × 3.2 m ≈ 32 W, pump ~4 W) and BUCK 5.0 V → ESP32 VIN, JSN, FLOW, TURB ×2, PHKIT, SERVO. Worst case ≈ 39 W = 3.3 A of 5 A. All ADC pins on ADC1, attenuation 11 dB (attenuation: 12db in current ESPHome).
Fail-safe float wiring: both floats are mounted so the contact is closed (to GND) in the safe state — reservoir float closed while water is above 3 L; pond float closed while level is below 21 cm. Open circuit (triggered or broken wire) = unsafe → pump blocked.
ESPHome flow excerpt (YF-S401 ≈ 5880 pulses/L; replace with your calibrated value):
sensor:
- platform: pulse_counter
pin: GPIO5
name: "mc_02_rain_flow"
unit_of_measurement: "L/min"
update_interval: 5s
filters:
- multiply: 0.00017007 # 1/5880 L per pulse
total:
name: "mc_02_rain_total"
unit_of_measurement: "L"
filters:
- multiply: 0.00017007
Calibration procedures
| Sensor | Procedure | Frequency |
|---|---|---|
| FLOW | Pump into a 1 L graduated jug for 60 s, 3 repeats at the event PWM; pulses/L = pulses ÷ litres; update the factor | At commissioning, after tubing changes |
| Rain uniformity | 8 catch cups per lane on a flat platform, 5 min, weigh; CU = 100 × (1 − Σ|x − mean| / (n × mean)) | Each rain-bar version |
| JSN | Ruler in the stilling tube at 3 water levels (12, 18, 21 cm); level = mount height − distance; fit offset | Commissioning, monthly check |
| PHKIT | Probe in pH 7.00 → record voltage V7; rinse; pH 4.01 → V4; slope = (V7 − V4)/2.99; pH = 7 − (V − V7)/slope (ESPHome calibrate_linear with the two points). Use solutions at room temperature; check against PHPEN |
2-point monthly; pH 7 check weekly |
| TURB (both) | Kaolin standards in dechlorinated water: 0, 0.05, 0.1, 0.2, 0.5, 1.0 g/L (stirred, read within 10 s); fit voltage → g/L (calibrate_linear or polynomial); daily zero check with clear water in the bench cup |
Commissioning, then monthly |
| SOIL | Each probe in its cassette mix: air reading, oven-dry soil, saturated soil; map to 0–100 %; check twice with gravimetric water content (weigh 20 g soil, dry, reweigh) | Per probe per substrate |
| DS18B20 | Ice-water bath (0 °C) and room vs a reference thermometer; offset | Commissioning |
| BH1750 | Compare with a phone lux app at 3 positions; record only as relative | Commissioning |
| Slope angle | Phone inclinometer on platform for each prop block | Each angle change |
Automation
Rain-event controller runs inside the ESP32 (ESPHome script), so an event always finishes or aborts even if Wi-Fi or Home Assistant is down. HA only triggers it (dashboard button with preset S10/S20/D2 and valve position) or schedules D2 drizzle when both SOIL values fall below the target band.
stateDiagram-v2
[*] --> Idle
Idle --> Precheck : HA button or schedule
Precheck --> Fault : interlock open
Precheck --> SetValve : all checks pass
SetValve --> Raining : servo settled 2 s
Raining --> Pausing : pulse time elapsed
Pausing --> Raining : pulses remaining
Pausing --> Draining : all pulses delivered
Raining --> Fault : float open or no flow or volume cap
Pausing --> Fault : float open
Draining --> Logging : 15 min runoff window
Logging --> Idle : event record written
Fault --> Idle : manual reset in HA
- Precheck: reservoir float closed; pond float closed; JSN level valid and < 20 cm; last event ≥ 2 h ago; for experiment events, SOIL A and B within the target band (warn, do not block, if outside).
- Raining: pump ON at calibrated PWM; flow pulses counted; pulse ends on time (15 s).
- Logging: event ID, preset, valve position, angle (entered in HA), pulses, litres, mean L/min, SOIL before/after, pond level before/+15 min. Stored in InfluxDB and appended to the nightly CSV.
- Fault: pump OFF, servo to "both", HA notification and OLED message; requires manual reset.
LED schedule
| Light | Default | Experiment use |
|---|---|---|
| Slope (PWM 1) | 06:00–20:00 (14 h), 70 %, 15 min ramp | Constant; off during rain events not needed |
| Pond/jars (PWM 2) | 07:00–21:00 (14 h), set PWM so BH1750 reads ~8,000 lux at the water surface | Fixed during H2; spring option: 10 h vs 14 h photoperiod or 50 % vs 100 % (move half the jars under shade mesh) |
Winter break (Dec 21 – Jan 7): lights continue on schedule, rain events disabled, reservoir and pond topped up on the last school day, HA alerts sent to the teacher's phone.
Safety interlocks (summary)
- Pump runs only while both floats are in the safe (closed) state and JSN < 20 cm.
- Hard caps per event: ≤ 2.0 L (11,760 pulses) and ≤ 300 s cumulative pump time.
- Flow fault: no pulses within 10 s of pump ON → abort (dry pump, kink or sensor failure).
restore_mode: ALWAYS_OFFon pump and MOSFET outputs; after any reboot the pump is off.- Minimum 2 h between events; maximum 4 events per day.
- All loads are 12 V DC; the only mains items (PSU12 brick, RCD strip) are on the wall shelf beside the rack.
Operations
Per-event checklist (≈ 40 min)
- HA dashboard: no faults; reservoir float OK; pond level < 20 cm; note SOIL A/B.
- Set angle (prop block, check inclinometer); rake bare cassettes 1 cm; photo of both cassettes from the fixed point.
- Place clean 1 L jugs under hoses A and B (erosion mode) or leave hoses in cartridges (filter mode).
- Start preset in HA; enter event ID, angle, cassette IDs, treatment.
- After the 15 min runoff window: read jug volumes; take 100 mL TSS subsamples and bench-turbidity samples; label (date_event_lane).
- Filter mode: grab 100 mL at hose inlet and at pond-end outlet at minutes 2, 5, 10.
- Pour remaining jug runoff slowly through its cartridge into the pond (keeps nutrient accounting closed).
- Photo after; write the event log line.
Weekly (Monday, ≈ 30 min): pond Secchi, photo green index, Lemna count, NO3/PO4, pH pen vs PHKIT; drawdown pond to 18 cm into the 5 L jug (this is the weekly pond sample); top up reservoir to 15 L with dechlorinated water; wipe TURB window; check pH probe in pH 7; check for mosquito larvae; inspect tubing and drip loops; refill catch tray dry.
Manual logs (printed sheet + shared spreadsheet): event log (ID, date, preset, angle, cassettes, rain L, runoff A/B mL, TSS A/B, turbidity A/B, notes); pond log; jar log; maintenance log (calibrations, cleaning, faults).
Filter cleaning: after every 5 events or when outflow time doubles: tip the top 1 cm of sediment-laden sand into a labelled bag (keep as sample), backwash gravel/sand in a bucket, re-pack to the marked height. Charcoal is replaced, not washed, every 10 events.
Water changes: no routine pond water changes (they would remove the nutrients being studied); only weekly drawdown and evaporation top-up with dechlorinated water. Emergency only: if snails die or water smells of rotten eggs, replace 30 % and log it.
Sample storage: nutrient samples tested the same day, or stored ≤ 48 h at 4 °C in a labelled screw-cap bottle in a dedicated (non-food) fridge or cool box; dried sediment filters in labelled zip bags in a dry box (archive for the year); photos named mc02_YYYYMMDD_subject.jpg in the shared folder.
Safety & risks
- HARD RULES apply: no 230 V is built, wired, modified or switched by students; the only mains items (RCD-protected strip, certified PSU12 brick) sit on a wall shelf beside and above the rack, away from water, with drip loops. Nothing mains-powered is in water, in soil, or inside the column. Everything that touches water — pump, sensors, LED strips — is ≤ 12 V DC.
- Water near electronics: node box IP65 on the side upright at 110 cm, outside the shelf footprint, glands facing down, drip loop on every cable; PH-4502C and all boards inside the box; LED strips in aluminium profiles, never submerged.
- Spills: pond and reservoir each stand in a spill box larger than their volume; shelves lined; mop and towels kept at the rack; rack wall-anchored against tipping (≈ 35 kg of water at 40 cm and floor level only).
- Overflow: fail-safe floats, JSN limit, event volume caps, 7 cm freeboard, weekly drawdown (see Automation).
- Hygiene: nitrile gloves for soil, pond water and fertiliser; wash hands after every session; pond water is never tasted, pipetted by mouth or poured into food containers; fertiliser and stock solution labelled and locked in the teacher's cupboard; snails handled with a net, not hands.
- Biology: no vertebrates; no release of any organism or water outdoors; avoid invasive species listed in Biology.
- Glass: rimless tank handled by two people, empty only; no load on the glass rim.
Educational outcomes & assessment
Students will be able to:
- Formulate a testable hypothesis on erosion/eutrophication and name independent, dependent and controlled variables.
- Explain why a calibration (bare vs bare) run and a position swap are needed before claiming an effect.
- Measure sediment yield (TSS × volume), turbidity, pH, NO3/PO4, and convert rain to mm and mm/h.
- Interpret a dose–response and a time series (diurnal pH swing) from the dashboard.
- Write requirements, build and test a filter against them, and justify a v2 from data.
- Explain the chain field → runoff → nutrients → algae → light/oxygen in the pond, and link it to real Romanian cases (Danube Delta and agricultural lakes eutrophication, EU Nitrates Directive buffer strips).
Assessment artefacts: lab notebook (individual), event/pond/jar logs (team), engineering design log with requirements table and test results (team), 5-minute December presentation with one graph per hypothesis (team), short individual reflection.
| Criterion | Developing (1) | Secure (2) | Strong (3) |
|---|---|---|---|
| Question & hypothesis | Vague | Testable, variables named | Testable, variables + controls + replication justified |
| Data quality | Gaps, no units | Complete logs with units | Complete, calibrated, uncertainty discussed |
| Analysis | Raw numbers | Correct graphs and means | Effect vs calibration difference, limitations stated |
| Engineering | Built one filter | Tested against requirements | Iterated with data, trade-offs explained |
| Teamwork & safety | Needs reminders | Follows checklists | Leads checklists, improves procedures |
Roles rotate every 2 weeks: hydrologist (rain, slope), chemist (water tests), engineer (filters, hardware), data lead (HA/Grafana, spreadsheet).
Sub-BOM
Cost-cut 2026-10-20: lighter shelving, strips plus one PO4 test instead of two drop tests, shared precision scale, electrical consumables moved to the project electronics lot.
Prices: estimates incl. VAT, RON (1 EUR ≈ 5.1 RON), October 2026, basis given per line.
| ID / item | Qty | Unit RON | Line RON | Basis |
|---|---|---|---|---|
| ESP32 | 1 | 35 | 35 | optimusdigital.ro / cleste.ro |
| TERMBOARD | 1 | 35 | 35 | optimusdigital.ro |
| OLED | 1 | 22 | 22 | optimusdigital.ro |
| BOX | 1 | 40 | 40 | IP65 ABS, emag.ro / dedeman.ro |
| GLAND (PG7/PG9 ×9, PG13.5 ×1 for BNC) | 10 | 3 | 30 | emag.ro |
| PSU12 | 1 | 60 | 60 | certified 12 V 5 A brick, emag.ro |
| BUCK | 1 | 12 | 12 | optimusdigital.ro |
| MOSFET | 3 | 8 | 24 | D4184 module, optimusdigital.ro |
| DS18B20 | 1 | 15 | 15 | waterproof 1 m, cleste.ro |
| SOIL | 2 | 12 | 24 | v2.0 TL555 version, optimusdigital.ro |
| BH1750 | 1 | 12 | 12 | optimusdigital.ro |
| JSN | 1 | 50 | 50 | JSN-SR04T, optimusdigital.ro / ardushop.ro |
| FLOAT | 2 | 12 | 24 | vertical PP float, emag.ro |
| FLOW | 1 | 35 | 35 | YF-S401, optimusdigital.ro / AliExpress |
| TURB | 2 | 55 | 110 | SEN0189-type, robofun.ro / AliExpress |
| PHKIT | 1 | 140 | 140 | BNC probe + PH-4502C, optimusdigital.ro |
| SERVO | 1 | 12 | 12 | SG90, optimusdigital.ro |
| PUMP | 1 | 45 | 45 | 12 V DC 240 L/h, emag.ro |
| LEDSTRIP | 1 | 120 | 120 | 5 m reel, 3.2 m used, rest to shared pool; emag.ro |
| LEDPROFILE | 5 | 25 | 125 | 1 m alu + diffuser, dedeman.ro |
| TANK25 | 1 | 160 | 160 | 40×25×25 rimless, aquarium shop / emag.ro |
| RESERVOIR | 1 | 45 | 45 | 15 L food-grade with lid, dedeman.ro |
| BOXPLASTIC | 2 | 55 | 110 | low under-bed box ~60×40×15, spill boxes, dedeman.ro |
| ACRYLIC | 1 | 190 | 190 | 3 mm 50×100 (cassettes); 1 of 3 approved sheets — lead to reconcile |
| MESH | 0.25 m² | 60 | 15 | fibreglass mesh, dedeman.ro |
| SILICONE | 1 | 35 | 35 | aquarium-safe, aquarium shop |
| TUBING | 5 m | 6 | 30 | silicone 6 mm ID, emag.ro |
| CALSOL | 1 | 60 | 60 | pH 4/7 + storage KCl (shared with Hydro possible) |
| FRAME: 3-tier wire shelving 90×45 cm, ≥ 50 kg per shelf (or existing bench plus wall brackets) | 1 | 130 | 130 | emag.ro / dedeman.ro |
| FRAME: anti-tip strap, PP shelf liner | 1 | 40 | 40 | dedeman.ro |
| Tilt platform: plywood 12 mm 60×40, varnish, prop blocks (hinges from approved lot) | 1 | 50 | 50 | dedeman.ro |
| Rain bars: PVC 16 mm 2 m, end caps, T-pieces, clips | 1 | 40 | 40 | dedeman.ro |
| 23G blunt dispensing needles set | 1 | 25 | 25 | emag.ro |
| Valves: 3-way aquarium valve, ball valve, non-return valve, 6 mm barbs | 1 | 45 | 45 | aquarium shop / emag.ro |
| Drain hose 16 mm clear 3 m + 6 barbed bulkheads | 1 | 80 | 80 | dedeman.ro |
| Kitchen funnels 12 cm | 2 | 5 | 10 | any household shop |
| Filter cartridge boxes PP 2.5 L | 6 | 10 | 60 | household shop / dedeman.ro |
| Stilling tube PVC 75 mm × 0.5 m + bracket | 1 | 25 | 25 | dedeman.ro |
| Filter media: pea gravel 5 kg, pool filter sand 25 kg, activated carbon 500 g | 1 | 110 | 110 | dedeman.ro, aquarium shop |
| Soil: topsoil 20 L + washed sand 10 kg | 1 | 30 | 30 | dedeman.ro |
| Seeds: Lolium perenne 0.5 kg, wheat 1 kg, Trifolium repens 100 g | 1 | 45 | 45 | Agroland / dedeman.ro |
| BIO: Ceratophyllum ×2, Egeria ×2, Lemna, Planorbarius ×5, dechlorinator | 1 | 110 | 110 | aquarium shops |
| Fertiliser: NPK 15-15-15 granular 1 kg + soluble NPK 20-20-20 1 kg | 1 | 55 | 55 | dedeman.ro / garden centre |
| Water tests: 6-in-1 strips (50) + PO4 drop test | 1 | 154 | 154 | JBL, emag.ro |
| Lab: coffee filters, 1 L jugs ×4, 100 mL cylinders ×2, 0.5 L jars ×12, kaolin 500 g, catch cups, Secchi/colour cards (0.01 g scale shared with team 1) | 1 | 150 | 150 | |
| Subtotal | 2 774 RON (≈ 544 EUR) |
Not included (shared pool): PHPEN, TDSPEN, syringes, labels, sample bags, small tools, hub/router. Spring item to budget: spare pH probe ≈ 70 RON.
Changes vs. draft allocation: SOIL 1 → 2 (one per lane, needed for antecedent-moisture control and A/B replication); TURB 1 → 2 (second as bench probe for runoff, filter in/out and jar samples — replaces buying a turbidimeter).
8-week timeline
Check the 2026–27 school calendar: if the autumn break falls in week 1, the teacher sows the cassettes. Nov 30 and Dec 1 are public holidays.
gantt
title EcoColumn build and first experiments
dateFormat YYYY-MM-DD
axisFormat %d %b
section Build
Collect parts, soil mix, sow cassettes :b1, 2026-10-26, 5d
Rack, cassettes, platform, rain bars :b2, 2026-11-02, 5d
Node wiring, ESPHome, HA dashboard :b3, 2026-11-04, 6d
Supply line, filters, pond hardware :b4, 2026-11-09, 5d
Calibrations and interlock tests :b5, 2026-11-12, 6d
Commissioning sign-off :milestone, m1, 2026-12-15, 0d
section Biology
Grass establishment :g1, 2026-10-27, 21d
Pond fill and plants :g2, 2026-11-03, 7d
Snails and inoculum, pond baseline :g3, 2026-11-10, 28d
Jar dose bioassay :g4, 2026-11-18, 21d
Fertilised runoff into pond :g5, 2026-12-07, 12d
section Experiments
Bare vs bare calibration events :e1, 2026-11-17, 4d
H1 vegetated vs bare with swap :e2, 2026-11-23, 5d
H1b angle series :e3, 2026-12-02, 3d
H3 buffer strip with fertiliser :e4, 2026-12-07, 5d
section Engineering
Rain bar uniformity v0 to v1 :n1, 2026-11-12, 5d
Filter v1 build and tests :n2, 2026-11-23, 9d
Filter v2 iteration :n3, 2026-12-07, 5d
section Report
Analysis and presentation :r1, 2026-12-14, 5d
| Week | Dates | Deliverable |
|---|---|---|
| 1 | Oct 26–30 | Parts collected, cassettes sown, soil mix sieved |
| 2 | Nov 2–6 | Rack + cassettes + platform built; pond filled and planted; node flashed |
| 3 | Nov 9–13 | Supply line + filters; FLOW, JSN, pH, TURB, SOIL calibrated; snails + inoculum in |
| 4 | Nov 16–20 | Interlocks tested; rain CU ≥ 80 %; 3 calibration events; jars started Nov 18 |
| 5 | Nov 23–27 | H1 events with position swap; filter v1 built |
| 6 | Nov 30–Dec 4 | (holidays Mon–Tue) angle series; filter v1 tests; jar day-14 readings |
| 7 | Dec 7–11 | H3 with fertiliser; filter v2; fertilised runoff starts entering pond |
| 8 | Dec 14–18 | Final events, analysis, presentation; sign-off Dec 15; winter-break mode set |
3. Toxic Ground — Brownfield
Node: mc-03-brownfield · Team: 3–4 students · Enclosure: TANK63 (60×30×35 cm) used as a 5-zone landscape + a cup "assay bench" for fast, truly replicated tests.
Safety baseline (repeat of HARD SAFETY RULES 1–5): contamination is simulated only — table salt (NaCl), household vinegar (acetic acid), baking soda / garden lime, compaction, a concrete tile and a 12 V heat pad. No heavy metals, no motor oil, no fuel, no fertiliser "spikes", no soil dug from roadsides or old industrial sites, ever. Everything inside or under the tank is ≤ 12 V DC; the only mains item is the certified PSU12 brick on the shelf above, on the RCD strip.
Concept (refined)
A 60 × 30 cm "city block" in a glass tank, divided by siliconed acrylic walls into five isolated soil cells, each one a typical urban damage type:
| Zone | Name | Damage simulated | Real-world analogue |
|---|---|---|---|
| A | Paved + heat | 10×10 cm concrete tile in the middle band, 12 V heat pad under the glass floor | sealed soil, urban heat island |
| B | Compacted | soil tamped in 3 layers, +20–30 % bulk density | car parks, construction sites, trampled verges |
| C | Saline | 3 g NaCl per kg dry soil | de-icing salt along Bucharest roads and pavements |
| D | Acidified | pH lowered ~1.5 units with diluted vinegar | acid-affected soil (concept only) |
| E | Control | loose, untreated mix | reference "healthy" soil |
The tank is the system-scale demonstration (one plot per treatment). The assay bench (48 × 400 mL clear cups) is where the real dose-response science and fast engineering screening happen, because cups can be truly replicated and cress gives a result in 7 days. Phase 1 (Nov–Dec): degrade, measure, understand. Phase 2 (Jan–May): restore zones A–D with the interventions that won on the bench, and track recovery against E.
Science track
Driving question: How do salt, pH change, heat and compaction — the typical damage of city soil — affect whether plants can germinate and grow, and which damage is worst?
Hypotheses (students write their own; these are the defaults):
| ID | Hypothesis | Prediction | Where tested |
|---|---|---|---|
| H1 | Germination and growth fall as salinity rises | cress germination at day 7: 0 g ≈ 90 %, 1 g/kg slightly lower, 3 g/kg clearly lower, 6 g/kg < 20 %; EC1:5 rises roughly linearly with dose | bench S1 + tank C |
| H2 | Compaction reduces root growth and infiltration more than germination | germination in B ≈ E, but radish root length/mass and infiltration speed clearly lower in B | tank B, bench C1 |
| H3 | Heated soil under pavement is warmer and drier and gives poorer growth at the pavement edge | ΔT(A − E) at 2 cm ≈ +6 °C during the photoperiod; SOIL A dries faster; cress taller early, then wilts / lower final biomass | tank A |
| H4 | Shifting pH ±1.5 from the baseline reduces growth; raising pH with baking soda hurts more than with lime because it also adds sodium | growth at pH −1.5 and +1.5 (lime) moderately lower; +1.5 (baking soda) lowest and EC1:5 highest | bench P1 + tank D |
| H5 | Salt-tolerant species (barley, orache) germinate where cress fails | at 3 g/kg barley germination > 70 %, cress < 50 % | bench S2 |
Variables
| Type | Variable | How |
|---|---|---|
| Independent | NaCl dose (0 / 1 / 3 / 6 g per kg dry soil); compaction (loose / tamped); heat (pad on / off); pH shift (−1.5 / 0 / +1.5 lime / +1.5 baking soda); species | set at mixing, weighed to 0.1 g |
| Dependent | germination % (day 3, 5, 7), shoot height (mm), leaf count, fresh/dry shoot mass (g), radish root length (mm), EC1:5 (µS/cm), pH1:5, infiltration time (s), penetration depth (mm), soil moisture (%), soil temperature (°C) | manual + sensors |
| Controlled | same soil mix batch, same seed lot, sowing depth 5 mm, seed count, water type (distilled), water volume by mass, light 14 h, room temperature, position in tank/bench (rotate bench cups every 2 days) | protocol |
| Confounders to discuss | heat dries soil (A); baking soda adds Na; vinegar is broken down by microbes so pH drifts back; potting soil already contains fertiliser salts (baseline EC); light is not perfectly even under the strip | measure, don't ignore |
Plot layout and replication
Every tank zone (11 × 28.8 cm inside) has the same three bands, front to back:
- Front band (y = 0–9 cm): cress — 3 rows × 5 seeds, rows 2.5 cm apart, seeds 2 cm apart, 5 mm deep (15 seeds/zone).
- Middle band (y = 9–19 cm): measurement band — SOIL probe, DS18B20 (A and E), extract cores, infiltration ring, penetrometer. In zone A this band is the tile.
- Back band (y = 19–29 cm): radish — 3 rows × 3 seeds, 4 cm apart (9 seeds/zone). Re-sown with barley / clover / orache in Phase 2.
Pseudo-replication warning (teach it explicitly): the 3 rows inside one zone are sub-samples of one treated plot, not independent replicates. Tank results show patterns; the bench (3 independent cups per level) is what supports a statistical claim.
Assay bench (true replication). Clear PP cups 400 mL, no drainage holes, 250 g dry soil mix each, brought to 60 % of water-holding capacity by weight, 10 seeds per cup, cups covered with cling film until germination, labelled with code (not treatment) so counting is blind.
| Run | Factor levels | Reps | Species | Cups | Start |
|---|---|---|---|---|---|
| S1 | NaCl 0 / 1 / 3 / 6 g·kg⁻¹ | 3 | cress | 12 | 29 Oct |
| S2 | NaCl 0 / 3 / 6 g·kg⁻¹ × cress / barley / orache | 3 | 3 species | 27 | 16 Nov |
| P1 | pH −1.5 (vinegar) / 0 / +1.5 (lime) / +1.5 (baking soda) | 3 | cress | 12 | 9 Nov |
| C1 | loose / compacted (radish root length) | 3 | radish | 6 | 9 Nov |
| R1–R3 | engineering screening (see Engineering) | 3 | cress | 12–18 | from 16 Nov |
Dosing calculations (students do these): salt dose per cup = 250 g × 3 g/kg = 0.75 g NaCl, dissolved in the water used to wet the cup. Tank zone: weigh the dry mix for that zone (≈ 3.2 L ≈ 2.2–2.6 kg), dose = mass × 3 g/kg (≈ 7 g). Expected EC1:5 increase: 1 g NaCl per L ≈ 2 000 µS/cm, and 1 g/kg in a 1:5 extract is 0.2 g/L → ≈ +400 µS/cm per g/kg (so 1 / 3 / 6 g/kg ≈ +400 / +1 200 / +2 400 µS/cm above the baseline). Students predict this before measuring, then compare.
pH shift: titrate a 100 g sample first — add 9 % vinegar diluted 1:10 in 5 mL steps, measure pH1:5 after each step, plot the curve, then scale to the zone mass. For +1.5 use garden lime (CaCO₃, slow, days) or baking soda (NaHCO₃, fast) the same way. Re-check pH weekly and re-dose zone D if it drifts back more than 0.5 units (record every dose).
Sampling schedule
| What | Tank | Bench | Who / tool |
|---|---|---|---|
| Sensors (moisture, T, RH, lux) | every 60 s, automatic | – | node → HA/InfluxDB |
| Germination count | day 2, 3, 5, 7, 10 after sowing | same | ruler, tweezers |
| Height (5 tallest per row) + leaf count | 2× per week (Mon, Thu) | day 7, 10, 14 | ruler 1 mm |
| Photo on fixed grid | every Monday + each count day | day 7, 14 | phone on tripod |
| EC1:5 + pH1:5 | at setup, then every 2 weeks (middle band core) | at setup + at end | TDSPEN, PHPEN |
| Infiltration test | at setup, week 4, week 8 (it disturbs soil — same spot) | – | 50 mm ring, 50 mL water |
| Penetrometer | at setup, week 4, week 8 | – | pencil + 1 kg |
| Harvest biomass (fresh, then dry) | cress day 14; radish day 28 | day 14 | kitchen scale 0.1 g |
| Leachate EC (sump tube) | weekly if water present | – | syringe + TDSPEN |
Manual measurement protocols
- Germination % = seeds with visible radicle ≥ 2 mm / seeds sown × 100, per row (tank) or per cup (bench).
- Height: soil surface to tip of the highest leaf, 5 tallest plants per row; leaf count = true leaves only (cotyledons separately).
- Soil EC and pH, 1:5 extract: take a core from the middle band with a cut-off 60 mL syringe (top 5 cm); air-dry 48 h on paper; crush, sieve 2 mm; weigh 10.0 g into a 100 mL screw-top jar; add 50 mL distilled water; shake 1 min, stand 30 min, shake again 30 s, let settle 30 min; dip TDSPEN (EC mode, auto-temperature-compensated to 25 °C) into the clear liquid, read when stable (30 s); rinse in distilled water; then PHPEN in the same extract. Record water temperature. Blank: distilled water alone must read < 10 µS/cm.
- EC notes: report µS/cm, not "ppm". If a pen only shows TDS, convert with the pen's factor (NaCl scale: EC ≈ TDS × 2; "442" scale: EC ≈ TDS × 1.4 — check the manual). EC1:5 is a relative index: to estimate the saturated-paste ECe used in agronomy multiply by ≈ 8–14 for sandy mixes (texture-dependent; our peat-sand mix is uncertain, so we compare zones, not absolute agronomic classes). Rule of thumb: ECe > 4 dS/m = saline for most crops.
- Calibrate TDSPEN with CALSOL EC 1413 µS/cm and PHPEN at pH 7 then 4 before every session; log the calibration.
- Infiltration: push a 5 cm long ring of 50 mm PVC pipe 2 cm into the soil; pour 50 mL distilled water in one go; stopwatch from pouring until no water glistens on the surface. Report seconds; repeat once 10 min later (second value = near-saturated rate).
- Penetrometer (static pencil test): an unsharpened HB pencil (flat 7 mm end) held vertically in a 20 mm PVC tube guide; place a 1.0 kg load (1 L water bottle) on top for 10 s; measure sinking depth in mm with a ruler. 3 readings per zone in the middle band, ≥ 3 cm apart. Calibrate the idea first on loose vs. tamped cups.
- Bulk density: 60 mL syringe core (volume known), oven-dry at 105 °C (teacher, kitchen oven) or air-dry 72 h, weigh: ρ = dry mass / volume (g/cm³).
Analysis
- Bench: mean ± range of germination % per level (n = 3); plot germination and shoot mass vs. measured EC1:5 (not just nominal dose); estimate the EC at which germination is halved by linear interpolation; compare cress vs. barley vs. orache curves (H5).
- Tank: time series in Grafana of ΔT =
mc_03_soil_temp_paved−mc_03_soil_temp_refand of moisture per zone; bar charts of row means per zone; compare each zone with E as % of control. - Simple statistics for liceu students: difference of means with range overlap; optional t-test / one-way ANOVA in a spreadsheet on bench data only.
- Ranking: "Which damage is worst?" — % of control for germination, final biomass, infiltration, penetration. Students must argue with data and name the confounders.
What shows by mid-December vs. spring
| By ~15 Dec 2026 | Spring 2027 (Feb–May) |
|---|---|
| Bench S1 and P1 complete (cress 7–10 days), S2 and C1 done; 2–3 rounds of engineering screening | Restoration of zones A–D with the winning interventions; EC trend after leaching/phytoremediation |
| Tank: cress germination and 14-day biomass per zone; radish ~4 weeks (sown 19 Nov) — leaf size, first root swelling | Radish to maturity; clover cover (%) and barley/orache biomass; repeat salinity test after 2 months of restoration |
| 4+ weeks of sensor data: ΔT heat island, drying curves per zone | Seasonal light change irrelevant (LED), but room temperature changes — compare winter vs. spring ΔT |
| Baseline + week-4 infiltration and penetrometer data | Earthworm avoidance tests (optional), final report and poster |
Engineering track
Problem statement: Our city block has four damaged plots (sealed + hot, compacted, salty, acidified). Design, build and test low-cost interventions that restore each plot so that plants grow at least 80 % as well as in the control soil, using only materials a school or a city could afford.
Requirements
| # | Requirement | Measure | Target |
|---|---|---|---|
| R1 | Growth recovery | cress shoot mass at day 14 as % of control | ≥ 80 % |
| R2 | Salt reduction (C) | EC1:5 drop vs. untreated salty cups | ≥ 50 % lower |
| R3 | Infiltration (A, B) | infiltration time | ≤ 2 × control |
| R4 | De-compaction (B) | pencil penetration depth | ≥ 75 % of control |
| R5 | Heat (A) | ΔT(A − E) at 2 cm with pad running the same program | reduced by ≥ 2 °C |
| R6 | Cost and safety | materials per m² of real city soil; non-toxic | < 50 RON/m² scaled, no hazardous materials |
| R7 | No salt export | leachate collected, measured and disposed of in the bin (never on garden beds) | 100 % of leachate logged |
Candidate interventions
| Damage | Intervention | Mechanism (what students should explain) | Test on bench / tank |
|---|---|---|---|
| Salt | Leaching with distilled water (1, 2, 3 pore volumes) | dissolves and moves NaCl down; salt moves, it does not disappear → leachate in sump | bench cups with drain hole over a saucer; tank C via sump tube |
| Salt | Agricultural gypsum 5 g/kg + leaching | Ca²⁺ replaces Na⁺ on soil particles, keeps structure open while leaching; gypsum alone does not lower EC (it is itself a salt) | bench R1 |
| Salt | Compost 20 % v/v / biochar 5 % v/v | more organic matter and water holding; dilution; biochar can adsorb a little; note compost has its own EC — measure it | bench R1 |
| Salt | Phytoremediation with Atriplex hortensis (orache), Hordeum vulgare (barley), Beta vulgaris (beet); optional Salicornia europaea | tolerant plants grow and take up some Na; harvest and measure leaf-extract EC → students compute how little salt a crop removes (critical thinking) | tank C Phase 2, bench S2 |
| Compaction | De-compaction (fork to 6 cm with a chopstick grid), compost + mulch, clover / radish "bio-drilling" | pores reopened mechanically vs. by roots and organisms | tank B, bench C1 |
| Paving | Pavement removal vs. permeable paving (pebbles / gravel-filled grid students design) | water enters soil, evaporation cools | tank A, infiltration test |
| Heat | Mulch 2 cm bark, vegetation cover, shade canopy (paper/acrylic "tree" under the LED), evaporative watering | less absorbed light, more evaporation; note our heat comes mainly from below (pad) — shade only reduces the LED share; use the IR thermometer on tile vs. mulch vs. soil | tank A |
| pH | Lime (for acid) / compost buffering; for alkaline, do not use more baking soda | neutralisation, buffering | bench P1 follow-up |
Test criteria: each intervention is compared against (a) untreated damaged cups/zone and (b) control, with 3 cups per treatment; pass = meets R1 + its specific requirement. Cost is computed per m² from the actual grams used.
Iteration plan
- R1 (16–23 Nov): screen 5 treatments on 3 g/kg salty soil: untreated, leach 2 PV, gypsum + leach, compost 20 %, biochar 5 % (15 cups, cress, 7 days + EC).
- R2 (23–30 Nov): keep the best 2, vary dose (e.g. leach 1 vs. 3 PV; compost 10 vs. 30 %) and combine (gypsum + compost + leach).
- R3 (30 Nov–7 Dec): test the final recipe on 6 g/kg soil and on compacted soil.
- Tank (Jan–Mar): apply final recipes to zones A–D (one at a time, logged), re-sow, compare with E; second paved-zone design (permeable paving prototype v2) after first infiltration results.
- Each iteration: design sheet (sketch, prediction, cost), build, test, one-paragraph "what we change and why".
Enclosure & build
Recommendation: TANK63 (60×30×35 cm glass, ~5 mm walls, inside ≈ 58.8×28.8 cm) used upright as a landscape: wide footprint, shallow 12 cm substrate, 23 cm of air above for plants, lighting and fan. Glass gives a side view of soil layers and roots. (The 60×40 BOXPLASTIC tray alternative is cheaper but opaque sides hide the soil profile and the walls flex when dividers are siliconed; use it only if TANK63 is unavailable.)
Internal layout (left → right, viewed from the front)
| Element | Width (cm) | Detail |
|---|---|---|
| Zone A — Paved + heat | 11 | tile 10×10×2 cm on 1 cm sand in middle band; HEATPAD under the glass floor below this zone |
| Thermal buffer | 2 | two acrylic dividers with a 20 mm XPS strip between (stops heat leaking into B) |
| Zone B — Compacted | 11 | |
| Zone C — Saline | 11 | |
| Zone D — Acidified | 11 | |
| Zone E — Control | 11 | |
| Dividers | 5 × 0.3 | 3 mm acrylic, 28.6 × 16 cm, siliconed to floor and both long walls |
Profile of each zone (bottom → top): 2 cm LECA drainage → geotextile → 10 cm soil mix → (zone A: 1 cm sand + tile). Each zone has a sump tube (16 mm PVC, 15 cm long, slotted bottom 2 cm, in the back-left corner down to the LECA) — a 60 mL syringe with silicone tubing pulls out excess water / leachate for measurement. Dividers stand 4 cm above the soil so watering cannot splash salt across zones.
Lid & light: two LEDPROFILE bars (cut to 58 cm, each with 55 cm of LEDSTRIP) screwed to two acrylic cross-bars (5 × 30 cm) resting on the top rim → LEDs 23 cm above the soil, at y ≈ 9 and y ≈ 20 cm. Rear half of the top covered by a 60 × 15 cm acrylic strip with a FAN cut-out (Ø 76 mm) above zone A and MESH-covered intake slots above zone E; front half open for access.
Under the tank: whole tank stands on a 20 mm XPS board (cushion + insulation); a 10×20 cm pocket is cut in the XPS under zone A for the HEATPAD, adhesive side up against the glass; KSD301 45 °C NC thermostat and 72 °C one-shot thermal fuse taped (aluminium tape) to the pad, wired in series in the pad's + lead. A filled tank weighs ≈ 45–50 kg: build it in its final place on a sturdy table.
Node box mounting: BOX on the wall/shelf bracket at the right end, box bottom above the tank rim; all cables enter from below via GLANDs with drip loops. PSU12 on the shelf above, on the RCD strip.
flowchart LR
subgraph TANK["TANK63 top view - front at bottom - LEDs 23 cm above soil"]
direction LR
A["Zone A Paved plus heat - tile 10x10 cm, HEATPAD under glass"]
X["XPS buffer 2 cm"]
B["Zone B Compacted"]
C["Zone C Saline 3 g NaCl per kg"]
D["Zone D Acidified pH minus 1.5"]
E["Zone E Control"]
A --- X --- B --- C --- D --- E
end
S1(["SOIL A plus DS18B20 paved at 2 cm under tile"]) -.-> A
S2(["SOIL B"]) -.-> B
S3(["SOIL C plus SHT31 on back glass plus BH1750 at canopy"]) -.-> C
S5(["DS18B20 ref plus SOIL D in control"]) -.-> E
F(["FAN 80 mm in lid above A"]) -.-> A
N["Node box mc-03-brownfield outside right end"]
E --- N
Soil probe allocation: SOIL A (paved), B (compacted), C (saline), D-channel probe placed in zone E (control). Zone D (acidified) has no continuous probe (only 4 ADC1 soil channels in the pin map): it is loose like E, so it is watered with the same volume as E, and its variable is pH, checked by extract. (Entity names follow the zone: mc_03_soil_moisture_paved, _compacted, _saline, _control.)
Build steps
| # | Step | Who | Time |
|---|---|---|---|
| 1 | Clean tank, mark zone lines on outside of glass with tape | students | 0.5 h |
| 2 | Cut acrylic: 6 dividers 28.6 × 16 cm, 2 cross-bars, rear lid strip, fan hole (teacher at saw/drill; deburr) | teacher + students | 2 h |
| 3 | Silicone dividers (glue A/buffer pair with XPS between), tape-hold vertical; cure 48 h | students | 1 h + 48 h |
| 4 | Water-test each cell: fill 2 cm in one cell, check neighbours after 2 h | students | 0.5 h |
| 5 | Cut XPS base, pocket for HEATPAD; fit pad, KSD301, fuse; strain-relief lead | Alacrity/teacher | 1 h |
| 6 | Node box: ESP32 on TERMBOARD, BUCK set to 5.0 V before connecting, 3 MOSFET modules, terminal wiring, glands; flash ESPHome | Alacrity + students | 3 h |
| 7 | Seal SOIL probe top edges (conformal coat + heat-shrink); label all cables | students | 1 h |
| 8 | LED strips into profiles, cross-bars, fan in lid | students | 1.5 h |
| 9 | Mix soil batch, fill sumps + LECA + fabric, fill zones; treat C (salt), D (vinegar), compact B, lay tile in A | students | 3 h |
| 10 | Probe calibration per zone, sensor commissioning, heat-loop test with pad (observe 2 h) | students + Alacrity | 2 h |
| 11 | Sow; photo grid set-up | students | 1 h |
Total ≈ 17 h of hands-on time + curing.
Biology
Indicator plants (all non-toxic, fast):
| Species | Common (RO) | Role | Germination / first data |
|---|---|---|---|
| Lepidium sativum | garden cress (creson) | main bioassay, salt-sensitive | 2–3 days; data at 7–10 days |
| Raphanus sativus | radish (ridiche de lună) | root/compaction indicator | 3–5 days; 3–4 weeks to swelling |
| Trifolium repens | white clover (trifoi alb) | ground cover, N-fixing, restoration | 5–10 days; cover in 6–8 weeks |
| Hordeum vulgare | barley (orz) | moderately salt-tolerant cereal | 2–4 days |
| Atriplex hortensis | garden orache (lobodă de grădină) | halophyte, phytoremediation | 5–10 days |
| Beta vulgaris | beet (sfeclă roșie) | salt-tolerant crop | 5–10 days |
| Salicornia europaea (optional) | glasswort (brâncă) | true halophyte, native to Romanian saline soils | slow, 10–20 days; seeds only online |
Seed sourcing (Bucharest): cress, radish, beet and orache seed packets (Agrosem, Florian, Opal, Agrosel brands, 3–7 RON/packet) at Dedeman, Hornbach, Leroy Merlin and agro shops (e.g. Piața Obor seed stalls); white clover in 100 g–1 kg lawn-seed bags (Dedeman/agro shops); barley as untreated feed grain from agro shops / pet shops ("orz", check it is not fungicide-treated seed — no coloured coating); Salicornia from online seed sellers (eMAG marketplace / EU shops). Use untreated seed only (no coloured fungicide coating).
Soil mix (one batch for everything, ~35 L): universal potting soil ("pământ universal", peat-based) : washed fine quartz sand = 1 : 1 by volume, mixed dry in a tub, sieved through 1 cm mesh. Measure baseline EC1:5 and pH1:5 of the batch (commercial potting soil often has 200–800 µS/cm of fertiliser salts and pH 5.5–6.5 — this is the "0" level). Do not use schoolyard or roadside soil (unknown contaminants).
Inoculants: optional mycorrhizal inoculant (garden-shop "micorize" product) dusted into the radish/clover rows in Phase 2 as an extra factor; clover nodules (pink = active) are a bonus indicator — if seed is not pre-inoculated, expect few nodules and record that.
Earthworms (optional bio-indicator, invertebrate): Eisenia fetida (red wigglers, "râme roșii", fishing shops, ~15 RON/cup). Use only in a separate avoidance test: a 1 L box split in half, control soil vs. test soil (salty / acid / restored), 10 worms placed on the line, cover dark, count on each side after 48 h; worms then return to the Orchestra of Rot compost. Never put worms in the salty tank zones.
Establishment steps
- Mix and moisten batch to ~60 % of water-holding capacity (squeeze test: holds shape, no dripping).
- Fill zones; apply treatments (salt dissolved in the wetting water, mixed in a bucket per zone before filling — homogeneous; vinegar the same way).
- Let zones equilibrate 3 days, then measure baseline EC/pH/infiltration/penetrometer.
- Sow with a template (cardboard strip with holes at 2 cm / 4 cm), 5 mm deep, mist with distilled water, cover the tank front half with cling film until day 3.
- Remove film when > 50 % of control seeds are up; begin height counts.
Instrumentation
| Catalog ID | Qty | Placement | Interval | Purpose / entity |
|---|---|---|---|---|
| SOIL | 4 | vertical in middle band of zones A, B, C and E, inserted to the line (sensing 0–6 cm), 3 cm from the tile edge in A | 60 s, mean of 10 samples | moisture per zone; mc_03_soil_moisture_paved / _compacted / _saline / _control |
| DS18B20 | 2 | (1) zone A, 2 cm deep directly under the tile; (2) zone E, 2 cm deep, middle band | 60 s | heat island ΔT and heater control; mc_03_soil_temp_paved, mc_03_soil_temp_ref |
| SHT31 | 1 | back glass, 15 cm above soil, zone C, in its case, shielded from direct LED | 60 s | air T/RH, fan control; mc_03_air_temp, mc_03_air_humidity |
| BH1750 | 1 | on a stake at canopy height (5 cm, raise as plants grow), zone C middle band, facing up | 60 s | photoperiod check, LED ageing; mc_03_light. Lux ≠ PAR — relative only |
| OLED | 1 | node box lid | live | values + Wi-Fi + heater state |
| PHPEN | shared | lab | per protocol | pH1:5 |
| TDSPEN | shared | lab | per protocol | EC1:5, leachate EC |
| CALSOL | shared | lab | before every session | pH 4/7 + EC 1413 µS/cm |
| TOOL: IR thermometer | 1 | handheld | each measurement day | surface T of tile / mulch / soil / leaves |
Pin assignment (standard pin map only)
| Function | GPIO | Connected |
|---|---|---|
| I2C SDA / SCL | 21 / 22 | SHT31 (0x44), BH1750 (0x23), OLED (0x3C) |
| 1-Wire | 4 | DS18B20 ×2, 4.7 kΩ pull-up to 3.3 V |
| Analog A / B / C / D | 32 / 33 / 34 / 35 | SOIL paved / compacted / saline / control |
| PWM 1 (light) | 16 | MOSFET → LEDSTRIP (2 × 55 cm) |
| PWM 2 (fan) | 17 | MOSFET → FAN |
| PWM 3 (pump) | 18 | unused (irrigation manual) |
| PWM 4 (heater) | 19 | MOSFET → KSD301 → fuse → HEATPAD |
| Not used | 36, 39, 23, 25, 26, 27, 13, 14, 5, 15, 12 | free for student extensions (e.g. analog E for a later continuous probe) |
MOSFET modules: use logic-level D4184 type (IRF520 boards do not fully switch at 3.3 V gate drive). Soil probes powered from 3.3 V so their output stays inside the ADC range; ADC attenuation 11 dB (written 12db in current ESPHome).
Power budget (PSU12 12 V 5 A = 60 W): LEDs 1.1 m × 14.4 W/m ≈ 16 W, HEATPAD 20 W, FAN 1.5 W, ESP32 + sensors via BUCK ≈ 2 W → ≈ 40 W peak (67 % of rating).
Soil probe calibration (per probe, per zone, in that zone's own soil):
- Take ~400 mL of the zone's treated mix (salty mix for C, compacted core for B) in a cup.
- Air reading (probe in air) and dry reading (air-dry mix) → 0 %.
- Saturated reading (add distilled water until free water appears, wait 30 min) → 100 % of saturation.
- A gravimetric mid-point: weigh cup, compute water content, record raw ADC → check linearity.
- Enter dry/wet raw voltages in ESPHome
calibrate_linearfor that channel; re-check in week 6.
Why per zone, including salty soil: a resistive fork probe measures the electrical current through the soil, which depends on dissolved ions as much as on water — adding salt makes the soil read "wet" even when it is dry, and the DC current corrodes the forks. A capacitive probe measures the soil's dielectric permittivity (water ≈ 80, mineral/organic matter ≈ 3–5, air = 1), which depends mostly on water content, so salt affects it much less. But the v2.0 probe works at a relatively low frequency (~1.5 MHz), where high ionic conductivity still raises the reading somewhat, and peat vs. compacted sand changes the dry/wet endpoints. So zone C may read a few % "wetter" than reality, and B differs from E — without per-zone calibration a moisture difference could be a salt or density artefact. Students can test this directly: same water content, 0 vs. 6 g/kg cup, compare raw readings.
ESPHome excerpt (heater loop; full YAML in the repo):
one_wire:
- platform: gpio
pin: GPIO4
sensor:
- platform: dallas_temp
id: t_paved
name: "mc_03_soil_temp_paved"
address: 0x0000000000000000 # fill in from log
- platform: dallas_temp
id: t_ref
name: "mc_03_soil_temp_ref"
address: 0x0000000000000000
output:
- platform: slow_pwm
id: heat_out
pin: GPIO19
period: 10s
globals:
- id: heat_lockout
type: bool
restore_value: true
initial_value: "false"
number:
- platform: template
id: delta_t
name: "mc_03_heat_delta_setpoint"
min_value: 0
max_value: 8
step: 0.5
initial_value: 6
optimistic: true
restore_value: true
switch:
- platform: template
id: heat_enable
name: "mc_03_heat_enable"
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
button:
- platform: template
name: "mc_03_heat_reset"
on_press:
- lambda: 'if (id(t_paved).state < 35) id(heat_lockout) = false;'
interval:
- interval: 30s
then:
- lambda: |-
float tp = id(t_paved).state, tr = id(t_ref).state;
bool bad = isnan(tp) || isnan(tr) || tp < -50 || tp > 84;
if (!bad && tp >= 42.0f) id(heat_lockout) = true;
if (bad || id(heat_lockout) || !id(heat_enable).state) { id(heat_out).set_level(0); return; }
float target = std::min(tr + (float) id(delta_t).state, 38.0f);
float duty = (target - tp) * 0.25f; // 25 % per degC error
duty = std::max(0.0f, std::min(duty, 0.70f)); // duty limit 70 %
id(heat_out).set_level(duty);
Automation
Heat-island control (zone A). Goal: soil under the tile at 2 cm = reference (zone E) + 6 °C during the photoperiod. Layers of protection: (1) software target capped at 38 °C, P-control with duty limit 70 %; (2) software lockout at 42 °C paved-soil temperature or any sensor fault (needs a manual reset in HA, only accepted below 35 °C); (3) KSD301 45 °C NC bimetal thermostat on the pad (hardware, self-resetting) — the pad/glass never exceeds ~45 °C; (4) 72 °C one-shot thermal fuse in series as last resort. HA automation turns mc_03_heat_enable on at 07:30 and off at 21:00, and sends an alert on lockout. The heater is off during school holidays.
stateDiagram-v2
[*] --> Off
Off --> Regulating: heat_enable on and both probes valid
Regulating --> Regulating: every 30 s duty = 0.25 x error, max 0.70
Regulating --> Off: heat_enable off at 21.00
Regulating --> Lockout: paved temp 42 or more, or probe fault
Off --> Lockout: probe reads 42 or more
Lockout --> Off: manual reset in HA and paved temp below 35
note right of Regulating
target = ref + 6, capped at 38
KSD301 opens at 45 on the pad
end note
Fan (GPIO17): air exchange 5 min every hour during the photoperiod; additionally ON at 100 % if mc_03_air_humidity > 85 % or mc_03_air_temp > 30 °C, OFF when < 80 % and < 28 °C (prevents mould on the cling-film days and condensation above the warm zone). PWM 25 kHz, minimum 40 % (below that 80 mm fans stall).
LED (GPIO16): 14 h/day, 07:00–21:00, ESPHome light with 15 min sunrise/sunset ramps, 80 % brightness default (adjust so BH1750 reads the same lux in every run; log the setting).
Irrigation stays manual, with measured volumes — why:
- Water volume is part of the experiment: it dilutes or concentrates salt and leaches it to the sump; every millilitre must be known for the salt mass balance.
- Five isolated cells would need five pumps/valves; one shared line would carry salt between zones.
- The tank has no drain; an automatic fault would waterlog a cell (anaerobic soil, ruined experiment).
- Students learn more by deciding when and how much to water from sensor data than by watching a pump.
Operations
Watering protocol: distilled water only (Bucharest tap water adds ~300–500 µS/cm of salts). Water a zone when its calibrated moisture < 40 % of saturation; add water with a 60 mL syringe / 100 mL cylinder to bring it to ~60 % (volume from the calibration: mL = (target − current) × zone pore volume; start with 50 mL steps); water the cress and radish bands, never the tile (zone A: pour 1/3 of the dose on the tile edge to simulate runoff). Log zone, date, mL, reason. Same volume rules on the bench, by weight (cup to target mass).
Weekly checklist (Monday, 20 min)
- Photos: phone on fixed tripod mark, 50 cm in front, full tank + one top-down per zone with a printed 1 cm grid card and zone label
- HA dashboard: all 8 sensor entities reporting, heater state, no lockout
- ΔT in Grafana last 7 days (expected ~+6 °C daytime)
- Moisture per zone → water per protocol, log volumes
- Sump tubes: extract any free water, measure EC, record mL, dispose in bin bag
- Check pad lead, glands, no water on the XPS
- Zone D pH check (every 2 weeks), re-dose if drift > 0.5
- Bench: rotate cups, count/measure per schedule
Manual logs (shared spreadsheet, one tab each): sowing & counts; heights & leaves; EC/pH extracts (incl. calibration line); infiltration & penetrometer; watering & leachate; interventions (what, grams, cost); incidents.
End of term (by 18 Dec): harvest cress, dry biomass; radish measured (leave in); disable heater (heat_enable off, HA automation paused); LED 12 h; water all zones to 60 %, cover front with cling film (with 2 cm gap); teacher check once a week in the holiday (HA moisture alert at < 30 %); export data snapshot CSV.
Disposal: salty and vinegar-treated soil goes into a sealed bag in the general waste — never onto school garden beds or lawn (it would really salinise them). Control-zone soil can go to compost.
Safety & risks
| Hazard | Control |
|---|---|
| Salt (NaCl) | non-toxic in these amounts but irritates eyes and cuts; goggles when mixing brine, gloves, wash hands; never taste anything; label all containers "NOT FOOD" |
| Vinegar 9 % | eye/skin irritant: goggles + gloves, dilute 1:10 before use (adult handles concentrate), never mix with bleach or other cleaners; baking soda + vinegar fizz (CO₂) is harmless but done in an open cup |
| Baking soda / lime | dust: scoop, do not pour from height; garden lime with gloves |
| Heat pad | 12 V only, through MOSFET; software cap 38 °C, lockout 42 °C, KSD301 45 °C NC + 72 °C one-shot fuse on the pad; pad on XPS (not on wood/paper), no wet contact; never run it with the tank removed; off during holidays |
| Glass edges / weight | rimless tank edges: gloves when moving; two people; fill in final position (≈ 50 kg filled); sturdy table |
| Acrylic cutting | teacher at the saw/drill; students deburr with file; goggles |
| Electrical | SELV ≤ 12 V inside/under the tank; PSU12 certified brick on shelf above on 30 mA RCD strip with drip loop; node box outside, glands from below; BUCK pre-set to 5.0 V before connecting the ESP32 |
| Soil/biology | gloves for soil and compost work; potting soil dust → moisten before mixing; wash hands; no schoolyard/roadside soil; only non-toxic plants; worms handled gently and returned to compost |
| Mould / fungus gnats | fan schedule, don't overwater, mesh on intake |
Educational outcomes & assessment
| Outcome | Evidence | Assessed by |
|---|---|---|
| Formulate testable hypotheses with predictions | hypothesis sheet with numeric predictions (e.g. EC per g/kg) | teacher rubric 0–3 |
| Design controlled, replicated experiments; recognise pseudo-replication | bench plan + written explanation of tank vs. bench | rubric |
| Precise measurement and calibration | calibration log, EC/pH protocol carried out independently (observed) | practical check |
| Quantitative reasoning | dose calculations, % of control, dose-response graph, EC halving point | worksheet |
| Systems thinking: salt moves, doesn't vanish; trade-offs (heat vs. moisture) | leachate mass balance, discussion of confounders | short written argument |
| Engineering design cycle | requirements table, 3 iteration sheets, cost per m², final recipe | design portfolio |
| Use of sensors/data | Grafana ΔT chart interpreted, sensor limits stated (lux ≠ PAR, capacitive vs. resistive) | presentation |
| Communication & civic link | 5-min presentation "Which damage is worst for Bucharest soil and what would you do?" | peer + teacher |
Sub-BOM
Cost-cut 2026-10-20: the three optional biology lines (Salicornia, inoculant, worms) are removed; add in spring if the restoration round needs them.
Price basis: Romanian retail estimates incl. VAT, Oct 2026 — electronics optimusdigital.ro / cleste.ro / ardushop.ro; tank & aquaristics emag.ro / pet shops; building and garden items dedeman.ro / hornbach.ro; heat pad & thermal parts AliExpress fallback. Shared items (PHPEN, TDSPEN, CALSOL, Pi hub, router) are in the common BOM and shown here at 0.
| ID / item | Qty | Unit RON | Line RON | Basis / note |
|---|---|---|---|---|
| ESP32 | 1 | 45 | 45 | optimusdigital |
| TERMBOARD | 1 | 30 | 30 | optimusdigital/AliExpress |
| OLED | 1 | 20 | 20 | optimusdigital |
| SHT31 | 1 | 55 | 55 | cased/PTFE version |
| DS18B20 | 2 | 15 | 30 | waterproof 1 m |
| SOIL | 4 | 10 | 40 | v2.0 TL555 version; spares from common pool |
| BH1750 | 1 | 12 | 12 | |
| MOSFET | 3 | 12 | 36 | D4184 logic-level (light, fan, heater) |
| PSU12 | 1 | 60 | 60 | certified 12 V 5 A brick + DC jack |
| BUCK | 1 | 10 | 10 | LM2596 |
| BOX | 1 | 35 | 35 | IP65 ABS |
| GLAND | 6 | 2.5 | 15 | PG9; sensor cables grouped |
| FAN | 1 | 25 | 25 | 12 V 80 mm |
| HEATPAD | 1 | 45 | 45 | 12 V 20 W silicone 10×20 cm |
| PART: KSD301 45 °C NC thermostat | 2 | 6 | 12 | 1 spare |
| PART: thermal fuse 72 °C 10 A one-shot | 2 | 3 | 6 | 1 spare |
| LEDSTRIP | 0.25 reel | 110 | 28 | 1.1 m of a shared 5 m reel |
| LEDPROFILE | 2 | 25 | 50 | cut to 58 cm |
| PART: 4-core cable 0.25 mm², 5 m | 1 | 15 | 15 | sensor runs; ferrules from common lot |
| TANK63 | 1 | 260 | 260 | 60×30×35 glass, emag/pet shop |
| ACRYLIC | 1 | 90 | 90 | dividers, lid strip, cross-bars |
| SILICONE | 1 | 30 | 30 | aquarium-safe |
| MESH | 0.1 m² | 50/m² | 5 | intake slots |
| PART: XPS board 20 mm | 1 | 20 | 20 | Dedeman, base + buffer strip |
| PART: screws, brackets, standoffs | 1 lot | 15 | 15 | |
| BIO: universal potting soil 50 L | 1 | 30 | 30 | Dedeman |
| BIO: washed quartz sand 25 kg | 1 | 20 | 20 | Dedeman/Hornbach |
| BIO: LECA expanded clay 10 L | 1 | 25 | 25 | drainage layer |
| BIO: geotextile 1 m² | 1 | 10 | 10 | |
| BIO: NaCl table salt 1 kg | 1 | 3 | 3 | supermarket |
| BIO: vinegar 9 % 1 L | 1 | 5 | 5 | supermarket |
| BIO: baking soda 500 g | 1 | 6 | 6 | supermarket |
| BIO: garden lime 2 kg | 1 | 15 | 15 | Dedeman |
| BIO: agricultural gypsum (CaSO₄·2H₂O) 2 kg | 1 | 30 | 30 | emag/agro shop — NOT construction plaster |
| BIO: vermicompost / compost 10 L | 1 | 25 | 25 | Dedeman |
| BIO: biochar 5 L | 1 | 45 | 45 | emag |
| BIO: pine bark mulch 10 L | 1 | 15 | 15 | |
| BIO: distilled water 5 L | 6 | 6 | 36 | auto/supermarket |
| BIO: concrete tile/paver 10×10–10×20 cm | 3 | 6 | 18 | 1 in use + prototypes |
| BIO: pebbles/gravel 5 kg | 1 | 15 | 15 | permeable paving prototypes |
| BIO: seeds cress (Lepidium sativum) | 3 pkt | 5 | 15 | Agrosem/Florian |
| BIO: seeds radish (Raphanus sativus) | 2 pkt | 4 | 8 | |
| BIO: seeds white clover (Trifolium repens) 100 g | 1 | 15 | 15 | |
| BIO: barley grain untreated (Hordeum vulgare) 1 kg | 1 | 12 | 12 | agro/pet shop |
| BIO: seeds orache (Atriplex hortensis) | 1 pkt | 7 | 7 | |
| BIO: seeds beet (Beta vulgaris) | 1 pkt | 4 | 4 | |
| TOOL: clear PP cups 400 mL | 50 | 0.4 | 20 | bench |
| TOOL: kitchen scale 0.1 g / 500 g | 1 | 40 | 40 | emag |
| TOOL: graduated cylinder 100 mL | 1 | 15 | 15 | |
| TOOL: syringes 60 mL | 4 | 3 | 12 | cores + sump extraction |
| TOOL: PVC pipe 50 mm 0.5 m + 16 mm 1 m + 20 mm 0.3 m | 1 | 13 | 13 | infiltration rings, sumps, penetrometer guide |
| TOOL: screw-top sample jars 100 mL | 12 | 1.5 | 18 | 1:5 extracts |
| TOOL: IR thermometer | 1 | 60 | 60 | emag |
| TOOL: 2 mm soil sieve | 1 | 15 | 15 | |
| TOOL: nitrile gloves box 100 | 1 | 30 | 30 | |
| TOOL: safety goggles | 2 | 12 | 24 | |
| TOOL: phone clamp + mini tripod | 1 | 40 | 40 | fixed photo grid |
| PHPEN, TDSPEN, CALSOL | shared | – | 0 | common pool |
| Subtotal | 1 635 RON (≈ 321 EUR) | of which electronics ≈ 584 RON; optional biology removed in the cost-cut pass |
8-week timeline (26 Oct – 18 Dec 2026)
| Week | Dates | Science | Engineering / build | Milestone |
|---|---|---|---|---|
| 1 | 26–30 Oct | driving question, hypotheses; soil batch mixed; baseline EC/pH; bench S1 sown 29 Oct | order parts; design sketches of tank zones | parts ordered, S1 running |
| 2 | 2–6 Nov | S1 counts day 2–7 (read 5 Nov); dose calculations for tank | cut acrylic, silicone dividers (cure), water test | first dose-response graph |
| 3 | 9–13 Nov | P1 (pH) and C1 (compaction) sown 9 Nov; vinegar titration curve | node box built and flashed; LED/fan lid; heat-pad install | node online in HA |
| 4 | 16–20 Nov | fill & treat zones, equilibrate 3 days, baseline infiltration/penetrometer; probe calibration; tank sown 19 Nov (cress + radish); S2 sown | heat loop commissioned (2 h supervised test); R1 screening sown | tank running, ΔT logged |
| 5 | 23–27 Nov | tank cress germination day 2–7; P1/C1 harvest | R1 read → choose best 2; R2 sown | iteration 1 report |
| 6 | 30 Nov–4 Dec | tank cress height + day-14 biomass (3 Dec); S2 read | R2 read; R3 (6 g/kg + compacted) sown | iteration 2 report |
| 7 | 7–11 Dec | week-4 infiltration/penetrometer; data analysis in spreadsheet + Grafana; radish ~3 weeks | R3 read; final restoration recipe + cost/m²; Phase-2 plan | commissioning complete by 15 Dec |
| 8 | 14–18 Dec | radish ~4 weeks measured; poster/presentation | holiday mode (heater off, LED 12 h, cover, alerts) | presentation; CSV snapshot |
Phase 2 (Jan–May 2027): apply recipes to zones A–D, re-sow clover/barley/orache, monthly EC/pH/infiltration, spring repeat of S1 on restored soil, earthworm avoidance tests, final report.
4–5. The Future Is Not What It Used to Be (2026 vs 2056)
Concept (refined)
Two identical 45 L glass tanks get the same substrate batch, seed lot, pot layout, LED strip and lid. They differ only in a climate treatment package written in software:
- Tank A,
mc-04-future2026: current Bucharest growing-season conditions, adapted to the classroom. - Tank B,
mc-05-future2056: a 2056 scenario. Air is +3.5 °C warmer. Rain over each 14-day cycle has the same total volume, but it comes as one extreme event, one small shower and then a 10-day drought. CO2 is held at 700–800 ppm while the lights are on.
Both tanks carry the full hardware set: heat pad, CO2 inlet, servo vent flap, pump and rain bars. The two ESPHome YAMLs differ only in substitutions:. Because of this, the treatments can be swapped between tanks in spring (crossover design) to separate the climate effect from any "tank effect".
This is a scenario experiment: heat, rainfall pattern and CO2 change together. Run 1 cannot attribute an effect to any single factor, and students must say so in their reports. A single-factor decomposition run is planned for spring (Run 3, CO2 dosing off).
Climate scenario definition
| Parameter | 2026 setpoint (mc-04) | 2056 setpoint (mc-05) | Source / justification |
|---|---|---|---|
| Air temperature | Room-following. Heater floor 19 °C (pad only switches on if the tank drops below 19 °C at night or on weekends). Expected 20–25 °C with lights on. | T_2026 (10-min mean) + 3.5 °C, clamped 22.5–30.5 °C. Fallback fixed 24.5 °C if T_2026 is unavailable > 10 min. | Bucharest May–June mean ≈ 17–21 °C, so a classroom at 20–22 °C stands in for the growing season. Projections for SE Romania by 2041–2060 (ANM / Copernicus CORDEX, RCP8.5) give +1.5–2.5 °C annual mean and up to ~+3 °C in summer. +3.5 °C is a deliberately amplified high-emission summer plus urban-heat-island value, chosen so the effect exceeds sensor error and day-to-day noise. |
| Substrate temperature | Response, logged (cap 30 °C) | Response, logged (hard cap 30 °C; heater off above it) | Heat comes from below (pad), as in a warming soil. Logged so students can see the soil–air gradient. |
| Establishment watering, days 0–6 after sowing | 20 mL/pot/day at 10h00 | Identical: 20 mL/pot/day | Germination must not be killed by drought. During this week heat and CO2 are the only differences, which isolates the germination hypothesis. |
| Rain, amount (from day 7) | 200 mL/pot per 14 days (≈ 22 mm on a 9.5 cm pot; ≈ 11 mm/week) | Same 200 mL/pot per 14 days | Bucharest normal ≈ 590–620 mm/yr (ANM 1991–2020) ≈ 11.5 mm/week. Pot area 90 cm²: 50 mL = 5.5 mm. |
| Rain, pattern | 4 × 50 mL/pot: every Mon and Thu at 10h00 | Every other Mon at 10h00: 150 mL/pot "cloudburst", delivered at full pump speed. The following Fri: 50 mL/pot. Then 10-day drought (Fri → Mon). | IPCC AR6 WGI (Ch. 11–12, Mediterranean/SE Europe): heavier short extreme events and longer dry spells. Total volume is held equal, so only the distribution changes. |
| Rain, per tank per event (15 pots) | 750 mL | 2 250 mL (cloudburst) / 750 mL | Pump time = volume ÷ calibrated mL/s. |
| Substrate moisture | Response. Expected 35–65 % of calibrated scale (0 = air-dry mix, 100 = saturated). | Response. Expected swings from ≈ 95 % (after the cloudburst) to < 15 % (end of drought). | Moisture is the response, not a controlled setpoint. Controlling it would cancel the treatment. |
| Drought rescue | n/a | If a pot shows wilting score 3 for 24 h, the teacher may give 30 mL by syringe. Logged as a data point. | Lets the run continue after a mis-specified drought. Every rescue becomes a result ("the 2056 drought kills radish seedlings at day X"). |
| CO2 | Room air, refreshed by scheduled "breaths". Expected 420–550 ppm nights/weekends, 800–1500 ppm in occupied lesson hours. | 700–800 ppm during the light period (dose below 700, stop at 780). Night: no dosing, cap 1 000 ppm. | Global mean ≈ 425 ppm in 2025 (NOAA). Urban Bucharest air ≈ 430–470. SSP2-4.5 gives ≈ 530–550 ppm by 2056, SSP5-8.5 ≈ 600 ppm. 700–800 ppm is amplified (late-century SSP3-7.0/5-8.5), chosen so the contrast stays > 200 ppm. SCD41 accuracy is ±(50 ppm + 5 %). |
| Air exchange | Identical in both tanks: lid slider set to a 5 mm gap. A "breath" every 30 min opens the flap and runs the fan at 60 % for 60 s. Extra breath if RH > 92 % for 30 min. 2026 only: also an extra breath if CO2 < 430 ppm (photosynthetic depletion). | Same breaths and same RH rule. A CO2 dose follows each breath. | Matched ventilation keeps RH and evaporation comparable. Without it, a sealed 2056 tank would also be a "humid tank". |
| Relative humidity | Response, logged | Response, logged. Mister disabled in Run 1 (enabled only in the spring "tropical night" variant). | Avoids adding an extra variable. Warmer air in the 2056 tank should lower RH slightly, which is realistic. |
| Light | 3 × 46 cm 12 V full-spectrum strips, PWM 80 % (trimmed so BH1750 at canopy matches the other tank ± 5 %) | Identical | Light is a controlled variable. BH1750 measures lux, not PAR, which is fine for checking equality. |
| Photoperiod | 14 h, 06h00–20h00 | Identical | Adequate for fast crops; the same in both. |
Honest limits of the CO2 treatment (state this in student reports).
- Classroom air is not "2026 outdoor air". Occupied classrooms regularly reach 1 000–2 000 ppm (Fisk 2017, Indoor Air 27:1039, review of school ventilation; EN 16798-1 Cat. II wants < 800 ppm above outdoor). During lessons the 2026 tank can therefore sit at 1 200 ppm, above the 2056 target. Mitigations:
- Put the pair in the least-occupied room (lab, not homeroom).
- Ventilate windows at every break.
- Report a treatment-fidelity metric: the share of light-period hours with CO2_2056 − CO2_2026 ≥ 200 ppm.
- Expected fidelity is ≈ 75–80 %, because about 130 of the 168 hours in a week are unoccupied.
- The 2056 tank is semi-sealed. Plants deplete CO2 in light, so it is a dosing controller, not a "set and forget". The yeast generator overproduces by ≈ 10–40×, so the servo pinch valve meters it.
- A single SCD41 per tank samples one point. Mixing relies on heat-pad and LED convection. Check homogeneity during commissioning by moving the sensor to 3 heights.
- The SCD41 automatic self-calibration (ASC) assumes the sensor sees ~400 ppm weekly. The 2056 tank never does, so ASC is disabled on both sensors. Calibration is manual (see Instrumentation).
Science track
Driving question. If Bucharest's climate in 2056 is hotter, has its rain in fewer and heavier events, and has more CO2, how will common crop plants germinate, grow and use water compared with today?
Hypotheses (directional, testable by mid-December or in spring):
| # | Hypothesis | Prediction | Measured by |
|---|---|---|---|
| H1 Germination | Warmer air and elevated CO2 speed up germination of cress and radish. Wheat changes less (cool-season crop). | T50 (days to 50 % emergence) in 2056 ≤ 0.75 × T50 in 2026 for cress and radish. Final germination % the same (± 10 points). | Daily emergence counts, days 1–7 |
| H2 Growth/biomass | Under the 2056 package, early shoot growth is faster while water is available (warmth + CO2 fertilisation of C3 plants). Final radish storage-root dry mass is lower (≥ 20 %) because of drought cycles and heat. | Height RGR higher in 2056 days 7–14. Hypocotyl dry mass lower at harvest (day 31). | Height, leaf count, fresh/dry mass, hypocotyl diameter |
| H3 Water use | 2056 pots lose more water per day (higher VPD). During the cloudburst a larger share of the rain drains through unused. | Daily mass loss per pot ≥ 1.3× the 2026 value. Drainage fraction of the cloudburst ≥ 30 % vs ≤ 10 % for 50 mL events. | Pot weighing, drainage volume siphoned from the tank floor, SOIL curves |
| H4 Stress signs | Visible drought stress (wilting, leaf rolling, chlorosis, tip burn) appears in 2056 from about day 6 of each drought window, and only rarely in 2026. | ≥ 3 wilting-score-≥ 2 days per pot per drought window in 2056 vs 0 in 2026 | Daily stress score 0–3, weekly photo |
Variables.
- Independent variable: climate package (2026 vs 2056).
- Dependent variables: emergence, height, leaf count, fresh/dry mass, hypocotyl diameter, root:shoot ratio, pot mass loss, drainage, stress score, SOIL %, canopy green area from photos.
- Controlled: tank model, lid, substrate batch and fill mass, seed lot, sowing depth and count, pot positions (same randomised map), light (lux matched), photoperiod, ventilation schedule, total water.
- Logged covariates: room CO2 (proxy = mc-04 right after a breath), room temperature, RH.
Replication.
- Per tank: 15 pots (9.5 × 9.5 × 9 cm) in a 5 × 3 grid.
- Science: 3 species × 3 replicate pots = 9 pots.
- Engineering: 6 radish pots (2 control, 2 mulch, 2 hydrogel). The engineering controls are biologically identical to the science radish pots, so radish control n = 5 per tank.
- Pot positions come from one random draw (dice/spreadsheet). The same map is used in both tanks.
- Every Monday all pots move one position along a fixed serpentine rotation, identically in both tanks. This averages out edge, heat-pad and fan gradients.
- Within-tank pots are pseudo-replicates of the treatment: there is only one tank per treatment. The spring crossover (Run 2: mc-04 becomes 2056, mc-05 becomes 2026) gives two independent tank × treatment combinations and shows whether a "tank effect" exists.
- Cress is re-sown every ~10 days (3 cycles before Christmas), which gives temporal replication.
Sampling schedule.
| What | When | Who |
|---|---|---|
| Automatic: SHT31, SCD41, DS18B20, SOIL, BH1750 | every 60 s (SOIL = mean of 10 reads) | node → InfluxDB |
| Emergence count (per pot, per species) | daily, days 1–7 (incl. Fri; weekend counts back-filled from photos) | student pair |
| Pot mass (5 kg / 1 g scale) | Mon and Thu before 10h00. Also 30 min after every rain event. | student pair |
| Height (tallest plant, ruler from substrate surface), leaf count | Mon and Thu | student pair |
| Stress score 0–3 (0 turgid, 1 slight droop, 2 wilted leaves, 3 collapsed) + chlorosis Y/N | every school day | student pair |
| Top-down photo from a fixed acrylic jig (phone, flash off, LEDs on) | Mon | student |
| Drainage on tank floor (syringe + tube into a measuring cylinder) | 24 h after every event, then Mon | student |
| Destructive harvest: thinned seedlings (day 7); cress (day 10 of each cycle); wheat clip at 3 cm (day 21); radish science pots (day 31) | per timeline | whole team |
| Dry mass: paper bags, oven 70 °C 48 h (teacher) or radiator shelf 7 days, then 0.01 g scale | after each harvest | teacher + student |
Analysis.
- Treatment fidelity first. Daily mean ΔT (target 3.5 ± 0.5 °C), the light-period CO2 contrast, and lux ratio. Data from days that failed fidelity is flagged, not deleted.
- Paired comparison by position. Pot i in A vs pot i in B (same species, same position): difference ± SD. With n = 3 per species, report effect size and all individual points (dot plot). Welch t-test or Mann–Whitney as an exercise only, with a power caveat.
- Growth curves. Height vs day per pot. RGR = (ln H2 − ln H1)/(t2 − t1). Biomass RGR from day 7 thinnings to day 31 harvest.
- Germination curves. Cumulative % vs time. T50 by linear interpolation.
- Water. Daily mass loss (g/day) per pot. Drainage fraction = drainage ÷ delivered. Water-use efficiency = dry mass ÷ water transpired.
- Sensor curves. Grafana overlays of SOIL A/B vs time with rain events annotated. Drying rate (slope % per day) after each event.
- Crossover (spring). Effect = mean over both runs of (2056 − 2026). Tank effect = mean of (Tank B − Tank A) across runs.
What shows by mid-December vs spring.
- By ~Dec 18:
- H1 complete for all 3 species (sown Nov 16).
- H3 and H4 over 2 drought cycles (Nov 23 – Dec 21).
- 3 cress cycles and 1 wheat clip.
- Radish science harvest (day 31, Dec 17). Roots will be small (≈ 1–2 cm), which is enough for the dry-mass comparison.
- First engineering results (mulch/hydrogel moisture curves).
- Spring (Feb–May):
- Run 2 crossover (Feb 1 – Mar 26): same protocol, tanks swapped.
- Run 3 decomposition (Apr 12 – May 28): 2056 heat + rain with CO2 dosing off vs full 2056, to estimate the CO2 contribution alone.
- Engineering iteration 2 (clover living mulch, drip stakes).
Engineering track
Problem statement. "The 2056 climate stresses plants through heat, a cloudburst that drains away, and a 10-day drought. Using only low-cost, low-maintenance interventions a Bucharest gardener could copy, make radish plants in the 2056 tank produce at least 80 % of the 2026 radish dry mass, using no extra water."
Requirements.
- Water budget unchanged: 200 mL/pot per 14 days.
- No extra electricity per pot.
- Cost ≤ 2 RON per pot.
- Materials non-toxic and available from Dedeman/garden shops.
- Must not change light at canopy by > 10 % (shade cloth tested separately).
- Measurable effect on at least one of: pot moisture at end of drought, drainage fraction, dry mass, stress days.
Candidate solutions (students pick and justify).
| Intervention | Mechanism | Run 1 (Nov–Jan) | Spring |
|---|---|---|---|
| Mulch: 1 cm coco chips or chopped straw | lower soil evaporation, cooler surface | 2 pots per tank | iterate thickness 0.5 / 1 / 2 cm |
| Hydrogel (potassium polyacrylate), 2 g dry per L of mix | stores cloudburst water, releases it in drought | 2 pots per tank | dose 1 / 2 / 4 g/L |
| Living mulch: white clover Trifolium repens sown around radish | shading of soil, competition trade-off | – | 2–3 pots |
| Drip stake per pot vs rain bar | slower delivery, less runoff in the cloudburst | – | swap delivery on one row (5 pots) |
| Shade cloth 30 % over the drought row | lower leaf temperature and VPD | – | only with lux logged; competes with light control |
| Drought-tolerant variety or species (e.g. wheat vs radish, or a "drought" radish cultivar) | biology instead of engineering | compare species in science pots | if a cultivar is found |
Test criteria.
- Primary: radish hypocotyl dry mass in 2056 intervention pots vs 2056 controls and vs 2026 controls (target ≥ 80 % of 2026).
- Secondary:
- SOIL % at end of drought (day 13), from the probe in the hydrogel pot (SOIL B) vs control (SOIL A).
- Mass loss g/day.
- Drainage fraction of the cloudburst.
- Stress days.
- Cost per pot.
- Fail criterion: intervention pots score worse than controls on 2 of 4 metrics → reject or redesign.
Iteration plan.
- Nov: build the baseline (mulch, hydrogel), log, harvest radish Jan 11.
- Jan: design review. Each team presents its data, rejects one intervention and refines one (dose or thickness).
- Feb–Mar: iteration 2 in the crossover run with 3 levels of the kept intervention.
- Apr–May: iteration 3 combines the best intervention with drip stakes or living mulch.
- June: final "resilience recipe" card for the Time Capsule team.
Enclosure & build
Tanks.
- 2 × TANK45 (50 × 30 × 30 cm, ≈ 45 L), same shop and same order.
- Check glass thickness and silicone seams are identical. Label them "A" and "B" with a permanent marker on the bottom corner; the treatment is software.
- Each tank stands on a full-size 20 mm XPS board (50 × 30 cm). The glass bottom is fully supported, which matters because a point-loaded glass bottom can crack.
Lids (identical on both; students design and cut).
- 3 mm ACRYLIC, 50 × 30 cm, resting on the rim on a self-adhesive EPDM foam gasket. Two lids use 60 cm of a 50 × 100 sheet; the remaining 50 × 40 cm is for flaps, slider, sensor mast and jigs.
- Exhaust port at one end:
- 75 mm hole with an 80 mm FAN screwed on top of the lid, blowing out.
- An acrylic flap over the fan outlet, hinged and driven by SERVO 2 (GPIO 27) mounted on top of the lid (dry side).
- Flap closed = semi-sealed; flap open + fan = "breath".
- Intake slot at the other end: 2 × 15 cm, covered with MESH, plus a manual acrylic slider set to a 5 mm gap on both tanks. Check with feeler gauge or printed gauge strip.
- Glands:
- PG9 for the sensor cable bundle.
- PG9 for the rain-bar supply tube.
- PG7 for the CO2 tube. On mc-04 it is plugged with a short tube stub and cap.
- LEDs:
- 3 LEDPROFILE pieces, each 46 cm, glued and screwed to the lid underside, 8 cm apart. Each holds a 46 cm cut of LEDSTRIP.
- 3 cuts per tank ≈ 1.38 m, ≈ 20 W at 14.4 W/m.
- Same reel and same cut lengths in both tanks. The profiles also stiffen the lid against sag.
- Lid lifts off. The cables run in a loop long enough (≥ 40 cm) to set the lid on the bench without unplugging.
Inside layout (bottom → top).
- Tank floor = drainage sump; drainage is siphoned out by syringe.
- Four 10 mm rigid PVC rails across the floor, siliconed, so pots stand 1.2 cm above the water.
- 15 square pots, 9.5 cm, in a 5 × 3 grid.
- Sensor mast: an acrylic strip siliconed to the back glass, centre, carrying:
- BH1750 facing up at 14 cm above floor (canopy height);
- SCD41 at 16 cm and SHT31 at 18 cm, each inside a white PP radiation shield (a small cup with holes, not in direct LED light).
- Rain bars: 3 rigid PVC tubes (8–10 mm, one per row of 5 pots), end-capped, with 2 × 1.2 mm holes above each pot. They are fed by a cross/tee from the 6 mm supply and clipped 4 cm above the pot rims.
- CO2 outlet: tube end at canopy height, back centre, opposite the exhaust fan.
Heat pad (both tanks; only treatment-active on 2056).
- HEATPAD 12 V 20 W silicone, ≈ 25 × 15 cm, bonded to a 0.5 mm aluminium spreader sheet (30 × 20 cm).
- The pad sits in a 3 mm pocket cut into the XPS board, so the glass rests evenly on XPS + aluminium. The pad never carries the tank weight on its own.
- Why the spreader instead of bare glass contact: direct contact is fine at ≤ 45 °C. A bare pad makes a hot rectangle under 2–4 pots, which cooks their roots and adds a position bias. The spreader halves that peak.
- The XPS underneath forces heat up into the tank instead of into the shelf.
- Hardware thermal fuse: KSD301 45 °C normally-closed snap-disc in series with the pad, clamped to the spreader.
- Software probe: a second DS18B20 taped to the spreader (stops heating at 42 °C).
- Heat estimate: glass + lid ≈ 0.5 m² × ~5 W/m²K ≈ 2.5 W/K, so +3.5 K needs ≈ 9 W. The pad at 60 % max duty supplies 12 W.
- If ΔT cannot be reached: add identical bubble-wrap to the back and sides of both tanks.
- mc-04 uses its pad only as a 19 °C night floor.
Water.
- One RESERVOIR (10 L) per tank on the floor shelf below the tank. This means no siphoning when the pump stops.
- A PUMP (12 V) sits in the reservoir, with a non-return valve to keep the line primed, then 6 mm TUBING to the rain-bar cross.
- FLOAT low sits in the reservoir (pump inhibit).
- FLOAT "floor flood" lies on its side in a tank corner and trips at 2 cm water on the tank floor (pump inhibit).
- Same hardware on both tanks; only the schedules differ.
Mister (mc-05 only, Run 1 disabled).
- MIST module in a small water cup on the tank floor corner, powered from its own 24 V adapter via RELAY 1 (GPIO 23).
- It can be moved to mc-04 in the crossover; mc-04 has an unused relay ready.
CO2 generator (mc-05; moves with the 2056 treatment).
- 1.5 L PET bottle (never glass) in a spill tray on the floor next to the tank.
- Cap drilled to 6 mm, with tube push-fitted and not glued. If pressure ever builds, the tube pops out.
- About 5 cm from the cap a tee:
- Branch 1 goes into an open water bubbler: a jam jar with the tube end 2 cm under water, so maximum back-pressure ≈ 2 mbar. When the valve is closed, the gas vents here. Bubbles per minute = production rate, which also shows whether the generator is alive.
- Branch 2 runs through the servo pinch valve: SERVO 1 (GPIO 26) presses soft silicone tube against an acrylic block, a student-designed part. From there it goes through the PG7 gland to the canopy outlet.
- Optional: a second jar on branch 2 that the gas bubbles through, to scrub ethanol vapour.
- Room impact: ≈ 4 L CO2/day into a ≈ 200 m³ room adds ≈ 2 ppm, negligible.
Node boxes.
- One BOX per tank, wall- or shelf-mounted above the tank rim level and beside it, never above the water.
- Contents: ESP32 on TERMBOARD, BUCK 12 → 5 V (ESP32 VIN + servos, 470 µF across servo 5 V), 4 × MOSFET, RELAY, OLED behind a window or on the lid.
- Cables enter through ≈ 8 GLAND each, with drip loops.
- PSU12 brick and the mister's 24 V adapter sit on the shelf on the RCD-protected strip.
flowchart TD
PSU["PSU12 12 V 5 A brick on shelf, RCD strip"] --> NODE["Node box BOX, ESP32 + TERMBOARD + BUCK + 4 MOSFET + RELAY + OLED"]
NODE -->|"PWM1 GPIO16"| LED["3 x LEDSTRIP in LEDPROFILE under lid"]
NODE -->|"PWM2 GPIO17"| FAN["FAN 80 mm exhaust on lid"]
NODE -->|"Servo2 GPIO27"| FLAP["Vent flap over fan"]
NODE -->|"PWM3 GPIO18"| PUMP["PUMP 12 V in RESERVOIR 10 L, below tank"]
PUMP --> NRV["Non-return valve"] --> BARS["3 rain bars over 5 x 3 pots"]
NODE -->|"PWM4 GPIO19"| FUSE["KSD301 45 C fuse"] --> PAD["HEATPAD 20 W on alu spreader in XPS pocket"]
NODE -->|"Servo1 GPIO26"| PINCH["Pinch valve on CO2 line"]
YEAST["PET yeast-sugar bottle, loose push-fit tube"] --> TEE["Tee"]
TEE --> BUB["Open bubbler jar, 2 cm water relief"]
TEE --> PINCH --> OUT["CO2 outlet at canopy height"]
NODE -->|"Relay1 GPIO23"| MIST["MIST 24 V, mc-05 only, own adapter"]
MAST["Sensor mast: SHT31 + SCD41 + BH1750 on I2C 21/22"] --> NODE
PROBES["DS18B20 substrate + pad on GPIO4, SOIL A/B on GPIO32/33"] --> NODE
FLOATS["FLOAT reservoir-low GPIO13, floor-flood GPIO14"] --> NODE
NODE -.->|"Wi-Fi MICROCOSM"| HA["Home Assistant on PI5"]
flowchart LR
LOT["One seed lot + one substrate batch, pots filled to equal mass"] --> A["Tank A mc-04"]
LOT --> B["Tank B mc-05"]
A --> R1A["Run 1 Nov-Jan, 2026 climate"]
B --> R1B["Run 1 Nov-Jan, 2056 climate"]
R1A --> R2A["Run 2 Feb-Mar, 2056 climate"]
R1B --> R2B["Run 2 Feb-Mar, 2026 climate"]
R1A --> CMP["Paired comparison by pot position"]
R1B --> CMP
R2A --> X["Crossover analysis: climate effect vs tank effect"]
R2B --> X
CMP --> X
Build steps (team of 4, teacher supervises tools).
| # | Step | Time |
|---|---|---|
| 1 | Unpack and inspect tanks, label A/B, water-test 24 h on the bench for leaks | 0.5 h + 24 h |
| 2 | Draw lid layout on paper at 1:1 (ports, glands, profiles) and get it reviewed | 1.5 h |
| 3 | Cut 2 lids + flaps + slider + mast + sowing jig from ACRYLIC (score-and-snap; holes with step drill, teacher) | 3 h |
| 4 | Fit gasket, fans, glands, mesh, slider, servo + flap, LED profiles. Solder or connect the LED strip leads with pre-crimped JST. | 3 h |
| 5 | Cut XPS pockets, bond heat pad to spreader, fit KSD301, tape the pad DS18B20 | 1.5 h |
| 6 | Glue PVC rails + sensor mast inside the tanks with SILICONE, cure 24 h | 1 h + 24 h |
| 7 | Build rain bars (drill holes, end caps, tees), plumb reservoir → pump → valve → bars | 2 h |
| 8 | Wire both node boxes identically from one wiring sheet, glands + labels | 4 h |
| 9 | Flash ESPHome (shared future_common.yaml + 2 substitution files), check entities in HA |
2 h |
| 10 | Calibrations (sensors, pump mL/s, rain-bar cup test, lux matching) | 3 h |
| 11 | Build the CO2 generator, bubbler and pinch valve; test valve closure by bubble-count (bubbles divert to bubbler when closed) | 1.5 h |
| 12 | Commissioning: uniformity run + CO2 decay test + 2056 controller trial | 5 days, 1 h/day |
Biology
Species (same in both tanks, all C3, non-toxic, fast).
| Species | Role | Pots per tank | Seeds per pot → thinned to | Depth | Harvest |
|---|---|---|---|---|---|
| Raphanus sativus radish 'Roșu de Saxa' / 'Saxa 2' | dicot, storage root, drought-sensitive | 3 science + 6 engineering | 10 → 2 at day 7 | 1 cm | day 31 (science), day 56 (engineering) |
| Lepidium sativum garden cress (creson) | very fast germination/biomass bioassay | 3 | 30 (no thinning) | surface + 2 mm sieved mix | day 10, re-sown ×3 |
| Triticum aestivum wheat (grâu pentru germinat, untreated) | monocot, cool-season comparison | 3 | 10 → 5 at day 7 | 2 cm | clip at 3 cm on day 21 (regrowth measured to day 31) |
| Trifolium repens white clover | ground cover / living mulch (engineering, spring) | – | – | surface | – |
Seeds.
- Agrosel / Prosem / Florian packets from Dedeman, Hornbach or garden centres.
- Buy all packets of one species with the same lot number (check the printed lot), and enough for Run 2 and Run 3. Store them dry in a jar in the fridge door.
- Wheat: one 1 kg bag of food-grade germination wheat; do a germination pre-test of 50 seeds on wet paper (should be ≥ 85 %).
Substrate recipe (one batch for both tanks plus refills, ≈ 35 L).
- Mix by volume: 60 % universal peat-based potting soil (pământ universal), 25 % perlite, 15 % washed sand 0–2 mm.
- Mix on a tarp with gloves. Sieve the soil through 1 cm mesh to remove lumps.
- Pre-moisten to "crumbly, no drip" (≈ 50 % WHC) and keep it in a closed bag for 24 h.
- Hydrogel pots: mix 2 g dry hydrogel per litre of mix (≈ 1.2 g per pot) before filling.
- Mulch pots: add 1 cm coco chips after emergence (day 7) so emergence counts stay comparable.
Planting protocol (identical starting conditions).
- Fill each pot to the same moist mass (e.g. 420 g ± 5 g on the kitchen scale), tap 3× on the bench, label the pot ID (A01–A15, B01–B15) on its side.
- Place pots in both tanks according to the one random layout map.
- Size-sort radish seeds by sieve (keep 2.5–3.5 mm). Count seeds into labelled paper envelopes the day before.
- Sow with the acrylic dibber jig (10 pins at fixed depth). Use the same jig and the same person for both tanks, alternating A01, B01, A02, B02… so time of sowing is balanced.
- Water every pot with 30 mL by syringe right after sowing. Close lids. Start the treatments at the same minute on both nodes (HA script
future_start_run). - Day 7: thin (radish to 2, wheat to 5) by cutting at the soil surface. Bag the thinned seedlings for fresh/dry mass, which is the first biomass sample.
- Cress re-sowing: into fresh pots prepared at the same time from the same substrate bag, same mass.
Instrumentation
Per tank (identical on mc-04 and mc-05).
| Catalog ID | Qty per tank | Placement | Interval | Purpose |
|---|---|---|---|---|
| SHT31 | 1 | mast, 18 cm, in radiation shield | 60 s | air T (control variable for the heater loop) and RH |
| SCD41 | 1 | mast, 16 cm, in radiation shield, ASC off | 60 s (periodic mode 5 s, averaged) | CO2 (2056 dosing loop; 2026 room tracking); T/RH cross-check |
| DS18B20 | 2 | (a) substrate 5 cm deep in radish control pot (moves with pot); (b) taped to heat-pad spreader | 60 s | substrate T (cap 30 °C); pad safety (42 °C) |
| SOIL | 2 | A: radish control pot; B: radish hydrogel pot; inserted to the line, top sealed | 60 s, mean of 10 | moisture curves, drought timing, engineering comparison |
| BH1750 | 1 | mast top, facing up, canopy height 14 cm | 60 s | light equality between tanks, photoperiod check |
| FLOAT | 2 | reservoir low; tank floor flood (2 cm) | event | pump inhibits |
| OLED | 1 | node box | 2 s refresh | live T, ΔT, CO2, SOIL, Wi-Fi |
Pin assignment (standard pin map; same on both nodes).
| Function | GPIO | Device / entity |
|---|---|---|
| I2C SDA/SCL | 21 / 22 | SHT31 0x44 (mc_0X_air_temp, _air_rh), SCD41 0x62 (mc_0X_co2), BH1750 0x23 (mc_0X_lux), OLED 0x3C. Bus 50 kHz, cable to mast ≤ 1 m |
| 1-Wire | 4 | DS18B20 mc_0X_substrate_temp, mc_0X_pad_temp (by address) |
| Analog A / B | 32 / 33 | SOIL mc_0X_soil_moisture_a (control), _b (hydrogel) |
| PWM 1 | 16 | MOSFET → LED strips |
| PWM 2 | 17 | MOSFET → FAN |
| PWM 3 | 18 | MOSFET → PUMP |
| PWM 4 | 19 | MOSFET → KSD301 → HEATPAD (max_power: 0.6) |
| Relay 1 | 23 | RELAY → MIST 24 V (mc-05; unused on mc-04) |
| Servo 1 / 2 | 26 / 27 | CO2 pinch valve / vent flap |
| Digital in 1 / 2 | 13 / 14 | FLOAT reservoir low / FLOAT floor flood |
| Unused | 34, 35, 36, 39, 5, 15, 12, 25 | spare (add SOIL C/D on 34/35 in spring if needed) |
YAML difference between nodes (only substitutions):
# mc-05-future2056.yaml # mc-04-future2026.yaml uses:
substitutions:
node: mc-05-future2056 # mc-04-future2026
heat_offset: "3.5" # "0.0"
t_floor: "22.5" # "19.0"
co2_dose_below: "700" # "0" (dosing disabled)
co2_stop_above: "780" # "0"
co2_extra_breath_below: "0" # "430"
rain_calendar: calendar.future_2056_rain # calendar.future_2026_rain
pump_ml_per_s: "14.2" # each tank's own calibration
packages:
common: !include future_common.yaml
Calibration.
- SHT31 + SCD41 T/RH: both masts side by side in one closed box for 24 h. Record offsets and apply them as
offset:filters. The ΔT target needs the two SHT31s to agree within 0.2 °C. - SCD41 CO2: disable ASC. Forced recalibration (FRC) to 425 ppm with both sensors outdoors (shaded, 10 min, same time), via an HA button calling
scd4x.perform_forced_calibration. Repeat monthly and log it. Cross-check: both in one sealed box should agree within 30 ppm. - DS18B20: ice-water bath (0 °C) and room water, all 4 probes together. Offsets ≤ 0.2 °C.
- SOIL: per probe, in the actual mix: air reading, then air-dry mix (= 0 %), then saturated mix (= 100 %), using
calibrate_linear. Verify against gravimetric water content of 3 sample pots. - BH1750 + LEDs: set both strips at PWM 80 %, read lux at canopy at 5 positions per tank, then trim one tank's PWM until the means match within 5 %. Record the trims, then lock the trims as fixed substitutions.
- Pump: run 30 s into a measuring jug (through the rain bars) 3× per tank and use the mean mL/s. Cup test: 15 cups in pot positions, one event; the coefficient of variation should be < 15 %. If it is higher, rework the hole sizes.
- Tank equivalence (commissioning):
- Uniformity run: both in 2026 mode with pots filled, no seeds, 72 h. Pass if mean T within 0.5 °C, RH within 5 points, CO2 within 50 ppm, lux within 5 %.
- CO2 decay test: dose both tanks to ≈ 1 500 ppm, close flaps, fit exp decay. Air-change rates must agree within 25 %. If not, adjust the slider or gasket.
Automation
Split of responsibilities.
- Safety loops and closed-loop control (heater, CO2 dosing, breaths, pump time limits, inhibits) run on the ESP32, so they work without Wi-Fi.
- The rain calendar, the T_2026 → mc-05 link, alerts and logging run in Home Assistant.
stateDiagram-v2
state Heater2056 {
[*] --> H_IDLE
H_IDLE --> H_ON : T_air below target minus 0.3 C
H_ON --> H_IDLE : T_air above target plus 0.3 C
H_ON --> H_FAULT : NaN or pad above 42 C or air above 31 C or substrate above 30 C
H_IDLE --> H_FAULT : any temperature sensor NaN
H_FAULT --> H_IDLE : sensors valid 10 min and teacher reset in HA
H_ON : duty up to 60 pct, target is T_2026 plus 3.5, clamp 22.5 to 30.5
H_FAULT : pad OFF, alert teacher
}
state Rain2056 {
[*] --> R_WAIT
R_WAIT --> R_PUMP : calendar event and reservoir OK and floor dry
R_PUMP --> R_WAIT : volume delivered or 240 s cap
R_PUMP --> R_LOCK : reservoir low or floor flood
R_WAIT --> R_LOCK : reservoir low or floor flood
R_LOCK --> R_WAIT : refilled and acknowledged
R_WAIT : cloudburst Mon 150 mL per pot, shower Fri 50, then 10-day drought
}
state Air2056 {
[*] --> A_SEALED
A_SEALED --> A_BREATH : every 30 min or RH above 92 for 30 min
A_BREATH --> A_DOSE : 60 s elapsed and lights on and CO2 below 700
A_BREATH --> A_SEALED : 60 s elapsed otherwise
A_SEALED --> A_DOSE : lights on and CO2 below 700
A_DOSE --> A_SEALED : CO2 above 780 or 120 s dose
A_SEALED --> A_PURGE : CO2 above 1500 or air above 32 C or SCD41 NaN
A_DOSE --> A_PURGE : CO2 above 1500 or SCD41 NaN
A_PURGE --> A_SEALED : CO2 below 1000 and air below 30 C and sensor valid
A_SEALED : flap closed, fan off, valve closed
A_BREATH : flap open, fan 60 pct, valve closed
A_DOSE : flap closed, pinch valve open
A_PURGE : flap open, fan 100 pct, valve closed, alert
}
stateDiagram-v2
state Air2026 {
[*] --> S_SEALED
S_SEALED --> S_BREATH : every 30 min, or CO2 below 430, or RH above 92 for 30 min
S_BREATH --> S_SEALED : 60 s elapsed
S_SEALED --> S_PURGE : air above 32 C or sensor NaN
S_PURGE --> S_SEALED : air below 30 C and sensors valid
}
state Rain2026 {
[*] --> W_WAIT
W_WAIT --> W_PUMP : Mon and Thu 10h00, reservoir OK, floor dry
W_PUMP --> W_WAIT : 750 mL delivered or 240 s cap
W_PUMP --> W_LOCK : reservoir low or floor flood
W_LOCK --> W_WAIT : refilled and acknowledged
}
state Floor2026 {
[*] --> F_OFF
F_OFF --> F_ON : T_air below 18.7 C
F_ON --> F_OFF : T_air above 19.3 C or pad above 42 C or NaN
}
Fail-safes (both nodes, implemented in ESPHome).
- Sensor NaN or stale > 3 min:
- Heater OFF.
- Pump OFF/inhibit.
- CO2 pinch valve CLOSED.
- Vent flap OPEN and fan 30 %. This fails toward fresh air and no CO2 build-up.
- LEDs keep their schedule.
- Heat pad:
max_power: 0.6on the output (duty ≤ 60 % = 12 W).- Software stops at pad 42 °C, air 31 °C (2056) or substrate 30 °C.
- Hardware KSD301 opens at 45 °C.
- If the pad has run at 60 % for > 2 h without reaching target, raise an alert (lid open? draught?).
- Pump:
- Max 240 s per event and max 3 L per day per tank, both enforced on the ESP.
- Reservoir-low float and floor-flood float inhibit the pump.
- Pump runs only when started by a calendar event or the teacher's manual button; there is no moisture-feedback watering.
- CO2:
- Dosing only with lights on.
- Dose pulse ≤ 120 s, then wait ≥ 5 min.
- Purge above 1 500 ppm.
- If CO2 stays < 600 ppm for 6 h of light with valve cycles, alert "generator exhausted".
- Link loss:
- If mc-05 loses the imported T_2026 for > 10 min → fixed target 24.5 °C.
- If HA is unreachable, rain events are skipped and logged; plants tolerate 2–3 days.
- An OLED banner shows "NO HUB".
- Power-up: all actuators boot OFF, flap OPEN, valve CLOSED (
restore_mode: ALWAYS_OFF).
Home Assistant automations (in words).
- Rain calendars. Two HA Local Calendars,
future_2026_rainandfuture_2056_rain, hold events titledRAIN 750/RAIN 2250(mL per tank). At event start, an automation callsesphome.mc_0X_rainwith the volume, and the ESP converts it to pump seconds. Students see and edit the calendar, which counts as a protocol change and needs teacher approval. The 2056 calendar is pre-filled with the 14-day cycle up to June. - Establishment week. Script
future_start_runsets both nodes to "establishment" (20 mL/pot/day = 300 mL per tank at 10h00) for 7 days, then switches both to their calendars automatically. - T link.
sensor.mc_04_air_tempis imported on mc-05 via the ESPHomehomeassistantsensor platform and filtered by a 10-min moving average. - Breath sync. Both nodes schedule breaths at :00 and :30 from SNTP time, so they are simultaneous.
- Alerts (mobile app/Telegram to teacher):
- reservoir low;
- floor flood;
- heater fault;
- |ΔT − 3.5| > 0.7 °C for 2 h;
- CO2 generator exhausted;
- any sensor unavailable > 15 min;
- node offline > 10 min.
- Fidelity dashboard (Grafana): ΔT, ΔCO2, lux ratio, SOIL A/B both tanks, rain events as annotations, plus a daily "fidelity score" sensor.
- Nightly CSV export (project-wide).
Operations
Daily (school days, 5 min, rotating pair).
- OLED on both nodes: values plausible, Wi-Fi OK, no fault banner.
- Stress score 0–3 for each of 30 pots, chlorosis Y/N → log sheet.
- Days 1–7 after sowing: emergence counts per pot.
- mc-05 bubbler: count bubbles in 1 min with the valve closed (should be ≥ 5 per minute).
- No condensation dripping onto electronics, no kinks in tubes, lids seated on gaskets.
Monday (30 min).
- Weigh all 30 pots (before 10h00), then measure height and leaf count.
- Siphon floor drainage from both tanks into a measuring cylinder and record mL per tank.
- Rotate pots one position along the serpentine map (both tanks identically) and update the map sheet.
- Top-down photos in the jig.
- Refresh the CO2 generator (recipe below).
- Check reservoir levels; refill both to the 10 L line with the same tap water, rested 24 h in an open jug to lose chlorine.
- 2056 cloudburst weeks: weigh again 30 min after the 10h00 event, then siphon drainage at 24 h (Tuesday).
Thursday (15 min). Weigh pots before 10h00 (2026 rain day); height and leaf count.
Monthly. SCD41 FRC outdoors (both sensors); lux equality check; SOIL probe visual check for corrosion; clean the fan dust and mesh.
Manual logs (one printed sheet per tank per week plus a shared Google Sheet with the same columns): date, time, student initials, pot ID, mass g, height mm, leaves, stress score, notes, rescue mL, drainage mL, bubbler count, refills, anomalies. Every intervention on a tank (lid opened > 5 min, spill, rescue) goes in the log, because it explains spikes in the data.
Reservoir refills. 2026 uses ≈ 1.5 L/week; 2056 averages the same. A 10 L reservoir lasts 5–6 weeks. Before the winter break (Dec 18), fill both to 10 L, which covers 3 weeks.
CO2 generator refresh.
- Recipe:
- 1.5 L PET bottle, 200 g white sugar, 1.2 L lukewarm water (≈ 30 °C).
- ½ teaspoon (≈ 2 g) dry baker's yeast (drojdie uscată).
- ¼ teaspoon baking soda as a pH buffer.
- Shake before inserting the tube.
- Starts producing within ≈ 1–2 h and gives ≈ 3–5 L CO2/day for 10–14 days at 20 °C. Theoretical yield: 200 g sucrose ≈ 2.3 mol CO2 ≈ 57 L.
- Cadence: replace every Monday. This avoids the late-fermentation slump and keeps the supply steady. Pour the old liquid (≈ 6–8 % ethanol) down the sink with plenty of water and rinse the bottle.
- Winter break (Dec 18 – Jan 7): a 2 L bottle with 300 g sugar and 1 g yeast lasts ≈ 3 weeks at lower output. Accept and log that the CO2 contrast may weaken in week 3.
- Consumption estimate: ≈ 30 yeast sachets and 7 kg sugar per school year.
Safety & risks
- Mains (HARD RULE 1–2):
- Only the PSU12 bricks, the mister's 24 V adapter and the PI5/ROUTER PSUs are 230 V. All are certified COTS with their own cords.
- They sit on a shelf above and away from both tanks, on the 30 mA RCD strip, with drip loops.
- Nothing 230 V is inside the tanks, the substrate or the reservoirs.
- All loads in or on the tanks are 12 V DC (LED, fan, pump, heat pad, servos 5 V); the mister is 24 V SELV from its own adapter via a relay. Students do not open adapters.
- Heat pad:
- 12 V silicone only, never a 230 V reptile mat.
- KSD301 45 °C hardware cut-off in series; software cut at 42 °C pad, 31 °C air, 30 °C substrate; duty capped at 60 %.
- Surface must never exceed 45 °C. Test this with the pad DS18B20 during commissioning at 100 % for 20 min with the fuse in place.
- Pad on an aluminium spreader in an XPS pocket. Nothing flammable on top, and the tank is fully supported.
- Yeast CO2:
- PET only, never glass. Cap never glued; push-fit tube.
- Open bubbler relief at the bottle (≤ 2 mbar). Never put a closed valve between the bottle and the bubbler tee.
- Never tighten a cap onto a fermenting bottle without a tube.
- Spill tray under the bottle.
- Fermentation liquid is not for drinking: label the bottle "NOT A DRINK – CO2 GENERATOR".
- Water + electronics (HARD RULE 4):
- Node box above the rim and beside the tank, glands facing down, drip loops on all cables.
- The reservoir sits below the tank, so overflow cannot run toward electronics.
- The floor-flood float stops the pump.
- Wipe up spills immediately; no pump testing with the box open.
- Glass:
- Lift tanks by two people, empty only.
- Full-size XPS board under each tank.
- No tools resting on the glass; tank edges are rimless, so put silicone edge guards on the top corners.
- Report chips at once.
- Acrylic cutting/drilling: the teacher operates the step drill; students wear goggles; clamp the sheet; deburr edges.
- Biology (HARD RULE 5):
- Gloves and a dust mask for dry potting mix and perlite; wash hands.
- All species are edible crops or clover. Do not eat experimental plants (handled with lab tools).
- Hydrogel: gloves; dispose of it in general waste, not the drain.
- Data risk: a mis-specified drought could kill everything. Mitigations are the daily stress score and the teacher rescue rule. The engineering pots act as a buffer.
Educational outcomes & assessment
| Outcome | Evidence | Assessment |
|---|---|---|
| Formulate hypotheses with variables and controls | Written H1–H4 with IV/DV/controls, before sowing | Rubric 0–3: directional, measurable, justified |
| Understand controlled experiments and their limits | Explanation of pseudo-replication, confounded package, CO2 room limit, crossover | Short oral defence (5 min/team) |
| Measure carefully and reproducibly | Log sheets, calibration records, inter-observer check (2 students score the same 5 pots) | Completeness % plus agreement within 1 stress point |
| Analyse data | Growth curves, T50, paired differences, fidelity metric, from InfluxDB/CSV in a spreadsheet | Graph quality checklist (axes, units, n, error bars or points) |
| Engineering design | Requirements, intervention choice, test results, iteration log, cost per pot | Design-review presentation in January plus final recipe card |
| Systems/automation literacy | Explain the 2056 state diagram, change one calendar event, read alerts | Practical: trace an alert to its cause |
| Climate literacy | Link setpoints to Bucharest normals and IPCC projections, and explain why they are amplified | Poster section "What 2056 really means for Bucharest" |
Sub-BOM
Cost-cut 2026-10-20: the 0.01 g pocket scale is shared with team 1; tanks are the 45 L MARINA size. (pair: mc-04 + mc-05)
Price basis: RON incl. VAT, Romanian web shops Oct 2026 (optimusdigital.ro, robofun.ro, ardushop.ro, emag.ro, dedeman.ro). AliExpress fallback noted where much cheaper.
| ID / item | Qty | Unit RON | Line RON | Basis / note |
|---|---|---|---|---|
| ESP32 | 2 | 40 | 80 | optimusdigital; 1 per node |
| TERMBOARD | 2 | 35 | 70 | emag/AliExpress |
| OLED | 2 | 20 | 40 | optimusdigital |
| SHT31 | 2 | 55 | 110 | cased probe with cable, robofun/AliExpress |
| SCD41 | 2 | 240 | 480 | robofun/ardushop; AliExpress ≈ 130 |
| DS18B20 | 4 | 12 | 48 | 2 per tank (substrate + pad); +2 vs draft allocation |
| SOIL | 4 | 12 | 48 | v2.0 with TL555, sealed |
| BH1750 | 2 | 12 | 24 | optimusdigital |
| FLOAT | 4 | 10 | 40 | reservoir low + floor flood per tank |
| FAN | 2 | 25 | 50 | 80 mm 12 V |
| PUMP | 2 | 25 | 50 | 12 V 3–5 W; uses the 2 approved submersible pumps |
| HEATPAD | 2 | 45 | 90 | 12 V 20 W silicone; both tanks (crossover) |
| MIST | 1 | 60 | 60 | with 24 V adapter; mc-05 |
| LEDSTRIP | 1 | 110 | 110 | one 5 m reel for both; 2.76 m used, rest spare |
| LEDPROFILE | 3 | 25 | 75 | each 1 m cut 2 × 46 cm |
| SERVO | 4 | 12 | 48 | pinch valve + flap per tank; uses all 4 approved |
| MOSFET | 8 | 8 | 64 | 4 per node (light, fan, pump, heat) |
| RELAY | 2 | 8 | 16 | mister; second ready for crossover |
| PSU12 | 2 | 55 | 110 | 12 V 5 A per node (peak load ≈ 47 W) |
| BUCK | 2 | 10 | 20 | 12 → 5 V, ESP32 + servos |
| BOX | 2 | 35 | 70 | IP65 150 × 110 × 70 |
| GLAND | 22 | 2 | 44 | 8 per box + 3 per lid |
| TANK45 | 2 | 220 | 440 | 50 × 30 × 30 rimless; same order |
| ACRYLIC | 1 | 120 | 120 | 3 mm 50 × 100: 2 lids + parts |
| MESH | 0.25 m² | 40 | 10 | intake slots |
| SILICONE | 1 | 30 | 30 | rails, mast |
| TUBING | 8 m | 5 | 40 | pump lines, CO2 lines (soft silicone at pinch) |
| RESERVOIR | 2 | 35 | 70 | 10 L food-grade with lid |
| MISC: KSD301 45 °C NC thermal cut-off | 2 | 5 | 10 | AliExpress/emag |
| MISC: aluminium sheet 0.5 mm 30 × 20 cm | 2 | 15 | 30 | dedeman |
| MISC: XPS board 20 mm | 1 | 35 | 35 | dedeman, cut to 2 × 50 × 30 |
| MISC: EPDM foam gasket tape | 2 | 15 | 30 | dedeman |
| MISC: rigid PVC tube 8–10 mm (rain bars, rails) | 3 m | 5 | 15 | dedeman; from approved "rigid tubes" lot |
| MISC: tees, crosses, end caps, 2 non-return valves | 1 lot | 35 | 35 | approved "nozzles/valves" lots |
| MISC: radiation shields (PP cups), labels | 1 lot | 10 | 10 | – |
| BIO: square pots 9.5 cm | 60 | 1 | 60 | 30 in use + cress re-sowing + Run 2 |
| BIO: universal potting soil 50 L | 2 | 30 | 60 | one batch through Run 3 |
| BIO: perlite 10 L | 1 | 20 | 20 | – |
| BIO: washed sand 0–2 mm 5 kg | 1 | 10 | 10 | – |
| BIO: hydrogel (K-polyacrylate) 250 g | 1 | 30 | 30 | emag |
| BIO: coco chips 5 L | 1 | 20 | 20 | mulch |
| BIO: Raphanus sativus 'Saxa' seeds, same lot | 3 | 5 | 15 | Agrosel/Prosem |
| BIO: Lepidium sativum seeds, same lot | 3 | 5 | 15 | – |
| BIO: Triticum aestivum germination wheat 1 kg | 1 | 15 | 15 | – |
| BIO: Trifolium repens seeds | 1 | 10 | 10 | spring |
| BIO: dry yeast 11 g sachets | 10 | 2 | 20 | through Feb; restock later |
| BIO: white sugar | 5 kg | 5 | 25 | – |
| TOOL: kitchen scale 5 kg / 1 g | 1 | 50 | 50 | pot weighing |
| TOOL: digital caliper | 1 | 40 | 40 | hypocotyl diameter |
| BIO: paper bags + permanent labels | 1 lot | 35 | 35 | harvest |
| Subtotal | 3 047 RON (≈ 597 EUR) | hardware IDs 2 457 + misc/bio/tools 590 |
Changes vs the approved list:
- Uses 2 of the 4 approved SCD41 (raised from 3).
- Uses both approved submersible pumps, all 4 servos and 1 of 2 misters.
- Needs 8 MOSFETs (approved 6 for the whole project) and 2 of the 4 "power supplies".
- Uses 2 of 4 reservoirs, 8 of 20 m tubing and 22 of 20 cable glands (buy a 50-pack).
- Shares the hub (PI5, ROUTER) with the project; not counted here.
8-week timeline (Oct 26 – Dec 18, 2026)
gantt
title Future 2026 vs 2056 - build and Run 1
dateFormat YYYY-MM-DD
axisFormat %d %b
section Plan and order
Hypotheses, lid design, order parts and seeds :p1, 2026-10-26, 5d
Substrate mix, seed pre-test :p2, 2026-10-29, 4d
section Build
Tank leak test, lids, flaps, LED profiles :b1, 2026-11-02, 5d
Heat pad assembly, rails, mast, rain bars :b2, 2026-11-03, 4d
Node boxes wiring, ESPHome flashing :b3, 2026-11-02, 6d
CO2 generator and pinch valve :b4, 2026-11-06, 2d
section Commission
Calibrations sensors pump lux :c1, 2026-11-09, 2d
Uniformity run both in 2026 mode :c2, 2026-11-10, 3d
CO2 decay test and 2056 controller trial :c3, 2026-11-12, 4d
section Run 1
Sow all pots, treatments start :milestone, m1, 2026-11-16, 0d
Establishment week, germination counts :r1, 2026-11-16, 7d
Rain regimes start, 2056 cloudburst 1 :milestone, m2, 2026-11-23, 0d
Drought cycle 1 :r2, 2026-11-27, 10d
Cloudburst 2 and drought cycle 2 :r3, 2026-12-07, 14d
Cress cycles 1-3 :r4, 2026-11-16, 31d
Wheat clip day 21 :milestone, m3, 2026-12-07, 0d
Radish science harvest day 31 :milestone, m4, 2026-12-17, 0d
section Report
Mid-term data analysis and poster :a1, 2026-12-10, 7d
Winter-break prep, refill, 2 L CO2 bottle :a2, 2026-12-18, 1d
Notes:
- Nov 30 and Dec 1 are public holidays. Automation runs on its own; log readings on Dec 2.
- The engineering radish pots run through the break; harvest is on Jan 11, 2027.
- Run 2 (crossover) starts Feb 1, 2027; Run 3 (decomposition) Apr 12, 2027.
6. Forests in Space
Node: mc-06-regolith · Enclosure: TANK63 (60×30×35 cm) used as a pot "greenhouse" · Team: 3–4 students · Round 1 (cress) runs Nov 16 – Dec 7, 2026. Round 2 (peas/wheat) runs Jan–Mar 2027.
Concept (refined)
Students make a classroom regolith analogue (a mineral powder with no organic matter or nitrogen, alkaline and poor at holding water). They test whether plants can establish in it and which Earth-supplied amendment, at the smallest import mass, makes it a working growing medium. The experiment is 15 individually potted replicates in one lit, humidity-controlled glass tank, with gravimetric (by-weight) watering and destructive harvest. The node logs only the environment the pots share, plus the moisture/temperature of three marker pots. The plant data is collected by hand, and that is deliberate.
Real context (for the students' introduction, 1 page):
- Paul, Elardo & Ferl (Univ. of Florida), Communications Biology 2022: Arabidopsis thaliana grown in ~0.9 g each of real Apollo 11, 12 and 17 regolith. Every seed germinated. Then plants grew slowly and were stunted, some with purple pigment, and they over-expressed salt-, metal- and oxidative-stress genes. Plants did worse in more "mature" regolith (longer exposure at the surface, Apollo 11) than in less-exposed samples. JSC-1A simulant was the control. Lesson: germination ≠ establishment. The problem is the chemistry and structure of the substrate, not the seed.
- Wamelink et al. (Wageningen UR), PLoS ONE 2014 and follow-ups 2016–2019: 14 species in JSC-1A (Moon) and JSC Mars-1A simulants vs. Rhine river soil. Mars simulant did surprisingly well. Moon simulant was poorest (poor water retention, high pH). Later trials added organic matter (cut grass/manure) and harvested tomato, radish, rye, pea, rocket and others, and tested the crops for heavy metals. Lesson: organic amendment + biology is the decisive engineering lever.
Why we do not buy certified simulant: LHS-1 (Space Resource Technologies, US) lists at $45/kg (≈ 210 RON/kg) plus US→RO shipping and customs, with lead times of several weeks. EAC-1A (ESA/EAC, Cologne) goes to ESA-supported research only and is not sold to schools. JSC-1A is discontinued in its original form. The ~15 kg this ecosystem needs would cost > 3 000 RON and might not arrive before December. Optional stretch: buy 1 kg LHS-1 (≈ 650 RON delivered) as a reference standard in Round 2 to benchmark our analogue against a real simulant (3 extra pots). It is not in the subtotal.
Classroom regolith analogue "MR-1" (Mare-type Regolith, recipe 1), by dry mass:
| Component | Mass % | Role / lunar counterpart | Source (Romania first) |
|---|---|---|---|
| Basalt rock dust (Gesteinsmehl/Urgesteinsmehl, garden remineraliser, mostly < 0.2 mm) | 65 | Mare basalt: pyroxene, plagioclase, Fe-Ti oxides | eMAG marketplace / Amazon.de (Oscorna, Steinkraft "Bodenkraft" 5–7 kg bags). Alternative: basalt quarry fines 0–4 mm (Racoș basalt, Brașov county, via aggregate depots), sieved < 1 mm |
| Fine quartz sand 0.1–0.5 mm, washed, dry | 25 | Bulk mineral grains; lowers water retention | Dedeman / Hornbach "nisip cuarțos" (filter or decorative sand, 25 kg) |
| Potassium feldspar powder | 5 | Stand-in for plagioclase/anorthosite (highland component) | Ceramics/pottery suppliers (Bucharest), "feldspat" 1 kg. Optional: replace with more basalt if not found |
| Perlite, crushed and sieved < 1 mm | 5 (≈ 10 % by volume) | Stand-in for porous glass/agglutinates; low density | Dedeman / garden centres, 5 L bag |
Target grain size: 100 % < 1 mm and ≥ 50 % < 0.1 mm by mass (real lunar regolith: median ≈ 60–80 µm). Check by sieving 100 g through 1 mm and 0.5 mm kitchen sieves and weighing each fraction. Expected pH of the 1:5 water extract is 8–9 (fresh-crushed basalt is alkaline). Record the measured value. If the extract is < 7.5, add 1 % ground dolomitic lime and re-measure, and log this as a recipe change (MR-1b).
What MR-1 reproduces and what it does not
| Lunar regolith property | Why it matters to plants | MR-1 reproduces? |
|---|---|---|
| No organic matter, no microbes | No nutrient cycling, no aggregation, no water-holding humus | Yes (baking optional, to kill bag contaminants) |
| No nitrogen (no NO₃⁻/NH₄⁺) | N is the first limiting nutrient | Yes |
| Alkaline, pH ≈ 8–9 in extract | Locks up Fe, Mn, P, Zn | Mostly (basalt dust is alkaline; measure) |
| Poor water retention, fast drainage, crusting | Drought stress between waterings | Yes (quartz + rock flour) |
| Nutrients present but locked in minerals (P, K, Ca, Mg, Fe) | Plants starve despite "rich" chemistry | Yes (basalt is the same rock type) |
| Very fine, cohesive dust | Packing, compaction, root penetration, inhalation hazard | Partly (fine, but less fine than real dust) |
| Sharp, jagged, unweathered grains and impact glass (agglutinates) | Root abrasion, odd packing | Partly (crushed rock is angular. No agglutinates or glass, perlite is a weak stand-in) |
| Nanophase metallic iron, solar-wind implants, highly reduced chemistry | Probably the source of the 2022 stress-gene response | No |
| Highlands anorthosite composition | Different Ca/Al ratio | No (MR-1 is "mare-type". Feldspar is only a gesture) |
| Low gravity, radiation, vacuum | – | No (out of scope) |
Science track
Driving question: Can plants establish in a lunar-like mineral substrate, and which single Earth-supplied amendment gives the most plant growth per kg of imported material?
Treatments (codes used everywhere: labels, data sheets, entity ids):
| Code | Substrate (by volume) | Tests |
|---|---|---|
| R0 | 100 % MR-1 analogue | Baseline "raw regolith" |
| RC | 80 % MR-1 + 20 % mature compost (sieved < 5 mm) | Organic matter: water + nutrients + microbes together |
| RB | 90 % MR-1 + 10 % biochar + slow-release fertiliser 3 g/L (Osmocote-type, ~15-9-11) | Mineral nutrition + structure without organic matter decomposition |
| RM | 95 % MR-1 + 5 % live soil from ecosystem 8 (Living Earth) + mycorrhizal powder (label dose, under the seed) | Biology alone ("inoculate, don't fertilise") |
| P | 100 % commercial universal potting soil | Terrestrial control |
Hypotheses (Round 1, cress):
- H1 (germination): germination % at day 7 in R0 is within 15 percentage points of P, because germination runs on seed reserves (consistent with the Apollo result).
- H2 (establishment): day-21 shoot dry mass in R0 is < 30 % of P.
- H3 (amendment): RB and RC both reach ≥ 60 % of P dry mass. RB is highest in biomass (most available N). RC is highest in water retention.
- H4 (biology alone): RM is not significantly different from R0 for cress. Lepidium and Raphanus are Brassicaceae, which do not form mycorrhizae, so any RM gain comes from microbes/nutrients in the 5 % soil. Round 2 tests mycorrhiza properly with peas/wheat, which are mycorrhizal hosts.
- H5 (substrate physics): water-holding capacity (WHC) of R0 is < 50 % of P per gram, and its 1:5 extract pH is ≥ 1.5 units higher than P.
Variables
- Independent: substrate treatment (5 levels).
- Dependent: germination % (days 1–7), T50 (days to 50 % of final germination), seedling height (days 7, 14, 21), longest root length, shoot fresh and dry mass per pot, leaf colour score (1–5 chart: yellow → dark green), green canopy cover % from photos, substrate pH and EC (1:5 extract, before sowing and after harvest), WHC, water used per pot (g), substrate moisture/temperature curves (marker pots).
- Controlled: seed lot (one packet, viability-tested), 10 seeds per pot, sowing depth 2–3 mm, pot type (7 cm square), substrate volume (0.22 L, filled to 1 cm below rim), photoperiod 16/8 h, LED PWM level, watering rule (back to 70 % of each substrate's WHC), tank climate (shared), harvest day.
- Light-gradient control: randomised complete blocks. Each of the 3 rows is a block with all 5 treatments in a dice-randomised order. The tray is rotated 180° every Monday.
Design: 5 treatments × 3 replicate pots = 15 pots. The pot is the experimental unit (n = 3). The 10 seedlings in a pot are sub-samples and are averaged first. Plus 1 extra R0 pot and 1 extra P pot outside the grid ("sacrificial" pots for root checks at day 10. They are not part of the statistics).
Sampling and manual measurements
| Measurement | When | How | Tool |
|---|---|---|---|
| Germination count | Days 1–7, daily (school days) | Cotyledons visible = germinated | Eye, data sheet |
| Height | Days 7, 14, 21 | Soil surface to cotyledon/leaf tip, all seedlings | Steel ruler 0.5 mm |
| Leaf colour score | Days 14, 21 | 1–5 printed colour chart | Chart |
| Green cover % | Weekly photo | Top-down photo → Canopeo app (free) or Fiji colour threshold | Phone on fixed mount |
| Root length | Day 21 (harvest), day 10 sacrificial pots | Wash root ball over sieve, longest root of 5 seedlings | Ruler |
| Shoot fresh mass | Day 21 | Cut at soil level, weigh per pot immediately | Jewellery scale 0.001 g |
| Shoot dry mass | Day 23–24 | Paper envelope, 60 °C for 48 h (oven/dehydrator) → weigh | 0.001 g scale |
| Substrate pH / EC | Before sowing and after harvest | 10 g substrate + 50 mL distilled water, shake 1 min, stand 30 min, measure supernatant | PHPEN, TDSPEN (shared pool), CALSOL |
| WHC (drain-and-weigh) | Week 3, each substrate × 3 | See protocol below | Kitchen scale 1 g |
| Water used | Every watering | Mass before/after (g = mL) | Kitchen scale 1 g |
| Biological activity | Harvest | (a) catalase foam test, (b) CO₂ respiration (borrowed), (c) tea-bag index (long run) | See below |
Water-retention test (drain-and-weigh), per substrate, 3 replicates:
- Line a 7 cm pot (drain holes) with one layer of fine mesh. Weigh the empty pot (m_pot).
- Fill with dry substrate to 1 cm below the rim, tap 5× on the table, weigh (m_dry).
- Stand in a bowl of water up to 1 cm below the substrate surface for 60 min (saturation from below).
- Remove the pot, cover the top with cling film, let it drain on a rack for 120 min, weigh (m_fc).
- WHC (g water per g dry substrate) = (m_fc − m_dry) / (m_dry − m_pot). Volumetric WHC = (m_fc − m_dry) / 220 mL.
- Drying curve: leave uncovered in the running tank and weigh daily for 5 days → % of retained water lost per day.
- The 70 % watering target mass for each substrate = m_dry + 0.7 × (m_fc − m_dry).
Biological activity (no CO₂ sensor on this node):
- Catalase foam test (harvest day): 2 g substrate in a 15 mL graduated tube + 2 mL 3 % H₂O₂ (pharmacy). Read the foam height after 2 min. Mn/Fe oxides in basalt also decompose H₂O₂, so run a baked control of each substrate (120 °C for 1 h) and report live minus baked. Goggles and gloves.
- Respiration: at harvest, bring 100 g of each substrate (pooled per treatment) to ecosystem 8's SCD41 respiration chamber (one 1 h closed-jar run each) → ppm CO₂ per h per 100 g. Book it with team 8.
- Tea Bag Index (spring result): bury 1 green tea + 1 rooibos pyramid bag (pre-weighed) in one extra 9 cm pot of each treatment at sowing. Dig up after 90 days (mid-Feb), dry, weigh → decomposition rate.
Analysis (spreadsheet, template provided by the teacher):
- Per pot: mean of the 10 seedlings → per treatment: mean ± range of 3 pots. Bar charts with all 3 points shown.
- Express every treatment as % of P (relative performance). Rank the amendments by "biomass gain over R0 per 100 g of imported material".
- Germination curves (cumulative % vs day) and T50 per treatment.
- Liceu teams: one-way ANOVA (or Welch t-test R0 vs each) in Google Sheets/LibreOffice, α = 0.05, with a stated caveat that n = 3 detects only large effects. Gimnaziu teams: "is the difference bigger than the spread between replicates?"
- Overlay the marker-pot moisture curves (R0, RC, P) from Grafana with the watering log → drying rate per substrate.
What you can show by mid-December vs spring
- By Dec 11: germination curves, 21-day heights, fresh/dry biomass, root lengths, pH/EC before/after, WHC and drying curves, catalase/respiration snapshot, first ranking of amendments → decision matrix for Round 2.
- Spring (Round 2, Jan 11 – Mar 2027): Pisum sativum (pea, mycorrhizal + rhizobia host) in 9 cm pots, 5 seeds/pot, 6–8 weeks. Count root nodules (pink inside = active N fixation), measure dry mass, and test H4 properly. Treatments are re-designed from Round 1 (see Engineering). Triticum aestivum (wheat, 10 seeds/pot) is an optional parallel set if a second tray of space is found. Tea Bag Index results come mid-February. Optional Round 3 (Apr–Jun): a pioneer "forest" pot of the best recipe with moss + white clover (Trifolium repens) + a birch seedling (Betula pendula).
Engineering track
Problem statement: design a growing medium made mostly of local regolith (MR-1) that supports a crop through a full cycle, while minimising material that must be shipped from Earth. Real lunar payload delivery costs on the order of $1 million per kg.
Requirements (measurable):
| # | Requirement | Target | Test |
|---|---|---|---|
| R1 | Import mass fraction | ≤ 20 % of dry mass from Earth (compost, biochar, fertiliser, soil) | Recipe mass balance |
| R2 | Water retention | Gravimetric WHC ≥ 0.35 g/g (or ≥ 2× R0) | Drain-and-weigh |
| R3 | Drying rate | Loses ≤ 25 % of retained water per day in the tank | Daily weighing |
| R4 | pH buffering | 1:5 extract pH 6.0–7.5 after 3 weeks of watering | PHPEN |
| R5 | Salinity safe | Extract EC 0.2–1.5 mS/cm (no fertiliser burn) | TDSPEN (EC mode) |
| R6 | Nutrient supply | Dry mass ≥ 60 % of P at day 21 (cress), leaf colour ≥ 3 | Harvest |
| R7 | Structure | No surface crust after 3 waterings. Seedlings emerge ≥ 80 % | Visual, germination % |
| R8 | Cost and availability | ≤ 10 RON per litre of medium, all components buyable in Bucharest | BOM |
Candidate solutions (students brainstorm, then pick 4 for Round 1. The table lists the realistic set):
- Organic matter: compost (RC), vermicompost, coconut coir (fibre + WHC, no N), used tea leaves/coffee grounds ("crew waste" analogue).
- Mineral nutrition + structure: biochar + slow-release fertiliser (RB), zeolite (cation exchange).
- Biology: live soil inoculum + mycorrhiza (RM), compost tea, rhizobia (via peas + Living Earth soil).
- pH correction: elemental sulfur (slow) or acidic peat (fast), which counter the alkaline basalt.
- Physical: hydrogel crystals (polyacrylate, garden centres) for WHC, mulch layer of perlite to stop crusting.
- "Closed-loop" idea for Round 2: re-use Round 1's R0 and RC pots ("biologically conditioned regolith") to test whether one crop cycle improves the medium.
Test criteria → weighted decision matrix (filled in week 8): dry mass as % of P (35 %), WHC (20 %), pH/EC within range (15 %), import mass fraction (15 %), cost/availability (10 %), handling (dust, crusting) (5 %). Score each 0–5 from the measured data, not from opinion.
Iteration plan, Round 2 (sow Jan 11, harvest by mid-March, peas):
- Keep R0 and P as anchors.
- Take the best Round 1 amendment and run a dose series at 5 %, 10 % and 20 % → find the minimum import fraction that meets R6.
- Add one combination recipe designed by the students (e.g. 10 % compost + 5 % biochar + inoculum) = "MR-1 Optimised".
- Add a baked-inoculum control (RM soil heated at 120 °C for 1 h) to separate the effect of biology from that of the nutrients in the soil. This fixes the Round 1 confound.
- 5 treatments × 3 pots × 9 cm pots fit the same tank (grid 47.5 × 28.5 cm with saucers).
- Round 3 (spring, optional): scale the winning recipe to a 10 L "forest" pot. Engineering focus: long-term pH drift and WHC after 3 months.
Enclosure & build
Enclosure: TANK63 glass aquarium 60×30×35 cm (inner ≈ 59 × 29 cm). It is a clear humidity greenhouse that photographs well. A BOXPLASTIC (opaque) would block side light and photos, so it is not used.
- Pot grid: 15 square pots 7×7×8 cm (≈ 0.22 L) each on its own saucer (8.5 cm). Pots must not share a tray, because fertiliser leachate from RB would contaminate the other treatments. The grid is 5 columns × 3 rows = 42.5 × 25.5 cm, at the left end. The right 16 cm holds the sensor stand (SHT31, BH1750) and the 2 sacrificial pots.
- Lid: 2 clear acrylic panels, each 30.5 × 31 cm (cut from 1 ACRYLIC sheet, edges sanded), resting on 4 self-adhesive silicone bumpers on the rim. Panel B (right) has an 80 mm hole for the FAN (blowing out) and a 3 × 8 cm mesh-covered inlet slot at the far end of panel A. Each panel lifts off independently for watering.
- Light bridge: 2 aluminium angles (20×20 mm, 65 cm) span the tank's short-side rims and carry 3 LEDPROFILE pieces of 50 cm (cut from 2 × 1 m profiles), spaced 9 cm apart, with LEDs facing down through the acrylic lid. LED electronics stay outside the humid air. Acrylic transmits ≈ 90 %. LED-to-soil distance ≈ 27 cm. Raise pots on a 5 cm riser (upturned tray) if lux at the pots is < 7 000.
- Humidity dome behaviour: days 0–4 lid fully closed and inlet taped (RH > 85 %, germination). Days 5–10 inlet open, fan on its cycle. From day 11, panel A shifted 2 cm open. Target 60–80 % RH and 20–26 °C. Condensation that blocks photos means too humid: open more.
- Node box: BOX (IP65) on the wall/shelf behind the tank, above the top of the tank. Cables enter through GLANDs from below with drip loops. PSU12 brick on the shelf, plugged into the shared RCD-protected strip. Only 12 V DC enters the light bridge and fan.
flowchart LR
subgraph TANK["TANK63 glass tank 60x30x35 cm"]
subgraph ROW1["Row 1 (block 1, back)"]
A1["RC"] --- A2["R0"] --- A3["P (SOIL C)"] --- A4["RM"] --- A5["RB"]
end
subgraph ROW2["Row 2 (block 2)"]
B1["RM"] --- B2["RB"] --- B3["R0 (SOIL A)"] --- B4["P"] --- B5["RC (SOIL B)"]
end
subgraph ROW3["Row 3 (block 3, front)"]
C1["P"] --- C2["RM"] --- C3["RB"] --- C4["RC"] --- C5["R0 (DS18B20)"]
end
STAND["Sensor stand: SHT31 at canopy height, BH1750 facing up"]
SAC["Sacrificial pots R0-x and P-x"]
end
LED["Light bridge: 3 x 50 cm LEDSTRIP in LEDPROFILE above acrylic lid"]
FAN["FAN 80 mm in lid, exhaust"]
NODE["Node box mc-06-regolith (ESP32, OLED, 2 MOSFET, BUCK)"]
PSU["PSU12 brick on shelf, RCD strip"]
LED --> TANK
FAN --> TANK
NODE -->|"PWM 12 V"| LED
NODE -->|"PWM 12 V"| FAN
NODE ---|"I2C, 1-Wire, 3 analog"| TANK
PSU -->|"12 V DC"| NODE
(The layout shown is one dice randomisation. Students re-roll their own and record it on the tank label.)
Build steps (team of 3–4, with time estimates):
| # | Step | Time |
|---|---|---|
| 1 | Inspect TANK63 for chips. Place it on a foam mat on a sturdy table away from the radiator and direct sun. Two people carry it, empty | 20 min |
| 2 | Cut the acrylic lid panels (teacher, fine-tooth saw or scoring knife), sand the edges, drill the 80 mm fan hole (hole saw, teacher) and cut the inlet slot. Glue mesh over the slot | 90 min |
| 3 | Cut the aluminium angles to 65 cm. Cut the LEDPROFILE to 3 × 50 cm, and the LEDSTRIP to 3 × 50 cm at the marked cut points. Stick the strips in, solder or clip leads (teacher solders), fit the diffusers, screw the profiles to the angles (M3) | 120 min |
| 4 | Node: ESP32 on TERMBOARD in BOX, BUCK set to 5.0 V before connecting the ESP32, 2 × MOSFET (LED, fan), OLED in the lid window, 6 GLANDs | 120 min |
| 5 | Flash ESPHome mc-06-regolith.yaml, join the MICROCOSM SSID, adopt in Home Assistant, check entities |
45 min |
| 6 | Sensor stand: acrylic offcut L-bracket. SHT31 at 10 cm height (canopy), BH1750 at pot-rim height facing up. Route cables through the lid gap edge (flat 4-core, under a bumper) | 45 min |
| 7 | Seal the SOIL probes: conformal coat or nail varnish on the PCB edges, heat-shrink over the electronics, mark the insertion line at 6 cm | 30 min |
| 8 | Light map: BH1750 on its cable at all 15 pot positions with LED at 80 % → map table. Adjust the riser if the min/max ratio is < 0.7 | 30 min |
| 9 | Calibration sessions (SOIL per substrate, SHT31 salt test, DS18B20 ice bath) | 2 × 45 min |
Regolith analogue preparation (teacher + 2 students, outdoors or by an open window, FFP2 + goggles + gloves):
- Weigh the components for a 10 kg batch: 6.5 kg basalt dust, 2.5 kg quartz sand, 0.5 kg feldspar, 0.5 kg perlite.
- Crush the perlite in a closed bag with a rolling pin. Sieve each component separately through a 1 mm kitchen sieve inside a large lidded bucket or bag (sieve low, no shaking in open air). Discard the > 1 mm fraction (or keep it for the crust-mulch experiment).
- Do not wash. The analogue stays dry and purely mineral. Washing would remove fines and soluble salts and change the pH.
- Optional sterilisation: spread 2 cm deep on oven trays, bake at 120 °C for 1 h (teacher, school kitchen/home oven), cool covered. Do this for all MR-1 so that R0 is "sterile like the Moon" and the RM inoculum is the only biology.
- Mix in a lidded 10 L bucket: close it, roll and tumble for 2 min, wait 5 min for the dust to settle, then open.
- Grain-size check: 100 g through 0.5 mm, weigh both fractions, record. Baseline pH/EC (1:5) and WHC.
- Store dry in the labelled lidded bucket ("MR-1 batch 1, date, mass").
- To suppress dust when filling pots, moisten the mix to ≈ 5 % water by mass (50 mL per kg, sprayed and stirred in the bucket). Do amendments by volume with a measuring jug: e.g. RC = 800 mL MR-1 + 200 mL compost, mixed in a bag.
Biology
Species
| Species | Use | Why | Source / RON |
|---|---|---|---|
| Lepidium sativum (garden cress, "creson") | Round 1 | Germinates in 1–2 days, harvestable at 14–21 days, sensitive to nutrient stress, uniform | Any garden centre/Dedeman, ≈ 5 RON/packet |
| Raphanus sativus (radish, e.g. 'Saxa' / microgreen radish) | Backup for Round 1, or pilot | Bigger seed, visible hypocotyl, 3–4 weeks | ≈ 5 RON |
| Pisum sativum (pea, e.g. 'Kelvedon Wonder') | Round 2 | Mycorrhizal host + root nodules (rhizobia) → tests the biology treatments | ≈ 8 RON / 250 g |
| Triticum aestivum (wheat, wheatgrass grain) | Round 2 optional | Grass (Wageningen-style crop), mycorrhizal host | ≈ 12 RON / 500 g (bio shop) |
| Pavement moss (Bryum argenteum or local cushion moss) | Optional pioneer pot | Pioneer on bare mineral substrate, no cost | Collected from a school courtyard |
| Arabidopsis thaliana | Not used | Tiny, 6–8 week cycle, seed only via stock centres (NASC), hard to measure by hand. Cite it, don't grow it | – |
Lichens: not practical (growth is mm per year). Do not collect them.
Inoculants and amendments
- Mycorrhizal powder (arbuscular mycorrhizal fungi, e.g. Rhizophagus irregularis products sold as "micorize" or Rootgrow): eMAG/garden centres, 1 pack. Put the label dose (≈ 1 g) in the sowing hole or under the seed layer. Effective only on peas/wheat (Round 2). In Round 1 it is part of RM by protocol.
- Live soil inoculum: 5 % v/v from ecosystem 8 (Living Earth) "healthy" soil, sieved < 5 mm, taken on sowing day.
- Compost tea (Round 2 option): 100 mL mature compost in 1 L dechlorinated water (left 24 h), aerated 24 h with the hydro AIRPUMP (borrowed) or shaken 3×/day, strained. 10 mL per pot. Gloves.
- Compost: bagged mature compost or sieved finished compost from ecosystem 1 (Orchestra of Rot) if ready.
- Biochar: horticultural biochar 3 L (eMAG). Pre-soak 24 h before use (dry biochar absorbs nutrients at first).
- Slow-release fertiliser: Osmocote-type granules, 3 g per litre of RB mix.
Sowing protocol (Round 1, Monday Nov 16, 2026 = day 0)
- Seed viability test the week before: 2 × 20 seeds on wet paper towel in a closed box, count at 72 h. Expect ≥ 90 %. Use one packet and one lot for all pots.
- Fill the pots to 1 cm below the rim with the pre-moistened substrate, tap 5×, weigh and record m_dry_equiv (correct for the 5 % moisture).
- Bring each pot to its 70 % WHC target mass with a syringe, from below the surface (no splashing).
- Place 10 seeds per pot in a 3 × 3 + 1 pattern with tweezers (template card with 10 holes).
- Cover with 2–3 mm of the same substrate (dry, sprinkled through a tea sieve). Mist 5 sprays.
- Label each pot on two sides (code + block, e.g. "RC-1"), place according to the randomisation sheet, insert the probes in the marker pots at the 6 cm line, 1 cm from the wall, before the seeds go in.
- Lid closed, inlet taped, LED on schedule from the same day.
- Days 1–7: mist only (5 sprays per pot per school day). Weigh-watering starts on day 7.
Instrumentation
| Catalog ID | Qty | Placement | Interval | Purpose |
|---|---|---|---|---|
| SOIL | 3 | A: pot R0 row 2 (B3). B: pot RC row 2 (B5). C: pot P row 1 (A3). Inserted to the 6 cm line | 60 s (median of 10 samples) | Drying curves after watering, analogue vs amended vs soil. Checks watering timing |
| DS18B20 | 1 | Pot R0 row 3 (C5), probe tip at 3 cm depth | 60 s | Root-zone temperature. Dark basalt mineral vs air temperature under the LED |
| SHT31 | 1 | Sensor stand, 10 cm above the floor (canopy height), shaded from direct LED | 60 s | Air T/RH. Humidity dome control (fan), damping-off risk |
| BH1750 | 1 | Sensor stand at pot-rim height, facing up. Also used on a cable for the light map | 60 s | Light level at the canopy. Confirms LED schedule/PWM. Lux, not PAR |
| OLED | 1 | Node box lid window | 5 s refresh | Live values + Wi-Fi/HA status for students at the tank |
| PHPEN / TDSPEN / CALSOL | shared pool | Bench | Before sowing, after harvest | 1:5 substrate extracts |
Why each SOIL probe is calibrated separately in its own substrate: a capacitive probe measures the bulk dielectric permittivity around it, not water directly. Water has ε ≈ 80, air 1, organic matter ≈ 2–5 and silicate minerals ≈ 4–9. Basalt with Fe-Ti oxides sits at the high end. MR-1 packs at ≈ 1.5 g/cm³, potting soil at ≈ 0.3–0.5 g/cm³, so the same raw reading means a different water content in each. The v2.0 probe works at ~1 MHz, where dissolved salts (fertiliser in RB, compost in RC) also raise the reading. So a single "soil" curve would make R0 look wetter or drier than it is. Every probe gets its own curve in the substrate of its marker pot, and graphs are reported in θv (mL water per 100 mL substrate) and in % of that substrate's WHC.
Pin assignment (standard pin map only):
| Function | GPIO | Device / entity id |
|---|---|---|
| I2C SDA / SCL | 21 / 22 | SHT31 0x44 → mc_06_air_temp, mc_06_air_rh. BH1750 0x23 → mc_06_lux. OLED 0x3C |
| 1-Wire | 4 (4.7 kΩ to 3.3 V, on TERMBOARD) | DS18B20 → mc_06_substrate_temp_r0 |
| Analog A | 32 | SOIL A → mc_06_soil_moisture_r0 |
| Analog B | 33 | SOIL B → mc_06_soil_moisture_rc |
| Analog C | 34 | SOIL C → mc_06_soil_moisture_p |
| PWM out 1 (light) | 16 → MOSFET 1 → LED bridge | mc_06_led (brightness logged as mc_06_led_pwm) |
| PWM out 2 (fan) | 17 → MOSFET 2 → FAN | mc_06_fan |
| Unused | 18, 19, 23, 25, 26, 27, 13, 14, 5, 15, 12, 35, 36, 39 | Free for Round 2 extensions (e.g. a 4th SOIL on GPIO35) |
SOIL probes are powered from 3.3 V (the output then stays within the 0–3.1 V ADC range at 11 dB attenuation). I2C cable to the stand ≤ 1 m, 4-core twisted, at 100 kHz.
ESPHome core (excerpt):
substitutions: { node: mc-06-regolith }
i2c: { sda: 21, scl: 22, frequency: 100kHz }
one_wire: [{ platform: gpio, pin: 4 }]
sensor:
- platform: sht3xd
address: 0x44
temperature: { name: mc_06_air_temp }
humidity: { name: mc_06_air_rh, id: rh }
update_interval: 60s
- platform: bh1750
name: mc_06_lux
update_interval: 60s
- platform: dallas_temp
name: mc_06_substrate_temp_r0
update_interval: 60s
- platform: adc
pin: GPIO32
name: mc_06_soil_moisture_r0
attenuation: 12db # "11 dB" in older ESPHome
update_interval: 6s
unit_of_measurement: "%" # theta_v, mL per 100 mL
filters:
- median: { window_size: 10, send_every: 10 }
- calibrate_linear: # MR-1 curve, replace with measured points
- 2.60 -> 0.0
- 1.45 -> 32.0
# GPIO33 (rc) and GPIO34 (p) identical, each with its own curve
output:
- { platform: ledc, pin: 16, id: pwm_led, frequency: 1000Hz }
- { platform: ledc, pin: 17, id: pwm_fan, frequency: 25000Hz }
light:
- { platform: monochromatic, output: pwm_led, name: mc_06_led, default_transition_length: 10min }
fan:
- { platform: speed, output: pwm_fan, name: mc_06_fan }
Calibration
- SOIL (per probe, in its substrate, week 3): 5 points. (1) Probe in air. (2) Oven-dry substrate packed in a 7 cm pot. (3)–(4) Substrate mixed in a bag with water at 33 % and 66 % of WHC, packed to the same mass. (5) At field capacity (drain-and-weigh step 4). θv = mL water / 220 mL. Fit linear (or 2-segment) in a spreadsheet and enter it in
calibrate_linear. Repeat point 5 after harvest to check drift. - SHT31: saturated NaCl slurry in a sealed zip bag with the sensor for 24 h → should read 75 ± 2 % RH. Record the offset.
- DS18B20: ice-water bath (0.0 °C) and the room vs a reference thermometer. Record the offset (typical ≤ 0.5 °C).
- BH1750: no absolute calibration. Use it for relative comparisons and the light map. Rough conversion for white full-spectrum LEDs: ≈ 70 lux per µmol·m⁻²·s⁻¹ (so 10 000 lux ≈ 140 µmol·m⁻²·s⁻¹. Target ≥ 7 000 lux at the pots ≈ 100 µmol, DLI ≈ 5.8 mol/m²/day at 16 h).
- PHPEN / TDSPEN: 2-point calibration with CALSOL (pH 7 + 4, EC 1413 µS/cm) on each measurement day, before the samples.
Automation
Minimal on purpose. The experiment's precision comes from hand-weighed watering.
- LED: 16 h light / 8 h dark, ON 06:00–22:00 with a 10 min fade in and out. Default PWM 80 %, chosen from the light map (≥ 7 000 lux at the lowest pot). The PWM % is logged as an entity, so the light dose is in the dataset. Safety dim: if air T > 30 °C, PWM drops to 50 % until T < 28 °C.
- Fan (optional but recommended): 5 min every 30 min during the light period (gentle airflow = sturdier seedlings, less damping-off). Extra runs while RH > 90 % (from day 5). Off during days 0–4 (germination dome). Manual override switch in HA.
- Watering stays manual, measured by mass, because: (1) each of the 15 pots needs its own amount to reach its own 70 % WHC target, and one pump with a manifold delivers unequal flows; (2) the water added per pot is itself a measured variable (water use per treatment); (3) a shared drip system would carry fertiliser between treatments; (4) 15 metered channels would cost more than the whole ecosystem and add water near electronics; (5) a 3–5 g watering error in a 0.22 L pot is 10 % of its capacity, and only a scale gets this right. The SOIL marker pots tell the team when the pots are drying. The scale decides how much water.
stateDiagram-v2
state "LED control" as LEDC {
[*] --> Night
Night --> Day : clock 0600, fade in 10 min
Day --> Dimmed : air temp above 30 C
Dimmed --> Day : air temp below 28 C
Day --> Night : clock 2200, fade out 10 min
Dimmed --> Night : clock 2200
}
state "Fan control" as FANC {
[*] --> Off
Off --> Venting : every 30 min in light period, or RH above 90
Venting --> Off : after 5 min and RH below 85
Off --> Locked : germination days 0 to 4
Locked --> Off : day 5 flag set in HA
}
Implementation: HA automations (the time triggers) + an ESPHome on_value rule for the temperature dim. If Wi-Fi/HA is down, the node keeps its last LED state, and an ESPHome time component with an SNTP fallback schedule (same 06–22) is included in the YAML, so the photoperiod survives a hub outage.
Operations
Daily (school days, 3 min, rota of 1 student):
- OLED/Grafana: air T 18–28 °C, RH 60–90 %, LED state correct for the time of day, all 3 SOIL values updating.
- Look for mould (white fuzz on the surface), damping-off (seedlings collapsing at the base), condensation blocking the view. Note it in the log with the pot code.
- Days 1–7: germination count + misting.
Mon / Wed / Fri watering (15 min, from day 7):
- Take each pot out (with its saucer), weigh it, add water with a syringe/wash bottle to its target mass (±2 g), pour away any saucer water before weighing.
- Record on the watering sheet: date, pot code, mass before, mass after, mL added, initials.
- Friday: water to target + 10 % (weekend). Before long breaks (Nov 30 – Dec 1 national holiday; school calendar breaks), water to target + 15 % and shift the lid to "humid".
- Monday: rotate the whole grid 180° (keep the randomised order).
Weekly photos (Friday 12:00, LED at 100 % for the photo then back to 80 %):
- Lift the lid. Phone on a fixed mount (acrylic offcut bridge) 40 cm above the pots, top-down, ruler + date card + colour card in frame, no flash. One photo per row + one side photo through the glass at a marked position.
- File name
mc06_YYYYMMDD_row1.jpg→ shared folderMICROCOSM/06-regolith/photos/. Run Canopeo (green cover %) on the row photos.
Harvest protocol (day 21 = Mon Dec 7, 2026; one double lesson):
- Final count, height of all seedlings, colour score. Photos.
- Cut the shoots at the substrate surface with scissors, one pot at a time. Weigh fresh mass per pot immediately (0.001 g scale, tared envelope) → record.
- Labelled paper envelope (code, date) → dry at 60 °C for 48 h → weigh dry mass. (If no oven/dehydrator: air-dry on a radiator for 7 days, weigh twice 24 h apart until constant, and note the method.)
- Roots: tip the pot onto a sieve over a bowl of water, soak 10 min, rinse gently, measure the longest root of 5 seedlings. Photograph the roots on a black card with a ruler.
- Substrate: take 20 g from each pot (1:5 extract for pH/EC + 2 g catalase test). Pool 100 g per treatment for the respiration run in ecosystem 8.
- Keep the R0 and RC substrates in labelled bags for Round 2 "conditioned regolith".
- Nothing from this experiment is eaten. Plant material goes to the compost (ecosystem 1).
Safety & risks
- Fine mineral dust (the main hazard): quartz sand contains crystalline silica, and inhaling fine (respirable, < 10 µm) silica dust over the long term damages the lungs. Basalt dust is also an irritant. Rules: FFP2 mask + safety goggles + nitrile gloves whenever dry material is sieved, mixed, baked or poured. Sieving is done by the teacher or with teacher supervision, outdoors or by an open window, inside a bucket or bag, never shaken in open air. No dry sweeping: wipe spills with a damp cloth. Fill pots only with pre-moistened mix (≈ 5 % water). Store closed. Students with asthma do not do the dry steps.
- Electrical: 230 V exists only inside the certified PSU12 brick, which is plugged into the shared RCD-protected (30 mA) strip on the shelf above and away from the tank, with a drip loop on its cord. Students never open or modify anything mains-powered. Everything at or in the tank is 12 V DC SELV (LED bridge, fan) or 3.3 V (sensors). The node box sits above the top of the tank, and cables enter through glands from below with drip loops. Unplug the brick before working on the light bridge.
- Glass: TANK63 weighs ≈ 15 kg empty. Two people carry it, only when empty, on a foam mat. Check the edges for chips. If the glass cracks, the teacher removes it.
- Biology: gloves for compost, Living Earth soil and inoculants. Wash hands after each session. Watch for mould: if a pot has dense mould by day 10, photograph and record it, but do not remove it (it is data). If it spreads to > 3 pots, increase ventilation. The compost tea is not sprayed (no aerosol), only poured.
- Chemicals: 3 % H₂O₂ (catalase test) with goggles and gloves, small volumes. Oven baking at 120 °C is done by the teacher with oven gloves. Biochar dust: same rule as mineral dust. Fertiliser granules are kept in a labelled jar and are not handled by students under 14 without gloves.
- Scientific risks and mitigations: seed lot failure → viability test in week 2, backup radish. Probe batch defects → test all 3 in water/air in week 2, spares from the pool. Light gradient → randomised blocks + rotation + light map. Basalt dust pH < 7.5 → MR-1b with dolomite. Holiday drying → weigh-water + 10/15 %, closed lid. Fungus gnats from compost → yellow sticky trap in the tank corner.
Educational outcomes & assessment
Students will be able to:
- Explain why germination is not establishment, using their own R0 vs P data and the 2022 Apollo-soil result.
- Design a controlled pot experiment with replication, randomised blocks and a terrestrial control, and say what their n = 3 can and cannot show.
- Measure water-holding capacity, pH and EC with standard methods, and explain why a capacitive sensor needs a separate calibration for each substrate.
- Translate an engineering goal (minimum import mass) into measurable requirements and a weighted decision matrix, and use the data to choose the Round 2 recipe.
- Combine manual data (biomass, counts) with logged sensor data (moisture curves, light, temperature) in one analysis.
Assessment (per team, 100 points):
| Item | Points | Evidence |
|---|---|---|
| Research plan: question, hypotheses H1–H5 in their own words, variables table, randomisation sheet | 15 | Plan document, week 2 |
| Analogue lab sheet: recipe mass balance, grain-size, pH/EC, WHC (with replicates) | 15 | Lab sheet, week 3 |
| Data quality: complete germination/watering/harvest logs, photo series, calibration records | 20 | Shared spreadsheet + folder |
| Analysis: charts with all replicates, % of control, honest statement of uncertainty | 20 | Analysis sheet, week 8 |
| Engineering: requirements table, decision matrix, justified Round 2 design | 20 | Design review, Dec 16 |
| Communication: 5 min presentation / poster at the MICROCOSM showcase | 10 | Dec 17–18 |
Individual: each student keeps a lab notebook (dated entries). Roles rotate weekly (lead, measurer, recorder, safety/dust officer).
Sub-BOM
Cost-cut 2026-10-20: feldspar omitted from the analogue recipe (basalt + quartz + perlite only); kitchen scale shared with teams 4–5.
Price basis: Romanian retail estimates incl. VAT, October 2026 (optimusdigital.ro / cleste.ro for electronics, eMAG, Dedeman/Hornbach, garden centres; basalt rock dust via eMAG marketplace or Amazon.de incl. a shipping share). 1 EUR ≈ 5.1 RON. Shared pool items (PHPEN, TDSPEN, CALSOL, safety goggles, hand tools, Pi/router) are not counted here.
| ID / item | Qty | Unit RON | Line RON | Basis / note |
|---|---|---|---|---|
| ESP32 | 1 | 40 | 40 | DevKitC 38-pin |
| TERMBOARD | 1 | 35 | 35 | Screw-terminal breakout |
| OLED | 1 | 20 | 20 | SSD1306 0.96" |
| SHT31 | 1 | 55 | 55 | Cased/PTFE membrane |
| SOIL | 3 | 12 | 36 | v2.0 TL555 version |
| DS18B20 | 1 | 15 | 15 | Waterproof, 1 m |
| BH1750 | 1 | 15 | 15 | Lux breakout |
| LEDSTRIP | 1 | 140 | 140 | 1.5 m used (3 × 50 cm). 3.5 m returns to the pool |
| LEDPROFILE | 2 | 30 | 60 | Cut to 3 × 50 cm + 1 spare 50 cm |
| MOSFET | 2 | 10 | 20 | LED, fan |
| FAN | 1 | 25 | 25 | 12 V 80 mm, lid exhaust |
| PSU12 | 1 | 60 | 60 | 12 V 5 A brick (load ≈ 1.6 A) |
| BUCK | 1 | 10 | 10 | 12 → 5 V for ESP32 VIN |
| BOX | 1 | 35 | 35 | IP65 150×110×70 |
| GLAND | 6 | 2 | 12 | 3 SOIL, DS18B20, I2C, 12 V out |
| TANK63 | 1 | 260 | 260 | Rimless glass 60×30×35 |
| ACRYLIC | 1 | 120 | 120 | 2 lid panels + sensor stand + photo bridge |
| MESH | 0.1 m² | 25 | 2.5 | Inlet vent, pot bottoms in WHC test |
| BIO: basalt rock dust (Urgesteinsmehl), ≈ 6–7 kg bag | 2 | 60 | 120 | ≈ 12 kg → 15 kg MR-1 (2 rounds + tests) |
| BIO: fine quartz sand 0.1–0.5 mm, 25 kg | 1 | 40 | 40 | Dedeman/Hornbach |
| BIO: perlite 5 L | 1 | 15 | 15 | Dedeman |
| BIO: universal potting soil 20 L | 1 | 25 | 25 | Control P |
| BIO: mature compost 20 L | 1 | 25 | 25 | Or from ecosystem 1 (then 0) |
| BIO: horticultural biochar 3 L | 1 | 50 | 50 | eMAG |
| BIO: slow-release fertiliser (Osmocote-type) 300 g | 1 | 40 | 40 | Garden centre |
| BIO: mycorrhizal inoculant powder | 1 | 45 | 45 | eMAG/garden centre |
| BIO: seeds (cress ×2, radish, pea 250 g, wheat 500 g) | 1 lot | 35 | 35 | Garden centre / bio shop |
| Consumable: square pots 7 cm | 20 | 0.5 | 10 | 15 + 2 sacrificial + 3 WHC test |
| Consumable: square pots 9 cm | 20 | 0.8 | 16 | Round 2 + tea-bag pots |
| Consumable: saucers 8.5–10 cm | 20 | 1 | 20 | One per pot, no shared tray |
| Tool: jewellery scale 0.001 g / 50 g | 1 | 70 | 70 | Cress biomass is ≈ 20–60 mg dry per pot |
| Tool: stainless kitchen sieves (1 mm, 0.5 mm, tea sieve) | 1 set | 40 | 40 | Analogue prep |
| Safety: FFP2 masks | 10 | 2 | 20 | Dust steps |
| Safety: nitrile gloves box 100 | 1 | 35 | 35 | Shared with ecosystem 8 if needed |
| Consumable: lidded 10 L buckets | 2 | 15 | 30 | Mixing + storage |
| Consumable: distilled water 5 L | 2 | 5 | 10 | 1:5 extracts |
| Hardware: aluminium angle 20×20 mm, 1 m | 2 | 20 | 40 | Light bridge |
| Hardware: M3 screws, silicone bumpers, 4-core cable 3 m | 1 lot | 20 | 20 | – |
| Consumable: labels, paper envelopes, colour chart print | 1 lot | 15 | 15 | – |
| BIO: tea bags green + rooibos (Tea Bag Index) | 2 boxes | 15 | 30 | Pyramid bags |
| Consumable: H₂O₂ 3 % 100 mL | 2 | 3 | 6 | Catalase test |
| Subtotal | 1 718 RON (≈ 337 EUR) | |||
| Optional (not in subtotal): LHS-1 certified simulant 1 kg | 1 | ≈ 337 EUR | (650) | $45/kg list + US shipping/customs, lead time several weeks |
8-week timeline (Oct 26 – Dec 18, 2026)
gantt
title Forests in Space - Round 1
dateFormat YYYY-MM-DD
axisFormat %d %b
section Plan and order
Team roles, question, read 2022 and Wageningen summaries :a1, 2026-10-26, 5d
Order basalt dust, biochar, scales, myco online :a2, 2026-10-26, 3d
Dedeman and garden centre run :a3, 2026-10-29, 2d
section Build
Node assembly and ESPHome flash :b1, 2026-11-02, 4d
Lid, light bridge, sensor stand :b2, 2026-11-02, 5d
Seed viability test :b3, 2026-11-03, 3d
section Substrate
Sieve, bake, mix MR-1, grain size :c1, 2026-11-09, 2d
Baseline pH EC and WHC of all 5 substrates :c2, 2026-11-10, 3d
SOIL, SHT31, DS18B20 calibration and light map :c3, 2026-11-11, 3d
section Experiment
Sow round 1 day 0 :milestone, d0, 2026-11-16, 0d
Germination counts days 1 to 7 :d1, 2026-11-17, 7d
Growth, weigh-watering, weekly photos :d2, 2026-11-23, 14d
Harvest day 21 :milestone, d3, 2026-12-07, 0d
Drying, dry mass, extracts, catalase, respiration :d4, 2026-12-07, 5d
section Analyse and present
Analysis and decision matrix :e1, 2026-12-09, 5d
Commissioning sign-off :milestone, e2, 2026-12-15, 0d
Design review, Round 2 recipe :e3, 2026-12-16, 1d
Showcase presentation :e4, 2026-12-17, 2d
| Week | Dates | Deliverable |
|---|---|---|
| 1 | Oct 26–30 | Roles, research plan draft, all orders placed (online by Oct 28) |
| 2 | Nov 2–6 | Node live in HA, lid + light bridge built, seed viability ≥ 90 % |
| 3 | Nov 9–13 | MR-1 batch 1 (10 kg), baseline pH/EC/WHC table, 3 SOIL curves, light map, randomisation sheet |
| 4 | Nov 16–20 | Sown Nov 16, germination curves |
| 5 | Nov 23–27 | Day 7/14 heights, weigh-watering log, photo week 1–2. Pre-holiday watering Nov 27 |
| 6 | Nov 30 – Dec 4 | (Nov 30 – Dec 1 no school) Day 14–18 data, sacrificial-pot root check |
| 7 | Dec 7–11 | Harvest Dec 7, dry mass Dec 9, extracts + biological activity tests |
| 8 | Dec 14–18 | Analysis, decision matrix, sign-off Dec 15, Round 2 design Dec 16, showcase Dec 17–18. Tank reset for Round 2 (sow Jan 11, 2027) |
Sources used for prices and context: Space Resource Technologies LHS-1 product page (spaceresourcetech.com, $45/kg list); Hornbach.ro crushed basalt listing (basalt aggregate availability in RO); Steinkraft "Bodenkraft" basalt powder (fromaustria.com) as an example of garden basalt rock dust; Paul et al., Commun. Biol. 5, 382 (2022); Wamelink et al., PLoS ONE 9(8): e103138 (2014).
7. The Hydroponic Jungle
Node: mc-07-hydro · Team: 3–4 students · Location: classroom bench, 60 × 85 cm growing footprint, a wall shelf ≥ 40 cm above the water line, and a hanging frame for the light.
Concept (refined)
This is a soil-free growing system with two parts:
- Main DWC unit (deep water culture), the "engineering" unit. An opaque 45 L food-grade PP box holds 25 L of nutrient solution and 8 net pots (50 mm). It is aerated by a COTS air pump. A 12 V pump circulates the solution. The node controls pH, EC and level automatically.
- Jar array, the "science" unit. A 3 × 3 grid of 9 × 2 L opaque glass jars, one plant per jar. These are cheap, independent replicates for the treatments (aeration, EC, light). Still (non-aerated) jars are Kratky jars. One jar has no plant and serves as the evaporation blank.
The node's probes stay in the DWC box. Students measure the jars by hand with the pens. This is deliberate: the jars teach measurement, and the DWC box teaches control.
Two pieces of 230 V equipment are allowed, and no others. The COTS LED panel hangs ≥ 30 cm above the open top of the unit, on its own cord. The COTS aquarium air pump sits on the shelf, and only its air line goes down into the water. Both plug into SMARTPLUGs on an RCD power strip. Everything that touches water or sits beside it runs on 12 V DC or less.
Science track
Driving question: What does a lettuce plant actually need from the water: oxygen, nutrients, or light? How much of each gives the most biomass?
Hypotheses (one per round)
| Round | When | Hypothesis | Treatment / control |
|---|---|---|---|
| R1 Aeration | 9 Nov – 14 Dec 2026 | H1: Aerated roots produce more root mass and shoot mass than still (Kratky) roots at the same EC (1.2 mS/cm). The difference grows once the roots fill the jar. | 4 aerated jars vs 4 still jars + 1 blank. The DWC box (aerated, n = 8) is a descriptive reference, not a statistical treatment, because its container differs. |
| R2 Nutrients | Jan – Feb 2027 | H2: Shoot mass rises from EC 0.8 to 1.2 mS/cm and then levels off (or drops) at 1.6. Tip-burn appears first at 1.6. | 3 × EC 0.8, 3 × EC 1.2, 3 × EC 1.6, all aerated. The blank moves to a corner of the tray. |
| R3 Light | Mar – Apr 2027 | H3: Biomass scales with daily light integral (DLI). Option A: distance to the panel (jars on risers at 30 / 45 / 60 cm under the panel). Option B: photoperiod 12 h vs 16 h, which needs a light-tight divider and a second LEDPANEL on its own SMARTPLUG (+≈ 260 RON). | 3 distances × 3 jars (A, recommended, no extra cost) |
Variables (R1)
- Independent: aeration (air stone on or off).
- Dependent: final shoot fresh mass (g), root fresh mass (g), root dry mass (g), root:shoot ratio, leaf count, plant height (cm), water used (mL/plant), root colour and smell score (1 = white/odourless … 4 = brown/slimy).
- Controlled: variety (Lactuca sativa 'Lollo Rossa' from one seed packet, sown on the same day), jar type and opaque wrap, starting volume 1.8 L, EC 1.2 ± 0.05 at the start, pH 6.0 ± 0.1 at the start, nutrient brand, light (positions re-randomised every Monday and Thursday), and water temperature (shared room).
- Measured covariates: lux at each jar position (BH1750 mapping, weekly) and room air T/RH (SHT31).
Design rules for students
- Assign jar positions randomly with dice and keep a position log. This removes the light gradient under the single panel as a systematic bias.
- Refill rule, the same for every jar: when the level falls below the 1/3 mark, refill with fresh EC 1.2 / pH 6.0 solution up to the line 5 cm below the net pot bottom. Never fill to the top, because Kratky plants depend on the air gap. Record every mL.
- The blank jar (no plant) gives evaporation. Plant transpiration = jar water loss − blank loss.
Sampling and manual measurements
| What | Who / tool | When |
|---|---|---|
| pH, EC and water temperature of the DWC box with PHPEN / TDSPEN, entered into HA "pen check" fields | duty student | every school day at 10:00 |
| pH and EC of each jar (pen; rinse in distilled water between jars) | duty student | Mon / Wed / Fri |
| Water consumption: jar level marks (mL scale on tape) and top-up reservoir level (L) | duty student | Mon / Wed / Fri |
| Leaf count (leaves > 1 cm) and height (rim to tallest leaf tip, cm) for every plant | 2 students | Mon and Thu |
| Photo of each plant from a fixed top view (phone on a jig) and of roots (lift the net pot, 10 s, back) | 1 student | Thu |
| Lux at each of 9 + 8 positions at canopy height (BH1750 on a stick) | 1 student | Monday after re-randomisation |
| Harvest: shoot fresh mass (0.1 g), root fresh mass (blotted), root dry mass (2 days on a radiator in a paper bag, then 0.01 g scale) | whole team | harvest day |
Analysis
- For each plant: growth curves (leaf count and height vs day), final masses, root:shoot ratio, and water use efficiency (g fresh shoot per L transpired).
- Gimnaziu: dot plots of all individual values with the mean per treatment, and the difference of means compared with the range within each group.
- Liceu: Welch t-test or Mann–Whitney U on shoot and root mass (n = 4 vs 4). Report effect size and the 95 % CI. Pool R1 with a spring replicate round to reach n = 8 per group.
- R2: dose–response plot (mass vs EC) with a fitted curve. Find the EC where the gain stops.
- R3: mass vs measured DLI. DLI ≈ PPFD × 3600 × h / 10⁶, with PPFD ≈ lux × 0.015 for white full-spectrum LEDs. This is an approximation: the BH1750 is not a PAR sensor, so use it for relative comparisons only.
- Node data: Grafana plots of pH, EC, water temperature and level. Students annotate every manual intervention and every dose event.
What shows by mid-December vs spring
- By ~14 Dec: first lettuce harvest from the jars and the DWC box (≈ 5 weeks after transplant, 7 weeks from seed). This gives R1 aeration results with visibly different roots (white and fluffy vs thin, brownish, with an air-root zone in the Kratky jars), basil established and pinched once, mint rooted and spreading, 7-day pH/EC stability test results, and the first iteration of the controller.
- Spring 2027: R2 (EC) and R3 (light) rounds, a replicate of R1, the NFT extension, a continuous basil and mint harvest, and optionally strawberries.
Engineering track
Problem statement: Keep the solution in the DWC box within the plants' range automatically, with no manual dosing for 7 days. Targets: pH 5.8–6.2, EC 1.2 ± 0.1 mS/cm, level ± 1 cm. Plants change pH, nutrient concentration and volume every hour. The system must never overdose and must stop safely when something is wrong.
Requirements
| ID | Requirement | Verified by |
|---|---|---|
| R1 | pH held at 6.0 ± 0.3 for 7 days with no manual intervention | InfluxDB: 100 % of 10-min medians inside 5.7–6.3 |
| R2 | EC held at 1.2 ± 0.1 mS/cm (25 °C-compensated) for 7 days | same, 1.1–1.3 |
| R3 | Level held within ± 1 cm of setpoint; top-up reservoir lasts ≥ 4 days | JSN log, top-up count |
| R4 | No single dose > 10 s pump run; daily caps A/B ≤ 20 mL each, pH-down ≤ 10 mL | ESPHome hard limits, dose log |
| R5 | Dosing locks out on low level, empty top-up tank, implausible probe values, failed or stale pen cross-check, or air pump without power | fault-injection tests (see below) |
| R6 | Probe vs pen agreement ≤ 0.2 pH and ≤ 0.1 mS/cm at the daily check | HA pen-check log |
| R7 | All safety limits work with Wi-Fi or HA down | test with the router unplugged |
| R8 | Every component that touches water is ≤ 12 V DC; all 230 V on the shelf through a SMARTPLUG and RCD | teacher checklist sign-off |
| R9 | A student can recalibrate pH in ≤ 15 min using the printed card | timed trial |
Candidate solutions (students compare them and justify the choice)
| Function | Option A | Option B | Option C | Recommended start |
|---|---|---|---|---|
| Top-up | Mechanical mini float valve (aquarium/livestock type, ≈ 25 RON). Gravity-fed from a top-up tank raised ≥ 20 cm. No electronics, not logged, can stick open. | 12 V PUMP in the top-up RESERVOIR, controlled by the JSN level. Overflow cut-off by FLOAT high; dry-run cut-off by FLOAT low. Logged, capped. | Manual daily top-up | B, with A built as a comparison in week 7. A frees one PUMP if the project is short on pumps. |
| Dosing | Timed fixed doses every X h (open loop) | Closed loop: measure → small dose → 15 min mix → re-measure, with caps and lockouts | Proportional dose (volume ∝ error) | B. C is a liceu iteration once dose-response is measured (titration). |
| Dose pumps | 3 × PERI (A, B, pH-down) | 2 × PERI with a one-part nutrient (e.g. GHE FloraNova Grow) | Manual syringe | A. Two-part A and B concentrates must never be mixed, so they need two pumps. |
| Mixing | Air stone + circulation PUMP 5 min / 30 min, continuous during MIX | Air stone only | — | A. Students test B in week 7: time until EC is uniform after a dose. |
| Phase 2 | NFT gutter extension: 1 m square PVC NFT channel (100 × 50 mm) with 6 × 50 mm holes, slope 1:40, fed by the circulation PUMP, gravity return into the DWC box. The pump then runs continuously. | Vertical tower | — | spring 2027 |
Test criteria (pass/fail, run 30 Nov – 6 Dec and again after each iteration)
- 7-day stability: pH 5.7–6.3 and EC 1.1–1.3 for 100 % of the time, with no human dosing. Refilling the top-up tank and dosing bottles is allowed and logged.
- Step response: add a defined disturbance of 2 L of plain dechlorinated water. The controller restores EC to within ± 0.1 in ≤ 3 dose cycles without overshooting by more than 0.15.
- Fault injection (each must lock out dosing and raise an HA alert within 2 min): lift the JSN probe and fake a low level by covering the stilling tube with a hand; lift FLOAT low in the top-up tank; unplug the air pump plug; enter a pen value 0.5 pH off the probe; force the pH probe out of the water (reading out of band).
- Watchdog: force a PERI on from the ESPHome web UI. It must stop by itself after ≤ 10 s.
Iteration plan
- v0 (week 3): human controller. Students follow the state diagram by hand, using pens and syringes, and log every dose. This gives the real dose-response: ΔEC per mL of A+B and ΔpH per mL of pH-down in 25 L.
- v1 (week 4): auto pH only. Hard limits and lockouts go into ESPHome.
- v2 (week 5): auto EC + pH and auto top-up.
- v3 (weeks 6–7): run the 7-day test, then fix the worst failure: tune deadbands, mixing time and dose size, compare top-up options A and B, and try option C dosing.
- Spring: NFT extension; isolated pH board (DFRobot DFR0504 isolator) vs alternating power. Present the results with data.
Enclosure & build
Main DWC box (BOXPLASTIC)
- Opaque PP storage box, ≈ 45 L, outer ≈ 60 × 40 × 28 cm, marked PP 05 or food-safe, black or dark grey. Avoid PVC and recycled-mix boxes. Fill to 15 cm depth ≈ 25 L (inner ≈ 56 × 36 cm, so 1 cm of depth ≈ 2 L).
- Light-proofing (algae prevention): if the box is lighter than black, wrap its outside with black/white "panda" film, white side out (it reflects light and heat). Tape over any translucent handles. Every unused hole gets a plug made from an empty net pot with tape over it. The lid must not let light reach the water.
- Lid: 8 holes for 50 mm net pots in a 4 × 2 grid, 14 cm pitch long side, 18 cm short side, ≥ 6 cm from the edges. Use a 48 mm hole saw (the net pot body is ≈ 48–50 mm and the rim ≈ 55–60 mm). Test on scrap first: the rim must sit flat and the pot must not drop through. The teacher drills on a clamped board at low speed; students deburr with a knife. Additional holes:
- 1 × 75 mm for the stilling tube (rear-left corner)
- 1 × 32 mm for the probe holder (rear-right corner)
- 1 × 16 mm grommet for air lines, pump cable, top-up line and dosing lines (rear centre). Dosing and top-up outlets end 3 cm above the water surface (air gap, no back-siphon).
- Air stones: 2 × 10 cm cylinder stones on the floor along the centre line under the plant rows, each on its own air line with a check valve. Weigh the lines down with a stainless nut.
- Circulation PUMP (12 V, 240 L/h): on rubber feet in the front-right corner, outlet aimed along the long wall to create a loop past the probes. PWM duty 70 % for less noise and splash.
- Stilling tube for JSN-SR04T: 75 mm PVC pipe, 45 cm long, standing on the box floor and passing through the lid, with 4 × 10 mm holes near the bottom and 2 × 6 mm vent holes near the top. It removes ripples and bubbles from the echo. The JSN transducer sits in a PVC end cap on top of the tube, with its face ≥ 25 cm above the maximum water level (the JSN-SR04T blind zone is ≈ 20–25 cm). Expected readings: full (15 cm depth) → ≈ 30 cm; dosing lockout (10 cm depth) → ≈ 35 cm. The level calibration table hangs on the tube.
- Probe holder: a 32 mm PVC sleeve, 20 cm long, through the lid, with a 3 mm acrylic disc at the top drilled for the pH probe (12 mm), the TDS probe (≈ 13 mm) and the DS18B20 (6 mm). Probe centres are ≥ 5 cm apart (minimum 3 cm). Tips hang 4 cm below the dosing-lockout level so they never dry out, and > 10 cm from the air stones (bubbles on the pH glass cause noise).
- Why pH and TDS interfere (ground loop) and the fix:
- The pH electrode is a ≈ 100 MΩ source whose few millivolts per pH unit are measured against the board ground (PH-4502C). The TDS module drives an AC excitation current between its two electrodes, which are also referenced to the same ESP32 ground.
- With both probes in the same conductive solution, the water becomes part of the circuit. Excitation current and any ground-potential difference (from the buck converter, or from the 12 V pump motor in the same water) flow through the pH reference junction. The pH reading then shifts by 0.1 to > 1 pH and jumps when the TDS module or the pump switches.
- Fix used here: never have both active at once. A changeover RELAY on GPIO25 powers the pH board (relay off, the default) or the TDS board (relay on). The circulation pump is off during every measurement window. Wait 30 s for pH to settle, then take a median of 10 readings. Switch to TDS, wait 10 s, take a median of 10.
- Phase-2 fix: a galvanically isolated analog board (DFRobot Gravity analog signal isolator, DFR0504) on the pH channel.
- Students prove the effect in week 4: log pH with TDS off and then on, and with the pump off and then on, and report the offset.
- Top-up RESERVOIR: 20 L food-grade canister, opaque or wrapped. It stands on the bench next to the box, not on the electrical shelf. It holds a 12 V PUMP (top-up) on the bottom and FLOAT low (dry-run cut-off) 4 cm above the pump intake. The 6 mm TUBING runs to the lid grommet. FLOAT high sits in the DWC box at 16.5 cm water depth (1.5 cm above setpoint) as an overflow cut-off. Fill with dechlorinated tap water (see Biology).
- Jar array: 9 × 2 L glass jars (Ø ≈ 13 cm) in a 3 × 3 grid on a tray, 42 × 42 cm. Each jar is wrapped in aluminium foil plus black tape, with a 2 cm vertical viewing slit covered by a tape flap. Lid: drill a 48 mm hole in the twist-off lid (teacher, step drill), then tape the cut edge. Aerated jars get a 2.5 cm air stone fed from the gang valve.
- LED panel hanging frame:
- Freestanding frame from 40 mm PVC drain pipe with tees and elbows (Dedeman/Hornbach), footprint 70 × 95 cm, height 120 cm, with feet weighted by sandbags or screwed to a board. Alternative: hang from a wall bracket.
- The LEDPANEL (45 W, COTS) hangs from 2 COTS ratchet hangers at the centre of the 60 × 85 cm growing area, 40 cm above the canopy, never < 30 cm above the lid or jar rims.
- Its cord runs up the frame with cable ties to the shelf. There it takes a drip loop and plugs into SMARTPLUG #1 on the RCD strip.
- White foam-board reflectors stand on 3 sides, 50 cm high, open at the top and front. They improve uniformity at the edges.
- Electrical shelf: ≥ 40 cm above the water line, at the back. It holds the RCD power strip, SMARTPLUG #1 (panel), SMARTPLUG #2 + AIRPUMP, PSU12 and the node BOX.
- The PERI pumps are screwed to a small board next to the node box.
- The dosing bottles sit below the PERI level in a drip tray with a raised edge, which catches any leak away from the electrics. Peristaltic pumps do not siphon when stopped.
- Every cable dropping to the water forms a drip loop below the shelf edge.
- Node BOX (IP65): ESP32 on the TERMBOARD, BUCK (12 → 5 V), 4 × MOSFET, 2 × RELAY, PH-4502C and TDS boards, JSN driver board, OLED behind a clear window (or on a short cable in the lid), and a 3 A inline fuse on the 12 V input.
- Glands (12): 1 × PG11 for the pH BNC (the BNC plug passes through the PG11 body before the cap is tightened); the rest PG7/PG9 for DS18B20, TDS probe, JSN transducer, FLOAT ×2, circulation pump, top-up pump, PERI ×3 (bundled, 2 glands), SHT31 + BH1750 (shared 4-core), and 12 V in.
flowchart LR
TAP["Tap water, dechlorinated 24 h"] --> TOP["Top-up RESERVOIR 20 L"]
TOP -->|"PUMP top-up (12 V)"| DWC["DWC box 25 L, 8 net pots"]
FLO["FLOAT low (dry-run)"] -.-> TOP
FHI["FLOAT high (overflow)"] -.-> DWC
NA["Bottle nutrient A"] -->|"PERI A"| DWC
NB["Bottle nutrient B"] -->|"PERI B"| DWC
ND["Bottle pH-down 5 percent"] -->|"PERI pH"| DWC
AIR["AIRPUMP 230 V on shelf via SMARTPLUG"] -->|"air line + check valve"| DWC
AIR -->|"gang valve"| JAR["Jar array 9 x 2 L"]
DWC -->|"circulation PUMP loop"| DWC
DWC --> PRB["Probes pH, TDS, DS18B20"]
DWC --> JSNT["JSN in stilling tube"]
PRB --> NODE["mc-07-hydro node box"]
JSNT --> NODE
NODE --> HA["Home Assistant on Pi 5"]
LED["LEDPANEL 230 V via SMARTPLUG, 40 cm above"] -.->|"light"| DWC
LED -.->|"light"| JAR
DWC -->|"every 2 weeks, drain"| OUT["Spent solution to school plants"]
Build steps (student hours; teacher does all drilling of metal and the 48 mm hole saw work)
| # | Step | Time |
|---|---|---|
| 1 | Lay out the lid on paper at 1:1, mark the holes, drill with the 48 mm hole saw, drill the 75/32/16 mm holes, deburr, test-fit pots | 2 h |
| 2 | Light-proof the box and jars (film, foil, tape), make the jar lids | 1.5 h |
| 3 | Build the PVC frame and reflectors; hang the panel; route the cord to the shelf with a drip loop (teacher checks) | 2 h |
| 4 | Mount the shelf items: RCD strip, smart plugs, node box, PERI board, dosing tray | 1 h |
| 5 | Flash the ESPHome base YAML; wire sensors on the screw terminals; bench-test all readings in a bucket of tap water | 3 h |
| 6 | Make the stilling tube and probe holder; install JSN, floats, pumps, air stones, check valves, gang valve | 2 h |
| 7 | Calibrate pH and TDS, calibrate the JSN level table, calibrate PERI flow (mL/s) and top-up pump flow (L/min) | 2 h |
| 8 | Leak test: 24 h with plain water, pumps cycling, paper towel under every joint | 1 h + 24 h |
| 9 | Fault-injection dry run (test criteria #3, #4) before the first plant goes in | 1 h |
Biology
Species
| Species | Use | Start | In DWC / jars |
|---|---|---|---|
| Lactuca sativa 'Lollo Rossa' (loose-leaf) and 'Grand Rapids' | main experimental plant, fast (5 weeks after transplant), cut-and-come-again | seed 27 Oct in rockwool | 4 DWC + all 9 jars ('Lollo Rossa' only in jars) |
| Ocimum basilicum 'Genovese' (basil) | slower; shows nutrient and temperature effects; pinch the tips | seed 27 Oct, plus 1 supermarket pot divided into 3 plugs with the soil washed off | 2 DWC |
| Mentha spicata / Mentha × piperita (mint) | roots from cuttings in 7–10 days; vigorous; tests the controller under load | 10 cm cuttings in water, 2 Nov | 2 DWC |
| Fragaria × ananassa (strawberry, day-neutral 'Albion') | spring 2027 NFT extension | runners/plants Mar 2027 | NFT |
Seed starting: Soak Grodan 36/40 rockwool plugs (or coco plugs) for 1 h in tap water adjusted to pH 5.5. Squeeze lightly and sow 2 seeds per plug. Lettuce seed needs light: press it on the surface, do not cover. Put the tray under a humidity dome at 18–22 °C, 5 cm under the edge of the panel's light. On day 7, thin to 1 seedling. From day 7, feed the plugs with quarter-strength solution (EC 0.4).
Transplant: at day 12–14 (9–10 Nov), when 2–3 true leaves show and roots come out of the plug bottom. Place each plug in a net pot and fill around it with rinsed clay pebbles. In the DWC box the water touches the net pot bottom for the first 7 days. After that, lower the setpoint by 2 cm to create a root air zone.
Nutrients (available in Romania)
- Recommended: Canna Aqua Vega A+B, 1 L each. It is a two-part recirculating-hydro formula sold by Romanian grow shops and on eMAG. The label rate is 20 mL A + 20 mL B per 10 L, which gives EC ≈ 1.2–1.4 above tap water. Add A, mix, then add B. Never mix A and B concentrates together. One 1 L set makes ≈ 500 L of solution, enough for the whole school year.
- Alternatives: GHE/Terra Aquatica TriPart (3-part), Plagron Hydro A&B, or Masterblend 4-18-38 + calcium nitrate + Epsom salt (Amazon.de). Masterblend is the cheapest per litre, and students learn to weigh salts, but it needs a 0.1 g scale and is not pH-buffered.
pH-down
- Recommended: phosphoric-acid pH-down concentrate (GHE/T.A. pH Down type, ≈ 75–85 % H₃PO₄, corrosive). The teacher dilutes it to ≈ 5 % in the prep room: acid into water, never water into acid, with goggles and nitrile gloves. Put the diluted solution in a labelled 500 mL HDPE dosing bottle. Students handle only the diluted bottle, and always with gloves and goggles.
- Citric acid alternative: 10 % w/v food-grade citric acid, which students can mix themselves. It is safe, but it biodegrades: it feeds biofilm and the pH drifts back up. Use it for manual jar adjustments only.
- pH-up: not automated. pH in lettuce DWC with Bucharest tap water normally drifts up. If it falls below 5.6, do a partial water change instead of adding caustic pH-up.
Water
- Use Bucharest tap water (Apa Nova). It is moderately hard: measure its EC (≈ 0.3–0.5 mS/cm) and pH (≈ 7.2–7.8) with the pens in week 1 and record them as the baseline.
- Dechlorinate by standing the water 24 h in the open top-up tank with a spare air stone running.
- Target EC is the total EC, including the tap water's baseline.
Target ranges: pH 5.8–6.2 (setpoint 6.0) · EC 1.0–1.4 mS/cm (lettuce 1.2; basil and mint tolerate 1.4) · water 18–22 °C (alert < 16 or > 24 °C; above 24 °C dissolved O₂ falls and Pythium root rot risk rises) · air 18–26 °C, 40–70 % RH · PPFD 200–300 µmol/m²/s at the canopy, DLI 12–17 mol/m²/day at 16 h.
Instrumentation
| Catalog ID | Qty | Placement | Interval | Purpose |
|---|---|---|---|---|
| DS18B20 | 1 | probe holder, 8 cm deep in the DWC box | 60 s | water temperature, temperature compensation for EC, root-rot alert |
| SHT31 | 1 | on the frame at canopy height + 20 cm, shaded from the panel | 60 s | air T/RH, VPD (template sensor) |
| BH1750 | 1 | at canopy height on a movable stick (1.5 m cable); fixed position = centre of the DWC lid | 60 s | lux, panel-on check, position mapping |
| JSN | 1 | top of the stilling tube | 60 s (median of 5) | continuous level, top-up control, consumption |
| FLOAT | 2 | #1 high, in the DWC box at 16.5 cm; #2 low, in the top-up reservoir | event + 60 s | overflow and dry-run hard stops |
| PHKIT | 1 | probe holder | 10-min measurement window | pH control |
| TDS | 1 | probe holder, ≥ 5 cm from pH | 10-min measurement window | EC control |
| PHPEN, TDSPEN | shared pool | handheld | daily 10:00 | cross-check, jar measurements |
| SMARTPLUG | 2 | shelf | 60 s power (W) | panel and air pump state, power-fail alert |
pH and EC are not sampled every 60 s like the other sensors. They use a 10-minute measurement window: pump off → pH powered → 30 s settle → median of 10 → TDS powered → 10 s → median of 10 → back to pH power. The window avoids the ground-loop error and the bubble noise.
Pin assignment (standard pin map only)
| Function | GPIO | Connected to |
|---|---|---|
| I2C SDA / SCL | 21 / 22 | SHT31 0x44, BH1750 0x23, OLED 0x3C |
| 1-Wire | 4 | DS18B20 water (4.7 kΩ pull-up) |
| Analog E | 36 (VP) | PH-4502C Po, through a 10 k / 20 k divider (protects the ADC from > 3.3 V); attenuation 11 dB (12db in current ESPHome) |
| Analog F | 39 (VN) | Gravity TDS analog out (0–2.3 V) |
| PWM 1 (light slot: unused, the panel is on a SMARTPLUG) | 16 | MOSFET → PERI pH-down |
| PWM 2 (fan slot: no fan in this ecosystem) | 17 | MOSFET → PERI nutrient A |
| PWM 3 (pump) | 18 | MOSFET → circulation PUMP |
| PWM 4 (heater/mister slot: unused) | 19 | MOSFET → top-up PUMP |
| Relay 1 | 23 | RELAY → PERI nutrient B (12 V, low-voltage load) |
| Relay 2 | 25 | RELAY changeover: COM = 5 V, NC → PH-4502C VCC, NO → TDS VCC (probe power selector) |
| Digital in 1 / 2 | 13 / 14 | FLOAT high (DWC) / FLOAT low (top-up), internal pull-up, switch to GND |
| Ultrasonic TRIG / ECHO | 15 / 12 | JSN-SR04T; ECHO through a 1 k / 2 k divider. GPIO12 is a strapping pin: the JSN echo idles low, so boot is safe; do not add a pull-up. |
| Reserved | 0, 2 | boot, onboard LED (blinks during dosing) |
| Unused | 5, 26, 27, 32–35 | free for phase 2 (e.g. FLOW on 5 for the NFT return) |
Use relay modules with a 3.3 V-compatible input (jumper for high/low trigger). Power the MOSFET and relay modules from 12 V and 5 V respectively, with a common GND.
ESPHome hard limits (illustrative excerpt for students to complete; these run on the node even if HA is down)
switch:
- platform: gpio
pin: GPIO16
id: peri_ph
name: "mc_07_peri_ph_down"
restore_mode: ALWAYS_OFF
on_turn_on:
- if:
condition:
or:
- binary_sensor.is_on: dosing_lockout
- lambda: 'return id(ph_dose_today_ml) >= 10.0;'
then:
- switch.turn_off: peri_ph
else:
- delay: !lambda 'return (uint32_t)(id(ph_dose_ml) / id(peri_ph_ml_per_s) * 1000);'
- switch.turn_off: peri_ph
on_turn_off:
- lambda: 'id(ph_dose_today_ml) += id(ph_dose_ml);'
# same pattern for peri_a (GPIO17), peri_b (GPIO23), topup_pump (GPIO19, max 60 s)
script:
- id: watchdog
then:
- delay: 10s # independent max-on for any PERI
- switch.turn_off: peri_ph
- switch.turn_off: peri_a
- switch.turn_off: peri_b
(Students complete the analogous blocks; the daily counters reset at 00:00 via time → on_time. The ESPHome script runs with mode: restart and is executed on every PERI turn-on.)
Calibration procedures
- pH, 2-point (weekly for the first month, then every 2 weeks, and whenever the pen check fails):
- Rinse the probe in distilled water and blot with tissue. Do not rub.
- Put it in pH 7.00 buffer at room temperature. Wait until the voltage is stable for 30 s, then record V7. On the PH-4502C, first turn the offset trimmer so that V7 is ≈ 2.50 V at the board (≈ 1.67 V at the ADC after the divider).
- Rinse, put it in pH 4.00 buffer, and record V4.
- Slope = (7 − 4) / (V7 − V4). pH = 7 + (V7 − V) × slope. Enter V7 and the slope as HA
numberentities, which are restored on the node. - Check in pH 10 or with the pen. Accept if within 0.1.
- Replace the probe if the slope is < 85 % of the theoretical value (59 mV/pH at 25 °C, before the board gain) or the response takes > 60 s.
- TDS/EC, 1-point:
- Put the probe in 1413 µS/cm standard at a known temperature (DS18B20 in the same cup).
- Compute the compensated voltage: V25 = V / (1 + 0.02 (T − 25)).
- Apply the DFRobot curve: TDS = (133.42 V25³ − 255.86 V25² + 857.39 V25) × 0.5 → EC (µS/cm) = 2 × TDS.
- Set the factor k = 1413 / EC_raw.
- Report EC in mS/cm at 25 °C. Never report "ppm": the pens may use the 500 or the 700 scale.
- Temperature compensation: both EC and the pH slope use the DS18B20 value: pH slope × (T + 273.15) / 298.15. Check the DS18B20 against an ice-water bath (0.0 ± 0.5 °C) once.
- Pens: calibrate PHPEN and TDSPEN with the same solutions on the same day as the probes. Otherwise the cross-check compares two drifting instruments.
- JSN: at 5 known volumes (add 2 L at a time with a measuring jug), record distance vs depth vs litres. Fit a straight line and put it in the YAML as
calibrate_linear. - PERI / pumps: run each for 30 s into a 100 mL graduated cylinder (3 repeats) → mL/s. Repeat monthly, because peristaltic tubing wears.
Probe maintenance
- Never let the pH probe dry. Store it in 3 M KCl storage solution in its cap. Never store it in distilled water.
- Every 2 weeks, at the reservoir change: soak the pH probe 5 min in a mild detergent solution, rinse, then soak 10 min in pH 4 buffer and recalibrate. Wipe the TDS electrodes with a soft cloth and alcohol and rinse. Check the DS18B20 cable entry for cracks.
- Do not touch the pH glass bulb. Keep it > 10 cm from the air stones.
- Expected pH probe life is 12–18 months in continuous immersion. Budget a spare probe for 2027 (≈ 60 RON).
Automation
Architecture: reflexes on the node, brain in HA.
- Node (ESPHome): measurement windows, the 10 s max-on watchdog, daily dose caps, and the hardware lockouts (FLOAT high/low, JSN low level, probe values out of range). These keep working with Wi-Fi down.
- Home Assistant: the dosing state machine, setpoints (
numberhelpers), pen-check entry (input_number+input_datetime), schedules and alerts. Students can edit all of these in the HA UI.
Dosing controller
Setpoints: pH 6.0, dose when > 6.2. EC 1.2, dose when < 1.10. Dose sizes: pH-down 1.0 mL of 5 %; A + B 3.0 mL each. In 25 L this is ≈ +0.08 mS/cm per step. Students measure and replace this in v0.
stateDiagram-v2
[*] --> Idle
Idle --> Measure: every 30 min, 07h to 21h
Measure --> Check: medians of pH and EC ready
Check --> Locked: any lockout true
Check --> DoseEC: EC below 1.10
Check --> DosePH: EC ok and pH above 6.2
Check --> Idle: all in band
Check --> AlertHigh: EC above 1.40 or pH below 5.6
DoseEC --> Mix: A 3 mL then wait 60 s then B 3 mL
DosePH --> Mix: pH-down 1 mL
Mix --> Measure: 15 min with circulation pump and air on
AlertHigh --> Idle: notify team, no automatic action
Locked --> Idle: lockout cleared by student acknowledge
The controller fixes EC first and pH second, because adding nutrient shifts pH. It makes at most one dose per Measure → Mix loop, and at most 6 dose loops per day.
Lockouts (any one blocks all dosing and sends an HA alert):
- Level < 10 cm (JSN), or the JSN reading is invalid for > 3 readings
- FLOAT low in the top-up tank (empty)
- A top-up ran less than 15 min ago (mixing not finished)
- pH outside 4.0–9.0 or EC outside 0.2–3.0 (probe fault)
- |probe − pen| > 0.3 pH or > 0.15 mS/cm at the last pen check
- Pen check older than 80 h (this allows weekends)
- Water temperature < 15 or > 26 °C
- SMARTPLUG #2 (air pump) reports < 1 W for > 5 min
- Daily cap reached (A or B 20 mL, pH-down 10 mL)
- Maintenance switch on (during the reservoir change)
Air pump: always on (SMARTPLUG #2 on; HA turns it back on if it is ever off). Alert "Air pump no power" if the plug reports < 1 W for 5 min while on, or if the plug is unavailable for 5 min. Dosing locks out in either case.
Light (SMARTPLUG #1): 16 h on / 8 h off, 06:00–22:00. HA runs the automation, and a Tasmota/ESPHome timer on the plug itself is the fallback if the hub is down.
- Alert if BH1750 < 2 000 lux for 10 min while the plug is on (panel failed).
- Alert if BH1750 > 200 lux for 10 min while the plug is off: the room lights are on at night, which spoils the photoperiod treatment.
- Panel power is logged (W). This gives kWh for the energy-per-gram calculation.
Circulation pump (GPIO18): 70 % PWM, 5 min on / 25 min off, continuous during Mix, and forced off during every Measure window and during top-up. Mid-shift, students compare EC uniformity with the pump off (air only).
Top-up (GPIO19):
- Check every 10 min. When the level is ≥ 1.0 cm below the setpoint (≈ 2 L), run the top-up pump until the level reaches the setpoint.
- Max run 60 s per activation (≈ 2–3 L at the calibrated flow). Max 4 activations / 5 L per day; more than that means a leak, so alert and lock out.
- Hard stops: FLOAT high (DWC) or FLOAT low (top-up tank), on the node.
- Dosing is inhibited for 15 min after each top-up.
- The logged litres are the plants' water consumption: DWC transpiration + evaporation.
Alerts to Home Assistant (mobile app notification to the team phone/tablet plus a dashboard banner): pH or EC out of band for > 2 h · dosing lockout (with reason) · daily cap reached · top-up tank low · overflow float · leak suspicion (top-up > 5 L/day) · water temperature out of range · air pump no power · panel failure / night light · node offline > 10 min · pen check overdue · calibration overdue (> 14 days).
Operations
Daily (school days, ≈ 10 min, duty student)
- Check the dashboard: any alerts and lockouts? Read the reason, fix it, acknowledge.
- Do the pen check at 10:00 in the DWC box: pH, EC, water temperature. Enter the values in HA and compare with the probes.
- Look: are the plants wilting or yellowing? Are the roots white? Is there algae (green film on the lid, at the holes)? Any leaks under the joints (paper towel)?
- Check the top-up tank level. Refill with dechlorinated water from the standing bucket. Re-fill the standing bucket for tomorrow.
- Jars (Mon/Wed/Fri): level, pH and EC, refill per the rule, log.
Weekly (Monday, ≈ 40 min)
- Re-randomise the jar positions (dice); map lux at all positions.
- Leaf count and height (Mon + Thu); photos (Thu).
- Check the dosing bottle levels (refill A, B and diluted pH-down; label with the date).
- Check the air stone output; replace a stone when its bubbles go coarse (≈ monthly).
- Check pH calibration against the buffer; recalibrate if off by > 0.1.
- Clean the dust off the panel (unplugged via SMARTPLUG first, by the teacher).
Reservoir change every 2 weeks (23 Nov, 7 Dec, then every second Monday; ≈ 45 min)
- Switch the maintenance mode on (all dosing and top-up locked; circulation off).
- Siphon the solution into buckets. Use it on school plants, diluted 1:1. Do not pour it into the sink concentrated.
- Lift the lid with the plants onto a support (2 bricks/blocks), keeping the roots in a tub of solution.
- Wipe the box with 3 % H₂O₂ on a cloth and rinse.
- Refill with 25 L dechlorinated water. Add 50 mL A, mix, add 50 mL B, mix 10 min. Measure EC and adjust to 1.2. Adjust pH to 6.0 with diluted pH-down.
- Replace the lid, maintenance off, log it.
- Clean the probes (see maintenance) and recalibrate.
Harvest
- Jars (R1, 14 Dec): remove each plant whole and cut at the plug. Weigh the shoot (0.1 g). Wash the roots, blot them, and weigh the root fresh mass. Put the roots in a labelled paper bag and dry them 48 h on the radiator, then weigh the dry mass (0.01 g). Photograph everything on a grid board with its label.
- DWC: harvest lettuce cut-and-come-again by taking the outer leaves (weigh per plant, per harvest), leaving the heart for regrowth. Pinch basil above the second node. Cut mint by one-third.
- Food: tasting only with the teacher's and parents' consent and after washing. Otherwise, compost the plants (link to ecosystem #1 Rot).
Safety & risks
HARD RULES applied here
- The LEDPANEL and AIRPUMP are the only 230 V items. Both are COTS with their own cord and plug, sit on (or hang from) the frame/shelf above and away from the water, and have drip loops on every cable. Both plug into SMARTPLUGs on a 30 mA RCD power strip.
- The panel hangs ≥ 30 cm above the open top (design: 40 cm above the canopy).
- Students never open, modify or rewire any 230 V item, plug or strip. The teacher plugs and unplugs them.
- Only the air line goes into the water. A check valve sits on each air line, so the water cannot siphon back into the pump.
- Everything in or near water is ≤ 12 V DC from a certified PSU12: pumps, PERI, sensors. The node box sits on the shelf above the water line, with cable glands and drip loops.
- No relay module ever switches 230 V. The two RELAYs switch only 12 V (PERI B) and 5 V (probe power).
Risks and controls
| Risk | Control |
|---|---|
| pH-down (phosphoric acid) splash on skin or eyes | The teacher dilutes the concentrate. Students use only the diluted 5 % solution, always wearing nitrile gloves and goggles. Keep an eyewash bottle and a sink nearby. Rinse a splash for 15 min. The concentrate is stored locked and labelled, outside the classroom. |
| Nutrient concentrates (irritant, oxidiser in A) | Gloves. A and B are never mixed undiluted. Bottles are labelled with pictograms; store them away from food. |
| Water + 12 V | SELV only. Fused at 3 A. Glands and drip loops. If water reaches the node box, pull the 12 V plug at the shelf (not the strip) and dry the box. |
| Leak or flood | Drip tray under the box and jars; paper-towel leak check; top-up caps (5 L/day); FLOAT high; reservoir change only in maintenance mode. |
| Overdosing | Hard 10 s max-on watchdog, daily caps, lockouts, and a dose log. Small diluted doses. Students test these in fault injection. |
| Algae | Opaque box and jars, every hole covered, panda film, no clear tubing in the light path (use black tubing or tape it). |
| Mould / root rot (Pythium) on rockwool and roots | Keep the plug tops dry. Clay pebble top-dress. Water ≤ 22 °C. Aeration always on. Reservoir change every 2 weeks. Remove any slimy, brown, smelly plant at once. |
| Rockwool fibres and dust | Wet it before handling; gloves; no cutting dry. |
| Panel heat, eye glare | Do not look into the panel. Keep it ≥ 30 cm away. Teacher only for any panel adjustment, with the plug off. |
| Lettuce bolting / tip-burn | Keep air ≤ 24 °C and EC ≤ 1.4. Use loose-leaf varieties. |
| Weekend / holiday failure | Alerts reach the teacher's phone. The 25 L DWC + 20 L top-up gives ≥ 4 days of autonomy. Before the 2-week winter break (from 19 Dec), harvest the jars, cut the DWC plants back, and set the panel to 12 h. |
Educational outcomes & assessment
| Outcome | Evidence | Assessment |
|---|---|---|
| Formulate a testable hypothesis with variables | R1 plan sheet: IV, DV, controls, n, randomisation | Rubric 1–4: clear IV/DV, valid control, replication |
| Measure carefully and estimate uncertainty | Pen vs probe log; jar measurements | Quantify the disagreement (mean difference, spread); explain one source of error |
| Analyse data | Growth curves, dot plots, effect size (t-test for liceu) | Report: claim–evidence–reasoning with figures |
| Engineering design | Requirements table, options matrix, v0 → v3 log | Test reports for the 7-day stability test and the fault injection, pass/fail per requirement |
| Systems thinking | Explain why pH drifts up and why EC rises when plants drink more water than nutrients | Oral explanation at the December presentation |
| Safe working | Chemical handling, electrical rules | Checklist sign-off before access to dosing bottles |
| Agency | Students choose the R2/R3 variable levels and propose the iteration | Team decision log; teacher notes |
Sub-BOM
Cost-cut 2026-10-20: panel hangs from the shelf above instead of a PVC frame; foil reflectors; hole saw and scale from the shared tools.
Price basis: estimates incl. VAT from Romanian shops (optimusdigital.ro, emag.ro, dedeman.ro). Nutrient price estimated from a UK listing at ≈ £16.50 (≈ 100 RON) for Canna Aqua Vega A+B 1 L; Romanian grow shops typically charge 90–120 RON, so verify before ordering. PHPEN/TDSPEN come from the shared pool and are not counted here.
| Item | Qty | Unit RON | Line RON | Basis / note |
|---|---|---|---|---|
| ESP32 | 1 | 40 | 40 | optimusdigital.ro |
| TERMBOARD | 1 | 35 | 35 | optimus / AliExpress |
| OLED | 1 | 20 | 20 | optimus |
| SHT31 | 1 | 45 | 45 | cased/membrane version |
| DS18B20 | 1 | 15 | 15 | waterproof 1 m |
| BH1750 | 1 | 15 | 15 | on 1.5 m 4-core cable |
| JSN | 1 | 45 | 45 | JSN-SR04T v3 |
| FLOAT | 2 | 10 | 20 | high (DWC) + low (top-up) |
| PHKIT | 1 | 120 | 120 | BNC probe + PH-4502C |
| TDS | 1 | 75 | 75 | Gravity analog TDS |
| CALSOL | 1 | 60 | 60 | dedicated set for this node (weekly calibrations) |
| PERI | 3 | 45 | 135 | A, B, pH-down. +1 vs the 2 approved project-wide. Fallback: 2 PERI with a one-part nutrient. |
| PUMP | 2 | 35 | 70 | circulation + top-up. Option A (float valve) needs only 1. |
| MOSFET | 4 | 8 | 32 | GPIO16–19 |
| RELAY | 2 | 8 | 16 | PERI B, probe power selector (low-voltage only) |
| PSU12 | 1 | 60 | 60 | 12 V 5 A certified |
| BUCK | 1 | 12 | 12 | 12 → 5 V |
| SMARTPLUG | 2 | 60 | 120 | with power metering (Tasmota, e.g. Nous A1T class), emag |
| LEDPANEL | 1 | 200 | 200 | 45 W full spectrum. Replaces 1 of the approved "grow lights 5–10 W". |
| AIRPUMP | 1 | 90 | 90 | 2-outlet ≈ 3–4 W, with 2 cylinder stones + air tubing |
| BOX | 1 | 35 | 35 | IP65 |
| GLAND | 12 | 2 | 24 | 1 × PG11 + PG7/PG9 mix |
| BOXPLASTIC | 1 | 70 | 70 | 45 L opaque PP, food-safe (DWC box). Counts against the approved "water reservoirs". |
| RESERVOIR | 1 | 45 | 45 | 20 L food-grade canister (top-up) |
| TUBING | 6 | 5 | 30 | 6 mm silicone, top-up + dosing |
| BIO: net pots 50 mm, pack of 50 | 1 | 35 | 35 | emag/AliExpress |
| BIO: Grodan rockwool plugs 36/40, 1 tray | 1 | 60 | 60 | grow shop |
| BIO: clay pebbles 10 L | 1 | 55 | 55 | grow shop / garden centre |
| BIO: Canna Aqua Vega A+B 1 L | 1 | 100 | 100 | see basis |
| BIO: phosphoric pH-down 250 mL | 1 | 35 | 35 | grow shop |
| BIO: citric acid 100 g (food grade) | 1 | 5 | 5 | supermarket |
| BIO: dosing bottles 3 × 500 mL HDPE + drip tray | 1 | 30 | 30 | |
| BIO: seeds (lettuce ×2, basil) + mint plant + basil pot | 1 | 35 | 35 | Agrosel/Florian packets, supermarket |
| BIO: 2 L glass jars | 9 | 8 | 72 | Dedeman/hypermarket |
| BIO: black tape + aluminium foil + panda film strip | 1 | 15 | 15 | |
| BIO: 6-way air gang valve, 6 check valves, 4 small stones | 1 | 35 | 35 | pet shop |
| BIO: pH probe KCl storage solution 250 mL | 1 | 30 | 30 | |
| BIO: 2 ratchet hangers + hooks to hang the panel from the shelf above (no PVC frame) | 1 | 30 | 30 | grow shop / dedeman.ro |
| BIO: PVC 75 mm × 0.5 m + end cap, 32 mm sleeve, acrylic offcut | 1 | 25 | 25 | stilling tube + probe holder |
| BIO: aluminium foil reflectors on cardboard | 1 | 10 | 10 | |
| BIO: 100 mL graduated cylinder + measuring jug | 1 | 25 | 25 | syringes from the approved lot |
| BIO: nitrile gloves box + 2 goggles + eyewash bottle | 1 | 50 | 50 | |
| BIO: 3 % H₂O₂ 1 L | 1 | 15 | 15 | pharmacy |
| BIO: seedling tray + humidity dome | 1 | 25 | 25 | |
| BIO: 3 A inline fuse holder + fuses | 1 | 15 | 15 | |
| Subtotal | 2 131 RON (≈ 418 EUR) | hardware 1 429 + consumables/BIO 702 |
Changes vs the approved list: PERI 3 (approved 2 for the whole project), PUMP 2 of the approved 2 (the lead must reconcile with EcoColumn and Future 2026/2056; option A float valve reduces this to 1), LEDPANEL instead of one small grow light, 2 SMARTPLUG and 1 AIRPUMP (new lines, covered by "aeration" in the items to discuss). Optional spring additions: 2nd LEDPANEL + SMARTPLUG for the photoperiod round (≈ 260 RON); DFR0504 isolator (≈ 100 RON); NFT channel 1 m + end caps (≈ 80 RON); spare pH probe (≈ 60 RON).
8-week timeline
gantt
title mc-07-hydro 26 Oct to 18 Dec 2026
dateFormat YYYY-MM-DD
axisFormat %d %b
section Plants
Order parts, baseline tap water :a1, 2026-10-26, 4d
Sow lettuce and basil in rockwool :a2, 2026-10-27, 13d
Mint cuttings rooting :a3, 2026-11-02, 9d
Transplant to DWC and jars :milestone, a4, 2026-11-09, 0d
R1 aeration experiment :a5, 2026-11-09, 35d
Reservoir change 1 :milestone, 2026-11-23, 0d
Reservoir change 2 :milestone, 2026-12-07, 0d
Harvest R1 jars, weigh, dry roots :a6, 2026-12-14, 3d
section Build and control
Lid, light-proofing, frame, shelf :b1, 2026-11-02, 5d
Node wiring, ESPHome, leak test :b2, 2026-11-04, 5d
v0 manual controller, titration :b3, 2026-11-09, 5d
Calibration and ground-loop test :b4, 2026-11-16, 3d
v1 auto pH, hard limits :b5, 2026-11-18, 5d
v2 auto EC and top-up :b6, 2026-11-23, 7d
7-day stability test :b7, 2026-11-30, 7d
v3 iterate, float valve vs pump :b8, 2026-12-07, 5d
Fault injection, commissioning :milestone, b9, 2026-12-11, 0d
section Reporting
Analysis and presentation :c1, 2026-12-14, 4d
Winter-break setup, 12 h light :c2, 2026-12-18, 1d
8. The Living Earth
Node: mc-08-soil · Enclosure: TANK63 split rhizotron · Team: 3–4 students · Alternative: 8b (mc-08b-bog)
Concept (refined)
One 60×30×35 cm glass tank is divided by a sealed acrylic wall into two 29×29 cm soil columns, both filled from the same batch of base soil:
- Half D, "Degraded": sieved, organic matter picked out, compacted to ≈1.4 kg/L, bare surface, no worms, no amendments.
- Half R, "Restored": same soil, loosened, with 20 % v/v compost and 5 % v/v charged biochar, a cover crop (rye + clover + ryegrass), earthworms, springtails, isopods and a 1 cm leaf mulch.
The front glass is a root window (rhizotron) under a removable black panel. Each half has one perforated clear observation tube (mini-rhizotron) at 45°, read with a USB/phone endoscope. A removable acrylic respiration lid with a gasket covers one half at a time. The lid carries the SCD41 and a small mixing fan, so students measure soil CO2 efflux directly (mg CO2 kg⁻¹ h⁻¹ and mg CO2 m⁻² h⁻¹). In January the team applies its best restoration recipe (from the engineering track) to Half D. It then becomes a before/after restoration experiment, with Half R as the reference, running until June 2027.
Science track
Driving question: How does degradation (compaction + organic-matter loss + bare surface) change how alive a soil is, and how fast can restoration bring that life back?
Hypotheses (directional, measurable):
| # | Hypothesis | Metric | Expected direction (R vs D) |
|---|---|---|---|
| H1 | Restored soil respires more | CO2 efflux, chamber test, dark | R ≥ 2× D |
| H2 | Restored soil takes in water faster and holds more | infiltration time (s); VWC after 48 h; drying-curve half-life | R faster infiltration, higher VWC at 48 h, slower drying |
| H3 | Restored soil has more invertebrates | Berlese counts per 100 cm³ (springtails, mites, other) | R > D by ≥ 3× |
| H4 | Roots grow deeper and longer in restored soil | root length on window grid (Tennant) and tube depth reached | R deeper/longer |
| H5 | Decomposition is faster in restored soil | Tea Bag Index k (higher) and S (lower); mass loss at 35 d | R k > D k |
| H6 | Aggregates in restored soil are more stable | slake-test class 1–6 | R ≥ D + 2 classes by spring |
Variables:
- Independent: soil treatment (D vs R). Phase 2 (Jan→): time since restoration of D.
- Dependent: CO2 efflux, VWC (SOIL probes), infiltration time, slake class, invertebrate counts, root length/depth, TBI k and S, cover-crop biomass (R only; D has phytometer plants only, see below).
- Controlled: same base soil batch; same tank, so the same room temperature, light and humidity; same watering volume per half (by mL, logged); same headspace volume and test duration; same LED photoperiod. Respiration tests are always done in the dark (LED off) at a logged soil temperature.
- Phytometer: to compare roots fairly, 5 Secale cereale seeds are sown along the front glass of both halves, plus 2 seeds beside each tube top. D gets no other plants, so its surface stays bare.
Design and replication (honest about limits):
- The tank has n = 1 per treatment (pseudo-replication). Students must say this in their report. Replication comes from:
- Repeated measures: ≥ 2 respiration tests per half per week, with the order alternated (D first / R first) to cancel time-of-day and room-CO2 drift.
- Subsamples: 4 tea-bag pairs per half; 2 Berlese cores per half per date; 3 slake aggregates per half; 2 infiltration spots per half.
- True replicates: the engineering screening pots (6 treatments × 3 replicates, see Engineering track).
- Tea Bag Index (TBI, Keuskamp et al. 2013, Methods in Ecology and Evolution; citizen-science protocol at teatime4science.org). Two commercial teas are standard "litter": Lipton green tea (EAN 8 722700 055525), which is fast and labile, and Lipton rooibos (EAN 8 722700 188438), which is slow and recalcitrant. Pairs are buried at 8 cm depth for 90 days, then dried and weighed. After 90 days green tea has stopped decomposing its labile part, while rooibos is still in the early phase. This gives two numbers:
- S (stabilisation factor): how much of the labile material the soil "locked away" instead of decomposing. Lower S means more complete decomposition.
- k (decomposition rate constant, d⁻¹): how fast fresh litter breaks down. Higher k means a more active decomposer community.
- Formulas (W = remaining mass fraction of tea content, t in days, Hg = 0.842 and Hr = 0.552 are the hydrolysable fractions of green and rooibos tea):
- ag = 1 − Wg(t) (decomposed fraction of green tea)
- S = 1 − ag / Hg
- ar = Hr × (1 − S) (predicted labile fraction of rooibos)
- k = ln( ar / (Wr(t) − (1 − ar)) ) / t
- Sample calculation: Wg = 0.35 → ag = 0.65 → S = 1 − 0.65/0.842 = 0.228 → ar = 0.552 × 0.772 = 0.426. Wr = 0.78 → Wr − 1 + ar = 0.206 → k = ln(0.426/0.206)/90 = 0.727/90 = 0.0081 d⁻¹.
- Procedure:
- Number each bag with a permanent marker on the label.
- Weigh each whole bag to 0.01 g. Weigh 5 empty bags (opened, tea removed) with string and label to get the mean empty-bag mass. Initial tea mass = bag mass − mean empty mass.
- Bury upright at 8 cm depth with the label outside the soil.
- Retrieve, brush off soil and roots, dry at 70 °C for 48 h (school oven or food dehydrator, adult operates), open and weigh the tea content only.
- Caveat: Lipton changed its bag material from woven nylon to a non-woven mesh. A 2022 study found TBI values may be biased with non-woven bags. Check the current EAN/bag note on teatime4science.org and treat k and S as relative (R vs D), not absolute.
- Bags have to stay buried for 90 days, so the full TBI result arrives in February. A 35-day set gives a December comparison (mass loss only, no k/S).
- Respiration (SCD41 closed chamber): the protocol is under Instrumentation. Units: R_kg in mg CO2 kg⁻¹(dry soil) h⁻¹ and F in mg CO2 m⁻² h⁻¹.
- Berlese–Tullgren funnel: 2 cores per half (PVC Ø 50 mm × 50 mm ≈ 100 cm³), 0–5 cm depth.
- Core sits on a 2 mm mesh in a PET-bottle funnel under a COTS desk lamp for 72 h.
- Animals fall into a jar with a damp plaster/charcoal base, so they are collected alive.
- Count under a 10× loupe in 3 groups: springtails, mites, other (isopods, larvae, enchytraeids, worms).
- Return animals and soil to the core hole within 24 h.
- Infiltration (single ring): PVC ring Ø 110 mm (inner area ≈ 82 cm²), pushed 2 cm into the surface at 2 marked spots per half.
- Pour 200 mL (≈ 25 mm) at once and time until no free water is visible.
- Counts as part of that half's watering; log the volume.
- Slake test (Herrick et al. 2001 classes): 3 air-dried aggregates of 6–8 mm per half are placed on a 2 mm mesh (tea strainer) and lowered into a jar of water.
- Class 1 = > 50 % of aggregate lost in 5 s.
- Class 2 = > 50 % lost in 5–30 s.
- Class 3 = > 50 % lost in 30–300 s, or < 10 % left after 5 dips.
- Class 4 = 10–25 % left after 5 dips.
- Class 5 = 25–75 % left after 5 dips.
- Class 6 = > 75 % left after 5 dips.
- Aggregates are taken from the surface 0–2 cm, away from tubes and the window.
- Water retention:
- (a) Continuous VWC from SOIL probes: after a standard watering of 500 mL per half, fit the drying curve (time for VWC to drop half-way back to its pre-watering value).
- (b) Lab "field capacity" on screening cups: saturate, drain 24 h with the top covered, weigh, then oven-dry. FC = water g per g dry soil.
Sampling schedule (2026; continues monthly to June 2027):
| Measure | Frequency | Dates (2026) |
|---|---|---|
| Sensors (VWC, T, RH, lux, CO2 ambient) | every 60 s, automatic | from Nov 9 |
| Respiration test D and R | 2× per week (Tue + Thu) | from Nov 17 |
| Root window photo + grid count | weekly (Mon) | Nov 16, 23, 30; Dec 7, 14 |
| Tube endoscope photos | weekly (Mon) | same as above |
| Infiltration | every 2 weeks | Nov 12 (baseline), Nov 26, Dec 10 |
| Slake test | monthly | Nov 6 (base soil, before split), Dec 10 |
| Berlese extraction | baseline + monthly | Nov 9 (base soil), Dec 7–10, then Jan 11, Feb 8… |
| Tea bags | bury Nov 10 | 35-day set retrieved Dec 15; 90-day set Feb 8, 2027 |
| Cover crop height/biomass | weekly height; clipped biomass monthly | from Nov 23 |
| pH / EC (handheld PHPEN/TDSPEN, 1:5 soil:water extract) | monthly | Nov 6, Dec 10 |
Analysis:
- Grafana panels show VWC D vs R, soil T D vs R, and CO2 during tests.
- The nightly CSV goes to a spreadsheet. Students plot each metric over time with D and R on the same axes.
- For repeated measures (respiration), report the mean ± SD of all tests per half per fortnight, the ratio R/D, and a paired difference per test day.
- Screening pots (n = 3) get mean ± SD per treatment and a simple ranking. Older students can add a one-way ANOVA or Kruskal–Wallis test in a spreadsheet.
- Respiration slope quality: report R² of every chamber regression. Reject tests with R² < 0.90 or a lid-open event.
What shows by mid-December vs spring:
| By Dec 15, 2026 | By spring (Mar–Jun 2027) |
|---|---|
| Respiration R ≫ D (compost effect is immediate) | Whether the R/D ratio persists after compost carbon is spent |
| Infiltration and drying-curve differences (compaction effect is immediate) | Slake-class change: real aggregate building by roots, fungi, worms |
| First roots on window/tubes; depth reached in 4–5 weeks | Full root architecture; worm burrows on the window |
| Berlese counts #2 (introduced springtails established in R?) | Colonisation of D after its restoration in January |
| 35-day tea mass loss (green tea already differs) | Full TBI k and S (Feb 8) plus a second TBI round in D after restoration (Feb → May) |
Engineering track
Problem statement: A compacted, organic-poor, bare urban soil (Half D) barely respires, sheds water and has few animals. Design a restoration method that a school or city could apply. It must be cheap, scalable, use local materials, and work within one season.
Requirements (measurable):
| ID | Requirement | Target |
|---|---|---|
| R1 | Infiltration | 200 mL disappears in < 60 s (D baseline expected > 5 min) |
| R2 | Water held 48 h after watering | VWC ≥ 1.3× untreated control |
| R3 | Biological activity | CO2 efflux ≥ 2× control at the same soil T, 4 weeks after treatment |
| R4 | Structure | slake class ≥ 4 by 8 weeks |
| R5 | Plant establishment | cress germination ≥ 80 % and shoot dry mass ≥ 1.5× control at 14 d |
| R6 | Cost and sourcing | ≤ 5 RON per 10 L of treated soil, materials available in Bucharest |
| R7 | No harm | no added synthetic fertiliser; only organic/mineral inputs listed in Biology |
Candidate solutions (screened first in pots, then the winner goes into Half D):
| Code | Treatment (per 0.5 L cup of degraded soil) | Mechanism tested |
|---|---|---|
| C0 | Control: degraded soil only | — |
| A1 | Compost 20 % v/v mixed into top 5 cm | food for microbes, porosity |
| A2 | Biochar 5 % v/v (pre-soaked 48 h in compost tea) + compost 10 % | stable carbon, water holding |
| M1 | 1 cm chopped-leaf mulch on surface | evaporation, food for surface fauna |
| P1 | Cover crop: 10 Secale + pinch Trifolium sown | living roots, root exudates |
| X1 | Aeration: 6 holes Ø 5 mm × 5 cm with a skewer, refilled with compost | breaking compaction |
- 6 treatments × 3 replicates = 18 clear 0.5 L cups with drainage holes, on 2 trays under the same LED.
- Earthworms are not put in cups (welfare: too small a volume). The worm effect is studied only in the tank.
Test criteria:
- R1 infiltration: cup version uses 50 mL poured into the cup.
- R2: weigh cups at saturation and after 48 h.
- R4 slake.
- R5 cress test: 20 Lepidium sativum seeds per cup on day 21, harvested on day 35.
- R6: cost.
- Each criterion is scored 0–3 in a weighted decision matrix: biology 30 %, water 30 %, structure 20 %, cost 20 %.
Iteration plan:
- v1 (Nov 16 – Dec 18): screen 6 single treatments in cups; pick the top 2.
- v2 (Jan 11 – Feb 7): combine the top 2 (e.g. A2 + P1) and test 3 doses in cups (n = 3).
- v3 (Feb 8): apply the best v2 recipe to Half D after retrieving its 90-day tea bags. Bury a new TBI set in both halves. Track D's recovery against R until June.
- Document every iteration on a one-page "design card": change, reason, result, next step.
- Optional phase 2 automation: a servo-closed respiration port, so tests run unattended overnight.
Enclosure & build
Tank: TANK63 (60×30×35 cm, ≈ 63 L, rimless glass, ≈ 14 kg empty).
- Internal ≈ 59×29 cm. With a 3 mm divider, each half is ≈ 29×29 cm (area A = 0.0841 m²).
- Weight when filled ≈ 55 kg (2 × ~17 L soil + LECA + water). It is placed once, on a sturdy bench, and never moved filled.
Layers, bottom to top (each half):
- 3 cm LECA (expanded clay) drainage.
- Geotextile fleece.
- 20 cm soil, filled in 4 lifts of 5 cm:
- D lifts tamped with a 2 kg rammer (brick in a bag, 10 drops per lift, target dry bulk density 1.4 kg/L).
- R lifts lightly firmed by hand (≈ 1.0 kg/L).
- R only: 1 cm leaf mulch.
- Headspace ≈ 12 cm to the rim.
Fittings:
- Drainage well: one vertical PVC tube Ø 20 mm per half in the back corner, down to the LECA. Check for standing water with a 60 mL syringe and tubing. The glass has no outlet, so this is the only way to remove excess water.
- Divider: 3 mm ACRYLIC, 29×35 cm, siliconed to the bottom and both side glasses, full height to the rim. It keeps worms out of D and gives the lid a sealing edge.
- Root window: the front glass. Draw a 2 cm grid with a permanent marker on the outside.
- Cover it with a black corrugated-PP panel (velcro, removable). Cover the back and side glass with fixed black panels, because roots also grow along those walls and light disturbs them.
- Open the front panel only for weekly photos (≤ 5 min).
- Observation tubes: the 2 approved perforated clear tubes, one per half, inserted at 45° from vertical, slanting towards the centre so the bottom ends ≈ 18 cm deep.
- Bottom capped with MESH + silicone. If the holes are > 3 mm, wrap the tube in one layer of fibreglass MESH so roots and springtails can enter but loose soil cannot.
- Install the tubes during filling, not by pushing them in later, to avoid gaps at the tube wall.
- The top stands 5 cm above soil with a black cap, and the exposed tube is wrapped in black tape.
- Mark depth every 3 cm on the endoscope's guide rod (a 10 mm PVC rod with the camera taped at the tip).
- Respiration lid (student build):
- 32×32 cm clear 3 mm ACRYLIC plate. EPDM foam gasket (9×4 mm) runs around the underside, ≈ 1 cm in from the edge, so it lands on the glass rim (3 sides) and the divider top (1 side).
- Underneath: the SCD41 (in a small perforated holder, 3 cm below the lid) and the 80 mm FAN (on 4 spacers, blowing horizontally, 30 % PWM).
- On top: a magnet that triggers the reed switch on the rim, so firmware knows the lid is on.
- One flat cable bundle (SCD41 4-wire + fan 2-wire + reed 2-wire, 1.5 m) leads to the node box through a GLAND, with a JST-SM connector so the lid can be unplugged.
- Seal by 2 spring clamps or 2 × 0.5 L water bottles on the lid.
- A second plain mesh-framed cover (MESH on a 32×32 acrylic frame with a 25×25 cut-out) sits on the half not under test, to keep gnats, isopods and worms in.
- Light bridge: 2 LEDPROFILE pieces, 55 cm each, carrying ≈ 1.1 m of 12 V LEDSTRIP in two rows, 8 cm apart.
- They sit on two 20 cm acrylic/PVC posts clamped to the tank ends, so the strip is ≈ 15 cm above the rim and the lid slides underneath.
- ≈ 16 W at 100 %.
- Node box: BOX on the wall/shelf behind and above the tank. Inside: ESP32 on TERMBOARD, BUCK, 2 MOSFET, OLED in the lid window, PSU12 plug in, and 6 GLANDs on the underside with drip loops. The PSU12 brick and RCD power strip sit on the shelf, never on the bench beside the tank.
flowchart TD
PSU["PSU12 brick on shelf (RCD strip)"] --> BOX["Node box mc-08-soil (ESP32 + TERMBOARD + BUCK + 2 MOSFET + OLED)"]
BOX -->|"PWM1 GPIO16"| LED["LED bridge 1.1 m strip (12 V)"]
BOX -->|"I2C + PWM2 GPIO17 + GPIO13"| LID["Respiration lid (SCD41 + FAN + reed magnet)"]
BOX -->|"I2C"| SHT["SHT31 on light bridge"]
BOX -->|"I2C"| LUX["BH1750 on divider top, back"]
BOX -->|"1-Wire GPIO4"| T["DS18B20 x2 at 10 cm (D and R)"]
BOX -->|"ADC 32/33/34"| SM["SOIL A (D 5 cm), B (R 5 cm), C (D 15 cm)"]
subgraph TANK["TANK63 split rhizotron"]
D["Half D degraded (compacted, bare)"]
R["Half R restored (compost, biochar, cover crop, worms)"]
W["Front root window (black panel, 2 cm grid)"]
TU["Observation tubes 45 deg, one per half"]
end
LID -.->|"placed on D or R"| TANK
LED --> TANK
Build steps (student hours, team of 3–4):
| # | Step | Time |
|---|---|---|
| 1 | Check tank for leaks (fill 5 cm water, 24 h, empty, dry) | 0.5 h + 24 h wait |
| 2 | Cut acrylic: divider 29×35, lid 32×32, mesh-cover frame 32×32 (score-and-snap or teacher with jigsaw; deburr) | 2 h |
| 3 | Silicone divider in place; cure 24 h | 1 h + 24 h |
| 4 | Black panels for back/sides (fixed, double-sided tape) and front (velcro); draw 2 cm grid on front glass | 1.5 h |
| 5 | Prepare tubes: cap bottoms with mesh, black tape on exposed part, depth marks; drainage wells | 1 h |
| 6 | Collect and sieve soil (5 mm), mix the batch, take baseline samples (moisture, pH/EC, slake, Berlese) | 3 h |
| 7 | Fill D: LECA, fleece, 4 compacted lifts, set tube at 45° and SOIL/DS18B20 probes during filling; weigh all soil added | 2 h |
| 8 | Fill R: mix compost + biochar into the soil, 4 loose lifts, tube and probes, weigh all soil | 2 h |
| 9 | Lid: gasket, SCD41 holder, fan spacers, magnet, cable + JST; reed switch on rim | 2.5 h |
| 10 | Light bridge and LED strip (solder pads with pre-tinned wires by teacher, or use clip connectors) | 2 h |
| 11 | Node box: TERMBOARD, BUCK set to 5.0 V (measure before connecting ESP32), MOSFETs, glands, labels | 3 h |
| 12 | Flash ESPHome, adopt in Home Assistant, calibrate sensors | 3 h |
| 13 | Leak test of lid (see Instrumentation) | 1 h |
| 14 | Biology: sow cover crop, add worms/springtails/isopods, mulch, bury tea bags | 1.5 h |
| Total | ≈ 27 h + cure/wait times |
Biology
Soil source:
- Collect ≈ 60 L (enough for the tank plus cups) of topsoil 0–15 cm from the school garden, or from a park/forest edge with written permission from the owner/administrator.
- Collect ≥ 20 m from roads (lead/tyre dust). Avoid dog-walking areas (Toxocara eggs).
- Prefer a loam: it should hold shape when squeezed moist and crumble under a finger.
- Do not use bagged sterile potting compost or peat as the base. It has almost no soil fauna or mineral structure, so there would be nothing to "degrade".
- Backup: one 50 L bag of garden soil ("pământ de grădină") from Dedeman/Hornbach, inoculated with 1 L of fresh forest litter and soil.
Amendments (Half R and cups):
- Compost or vermicompost ("biohumus", bagged, 20 L).
- Biochar: bagged horticultural biochar, or untreated lump charcoal crushed to 2–10 mm. Never briquettes (binders and accelerants).
- Charge biochar 48 h in compost tea before use, or it will absorb nutrients from the soil for weeks.
Fauna (Half R only at start):
| Organism | Role | Qty in R | Source (Romania) |
|---|---|---|---|
| Aporrectodea caliginosa / Allolobophora chlorotica (endogeic garden worms) | burrow in mineral soil, mix | 6 | dig from school garden when collecting soil (free) |
| Lumbricus terrestris (anecic nightcrawler) | vertical burrows, pull litter down; visible on window | 2 | fishing shops sell them as "râme canadiene" (≈ 25–35 RON per box of 20–25); keep the rest in a cool box of damp soil and release in the garden |
| Eisenia fetida (epigeic red worm, "râmă californiană / roșie") | lives in mulch/compost layer only, not deep mineral soil | 5 | vermicompost farms via OLX/eMAG ("râme californiene"), or fishing shops; ≈ 30–40 RON per small culture |
| Folsomia candida (springtails, "colembole") | fungal grazers, Berlese indicator | ½ culture (≈ 100+) | terrarium/exotic pet shops and OLX ("colembole cultură"); ≈ 25–40 RON |
| Porcellio scaber / Armadillidium vulgare (isopods) | shred litter on surface | 6 | collect under stones/wood in the school yard (native, free) |
- Stocking density: 13 worms per 0.084 m² ≈ 150 per m², which is typical of a good grassland.
- Eisenia is epigeic and dies in compacted mineral soil. That is why the mineral layer gets native endogeic worms and L. terrestris.
Cover crop (Half R):
- Mix: Secale cereale (winter rye) 3 g, Trifolium repens (white clover) 0.3 g and Lolium perenne (perennial ryegrass) 0.5 g, sown on Nov 10 and raked 5 mm in.
- Seed from agricultural/garden shops or eMAG.
- Clip ("mow") to 10 cm whenever it exceeds 15 cm, so it stays below the lid and light bridge. Dry and weigh the clippings: this is the biomass data.
- Phytometer plants in D: see Science track.
Establishment:
- Fill both halves and water each to ≈ 60 % of the field capacity measured on base-soil cups.
- Wait 3 days.
- Add fauna in the evening with the LED off. Worms are placed on the surface and must burrow within 30 min; remove and replace any that do not.
- Apply mulch, sow, and bury the tea bags (Nov 10).
Invertebrate welfare:
- Soil kept at 15–24 °C (room, logged by the DS18B20s) and VWC 25–40 %. Never waterlogged: check the drainage well weekly.
- Darkness on all glass except during photos.
- Berlese collection is live (damp plaster base, no alcohol) and animals are returned within 24 h. Max 2 cores per half per month.
- No worms in screening cups.
- End of project: worms and isopods are released into the school garden. Springtails and the soil go to the garden compost heap.
- Do not release L. terrestris bought from shops if they might be non-local stock. Instead keep them in the tank or a worm bin. Eisenia is already widespread in Romanian compost heaps.
Instrumentation
| Catalog ID | Qty | Placement | Interval | Purpose |
|---|---|---|---|---|
| SOIL | 3 | A: Half D at 5 cm; B: Half R at 5 cm; C: Half D at 15 cm (deep/compacted layer, shows perched water) | 60 s (mean of 10 samples) | VWC, drying curves, watering trigger |
| DS18B20 | 2 | 10 cm depth, centre of D and centre of R | 60 s | soil T for respiration normalisation, welfare |
| SCD41 | 1 | under the respiration lid (3 cm below plate); when the lid is parked on its shelf hook beside the tank: ambient room CO2 | 60 s (normal), 60 s during tests (25–55 points per test) | chamber CO2 slope, plus T/RH inside chamber |
| SHT31 | 1 | on the light bridge, 15 cm above the rim, shielded from the strip by the profile | 60 s | room air T/RH beside the tank |
| BH1750 | 1 | top of divider at the back, facing up, at the rim level | 60 s | LED on/off verification, light dose (lux; not PAR, relative only) |
| FAN | 1 | under the respiration lid | on only during tests, 30 % PWM | mix headspace |
| Reed switch (free-text) | 1 | rim of tank; magnet on lid | event | lid-on detection |
| OLED | 1 | node box window | 2 s page cycle | live values, test countdown |
| SERVO | 1 (phase 2) | respiration-port flap | event | unattended tests later |
Pin assignment (standard pin map only):
| Function | GPIO | Device |
|---|---|---|
| I2C SDA / SCL | 21 / 22 | SCD41 0x62, SHT31 0x44, BH1750 0x23, OLED 0x3C (bus at 50 kHz because of the 1.5 m lid cable) |
| 1-Wire | 4 | DS18B20 D and R (4.7 kΩ to 3.3 V) |
| Analog A / B / C | 32 / 33 / 34 | SOIL A (D 5 cm), B (R 5 cm), C (D 15 cm) |
| PWM out 1 | 16 | MOSFET to LED strip |
| PWM out 2 | 17 | MOSFET to lid FAN |
| Digital in 1 | 13 | lid reed switch (pull-up, closed to GND = lid on) |
| Servo 1 | 26 | phase 2 port flap |
| Free | 35, 36, 39, 18, 19, 23, 25, 27, 14, 5, 15, 12 | spare (e.g. SOIL D for R 15 cm if a 4th probe is added) |
Calibration:
- SOIL (per probe, in this soil):
- Record raw V in air.
- Record raw V in oven-dried soil (70 °C, 24 h) packed into a 0.5 L cup at the same density as its half.
- Record raw V in saturated soil.
- Add 3 intermediate gravimetric points: add known water, then VWC = water mL / soil volume mL.
- Fit linear or 2-segment calibration in ESPHome
calibrate_linear. - Seal the probe top edge and PCB with conformal coating plus heat-shrink before use.
- DS18B20: ice-water bath (0 °C) and room-water against a reference thermometer; offset in YAML. Accept ±0.3 °C.
- SCD41:
- Disable automatic self-calibration (ASC). The chamber regularly reaches > 1000 ppm and the classroom rarely drops to 400 ppm, so ASC would drift.
- Do a forced recalibration outdoors (school yard, calm air, 5 min running, then FRC at 420 ppm) on Nov 13 and then monthly.
- Log every FRC in the lab book.
- BH1750: relative only. Compare with a phone lux app on day 1 to sanity-check the order of magnitude.
- Chamber leak test (Nov 19):
- Place the lid on Half D with soil covered by a sealed plastic sheet (so no soil respiration).
- Exhale gently into the headspace through the reed gap until CO2 is ≈ 2000 ppm, then close.
- Log 30 min. A leak-free chamber holds within ±50 ppm. Record the decay rate (ppm/h) as the leak correction: added back to measured slopes, or the gasket is redone if > 10 % of a typical D slope.
- Headspace volume V:
- Measure on each half at 5 points from the soil surface to the lid underside (mean h, cm). V = 29 × 29 × h / 1000 L, minus 0.2 L for sensor, fan and plants (add measured plant volume when the cover crop grows: clip before tests, or estimate by water displacement of clippings).
- Re-measure monthly, because the soil settles.
- Dry soil mass m: soil mass added to each half × (1 − gravimetric water fraction of the filling batch). Gravimetric water fraction comes from 3 subsamples dried at 105 °C for 24 h (or 70 °C for 48 h).
Respiration test protocol (one half, ≈ 45 min):
- Check the last watering was ≥ 24 h ago. Watering pulses CO2 out of the pores; log hours since watering.
- On the HA dashboard: select chamber position D or R, check that the V and m numbers are current, and press Start respiration test.
- Place the lid on that half within 2 min: gasket on rim and divider, 2 clamps or bottles on top. The reed switch must show "lid on", or the test will not start measuring.
- Firmware automatically:
- switches the LED off (dark test, to exclude photosynthesis);
- runs the fan at 30 %;
- discards 5 min (mixing/equilibration);
- collects 30 min of CO2 readings, extended to 60 min for Half D if the rise is < 150 ppm after 30 min;
- fits a linear regression;
- publishes slope (ppm/h), R², R_kg and F;
- restores the LED according to the schedule;
- sends a "done" notification.
- Remove the lid, ventilate 5 min (or wait until ambient CO2 is back to within 50 ppm of the pre-test value), then test the other half.
- Alternate which half goes first on each test day.
Formula:
ρCO2 (mg/L) = P × M / (R × T) = 101325 × 44.01 / (8.314 × TK) (≈ 1830 mg/L at 20 °C; use the chamber T from SCD41)
Mass rate (mg CO2/h) = slopeppm/h × 10⁻⁶ × VL × ρCO2
- R_kg (mg CO2 kg⁻¹ h⁻¹) = mass rate / mkg dry soil
- F (mg CO2 m⁻² h⁻¹) = mass rate / Am², with A = 0.0841 m²
Sample calculation (Half R):
- Slope 1500 ppm/h, R² = 0.98, chamber T = 21 °C → ρ = 101325 × 44.01 / (8.314 × 294.15) = 1823 mg/L.
- V = 10.0 L (12.0 cm mean headspace × 841 cm² = 10.1 L − 0.1 L).
- Mass rate = 1500 × 10⁻⁶ × 10.0 × 1823 = 27.3 mg CO2/h.
- m = 16.0 kg dry soil → R_kg = 1.71 mg CO2 kg⁻¹ h⁻¹. A = 0.0841 m² → F = 325 mg CO2 m⁻² h⁻¹, within the range of field soils (≈ 100–1000).
- For Half D, expect 150–500 ppm/h. The 30 min rise is then 75–250 ppm, well above SCD41 repeatability (±10 ppm).
- The cover crop in R respires too, so this is "soil + root" respiration. Students should note it. An extension is a test right after clipping, compared with a test before clipping.
- SCD41 accuracy is ±(50 ppm + 5 % of reading) between 400 and 5000 ppm. The test aborts or stops early above 5000 ppm.
Automation
ESPHome core (excerpt; full file mc-08-soil.yaml):
esphome: { name: mc-08-soil }
i2c: { sda: 21, scl: 22, frequency: 50kHz }
one_wire: [{ platform: gpio, pin: 4 }]
globals:
- { id: resp_state, type: int, initial_value: '0' } # 0 idle, 1 mixing, 2 measuring
- { id: t0, type: uint32_t, initial_value: '0' }
- { id: sn, type: double, initial_value: '0' }
- { id: st, type: double, initial_value: '0' }
- { id: sc, type: double, initial_value: '0' }
- { id: stt, type: double, initial_value: '0' }
- { id: stc, type: double, initial_value: '0' }
- { id: scc, type: double, initial_value: '0' }
sensor:
- platform: scd4x
automatic_self_calibration: false
update_interval: 60s
co2:
id: co2
name: "mc_08_co2_chamber"
on_value:
then:
- lambda: |-
if (id(resp_state) == 2) {
double t = (millis() - id(t0)) / 3600000.0; // hours
id(sn) += 1; id(st) += t; id(sc) += x;
id(stt) += t*t; id(stc) += t*x; id(scc) += x*x;
}
if (id(resp_state) == 2 && x > 5000) id(resp_finish).execute();
temperature: { id: ch_t, name: "mc_08_air_temp_chamber" }
humidity: { name: "mc_08_air_humidity_chamber" }
- { platform: template, id: slope, name: "mc_08_resp_slope", unit_of_measurement: "ppm/h" }
- { platform: template, id: r2, name: "mc_08_resp_r2" }
- { platform: template, id: rkg, name: "mc_08_resp_rate_kg", unit_of_measurement: "mg/kg/h" }
- { platform: template, id: fm2, name: "mc_08_resp_flux_m2", unit_of_measurement: "mg/m2/h" }
number:
- { platform: template, id: vol_l, name: "mc_08_headspace_l", min_value: 2, max_value: 20, step: 0.1, optimistic: true, restore_value: true, initial_value: 10 }
- { platform: template, id: m_kg, name: "mc_08_dry_soil_kg", min_value: 1, max_value: 40, step: 0.1, optimistic: true, restore_value: true, initial_value: 16 }
binary_sensor:
- platform: gpio
id: lid_on
name: "mc_08_lid_on"
pin: { number: 13, mode: INPUT_PULLUP, inverted: true }
on_release: # lid lifted
- if:
condition: { lambda: 'return id(resp_state) > 0;' }
then: [ script.stop: resp_test, lambda: 'id(resp_state) = 0;', text_sensor.template.publish: { id: status, state: "ABORTED lid open" } ]
button:
- { platform: template, name: "mc_08_resp_start", on_press: [ script.execute: resp_test ] }
script:
- id: resp_test
mode: single
then:
- wait_until: { condition: { binary_sensor.is_on: lid_on }, timeout: 120s }
- if: { condition: { binary_sensor.is_off: lid_on }, then: [ text_sensor.template.publish: { id: status, state: "ABORTED no lid" }, script.stop: resp_test ] }
- light.turn_off: grow
- output.set_level: { id: fan_out, level: 30% }
- lambda: 'id(resp_state) = 1; id(sn)=id(st)=id(sc)=id(stt)=id(stc)=id(scc)=0;'
- text_sensor.template.publish: { id: status, state: "MIXING" }
- delay: 5min
- lambda: 'id(t0) = millis(); id(resp_state) = 2;'
- text_sensor.template.publish: { id: status, state: "MEASURING" }
- delay: 30min
- script.execute: resp_finish
- id: resp_finish
then:
- lambda: |-
id(resp_state) = 0;
double n=id(sn), d = n*id(stt) - id(st)*id(st);
if (n < 10 || d <= 0) { id(status).publish_state("FAILED too few points"); return; }
double b = (n*id(stc) - id(st)*id(sc)) / d;
double rnum = n*id(stc) - id(st)*id(sc);
double rden = sqrt(d * (n*id(scc) - id(sc)*id(sc)));
double rho = 101325.0*44.01/(8.314*(id(ch_t).state + 273.15)); // mg/L
double mg_h = b * 1e-6 * id(vol_l).state * rho;
id(slope).publish_state(b); id(r2).publish_state(rden > 0 ? (rnum/rden)*(rnum/rden) : 0);
id(rkg).publish_state(mg_h / id(m_kg).state); id(fm2).publish_state(mg_h / 0.0841);
id(status).publish_state("DONE");
- output.set_level: { id: fan_out, level: 0% }
- script.execute: led_restore # turns grow light on if inside 0600-2000 window
- Not shown in the excerpt:
output(ledc GPIO16 1 kHz, GPIO17 25 kHz),lightgrow,text_sensorstatus, theled_restorescript and the SOIL/DS18B20/SHT31/BH1750 sensors. All follow the shared node template. - 30 min at 60 s gives ≈ 30 points.
- The "extend to 60 min" option is a second button,
mc_08_resp_start_long, using the same script withdelay: 60min. - Home Assistant:
- an
input_selectmirrors the chamber position D/R; - an automation on
sensor.mc_08_resp_rate_kgchange writes a logbook entry ("Resp test R: 1.71 mg/kg/h, R² 0.98, soil T 19.8 °C") and sends a mobile-app/persistent notification "Respiration test done — remove lid"; - InfluxDB stores everything;
- a second automation alerts if status = ABORTED.
- an
- Watering alert: HA notifies when SOIL A or B VWC < 22 % (2-h mean). Watering stays manual by design: it is an experimental variable and must be logged in mL.
stateDiagram-v2
[*] --> Night
Night --> Day : 0600 schedule
Day --> Night : 2000 schedule
Day --> TestArmed : start button pressed
Night --> TestArmed : start button pressed
TestArmed --> Mixing : lid switch closed within 2 min
TestArmed --> Aborted : no lid after 2 min
Mixing --> Measuring : 5 min elapsed, LED off, fan 30 pct
Measuring --> Computing : 30 or 60 min elapsed
Measuring --> Computing : CO2 above 5000 ppm
Mixing --> Aborted : lid opened
Measuring --> Aborted : lid opened
Computing --> Done : slope, R2, rates published
Done --> Day : LED restore inside photoperiod
Done --> Night : LED restore outside photoperiod
Aborted --> Night : notify and restore
- LED schedule: 14 h on (06:00–20:00), 100 % PWM. Soft start over 10 min via ESPHome
default_transition_length. - Phase 2 (Feb–Mar 2027, optional): a second, permanently mounted lid on Half R with a 6 cm round port. An SG90 on GPIO26 closes the port with a gasketed flap, so tests run at 02:00 nightly (both halves need a lid, so in practice R only, or two lids and a second SCD41 from spares). Requires a flap leak test as above.
Operations
Daily (2 min, any team member):
- OLED shows Wi-Fi OK and all 7 values.
- LED on in the day window.
- No condensation pooling on the glass.
- No escaped isopods/worms on the rim.
Twice weekly (Tue/Thu, 25 min):
- Respiration test D and R (order alternated).
- Check logbook entry and R² ≥ 0.90.
- Record hours since last watering.
Weekly (Mon, 30 min):
- Remove front panel. Photograph the root window with the phone on a fixed stand at 40 cm, plus a 2 cm-grid close-up per half. Replace the panel within 5 min.
- Endoscope in each tube: photo at every 3 cm mark (3, 6, 9, 12, 15, 18 cm), camera facing upward-out, LED on. Note roots, hyphae, animals.
- Root count: Tennant line-intersect, L = (11/14) × N × G (N = root crossings with grid lines, G = 2 cm). Record max root depth.
- Drainage wells: syringe out any standing water and record mL.
- Watering to target (VWC 30 %) with equal mL to both halves unless the protocol says otherwise. Log mL.
- Cover-crop height (5 points); clip if > 15 cm, dry and weigh the clippings.
- Yellow sticky trap count (fungus gnats).
Tea bags:
| Event | Date | Bags |
|---|---|---|
| Weigh, number, bury at 8 cm | Tue Nov 10, 2026 | per half: 2 green + 2 rooibos (35-day set), 2 green + 2 rooibos (90-day set) = 16 bags total |
| Retrieve 35-day set | Tue Dec 15, 2026 | 8 bags |
| Retrieve 90-day set | Mon Feb 8, 2027 | 8 bags |
| New 90-day set after restoring D | Feb 9 → May 10, 2027 | 8 bags |
Berlese extraction:
| Round | Collect cores | Lamp on 72 h | Count and return |
|---|---|---|---|
| Baseline (base soil, 2 cores) | Mon Nov 9 | Nov 9–12 | Nov 12 |
| Round 2 (2 cores per half) | Mon Dec 7 | Dec 7–10 | Dec 10 |
| Then monthly | 2nd Monday | +72 h | Thursday |
Holidays (Dec 19 – Jan 10):
- Water both halves to 35 % VWC on Dec 18 and lay a clear acrylic sheet over 2/3 of each half (leaving a 10 cm gap) to cut evaporation.
- The LED keeps running.
- The teacher checks HA alerts remotely and visits once (≈ Jan 2) if VWC < 22 %.
Safety & risks
- Electrical (HARD RULES 1–4):
- Everything at or in the tank is 12 V DC or less: LED strip, fan, sensors.
- The PSU12 brick and RCD-protected (30 mA) strip are on the shelf above and behind, with drip loops. The node box is outside the tank, above soil level, and cables enter through glands.
- Students never open, wire or switch 230 V.
- The Berlese desk lamp is a certified COTS lamp on a dry bench ≥ 1 m from any tank or water. The teacher plugs it in, and it is not left on overnight unattended. Use a timer smart plug (SMARTPLUG from the shared pool) set to 72 h max, with a lampshade so nobody touches the hot bulb.
- Soil hygiene:
- Soil contains Clostridium tetani spores. Before soil work the teacher confirms students' tetanus vaccination is up to date (the Romanian schedule includes a dT booster at 14 years). Cover cuts with waterproof plasters.
- Nitrile gloves for all soil, compost and worm handling. Wash hands after and before leaving. No food or drink at the bench.
- Sieve dry soil and compost outdoors or wear an FFP2 mask; students with asthma or mould allergy do not sieve.
- Soil only from known, non-roadside, non-dog-area sites.
- Fungus gnats (Bradysia):
- Prevention: let the top 1 cm dry between waterings, keep the mesh cover on, and use yellow sticky traps (also a data series).
- If gnats exceed 20 per trap per week: Bacillus thuringiensis israelensis (BTI, e.g. mosquito dunks soaked in the watering water) or Steinernema feltiae nematodes. No chemical insecticides, because they would destroy the experiment.
- Glass and weight:
- The 55 kg filled tank is lifted only empty, by 2 people, onto a bench rated for it, on a 5 mm foam mat. It is never moved after filling.
- Acrylic is cut by score-and-snap or by the teacher. Deburr edges. Safety glasses during cutting.
- The lid is light acrylic, never glass.
- CO2: chamber concentrations (≤ 5000 ppm) are confined to ≈ 10 L of headspace. There is no exposure risk to people.
- Biology: no vertebrates, no toxic plants. Worms are kept moist and dark. Live Berlese extraction. Release plan as above.
Educational outcomes & assessment
| Outcome | Evidence | Assessment |
|---|---|---|
| Formulate testable hypotheses with variables and controls | hypothesis table (H1–H6) in the team notebook | rubric 0–3: testable, directional, metric named, control named |
| Understand replication and pseudo-replication | written paragraph: why n = 1 tank ≠ proof; how cups give true replicates | teacher check |
| Measure and compute a physical rate | 2 hand-calculated respiration rates matching firmware within 5 % | correct units and formula |
| Use a standard scientific protocol | TBI data sheet submitted to teatime4science.org (optional) | complete data sheet |
| Quantitative image analysis | weekly root-length series (Tennant) and depth-vs-time graph | consistency between 2 students counting the same photo (≤ 15 % difference) |
| Engineering design cycle | decision matrix, 3 design cards (v1–v3), final restoration recipe | rubric: requirements met, evidence-based choice, iteration documented |
| Systems/IoT literacy | explain the state diagram; modify one YAML parameter (e.g. mixing time) and test | working change on a spare board |
| Communication | Dec 17 poster/3-min pitch; June final report | peer + teacher rubric |
| Ethics and welfare | welfare checklist kept; release plan executed | checklist completion |
Sub-BOM
Cost-cut 2026-10-20: Berlese funnel uses a school desk lamp.
Prices are estimates incl. VAT. Basis: optimusdigital.ro / robofun.ro / sigmanortec.ro for electronics, emag.ro for the endoscope/scale, dedeman.ro / hornbach.ro for materials, fishing/pet shops and OLX for animals, Amazon.de where noted. 1 EUR ≈ 5.1 RON.
| ID / item | Qty | Unit RON | Line RON | Basis / note |
|---|---|---|---|---|
| ESP32 | 1 | 35 | 35 | optimusdigital/sigmanortec |
| TERMBOARD | 1 | 30 | 30 | sigmanortec/AliExpress |
| OLED | 1 | 20 | 20 | optimusdigital |
| SHT31 | 1 | 45 | 45 | cased/membrane breakout |
| SCD41 | 1 | 230 | 230 | robofun/Adafruit-class breakout |
| DS18B20 | 2 | 15 | 30 | waterproof 1 m |
| SOIL | 3 | 12 | 36 | v2.0, TL555 version |
| BH1750 | 1 | 15 | 15 | GY-302 |
| FAN | 1 | 25 | 25 | 80 mm 12 V, lid mixing (one from the approved 4) |
| LEDSTRIP | 0.25 reel | 150 | 38 | 1.1 m used from a pooled 5 m reel |
| LEDPROFILE | 2 | 30 | 60 | 2 × 55 cm cut from 1 m profiles |
| MOSFET | 2 | 10 | 20 | LED, fan |
| SERVO | 1 | 15 | 15 | phase 2 (optional) |
| PSU12 | 1 | 60 | 60 | certified 12 V 5 A brick |
| BUCK | 1 | 12 | 12 | LM2596 |
| BOX | 1 | 35 | 35 | IP65 150×110×70 |
| GLAND | 6 | 3 | 18 | PG7/PG9 |
| TANK63 | 1 | 320 | 320 | 60×30×35 rimless glass, local aquarium shop/eMAG |
| ACRYLIC | 1 | 120 | 120 | divider, lid, mesh-cover frame |
| MESH | 0.25 m² | 40 | 10 | cover + tube bottoms |
| SILICONE | 1 | 30 | 30 | aquarium-safe |
| Catalog subtotal | 1 204 | |||
| APPROVED: transparent perforated observation tube | 2 | 35 | 70 | approved line item; Ø ≈ 40–50 mm × 40 cm |
| Black corrugated PP panels A2 ×2 + velcro | 1 set | 45 | 45 | dedeman/office supplies |
| EPDM self-adhesive foam gasket 9×4 mm, 5 m | 1 | 20 | 20 | dedeman (window seal) |
| Spring clamps (small) | 4 | 5 | 20 | dedeman |
| Wired reed switch + magnet (MC-38) | 1 | 12 | 12 | optimusdigital/AliExpress |
| USB-C/Android endoscope, 5.5 mm, LED, 2 m semi-rigid | 1 | 70 | 70 | emag.ro |
| BIO: Lipton green tea (EAN 8722700055525) + Lipton rooibos (EAN 8722700188438), 20 bags each | 2 boxes | 25 | 50 | supermarket / Amazon.de for rooibos |
| Precision scale 0.01 g / 200 g | 1 | 45 | 45 | emag.ro |
| Berlese: school desk lamp + 28 W eco-halogen bulb | 1 | 10 | 10 | bulb only |
| Berlese: 2 mm hardware mesh 0.25 m², plaster of Paris 1 kg, 4 jars, 4 PET 2 L bottles (reused) | 1 set | 50 | 50 | dedeman |
| 10× loupes ×2, white trays ×2, soft brush, DIY aspirator | 1 set | 40 | 40 | emag |
| Infiltration ring (PVC Ø 110 offcut) + 500 mL measuring jug | 1 | 25 | 25 | dedeman |
| Slake: tea strainers ×2 + clear jars ×2 | 1 set | 20 | 20 | household shop |
| Soil corer PVC Ø 50 mm, drainage wells PVC Ø 20 mm | — | 0 | 0 | from approved "rigid tubes and fittings" lot |
| BIO: compost/biohumus 20 L | 1 | 35 | 35 | dedeman/hornbach |
| BIO: biochar 5 L (or untreated lump charcoal 3 kg) | 1 | 50 | 50 | eMAG/garden shops |
| LECA expanded clay 10 L | 1 | 25 | 25 | dedeman |
| Geotextile fleece 1 m² | 1 | 10 | 10 | dedeman |
| BIO: topsoil 60 L | — | 0 | 0 | collected with permission |
| BIO: backup garden soil 50 L | 1 | 30 | 30 | dedeman ("pământ de grădină"), also for cups |
| BIO: seeds Secale cereale 1 kg, Trifolium repens 100 g, Lolium perenne 500 g, Lepidium sativum (cress) | 1 set | 55 | 55 | agri/garden shops, eMAG |
| BIO: Lumbricus terrestris ("râme canadiene") box of ~25 | 1 | 30 | 30 | fishing shop |
| BIO: Eisenia fetida starter culture | 1 | 35 | 35 | vermicompost farm (OLX/eMAG) |
| BIO: Folsomia candida springtail culture | 1 | 35 | 35 | terrarium shop/OLX |
| BIO: endogeic worms, isopods | — | 0 | 0 | collected in school garden |
| Screening cups 0.5 L clear ×18 + 2 trays | 1 set | 30 | 30 | household/eMAG |
| Nitrile gloves box of 100 | 1 | 35 | 35 | pharmacy/dedeman |
| Yellow sticky traps ×10 | 1 | 15 | 15 | garden shop |
| Free-text subtotal | 862 | |||
| Ecosystem 8 total | 2 066 RON (≈ 405 EUR) |
Delta vs the approved list:
- Uses 1 of the 4 CO2 sensors, 1 of the 4 fans, 2 of the 6 MOSFETs, 1 optional servo, both observation tubes, and 1 of the "glass-panel packs" (replaced by TANK63).
- No microSD/RTC on this node: hub logging is enough.
8-week timeline
gantt
title Living Earth build and first experiments (2026)
dateFormat YYYY-MM-DD
axisFormat %d %b
section Plan and source
Questions, hypotheses, order parts :a1, 2026-10-26, 7d
Collect soil, worms, seeds :a2, 2026-10-30, 7d
section Build
Tank leak test, divider, panels :b1, 2026-11-02, 4d
Node box, flash ESPHome, LED bridge :b2, 2026-11-02, 7d
Baseline soil tests and fill both halves :b3, 2026-11-06, 3d
Fauna, sowing, tea bags buried :milestone, b4, 2026-11-10, 0d
Sensor calibration and SCD41 FRC :b5, 2026-11-11, 3d
Lid gasket and leak test :b6, 2026-11-16, 4d
section Science
Respiration tests twice weekly :c1, 2026-11-17, 30d
Weekly rhizotron and tube photos :c2, 2026-11-16, 30d
Infiltration rounds :c3, 2026-11-12, 29d
Berlese round 2 :c4, 2026-12-07, 4d
Retrieve 35 day tea bags :milestone, c5, 2026-12-15, 0d
section Engineering
Screening cups v1 set up and run :d1, 2026-11-16, 30d
Decision matrix and design card v1 :d2, 2026-12-14, 4d
section Wrap up
Commissioning sign-off :milestone, e1, 2026-12-15, 0d
Poster and pitch, holiday autopilot :e2, 2026-12-15, 4d
| Week | Dates | Deliverable |
|---|---|---|
| 1 | Oct 26 – Nov 1 | hypothesis table, BOM ordered, soil site permission (check autumn-break dates) |
| 2 | Nov 2 – 8 | tank divided and paneled, node box built, base-soil baseline (pH/EC, slake, moisture), halves filled |
| 3 | Nov 9 – 15 | Berlese baseline, fauna added, cover crop sown, tea bags in (Nov 10), sensors live and calibrated, SCD41 FRC |
| 4 | Nov 16 – 22 | lid finished and leak-tested, first respiration tests, screening cups started, first root photos |
| 5 | Nov 23 – 29 | routine tests; infiltration round 2; cress sown in cups (day 21 ≈ Dec 7 if cups set Nov 16) |
| 6 | Nov 30 – Dec 6 | mid-point data review; firmware result check (hand calc vs firmware) |
| 7 | Dec 7 – 13 | Berlese round 2, infiltration round 3, slake + pH/EC round 2, cup measurements |
| 8 | Dec 14 – 18 | 35-day tea bags out (Dec 15), commissioning sign-off (Dec 15), decision matrix, poster/pitch (Dec 17), holiday setup (Dec 18) |
8b. Alternative: The Carnivorous Bog
Node: mc-08b-bog · Enclosure: TANK25 · Use instead of #8 if the team prefers.
Concept: A nutrient-poor acid bog where sundews get nitrogen from insects instead of soil. Students test how carnivorous plants detect and respond to prey, and engineer a stable constant-water-level, high-humidity habitat that uses only mineral-free water.
Science:
- Q1, tentacle response: what triggers sundew tentacle bending and leaf curling (Darwin's 1875 experiment)?
- Stimuli on marked leaves of D. capensis: inert sand grain, wet paper, 1 mg fish flake (protein), sugar crystal, live fruit fly.
- n = 5 leaves per stimulus.
- Phone time-lapse (1 frame per 2 min) records time to first tentacle bend (min) and leaf curl angle at 2, 6 and 24 h.
- Q2, prey capture rate: count flies stuck per leaf per week after releasing a fixed number (20) of flightless Drosophila inside the tank. Compare high-light and low-light ends of the tank.
- Q3, growth vs water level and light:
- 9 D. capensis in 3 groups standing on spacers: pot base 0, 1.5 and 3 cm above the water surface (= wet / medium / drier).
- Light gradient along the strip, logged by BH1750 at each end on calibration day.
- Metrics: rosette diameter, leaf count, flower stalks, leaf redness (phone photo with colour card) every 2 weeks.
Engineering: Design a self-watering tray that holds a constant water level (±5 mm) using only distilled or RO water (TDS < 50 ppm, checked with TDSPEN), and keeps humidity at 60–80 % without mould. Requirements:
- water level within the band for 14 days unattended;
- RH 60–80 % for 90 % of the time;
- no standing condensation on the front glass;
- top-up reservoir lasts ≥ 3 weeks (covers the winter holiday).
Iterate on float positions, pulse length, mister duty and vent gap.
Enclosure: TANK25 (40×25×25 cm).
- The bottom 3 cm is the water tray. Pots stand in it on spacers.
- Pots: 9 cm plastic, mix unfertilised sphagnum peat : perlite 1:1 (no lime, no fertiliser, pH 3.5–4.5).
- Lid: ACRYLIC with a 1 cm adjustable vent slot.
- 2 FLOAT switches on a bracket in the back corner: low at 1.5 cm, high at 2.5 cm water depth.
- Top-up: PUMP in an external RESERVOIR (10 L distilled water, on the shelf beside but lower than the node box), feeding TUBING to the tank corner.
- MIST disc in a small separate 1 L PP container outside the tank. Fog is ducted in by a 25 mm tube, so the mister electronics stay outside.
- 12 V LEDSTRIP in 2 rows (2 × 40 cm in LEDPROFILE) on the lid, 10–12 cm above the rosettes. Target 8000–15000 lux at rosette level, 14 h/day.
- The node box is outside on the wall. Same HARD RULES: 12 V/24 V DC only at the tank, the PSU12 and the mister's own 24 V adapter on the RCD strip on the shelf.
Biology:
| Species | Qty | Notes | Source (Romania) |
|---|---|---|---|
| Drosera capensis (Cape sundew, "roua cerului") | 9 | no winter dormancy, fast, forgiving, flowers indoors | Hornbach (FloraSelf, 9 cm pot ≈ 30 RON), secretgarden.ro (≈ 29–49 RON) |
| Drosera aliciae (Alice sundew) | 2 | rosette, no dormancy, good comparison species | secretgarden.ro / Romanian carnivorous-plant sellers on OLX |
| Pinguicula (Mexican hybrid, e.g. 'Tina' or P. moranensis) | 2 | butterwort, sticky leaves; has a dry "succulent" winter phase: keep on the 3 cm spacer and drier Dec–Feb | same sellers |
| D. capensis seed | 1 packet | sow on peat in Week 2 for a seedling series | same sellers / plants' own seed |
| Flightless Drosophila culture | 1 | prey | terrarium shops |
- Feeding: 1 fruit fly or a pinch (≈ 1 mg) of crushed fish flakes per mature plant per week. Never give meat. Never give tap or mineral water: Bucharest tap water is ≈ 300–400 ppm TDS and will kill the plants within weeks.
- Dormancy note: D. capensis and D. aliciae need no cold dormancy, so they grow through the indoor winter. This is the main reason to choose them for a Dec–Jun school timeline. Temperate species like D. rotundifolia or Dionaea would need a cold rest Nov–Feb.
Instrumentation and pins (standard map):
| Catalog ID | Qty | Placement | Interval | Purpose | GPIO |
|---|---|---|---|---|---|
| SHT31 | 1 | back wall, 10 cm above pots | 60 s | RH/T control | I2C 21/22 (0x44) |
| BH1750 | 1 | at rosette height, centre (moved to ends on calibration day) | 60 s | light dose | I2C 21/22 (0x23) |
| OLED | 1 | node box | — | live values | I2C 21/22 (0x3C) |
| DS18B20 | 1 | in the water tray | 60 s | water/root-zone T | 1-Wire 4 |
| SOIL | 1 | in one "medium" pot, calibrated in peat:perlite | 60 s | substrate moisture vs level | ADC 32 |
| FLOAT | 2 | low 1.5 cm, high 2.5 cm | event | level control | DI 13 (low), DI 14 (high) |
| LEDSTRIP + MOSFET | 1 | lid | schedule | light | PWM1 16 |
| PUMP + MOSFET | 1 | in external reservoir | event | top-up | PWM3 18 |
| MIST | 1 | outside container, ducted | RH loop | humidity | Relay 1 23 (switches 24 V DC) |
- 2 floats instead of the 1 in the draft allocation: a low-only float plus timer could overfill the tray if a float sticks, so the high float acts as a hard stop.
Automation:
- Level: when the low float opens, run the pump in 5 s pulses (60 % PWM) with 20 s pauses until the high float closes. Max 6 pulses per hour, then stop and alert "reservoir empty or float stuck".
- Humidity: mister on below 60 % RH, off at 72 % RH. Max 2 min on per 15 min, only during the photoperiod. Every 4 h, if RH > 85 %, alert "open vent".
- LED: 14 h (06:00–20:00).
- Alerts: distilled reservoir low (counted from pump pulses, ≈ 2 L per week expected), DS18B20 < 15 °C or > 30 °C.
Safety: 12 V/24 V DC only at the tank (HARD RULES 1–4), adapters on the RCD strip on the shelf, drip loops. The mister and its electronics are outside the tank, and the reservoir sits below the node box. Peat dust: moisten before handling, gloves, wash hands. Plants are non-toxic. Fruit flies are kept in a closed culture, and the tank lid has a mesh vent.
Sub-BOM 8b:
| ID / item | Qty | Unit RON | Line RON | Basis |
|---|---|---|---|---|
| ESP32 | 1 | 35 | 35 | optimusdigital |
| TERMBOARD | 1 | 30 | 30 | sigmanortec |
| OLED | 1 | 20 | 20 | optimusdigital |
| SHT31 | 1 | 45 | 45 | cased |
| DS18B20 | 1 | 15 | 15 | waterproof |
| SOIL | 1 | 12 | 12 | v2.0 |
| BH1750 | 1 | 15 | 15 | GY-302 |
| FLOAT | 2 | 10 | 20 | vertical plastic |
| PUMP | 1 | 35 | 35 | 12 V 3 W |
| TUBING | 2 m | 4 | 8 | 6 mm ID |
| RESERVOIR | 1 | 35 | 35 | 10 L food-grade |
| MIST | 1 | 60 | 60 | incl. 24 V adapter |
| RELAY | 1 | 8 | 8 | 24 V mister line |
| LEDSTRIP | 0.25 reel | 150 | 38 | 0.8 m used, pooled reel |
| LEDPROFILE | 1 | 30 | 30 | cut 2 × 40 cm |
| MOSFET | 2 | 10 | 20 | LED, pump |
| PSU12 | 1 | 60 | 60 | certified |
| BUCK | 1 | 12 | 12 | LM2596 |
| BOX | 1 | 35 | 35 | IP65 |
| GLAND | 5 | 3 | 15 | PG7/PG9 |
| TANK25 | 1 | 150 | 150 | 40×25×25 glass |
| ACRYLIC | 0.5 sheet | 120 | 60 | lid with vent slot |
| SILICONE | 1 | 30 | 30 | aquarium-safe |
| Catalog subtotal | 788 | |||
| BIO: Drosera capensis | 9 | 30 | 270 | Hornbach FloraSelf / secretgarden.ro |
| BIO: Drosera aliciae | 2 | 35 | 70 | secretgarden.ro / OLX sellers |
| BIO: Pinguicula Mexican hybrid | 2 | 35 | 70 | same |
| BIO: D. capensis seed | 1 | 20 | 20 | same |
| Unfertilised sphagnum peat 20 L | 1 | 35 | 35 | dedeman/hornbach ("turbă" pH 3.5–4.5, no NPK) |
| Perlite 5 L | 1 | 20 | 20 | dedeman |
| Distilled water 5 L | 4 | 5 | 20 | dedeman/auto shops |
| 9 cm pots ×12 + spacers | 1 set | 20 | 20 | garden shop |
| BIO: flightless Drosophila culture | 1 | 30 | 30 | terrarium shop |
| Fish flakes | 1 | 15 | 15 | pet shop |
| Free-text subtotal | 570 | |||
| Ecosystem 8b total | 1358 RON (≈ 266 EUR) |
9. The Time Capsule
Node: mc-09-capsule · Team: all teams (core build team of 4 + one delegate from each of teams 1–8) · Built 1–12 Dec 2026 · Sealed mid-January 2027 · Capsule box opened in December 2036.
Concept (refined)
A closed bioactive terrarium in a 63 L glass tank. It is designed to run for 10+ years with almost no intervention, like David Latimer's bottle garden (sealed 1972, watered once in 1972). Plants recycle water through transpiration and condensation. Springtails, isopods, fungi and bacteria recycle dead matter into nutrients. The only external input is light.
Three rules shape the whole design:
- The living system never depends on the electronics. All sensors sit in one removable sensor pod that plugs into the lid. The light runs on a COTS timer plug with a hardware fail-safe, so it keeps working even if the ESP32, the Wi-Fi or Home Assistant are dead.
- Every intervention is possible without opening the lid. Water goes in and out through an external fill/drain standpipe. Air exchange goes through a screw-capped 20 mm vent port. Sensors are swapped through a 50 mm pod port.
- Everything is documented for strangers. The 2033 Keeper never met the 2026 builders. The manual, the labels and the data archive have to work without anyone remembering how things were done.
The capsule ritual. A lockable steel A4 document box is bolted inside the stand cabinet. It has two compartments:
| Compartment | Contents | Opened |
|---|---|---|
| A — Founding capsule (sealed with a numbered tamper seal on Sealing Day, Jan 2027) | One letter from each founding student "to the Keeper of 2036". A printed founding photo set (Day 0, Day 28, Sealing Day). The design document v1.0 on paper. The founding species list. Predictions for 2036, written down and signed (moss cover %, surviving species, CO2 amplitude). 2× USB 32 GB of different brands, holding identical founding data (CSV, JPG, PDF/A). | December 2036, at a school event. Predictions are compared with reality. |
| B — Annual archive pocket (deposit slot cut in an inner folder, never sealed) | Each June: one printed A4 "Year in the Capsule" summary page, and from 2028 the retired SD card (every 3 years) or a USB stick holding that year's ZIP. | December 2036, together with A. |
Science track
Driving question: Does a closed ecosystem reach a stable state, and how do its CO2, humidity and temperature cycles evolve over years?
Sub-questions for cohorts:
- How long does the "establishment pulse" last? This is the burst of decomposition from fresh substrate.
- Does the day/night CO2 cycle become regular?
- Which species win?
- Does the total water stay constant?
Hypotheses (each cohort may add its own; all are recorded in the manual):
| ID | Hypothesis | Testable by |
|---|---|---|
| H1 | Night-time CO2 is high in the first 3–6 months: fresh coir and bark decompose and soil respiration exceeds photosynthesis. The daily CO2 amplitude (night max − day min) then falls and stabilises within ±20 % month-to-month by the end of 2027. | SCD41 daily summaries |
| H2 | Night CO2 rise rate follows substrate temperature: roughly ×2 per +10 °C (Q10 ≈ 2). It is therefore higher in summer and in the heating season. | SCD41 + DS18B20 regression |
| H3 | Air RH stays ≥ 90 % while sealed. A sustained drop below 75 % means a seal leak, not a biological change. | SHT31 |
| H4 | Vascular species richness falls from 8 to 3–5 by 2031 (competitive exclusion). Ficus pumila and Selaginella spread most. | Yearly inventory |
| H5 | Moss cover (% of substrate area seen from the front and top) increases for 2–3 years, then plateaus. | Yearly fixed-jig photos |
| H6 | Water is conserved. Sump level changes by < 5 mm per year when the lid is sealed and nobody adds water. | Standpipe scale + SOIL B |
Measured continuously (60 s to Home Assistant/InfluxDB; 10 min means to the local SD card):
- Air T/RH (SHT31) and CO2 (SCD41, also T/RH)
- Canopy lux (BH1750)
- Substrate temperature (DS18B20 #1) and room temperature reference (DS18B20 #2, outside the tank)
- Soil moisture shallow and deep (SOIL A/B)
- LED supply present (12 V sense) and LED duty %
Measured by people:
| What | When | How |
|---|---|---|
| Fog score 0–4 (0 clear; 1 droplets on top quarter; 2 half of glass; 3 most; 4 fully fogged) | Monthly glance, at 08:00 and 14:00 on the same day | Paper logbook + HA input_number |
| Sump level (mm) | Monthly | Scale on the clear standpipe |
| Front + side photos | Quarterly | Fixed phone jig (see Engineering). LED at 100 %, room lights off, grey/colour card in frame. |
| Species inventory | Yearly (June) | Presence, estimated cover % per species on the printed 5 × 5 cm grid overlay, tallest height in cm |
| Moss cover % | Yearly | Fiji/ImageJ colour threshold (HSB) on the jig photo, fixed ROI; plus manual grid-cell count as a cross-check |
| Cleanup crew census | Yearly, at 08:00 before lights on | Count springtails and isopods visible against the front glass in a marked 10 × 10 cm window at substrate level. Three counts, 5 min apart. |
| Condensation pattern | Yearly | Photo series every 2 h for one day (08:00–18:00) |
| Pruned/removed biomass (g fresh, g dry) | At each service opening | Kitchen scale 0.1 g; dry 24 h at 60 °C. This is carbon exported from the system. |
Analysis over years:
- Daily summaries, computed by an HA/InfluxDB task or a Python notebook stored in the archive: mean/min/max per variable, CO2 amplitude, CO2 night-rise rate (ppm/h, 20:00–06:00), photoperiod check.
- Monthly and yearly: box-plots per month, year-over-year overlay of the same calendar month, and the tank-minus-room temperature difference. The room DS18B20 separates internal dynamics from classroom climate: heating season Oct–Apr, summer heat in July–August.
- Stability definition, fixed now so that future cohorts don't move the goalposts: the system is "stable" for a variable when 6 consecutive monthly means of its daily amplitude stay within ±20 % of their 6-month mean.
- Event annotation: every opening, water addition, pod swap and power cut is logged in
events.csv. Analyses must mark these points.
Role of the first 8 weeks (establishment baseline, Dec 2026 – Feb 2027). This is the founding cohort's own experiment. It is a natural before/after design:
- Weeks 1–4: lid cracked, vent open.
- Weeks 5–8: sealed.
Predictions to write down before sealing:
- Night CO2 peak rises at least 2× after sealing.
- RH rises from ~85 % to ≥ 95 %.
- The day/night temperature cycle is unchanged.
Students compute the effect size (weekly mean of the daily CO2 amplitude, open vs sealed) and report it in March 2027. These 8 weeks are also the reference baseline that every later year is compared against.
Engineering track
Design-for-longevity requirements (verify each one at commissioning; re-verify in the yearly checklist):
| ID | Requirement | Design answer | Verification |
|---|---|---|---|
| R1 | The living system survives 30 days with all electronics and network dead | Passive water cycle. Light runs on a COTS timer plug through a relay NC bypass. | Unplug the node PSU5 for 48 h: LED still follows the 07:00–19:00 schedule |
| R2 | Semi-sealed with controllable gas exchange | Gasketed glass lid + 20 mm vent port with PVC screw cap and stainless mesh. Cap closed = sealed; cap off = passive vent. | RH stays ≥ 90 % for 7 days with cap closed |
| R3 | Water can be added and removed without opening | 20 mm clear acrylic standpipe from the LECA sump to a ½" bulkhead in the lid. Syringe drain; optional 12 V peristaltic top-up. | Add and remove 100 mL through the port; read the level on the standpipe scale |
| R4 | Light independent of windows and school timetable | 12 V LED strip in aluminium profiles above the lid, 12 h/day, weekends and holidays included | BH1750 ≥ 3,000 lux at canopy |
| R5 | Optical clarity and integrity for 10 years | COTS glass tank + 6 mm float-glass lid. No acrylic walls: acrylic scratches, yellows and bows over 10 years. | Yearly seam and scratch inspection |
| R6 | No adhesive that can fail | Mechanical fasteners only: clamp hinges, toggle clamps, threaded bulkheads, cable glands. Aquarium silicone only where the tank already uses it. No hot glue, foam tape, cyanoacrylate, epoxy or PVA in the wet zone. Neutral-cure (not acetoxy) silicone on electronics. | Visual |
| R7 | Sensors are replaceable without opening the lid | Sensor pod: acrylic mast hung from a DN50 screw cap carrying ONE PG9 gland + one blanked spare PG9 | Full pod swap in < 15 min (rehearsed at commissioning) |
| R8 | Data survives hub failure | DS3231 RTC + local microSD CSV log on the node, independent of Wi-Fi/HA | Stop HA for 24 h; SD file has no gaps |
| R9 | Understandable by strangers | Versioned manual (paper + PDF + repository), printed information panel, every cable labelled at both ends | A student outside the project performs the monthly check using only the manual |
| R10 | Survives a room move | Stand + tank + node move as one unit. All couplings unpluggable (DC jacks, standpipe sleeve). | Move procedure written and rehearsed once (empty-tank dry run) |
| R11 | Safe | SELV 12 V only on the stand. Mains bricks on a wall shelf above and away, on an RCD strip. | Teacher sign-off |
Sealed vs. semi-sealed. Fully sealed (Latimer style) gives the best science, because it is a truly closed system. The risk is an unrecoverable mould or anaerobic crash in year 1, when nobody has experience with this tank. Decision: semi-sealed by design, sealed in operation. The vent cap is normally closed. The cap is opened only by rule (fog score 4 all day for 3 consecutive days, or mould bloom), and every opening is logged as an event.
Data archive strategy. Data is kept in four independent places:
- InfluxDB on the hub (retention forever).
- Nightly CSV export to the school Google Drive. The account is owned by the school, not a person.
- A local monthly CSV on the node's SD card.
- A yearly ZIP: open formats only (CSV, JPG, PDF/A, TXT, MD), plus a
README.txtdescribing columns, units, sensor versions, calibration and events. It goes to the school drive, a USB stick, and a printed summary page in capsule compartment B.
USB flash and SD cards can lose data after years without power. Paper is the guaranteed format, and the drive copy is refreshed yearly.
Failure modes & recovery:
| Failure | Detection | Recovery |
|---|---|---|
| Mould bloom: white fuzz on wood or leaf litter. Normal in weeks 1–8. | Visual; fog score 4 for days | Weeks 1–8: do nothing; springtails graze it. If it covers > 10 cm² on a plant, or is still spreading after week 8: open the vent cap for 1–3 days. Remove affected material with long tweezers during a service opening. Log mass removed. |
| Plant die-off (rotting mass) | Visual; CO2 night peak +50 % over the 30-day median | Remove rotting tissue > 5 cm² at a service opening (log g). Replant only with a species already in the inventory, or document the new one. |
| Pest outbreak: fungus gnats (Bradysia), mites, snails/slugs from wild moss | Yellow sticky trap during settling; visual | Prevention: freeze substrate bags and moss 48 h at −18 °C, and quarantine moss for 2 weeks. Gnats: lower the sump level, leave the vent open 1 week, yellow trap. Slugs: remove by hand at night. |
| Overwatering: sump > 30 mm, waterlogged substrate | Standpipe scale; SOIL B saturated > 7 days | Drain via standpipe with a 60 mL syringe and 6 mm tube. Log mL. |
| Drying or seal leak | RH < 75 % for 6 h; SOIL A dry; no condensation for 3 days | Check gasket and clamps, vent cap and glands. Add 50 mL distilled water via the standpipe. |
| Algae on glass | Green film; BH1750 falls > 20 % vs baseline | Reduce LED to 50 % or 10 h. Wipe the inside at the yearly opening with a magnetic glass cleaner (no chemicals). |
| Sensor failure | NaN/stuck values; HA alert | Swap the whole pod with the spare pod or rebuilt pod (15 min). Repair the old pod at the bench. |
| Node failure | "No data 24 h" alert; OLED dark | LED continues via relay NC bypass on the timer plug. Swap in a spare ESP32 + TERMBOARD and flash the archived .bin from the repo. |
| Hub failure | No dashboard | Node keeps logging to SD. Restore the HA backup on a new Pi. Back-fill InfluxDB from the SD CSVs. |
| Long power cut | events.csv boot record; RTC time stays correct |
Nothing to do. The digital timer plug has battery backup; check its clock afterwards. |
| School renovation or room move | Planned | Follow the move procedure (Operations). Move the stand as one unit with 4 people. Max 2 h without light. Never move it while the sump is > 10 mm. |
| Summer heat (room > 30 °C in July–August) | T > 30 °C alert | Automatic summer mode (Jun 15–Sep 10): 10 h photoperiod at 50 %. The teacher checks the dashboard weekly in the holiday. |
Enclosure & build
Tank.
- Baseline: TANK63 (60 × 30 × 35 cm, ~63 L, COTS glass, 5–6 mm).
- If budget allows: 60 × 40 × 40 cm (~96 L). It gives a bigger air volume (slower CO2/RH swings), more room for 10 years of growth, and the same 60 cm footprint length. Extra cost ≈ +480 RON (tank +300, lid +80, substrate +100). Weight ≈ 55 kg. All layer depths stay the same; volumes scale ×1.33.
Layers (bottom → top; volumes for 60 × 30 cm internal ≈ 58 × 28 cm):
| Layer | Depth | Volume | Notes |
|---|---|---|---|
| LECA drainage + sump | 4 cm | 6.5 L | Rinse, soak 24 h in distilled water. 1 cm of sump water ≈ 0.65 L (porosity ~40 %). Normal sump: 10–20 mm; MAX line 30 mm, marked on the front glass with a small label. |
| MESH separator | — | 58 × 28 cm + 2 cm upturned edges | Fibreglass or stainless. Stops substrate falling into the sump. |
| Activated charcoal | 1 cm | 1.6 L | Horticultural or aquarium grade, rinsed. Adsorbs organic acids and odour. |
| ABG-style substrate | 8 cm at the front → 11 cm at the rear (slope) | ~15 L | Mix by volume: 2 coco coir : 2 orchid bark (fine) : 1 chopped sphagnum : 1 charcoal : 1 peat or tree-fern fibre. Pre-moisten with distilled water to "squeeze → a few drops". |
| Hardscape | — | — | 2 pieces of natural cork bark (≈ 30 × 15 cm and 20 × 10 cm), one leaned on the rear glass as a climbing face for Ficus. Optionally 2–3 boiled river stones. No treated or painted wood. |
| Leaf litter | 1–2 cm | ~2 L loose | Dried oak/beech leaves (bake 30 min at 90 °C) + 3–5 Terminalia catappa leaves. This is the food for the cleanup crew for years. |
Water. Only distilled or demineralised water, ever. Bucharest tap water is hard (Ca/Mg). In a closed system, the salts accumulate on glass and in substrate over 10 years.
Fill/drain standpipe.
- Pipe: clear acrylic tube, 20 mm OD, 33 cm long. It stands on the tank floor in the rear-left corner. The bottom 4 cm has eight 5 mm holes and is wrapped in MESH. A 0–40 mm scale is drawn on it with a permanent marker or scale sticker, readable through the front-left glass.
- Lid connection: the pipe top ends 1 cm below the lid. A 5 cm silicone sleeve joins it to the underside of a ½" PVC tank connector (bulkhead) in the lid. The sleeve slips off when the lid is opened. The bulkhead has an external screw cap.
- Drain: push a 6 mm silicone tube down the standpipe and pull with a 60 mL syringe.
- Fill (optional automated): a 12 V PERI peristaltic pump on the stand pumps from a 1 L bottle of distilled water through 6 mm TUBING into the standpipe cap (cap with hose barb).
- Why PERI and not PUMP: a 240 L/h submersible delivers 50 mL in under 1 s. That is far too fast to dose, and it cannot sit in a 20 mm pipe. The peristaltic pump gives ~80–100 mL/min, self-primes and doses precisely. A PUMP can be used if a PERI is not available, in 0.5 s pulses with a hard limit.
Lid.
- Glass: 6 mm float glass, 60 × 30 cm, polished edges, cut by a Bucharest glazier (≈ 1 week lead time; order by 20 Nov). Three diamond-drilled holes, all ≥ 30 mm from any edge:
- rear-left Ø 22 mm (standpipe bulkhead)
- rear-centre Ø 22 mm (vent port)
- rear-right Ø 60–62 mm (DN50 pod port; check the hole size against the purchased connector before ordering)
- Gasket: 6 × 4 mm closed-cell silicone sponge cord along the tank top rim. Fixed to the lid underside with 6 small dots of aquarium silicone, for positioning only. It is a consumable: replace every 5 years.
- Hinges: 2 clamp-type glass-door hinges for 4–8 mm glass (screw clamp, no glue). The glass side grips the lid's rear edge; the other leaf is screwed to the stand's rear board. Comes from the approved "small hinges" lot.
- Latches: 2 vertical hold-down toggle clamps (GH-101 type, rubber tip). They are mounted on two short hardwood posts screwed to the cabinet top at the front corners. They press the lid onto the gasket with light force. Never clamp directly on bare glass edges.
- Vent port: ½" PVC tank connector with rubber washer and lock nut. Stainless mesh disc under a PVC ½" screw cap. A 3D-printed PETG/ASA cap is acceptable if it is kept out of direct LED heat.
- Pod port: DN50 (2") PVC tank connector with lock nut and gasket. A DN50 threaded screw cap carries the sensor pod.
Opening the lid (rare; procedure in the manual):
- Unplug the LED bar's DC jack and lift off the light bridge.
- Unscrew the pod cap and lift the pod out.
- Release the toggle clamps.
- Tilt the lid up on its hinges. The standpipe sleeve slides off.
Light.
- LEDs: 2 rows of LEDSTRIP, 58 cm each, in 2 × LEDPROFILE with diffuser. ~1.2 m in total ≈ 12–17 W at 100 %; normal operation is 70 %.
- Light bridge: an aluminium flat bar resting on 2 shelf brackets screwed to the rear board, 5 cm above the lid. It sits on 2 dowel pins so it lifts off.
- Why outside: mounted outside, the LEDs never see condensation. Their slight warmth keeps the lid clearer than the front glass, so condensation forms on the sides and front, where it is visible.
- Spare: keep the remaining ~3.8 m of the reel in the cabinet. It is the replacement strip for 2031 (LED aging).
Stand and mains.
- Cabinet: a COTS aquarium cabinet for 60 × 30 tanks, rated ≥ 100 kg, ~72 cm high, lockable doors.
- Rear board: 18 mm plywood, 60 × 100 cm, bolted to the cabinet back. It rises behind the tank and carries the hinges, the light bridge brackets, the node BOX (at lid height, beside the tank — above water level and outside the enclosure), the photo-jig socket and the information panel.
- Inside the cabinet: the capsule document box (bolted), the spare pod, the logbook and the manual binder.
- Mains: a wall shelf 30 cm above lid level and 20 cm to the side carries the RCD-protected power strip, the timer plug, PSU12 and PSU5. Cables drop to the stand with drip loops.
Sensor pass-through.
- The pod gland: ONE PG9 GLAND in the pod cap carries ONE 8-core shielded cable (LiYCY 8 × 0.25 mm², Ø ≈ 6 mm). Conductors: 3V3, GND, SDA, SCL, 1-Wire, SOIL A, SOIL B, spare. That one cable serves the SHT31, BH1750, SCD41, DS18B20 #1 and both SOIL probes.
- Splice block: the conductors split at the top of the mast in a potted "splice block" (adhesive-lined heat-shrink on each joint, then the cluster encapsulated in neutral-cure electronics silicone). No connectors inside the wet zone.
- Spare gland: a second PG9 GLAND in the same cap is fitted with a blind plug, for a future sensor.
flowchart TD
WS["Wall shelf above and away - RCD strip, timer plug, PSU12, PSU5 (230 V COTS only)"]
LB["Light bridge - 2x LED profile 58 cm (12 V), 5 cm above lid"]
LID["Glass lid 6 mm + silicone gasket, 2 clamp hinges, 2 toggle clamps"]
PORTS["Lid ports - standpipe bulkhead, vent cap with mesh, DN50 pod port"]
POD["Sensor pod - acrylic mast with SHT31, SCD41, BH1750, DS18B20, SOIL A and B"]
AIR["Air space about 20 cm - condensation cycle"]
LIT["Leaf litter 1-2 cm"]
SUB["ABG-style substrate 8-11 cm"]
CH["Activated charcoal 1 cm"]
ME["Mesh separator"]
LE["LECA 4 cm with sump water 10-30 mm"]
SP["Clear standpipe 20 mm, rear-left, fill and drain"]
BOXN["Node box mc-09-capsule on rear board - ESP32, RTC, SD, MOSFET, relay"]
CAB["Cabinet - capsule document box, spare pod, manual"]
WS -->|"12 V and 5 V DC, drip loops"| BOXN
BOXN -->|"12 V PWM"| LB
LB --> LID
LID --- PORTS
PORTS --> POD
PORTS --> SP
POD -->|"8-core cable via 1 PG9"| BOXN
LID --> AIR --> LIT --> SUB --> CH --> ME --> LE
SP --> LE
LE --> CAB
Build steps (core team of 4 plus delegates):
| # | Step | Time |
|---|---|---|
| 1 | Assemble and level the cabinet (spirit level, shims under the feet). Bolt on the rear board. Fit the wall shelf. Fit the lid hinges' wood leaves and the clamp posts. | 3 h |
| 2 | Leak test: TANK63 with 5 cm water for 24 h on the cabinet, paper towel underneath. Then empty and dry. | 0.5 h + 24 h |
| 3 | Lid (pre-ordered from the glazier): fit bulkheads, vent cap, pod connector and gasket. Dry-fit the hinges and toggle clamps. | 1.5 h |
| 4 | Substrate prep: soak LECA 24 h; hydrate 2 coir bricks; freeze moss and bagged substrate 48 h; bake leaves. Mix the ABG-style substrate in a 60 L box with gloves. | 2 h + soaking |
| 5 | Install standpipe → LECA 4 cm (level) → MESH (upturned edges) → charcoal 1 cm → substrate, sloped 8 → 11 cm | 1.5 h |
| 6 | Hardscape: cork pieces, stones. Mark the 6 × 6 cm "pod patch" at rear-right, left unplanted and covered with litter only. | 1 h |
| 7 | Insert the pod mast through the open top, pushing the probes into the substrate first. Route the cable. Fit the cap on the lid later. | 1 h |
| 8 | Planting (largest first: ferns, Asplenium, Peperomia, Pilea, Fittonia, Ficus at the cork, Selaginella), then mosses, then leaf litter. Mist with 200–400 mL distilled water. | 3 h |
| 9 | Add the cleanup crew: 1 springtail culture tipped over the litter; 30+ isopods under the cork. Keep the 2nd springtail culture as a backup. | 0.5 h |
| 10 | Electronics: node box on the rear board, LED bridge, timer plug programme, 12 V wiring, relay bypass, pod cable into the box. Label every cable at both ends. | 3 h |
| 11 | Commissioning: ESPHome flash, HA entities, alert tests (cold spray on DS18B20, unplug pod cable), SD file check, fail-safe test (unplug PSU5 → LED keeps the timer schedule) | 2 h |
| 12 | Day-0 baseline: jig photos, species inventory, calibration sheet into the manual | 1 h |
| 13 | Fit the information panel. Put the logbook and manual v1.0 in the cabinet. | 0.5 h |
Information panel (approved "printed durable ecosystem labels / information panels"):
- A3 UV-printed aluminium composite on the rear board, above the node box.
- Content: name and founding date; layer cross-section; species list with Latin names; "Do not open — ask the Keeper"; monthly check box; QR code to the read-only dashboard and the manual PDF; emergency contact (teacher sponsor); "Capsule box opens December 2036".
- Separate engraved/printed labels on every cable, the standpipe ("WATER — distilled only, max 50 mL") and the vent cap ("VENT — open only per manual §4").
Biology
Plants. All are non-toxic for handling with gloves, robust in closed terrariums, and available at Dedeman/Hornbach/Leroy Merlin garden sections, florists, or Romanian terrarium shops/OLX:
| Species (common) | Qty | Position | 10-year note |
|---|---|---|---|
| Fittonia albivenis 'Mini' (nerve plant) | 2 | Front-middle | Classic closed-terrarium plant; prune at service openings |
| Ficus pumila 'Minima' (creeping fig) | 1 | At the rear cork | Most vigorous; prune yearly. Latex is a mild skin irritant, so wear gloves. Alternative: Pellionia repens. |
| Peperomia rotundifolia or P. caperata mini | 1 | Mid-left | Slow, very tolerant |
| Pilea glauca or P. depressa | 1 | Front-right ground cover | Fast ground cover |
| Nephrolepis cordifolia 'Duffii' (lemon-button fern) | 1 | Rear-left | Dwarf form only. Standard N. exaltata outgrows 60 L. |
| Asplenium nidus juvenile (bird's-nest fern) | 1 | Rear-centre | Slow; may reach 25–30 cm by 2032 |
| Selaginella kraussiana (spike moss) | 1 | Low, humid front | Needs 90 %+ RH; indicator of humidity health |
| Mosses: Leucobryum glaucum (cushion moss), Hypnum cupressiforme (sheet moss) | 3 portions (≈ 0.05 m² total) | Front slope, on stones and cork | See sourcing note below |
Moss sourcing. Buy from terrarium shops where possible. If collecting: take small amounts only, with the forest administrator's permission (Romsilva / owner), never in protected areas. Leucobryum glaucum is listed in Annex V of the EU Habitats Directive. Quarantine moss 2 weeks in a tray and freeze it for 48 h to kill slugs and mites.
Cleanup crew. No animals that need feeding; no vertebrates.
- Springtails Folsomia candida: 2 cultures. One goes into the tank; one is kept as a backup culture in a plaster/charcoal deli cup for 1 year.
- Dwarf white isopods Trichorhina tomentosa: ≥ 30 individuals. They are parthenogenetic, so a population cannot fail for lack of males.
- Sourcing: Romanian terrarium hobbyists (OLX.ro, Facebook groups "Terarii România" / "Izopode România"), or EU breeders that ship to RO. Example: Exuvium (NL) lists T. tomentosa at ≈ 5 EUR per 30+ animals plus shipping. Combine the live-shipping order with teams 1 and 8, who also need decomposers.
- Shipping season: the tank is built in early December. Ship with a heat pack, or pick up locally.
Establishment and settling (4 weeks, ~12 Dec 2026 – ~11 Jan 2027).
- Lid closed on the gasket, but propped 5 mm at the front with 2 silicone spacers, and the vent cap open. A yellow sticky trap hangs inside for an insect census.
- Expect a white mould bloom on wood and litter in weeks 1–3. Do not remove it unless it is on plants.
- Remove any plant that rots. Add water only if no condensation forms for 3 days.
- Winter break: the teacher checks the dashboard every 2–3 days; nobody touches the tank.
- Sealing Day (week of 11–15 Jan 2027):
- Remove the sticky trap (count and log the insects).
- Wipe the gasket.
- Remove the spacers and close the toggle clamps.
- Screw the vent cap shut.
- Seal capsule compartment A in the same ceremony.
Expected condensation cycle (sealed, LED 07:00–19:00):
- Night and early morning: fog on the front and sides (glass cooler than the air).
- 1–3 h after lights on: it clears from the top down.
- Late afternoon: light droplets only.
Tuning rules:
| Observation | Action |
|---|---|
| Fully fogged (score 4) all day | Open the vent cap 10 min. Repeat daily up to 3 days, then reassess. |
| No condensation at all for 3 days | Add 50 mL distilled water via the standpipe |
| Water above 30 mm in the standpipe | Drain to 15 mm with the syringe |
| Pale, stretched plants | Raise LED duty +10 % (max 90 %) |
| Algae on glass or scorched moss | Lower LED duty −10 % or shorten to 10 h |
Every action is logged in events.csv and the paper logbook.
Instrumentation
| Catalog ID | Qty | Placement | Interval | Purpose |
|---|---|---|---|---|
| SHT31 | 1 | Inside, on the pod mast 4 cm below the lid, in a cased PTFE-membrane probe housing, membrane facing down | 60 s | Air T/RH, seal integrity (RH < 75 % = leak), dew point |
| SCD41 | 1 (strongly recommended) | Inside, on the pod mast 6 cm below the lid (warmest, least-condensing point under the LED), membrane-covered cased board | 60 s | Day/night CO2 cycle: the most informative long-term signal of a sealed ecosystem (respiration vs photosynthesis). Also a secondary T/RH. |
| BH1750 | 1 | Pod mast at canopy height (~10 cm above the substrate), facing up, conformal-coated, clear cover | 60 s | Canopy lux. Relative trend from LED aging, lid fog and algae. Not PAR. |
| DS18B20 | 2 | #1 in the substrate at 5 cm depth (pod mast); #2 outside on the rear board, shaded (room reference) | 60 s | Substrate T for the Q10 analysis; room T separates internal from classroom dynamics |
| SOIL | 2 | A: shallow, sensing zone 0–5 cm; B: deep, tip 1 cm above the mesh near the sump. Both on the pod mast. | 60 s (mean of 10) | Water distribution; B detects waterlogging |
| RTC | 1 | Node box (I2C 0x68) | — | Timestamps for SD logging; light schedule without NTP |
| SDMOD + SD64 | 1 + 2 | Node box (SPI) | 10 min | Local CSV log independent of hub and Wi-Fi |
| OLED | 1 | Node box lid window | 5 s page cycle | Live values, Wi-Fi/SD status, "last top-up" date |
Why not a BME680 here:
- The tank runs at 90–100 % RH with condensation most nights. Bosch rates the BME680 humidity element for non-condensing use; it saturates and drifts after prolonged exposure. Uncased breakouts corrode within months.
- Its MOX gas sensor is poisoned by siloxanes. Our tank is built with fresh silicone.
- Its gas reading is a resistance, not a concentration, and it drifts over years, so it is useless for a 10-year series.
- The SHT31 in a PTFE-membrane housing is designed for high-humidity environments. Its heater can be pulsed to drive off condensation: ESPHome lambda, 10 s every 6 h when RH ≥ 99 % for 12 h.
SCD41 notes:
- Disable ASC (automatic self-calibration). ASC assumes the sensor sees fresh air (~420 ppm) weekly. A sealed tank never does, so ASC would slowly corrupt the baseline.
- Set altitude compensation to 80 m (Bucharest).
- Before installation and at each pod build, run forced recalibration (FRC) outdoors at ~420 ppm.
- The signal of interest is the daily amplitude, which is robust to slow offset drift.
- The SCD41 is rated non-condensing. It is placed at the warmest point and replaced with the pod every 3 years.
SD logging and card lifetime:
- Firmware: ESPHome (pinned version, recorded in the manual), plus a small vendored external component. The component is copied into the repo, not referenced by URL. It uses the Arduino SD library over SPI.
- Card format: FAT32. A 64 GB card is exFAT from the factory, so reformat it as FAT32.
- Files: one file per month,
/mc09/2027/mc09_2027-01.csv. One row every 10 min: timestamp (RTC, UTC), then the mean/min/max of each sensor. - Header block: pod version, sensor serials and calibration coefficients.
- Events:
/mc09/events.csvrecords boots, SD errors, top-ups, light-supply loss and pod swaps. - Writes: each row is open-append-close, so a power cut loses at most one row.
- Size: ≈ 150 B × 144 rows/day × 365 ≈ 8 MB/year, so 10 years < 100 MB.
- Wear: ~52,000 appends/year is negligible for a wear-levelled High-Endurance card. The real risks are power-loss corruption, contact oxidation and counterfeit cards.
- Rotation policy: the card is copied yearly and replaced with the pod every 3 years. The retired card goes into capsule compartment B.
- RTC battery: many cheap DS3231 modules have a charging circuit that damages a non-rechargeable CR2032. Remove the charging resistor/diode (documented with a photo in the manual), or fit an LIR2032. Replace the cell every 5 years.
Pin assignment (standard pin map; unused standard slots reused for SPI and documented):
| Function | GPIO | Standard-map slot |
|---|---|---|
| I2C SDA / SCL: SHT31 0x44, SCD41 0x62, BH1750 0x23, OLED 0x3C, RTC 0x68 (+ EEPROM 0x57) | 21 / 22 | I2C; bus at 50 kHz because of the ~1.2 m pod cable; 2.2 kΩ pull-ups |
| 1-Wire: DS18B20 #1 substrate, #2 room | 4 | 1-Wire, 4.7 kΩ to 3.3 V |
| SOIL A (shallow) / SOIL B (deep) | 32 / 33 | Analog A / B (ADC1, 11 dB) |
| 12 V LED-supply sense (47 k / 10 k divider → 2.1 V) | 36 | Analog E |
| LED PWM (MOSFET 1, 2 kHz) | 16 | PWM 1 — light |
| PERI top-up (MOSFET 2, on/off) | 18 | PWM 3 — pump |
| Relay 1: LED fail-safe bypass (energised = MOSFET control; de-energised = NC bypass) | 23 | Relay 1 (12 V DC load only) |
| SD SPI SCK / MOSI | 26 / 27 | Servo 1 / 2 slots (no servos on this node) |
| SD SPI MISO | 19 | PWM 4 slot (unused here) |
| SD SPI CS | 5 | Pulse-counter slot (unused here; high at boot = card deselected) |
| Status LED heartbeat | 2 | Reserved onboard LED |
Power:
- Node: PSU5, always on.
- LED + PERI: PSU12, plugged into the timer plug, so it is on only 07:00–19:00. 2 A blade fuse on the +12 V line.
- No BUCK on this node, because the 12 V supply is switched off at night.
Calibration (results go on the calibration sheet in the manual and in the CSV header):
- SHT31: saturated NaCl salt test (75.3 % RH) in a sealed jar, 24 h at stable room temperature. Record the offset. Cross-check T against a reference thermometer.
- DS18B20 ×2: ice-water bath (0.0 °C) and a room-temperature comparison against each other. Record offsets.
- SOIL ×2, 3 points, in the actual substrate mix: raw volts in air; in oven-dried mix (60 °C, 24 h); in mix at known gravimetric water content (add weighed water: 0 %, 50 %, 100 % of saturation). ESPHome
calibrate_linearto % of saturation. - SCD41: FRC outdoors at ~420 ppm; ASC off.
- BH1750: no absolute calibration. Record the Day-0 reading at LED 100 % with a clean lid; later readings are expressed as % of Day 0.
- PERI: time 3 runs into a measuring cylinder and record mL/s. Set the "50 mL" run time.
The sensor pod (swappable in 2029/2030 without opening the lid):
- Pod cap: a DN50 threaded PVC screw cap carrying ONE PG9 gland (the 8-core cable) and a spare PG9 with a blind plug.
- Mast: a 30 cm L-profile made by heat-bending a 40 mm strip of 3 mm ACRYLIC into 20 + 20 mm. It is screwed to the underside of the cap with 2 nylon M4 screws.
- On the mast, top to bottom: potted splice block, SHT31 housing, SCD41, BH1750 at canopy height, then DS18B20 #1 and both SOIL probes. The probes are held with nylon cable ties through drilled holes and point down into the substrate. Max pod width 45 mm, so it passes through the DN50 bore.
- Swap procedure:
- Log the event.
- Unplug the pod cable's JST/screw-terminal connection in the node box.
- Unscrew the cap and lift the whole pod straight up. The probes slide out of the unplanted pod patch.
- Lower the new, pre-calibrated pod into the same holes and screw the cap down.
- Reconnect and check the readings.
- Duration: < 15 min with the port open; the lid is never opened.
- Rebuild: the old pod goes back to the bench for rebuild.
- Spares: keep one spare pod kit (2× SOIL, 1× DS18B20) in the cabinet from day one.
- Future sensors: the blanked spare gland is for a sensor not yet invented, or an endoscope camera cable.
Automation
Everything is passive except light. The pump top-up is optional and human-confirmed.
- Light: 12 h/day, 07:00–19:00, all days of the year. 30 min dawn ramp 0 → 70 % from 07:00, 30 min dusk ramp 70 → 0 % ending 19:00. Summer mode (15 Jun – 10 Sep): 08:00–18:00 at 50 %.
- Timer plug: programmed 06:55–19:05, as the master on/off. The node only dims within that window.
Fail-safe:
- Wiring: LED− goes to relay COM. Relay NO goes to the MOSFET output. Relay NC goes straight to 12 V GND.
- Normal operation: the node energises the relay (GPIO23 high) after it has set the PWM, and the MOSFET dims the LEDs.
- If the node is unpowered, crashed or rebooting: the relay drops to NC and the LED runs at 100 % on the timer-plug schedule. The plants lose the ramp, not the light.
- Relay module jumper: set to active-high trigger, so a low or floating GPIO means bypass.
- Home Assistant: never in the light path.
Alerts (HA automations → HA mobile app + e-mail to the teacher sponsor and both Keepers; also shown on the OLED and in events.csv):
| Alert | Condition |
|---|---|
| Too hot | Air or substrate T > 30 °C for 15 min |
| Too cold | Air T < 12 °C for 30 min (heating failure in winter) |
| Seal leak / drying | RH < 75 % for 6 h |
| Soil dry | SOIL A < 25 % of saturation for 24 h |
| Waterlogged | SOIL B ≥ 98 % for 7 days |
| No data | Any mc_09_* entity unchanged for 24 h (HA side) |
| SD error | Write failure or card missing (node side, on boot or write) |
| Light supply | 12 V absent between 07:30 and 18:30, or present between 19:30 and 06:30 (timer plug fault) |
| CO2 info | Night peak > 2× the 30-day median (possible die-off; inspect) |
Optional top-up:
- HA shows "Consider adding 50 mL" when the soil-dry alert has lasted 24 h, or no condensation has been logged for 3 days.
- A Keeper presses "Add 50 mL". ESPHome runs the PERI for the calibrated time.
- Interlocks: max 60 s per run; max 100 mL per 7 days; disabled if SOIL B ≥ 90 %; works only while 12 V is present.
- No fully automatic watering. Drowning is the likeliest way to kill a sealed tank.
stateDiagram-v2
[*] --> Boot
Boot --> Bypass : relay off during boot
Bypass --> Night : time valid from RTC or NTP
Night --> Dawn : 0700 and 12 V present
Dawn --> Day : ramp done 70 pct
Day --> Dusk : 1830
Dusk --> Night : 1900 duty 0
Day --> TopUp : Keeper presses Add 50 mL
TopUp --> Day : run time done or interlock
Night --> Alert : threshold breached
Day --> Alert : threshold breached
Alert --> Night : cleared at night
Alert --> Day : cleared at day
Day --> Bypass : node crash or power loss
Night --> Bypass : node crash or power loss
Bypass --> Bypass : LED follows timer plug at 100 pct
Operations
10-year maintenance calendar:
| Frequency | Who | Tasks | Time |
|---|---|---|---|
| Weekly (school weeks) | Keepers | Glance at the dashboard; read the OLED | 2 min |
| Monthly | Keepers | Fog score (08:00 and 14:00), standpipe level, visual check (mould, pests, dead plants), confirm the timer-plug clock, fill in the logbook, tick the panel box | 15 min |
| Quarterly (Sep, Dec, Mar, Jun) | Keepers | Jig photos (front + side, grey card), upload to the drive | 20 min |
| Yearly (June, before summer) | Keepers + teacher | See the yearly checklist below | 2–3 h |
| Every 3 years (2029/30, 2032/33, 2035/36) | Keepers + an electronics-capable student | Build, calibrate and swap a new sensor pod (SHT31, SCD41, BH1750, DS18B20, 2× SOIL, 8-core cable). Retire the SD card to capsule compartment B and insert a new SD64. | 1 day bench + 15 min swap |
| Every 5 years (2031, 2036) | Teacher + Alacrity/IT volunteer | Hub refresh: new Pi or successor + storage; restore the HA backup; export the full InfluxDB to CSV; replace the gasket, RTC cell and timer plug; replace the LED strip from the spare reel if Day-0 lux has dropped below 70 % | 1 day |
| December 2036 | Whole school | Capsule opening; compare the 2026 predictions with the data; decide on the next decade | Event |
Yearly checklist (June):
- Species inventory, moss cover, crew census, condensation photo day.
- Copy the SD card and verify it against InfluxDB (row counts per month).
- Build the yearly ZIP: CSV of 10 min and daily data, photos, inventory, events, manual PDF, README.
- Upload the ZIP to the school drive. Put a USB copy and the printed A4 summary page in compartment B.
- Inspect the tank silicone seams, gasket, clamps and glands.
- Optional service opening (≤ 60 min, only if needed): prune Ficus and ferns, remove rot, clean the inside glass. Weigh removed biomass (fresh and dry) and log the event.
- Check the summer-mode schedule.
- Write the manual change log and bump the version.
- Hand over the Keeper role (below).
The Keeper role:
- Who: each school year has 2 student Keepers (one from each of 2 different grades, so one stays the next year) + 1 teacher sponsor.
- Handover: in June, the outgoing Keepers train the incoming ones on one monthly check and one quarterly photo session. Both sign the logbook handover page.
- Access: Keepers get the HA dashboard login and the alert notifications.
- Recognition: a certificate signed by the school director, plus a line in the next capsule summary page.
Maintenance manual outline ("MC-09 Keeper Manual vX.Y"; paper binder in the cabinet + PDF + Markdown in the project repository; every page dated and versioned; change log at the front):
| § | Content |
|---|---|
| 0 | Change log, Keeper list, contacts |
| 1 | What this is: concept, layers, species, why it is sealed |
| 2 | Monthly / quarterly / yearly checklists (one page each, tick-box) |
| 3 | Tuning rules (condensation table), water rules (distilled only, 50 mL max per action) |
| 4 | Vent, standpipe, pod swap and lid opening procedures, with photos |
| 5 | Electronics: wiring diagram, pin table, cable labels, ESPHome version and YAML, .bin location, flashing steps, relay bypass explanation |
| 6 | Calibration procedures and the calibration history table |
| 7 | Alerts: what each one means and what to do |
| 8 | Failure modes & recovery (table above) |
| 9 | Data: where it lives, file formats, column dictionary, how to build the yearly ZIP |
| 10 | Move procedure for renovation (see Safety) |
| 11 | Safety rules (the hard rules, verbatim) |
| 12 | Parts list with suppliers and 2026 prices, plus "equivalent part" guidance for when parts are discontinued |
Data archive:
- Yearly ZIP named
MC09_<year>_archive.zip, containing:data_10min.csv,data_daily.csvevents.csvinventory_<year>.csvphotos/(JPG, file namesYYYY-MM-DD_front.jpg)manual_vX.Y.pdfREADME.txt
- Destinations: the school-owned drive; a USB stick and the printed A4 summary in compartment B.
- Printed A4 summary: monthly T/RH/CO2 amplitude chart, moss cover %, species list, events, Keeper names.
Safety & risks
Hard rules that apply here.
- Mains (230 V) exists only inside the COTS timer plug, PSU12, PSU5 and the RCD strip. These sit on the wall shelf above and away from the tank, with drip loops on every cable. Students never open, wire or modify them.
- Everything on the stand, in the lid and inside the tank is ≤ 12 V DC: LEDs, PERI, sensors at 3.3 V.
- The relay switches only the 12 V LED return line.
- No mains device is ever inside the cabinet, in the tank or in the substrate.
Weight.
- TANK63 build: tank ~13 kg + lid 2.7 kg + LECA wet ~4 kg + sump ≤ 2 kg + substrate wet ~10 kg + charcoal, hardscape and plants ~4 kg ≈ 36 kg. Use 40–50 kg as the design figure.
- 60 × 40 × 40 build: ≈ 55 kg.
- Stand: COTS aquarium cabinet rated ≥ 100 kg, levelled, on a solid floor, and anchored to the wall with an anti-tip strap.
- Lifting: 2 people for the empty tank, 4 for any move. Never lift a filled tank by its glass edges; move it on the stand.
Sealing and mould.
- Wear gloves (nitrile) for all substrate, moss and leaf-litter work.
- Open the lid only in a ventilated room.
- Anyone with a mould allergy or asthma does not do service openings.
- The tank is never opened just to "air it" except by the tuning rules.
Vandalism and knocks.
- Location: an interior wall away from doors, corridors and sports traffic, not in a walkway. Not on a window wall (sun overheating) and ≥ 1 m from radiators.
- Protection: the cabinet stays locked. The lid toggle clamps get small padlock-able tabs or cable ties with a numbered seal. The front glass is 72 cm above the floor, out of bag-swing height.
School renovation / move.
- Plan: the manual §10 move procedure: drain the sump to < 10 mm 1 week before, lift off the light bridge, remove the pod, then move the stand as one unit with 4 people on a flat trolley.
- Limits: max 2 h without light; re-level in the new place; log the event.
- Long-term storage: if it must be stored for months, keep it in a room at 15–25 °C with the LED bridge + timer plug only (no network needed).
Other risks.
- Glass breakage: a leak test before planting. The 6 mm lid has polished edges. Keep a first-aid kit and a glass-handling protocol (gloves for glass).
- Electrical: 2 A fuse on 12 V. PSUs are certified (CE). The RCD strip is tested by pressing its test button yearly.
- Biology: no vertebrates. Springtails and isopods are harmless. Ficus latex is a mild skin irritant (gloves).
Educational outcomes & assessment
Outcomes. Students can:
- define a long-term research question and an operational definition of "stability";
- design and run a before/after experiment (open vs sealed) with predictions written first;
- analyse multi-year time series (daily summaries, seasonality, anomalies);
- write requirements, then verify them (R1–R11);
- design for maintenance by strangers (manual, labelling, archive);
- run a failure mode analysis and rehearse recoveries;
- take responsibility over time (the Keeper role).
Collaborative design: one lesson learned from each team. Each team presents its lesson in a 5-minute "design review" on 30 Nov 2026. The capsule team turns each into a written requirement or design change.
| Team | Example lesson (to be confirmed with real results) | Becomes |
|---|---|---|
| 1 Orchestra of Rot | Which decomposers persisted; mould dynamics; charcoal against odour | Crew choice, charcoal layer, mould tuning rule |
| 2 EcoColumn | Drainage, water-level reading, sediment clogging mesh | Sump + standpipe scale, mesh with upturned edges |
| 3 Brownfield | Salt accumulation and compaction harm roots | Distilled water only; open, bark-rich substrate |
| 4 Future 2026 | Real classroom T/RH swings and heating-season effect | Room DS18B20, cold alert |
| 5 Future 2056 | Heat stress thresholds | 30 °C alert, summer mode |
| 6 Forests in Space | Substrate recipes and water retention | ABG mix ratios, SOIL calibration in the actual mix |
| 7 Hydroponic Jungle | LED intensity/photoperiod vs growth; PWM dimming | 70 % duty, 12 h, ramp, LED spare reel |
| 8 Living Earth | Soil respiration CO2 vs temperature | SCD41 inclusion, Q10 analysis, ASC off |
| 9 Capsule prototype jars | 4 × 4 L sealed jar prototypes (built ~9 Nov), 4 weeks of observation: condensation and mould behaviour of the mix | Final mix, water dose, settling duration |
Assessment (team grade 60 % + individual 40 %):
| Component | Evidence |
|---|---|
| Requirements & verification | R1–R11 table with test results |
| Build quality | Checklist: labels, gland seals, no loose wires, level, leak test log |
| Baseline experiment | Pre-registered predictions, 8-week open/sealed report with plots and effect size |
| Manual v1.0 | A non-team student completes a monthly check using only the manual (pass/fail + feedback) |
| Individual | Letter to the 2036 Keeper (in the capsule), plus a short reflection: one design decision and its trade-off |
Sub-BOM
Cost-cut 2026-10-20: MARINA 54 L tank, SCD41 deferred to 2027, top-up by 60 mL syringe through the fill tube instead of a peristaltic pump, existing furniture instead of a new cabinet, one timer plug, laminated panel, plastic archive box, fewer jars, prints, cork, moss and cultures. The sensor pod keeps a reserved slot for the SCD41.
Price basis: Romanian web shops Oct 2026, incl. VAT. Electronics from optimusdigital.ro, ardushop.ro, robofun.ro and emag.ro (AliExpress fallback for the cased SHT31). Hardware from dedeman.ro and hornbach.ro. Tank and cabinet from Romanian aquarium shops. Live animals from OLX.ro hobbyists or EU breeders. 1 EUR ≈ 5.1 RON.
| Item | Qty | Unit RON | Line RON | Basis / note |
|---|---|---|---|---|
| TANK63 | 1 | 139 | 139 | Hornbach MARINA 60×30×30 (54 L). Ultraclear 60×30×36 at ≈ 362 if the extra height is wanted. |
| ESP32 | 1 | 35 | 35 | Optimus/emag |
| TERMBOARD | 1 | 30 | 30 | Screw-terminal breakout |
| OLED | 1 | 25 | 25 | |
| SHT31 | 1 | 75 | 75 | Cased probe with PTFE membrane |
| Optional (not in subtotal): SCD41 CO2 sensor, deferred to the 2027 budget | 1 | 230 | (230) | The sealed-tank CO2 cycle is the best long-term signal; the gland and pod have a reserved slot for it |
| DS18B20 | 2 | 15 | 30 | Substrate + room reference |
| SOIL | 2 | 12 | 24 | v2.0 TL555, top edge sealed |
| BH1750 | 1 | 15 | 15 | |
| RTC | 1 | 20 | 20 | DS3231; charging diode removed or LIR2032 |
| SDMOD | 1 | 10 | 10 | SPI microSD breakout |
| SD64 | 1 | 70 | 70 | High Endurance; rotation card bought at year 3 |
| MOSFET | 2 | 10 | 20 | LED dimming + PERI |
| RELAY | 1 | 10 | 10 | LED fail-safe bypass (12 V DC only), active-high jumper |
| PSU12 | 1 | 60 | 60 | On the timer plug |
| PSU5 | 1 | 30 | 30 | Node, always on |
| BOX | 1 | 40 | 40 | IP65, on the rear board |
| GLAND | 6 | 3 | 18 | 2 in the pod cap (1 blanked) + 4 on the node box |
| LEDSTRIP | 1 | 90 | 90 | 1.2 m used; 3.8 m kept as the 2031 spare |
| LEDPROFILE | 2 | 25 | 50 | Cut to 58 cm |
| TUBING | 2 m | 8 | 16 | PERI line + drain tube |
| SILICONE | 1 | 35 | 35 | Aquarium-safe, no fungicide (gasket dots, standpipe sleeve seat) |
| MESH | 0.25 m² | 10 (lot) | 10 | Separator + standpipe wrap + vent disc |
| ACRYLIC | 0.25 sheet | 30 (share) | 30 | Pod mast L-profiles (2, incl. spare pod) |
| 8-core shielded cable LiYCY 8×0.25 | 3 m | 6 | 18 | Pod cable (×2 pods) |
| Neutral-cure electronics silicone / potting | 1 | 30 | 30 | Splice block (not acetoxy) |
| Fuse holder 2 A, adhesive heat-shrink, terminal blocks, 47 k/10 k resistors | 1 lot | 30 | 30 | From the consumables lot |
| PVC ½" tank connector (bulkhead) | 2 | 15 | 30 | Standpipe + vent |
| PVC ½" screw cap | 1 | 5 | 5 | Vent cap |
| PVC DN50 (2") tank connector + DN50 screw cap | 1 | 60 | 60 | Pod port |
| Clear acrylic tube 20 mm OD × 40 cm | 1 | 20 | 20 | Standpipe (rigid tubes lot) |
| Glass lid 6 mm 60×30, polished, 3 holes | 1 | 180 | 180 | Bucharest glazier, order by 20 Nov |
| Silicone sponge gasket cord 6×4 mm | 3 m | 35 (roll) | 35 | Replace 2031 |
| Clamp-type glass hinges 4–8 mm | 2 | 25 | 50 | From the approved hinges lot |
| Toggle hold-down clamps GH-101 | 2 | 20 | 40 | Latches |
| Existing school cabinet or bench rated ≥ 100 kg, plus wall-anchor kit and 18 mm plinth board | 1 | 100 | 100 | confirm the furniture rating before filling the tank |
| Rear board 18 mm plywood 60×100 + 2 brackets + aluminium light bridge | 1 | 120 | 120 | Dedeman |
| Wall shelf for mains bricks | 1 | 40 | 40 | |
| Digital timer plug with battery backup | 1 | 50 | 50 | LED fail-safe schedule |
| Information panel A3 laminated print + cable/port labels | 1 | 25 | 25 | |
| BIO: LECA 10 L | 1 | 25 | 25 | |
| BIO: activated charcoal 3 L | 1 | 70 | 70 | Layer + mix |
| BIO: coco coir brick 650 g | 2 | 15 | 30 | |
| BIO: orchid bark fine 5 L | 1 | 30 | 30 | |
| BIO: dried sphagnum 150 g | 1 | 35 | 35 | |
| BIO: peat or tree-fern fibre 5–20 L | 1 | 25 | 25 | |
| BIO: natural cork bark piece + collected hardwood branch (baked) | 1 | 50 | 50 | |
| BIO: Terminalia catappa leaves (10) + collected oak/beech litter | 1 | 20 | 20 | Litter collected free |
| BIO: Fittonia albivenis mini | 2 | 15 | 30 | |
| BIO: Ficus pumila 'Minima' | 1 | 15 | 15 | |
| BIO: Peperomia rotundifolia / caperata mini | 1 | 20 | 20 | |
| BIO: Pilea glauca / depressa | 1 | 20 | 20 | |
| BIO: Nephrolepis cordifolia 'Duffii' | 1 | 25 | 25 | |
| BIO: Asplenium nidus juvenile | 1 | 25 | 25 | |
| BIO: Selaginella kraussiana | 1 | 25 | 25 | |
| BIO: mosses (Leucobryum, Hypnum) portions, plus moss collected with permission | 2 | 30 | 60 | |
| BIO: springtails Folsomia candida culture (split from the team 1 and 8 cultures) | 1 | 40 | 40 | |
| BIO: dwarf white isopods Trichorhina tomentosa 30+ | 1 | 60 | 60 | Incl. shipping share |
| Distilled water 5 L | 2 | 8 | 16 | |
| Yellow sticky traps | 1 pack | 15 | 15 | Settling census |
| Prototype jars 4 L with clamp lid | 2 | 20 | 40 | |
| Lockable plastic archive box A4 (capsule) | 1 | 45 | 45 | |
| Acid-free sleeves/folders + slot pocket | 1 | 25 | 25 | |
| Silica gel packs | 1 | 20 | 20 | |
| USB 32 GB (two brands) | 2 | 30 | 60 | Founding data |
| Numbered tamper seals | 1 pack | 20 | 20 | |
| Photo prints (founding set) | 1 | 20 | 20 | |
| Photo jig (aluminium arm + phone clamp) | 1 | 40 | 40 | Slots into the cabinet top |
| Grey/colour reference card, laminated | 1 | 15 | 15 | |
| 60 mL syringes | 2 | 5 | 10 | Approved syringes lot |
| Subtotal | 2 646 RON (≈ 519 EUR) | catalog hardware 882 · lid, plinth, pod and operations 928 · biology 836 (after the cost-cut pass) |
Without the optional SCD41 + PERI: 3,832 RON. Not recommended to drop the SCD41.
Shared items, not counted here: the RCD power strip, hub, router and handheld pens.
Allocation from the approved list:
- hinges 2 of 12
- glands 6 of 20
- silicone 1 of 4 tubes
- junction box 1 of 6
- microSD modules 1 of 9
- microSD cards 2 of 9
- RTC 1 of 2
- tubing 2 of 20 m
- PERI 1 (one more than the 2 for hydro; take a spare or buy one)
Timeline
| Dates | Milestone |
|---|---|
| 26 Oct – 6 Nov 2026 | Requirements R1–R11 agreed; order the tank, cabinet, electronics and live crew (book for an early-December pickup) |
| 9 Nov – 4 Dec | 4 prototype jars sealed and observed. Pod bench build and calibration (salt test, ice bath, SOIL 3-point, SCD41 FRC). ESPHome YAML + SD component tested. |
| by 20 Nov | Glass lid ordered from the glazier (holes checked against the actual bulkheads) |
| 30 Nov | Design review: 9 lessons learned → final design v1.0 |
| 1–12 Dec | Build steps 1–13; commissioning and fail-safe test; Day-0 baseline |
| 12 Dec – ~11 Jan 2027 | Settling: lid cracked, vent open; dashboard checks over the winter break |
| 11–15 Jan 2027 | Sealing Day: tank sealed, capsule compartment A sealed |
| Jan – Mar 2027 | Weeks 5–8 sealed baseline; March report (open vs sealed) |
| June 2027 | First yearly checklist; first Keeper handover |
gantt
title MC-09 Time Capsule - build and 10-year calendar
dateFormat YYYY-MM-DD
axisFormat %Y
section Build 2026
Prototype jars and pod bench build :a1, 2026-11-09, 2026-12-04
Build and commissioning :a2, 2026-12-01, 2026-12-12
Settling with lid cracked :a3, 2026-12-12, 2027-01-11
Sealing Day and capsule A sealed :milestone, m0, 2027-01-13, 0d
Sealed baseline weeks 5-8 :a4, 2027-01-13, 2027-03-10
section Yearly
Yearly checklist 2027 :milestone, y27, 2027-06-15, 0d
Yearly checklist 2028 :milestone, y28, 2028-06-15, 0d
Yearly checklist 2029 :milestone, y29, 2029-06-15, 0d
Yearly checklist 2030 :milestone, y30, 2030-06-15, 0d
Yearly checklist 2031 :milestone, y31, 2031-06-15, 0d
Yearly checklist 2032 :milestone, y32, 2032-06-15, 0d
Yearly checklist 2033 :milestone, y33, 2033-06-15, 0d
Yearly checklist 2034 :milestone, y34, 2034-06-15, 0d
Yearly checklist 2035 :milestone, y35, 2035-06-15, 0d
Yearly checklist 2036 :milestone, y36, 2036-06-15, 0d
section Pod and hub
Sensor pod v2 swap :milestone, p2, 2029-11-15, 0d
Hub refresh and gasket and LED check :milestone, h1, 2031-06-20, 0d
Sensor pod v3 swap :milestone, p3, 2032-11-15, 0d
Sensor pod v4 swap :milestone, p4, 2035-11-15, 0d
section Capsule
Capsule opening and next decade decision :milestone, c1, 2036-12-10, 0d
6. Procurement and budget
6.1 Method and assumptions
- Prices are Romanian web-shop prices including VAT, checked on 2026-10-20 by two research passes (electronics; actuators, construction and biology), with AliExpress or Amazon.de as the fallback at 1 EUR = 5.1 RON. Expect ±20 % at order time; several eMAG and Optimus listings were out of stock on the day.
- Quantities are the sums of the nine ecosystem sub-BOMs in Chapter 5 plus the spare pool in Chapter 4.4 and the platform in Chapter 3. Group E ("biology and consumables per ecosystem") is taken directly from each ecosystem's sub-BOM, non-catalog rows only, so nothing is counted twice.
- The "Approved list priced as-is" column prices the proposal's own quantities at the same unit prices, where a line can be mapped. It shows what the approved list would have cost, not what it would have delivered: it had no hub, no biology, no heaters and no network.
- A cost-cut pass on 2026-10-20 removed the project router (the nodes use the school's existing Wi-Fi), the NVMe drive for the Pi, the Time Capsule's CO2 sensor (deferred to 2027), most spares, new shelving (existing school furniture is used), a new cabinet for the Time Capsule, printed foamboard panels, a crimp tool and duplicated per-team scales and PPE. Table 6.6 lists every cut with its saving.
- Two items changed in kind, not only in number. TANK63 is supplied as the Hornbach MARINA 60×30×30 cm (54 L) because a bare 60×30×35 is not sold in Romania; designs that quote 35 cm height lose 5 cm of headroom, which matters only for the Time Capsule (use the ultraclear 60×30×36 at about 362 RON if height is wanted there). Twelve-volt silicone heat pads are not sold in Romania; the 230 V seedling and terrarium mats sold locally are not allowed by the safety rules, so the heat pads are the one item ordered from AliExpress on day one (2–3 weeks).
6.2 Budget tables
A. Controllers and sensors
| ID | Item | Approved qty | Recommended qty | Unit (RON) | Line (RON) | Source / basis | Note |
|---|---|---|---|---|---|---|---|
| ESP32 | ESP32-WROOM-32 DevKitC 38-pin | 12 | 12 | 48 | 576 | emag.ro ESP32 38-pin CP2102 USB-C | buy all 12 from one listing so pinout and row spacing match |
| TERMBOARD | ESP32 DevKitC screw-terminal breakout | – | 10 | 18 | 180 | sigmanortec.ro 38P screw-terminal board | CHECK row spacing against the DevKitC (a review reports a 25 mm pitch mismatch); eMAG sells ESP32 + terminal board as a matched pair at 92 |
| OLED | SSD1306 0.96 in I2C OLED | 12 | 12 | 19 | 228 | sigmanortec.ro SSD1306 0.96 in I2C | expect 1–2 dead on arrival; spares cover it |
| SHT31 | SHT31-D T/RH breakout with PTFE membrane | – | 8 | 50 | 400 | emag.ro SHT31 I2C (2-pack 99) | probe-style cased SHT31 with cable (AliExpress ≈ 31–60) is better in 90 % RH tanks: order 8 on day one as the primary, eMAG as fallback |
| BME680 | BME680 T/RH/P/gas breakout | 9 | 2 | 60 | 120 | optimusdigital.ro BME680 module (in stock) | purple 3.3 V I2C board |
| SCD41 | Sensirion SCD41 NDIR CO2 breakout | 3 | 4 | 230 | 920 | sigmanortec.ro SCD41 module 201 (out of stock on 2026-10-20) / Pimoroni EU 260 | genuine Sensirion SCD41, not SCD40 or MH-Z19; order day one |
| DS18B20 | DS18B20 waterproof probe 1 m | 9 | 15 | 16 | 240 | emag.ro stainless 1 m, 3-pack 47 | test every probe in ice water; 2–3 m cable for hydroponics |
| SOIL | Capacitive soil moisture v2.0 (TL555 version) | 12 | 22 | 7 | 154 | sigmanortec.ro capacitive v2.0 (5) / known-good TLC555 batch (9) | reject NE555 boards; conformal-coat the top edge |
| BH1750 | BH1750 lux breakout | 9 | 9 | 14 | 126 | optimusdigital.ro GY-302 (in stock) | mount behind a clear window |
| FLOAT | Float switch vertical | 3* | 10 | 26 | 260 | emag.ro vertical PP float, side mount | AliExpress ≈ 6 but 2–4 weeks; floats are needed at commissioning, so buy local |
| JSN | JSN-SR04T waterproof ultrasonic | – | 2 | 50 | 100 | emag.ro JSN-SR04T | buy v3.0; 25 cm blind zone |
| FLOW | YF-S401 flow sensor | 2 | 2 | 24 | 48 | emag.ro YF-S401 | calibrate pulses per litre with a jug |
| PHKIT | Analog pH kit (BNC probe + PH-4502C) | – | 2 | 140 | 280 | sigmanortec.ro pH probe + PH-4502C kit | output 0–5 V: divider to ESP32 ADC; store tip in KCl; probe life 6–12 months |
| TDS | Gravity analog TDS module | – | 1 | 28 | 28 | sigmanortec.ro Gravity-style TDS module | 3.3 V compatible |
| TURB | Analog turbidity module | – | 2 | 59 | 118 | emag.ro turbidity module | probe top not waterproof: mount through a lid; relative readings only |
| PHPEN | Handheld pH pen | – | 2 | 42 | 84 | emag.ro pH pen with ATC + calibration powders | |
| TDSPEN | Handheld TDS/EC pen | – | 1 | 25 | 25 | emag.ro TDS/EC pen | must show EC in µS/cm |
| CALSOL | pH 4/7/10 + EC 1413 calibration set | 1 lot | 2 | 55 | 110 | emag.ro pH sachet set 30 + EC 1413 sachets ≈ 25 (est.) | sachets stay uncontaminated; add KCl 3 M storage bottle |
| RTC | DS3231 RTC module | 2 | 2 | 22 | 44 | sigmanortec.ro DS3231 module | remove the LIR2032 charging diode if a CR2032 is fitted |
| SDMOD | microSD breakout module | 9 | 2 | 4 | 8 | sigmanortec.ro microSD SPI module | 3.3 V-native version |
| SDCARD | microSD 32 GB (node logging) | 9 | 2 | 50 | 100 | emag.ro ADATA 32 GB UHS-I | brand-name only; FAT32 |
| ELECCONS | Electronics consumables: 9 node cable kits (pre-crimped JST-XH leads, 22 AWG wire, ferrules, heat-shrink) 270 + 12 inline fuse holders with 5 A fuses 96 + backplates, standoffs, flyback diodes, labels 100 | 1 lot | 1 | 466 | 466 | optimusdigital.ro / emag.ro (platform chapter estimate) | replaces the 4 approved "lots" |
| Subtotal A. Controllers and sensors | 4 615 |
B. Automation and power
| ID | Item | Approved qty | Recommended qty | Unit (RON) | Line (RON) | Source / basis | Note |
|---|---|---|---|---|---|---|---|
| FAN | 12 V 80 mm fan | 4 | 6 | 10 | 60 | optimusdigital.ro CMP-FAN23 12 V 80 mm | only ~21 in stock; Sunon ball-bearing alt. ~25 |
| PUMP | 12 V DC submersible pump 3–5 W | 2 | 5 | 45 | 225 | cleste.ro 12 V brushless 240 L/h (32, snippet) / bitmi.ro JT-500 (60) | budgeted mid-way; confirm stock |
| PERI | 12 V peristaltic dosing pump | 2 | 3 | 135 | 405 | emag.ro G528 12 V peristaltic set | Amazon.de Kamoer ≈ 77; buy 1 m spare pump tubing |
| HEATPAD | 12 V silicone heat pad 10–25 W | – | 4 | 35 | 140 | AliExpress 12 V 20 W silicone pad | not in approved list; 2056 scenario needs it; NOT sold in RO as 12 V; order first, 2–3 weeks; RO 230 V mats are not allowed |
| THERMO | KSD301 45 °C thermostat + 72 °C one-shot thermal fuse (set) | – | 4 | 10 | 40 | optimusdigital.ro / emag.ro KSD301 + thermal fuse | one set per heat pad; one set per heat pad |
| MIST | Ultrasonic mister + 24 V adapter | 2 | 2 | 83 | 166 | emag.ro MY-20 fogger with 24 V PSU | in stock |
| AIRPUMP | COTS 230 V aquarium air pump + stone + tubing | – | 1 | 102 | 102 | maxi-pet.ro Tetra APS 50 + stone + 3 m tube | COTS 230 V on the shelf |
| LEDSTRIP | 12 V full-spectrum LED strip 5 m reel | 4* | 4 | 70 | 280 | emag.ro ZenLED 12 V COB 4000 K 12 W/m 5 m | approved: grow lights 5–10 W ×4; full-spectrum 12 V strips out of stock in RO; AliExpress option ≈ 60 |
| LEDPROFILE | Aluminium LED profile 1 m + diffuser | – | 16 | 31 | 496 | emag.ro profile 1 m + opal diffuser + caps | |
| LEDPANEL | COTS 230 V full-spectrum LED panel 45 W | – | 1 | 136 | 136 | emag.ro EVI Tech Slim 36 W grow panel | hydroponics only; verify real draw; hanging kit |
| SERVO | SG90 micro servo | 4 | 8 | 12 | 96 | optimusdigital.ro SG90 180° (in stock) | power from the 5 V buck |
| MOSFET | MOSFET PWM module (D4184) | 6 | 27 | 11 | 297 | emag.ro dual-D4184 15 A PWM module 23 (9 for the critical path) + AliExpress D4184 ≈ 5 (18) | never IRF520; blended price |
| RELAY | 1-ch 5 V relay module (low-voltage loads only) | 4 | 6 | 9 | 54 | sigmanortec.ro 1-ch 5 V optocoupler relay | low-voltage loads only |
| PSU12 | 12 V 5 A certified brick + DC jack adapter | 4* | 9 | 70 | 630 | emag.ro CE-marked brand 12 V 5 A desktop adapter (LED/CCTV type, ≈ 50–90); Mean Well GST60A12 at AVmall 173 is the premium option | certified brand only; it sits on the mains side |
| PSU5 | 5 V 2 A USB adapter + cable | – | 2 | 16 | 32 | emag.ro OptimStar 5 V 2 A USB-A | CE-marked brand only |
| BUCK | LM2596 buck module | – | 10 | 10 | 100 | emag.ro LM2596 | set 5.0 V before connecting; lock the trimmer |
| SMARTPLUG | COTS Wi-Fi smart plug with power metering | – | 2 | 61 | 122 | Domadoo NOUS A1T (Tasmota pre-flashed, metering) / emag.ro Sonoff S60TPF 53 | no cloud; power metering doubles as an air-pump sensor |
| RCDSTRIP | RCD-protected (30 mA) power strip | – | 2 | 147 | 294 | emag.ro Tracon TFGA-1 30 mA RCD adapter | one per shelf; test button monthly |
| STRIP | Standard 6-socket power strip 3 m | – | 4 | 44 | 176 | dedeman.ro Lohuis 6-socket 3 m strip | mounted on wall/top shelf |
| AUTOCONS | Automation consumables lot (valves, non-return valves, barbs, spray bar PVC, cabling, fuses) | 1 lot | 1 | 213 | 213 | emag.ro aquarium connector kit 120 + 6 non-return valves 48 + PPR spray bar 45 | approved as sprayers/valves/cabling/spares lots |
| Subtotal B. Automation and power | 4 064 |
C. Enclosures and construction
| ID | Item | Approved qty | Recommended qty | Unit (RON) | Line (RON) | Source / basis | Note |
|---|---|---|---|---|---|---|---|
| TANK25 | Glass aquarium ~25 L | – | 1 | 109 | 109 | hornbach.ro MARINA 40×25×24 | EcoColumn pond |
| TANK45 | Glass aquarium ~45 L | – | 3 | 129 | 387 | hornbach.ro MARINA 50×30×30 | Rot, 2026, 2056 |
| TANK63 | Glass aquarium ~63 L | 9* | 4 | 139 | 556 | hornbach.ro MARINA 60×30×30 (54 L) | approved: glass-panel construction packs ×9; Brownfield, Regolith, Living Earth, Capsule; 60×30×35 not sold bare in RO; ultraclear 60×30×36 at 362 if height matters |
| ACRYLIC | Polycarbonate 3 mm, 205×125 cm sheet (= 4 panels 50×100) | 0.75 | 1 | 419 | 419 | dedeman.ro polycarbonate 3 mm 205×125 cm sheet 419 = 4 panels 50×100 | 1 full sheet = 4 panels; 2 more panels below |
| ACRYLIC2 | Acrylic panel 3 mm 50×100 cm from a local plastics shop | – | 2 | 100 | 200 | local plastics shop (estimate) | designs use 5.85 panels in total |
| MESH | Fine mesh per m² | 1 lot | 2 | 19 | 38 | hornbach.ro fibreglass mesh 120 cm, per m | |
| SILICONE | Aquarium-safe silicone tube | 4 | 6 | 43 | 258 | hornbach.ro Soudal aquarium silicone 280 mL | |
| TUBING | Tubing lot: 5 m silicone 6 mm ID + 50 m PVC Cristal 8×10 mm | 1 lot | 1 | 229 | 229 | emag.ro silicone 25/m + dedeman.ro Cristal roll 104 | approved 20 m; silicone only where needed |
| RESERVOIR | Food-grade container 10–20 L with lid | 4 | 5 | 48 | 240 | dedeman.ro 20 L HDPE food-grade canister with lid | wrap in black foil for hydroponics |
| BOXPLASTIC | Opaque storage box 30–60 L | – | 3 | 40 | 120 | leroymerlin.ro 45 L storage box with lid | buy opaque colour for hydroponics |
| BOX | IP65 junction box | 6 | 9 | 31 | 279 | hornbach.ro Pawbol 150×110 IP65 transparent lid (snippet) | transparent lid shows the OLED |
| GLAND | PG7/PG9 cable gland | 20 | 80 | 2 | 160 | emag.ro Pawbol PG7 10-pack 17 | 70 % PG7, 30 % PG9, plus blanking plugs |
| HINGES | Small hinges + clamp latches + handles/fasteners lot | 1 lot | 1 | 124 | 124 | dedeman.ro hinges 12×3 + latches 4×12 + fasteners est. 40 | |
| OBSTUBE | Transparent perforated observation tube | 2 | 2 | 0 | 0 | costed in Section 5.8 sub-BOM (PVC 32/40 mm drilled) | |
| MOUNT | Mounting lot (shelf brackets, aluminium angle, rigid PVC tubes and fittings) | 1 lot | 1 | 222 | 222 | hornbach.ro aluminium angle ×6 + brackets + PVC/PPR tube lot | |
| TOOLS | Small tools lot: 2 UNI-T multimeters 124, hole saw 51 mm 33, step drill 30, glue gun 41, auto stripper 26, side cutters 25, caulking gun 15 (pliers and screwdrivers from the school) | 1 lot | 1 | 300 | 300 | dedeman.ro / leroymerlin.ro / hornbach.ro: 2 cutters, 2 strippers, 2 pliers, hole saw 51, step drill, 2 glue guns, caulking gun, 2 UNI-T multimeters | |
| LABCONS | Syringes, sample containers and bags, labels, markers (lot) | 1 lot | 1 | 165 | 165 | pharmacy / emag.ro / office: syringes 45 + containers & bags 60 + markers & labels 60 | |
| PANELS | Printed information panels: 10× A3 laminated prints (foamboard upgrade later) | 1 lot | 1 | 100 | 100 | school printer + laminating | get 2–3 quotes |
| METROLOGY | Metrology kit: reference thermometer 60, salt-test calibration jars and salts 40, cable trunking and drip-loop clips 80 (crimp tool dropped: pre-crimped leads) | – | 1 | 180 | 180 | optimusdigital.ro / dedeman.ro (platform chapter estimate) | |
| Subtotal C. Enclosures and construction | 4 086 |
D. Hub and network
| ID | Item | Approved qty | Recommended qty | Unit (RON) | Line (RON) | Source / basis | Note |
|---|---|---|---|---|---|---|---|
| PI5 | Raspberry Pi 5 4 GB + 27 W PSU + active cooler case | – | 1 | 557 | 557 | ardushop.ro Pi 5 4 GB 463 + optimusdigital.ro official 27 W PSU 67 + Argon active cooler 27 | authorised reseller only; eMAG marketplace is over 1 000 |
| SD64 | 64 GB A2 microSD | 1 | 2 | 132 | 264 | emag.ro SanDisk Ultra 64 GB A1 | prefer Extreme A2 or High Endurance for 24/7 writes |
| USBSTICK | USB stick 64 GB for backups | – | 1 | 90 | 90 | emag.ro SanDisk 64 GB | backup rotation |
| NETCONS | Ethernet patch cable + USB/HDMI cables for the Pi (lot) | – | 1 | 20 | 20 | emag.ro patch cable + USB/HDMI cables | |
| PIRTC | Pi 5 RTC battery | – | 1 | 30 | 30 | estimate | |
| Subtotal D. Hub and network | 961 |
E. Biology and consumables per ecosystem
| ID | Item | Approved qty | Recommended qty | Unit (RON) | Line (RON) | Source / basis | Note |
|---|---|---|---|---|---|---|---|
| E01 | 1 Rot: organisms + substrate + consumables + tools (from Section 5.1 sub-BOM) | – | 1 | 715 | 715 | Section 5.1 | |
| E02 | 2 EcoColumn: rack + water tests + biology + lab consumables (Section 5.2) | – | 1 | 1 159 | 1 159 | Section 5.2 | includes 130 RON shelving |
| E03 | 3 Brownfield: soils + seeds + amendments + tools (Section 5.3) | – | 1 | 714 | 714 | Section 5.3 | |
| E0405 | 4–5 Future pair: seeds + substrate + CO2 generator + tools (Section 5.4) | – | 1 | 590 | 590 | Section 5.4 | |
| E06 | 6 Regolith: basalt dust + sand + amendments + pots + scales (Section 5.6) | – | 1 | 757 | 757 | Section 5.6 | |
| E07 | 7 Hydroponics: nutrients + media + frame + jars + PPE (Section 5.7) | – | 1 | 702 | 702 | Section 5.7 | |
| E08 | 8 Living Earth: tubes + endoscope + tea bags + Berlese + biology (Section 5.8) | – | 1 | 862 | 862 | Section 5.8 | |
| E09 | 9 Time Capsule: glazier lid, plinth hardware, substrate, plants, capsule box (Section 5.9) | – | 1 | 1 764 | 1 764 | Section 5.9 | SCD41 deferred to 2027 |
| Subtotal E. Biology and consumables per ecosystem | 7 263 |
Summary by group
| Group | Approved list priced as-is (RON) | Recommended plan (RON) | Recommended (EUR) |
|---|---|---|---|
| A. Controllers and sensors | 3 565 | 4 615 | 905 |
| B. Automation and power | 1 489 | 4 064 | 797 |
| C. Enclosures and construction | 3 314 | 4 086 | 801 |
| D. Hub and network | 132 | 961 | 188 |
| E. Biology and consumables per ecosystem | – | 7 263 | 1 424 |
| Total | 8 500 | 20 989 | 4 115 |
Contingency 15 %: 3 148 RON. Total with contingency: 24 137 RON (4 733 EUR).
6.3 Per-ecosystem cost (as designed in Chapter 5)
These are the subtotals each ecosystem section declares, including its share of node electronics, enclosure, biology and tools. They overlap with the tables above (the catalog items are the same parts) and are shown so the school can see where the money goes.
| Ecosystem | Sub-BOM total (RON) | Of which biology, consumables, tools (RON) | Notes |
|---|---|---|---|
| 1 Orchestra of Rot | 1 874 | 715 | two BME680, one SCD41, mister, carbon filter |
| 2 EcoColumn | 2 774 | 1 159 | includes 130 RON shelving, water tests, pH kit, two turbidity probes |
| 3 Brownfield | 1 635 | 714 | 63 L tank, heat pad, 48-cup replication bench |
| 4–5 Future 2026 / 2056 | 3 047 | 590 | two full nodes, two SCD41, two heat pads, four servos |
| 6 Forests in Space | 1 718 | 757 | basalt dust, 0.001 g scale; optional 1 kg LHS-1 simulant (≈ 650) not included |
| 7 Hydroponic Jungle | 2 131 | 702 | LED panel, air pump, three peristaltic pumps, nutrients |
| 8 Living Earth | 2 066 | 862 | SCD41, endoscope, observation tubes, tea bags, Berlese kit |
| 9 Time Capsule | 2 646 | 1 764 | glazier lid, plinth hardware, RTC and SD logging, plants, capsule box; SCD41 deferred to 2027 |
| Sum of ecosystem sub-BOMs | 17 891 | 7 263 | catalog parts inside these sums are the same parts as groups A–C above |
| 8b Carnivorous Bog (alternative to 8) | 1 358 | 570 | only if chosen instead of Living Earth |
6.4 Reconciliation with the approved ARCUB list
Every approved line, what this plan buys against it, and why. "Lot" lines in the proposal had no quantity; they are mapped to the consumables lines above.
| Approved line (Annex 2) | Approved qty | This plan | Change and reason |
|---|---|---|---|
| ESP32 development boards | 12 | 12 ESP32 + 12 screw-terminal breakouts | same count; breakouts added so final builds have no loose wires |
| BME680 T/RH/VOC sensors | 9 | 2 BME680 + 8 SHT31 | BME680 only where VOC is the science (Rot); SHT31 survives wet air |
| DS18B20 waterproof probes | 9 | 15 | two per tank where thermostat feedback or paired zones need them, plus spares |
| BH1750 light sensors | 9 | 9 | unchanged |
| Capacitive soil moisture v2 | 12 | 22 | replicated plots and known batch defects |
| CO2 sensor breakouts (real CO2) | 3 | 4 SCD41 | Rot, Living Earth, 2026, 2056 (paired); Time Capsule deferred to 2027 |
| Water-level sensors | 3 | 10 floats + 2 ultrasonic | floats are the interlocks, ultrasonic gives continuous level |
| Water-flow sensors | 2 | 2 YF-S401 | type fixed (YF-S201 cannot read these flows) |
| OLED displays | 12 | 12 | unchanged |
| microSD modules + cards | 9 + 9 | 2 + 2 | hub logging is primary; local logging only where independence matters |
| RTC modules | 2 | 2 | one per SD logger |
| Breadboards, jumpers, connectors, consumables (4 lots) | 4 lots | 1 electronics consumables line (466) | prototyping kit kept; final builds use JST and screw terminals |
| Peristaltic dosing pumps | 2 | 3 | hydroponics A, B, pH-down |
| Submersible water pumps | 2 | 5 | EcoColumn rain, 2026 and 2056 irrigation, hydroponics circulation and top-up |
| Ultrasonic misting modules | 2 | 2 | unchanged; each with its own 24 V adapter |
| 5 V / 12 V fans | 4 | 6 | six enclosures need ventilation control |
| SG90 microservos | 4 | 8 | Rot flap, EcoColumn valve, 2026/2056 gates, Living Earth lid, spare |
| MOSFET switching modules | 6 | 27 | 25 PWM loads across nine ecosystems plus two spares; D4184 type only |
| Relay modules | 4 | 6 | low-voltage loads only |
| Grow lights (5–10 W) | 4 | 4 reels of 12 V LED strip + 16 profiles + 1 LED panel | eight enclosures need light; 5–10 W is not enough for any of them |
| Water reservoirs | 4 | 5 + 3 opaque boxes | one per automated water system |
| Silicone / PVC tubing | 20 m | 5 m silicone + 50 m PVC roll | silicone only where needed |
| Sprayers, nozzles, connectors; valves (2 lots) | 2 lots | automation consumables line (213) | mapped |
| Power supplies / adapters | 4 | 9 × 12 V bricks + 2 × 5 V + 10 bucks | nine nodes with 12 V loads |
| Automation cabling; automation spares (2 lots) | 2 lots | in electronics consumables and spare pool | mapped |
| Glass-panel construction packs | 9 packs | 8 COTS glass tanks (1×25 L, 3×45 L, 4×54 L) + 1 opaque hydroponics box | leak-tested tanks; the engineering is in lids and internals |
| Transparent acrylic / polycarbonate sheets | 3 | 1 polycarbonate sheet (4 panels of 50×100) + 2 acrylic panels | designs use about 6 panels |
| Fine insect / ventilation mesh | 1 lot | 2 m | mapped |
| Small hinges | 12 | 12 + 4 latches | mapped |
| Handles / fasteners | 1 lot | in hinges line | mapped |
| Cable glands | 20 | 80 | about 9 per node |
| Waterproof electrical connectors | 1 lot | in electronics consumables | mapped |
| Aquarium-safe silicone | 4 tubes | 6 | ten tanks, lids and dividers |
| Rigid acrylic / PVC tubes and fittings; mounting supports (2 lots) | 2 lots | mounting lot (222) | mapped |
| Electronics project cases / junction boxes | 6 | 9 | one per node |
| Transparent perforated observation tubes | 2 | 2 | made from drilled PVC, costed in Section 5.8 |
| Small tools | 1 lot | tools lot (300) + metrology kit (180) | multimeters, drills, reference thermometer; pliers and screwdrivers from the school |
| pH / EC calibration and storage solutions | 1 lot | 2 sets + 2 pH kits + 1 TDS + 2 pH pens + 1 TDS pen + 2 turbidity | probes were missing |
| Syringes; sample containers; labels (3 lots) | 3 lots | lab consumables line (165) | mapped |
| Printed durable labels / information panels | 1 lot | 10 A3 laminated prints (100) | mapped |
| microSD card for Raspberry Pi | 1 | Raspberry Pi 5 kit + 2 SD cards | the computer was missing; nodes use the school Wi-Fi |
| (not listed) | – | heat pads, thermostats, air pump, smart plugs, RCD adapters, power strips, biology for nine ecosystems | the living and the safety parts of the project |
6.5 Procurement plan
| When | What | Where | Why |
|---|---|---|---|
| Tue 2026-10-21 | Heat pads ×4, full-spectrum LED strip option, Kamoer peristaltic alternative | AliExpress / Amazon.de | 2–3 week lead time; nothing else may wait for China |
| Tue–Wed 2026-10-21/22 | All electronics (group A), MOSFETs, bucks, bricks, boxes, glands | optimusdigital.ro, cleste.ro, sigmanortec.ro, emag.ro | Romanian stock, 2–5 day delivery; order from two shops for critical items |
| Wed 2026-10-22 | Raspberry Pi 5 kit, SD cards, smart plugs, RCD adapters | emag.ro, pcgarage.ro | hub must be up by 2026-10-30 |
| Thu 2026-10-23 | Tanks, polycarbonate, silicone, mesh, hinges, tools, substrates | hornbach.ro, dedeman.ro, leroymerlin.ro (store pickup) | bulky; one van trip |
| Fri 2026-10-23 noon | "China fallback" check: anything not confirmed in a Romanian shop is ordered abroad the same day with a local substitute | – | see Chapter 7 |
| 2026-11-03 to 11-10 | Live organisms (worms, springtails, isopods, snails, aquarium plants), hydroponic nutrients, seeds | OLX breeders, secretgarden.ro, hornbach.ro, grow shops | ship live animals before mid-November cold; substrates must be ready first |
| 2026-11-20 | Glazier order for the Time Capsule lid | local glazier | needed by 2026-12-01 |
Invoices: keep a mapping from each approved line to the actual invoice line (table 6.4 is that mapping). Confirm with ARCUB whether foreign marketplace invoices (AliExpress, Amazon.de) are eligible before placing them; if not, the heat pads are the only item at risk, and the fallback is a 12 V PTC heater module from optimusdigital.ro when it is back in stock.
6.6 Cost reductions applied (2026-10-20)
Requested cuts and the further trims made in the same pass. Savings are against the first full costing; electronics prices are the provisional ones used in that costing.
| Cut | Saving (RON) | What it costs the project |
|---|---|---|
| No NVMe drive or M.2 HAT for the Pi | 200 | SD-card wear risk; mitigated by nightly backups and a spare imaged card |
| No project router (school Wi-Fi used) | 180 | Depends on school IT providing a 2.4 GHz PSK SSID; fallback router stays on the list as optional |
| Time Capsule CO2 sensor deferred to 2027; no spare SCD41 | 440 | The sealed-tank CO2 cycle is not recorded in year one; pod slot reserved |
| No spare BME680 | 75 | – |
| RCD adapters 4 → 2; power strips 6 → 4; smart plugs 4 → 2; no separate timer plugs (Capsule keeps one) | 574 | Two shelf power groups instead of four; capsule light fail-safe unchanged |
| Spares trimmed: bricks 10 → 9, 5 V adapters 3 → 2, bucks 12 → 10, breakouts 12 → 10, MOSFET 30 → 27, relays 8 → 6, pumps 6 → 5, fans 7 → 6, DS18B20 16 → 15, soil 24 → 22, SD/RTC sets 3 → 2, TDS pen 2 → 1, calibration sets 3 → 2 | 596 | Failures in these parts become a same-week purchase |
| Peristaltic pumps 4 → 3 (Capsule top-up by syringe) | 135 | Manual, which the ten-year design prefers anyway |
| Air pumps 2 → 1 | 102 | EcoColumn pond is not aerated (its science does not need it) |
| LED strip 5 → 4 reels, profiles 18 → 16 | 132 | None; 14 m are actually cut |
| No new shelving (existing school furniture, rated) | 260 | Must verify the furniture can carry 50 kg per tank |
| Time Capsule: existing cabinet instead of a new one, MARINA tank, one timer plug, laminated panel, plastic archive box, fewer jars, prints, cork, moss, cultures | 1 466 | Capsule total 4 112 → 2 646 |
| EcoColumn: lighter shelving, strips plus one PO4 test, shared scale, consumables moved to the project lot | 341 | – |
| Hydroponics: panel hung from the shelf (no PVC frame), foil reflectors, shared scale and hole saw | 215 | – |
| Polycarbonate 2 sheets → 1 sheet + 2 acrylic panels | 219 | 6 panels instead of 8 |
| Tools and metrology: no crimp tool (pre-crimped leads), school pliers and screwdrivers | 326 | – |
| Electronics consumables lot trimmed | 180 | – |
| Printed panels: laminated A3 instead of foamboard | 250 | Upgrade later from the school budget |
| Glands 100 → 80, boxes 10 → 9, no spare 12 L tank, Brownfield optional biology, Rot BTI granules, Regolith feldspar, Living Earth desk lamp, Future pair spare scale | 362 | – |
| Total reduction | ≈ 5 350 (25 625 → 20 269 at the provisional electronics prices; the final total with researched electronics prices is 20 989 RON) | – |
7. Programme: schedule, people, pedagogy, risks
Planning assumptions (confirm by Fri 2026-10-23)
| # | Assumption | Confirm with | If wrong |
|---|---|---|---|
| A1 | Autumn break (vacanța de toamnă) for gimnaziu: Sat 2026-10-31 – Sun 2026-11-08. No sessions in that week. | School secretariat / MEC structure order | If liceu students are in school during that week, run one optional catch-up session (node soldering is not needed, so only kit sorting and planning) |
| A2 | Winter break starts Sat 2026-12-19 and runs to about Sun 2027-01-10. | Secretariat | Showcase stays in the week of Dec 14–18 regardless |
| A3 | Project sessions Tue and Thu, 14:00–15:30 (2 × 90 min per week) in the lab room. | Both teachers | Shift the day labels; the sequence stays the same |
| A4 | Three Saturday build days, 09:30–15:30, with 2 Alacrity engineers present: Sat Nov 14, Sat Nov 21, Sat Dec 5. | Head teacher (building access, caretaker) | Move to the following Saturday. Nov 21 has no slack |
| A5 | Mon Nov 30 (Sf. Andrei) and Tue Dec 1 (Ziua Națională) are public holidays. The Tue Dec 1 session moves to Wed Dec 2. Automated treatments can still start on Dec 1 through Home Assistant schedules. | – | – |
| A6 | 9 teams × 3–4 students (27–36 students), 2 teachers (T1 = project coordinator, biology/science; T2 = physics/ICT/technology), Alacrity engineers E1 + E2 at ~4 h/week each, plus the 3 build days. | ARCUB contract / Alacrity | With only one engineer, E1 covers sessions and the build days lose one adult. Keep the 1:8 ratio for tool work by adding T2 |
| A7 | ARCUB deliverables due Fri 2026-12-18. Public showcase Tue Dec 15 – Thu Dec 17. | ARCUB contract (check the visibility clauses and the budget-line transfer threshold) | – |
Adult time budget, Oct 26 – Dec 18: E1 + E2 ≈ 2 × 4 h × 8 weeks = 64 h plus 3 build days × 2 × 6 h = 36 h. Total ≈ 100 h. The schedule below uses about 90 h, which leaves ~10 h as contingency.
Master schedule
gantt
title MICROCOSM programme Oct 2026 - Jun 2027
dateFormat YYYY-MM-DD
axisFormat %d %b
section School calendar
Autumn break (assumed) :done, cal1, 2026-10-31, 2026-11-09
Winter break (assumed) :done, cal2, 2026-12-19, 2027-01-11
section Procurement
Order electronics :crit, pr1, 2026-10-21, 3d
Order tanks and materials :crit, pr2, 2026-10-21, 3d
Deliveries RO shops :crit, pr3, 2026-10-26, 2026-11-07
China fallback window :pr4, 2026-10-23, 2026-11-20
China fallback latest arrival :milestone, pr5, 2026-11-20, 0d
section Platform
Hub setup :pl1, 2026-10-26, 2026-10-31
Node v1 reference build and firmware :pl2, 2026-10-27, 2026-11-07
Node kits handed to teams :milestone, crit, pl3, 2026-11-09, 0d
section Workshops
W1 Kickoff and safety :milestone, ws1, 2026-10-27, 0d
W2 Ecosystem science design :milestone, ws2, 2026-10-29, 0d
W3 Node assembly :milestone, crit, ws3, 2026-11-10, 0d
W4 ESPHome and dashboards :milestone, crit, ws4, 2026-11-12, 0d
W5 Design sprint (build day 1) :milestone, ws5, 2026-11-14, 0d
W6 Calibration lab :milestone, ws6, 2026-11-17, 0d
W7 Data analysis :milestone, ws7, 2026-12-03, 0d
W8 Presentation skills :milestone, ws8, 2026-12-08, 0d
section Ecosystem builds
Enclosures and substrates :crit, eb1, 2026-11-09, 2026-11-21
Instrumentation and commissioning :crit, eb2, 2026-11-16, 2026-11-28
Biology established :eb3, 2026-11-20, 2026-12-05
section Experiments
Baseline :ex1, 2026-11-23, 2026-12-05
Treatments :ex2, 2026-12-01, 2026-12-19
Data review :crit, ex3, 2026-12-07, 2026-12-12
section Time Capsule
Capsule design :tc1, 2026-11-23, 2026-11-28
Capsule build :tc2, 2026-12-01, 2026-12-12
Capsule sealed :milestone, tc3, 2026-12-14, 0d
section Showcase and reporting
Rehearsal :milestone, sh1, 2026-12-11, 0d
Public showcase :crit, sh2, 2026-12-15, 2026-12-18
ARCUB report submitted :milestone, crit, sh3, 2026-12-18, 0d
section Continuation
Round 2 experiments :co1, 2027-01-11, 2027-06-19
Monthly data reviews :co2, 2027-01-14, 2027-06-19
Week-by-week
| Week | Dates | What happens | Who | Outputs | Risks |
|---|---|---|---|---|---|
| W0 | Tue Oct 20 – Fri Oct 23 | Final BOM reconciliation against the ARCUB list. All RO orders placed Oct 21–23. Anything not in stock at an RO shop on Oct 23 goes to AliExpress the same day and a RO substitute is named. Teams formed. Parental consent and photo forms sent home. Room layout agreed: tank tables, mains shelf above, RCD strips. | T1 (orders, forms), E1 (BOM, substitutes), head teacher (room) | Purchase orders and pro-forma invoices; substitution log; team list; consent forms out | Stock-outs (SCD41, cased SHT31, TL555 soil probes); slow invoice approval by the school bursar |
| W1 | Oct 26 – Oct 30 | Deliveries start. E1 obtains the 2.4 GHz WPA2-PSK SSID and reservations from school IT, sets up the Pi 5 with HA OS and add-ons, and a test dashboard. E2 builds one reference node (mc-00-ref) plus the ESPHome YAML templates. Tue Oct 27 W1 kickoff and safety. Thu Oct 29 W2 science design: each team drafts its question, hypothesis and variables. | E1, E2, T1, T2, all students | Hub online; mc-00-ref on the dashboard; signed safety pledge per student; draft experiment plan per team (1 page) | School IT objects to the router; late tank delivery |
| W2 | Nov 2 – Nov 6 (break) | No student sessions. Remaining deliveries arrive. T1/T2 receive and check goods against invoices (proces-verbal de recepție). E1/E2 sort node kits into 9 labelled bags and bench-test every sensor on mc-00-ref; DOA parts go back for replacement. | T1 (reception), E1/E2 (kit test, ~6 h) | Goods-received log; 9 tested node kits plus spares; DOA list | DOA sensors with no time to replace; capacitive probe batch defects |
| W3 | Nov 9 – Nov 13 | Mon Nov 9 kits issued. Tue Nov 10 W3 node assembly: students build their own node in an IP65 box on a screw-terminal board. Thu Nov 12 W4 ESPHome and HA: each team flashes its node and sees its own sensors. Teams clean tanks, cut and fit substrate layers and draw lid/vent designs. Tanks are placed on tables and never moved again. | Students (build), E1 + E2 (mentor), T2 | 9 nodes reporting to HA (OLED shows IP + values); lid sketches; tanks in final position | Wi-Fi or flash problems eat W4; absent students |
| W4 | Nov 14 – Nov 20 | Sat Nov 14 Build Day 1 (W5 design sprint): lids, vents and mounts from acrylic, mesh and hinges; substrates layered; glands drilled in the node boxes. Tue Nov 17 W6 calibration lab (soil probes per substrate, pH/EC pens, DS18B20 ice and room cross-check). Thu Nov 19 sensors installed in enclosures. Biology goes in from Nov 20: plants, decomposers, inocula. | Students, E1 + E2 (Sat), T1 (biology sourcing) | Lids and vents fitted; calibration table per probe in the Data folder; first plantings | Glass breakage while drilling or fitting (no student glass cutting); plants not sourced |
| W5 | Nov 21 – Nov 27 | Sat Nov 21 Build Day 2: actuators (12 V pumps, fans, LED strips in profiles, heat pads with thermal fuse) wired SELV-side only. E1 places the mains-side COTS devices (bricks, smart plugs, LED panel, air pump) on the shelf with drip loops. Automations created in HA. Commissioning checklist signed per ecosystem by Fri Nov 27. Baseline logging starts Nov 23. Capsule Council designs the Time Capsule (Nov 23–27). | Students, E1 + E2, T1/T2 | Commissioning certificate × 9; HA automations; baseline running; Capsule design brief v1 | Critical: any ecosystem not commissioned by Nov 27 cannot reach 2 weeks of data by Dec 11 |
| W6 | Nov 30 – Dec 4 | Holidays Mon/Tue. Treatments switch on from Dec 1 (scheduled in HA, e.g. 2056 heat and drought profile, Brownfield salt dose) once a team has ≥ 7 days of clean baseline. Wed Dec 2 session (moved from Tue): role rotation 2, treatment checks. Thu Dec 3 W7 data analysis in Google Sheets on real CSV. Capsule build starts. Sat Dec 5 Build Day 3: Capsule build, fixes, panel drafts. | Students, T1/T2, E1 + E2 (Sat) | Treatment logs started; first chart per team; Capsule hardscape plus node | Plant die-off from low light; gnats; heat-pad faults |
| W7 | Dec 7 – Dec 11 | Tue Dec 8 W8 presentation skills. Data review: each team picks one chart and writes its claim and evidence. Information panels sent to print Wed Dec 9 (latest). Capsule build finished. Fri Dec 11 rehearsal (full run, timed). Evidence folder checked against the ARCUB list. | Students, T1 (print order), T2 (rehearsal), E1 (dashboard kiosk view, 2 h) | 9 charts; 9 panels at the printer; showcase run-sheet; evidence folder ≥ 90 % complete | Printer turnaround; missing consent forms block photos |
| W8 | Dec 14 – Dec 18 | Mon Dec 14 Time Capsule sealed (ceremony, logbook entry #1). Tue Dec 15 – Thu Dec 17 public showcase (2 h slots, teams present in rotation). Fri Dec 18 ARCUB final report and evidence pack submitted. Winter care rota and alerts tested. | All; T1 (report), E1 (data annex, remote alerts) | Showcase held; attendance list; final report; data export; winter rota | Visitor accidents; report missing invoices |
| W9 | Sat Dec 19 – ~Jan 10 (break) | Winter care: automated light and irrigation; T1/T2 or the caretaker visit Mon + Thu (15 min checklist); HA alerts go to T1 and E1 by push or email. Restart Jan 11 with round 2 planning. | T1/T2 (visits), E1 (remote monitoring) | Visit log; no losses | Power cut or Pi down over the break; dry-out |
Critical path & slack
flowchart LR
A["Orders placed Oct 21-23"] --> B["Electronics delivered by Nov 6"]
B --> C["Kits tested and issued Nov 9"]
H["Hub Oct 26-30"] --> D
C --> D["W3 node assembly + W4 ESPHome Nov 10-12"]
A --> E["Tanks and materials by Nov 6"]
E --> F["Enclosures and substrates Nov 9-20"]
D --> G["Instrumentation and commissioning by Nov 27"]
F --> G
F --> I["Biology in from Nov 20"]
G --> J["2 weeks of data Nov 28 - Dec 11"]
I --> J
J --> K["Data review and one chart per team Dec 7-11"]
K --> L["Showcase Dec 15-17"]
L --> M["ARCUB report Dec 18"]
Gates and slack
| Gate | Gated by | Gates | Slack | If it slips |
|---|---|---|---|---|
| G1 Orders placed | BOM sign-off Oct 21 | All of it | 0 days | Every day lost here comes straight off the data window |
| G2 Electronics delivered (ESP32, terminal boards, OLED, SHT31, DS18B20, BH1750, soil probes, boxes, glands, bricks, buck, MOSFET) | G1 | Kit test (Nov 2–6), W3 Nov 10 | ~3 days (kits can be tested Mon Nov 9 morning) | Teams assemble with whatever has arrived; missing sensors are added as plug-in screw-terminal connections later |
| G3 Hub online | Pi 5, SD64, Wi-Fi credentials from IT | W4 Nov 12 | ~9 days | Fallback is W4 on a laptop running the ESPHome dashboard with the router only, then migrate to the Pi |
| G4 Tanks + acrylic + mesh + silicone | G1 | Enclosures Nov 9 | ~5 days (substrate prep and lid design can start without tanks) | Start substrates in buckets; silicone needs 24–48 h cure before water or substrate goes in |
| G5 Commissioning ×9 | G2, G3, G4, W6 calibration | Data window | ~2 days (latest Sun Nov 29 for 14 full days to Dec 12) | Drop that team's actuators. Commission sensors only (minimum viable) |
| G6 Biology alive | Plant/organism sourcing (order by Nov 13), enclosures | Treatments, panels | ~5 days for the MVS (only "alive") | Use garden-centre plugs (Dedeman/Hornbach) instead of seeds; cress and radish give a visible result within 5–7 days |
| G7 Panels printed | Chart + text by Dec 9 | Showcase | ~2 days | Print A3 on the school laser printer, laminate |
| G8 Report | Evidence folder kept live from Oct 21 | ARCUB | ~1 day | Do not leave the evidence collection for Dec 18 |
China fallback rule (binding)
- On Fri Oct 23 at 12:00, E1 checks every BOM line. Any item not orderable in stock from a RO shop (optimusdigital, cleste, ardushop, robofun, sigmanortec, emag) is ordered on AliExpress the same day, choosing "Choice" or EU-warehouse offers where they exist.
- At the same time a RO substitute is named and bought, so that the build never waits for China. Typical pairs:
| Missing item | RO substitute used meanwhile | Swap-in |
|---|---|---|
| SCD41 | Run respiration ecosystems without CO2. BME680 gas resistance as a qualitative indicator (labelled "not CO2") | When it arrives; 1 week of re-baseline |
| Cased SHT31 | Bare SHT31-D breakout behind a PTFE vent plug or in a perforated tube, mounted high | January |
| Capacitive v2.0 with TL555 | Any v1.2/v2.0 probe in stock, each one tested on mc-00-ref (dry/wet reading spread > 800 counts) | January (re-calibrate) |
| JSN-SR04T | 2 float switches only (low/high) | January |
| YF-S401 | Pump runtime × flow measured by a bucket test (L/min) | January |
| TERMBOARD | DevKitC on a perfboard with screw terminal blocks (E-supervised) | When it arrives, before final mounting |
| PERI | Manual dosing with a syringe, logged in HA via an input button | January |
- Latest useful arrival is Fri Nov 20. Anything arriving later is installed in January. The substitute stays for the showcase.
- AliExpress orders: keep each order < 150 EUR (IOSS, VAT charged at checkout, no customs hold). Download the invoice PDF straight away. Check with ARCUB whether foreign marketplace invoices are eligible. If they are not, the fallback is paid from Alacrity's own contribution or bought from Amazon.de with an invoice on the school's fiscal code (CIF).
Minimum viable showcase (MVS)
The ARCUB deliverable is met if, on Dec 15:
| # | MVS criterion | Evidence |
|---|---|---|
| 1 | All 9 ecosystems built, alive and instrumented (≥ 1 T/RH or DS18B20 + 1 soil or water sensor reporting) | Photos; HA "all nodes online" screenshot |
| 2 | Hub dashboard live (Grafana or HA kiosk on a screen) | Live demo + screenshot |
| 3 | ≥ 14 days of continuous data per ecosystem (Nov 28 – Dec 11) | CSV export in Drive |
| 4 | Each team presents one chart with a claim | Panel + slide |
| 5 | Safety documentation complete | Signed pledges, incident log, commissioning checklists |
Can slip to January without hurting the deliverable: SCD41-based respiration experiments, peristaltic dosing automation, EcoColumn flow and turbidity, servo vents/gates, the Time Capsule's long-term alerting beyond the basics, Arduino/PlatformIO work on spare boards, statistical replication (round 2), full treatment phases (a treatment that started Dec 1–7 with partial data still counts), and any AliExpress-dependent sensor.
Cannot slip: G1, G5, the panels, the evidence folder, the Capsule sealing (it is the showcase's public moment). If the Capsule is late it is sealed "planted but unsealed" with a lid ceremony in January. That is acceptable, but avoid it.
Team structure & roles
Per-team roles (each team of 3–4; rotate monthly)
| Role | Does | Weekly time | Rotation |
|---|---|---|---|
| Lead Scientist | Owns the question, hypothesis, variables and controls; keeps the experiment plan current; writes the claim for the chart | In sessions | Rotation 1: Oct 27 – Nov 27. Rotation 2: Dec 2 – Jan 29 (stable through the showcase). Then monthly |
| Lead Engineer | Owns node, wiring (SELV only), ESPHome YAML, lids/vents/mounts; runs the commissioning checklist | In sessions + build days | Same |
| Data Steward | Checks the dashboard every session, flags gaps, exports CSV, keeps the calibration table and the data dictionary | 10 min per session | Same |
| Biology Keeper | Watering/feeding schedule, plant/organism health log, pest checks, photo of the ecosystem every session from a fixed spot (same angle) | 10 min per session | Same. In 3-person teams the Lead Scientist also acts as Biology Keeper |
Rule: every student must hold the Lead Engineer and the Lead Scientist role at least once by June. The rotation handover is a 10-minute "role card" briefing, and the outgoing holder signs the handover in the lab notebook.
Cross-team roles
| Role | Who | Does | Doesn't |
|---|---|---|---|
| Hub Admins ×2 | 2 students (1 liceu + 1 gimnaziu ideally), mentored by E1 | Add nodes to HA, manage dashboards, check the nightly CSV export, keep the IP/lease table, run the weekly backup check | Touch the router admin password or remote access (E1 only); edit another team's YAML without the team present |
| Safety Officers ×2 | 2 students, mentored by T2 | Run the 2-minute safety check at the start of every session (drip loops, RCD test button monthly, no water near the mains shelf, PPE out), keep the incident log, may stop any activity | Fix electrical faults (they report to an adult) |
| Capsule Council | 1 delegate per team (9) + T1 as chair | Design brief, species choice, longevity rules, Capsule Charter, logbook, sealing ceremony, Jan handover to the younger cohort | Decide alone; decisions go by majority vote, recorded in minutes |
Adult roles
| Adult | Does | Doesn't |
|---|---|---|
| T1 Teacher-coach (coordinator) | Programme lead; procurement and invoices; consent; biology sourcing; assessment; ARCUB report; asks questions ("what would convince you?") | Write students' hypotheses or conclusions |
| T2 Teacher-coach (technology) | Supervision of tools and SELV wiring; safety lead; rehearsal; second marker | Wire or assemble nodes for teams |
| E1 Alacrity engineer-mentor (platform) | Wi-Fi access with school IT, Pi/HA setup, reference node, YAML templates, all mains-side placement (COTS bricks, smart plugs, LED panel, air pump on the shelf, RCD strips), remote alerts, data annex | Build team nodes; debug by taking the keyboard (the rule is hands behind the back: explain, point, let the student do it) |
| E2 Alacrity engineer-mentor (sensors/actuators) | Kit testing, calibration lab, actuator/MOSFET review, heat-pad safety sign-off, design sprint coaching | Same as E1 |
| Any adult | Glass cutting or drilling glass (if needed at all), mains-side setup, final sign-off of the commissioning checklist | Anything else students can do safely themselves |
RACI for main deliverables
R = does the work, A = accountable (one per row), C = consulted, I = informed.
| Deliverable | Team (students) | Hub Admins | Safety Officers | Capsule Council | T1 | T2 | E1 | E2 |
|---|---|---|---|---|---|---|---|---|
| Procurement & substitution log | I | I | – | – | A/R | C | R | C |
| Pi + HA platform + Wi-Fi access | I | R | – | – | I | I | A/R | C |
| Reference node + YAML templates | I | C | – | – | I | I | R | A/R |
| Team node (assembled, flashed) | R | C | C | – | I | A | C | C |
| Enclosure, lid, vents, substrate | R | – | C | – | C | A | I | C |
| Mains-side installation | I | I | C | – | I | C | A/R | C |
| Calibration tables | R | C | – | – | I | C | C | A |
| Commissioning checklist ×9 | R | C | C | – | I | A | C | R |
| Experiment plan + lab notebook | R | – | – | – | A | C | I | I |
| Data export + charts | R | R | – | – | A | C | C | I |
| Time Capsule | C | C | C | R | A | C | C | C |
| Safety pledge, incident log | C | – | R | – | I | A | I | I |
| Information panels ×9 | R | – | – | C | A | C | C | I |
| Showcase | R | R | R | R | A | R | C | C |
| ARCUB report + evidence pack | C | C | C | C | A/R | R | R | C |
Workshop sequence
Workshops W1–W4 and W6–W8 take a full 90-min session unless stated. W5 runs inside Build Day 1.
| # | Date | Title | Duration | Objectives | Materials | Activities | Output |
|---|---|---|---|---|---|---|---|
| W1 | Tue Oct 27 | Kickoff, safety & electricity basics | 90 min | Know the 10 wall rules; tell SELV from mains; know why water + mains is the hazard; know the stop word | Wall-rules poster (A2), RCD strip, 12 V brick, multimeter, 9 V battery + LED, PPE samples, safety pledge form | 15' project tour and the 9 ecosystems; 20' "voltage ladder" demo (3.3 / 5 / 12 V measured with a multimeter by students; 230 V shown only as a sealed COTS brick); 20' hazard hunt in the room (find 5 planted hazards); 20' teams formed, roles assigned; 15' pledge signed | Signed pledge per student; team + role list |
| W2 | Thu Oct 29 | Scientific method applied + ecosystem science design | 90 min | Write a testable hypothesis; name IV, DV and controlled variables; plan a control and replicates | Driving-question cards, lab notebook template, variable worksheet, example dataset | 15' "good vs bad hypothesis" sort; 30' each team turns its driving question into a hypothesis plus an IV/DV/controls table; 20' peer critique (2 teams pair up); 25' first draft of the experiment plan (1 page) and first notebook entry | Experiment plan v1; notebook started |
| W3 | Tue Nov 10 | Node assembly | 90 min | Assemble an ESP32 node on a screw-terminal board in an IP65 box; route cables through glands; check polarity with a multimeter | Team kit bag (ESP32, TERMBOARD, OLED, SHT31/BH1750, DS18B20, SOIL, BOX, GLAND, pre-crimped JST/Dupont leads, BUCK pre-set to 5.0 V by E2), screwdrivers, wire strippers, labels | 10' tour of the reference node; 50' assembly following the pin-map card (GPIO 21/22 I2C, 4 1-Wire, 32–35 soil); 15' multimeter checks (3.3 V, 5 V, no shorts); 15' label every cable at both ends | 9 assembled nodes, labelled |
| W4 | Thu Nov 12 | ESPHome & Home Assistant basics | 90 min | Flash a node; read YAML; add a sensor; see it on the dashboard | Laptops/Chromebooks with Chrome (ESPHome Web), USB cables, YAML template per node (mc-0X-*), HA user per team | 15' what YAML is; 25' flash the base template (Wi-Fi + OLED + one sensor); 25' add a second sensor by editing YAML (e.g. BH1750), reflash OTA; 15' build the team's dashboard card in HA; 10' Data Steward exports the first CSV | Each node online with ≥ 2 sensors; team dashboard card |
| W5 | Sat Nov 14 (Build Day 1) | Engineering design sprint (lids, vents, mounts, cable routing) | 2 × 90 min within the build day | Requirements → sketch → prototype → test → iterate | Acrylic 3 mm, scoring knife, mesh, hinges, silicone, cardboard for mock-ups, cut-resistant gloves, requirements card | 20' write 5 requirements (e.g. "RH > 80 %", "lid opens with 1 hand", "no water on node box"); 20' 3 sketches each, pick 1; 60' cardboard prototype; 30' test against the requirements (mist test, open/close 20×); 40' acrylic version | Design sheet (requirements, sketches, test results); fitted lid/vent |
| W6 | Tue Nov 17 | Calibration lab | 90 min | Understand that a sensor gives a number, not the truth; do a 2-point calibration; record uncertainty | Substrate samples in cups (dry / field-wet / saturated), ice water + room water, pH 4/7/10 and EC 1413 solutions, PHPEN, TDSPEN, reference thermometer | Station rotation, 20' each: (1) soil probe raw value in air / dry / saturated per team substrate → map to 0–100 %; (2) DS18B20 vs reference in ice water and room water → offset; (3) pH/EC pen calibration + 1:5 soil extract; 30' enter calibrations in YAML (calibrate_linear) |
Calibration table per probe (date, raw, reference, offset); YAML updated |
| W7 | Thu Dec 3 | Data analysis in Google Sheets | 90 min | Import CSV; plot a time series; compare treatment vs control; mean, SD, paired comparison; what "significant" means at school level | Team CSV (≥ 10 days), Sheets template with formulas, worked example | 15' import + clean (timestamps, units); 20' line chart; 20' daily means, AVERAGE, STDEV; 20' compare two conditions: difference in means vs SD; paired differences day by day (e.g. 2026 vs 2056 same day) and how many days out of N go the same way; 15' school-level rule: "a difference is convincing if it is bigger than about 2 × SD of the day-to-day noise and shows up in most replicates or days. Otherwise we say 'no clear difference yet'" |
One chart + one sentence claim per team |
| W8 | Tue Dec 8 | Presentation skills for the showcase | 90 min | Tell a 3-minute story: question → what we built → what we saw → what we would do next | Panel draft, timer, chart printout | 15' structure (Claim–Evidence–Reasoning); 30' each team drafts its 3-minute talk with everyone speaking; 30' practice in pairs of teams with feedback (2 stars + 1 wish); 15' visitor Q&A practice ("what went wrong?") | Talk script; speaker order |
The 10 wall rules (A2 poster at the door, read aloud at W1 and on every build day):
- Only adults touch anything that plugs into the wall. Students work only on the 12 V side.
- Every mains device lives on the shelf above, never on or under a tank table.
- Every cable has a drip loop. If you see a cable without one, stop and tell an adult.
- No water within 1 m of the mains shelf. Fill and drain at the sink, using a jug.
- Unplug the 12 V brick before you touch wiring. Plug it back in only after a partner checks.
- Hands dry before electronics, gloves on before soil, compost or solutions.
- Goggles for cutting, drilling, solutions and anything that can splash.
- Nobody cuts glass. Broken glass: step back, call an adult, use the dustpan, not hands.
- Anyone can say "STOP", and everyone stops.
- Every incident, spill or near miss is logged the same day, with no blame.
Pedagogy & assessment
Learning outcomes and observable indicators
| Outcome | Observable indicator (what an adult can see or tick) | Evidence |
|---|---|---|
| Agency | Student proposes a change unprompted; takes and hands over a role; fixes or escalates a problem without waiting; asks for help with a specific question ("I measured 0 V at GPIO 32; is the probe dead?") | Notebook entries, role handover sign-off, adult observation sheet (weekly, 1 line per team) |
| Scientific thinking | Writes a hypothesis with a direction and a reason; names IV, DV and ≥ 3 controls; uses a control or a paired comparison; distinguishes noise from effect; reports a null result honestly | Experiment plan, chart + claim, data review |
| Engineering design | Writes measurable requirements; produces ≥ 2 alternatives; tests a prototype against requirements; documents an iteration with a reason | Design sheet, commissioning checklist, photos of v1/v2 |
| Collaboration & communication | Every member can explain the system; talk is shared; feedback given and used | Rehearsal checklist, showcase |
Lab notebook template (one Google Doc per team + paper notebook at the tank)
| Field | Example |
|---|---|
| Date / time / session # | 2026-11-24 14:05, S10 |
| Who was present / roles today | Ana (LS), Mihai (LE), Ioana (DS), Radu (BK) |
| Observation (what we saw, not what we think) | "Fungus gnats ×4 on yellow trap; condensation on lid 3/4 of area" |
| Measurements (sensor + manual) | Dashboard: RH 94 %, soil A 62 %; PHPEN 6.8 |
| Photo ID (fixed-angle photo) | IMG_mc04_20261124.jpg |
| Actions / interventions (time-stamped) | 14:20 watered 50 mL, recorded via HA input button |
| Changes to setup (hardware/software) | YAML v1.3: soil A calibration updated |
| Problems & how we handled them | "Node offline 03:00–07:00, power strip switched off by cleaner. Added label." |
| Question / idea for next time | "Is RH above 90 % causing mould on the cress?" |
| Next steps + owner | Mihai: vent test Thu |
| Signature of note-taker | – |
Experiment-plan header (front page, updated when it changes): driving question, hypothesis ("If … then … because …"), IV / DV / controlled variables, control or comparison, replicates (n), measurement schedule, safety notes, version + date.
Team project rubric (4 criteria × 4 levels)
| Criterion | 1 Beginning | 2 Developing | 3 Secure | 4 Excellent |
|---|---|---|---|---|
| Scientific process | Question unclear; no variables named | Hypothesis present; variables partly named; no control | Testable hypothesis; IV/DV/controls; control or comparison used | As 3, plus replication or paired design, limitations stated, next experiment proposed from the result |
| Engineering design | Built as told; no requirements | Some requirements; one design; informal testing | Measurable requirements; tested against them; ≥ 1 documented iteration | As 3, plus trade-offs explained, reliability or safety improvement evidenced by a test |
| Data & evidence | No data used | Chart shown, no claim, or claim not supported | Clean chart with units; claim matches data; noise acknowledged | As 3, plus mean/SD or paired comparison, a correct "no clear difference yet" call where needed, calibration referenced |
| Documentation & communication | Sparse notebook | Notebook irregular; talk read from notes | Notebook every session; clear 3-minute talk, everyone speaks | As 3, plus failures documented with causes and fixes; answers visitor questions with evidence |
Scoring rule: results don't score; process does. A treatment that killed every plant, or a sensor that failed, scores 4 on "Data & evidence" if the team detected it, explained it with evidence and proposed a fix. A team that "proves" its hypothesis with an uncontrolled comparison scores at most 2. Assessment is formative until January (feedback only). The first graded checkpoint is the showcase, the second is the June review.
Driving questions (one per ecosystem)
| # | Ecosystem | Driving question |
|---|---|---|
| 1 | The Orchestra of Rot | Which organic materials do our decomposers recycle fastest, and what conditions make the system most efficient? |
| 2 | The Domino Effect, EcoColumn | How does rain on bare vs protected soil move sediment and fertiliser into the water, and can a natural filter stop the algal bloom? |
| 3 | Toxic Ground, Brownfield | How do salt, pH change, heat and compaction damage a soil, and which restoration helps life come back? |
| 4 | Future 2026 | How does today's ecosystem respond under current Bucharest-like conditions (our control)? |
| 5 | Future 2056 | What happens to the same ecosystem under 2056-style heat, drought, extreme rain and elevated CO2, and which intervention makes it more resilient? |
| 6 | Forests in Space | Can plants establish in a lunar-like mineral substrate, and what is the least we must add to make it a viable growing medium? |
| 7 | The Hydroponic Jungle | How do nutrients, aeration and light affect plant growth without soil, and can we automate a stable system? |
| 8 | The Living Earth | How much life (respiration, invertebrates, roots, water retention) is in healthy vs degraded soil, and which method restores it fastest? |
| 8b | The Carnivorous Bog (alt.) | How do sundews catch prey and survive in nutrient-poor water? |
| 9 | The Time Capsule | How do we design an ecosystem that stays alive and observable for 10 years, and what will change in it? |
Keeping educational outcomes ahead of scientific results
- The showcase asks "what did you learn and how do you know?", not "did it work?". The panel template includes a mandatory "What went wrong and what we changed" box.
- Pre-register: the hypothesis is frozen in the plan before treatments start (version-dated). Changing it later is allowed but must be logged.
- Adults ask, they don't answer: "What would convince you?", "What else could explain that?", "What's your control?".
- Failure log: each team keeps a "bug and death list". Each entry earns visible credit (a sticker on the team board).
- Biology needs months. December shows set-up and baseline; round 2 (Jan–Jun) carries the real experiments with replication.
Younger cohorts from January and the Time Capsule handover
| When | What |
|---|---|
| Jan 12 – Feb 5 | Each team adopts 2–3 "apprentices" (grade 5–6). Apprentices shadow the Biology Keeper and Data Steward roles and are trained with the role cards. |
| Feb | Apprentices run the weekly Capsule check under supervision; first entry in the Capsule logbook in their own handwriting. |
| Mar – Apr | Mixed teams for round 2: apprentices take Biology Keeper, current students take Lead roles. |
| May | Capsule handover ceremony: the outgoing Capsule Council briefs the incoming one (apprentice delegates); signs the Capsule Charter; hands over the logbook, maintenance card, spares box and HA access for 2 new Hub Admins. |
| Every December (2027–2036) | "Capsule Day": annual photo from the fixed angle, data export, logbook entry, maintenance (spare node swap if needed). |
Capsule handover kit: Capsule Charter (rules: what may never be added or removed), species list with Latin names, maintenance card (weekly / monthly / yearly tasks), spare node pre-flashed (mc-09-capsule-spare), spare SD card, printed YAML + wiring diagram, logbook, password envelope sealed with the head teacher.
Risk register
L = likelihood, I = impact, each rated H / M / L.
| ID | Risk | L | I | Mitigation | Owner | Trigger |
|---|---|---|---|---|---|---|
| R01 | Delivery delays from RO shops (stock "in 5–7 days" turns into 3 weeks) | M | H | Order Oct 21–23; prefer "în stoc" items; split across 2 shops for critical parts (ESP32, SHT31, DS18B20); call the shop on day 3 if not shipped | T1 + E1 | Item not shipped by Oct 28 |
| R02 | Customs/VAT and invoice eligibility for China orders | M | M | Orders < 150 EUR (IOSS); download invoices; confirm ARCUB eligibility; RO substitute in parallel (China fallback rule) | T1 | Parcel held by customs; ARCUB rejects invoice |
| R03 | School IT cannot provide a 2.4 GHz WPA2-PSK SSID for the nodes (enterprise-only Wi-Fi, captive portal, MAC filtering) | M | M | Ask IT in writing by Oct 23 for a 2.4 GHz WPA2-PSK SSID, 12 DHCP reservations and the Pi reachable from student devices. If refused, buy the fallback router (≈ 160 RON) the same day and run an isolated project network as the platform chapter describes. | E1 | IT objection or WAN port blocked |
| R04 | Power cuts or someone switches off the strip | M | M | Nodes reconnect automatically; heat pad/pump restore_mode: ALWAYS_OFF; HA backup nightly; label "DO NOT SWITCH OFF" on the strips; optional small UPS (~400 RON, ~80 EUR, emag.ro) for Pi + router |
E1 | Node offline > 30 min (HA alert) |
| R05 | Water damage (leak, overflow, spill on electronics) | M | H | Rules 2–4; node boxes above the water line; glands; trays under tanks; float-switch high cut-off on pump-fed systems; leak test 24 h with water before electronics are fitted | T2 | Water on table or floor; float high alarm |
| R06 | Mould/odour complaints (Rot, Living Earth) | M | M | No meat/dairy/cooked food; charcoal-filter vent fan; lid closed; weekly sniff test; BME680 gas trend alert; remove mouldy items in a sealed bag | Team 1 Biology Keeper + T1 | Complaint from staff; visible fuzzy mould outside the intended substrate |
| R07 | Pests: fungus gnats, mites, fruit flies | H | L | Yellow sticky traps in every enclosure; 1 cm sand top-dressing; let the surface dry between waterings; Bti (mosquito dunks) in the watering water; mesh on vents; quarantine new soil for 3 days | Biology Keepers | > 5 gnats per trap per week |
| R08 | Plant die-off in winter light (Bucharest ~9 h daylight in December) | H | M | 12 V LED strips 12–14 h photoperiod via HA schedule; shade-tolerant species; spare seedlings; never rely on window light; BH1750 check that lux > 5 000 at the canopy | T1 + teams | Lux < 2 000 at the canopy or wilting > 20 % of plants |
| R09 | Sensor failures or drift | M | M | Bench test in W2; spares (3 nodes, extra probes); calibration log; monthly cross-check against handheld pens and the reference thermometer; HA "unavailable" alert | E2 + Data Stewards | Flatline > 2 h or step change > 3 SD |
| R10 | Capacitive probe batch defects (no TL555, wrong regulator, top-edge corrosion) | H | M | Buy "v2.0 TL555" version; test every probe dry/wet before issue; reject spread < 800 counts; seal the top edge with heat-shrink + conformal coat; 24 bought for 18 used | E2 | > 3 probes fail the bench test |
| R11 | SCD41 auto-self-calibration (ASC) drifts in closed tanks (ASC assumes weekly fresh-air ~420 ppm) | H | M | automatic_self_calibration: false in ESPHome; forced recalibration at an open window (420 ppm) at commissioning and monthly; record in the calibration log |
E2 | CO2 baseline < 400 ppm or slow downward creep |
| R12 | Student absence (autumn break, illness, other commitments) | M | M | Break falls before biology; role cards and notebooks allow handover; teams of 4 where possible; every task has a named backup | T1 | < 50 % of a team present twice in a row |
| R13 | Teacher time overload (T1 carries procurement + report + teaching) | H | H | E1 drafts BOM/orders and the data annex; Hub Admins and Data Stewards do routine work; ARCUB evidence collected weekly (15 min Fridays) rather than at the end | Head teacher | T1 misses 2 weekly status reports |
| R14 | Alacrity time (4 h/week insufficient in W3–W5) | M | H | Front-load: hub and reference node before break; templates for all 9 YAMLs ready Nov 9; the 3 build days carry the peak; contingency ~10 h | Alacrity lead | E1/E2 hours > 120 % of plan by Nov 20 |
| R15 | ARCUB reporting evidence incomplete (missing attendance, invoices, photos, visibility) | M | H | Evidence folder from day 1; attendance sheet every session; ARCUB logo on panels, posters, posts; weekly evidence check against the list | T1 | Folder < 70 % complete on Dec 4 |
| R16 | Data loss (Pi SD corruption, Drive sync failure) | M | H | A2 SD; HA backup nightly to Drive; nightly CSV export via rclone; weekly test restore of one CSV; spare SD64 pre-imaged; Time Capsule node logs locally to microSD | Hub Admins + E1 | Backup or export missing 2 nights in a row |
| R17 | Vandalism / accidents (bumped tanks, curious visitors, cleaning staff) | L | H | Locked room outside sessions; tanks on stable tables, back against the wall; showcase with a rope line and student guides; brief the cleaning staff | Head teacher + T2 | Any damage incident |
| R18 | Glass breakage (tank dropped, lid fitting, drilling) | L | H | COTS tanks; no student glass cutting/drilling; carry tanks with 2 people; foam mat under tanks; cut-resistant gloves for handling; broken-glass kit (dustpan, thick bag) | T2 | Crack or chip noticed |
| R19 | Heat-pad overheating | L | H | 12 V pads only; DS18B20 thermostat loop on the ESP32 (not via HA); max PWM 60 %; hardware thermal fuse (~72 °C) in series; pad off if the sensor is unavailable > 60 s; pad never under substrate without an air gap | E2 | Pad surface > 40 °C or substrate > setpoint + 5 °C |
| R20 | pH-down / chemical handling (hydroponics, Brownfield) | L | M | Use citric acid solution (pre-diluted by T1, labelled) instead of concentrated phosphoric acid; small dropper bottles; goggles + nitrile gloves; nutrient concentrate stored in a locked cabinet; SDS kept in the folder | T1 | Spill or skin contact |
| R21 | Scope creep (too much automation, every sensor at once) | H | M | Feature freeze for the MVS on Fri Nov 13: only the sensors and actuators in the commissioning checklist; everything else goes on a "January list" | E1 + T1 | New feature requested after Nov 13 |
| R22 | "ChatGPT plan" ambiguity (approved items without specs, e.g. "glass-panel construction packs", "grow lights 5–10 W") | H | M | Reconciliation table: each approved line → concrete spec + catalog ID + reason for change; T1 confirms with ARCUB in writing before invoices; keep a change log | T1 + E1 | ARCUB queries a line, or an invoice does not match a line name |
| R23 | Budget overrun ±20 % | M | M | 10 % contingency line; price basis recorded per item; cheaper RO alternatives listed; reallocation between lines within the contract threshold (confirm %); scope cuts from the "January list" first | T1 | Committed spend > 90 % of a line |
| R24 | Photo/consent gaps block showcase documentation | M | M | Consent forms out in W0; tracker; non-consented students wear a coloured lanyard and are photographed from behind / hands only | T1 | Form missing on Dec 7 |
| R25 | Holiday-period failure (Dec 19 – Jan 10) | M | H | Visit rota Mon + Thu; remote alerts; automated light/water; 3-week water reservoirs; no new treatments after Dec 14 | T1 + E1 | Alert unacknowledged > 24 h |
Safety & compliance
Safety protocol summary
| Domain | Rules (binding) |
|---|---|
| Electrical | Students work only on SELV ≤ 12 V DC (24 V DC for the mister, behind its own adapter). All 230 V exists only inside certified COTS products with their own cord and plug. Mains devices go on the shelf above and away from water, with a drip loop on every cable, on a 30 mA RCD-protected strip. Mains is switched only through certified COTS smart plugs, never bare relays. Nothing mains-powered inside an enclosure, in water or in substrate. Every 12 V brick is a certified adapter. Unplug before rewiring; buddy check before re-power. RCD test button pressed monthly (logged). |
| Water | Node boxes outside enclosures, above the water line, cables through glands. Fill and drain at the sink with a jug. Trays under tanks. 24 h leak test before electronics. Spills mopped immediately; floor sign if wet. |
| Biological | Gloves for compost, soil and organism work; hand-washing after every session; no toxic plants; no vertebrates; no wild-collected soil from contaminated sites; mould removed in sealed bags; anyone with allergies or asthma informs T1 and is excused from Rot/compost handling. |
| Chemical | Brownfield "contamination" = table salt, vinegar/baking soda, compaction, heat only. No heavy metals, no real pollutants. pH-down = pre-diluted citric acid. Calibration solutions and nutrients in labelled bottles, locked cabinet, SDS on file. Goggles + gloves for all solutions. |
| Glass & tools | No student glass cutting or glass drilling (adults only, if at all). Acrylic scoring with a steel rule and cut-resistant gloves; goggles for cutting and drilling. Hand tools signed out and back in; hot-glue at a fixed station; no soldering by students in the build phase (pre-crimped and screw terminals), except optional supervised soldering in January on spare boards with a fume extractor. |
Supervision ratios
| Activity | Ratio (adult : students) | Notes |
|---|---|---|
| Normal session (observation, data, planning) | 1 : 18 | 2 teachers for the whole group |
| Tool work (acrylic, drilling plastic boxes, screwdrivers) | 1 : 8 | Build days: T1, T2, E1, E2 = 4 adults for ≤ 32 students |
| Node power-up / first 12 V connection | 1 adult per active bench | Buddy check + adult nod before plugging in |
| Solutions / chemicals | 1 : 6 | At the designated wet bench only |
| Mains-side placement | Adult only | Students out of the shelf zone |
| Showcase | 1 adult per 3 ecosystems + student guides | Rope line; no touching tanks |
PPE list (quantities for 36 students + 4 adults)
| Item | Qty | Use |
|---|---|---|
| Safety goggles (EN 166) | 20 | Cutting, drilling, solutions |
| Nitrile gloves, M/L boxes of 100 | 4 boxes | Soil, compost, solutions |
| Cut-resistant gloves (EN 388, level C) | 8 pairs | Acrylic scoring, tank handling |
| Lab aprons | 12 | Wet bench, substrates |
| Dust masks FFP2 | 1 box of 20 | Dry substrate mixing (regolith simulant, perlite, vermiculite) |
| First-aid kit + eye-wash bottle | 1 + 2 | Lab |
| Broken-glass kit (dustpan, brush, thick bag, label) | 1 | Lab |
| Fire blanket + CO2 extinguisher (school-provided, check date) | 1 + 1 | Lab |
Incident log (Google Sheet + paper copy on the wall)
Fields: ID · date/time · location/ecosystem · who was involved (initials) · what happened · type (injury / near miss / spill / electrical / glass / biological / equipment damage) · immediate action · adult informed (name) · root cause · corrective action + owner + date · parents informed (Y/N, by whom) · closed (date). Reviewed every Friday by the Safety Officers + T2. Any injury: head teacher and parents informed the same day.
Consent & photo policy for the showcase
- GDPR-compliant parental consent (minors under 16: parent/guardian; 16–17: parent + student countersignature) covering: participation, photos/video for ARCUB reporting, photos for public posts, first name on panels. Each item is a separate tick box.
- No surnames on panels or posts; no faces of students without the "public" consent; non-consented students wear a coloured lanyard, and photographers shoot hands, backs or the ecosystems only.
- Visitor photography at the showcase: a sign at the entrance; visitors asked not to post photos of students.
- Photos stored only in the project Drive (school account), not on personal phones beyond the session. Phones used for photos are cleared weekly after upload.
ARCUB evidence (likely required; confirm against the financing contract)
| Evidence | Source | When collected |
|---|---|---|
| Fiscal invoices + payment proof (OP / card statement) for every item | T1 | At purchase |
| Goods-received records (proces-verbal de recepție) + reconciliation table (approved line → purchased item) | T1 + E1 | On delivery |
| Attendance lists per session (date, names, signatures) | Teachers | Every session |
| Dated photos: before / during / after per ecosystem, workshops, build days, showcase | Biology Keepers + T2 | Weekly + events |
| Outputs: experiment plans, notebooks (scans), design sheets, calibration tables, CSV data export, dashboard screenshots, panels (PDF) | Teams + Hub Admins | Weekly |
| Visibility proof: ARCUB logo on panels, invitations, posts; screenshots of posts | T1 | When published |
| Showcase: invitation, visitor count / sign-in sheet, programme, photos | T1/T2 | Dec 15–17 |
| Narrative + financial report | T1 + E1 | Dec 18 |
Evidence folder structure (inside the shared Drive, 06_ARCUB_Evidence/)
06_ARCUB_Evidence/
01_Contract_and_budget/ contract, annexes, approved budget, change requests
02_Procurement/
2026-10-21_optimusdigital_INV-xxxx.pdf (one file per invoice, prefixed by date)
payments/ OP / statements
receipts_PVR/ proces-verbal de recepție, signed
reconciliation.xlsx approved line → item → invoice → RON
03_Attendance/ YYYY-MM-DD_session-NN.pdf
04_Photos/
by_ecosystem/mc-01 ... mc-09/ YYYYMMDD_mcXX_fixed.jpg
events/W1_kickoff/ ... showcase/
05_Outputs/ plans, notebooks, design sheets, calibration, panels, data exports
06_Visibility/ logo usage, posts, invitations
07_Showcase/ programme, sign-in sheets, feedback forms
08_Safety/ pledges, incident log, commissioning checklists, RCD tests
09_Consent/ consent forms (restricted access: T1 + head teacher only)
10_Final_report/ narrative report, financial report, annexes
Communication & documentation
Shared drive structure (school Google Workspace, owner T1, Alacrity as editors)
MICROCOSM/
00_Admin/ contacts, calendar, weekly status reports, minutes
01_Plan/ this plan, BOM, pin map, substitution log, change log
02_Platform/ network table (IPs, leases), HA backups, YAML (one folder per node), wiring diagrams
03_Teams/
mc-01-rot/ ... mc-09-capsule/
plan/ experiment plan (versioned), design sheets
notebook/ lab notebook doc + scans
data/ calibration table, team charts
photos/ fixed-angle series
04_Data/
csv_nightly/ YYYY-MM-DD_all-nodes.csv (rclone export)
data_dictionary.xlsx entity id, unit, calibration, valid range
05_Workshops/ slides, worksheets, role cards, rubric, wall rules
06_ARCUB_Evidence/ (see above)
07_Showcase/ panels (source + PDF), talk scripts, run-sheet
08_TimeCapsule/ charter, species list, maintenance card, logbook scans, council minutes
Naming rule: YYYY-MM-DD_<node>_<what>_v<N> (e.g. 2026-11-17_mc-04_soilcal_v1.xlsx). No spaces, no diacritics in file names.
Weekly status (10 lines, T1 posts every Friday by 16:00 in 00_Admin/status/, sent to E1, E2, head teacher)
1. Week / dates:
2. Overall: GREEN / AMBER / RED (one reason)
3. Done this week (max 3 bullets):
4. Next week (max 3 bullets, with owner):
5. Ecosystems online: X/9 · alive: X/9 · days of data: X
6. Procurement: items outstanding (IDs) · China orders pending · expected dates
7. Top risk this week (ID) + action:
8. Safety: incidents/near misses (IDs) · open actions:
9. Evidence folder: % complete · missing items:
10. Decisions needed / from whom / by when:
Final report outline for ARCUB (submit Fri Dec 18)
- Summary (1 page): what was built, how many students, key numbers (9 ecosystems, N sessions, N student-hours, days of data, visitors).
- Objectives vs achieved: table per approved objective → evidence reference.
- Activities: timeline (the gantt above, as-run), workshops held with dates and attendance.
- The nine ecosystems: one page each: driving question, setup photo, sensors, one chart, what students learned, what comes next.
- Educational outcomes: indicators observed, rubric summary (anonymised), sample student reflections.
- Technical platform: architecture diagram, sensors per node, data volume, uptime %.
- Safety: protocol, incidents (count and type), commissioning certificates.
- Public showcase: dates, programme, visitors, photos, feedback.
- Procurement & budget: reconciliation of approved lines vs purchased items with reasons for each change; spend per line; remaining commitments.
- Visibility: logo usage, posts, press.
- Continuation plan (Jan–Jun 2027) and Time Capsule 10-year plan.
- Annexes: evidence index (file list referencing
06_ARCUB_Evidence/), data export, panels PDF.
Public one-pager per ecosystem (the "printed durable information panels")
Format: A3 portrait, printed on 3 mm PVC foam board (forex) or 5 mm, UV-laminated, one per ecosystem plus one project overview panel (10 panels), mounted on the table edge or the wall beside each tank. Basis: ~40–60 RON per A3 forex panel at a Bucharest print shop (≈ 8–12 EUR); 10 panels ≈ 500 RON. Send to print by Wed Dec 9. Time Capsule panel printed on aluminium composite (dibond) for a 10-year life (~120 RON).
| Block | Content | Who writes |
|---|---|---|
| Header | Ecosystem name + number, team first names, ARCUB + school + Alacrity logos | T1 template |
| Driving question | One line (table above) | Lead Scientist |
| What's inside | Species (Latin + common), substrate layers, 1 labelled photo or drawing | Biology Keeper |
| What we measure | Icons: temperature, humidity, soil moisture, light, CO2, water; sampling every 60 s | Data Steward |
| What we built | Node + actuators, 1 diagram; "everything inside the tank runs at 12 V or less" | Lead Engineer |
| Our experiment | Hypothesis, what we change, what we keep the same, control | Lead Scientist |
| What we've seen so far | One chart + one-sentence claim (updatable sticker area or QR) | Team |
| What went wrong and what we changed | 2–3 bullets | Team |
| QR code | Link to a public read-only Drive folder with the latest chart PDF (refreshed monthly by Hub Admins). The HA dashboard itself is not public | Hub Admins |
| Footer | "Please don't touch the tanks or the cables." Date + version | T1 |
8. Answers to the proposal's "Items to discuss"
The proposal closes with six open questions for Alacrity. Short answers, with pointers to the chapters that justify them.
| Question from the proposal | Answer |
|---|---|
| Common ESP32 architecture across ecosystems | Yes. One node design ("MICROCOSM node v1"): ESP32 DevKitC on a screw-terminal breakout in an IP65 box, one pin map, one ESPHome base YAML, one 12 V rail, one hub. A team configures a node; it never designs one. Chapter 3. |
| Useful vs unnecessary sensors | Keep DS18B20, BH1750, OLED, capacitive soil (with mitigation), NDIR CO2. Replace 7 of 9 BME680 with SHT31. Add floats, ultrasonic level, pH, TDS, turbidity and handheld pens where the science needs them. Drop SD cards and RTCs from 6 of 9 nodes. Skip dissolved oxygen. Chapter 4. |
| Automation for hydroponics | Light and air pump through smart plugs, circulation pump on a duty cycle, peristaltic dosing of nutrient and pH-down with daily caps, mixing waits and lockouts, level top-up with float interlocks, pen cross-checks daily. Chapter 5.7. |
| Automation for climate simulations | 2056: heating loop with hysteresis and a hardware thermal fuse, drought and extreme-rain calendar, CO2 from a yeast generator with SCD41 feedback and vent/seal logic, humidity fan. 2026: steady irrigation and ventilation. Same hardware on both tanks, only setpoints differ. Chapter 5.4–5. |
| Automation for long-term monitoring | Time Capsule: light on a schedule with a timer-plug fallback that works without the hub, alerts for temperature, humidity, dryness, data gaps and SD errors, local CSV logging with RTC, a replaceable external sensor pod, a ten-year maintenance calendar. Chapter 5.9. |
| Spare capacity | 3 ESP32 boards (approved), one spare SHT31, BH1750 and DS18B20, two spare soil probes, floats, MOSFETs and bucks, one spare heat pad and 5 V adapter. No spare CO2 sensor, pump or brick after the cost cut; a failure there is a same-week purchase. Chapter 4.4. |
| Extra equipment for pH, EC, turbidity and aeration | Yes to all four: 2 analog pH kits, 1 TDS module, 2 turbidity modules, 2 handheld pH pens, 1 TDS pen, 2 calibration sets, 1 COTS aquarium air pump with air stones. Chapter 6. |
| Note: calibration solutions listed, no probes | Confirmed and fixed: probes and pens added. |
| Note: Raspberry Pi SD card listed, no Pi | Confirmed and fixed: Raspberry Pi 5 (4 GB), official PSU, active cooler; the nodes use the school's existing Wi-Fi. |
Appendix A. Glossary
| Term | Meaning |
|---|---|
| ARCUB | Centrul Cultural al Municipiului București, the funding body for this project |
| COTS | Commercial off-the-shelf: a finished product bought as-is, not built from parts |
| SELV | Safety extra-low voltage: circuits at 12 V DC or below in this project, safe to touch and to run in water |
| RCD | Residual-current device (differential protection), trips at 30 mA leakage; required on every power strip here |
| ESP32 | The Wi-Fi microcontroller used in every node |
| ESPHome | Firmware framework configured in YAML, integrates natively with Home Assistant |
| Home Assistant (HA) | Open-source home-automation hub software running on the Raspberry Pi; dashboards, automations, alerts |
| InfluxDB / Grafana | Time-series database and charting tool, run as Home Assistant add-ons for long-term data and CSV export |
| MQTT | Lightweight messaging protocol; available on the hub for the advanced track |
| OTA | Over-the-air firmware update over Wi-Fi |
| I2C, 1-Wire | Two-wire digital sensor buses; I2C for SHT31/SCD41/BH1750/OLED, 1-Wire for DS18B20 |
| ADC1 | The ESP32 analog inputs that still work while Wi-Fi is on (GPIO 32–39) |
| PWM | Pulse-width modulation: dimming lights, fans and heaters by switching fast |
| MOSFET module | A transistor switch board that lets a 3.3 V pin control a 12 V load |
| Buck module | A step-down converter, here 12 V to 5 V for the ESP32 |
| NDIR | Non-dispersive infrared, the measuring principle of a real CO2 sensor (SCD41) |
| VOC | Volatile organic compounds; the BME680 reports a gas resistance that falls as VOCs rise |
| ASC / FRC | Automatic self-calibration / forced recalibration of the SCD41; ASC must be off in sealed tanks |
| EC / TDS | Electrical conductivity / total dissolved solids: a measure of dissolved salts in water or a soil extract |
| DWC / Kratky | Deep water culture (aerated) and passive (non-aerated) hydroponic methods |
| Rhizotron | A clear-walled container for observing roots in soil |
| Tea Bag Index (TBI) | A standard citizen-science method for decomposition rate using buried tea bags |
| Berlese funnel | A lamp-and-funnel device that drives soil invertebrates into a collecting jar for counting |
| Litter bag | A mesh bag with a known mass of material, buried and reweighed to measure decomposition |
| Regolith | Loose surface material of the Moon; here a basalt-based classroom analogue |
| Node | One ESP32 box serving one ecosystem |
| Hub | The Raspberry Pi running Home Assistant |
Appendix B. ESPHome firmware listing
These files are the firmware referred to in Chapter 3. Copy the common/ folder to /config/esphome/common/ on the hub; each node YAML then needs only substitutions and the list of packages it uses.
common/mc-base.yaml
# common/mc-base.yaml — MICROCOSM node v1 base package (ESPHome 2025.x/2026.x)
# Every node YAML includes this file first and overrides the substitutions below.
substitutions:
node_name: mc-00-test # hostname, = ESPHome device name
friendly_name: "MC 00" # HA device name -> entity ids start with mc_00_
area: "Lab"
api_key: !secret mc00_api_key # one key per node (secrets.yaml)
ntp_server: "0.ro.pool.ntp.org" # fallback only; primary time = HA over the API
user1_src: wifi_rssi_s # id of any sensor shown on OLED line 4
user1_label: "RSSI dBm" # no percent sign in labels (printf)
user2_src: uptime_s # id of any sensor shown on OLED line 5
user2_label: "Uptime s"
esphome:
name: ${node_name}
friendly_name: ${friendly_name}
area: ${area}
on_boot:
priority: 600
then:
- logger.log: "MICROCOSM ${node_name} booting"
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
level: INFO
api:
encryption:
key: ${api_key}
reboot_timeout: 0s # do NOT reboot when HA is down: local logic keeps running
ota:
- platform: esphome
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
reboot_timeout: 0s # keep running local automations without Wi-Fi
ap:
ssid: "${node_name}-fb"
password: !secret fallback_ap_password
captive_portal:
time:
# Both sources set the same ESP32 system clock; ha_time works without Internet
# (HA over the native API), sntp is the fallback when HA is down.
- platform: homeassistant
id: ha_time
timezone: Europe/Bucharest
- platform: sntp
id: sntp_time
timezone: Europe/Bucharest
servers:
- ${ntp_server}
- 1.ro.pool.ntp.org
- 2.ro.pool.ntp.org
i2c:
id: bus_a
sda: GPIO21
scl: GPIO22
frequency: 100kHz # 50kHz if total bus cable > 50 cm
scan: true
one_wire:
- platform: gpio
id: ow_bus
pin: GPIO4 # 4.7 k pull-up to 3.3 V on the bus
globals:
- id: g_air_t # written by sens-sht31 / sens-bme680, read by OLED
type: float
restore_value: false
initial_value: "NAN"
- id: g_air_rh
type: float
restore_value: false
initial_value: "NAN"
sensor:
- platform: wifi_signal
id: wifi_rssi_s
name: "WiFi RSSI"
update_interval: 60s
entity_category: diagnostic
- platform: uptime
id: uptime_s
name: "Uptime"
update_interval: 60s
entity_category: diagnostic
binary_sensor:
- platform: status
id: api_status
name: "Status"
button:
- platform: restart
name: "Restart"
entity_category: config
- platform: safe_mode
name: "Safe mode boot"
entity_category: config
font:
- file: "gfonts://Roboto Mono" # offline: put a .ttf in /config/esphome/fonts/
id: f_small
size: 10
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
i2c_id: bus_a
address: 0x3C
update_interval: 5s
lambda: |-
it.printf(0, 0, id(f_small), "%s", "${node_name}");
if (id(api_status).state) {
it.printf(0, 12, id(f_small), "WiFi %.0f dBm HA ok", id(wifi_rssi_s).state);
} else if (wifi::global_wifi_component->is_connected()) {
it.printf(0, 12, id(f_small), "WiFi %.0f dBm no HA", id(wifi_rssi_s).state);
} else {
it.print(0, 12, id(f_small), "WiFi DOWN - local");
}
if (std::isnan(id(g_air_t))) {
it.print(0, 26, id(f_small), "T -- RH --");
} else {
it.printf(0, 26, id(f_small), "T %.1f C RH %.0f %%", id(g_air_t), id(g_air_rh));
}
it.printf(0, 40, id(f_small), "${user1_label}: %.1f", id(${user1_src}).state);
it.printf(0, 52, id(f_small), "${user2_label}: %.1f", id(${user2_src}).state);
Sensor packages
# ---------- common/sens-sht31.yaml ----------
# SHT31-D on I2C 0x44 -> mc_XX_air_temp, mc_XX_air_rh
sensor:
- platform: sht3xd
i2c_id: bus_a
address: 0x44
update_interval: 60s
heater_enabled: false
temperature:
id: air_t
name: "Air temp"
accuracy_decimals: 1
on_value:
- lambda: "id(g_air_t) = x;"
humidity:
id: air_rh
name: "Air RH"
accuracy_decimals: 0
on_value:
- lambda: "id(g_air_rh) = x;"
# ---------- common/sens-bme680.yaml (Orchestra of Rot only) ----------
# BME680 on I2C 0x77 (0x76 if SDO to GND) -> air temp/RH/pressure + gas resistance (VOC proxy)
sensor:
- platform: bme680
i2c_id: bus_a
address: 0x77
update_interval: 60s
temperature:
id: air_t
name: "Air temp"
oversampling: 2x
on_value:
- lambda: "id(g_air_t) = x;"
humidity:
id: air_rh
name: "Air RH"
oversampling: 2x
on_value:
- lambda: "id(g_air_rh) = x;"
pressure:
id: air_p
name: "Air pressure"
gas_resistance:
id: gas_r
name: "Gas resistance"
heater:
temperature: 320
duration: 150ms
# ---------- common/sens-scd41.yaml ----------
# Sensirion SCD41 on I2C 0x62 -> mc_XX_co2 (+ diagnostic T/RH)
# ASC is OFF: sealed/biological enclosures never see fresh air (see Calibration).
sensor:
- platform: scd4x
id: scd41
i2c_id: bus_a
update_interval: 60s
measurement_mode: periodic
automatic_self_calibration: false
altitude_compensation: 80m # Bucharest
co2:
id: co2
name: "CO2"
accuracy_decimals: 0
temperature:
id: co2_t
name: "CO2 sensor temp"
entity_category: diagnostic
humidity:
id: co2_rh
name: "CO2 sensor RH"
entity_category: diagnostic
button:
- platform: template
name: "CO2 FRC 425 ppm" # press ONLY outdoors after >= 5 min stable readings
entity_category: config
on_press:
- scd4x.perform_forced_calibration:
id: scd41
value: 425
# ---------- common/sens-bh1750.yaml ----------
# BH1750 on I2C 0x23 -> mc_XX_illuminance (lux, not PAR)
sensor:
- platform: bh1750
i2c_id: bus_a
id: lux
name: "Illuminance"
address: 0x23
update_interval: 60s
# ---------- common/sens-ds18b20.yaml ----------
# One DS18B20 probe on the 1-Wire bus (GPIO4). vars: sid, label, addr, offset
sensor:
- platform: dallas_temp
one_wire_id: ow_bus
id: ${sid}
name: "${label}"
address: ${addr}
resolution: 12
update_interval: 60s
filters:
- offset: ${offset} # from the ice-water check (record sheet M3)
Finding a probe address: connect one probe, boot, read the 64-bit address (0x....) that the ESPHome log lists for the 1-Wire bus at boot, write the last 4 hex digits on the probe's label, add the include, then add the next probe.
# ---------- common/sens-soil.yaml ----------
# Capacitive soil probe v2.0 on an ADC1 pin. vars: pos (a..d), pin, dry_v, wet_v
# 10 samples x 6 s -> one averaged value per 60 s. Raw volts kept for re-calibration.
sensor:
- platform: adc
id: soil_${pos}_v
name: "Soil raw ${pos}"
pin: ${pin}
attenuation: 12db # = the old "11db" setting (renamed in ESPHome)
update_interval: 6s
accuracy_decimals: 3
unit_of_measurement: "V"
entity_category: diagnostic
filters:
- sliding_window_moving_average:
window_size: 10
send_every: 10
- platform: copy
source_id: soil_${pos}_v
id: soil_${pos}
name: "Soil moisture ${pos}"
unit_of_measurement: "%"
device_class: moisture
accuracy_decimals: 0
filters:
- calibrate_linear:
- ${dry_v} -> 0.0 # dry substrate (volts go DOWN when wetter)
- ${wet_v} -> 100.0 # saturated substrate
- clamp:
min_value: 0
max_value: 100
# ---------- common/sens-analog.yaml (pH on GPIO36, TDS on GPIO39) ----------
# Generic analog probe (pH board on GPIO36, TDS board on GPIO39). vars: aid, pin, label, unit, v1, y1, v2, y2
sensor:
- platform: adc
id: ${aid}_v
name: "${label} raw"
pin: ${pin}
attenuation: 12db
update_interval: 6s
accuracy_decimals: 3
unit_of_measurement: "V"
entity_category: diagnostic
filters:
- median:
window_size: 10
send_every: 10
- platform: copy
source_id: ${aid}_v
id: ${aid}
name: "${label}"
unit_of_measurement: "${unit}"
accuracy_decimals: 2
filters:
- calibrate_linear:
- ${v1} -> ${y1}
- ${v2} -> ${y2}
# ---------- common/in-floats.yaml ----------
# Float switches on GPIO13 / GPIO14, switch to GND, internal pull-up.
# Fail-safe wiring: ON = alarm, and an open circuit (broken wire) also reads ON.
# low float : mount so the contact is CLOSED when the float is UP (water above low mark)
# high float: mount so the contact is CLOSED when the float is DOWN (water below high mark)
binary_sensor:
- platform: gpio
id: level_low
name: "Level low alarm"
device_class: problem
pin:
number: GPIO13
mode:
input: true
pullup: true
filters:
- delayed_on: 2s
- delayed_off: 2s
- platform: gpio
id: level_high
name: "Level high alarm"
device_class: problem
pin:
number: GPIO14
mode:
input: true
pullup: true
filters:
- delayed_on: 2s
- delayed_off: 2s
# ---------- common/in-flow.yaml ----------
# YF-S401 on GPIO5 via 10k/20k divider (sensor powered from 5 V).
# Nominal K = 5880 pulses/L (F[Hz] = 98 x Q[L/min]); replace with your bucket test value.
substitutions:
flow_k: "0.00017007" # = 1 / 5880 L per pulse
sensor:
- platform: pulse_counter
id: flow_rate
name: "Flow rate"
pin:
number: GPIO5
mode:
input: true
unit_of_measurement: "L/min"
accuracy_decimals: 2
update_interval: 10s # exception to 60 s: rain events last 1-3 min
internal_filter: 13us
count_mode:
rising_edge: INCREMENT
falling_edge: DISABLE
filters:
- multiply: ${flow_k} # pulses/min -> L/min
total:
id: flow_total
name: "Flow total"
unit_of_measurement: "L"
device_class: water
state_class: total_increasing
accuracy_decimals: 3
filters:
- multiply: ${flow_k} # pulses -> L
YF-S401: nominal F = 98 × Q (Hz, L/min) → 5 880 pulses/L, ±10 % between units. Calibrate each sensor once: pump exactly 1.000 L into a measuring jug, read Flow total, and set flow_k = 1 / pulses_counted.
# ---------- common/in-level.yaml ----------
# JSN-SR04T: TRIG GPIO15, ECHO GPIO12 through 1k (series) / 2k (to GND) divider.
# GPIO12 is a strapping pin: it MUST be low at boot - the 2k to GND guarantees that.
substitutions:
tank_depth_m: "0.30" # distance sensor face -> tank bottom, measured
sensor:
- platform: ultrasonic
id: us_dist
name: "Water distance"
trigger_pin: GPIO15
echo_pin: GPIO12
update_interval: 10s
timeout: 4m
pulse_time: 20us
accuracy_decimals: 3
entity_category: diagnostic
filters:
- filter_out: nan # timeouts
- lambda: |-
if (x < 0.22 || x > 4.0) return {}; // blind zone / out of range -> drop
return x;
- median:
window_size: 6
send_every: 6 # 1 value per 60 s
- platform: copy
source_id: us_dist
id: water_level
name: "Water level"
unit_of_measurement: "m"
accuracy_decimals: 3
filters:
- lambda: "return ${tank_depth_m} - x;"
Mount the JSN-SR04T ≥ 25 cm above the maximum water level (its blind zone is ≈ 20–22 cm), pointing straight down, away from the walls.
Actuator packages
# ---------- common/act-light.yaml ----------
# PWM1 / GPIO16 -> MOSFET -> 12 V LED strip. Local photoperiod runs even without HA.
substitutions:
light_on_min: "420" # minutes after midnight (07:00)
light_off_min: "1260" # 21:00
light_level: "0.8" # 0..1 duty when the schedule switches on
output:
- platform: ledc
id: out_pwm1
pin: GPIO16
frequency: 1000Hz
light:
- platform: monochromatic
id: grow_light
name: "Grow light"
output: out_pwm1
gamma_correct: 1.0 # linear: duty = light, easier to report
default_transition_length: 2s
restore_mode: RESTORE_DEFAULT_OFF
switch:
- platform: template
id: light_auto
name: "Grow light schedule"
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
interval:
- interval: 60s
then:
- if:
condition:
switch.is_on: light_auto
then:
- lambda: |-
auto now = id(ha_time).now();
if (!now.is_valid()) return;
int m = now.hour * 60 + now.minute;
bool want = (m >= ${light_on_min}) && (m < ${light_off_min});
bool is_on = id(grow_light).current_values.is_on();
if (want && !is_on) {
auto call = id(grow_light).turn_on();
call.set_brightness(${light_level});
call.perform();
} else if (!want && is_on) {
id(grow_light).turn_off().perform();
}
# ---------- common/act-fan.yaml ----------
# PWM2 / GPIO17 -> MOSFET -> 12 V 80 mm fan
output:
- platform: ledc
id: out_pwm2
pin: GPIO17
frequency: 500Hz
min_power: 0.30 # below ~30 % duty the fan stalls
zero_means_zero: true
fan:
- platform: speed
id: fan1
name: "Fan"
output: out_pwm2
speed_count: 10
restore_mode: ALWAYS_OFF
# ---------- common/act-pump.yaml ----------
# 12 V DC pump on a PWM/MOSFET channel (default PWM3 / GPIO18). vars: pid, pin, label, max_s
# Firmware max-run timer: the pump can never run longer than max_s per start.
output:
- platform: ledc
id: ${pid}_out
pin: ${pin}
frequency: 500Hz
min_power: 0.40
zero_means_zero: true
fan:
- platform: speed
id: ${pid}
name: "${label}"
output: ${pid}_out
speed_count: 10
restore_mode: ALWAYS_OFF
on_turn_on:
- script.execute: ${pid}_timeout
on_turn_off:
- script.stop: ${pid}_timeout
script:
- id: ${pid}_timeout
mode: restart
then:
- delay: ${max_s}s
- fan.turn_off: ${pid}
- logger.log:
level: WARN
format: "${label}: max run time reached -> OFF"
# ---------- common/guard-dryrun.yaml ----------
# Needs in-floats.yaml and act-pump.yaml. vars: pid. Pump off while the low-level alarm is on.
interval:
- interval: 1s
then:
- if:
condition:
and:
- binary_sensor.is_on: level_low
- fan.is_on: ${pid}
then:
- fan.turn_off: ${pid}
- logger.log:
level: WARN
format: "Dry-run guard: ${pid} OFF (level low)"
# ---------- common/act-relay.yaml ----------
# Relay 1/2 (GPIO23 / GPIO25) for an isolated LOW-VOLTAGE load (e.g. 24 V mister). vars: rid, pin, label, max_s
output:
- platform: gpio
id: ${rid}_out
pin:
number: ${pin}
inverted: false # set true for active-low relay boards
switch:
- platform: output
id: ${rid}
name: "${label}"
output: ${rid}_out
restore_mode: ALWAYS_OFF
on_turn_on:
- script.execute: ${rid}_timeout
on_turn_off:
- script.stop: ${rid}_timeout
script:
- id: ${rid}_timeout
mode: restart
then:
- delay: ${max_s}s
- switch.turn_off: ${rid}
# ---------- common/act-servo.yaml ----------
# SG90 servo on GPIO26 / GPIO27 (5 V from the buck, signal 3.3 V). vars: sid, pin, label
output:
- platform: ledc
id: ${sid}_pwm
pin: ${pin}
frequency: 50Hz
servo:
- id: ${sid}
output: ${sid}_pwm
auto_detach_time: 2s # no buzzing/heat when idle
transition_length: 1s
number:
- platform: template
id: ${sid}_pos
name: "${label}"
min_value: -100
max_value: 100
step: 5
initial_value: 0
optimistic: true
restore_value: true
set_action:
- servo.write:
id: ${sid}
level: !lambda "return x / 100.0;"
Safety interlock: common/act-heater.yaml
The heat pad is driven only by a script in the node. The script runs every 5 s, needs no Wi-Fi or HA, and latches OFF when the controlling DS18B20 reads NaN (probe unplugged or broken) or more than 45 °C. Reset is deliberate: switch Heater enable off and on again (and if the fault persists, it trips again within 5 s). Hardware back-up: a 72 °C thermal cut-off fuse in series with the pad, taped to the pad surface.
# PWM4 / GPIO19 -> MOSFET -> 12 V heat pad (10-25 W) + 72 C thermal fuse in series (hardware).
# Local thermostat with LATCHED safety interlock. Runs in the node, works without HA/Wi-Fi.
substitutions:
heat_probe: t_sub_a # id of the DS18B20 taped to the pad / in the heated substrate
heat_max: "45.0" # C, firmware hard limit
heat_hyst: "0.5" # C, thermostat hysteresis
globals:
- id: heat_tripped
type: bool
restore_value: false
initial_value: "false"
output:
- platform: gpio
id: out_heat
pin: GPIO19
switch:
- platform: output
id: heater_raw # internal: only the guard script may drive it
output: out_heat
restore_mode: ALWAYS_OFF
internal: true
- platform: template
id: heater_enable
name: "Heater enable"
optimistic: true
restore_mode: ALWAYS_OFF
on_turn_off:
- switch.turn_off: heater_raw
- lambda: "id(heat_tripped) = false;" # manual reset = toggle enable off/on
number:
- platform: template
id: heat_sp
name: "Heater setpoint"
unit_of_measurement: "°C"
min_value: 15
max_value: 40
step: 0.5
initial_value: 25
optimistic: true
restore_value: true
binary_sensor:
- platform: template
id: heat_trip_bs
name: "Heater interlock"
device_class: problem
lambda: "return id(heat_tripped);"
- platform: template
id: heat_on_bs
name: "Heater on"
device_class: heat
lambda: "return id(heater_raw).state;"
script:
- id: heater_guard
mode: single
then:
- lambda: |-
const float t = id(${heat_probe}).state;
if (!id(heater_enable).state) {
if (id(heater_raw).state) id(heater_raw).turn_off();
return;
}
if (std::isnan(t) || t > ${heat_max}) {
if (id(heater_raw).state) id(heater_raw).turn_off();
if (!id(heat_tripped)) {
ESP_LOGW("safety", "Heater interlock TRIPPED (t=%.1f). Toggle Heater enable to reset.", t);
}
id(heat_tripped) = true;
return;
}
if (id(heat_tripped)) return; // latched until manual reset
const float sp = id(heat_sp).state;
if (t < sp - ${heat_hyst} && !id(heater_raw).state) id(heater_raw).turn_on();
if (t > sp + ${heat_hyst} && id(heater_raw).state) id(heater_raw).turn_off();
interval:
- interval: 5s
then:
- script.execute: heater_guard