Open-Source Photobioreactor for Low-Cost, Efficient Microalgae Cultivation

Orr Biologicals
Los Angeles, California
BiologyComputer Science
$225
Raised of $572 Goal
40%
Ended on 7/31/26
Campaign Ended
  • $225
    pledged
  • 40%
    funded
  • Finished
    on 7/31/26

About This Project

Hi, my name is Cameron, and I’m a high school student working on an open-source AI project to improve microalgae yields this summer. Microalgae are important microbes with major uses in biofuels, food, and other biotech applications. Our goal is to build a working prototype that shows how an AI-driven sensor feedback loop can improve biomass yield compared to a traditional fixed-control photobioreactor.

Ask the Scientists

Join The Discussion

What is the context of this research?

As a 15-year-old high school student, I’ve seen firsthand how difficult and expensive it can be to grow microalgae in a sterile vessel and achieve high biomass concentrations without a traditional photobioreactor. This challenge is not unique to me; many independent phycologists and small labs face the same financial barrier, limiting research in fields such as biofuels, food, and pharmaceuticals.

This project addresses the algal biotechnology sector, a relatively new but rapidly growing industry with major potential across many areas of life. However, current photobioreactors still face major bottlenecks, especially high operating costs and difficulty scaling to larger volumes. By building on research from the AI and biology communities, we aim to combine these fields into a more efficient system for cultivating microalgae. With support for open-source, data-driven software, scientists and small researchers could gain access to affordable and effective algae cultivation tools.

What is the significance of this project?

This project is significant because it addresses a major gap in microalgae biotechnology: while AI and machine learning have shown promise, there are still very few open-source systems that use real sensor feedback to actively improve biomass yield. MAIN aims to turn that research potential into a practical, affordable, and reproducible platform that small labs, independent researchers, and students can actually use.

What are the goals of the project?

We have three main goals for this project.

First, we want to build a microcontroller-based package with sensors that can connect to almost any growth vessel and turn it into a working photobioreactor capable of growing Spirulina to about 1 g/L in 10 days.

Second, we want to prove that the AI agent can communicate autonomously with the native microcontroller package using MQTT, creating a real closed-loop control system.

Third, we want to keep the final hardware design affordable, with an estimated bill of materials under $50, while still showing that our AI system can outperform a standard photobioreactor by increasing biomass yield by at least 50% compared to a commercial baseline of 1 g/L.

Budget

Please wait...

These items will act as the interface between the AI model on my computer and the sensors allowing them to communicate with each other.

You can see we used dissolved oxygen, which is a great indicator of culture health. Although it is expensive, I do want to test if it produces any noticeable difference. If not, it will be removed from the final product to eliminate cost. We are building ONE test pilot bioreactor but the extra cost is due to experimental features, consumables, and microalgae cultures.

Endorsed by

This project is moving into the realm of autonomous microorganism growth that is both more efficient and cheaper than conventional methods. This project also addresses the intersection between world-model AI and biology.

Project Timeline

Within one month of funding, all five reactor controllers will be assembled, wired, and tested with five algae strains: Spirulina, H. pluvialis, Chlorella, Pavlova, and Schizochytrium. These strains will be grown under AI-driven autonomous optimization, with weekly public updates and a controlled comparison against a fixed-recipe reactor. By Month 4, we will release the complete open-source package, including hardware plans, code, a build guide, and the full eight-week dataset.

Jul 11, 2026

Project Start

Jul 17, 2026

Project Launched

Jul 22, 2026

Purchase Materials

Jul 30, 2026

Assemble Code and Hardware

Aug 13, 2026

AI driven trials vs control

Meet the Team

Cameron Orr
Cameron Orr
Student

Affiliates

Orr Biologicals
View Profile

Cameron Orr

I started off interested in biology at around the age of ten trying to understand the immune system. However, I currently am extremely excited about the opportunities in algal biotechnology in real-world applications. As a result, I founded Orr Biologicals.

I have taken three UCSD extension courses in microbiology to challenge and deepen my learning. This is why I always read scientific literature in my free time.

Lab Notes

Nothing posted yet.

Additional Information

cameronorr2011-beep/spirulina: Stunning Green look at my code

orrbiologicals.com for more

# MAIN / PhycoNet — Complete Strain‑Adaptive System Workflow

**Version:** 3.0 — definitive, matches the audited code in `https://github.com/cameronorr2011-beep/spirulina`

**Hardware:** Raspberry Pi Zero 2 W + MCP3008 ADC, 5 peristaltic pumps, touchscreen, ESP32‑CAM

**Principle:** The AI is a recommendation engine; the Pi is the edge controller. Safety and digital twin validation are never bypassed.

---

## 1. Unboxing & Physical Setup

The “PhycoNet Module” is a pre‑wired, self‑contained controller box. It contains:

