Last updated: 2026-06-30
An Arduino-based environmental monitoring system for observing fungal growth through a solid substrate. The system continuously logs multi-sensor environmental data (temperature, humidity, pressure, VOC proxy, and spectral light) from a liquid fungal culture inoculated into a bag of sterile substrate.
This repo previously hosted astroPharmReactor, an E. coli bioreactor monitoring project. It has been repurposed for fungal substrate colonization studies; the historical bacterial studies and their generated dashboard data have been removed.
Use this section to resume work. At the start of a new session, ask Claude to read this README.
Current status (2026-06-30): Study 001 (pilot) just started — a liquid culture of fungus was inoculated into a bag of sterile substrate and outfitted with sensors at 5:00pm. Two short logging sessions exist so far (~10 minutes total). The sensor stack and logging scripts are unchanged from the prior project; only the organism, vessel, and sensor placement have changed. Stepper motor and pump remain wired but idle — this is a passive substrate monitoring setup, not an actively mixed liquid culture.
Open threads / next steps to discuss:
- (add notes here as discussions happen)
Monitor and log environmental conditions in and around a fungus-inoculated substrate bag over an extended colonization period. Sensor data (temperature, humidity, pressure, volatile organic compounds via gas resistance, and spectral light) is streamed from an Arduino over serial and saved to timestamped CSV files by a Python logger running on a host PC. The goal is to build a low-cost, reproducible sensor stack for tracking substrate colonization — using temperature/humidity/VOC changes as proxies for fungal metabolic activity, and light transmission through the bag as a proxy for mycelial density.
Study 001 (pilot) — a liquid culture of fungus was inoculated into a bag of sterile substrate and instrumented on 2026-06-30 at 5:00pm:
- SHT30 and BME688 #1 sit outside the bag, on the table next to it, measuring ambient room conditions.
- BME688 #2 sits inside the bag, in contact with the substrate headspace.
- The AS7341 light sensor sits under the bag, illuminated from above with a light strong enough to noticeably saturate the sensor's 16-bit ADC channels (0-65535 raw counts) if the bag were not there — so the bag's own light attenuation is the signal of interest. As mycelium colonizes the substrate and the bag interior turns opaque with growth, transmitted light reaching the sensor is expected to decrease.
- Arduino (serial at 115200 baud, no RTC — timestamps are assigned by the host PC)
| Sensor | I2C Address | Measurements | Placement (Study 001) |
|---|---|---|---|
| SHT30 Temperature & Humidity | 0x44 | Temperature (°C), Relative Humidity (%RH) | Outside the bag (ambient) |
| BME688 #1 Gas/Environmental | 0x76 (SDO → GND) | Temperature, Humidity, Pressure (hPa), Gas Resistance (Ω) | Outside the bag (ambient) |
| BME688 #2 Gas/Environmental | 0x77 (SDO → VCC) | Temperature, Humidity, Pressure (hPa), Gas Resistance (Ω) | Inside the bag |
| AS7341 Spectral Light (DFRobot Gravity) | 0x39 | F1 415nm Violet, F2 445nm Indigo, F3 480nm Blue, F4 515nm Cyan, F5 555nm Green, F6 590nm Yellow, F7 630nm Orange, F8 680nm Red, CLEAR, NIR (raw 16-bit ADC counts). All 10 channels logged as of 2026-07-08; earlier sessions logged only F1-F4, CLEAR, NIR | Under the bag, strongly illuminated from above |
The two BME688 sensors are differentiated by the state of their SDO pin: BME688 #1 has SDO pulled to GND (address 0x76) and BME688 #2 has SDO pulled to VCC/3.3V (address 0x77). This allows two identical sensors on the same I2C bus — one outside the bag as an ambient baseline, one inside the bag against the substrate.
| Actuator | Pin(s) | Notes |
|---|---|---|
| Peristaltic Pump | PWM Pin 5 | Wired but idle for Study 001 (passive substrate, no liquid feed) |
| Stepper Motor | Step: Pin 2, Dir: Pin 3 | Wired but idle for Study 001 (no agitation of a solid substrate) |
File: user_provided/arduino/01_stepper_motor/01_stepper_motor.ino
Written in C/C++. Reads all sensors and streams comma-separated values over serial at 115200 baud every 5 seconds. Controls pump duty cycle timing and stepper motor speed (unused in Study 001). No real-time clock — Arduino timestamps are millis() since boot; absolute timestamps are added by the Python logger.
Required Arduino libraries:
Wire(built-in)Adafruit_SHT31Adafruit_BME680DFRobot_AS7341
Location: user_provided/arduino/01_stepper_motor/ (run from here alongside the Arduino .ino)
Archived copies: user_provided/python/archive/
Python scripts open the Arduino serial port, parse incoming CSV lines, prepend a PC timestamp and elapsed time, and write rows directly to the correct studies/ subfolder. Scripts handle malformed packets and Arduino startup noise gracefully and print live sensor values to the terminal.
| Script | Sensors Logged | Used In |
|---|---|---|
logging_sht30.py |
SHT30 + 1× BME688 | (historical, prior project) |
logging_sht30_bme688_bme688.py |
SHT30 + 2× BME688 | (historical, prior project) |
logging_sht30_bme688_bme688_as7341.py |
SHT30 + 2× BME688 + AS7341 | Study 001 |
As of 2026-07-08 the full-sensor logger outputs 28-column CSV files: PC timestamp, elapsed time, SHT30 (temp, humidity), BME688 #1 (temp, humidity, pressure, gas resistance), BME688 #2 (same), AS7341 (F1–F8, CLEAR, NIR), stepper speed, pump speed, pump state. Sessions logged before 2026-07-08 have 24 columns — AS7341 F5–F8 were not yet read (see Sensors table above).
Output path — controlled by two variables at the top of each script:
SERIAL_PORT = "COM4" # Windows: "COM4" | Linux: "/dev/ttyUSB0"
STUDY_NAME = 'study001_pilot' # routes CSV output to studies/study001_pilot/The script resolves the absolute path to studies/STUDY_NAME/ automatically and creates the folder if it does not exist. Running build.sh after a session will pick up the new CSV immediately.
Python dependencies: pyserial
user_provided/python/generate_study_summaries.py — Reads all CSV files from studies/study*/, normalises column names across historical schema versions, filters bad/saturated sensor values, downsamples to ~4 000 points per study, and writes one JS file per study to docs/js/.
Each generated JS file exports two globals consumed by that study's own page (e.g. docs/study001_pilot.html):
| Global | Contents |
|---|---|
window.STUDY_SUMMARIES["study_name"] |
Experiment description (from description_001.txt), timeline (sessions, gaps, wall-clock, logged hours), per-variable stats (min/max/range/mean, bad-row count, bad-data windows), auto-generated interpretation (temp-pressure text + result bullets) |
window.STUDY_CHARTS["study_name"] |
Shared x-timestamps, downsampled y arrays per sensor trace (null = bad data or session gap), grouped by measurement unit (temperature, humidity, pressure, gas, light) |
The site is a small static multi-page dashboard, navigated via a left sidebar. No server required.
docs/index.html— the About page: objective, hardware, wiring, software, and sensor physics reference. Does not load any study data.docs/study001_pilot.html— Study 001's dedicated analysis page: description, timeline, variable stats, time-series charts, weather overlay, cross-correlation scatter plots, and data export, all rendered fromdocs/js/study001_pilot.js. Each future study gets its own page in the same pattern, linked from the sidebar.
Libraries:
- Plotly.js — session Gantt timeline, bad-data bar chart, dual-axis Temperature + Pressure chart, per-group time-series charts (study pages only)
- Tabulator v6 — sortable / downloadable tables for sensors, wiring, actuators, logger scripts (About page), and per-study variable statistics (study pages)
user_provided/makefile/build.sh — Runs the Python pipeline then opens docs/index.html in the browser.
bash user_provided/makefile/build.sh- Upload
01_stepper_motor.inoto the Arduino via Arduino IDE. - Connect the Arduino via USB and confirm the serial port (
/dev/ttyUSB0on Linux,COM3/COM4on Windows). - Edit
SERIAL_PORTandSTUDY_NAMEat the top of the logging script if needed. - Run from
user_provided/arduino/01_stepper_motor/:python logging_sht30_bme688_bme688_as7341.py
- CSVs are written directly to
studies/study001_pilot/(or whichever study is set). - After a session, run
bash user_provided/makefile/build.shto update the dashboard.
Place a description_001.txt-style plain-text file in the study folder to add a description that appears at the top of the study block on the website:
studies/study001_pilot/description_001.txt
Plain text, any length. Run build.sh to include it in the dashboard.
Logged CSV files are organized by study under studies/ at the repo root:
studies/
└── study001_pilot/ — Pilot study: fungal culture inoculated into a sterile substrate bag
Study 001 started 2026-06-30; sensors were just deployed and logging is ongoing.
The website pipeline reads from studies/ — copy or move completed sessions here to include them in the dashboard.
| Commit | Description |
|---|---|
| 0d62d85 | study001 updated |
| 8c1db2e | first comit |
| a6548ee | Initial commit |