# Mycodo: environmental monitoring and regulation on a Raspberry Pi

> Mycodo couples sensors to relays, PWM channels and scripts through Inputs, Outputs and Functions, and exposes the result in a web interface. It is built for growers and lab tinkerers who want a PID loop and a time-series graph without writing a control daemon.

**kizniche/Mycodo** — An environmental monitoring and regulation system

- Repository: https://github.com/kizniche/Mycodo
- Website: http://kylegabriel.com/projects/
- Stars: 3,291 · Forks: 566
- Language: Python
- License: GPL-3.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/kizniche-mycodo

## What Mycodo regulates, and who ends up running it

Mycodo is a Python application for the Raspberry Pi that, in the README's words, "couples inputs and outputs in interesting ways to sense and manipulate the environment." The problem it addresses is the gap between a sensor reading and an action. A temperature probe produces a number; a relay produces an on or off state; something has to sit in between, decide, and remember what happened. Mycodo is that something, and it keeps the history.

The README traces the project's origin to edible mushroom cultivation, and the topic list on the repository (cultivation, hydroponic, mushroom, plants) shows where most of its users come from. That origin explains the shape of the feature set: humidity and CO2 matter as much as temperature, and a fruiting chamber needs scheduled light and fan cycles, not just a thermostat. The same machinery maps onto hydroponic reservoirs, terrariums, reflow ovens, thermal cyclers and sous-vide baths, all of which the README names as setpoint-tracking use cases.

Who it is for, concretely: someone with a single board computer and a handful of sensors who wants a browser page showing live and historical graphs, threshold alerts by email, and a control loop that adjusts a heater or a pump. Who it is not for: anyone who needs firmware on a battery-powered node, or who wants a hosted service. Mycodo runs on hardware you own and administer.

## Inputs, Outputs, Functions: the three-part model

The architecture is a fixed vocabulary of three object types, and understanding it is most of the learning curve.

An Input is anything that produces a measurement. The README lists sensors, GPIO pin states and analog-to-digital converters, and points to a supported-inputs index organised by measurement type. Each Input runs on a period you set and writes rows into a time-series store.

An Output is anything that performs an action. The README gives switching a GPIO pin high or low, generating a PWM signal, and executing shell scripts or Python code. That last pair is the escape hatch: if your hardware is not on the supported list, an Output that shells out to your own program is a legitimate integration path.

A Function is the logic layer that connects the other two. The README names PID, Conditional and Trigger controllers as examples. A PID Function reads a measurement from an Input, compares it to a setpoint, and writes a duty cycle or a switching action to an Output. A Conditional Function evaluates a measurement against a threshold. Functions are also where setpoint tracking lives, which is how the README describes changing a PID setpoint over time for terrariums and thermal cyclers.

The data flow is therefore: Input samples, Function decides, Output acts, and the measurement plus the resulting state are recorded for graphing. Alerts sit alongside this loop, sending email when a measurement crosses a threshold you specify. Dashboards read from the same store, with widgets for live graphs, gauges and output state indicators. Notes let you annotate events in time so they appear overlaid on the graphs, which is the feature that makes a failed batch diagnosable after the fact.

## Installing Mycodo on Raspberry Pi OS and running a first Input

The README states the prerequisite plainly: a Debian-based Linux operating system, tested with Raspberry Pi OS 13 Trixie, and it recommends a single board computer with GPIO pins. The quick install is a single piped shell command:

```bash
curl -L https://kizniche.github.io/Mycodo/install | bash
```

That fetches and executes the installer from the project's documentation site. Because it is a pipe to bash, read the script before running it on a machine that controls physical hardware. The repository also carries an install/ directory, which is where the installer source lives if you prefer to inspect it first.

Once installed, the README says the system is configured through the web interface, reachable on your local network or remotely with an internet connection. That interface is where you add an Input. The README's Inputs documentation is the reference for the supported list; the practical first step is to pick a sensor you actually have, add it as an Input, set its sampling period, and confirm that measurements start appearing in a graph.

After the Input is recording, the next step is an Output. On a bare board with no relay attached, a GPIO pin is the simplest Output to add, since the README lists switching a GPIO pin high and low as a supported action. Adding it and toggling it from the interface verifies the whole path from web UI to pin before you introduce a PID loop. Only then is it worth adding a Function that reads the Input and drives the Output.

Upgrades go through the web interface as well. The README describes an upgrade system for moving to the latest release and a backup and restore path for returning to an earlier one.

## Where Mycodo is the wrong tool

The stack is Python, a web server and a database on one board, and that shapes its limits. A Raspberry Pi draws watts and needs a reliable power supply and SD card. If your deployment is a remote field site on solar, or a sealed enclosure you cannot easily service, the failure mode is the storage medium: SD cards wear out, and a corrupted card takes the database with it. The README does not document an automatic off-device replication scheme for measurements, so continuity depends on the backup and restore feature and on you using it.

Latency is the second boundary. A control loop implemented as a Function in a Python process is not a real-time controller. For a mushroom chamber or a hydroponic reservoir, a sampling period measured in seconds is fine. For a motor commutation loop or anything needing deterministic microsecond timing, it is not, and the README makes no real-time claim.