- Raspberry Pi Zero 2 W (512 MB RAM) with 32 GB microSD pre‑flashed with MAIN

- MCP3008 8‑channel ADC (SPI)

- All sensors (mandatory): DS18B20 (One‑Wire), E‑201C pH probe, TSD‑10 turbidity, analog TDS, BH1750 light, optical DO probe (DFRobot SEN0237)

- ESP32‑CAM microscope module (wired via USB; includes HQ camera, flow‑through bypass cell, LED ring)

- 5 peristaltic pumps (12 V DC)

- 4 IRF520 MOSFET driver modules, 1 relay module for heater

- RGB LED strip with separate PWM channels (Red, Green, Blue)

- 3.5″ touchscreen (SPI) + SSD1306 OLED (I²C)

- Emergency stop button (hardwired to a normally‑closed relay that physically cuts actuator power)

- Water level float switch (GPIO24 – **Known conflict:** GPIO24 is shared with Pump 5 (air pump). In the next hardware revision, move the float switch to GPIO5. Until then, the water level safety is disabled if Pump 5 is in use.)

- Culture vessel (≤ 20 L), bicarbonate reservoir, nutrient reservoir, cleaning solution reservoir, sterile inoculation vessel with 0.22 µm filter, tubing, check valves, harvest mesh (50 µm)

**User actions:**

1. Place all sensors into the photobioreactor bottle.

2. Fill the bicarbonate jar (1 tablespoon baking soda in 100 mL water) and connect tubing to **Pump 1**.

3. Fill the nutrient jar (Zarrouk / f/2) and connect tubing to **Pump 2**.

4. Fill the cleaning solution jar and connect to **Pump 3**.

5. Prepare a sterile inoculation vessel with a 0.22 µm filter in‑line, connect to **Pump 4**.

6. Attach the air pump to **Pump 5**.

7. Plug all sensor and pump cables into the labelled ports.

8. Plug the 12 V power adapter into the wall and the controller.

---

## 2. First Boot — Setup Hotspot

1. Pi boots. No `config.json` exists → enters **setup mode**.

2. The Pi creates a temporary, open Wi‑Fi network `MAIN‑Setup‑` on virtual interface `wlan0_ap`.

3. The **touchscreen** displays: `“Welcome to MAIN – connect your phone to MAIN‑Setup‑XXXX to begin.”`

4. A Flask captive portal runs on port 80; `dnsmasq` redirects all traffic to `192.168.4.1`.

5. The user’s phone connects to the temporary hotspot; the setup page opens automatically.

**Setup form fields:**

- **Algae strain** (dropdown: Spirulina, Chlorella, Haematococcus, etc.)

- **Free‑text growth goal** (e.g., “I want bright orange spirulina with high phycocyanin”)

- **PBR type and volume** (bottle, flat panel, tubular; up to 20 L)

- **Culture medium** (Zarrouk, BG11, f/2)

- **Home Wi‑Fi SSID + password** (optional – enables internet)

- **Password for the permanent MAIN‑Regular hotspot**

6. User taps “Save & Connect”.

7. The Flask backend writes all choices into `/home/pi/gaon/config.json` (on the SD card).

8. The Pi reboots.

---

## 3. Permanent Network & Services Start

After reboot:

1. `main.py` reads `config.json`.

2. A permanent, WPA2‑secured hotspot **`MAIN‑Regular`** is created on `wlan0_ap` (password from config).

3. If home Wi‑Fi was given, `wlan0` connects as a client to the home router → internet access.

4. Three systemd services launch automatically:

- `main.service` – sensor loop, MQTT cloud client, actuator command handler

- `wifi.service` – Flask API, hotspot management

- `dashboard.service` – Streamlit on port 8501

5. **Touchscreen** now shows the live local GUI:

- Large digits: pH, temperature, optical density (turbidity), dissolved oxygen, TDS

- System status: “Healthy”, “Warning”, “Action needed”

- Last executed action

- Emergency STOP button (software + hardware relay)

6. Secondary OLED (I²C, 0x3C) scrolls through IP addresses and vitals.

---

## 4. Connecting the Phone for Daily Use

1. User manually connects to `MAIN‑Regular` once, entering the hotspot password. The phone remembers it.

2. **Local dashboard** (always available): `http://192.168.4.1:8501`.

3. **Home‑network dashboard** (if Pi is on home Wi‑Fi): `http://main.local:8501` (via mDNS).

4. The Streamlit dashboard provides:

- Live charts (pH, temp, OD, DO, TDS, light)

- Latest AI proposal and reasoning

- Manual override panel

- **Settings** tab to edit goal, Wi‑Fi, safety limits, or strain – overwrites `config.json` and reloads modules without reboot.

---

## 5. Continuous Sensor Loop (Every 60 Seconds)

1. `main.py` calls `HardwareDriver.read_all()`:

- DS18B20 (One‑Wire, GPIO4)

- pH (MCP3008 CH0)

- Turbidity (MCP3008 CH1)

- TDS (MCP3008 CH2)

- BH1750 (I²C)

- Optical DO (I²C)

2. `sensors.py` applies calibration curves (slope/intercept from `config.json`).

3. Sanitised values are:

- Appended to `/home/pi/gaon/data/{pbr_id}.csv` (rotated monthly, max 10 000 lines)

- Published to the **private HiveMQ Cloud broker** (TLS, authenticated) on `gaon/pbr/{pbr_id}/telemetry`

- Pushed to local MQTT for dashboard/touchscreen updates

4. If the cloud broker is unreachable, `mqtt_queue.py` buffers telemetry in SQLite; replays on reconnect.

---

## 6. Microscopy Imaging Loop (Every 6 Hours or on Demand)

1. `image_handler.py` triggers the ESP32‑CAM (USB) to capture a JPEG.

2. The image is analysed locally for optical density (pixel intensity) and basic contamination flagging (colour clustering, morphology).

3. Results (contamination probability, cell health score) are appended to the telemetry snapshot.

4. If contamination probability rises, the AI router will later select **Gemini** for deeper biological reasoning.

---

## 7. Digital Twin — Strain‑Specific & Self‑Calibrating

The digital twin is initialised with the **strain name** from `config.json`. A built‑in library provides the following defaults (overridable via `config.json`):

| Parameter | Spirulina | Chlorella | Haematococcus |

|-----------|-----------|-----------|---------------|

| `μ_max` (h⁻¹) | 0.04 | 0.06 | 0.03 |

| `I_opt` (µE/m²/s) | 220 | 180 | 150 |

| `pH_opt` | 9.5 | 7.0 | 7.5 |

| `T_opt` (°C) | 30 | 28 | 25 |

| `K_s` (mg N/L) | 2.5 | 1.8 | 3.0 |

| `Q0` (mg N / mg C) | 0.03 | 0.02 | 0.04 |

**Calibration (every 6 hours):**

1. `EvolvingTwin.calibrate_from_csv()` loads the last 48 h of local CSV data.

2. Using `scipy.optimize.least_squares`, it fits only three parameters — `μ_max`, `K_s`, `I_opt` — to minimise the error between simulated and measured OD. All other parameters stay at literature values.

3. Updated parameters are saved to `data/{strain}_params.json`.

4. After calibration, a 24‑h forward prediction is run; the predicted biomass, nutrients, and lipids are included in the telemetry sent to the AI.

---

## 8. Safety Envelope — Strain‑Adaptive Hard Limits

`safety.py` reads the strain‑specific bounds at startup. If the user has overridden any limit in `config.json`, those values are used.

| Limit | Spirulina | Chlorella | Haematococcus |

|-------|-----------|-----------|---------------|

| pH min – max | 8.5 – 10.5 | 6.5 – 7.5 | 7.0 – 8.5 |

| Temp min – max | 20 – 35 °C | 20 – 32 °C | 18 – 28 °C |

| Light min – max | 100 – 400 µE/m²/s | 100 – 400 µE/m²/s | 100 – 300 µE/m²/s |

| Nutrient pulse max | 20 mL | 20 mL | 15 mL |

| Bicarbonate dose max | 5 g | 3 g | 4 g |

**Universal hard limits (all strains):**

- Pump runtime ≤ 15 s per dose

- Heater runtime ≤ 5 min per cycle

- **Acid‑crash floor:** if pH < 6.5, **all dosing commands are rejected** regardless of strain optimum.

**Additional protections:**

- **Override button (GPIO15):** hardware interrupt → immediate `STOP_ALL`. A normally‑closed relay physically cuts actuator power.

- **Water level sensor (GPIO24):** when low, heater relay is disabled. (Note pin conflict; see Section 1.)

- **Watchdog:** hardware watchdog (8 s timeout) reboots the Pi if the main loop hangs.

- **Digital twin pre‑check:** before any command, the twin simulates the proposed action. If predicted growth rate < 0.01 h⁻¹, the action is blocked.

---

## 9. AI Brain Cycle — Strain‑Aware & Dual‑Model (Laptop)

The AI brain runs on a **separate laptop** (or cloud instance) connected to the same HiveMQ Cloud broker. It never directly controls hardware.

**Normal mode (internet available):**

1. `run_brain.py` (or `ai/agent.py`) receives the latest telemetry + twin 24‑h prediction.

2. **Memory retrieval:** `ChromaMemory.retrieve_similar()` returns the top‑3 past experiments with similar conditions.

3. **Health score:** `sensor_health.compute_reactor_health_score()` generates a 0‑100 value from pH, temp, light, OD, alarms, and twin prediction.