The third case is scale and heterogeneity. Mycodo is one system on one board. If you already run a home automation hub and want your sensors to be one device among hundreds, integrating Mycodo into that graph is extra work, and the README does not present it as a component of a larger orchestration layer. It is the orchestrator.

Finally, the supported-hardware lists are the real constraint. The README links to indexes of supported Inputs, Outputs, Functions and Widgets rather than claiming universality. A sensor that is not on the Inputs list needs a custom module, and the README points to a separate custom module repository for sharing those. That is a real development task, not a configuration toggle.

## Mycodo against Home Assistant and plain scripts

The obvious comparison is Home Assistant. Both run on a Raspberry Pi, both have a web interface and a database, and both can read a temperature sensor and switch a relay. The difference in approach is the unit of configuration. Home Assistant is organised around entities and automations: you describe a device, then write a rule that reacts to its state. Mycodo is organised around the control loop itself. A PID controller is a first-class object with a setpoint, and setpoint tracking over time is a documented feature rather than something you assemble from scheduled automations. If your goal is a chamber that ramps from 20 to 25 degrees over six hours and holds, that is native in Mycodo and a construction project in a general-purpose hub.

The other alternative is writing your own script: read the sensor, compare, toggle the pin, log to a file. That is genuinely less code than learning Mycodo's model, and for a single sensor and a single relay it may be the better choice. What you give up is everything after the first week: the historical graphs, the alert emails, the notes overlaid on timelines, the camera time-lapse, the energy usage tracking, and the upgrade path. Those are the features the README spends its length on, and they are what you are adopting when you install it. Mycodo is not a smaller thing than a script; it is a larger thing that includes one.

## Licence, maintenance and the cost of upgrading

Mycodo is GPL-3.0. For a grower running it on their own board, the practical effect is that you can use, modify and redistribute it, and if you distribute a modified version you must do so under the same licence with source. Custom Inputs, Outputs and Functions that you write and keep to yourself are your own business; the question of whether a module that links against Mycodo's internals is a derivative work is a legal question, not one this article can settle. If you plan to ship a product built on Mycodo, read the licence text in LICENSE.txt rather than a summary.

On maintenance: the repository is not archived, and the last push was on 2026-08-03, which is the same date as the v8.17.0 release. The previous release, v8.16.2, is dated 2025-06-10, and v8.16.1 is dated 2025-04-26. That spacing is worth noting: there was a roughly fourteen-month gap between v8.16.2 and v8.17.0, with two releases close together before it. The project is not dormant, but its release cadence has not been steady, so pinning to a known-good version and reading CHANGELOG.md before upgrading is the prudent pattern.

Upgrade cost is mostly the database. The repository contains an alembic_db/ directory, which indicates schema migrations are part of the release process. That means an upgrade is not just swapping code; it can alter the database your measurements live in. The README's upgrade system and backup and restore features exist for this reason, and the restore path is the one to test before you need it. The README does not document rollback beyond restoring a backup, so a backup taken immediately before each upgrade is the only recovery you should count on.

## Conclusion

Adopt Mycodo if you have a Debian-based single board computer with GPIO pins and you want sensor logging, PID regulation and a browser dashboard without writing the control loop yourself. Skip it if your target is a microcontroller with kilobytes of RAM, or if you cannot accept a Python and SQLite stack on the same machine that switches your hardware. Before committing a grow room or an incubator to it, verify three things on your own board: that your sensor appears in the supported Inputs list, that your relay or PWM device appears in the supported Outputs list, and that the install script completes on your OS release, since the README names Raspberry Pi OS 13 Trixie as the tested target.

## FAQ

### How to install Mycodo?

The README gives a single command: curl -L https://kizniche.github.io/Mycodo/install | bash. It requires a Debian-based Linux system and recommends a single board computer with GPIO pins, tested with Raspberry Pi OS 13 Trixie.

### Does Mycodo run on a Raspberry Pi?

Yes. The README describes Mycodo as open source software for the Raspberry Pi and recommends a single board computer with GPIO pins as the target hardware.

### What hardware can Mycodo read sensors from?

Inputs record measurements from sensors, GPIO pin states and analog-to-digital converters, and the README links to a supported-inputs index organised by measurement type. Anything outside that list requires writing a custom Input.

### Can Mycodo control a heater or pump with a PID loop?

The README lists a PID controller as one of the supported Functions, which couple Inputs to Outputs. Outputs can switch GPIO pins, generate PWM signals, or run shell scripts and Python code.

### How do I upgrade Mycodo to a new version?

The README describes an upgrade system in the web interface for moving to the latest release, alongside a backup and restore feature for returning to a previously backed-up version. The repository also contains an alembic_db/ directory, so upgrades can involve database schema migrations.

## Sources

- [kizniche/Mycodo on GitHub](https://github.com/kizniche/Mycodo)
- [License: GPL-3.0](https://github.com/kizniche/Mycodo/blob/master/LICENSE)
- [Project website](http://kylegabriel.com/projects/)
- [README](https://github.com/kizniche/Mycodo/blob/master/README.md)
- [Releases](https://github.com/kizniche/Mycodo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kizniche-mycodo