4. **Router (`ai/router.py`):**

- If health score < 50, or contamination flag is set → **Gemini** (deep biological reasoning).

- Otherwise → **Groq** (routine daily optimisation).

5. **Gemini prompt** is built with:

- User’s free‑text goal

- Strain name and **its optimal environmental ranges**

- Current sensor snapshot

- 24‑h twin prediction

- Top‑3 similar past experiments

- A strict reminder of the strain‑specific hard safety bounds

Gemini returns a biological assessment and a recommended action with confidence.

6. **Groq path:** Groq converts the recommendation (or generates a routine daily proposal) into a precise JSON command and performs a syntax‑and‑safety critique.

7. **Structured output:**

`{"action":"ADJUST_LIGHT","value":220,"reason":"…","confidence":0.88}`

8. **Safety validation on the laptop:**

- `SafetyValidator` checks strain‑specific hard bounds.

- The laptop’s copy of the digital twin (seeded with the same calibrated parameters) simulates the action for 24 h. If predicted growth < 0.01 h⁻¹, block.

9. If approved, publish command to `gaon/pbr/{pbr_id}/command`.

**Offline fallback (no internet > 5 minutes):**

- Pi detects loss (ping 8.8.8.8 fails).

- If no remote command in 6 h, `offline_fallback.py` activates.

- It maintains the last safe pH/temp setpoints (within strain bounds) and keeps air pump running.

- No local LLM runs (Pi Zero 2 W cannot support it).

---

## 10. Command Execution & Memory Logging

1. Pi receives command via `mqtt_client.py`.

2. `safety.py` re‑validates against strain‑specific bounds.

3. `actuators.py` executes: pump MOSFET, LED PWM, heater relay.

4. Acknowledgment published to `gaon/pbr/{pbr_id}/command_ack`.

5. **Only after** 24 h (or next twin calibration) is the **validated outcome** stored:

- Laptop’s **ChromaDB** (fast search)

- Pi’s **JSON memory** (`experiments.json`) for offline fallback.

---

## 11. Federated Learning (Every 12 Hours)

1. Pi publishes its calibrated twin parameters (dict of floats + confidence) to `gaon/federated/model_update`.

2. Laptop aggregator (`aggregator.py`) groups by strain, computes a weighted average (rejects outliers >3σ), and publishes the global model to `gaon/federated/global_model`.

3. Pis update their twin with the global parameters.

4. No raw sensor data, images, or private information ever leaves the device.

---

## 12. Editing `config.json` Later

- Dashboard **Settings** tab writes changes to `config.json`.

- `main.py` reloads the affected modules without reboot.

- Touchscreen immediately reflects new goal or strain name.

---

## 13. Maintenance

- **Harvesting:** manual via 50 µm mesh as recommended by AI.

- **Refilling reservoirs:** dashboard warns when dosing frequency drops.

- **Sensor cleaning:** manual wipe when biofilm is suspected.

- **pH recalibration:** dashboard prompts if drift >0.3 units for 24 h (measured vs twin prediction).

---

## 14. Final Pin Map (with known conflict)

| Function | GPIO | Notes |

|----------|------|-------|

| MCP3008 CE0 | 8 | SPI CS |

| MCP3008 MOSI | 10 | SPI |

| MCP3008 MISO | 9 | SPI |

| MCP3008 SCLK | 11 | SPI |

| DS18B20 (temp) | 4 | One‑Wire |

| pH probe | MCP3008 CH0 | Analog |

| Turbidity | MCP3008 CH1 | Analog |

| TDS | MCP3008 CH2 | Analog |

| BH1750 (light) | 2/3 | I²C SDA/SCL |

| DO probe | 2/3 | I²C |

| OLED (secondary) | 2/3 | I²C (0x3C) |

| Touchscreen | SPI/DPI | Per screen model |

| Pump 1 – Bicarbonate | 17 | MOSFET |

| Pump 2 – Nutrient | 27 | MOSFET |

| Pump 3 – Cleaning | 22 | MOSFET |

| Pump 4 – Inoculation | 23 | MOSFET |

| Pump 5 – Air pump | 24 | MOSFET |

| Heater relay | 25 | Relay |

| LED Red | 12 | PWM MOSFET |

| LED Green | 13 | PWM MOSFET |

| LED Blue | 18 | PWM MOSFET |

| Override button | 15 | Active‑low, pull‑up |

| Water level sensor | 24* | *Conflict with Pump 5; move to GPIO5 in next HW rev. |

---

**This document is the authoritative specification of MAIN’s complete operational behaviour. It incorporates all audited fixes, strain‑adaptive guardrails, and the clarification that the AI is a recommendation engine, not an autonomous controller.**


Project Backers

  • 2Backers
  • 40%Funded
  • $225Total Donations
  • $112.50Average Donation
Please wait...