Python HTML JavaScript Shell CSS C


Environmental Regulation System

Latest version: 4.1.16 Build Status Codacy Badge

Mycodo is a remote monitoring and automated regulation system with a focus on modulating environmental conditions. It was built to run on the Raspberry Pi (versions Zero, 1, 2, and 3) and aims to be easy to install and set up.

The core system coordinates a diverse set of responses to sensor measurements, including actions such as camera captures, email notifications, relay activation/deactivation, regulation with PID control, and more. Mycodo has been used for cultivating gourmet mushrooms, cultivating plants, culturing microorganisms, maintaining honey bee apiary homeostasis, incubating snake eggs and young animals, aging cheeses, fermenting foods, maintaining aquatic systems, and more.

What is PID Control?


A proportional-derivative-integral (PID) controller is a control loop feedback mechanism used throughout industry for controlling systems. It efficiently brings a measurable condition, such as the temperature, to a desired state and maintains it there with little overshoot and oscillation. A well-tuned PID controller will raise to the setpoint quickly, have minimal overshoot, and maintain the setpoint with little oscillation.

In the top graph of the above screenshot visualizes the regulation of temperature in a sealed chamber. The red line is the desired temperature setpoint that has been configured (which also happens to have been configured to change over the course of each day). The blue line is the actual recorded temperature. The green vertical bars represent how long a heater is activated for, per every 20-second period. This regulation was achieved with minimal tuning (Actual tuned gains: KP=0.08, KI=0.005, KD=0.001), and already displays a very minimal deviation from the setpoint (±0.5° Celsius). Further tuning would reduce this variability even more.

Table of Contents


  • Web interface: Visualize data, configure the system, manipulate relays, and more, from anywhere with an internet connection.
  • Many Analog and digital sensors supported: Measuring temperature, humidity, CO2, atmospheric pressure, luminosity, infrared heat, soil moisture, and more!
    • Analog to digital converter support for reading any analog sensor or signal.
  • Event triggers: When certain conditions are met, activate relays, camera recording, email notification, and more.
  • Discrete PID control: Regulate environmental conditions with prediction and precision.
  • Method creation for dynamic PID setpoints for changing conditions over time (setpoint tracking).
    • Time/Date: Change the setpoint based on specific times and dates (ideal for long-duration changes).
    • Duration: Change the setpoint at durations form when it was activated (examples: reflow oven, thermal cycler).
    • Daily: Change the setpoint on a daily, repeatable schedule.
    • Daily Sine Wave: Change the setpoint on a daily, repeatable schedule that follows a configurable sinusoidal wave.
    • Daily Bezier Curve: Change the setpoint on a daily, repeatable schedule that follows a configurable Bezier curve.
  • 16x2 and 20x4 I2C LCD support: Create a physical display of conditions or status of the system.
  • I2C multiplexer support to allow using multiple devices/sensors with the same I2C address.
  • Pi Camera support: Stream live video, capture still images, or create time-lapses.
  • Automated system upgrade: When there's new release on github, an upgrade can be initiated from the web UI.
  • Languages: English and Spanish.


  • Support Serial Port Expander
  • Support more Atlas Scientific sensors
  • Add PID filters (of input or output) and alternate PID functions.
  • Add support for wireless communication (z-wave, xbee, or other).
  • Support for PWM and servo/stepper motors
  • Continue development of Remote Admin Dashboard to monitor other Mycodo servers
  • Add graph export options (width, height, scale)
  • Create custom log from influxdb query
  • Notes, flag points of time on graph (text, file upload, graph saving, etc.).


These install procedures have been tested to work with a Raspberry Pi following a fresh install of Raspbian Jessie (Full or Lite version), with an active internet connection.

It appears that with the current version of Raspbian, SSH is not enabled by default. This necessitates the use of a keyboard and monitor to run raspi-config and enable SSH.

Set up the initial settings with raspi-config. It's very important that you don't skip the file system expansion and reboot! This needs to be done before continuing or there won't be any free disk space.

sudo raspi-config

  • Expand File system (required)**
  • Change User Password
  • Internationalisation Options -> Change Locale (set and select en_US.UTF-8 if US)
  • Internationalisation Options -> Change Timezone
  • Enable Camera
  • Advanced Options -> Enable SSH
  • Advanced Options -> Enable I2C (required if using certain sensors)
  • Reboot (required)

Mycodo will be installed by executing As a part of the installation, it will install and modify the default apache2 configuration to host the Mycodo web UI. If you require a custom setup, examine and modify this script accordingly. If you do not require a custom setup, just run the install script with the following commands:

sudo apt-get install jq
cd ~
curl -s | \
jq -r '.tarball_url' | wget -i - -O mycodo-latest.tar.gz
mkdir Mycodo
tar xzf mycodo-latest.tar.gz -C Mycodo --strip-components=1
rm -f mycodo-latest.tar.gz
cd Mycodo/install
sudo /bin/bash ./

Make sure the script finishes without errors. A log of the script output will be created at ~/Mycodo/install/setup.log.

If the install is successful, the web user interface should be accessible with your PI's IP address https://IPaddress/. The first time you visit this page, you will be prompted to create an admin user. After creating an admin user, you should be redirected to the login page to use the credentials just created to log in. Once logged in, make sure the host name and version number at the top left is green, indicating the daemon is running. Red indicates the daemon is inactive or unresponsive. Ensure any java-blocking plugins are disabled for all the web UI features to work.

Alternatively, an admin user may also be created with the following command:

sudo ~/Mycodo/ --addadmin

Install Notes

If you want write access to the mycodo files, add your user to the mycodo group, changing 'username' to your user.

sudo usermod -a -G mycodo username

In certain circumstances after the initial install, the mycodo service will not be able to start because of a missing or corrupt package. I'm still trying to understand why this happens and how to prevent it. If you cannot start the daemon, try to reinstall the required python modules with the following command:

sudo pip install -r ~/Mycodo/install/requirements.txt --upgrade --force-reinstall --no-deps

Then reboot

sudo shutdown now -r

If you receive an unresolvable error during the install, please create an issue.

Supported Devices and Sensors

Certain sensors will require extra steps to be taken in order to set up the interface for communication. This includes I2C, one-wire, and UART.


The 1-wire interface should be configured with these instructions.

DS18B20, DS18S20, DS1822, DS28EA00, DS1825/MAX31850K Temperature


DHT11, DHT22, AM2302 Relative humidity and temperature.

SHT1x, SHT2x, SHT7x Relative humidity and temperature.


K30 Carbon dioxide (CO2) in ppmv

This documentation provides specific installation procedures for the K30 with the Raspberry Pi version 1 or 2. Once the K30 has been configured with this documentation, it can be tested whether the sensor is able to be read, by executing ~/Mycodo/mycodo/tests/

Because the UART is handled differently by the Raspberry Pi 3, from of the addition of bluetooth, there are a different set of instructions for getting the K30 working on the Raspberry Pi 3. If installing on a Raspberry Pi 3, you only need to perform these steps to get the K30 working:

Run raspi-config

sudo raspi-config

Go to Advanced Options->Serial and disable. Then edit /boot/config.txt

sudo vi /boot/config.txt

Find the line "enable_uart=0" and change it to "enable_uart=1", then reboot.


The I2C interface should be enabled with raspi-config.

AM2315 Relative humidity and temperature.

Atlas Scientific PT-1000 Temperature

BME280 Barometric pressure, humidity, and temperature

BMP085, BMP180 Barometric pressure and temperature

HTU21D Relative humidity and temperature

TMP006, TMP007 Contactless temperature

TSL2561 Light

Chirp Moisture, light, and temperature

Edge Detection

The detection of a changing signal, for instance a simple switch completing a circuit, requires the use of edge detection. By detecting a rising edge (LOW to HIGH), a falling edge (HIGH to LOW), or both, actions or events can be triggered. The GPIO chosen to detect the signal should be equipped with an appropriate resistor that either pulls the GPIO up [to 5-volts] or down [to ground]. The option to enable the internal pull-up or pull-down resistors is not available for safety reasons. Use your own resistor to pull the GPIO high or low.

Examples of devices that can be used with edge detection: simple switches and buttons, PIR motion sensors, reed switches, hall effect sensors, float switches, and more.


I2C Multiplexers

All devices that connected to the Raspberry Pi by the I2C bus need to have a unique address in order to communicate. Some sensors may have the same address (such as the AM2315), which prevents more than one from being connected at the same time. Others may provide the ability to change the address, however the address range may be limited, which limits by how many you can use at the same time. I2C multiplexers are extremely clever and useful in these scenarios because they allow multiple sensors with the same I2C address to be connected.

TCA9548A I2C Multiplexer (I2C): Has 8 selectable addresses, so 8 multiplexers can be connected to one Raspberry Pi. Each multiplexer has 8 channels, allowing up to 8 devices/sensors with the same address to be connected to each multiplexer. 8 multiplexers x 8 channels = 64 devices/sensors with the same I2C address.

TCA9545A Grove I2C Bus Multiplexer (I2C): This board works a little differently than the TCA9548A, ablove. This board actually creates 4 new I2C busses, each with their own selectable voltage, either 3.3 or 5.0 volts. Instructions to enable the Device Tree Overlay are at Nothing else needs to be done in Mycodo after that except to select the correct I2C bus when configuring the sensor.

Analog to Digital Converters

An analog to digital converter (ADC) allows the use of any analog sensor that outputs a variable voltage. A voltage divider may be necessary to attain your desired range.

ADS1x15 Analog to Digital Converters ±4.096 (I2C)

MCP342x Analog to Digital Converters ±2.048 (I2C)


A minimal set of anonymous usage statistics are collected to help improve development. No identifying information is saved from the information that is collected and it is only used to improve Mycodo. No other sources will have access to this information. The data collected is mainly how much specific features are used, how often errors occur, and other similar statistics. The data that's collected can be viewed from the 'View collected statistics' link in the Settings/General panel of the UI or in the file Mycodo/databases/statistics.csv. You may opt out from transmitting this information from the General settings in the Admin panel.

Mycodo/mycodo/scripts/mycodo_wrapper is a binary executable used to update the system from the web interface. It has the setuid bit to permit it to be executed as root ('sudo bash ~/Mycodo/mycodo/scripts/ initialize' sets the correct permissions and setuid). Since shell scripts cannot be setuid (ony binary files), the mycodo_wrapper binary permits these operations to be executed as root by a non-root user (in this case, members of the group 'mycodo'). You can audit the source code of Mycodo/mycodo/scripts/mycodo_wrapper.c and if you want to ensure the binary is indeed compiled from that source, you may compile it yourself with the following command. Otherwise, the compiled binary is already included and no further action is needed.

sudo gcc ~/Mycodo/mycodo/scripts/mycodo_wrapper.c -o ~/Mycodo/mycodo/scripts/mycodo_wrapper

HTTP Server Security

An SSL certificate will be generated and stored at ~/Mycodo/mycodo/mycodo_flask/ssl_certs/ during the install process. If you want to use your own SSL certificates, replace them with your own. provides free verified SSL certificates if you have your own domain.

If using the auto-generated certificate from the install, be aware that it will not be verified when visiting the 'https://' version (opposed to 'http://')of the web UI. You may receive a warning message about the security of your site, unless you add the certificate to your browser's trusted list.

Daemon info

The status of the daemon's service can be checked

sudo service mycodo service

The daemon can also be started manually if the systemd method above isn't used or an error needs to be debugged

sudo ~/Mycodo/mycodo/

Also, use '-d' to log all debug messages to /var/log/mycodo/mycodo.log

sudo ~/Mycodo/mycodo/ -d

To terminate the daemon, you can use two methods. If the daemon was started with sudo service mycodo start, please use sudo service mycodo stop to stop it. If the daemon was started from either of the two commands above, then the following command may be used to terminate the daemon:

python ~/Mycodo/mycodo/ -t


If you already have Mycodo installed (>=4.0.0), you can perform an upgrade to the latest release on github by either using the Admin/Upgrade menu in the web UI (recommended) or by issuing the following command at the terminal. A log of the upgrade process is created at /var/log/mycodo/mycodoupgrade.log

sudo /bin/bash ~/Mycodo/mycodo/scripts/ upgrade

Upgrading the mycodo database is performed automatically during the upgrade process, however it can also be performed manually with the following commands (Note: This does not create the database, only upgrade them. You must already have a database created in order to upgrade):

cd ~/Mycodo/databases
alembic upgrade head

Refer to the alembic documentation for other functions.

Backup and Restore

Currently only the Mycodo settings are backed up when the system is upgraded from the Admin/Upgrade menu of the web UI.

If you would like to create a full backup that includes all the sensor data, which can be used to set up Mycodo on a new system as it was on the old, you can follow these steps:

Backup the influx databases:

influxd backup <path-to-metastore-backup>
influxd backup -database mycodo_db <path-to-database-backup>

Backup the Mycodo databases:

cd ~/Mycodo/databases
tar zcf ~/Mycodo-databases.tar.gz users.db mycodo.db

Then, on the new system, assign the same IP as the old system (if using the remote admin).

Clone the latest Mycodo from github (ensure prerequisites are taken care of first):

cd ~
clone git clone

Extract the Mycodo databases back to Mycodo/databases:

tar zxvf ~/Mycodo-databases.tar.gz -C ~/Mycodo/databases

To ensure your databases are up-to-date and compatible with the latest version of Mycodo, run:

cd ~/Mycodo/databases
alembic upgrade head

Execute the Mycodo script:

cd ~/Mycodo/install
sudo /bin/bash

Restore the influx databases:

service influxdb stop
influxd restore -metadir /var/lib/influxdb/meta <path-to-metastore-backup>
influxd restore -datadir /var/lib/influxdb/data <path-to-database-backup>
sudo chown -R influxdb:influxdb /var/lib/influxdb
service influxdb start

The order of these events are important, because databases will be created and services started while the script is running, so certain commands need to be done before this happens.

You could also copy the influx databases and just copy the entire Mycodo directory (archive to preserve permissions) to a new system, but I was writing from the perspective of backing up the most minimal set of data, so if a system became corrupt somewhere, the backups could be restored to a new system.


Translation support has been added but there is currently a lack of translation languages. If you know another language and would like to create translations, follow the steps below.

To create your own translation, use the following commands.

cd ~/Mycodo/mycodo

Create a messages.pot file from searching all files that contain translatable text.

pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot .

Create the translation for the new language (in this case it is 'es' for Spanish).

pybabel init -i messages.pot -d mycodo_flask/translations -l es

There will now be the file 'messages.po' created in ~/Mycodo/mycodo/mycodo_flask/translations/es/LC_MESSAGES/

Edit messages.po (I used poedit) to edit and save the translation for each translatable word or phrase.

Finally, compile the new translation.

pybabel compile -d mycodo_flask/translations

If you would like to rescan for translatable text and update your language's messages.po file (or add translations to an already-created messages.po) without losing your previous translation work, use the following commands instead of the above commands. Then edit with poedit (or similar app) and compile for it to take effect.

pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot .
pybabel update -i messages.pot -d mycodo_flask/translations
pybabel compile -d mycodo_flask/translations

The important file is ~/Mycodo/mycodo/mycodo_flask/translations/##/LC_MESSAGES/messages.po (with '##' representing the language code, e.g. 'es' for spanish, 'fr' for French) that should either be sent to me or added to a pull request. This is how the new translations can be incorporated into Mycodo.

Refer to The Flask Mega-Tutorial, Part XIV: I18n and L10n for more details of this process.

Directory Structure

This is the file structure of Mycodo, so it may assist anyone to understand or modify the system. I'll try to keep this current.

├── - Mycodo version changelog
├── databases - SQLite databases (for configuration)
│   ├── alembic - Alembic SQL database migration tool
│   │   └── versions - Scripts to upgrade/downgrade databases
│   │       ├──
│   │       ├──
│   │       └── ...
│   ├── mycodo.db - Mycodo settings
│   ├── notes.db
│   ├── statistics.csv - Anonymous statistics data
│   └── users.db - User settings
├── - Script to create SQLite databases and users
├── install
│   ├── - Ensures proper line is in crontab
│   ├── mycodo.service - Systemd script
│   ├── mycodo_flask_apache.conf - Apache2 configuration file
│   ├── requirements.txt - Python module requirements
│   └── - Mycodo install script
├── mycodo
│   ├── - Global configuration file
│   ├── - LCD controller class
│   ├── - Log controller class
│   ├── - PID controller class
│   ├── - Relay controller class
│   ├── - Sensor controller class
│   ├── - Timer controller class
│   ├── - Various functions to assist
│   ├── databases - SQL database manipulation framework (SQLAlchemy)
│   │   └── ...
│   ├── devices - Python modules for devices (such as I2C multiplexer)
│   │   ├──
│   │   ├──
│   │   └── ...
│   ├── - Flask form classes
│   ├── - Various functions to assist the flask UI
│   ├── mycodo_flask - HTTP server files (Flask)
│   │   ├── - Admin page routes
│   │   ├── - Authentication routes
│   │   ├── - General routes
│   │   ├── - Method routes
│   │   ├── - General page routes
│   │   ├── - Settings page routes
│   │   ├── ssl_certs - Location of HTTP SSL certificates
│   │   ├── static - Static files reside (images, css, js, etc.)
│   │   ├── templates - Flask HTML templates
│   │   │   ├── 404.html
│   │   │   ├── flash_messages.html - Error message handler
│   │   │   ├── layout.html - Template for pages/, settings/, /tools
│   │   │   ├── layout-remote.html - Template for /remote
│   │   │   ├── layout-settings.html - Template for /settings
│   │   │   ├── login.html - Login page
│   │   │   ├── manual.html - Mycodo usage manual
│   │   │   ├── admin - Flask admin pages
│   │   │   ├── pages - Flask general pages
│   │   │   │   ├── graph.html - Graph display age
│   │   │   │   ├── live.html - Live data display page
│   │   │   │   ├── sensor.html - Sensor configuration page
│   │   │   │   └── ...
│   │   │   ├── remote - Future remote administration panel
│   │   │   │   └── setup.html - Add or check the status of remote systems
│   │   │   ├── settings - Flask settings pages
│   │   │   │   ├── alerts.html - Alerts settings page
│   │   │   │   ├── users.html - Users settings page
│   │   │   │   └── ...
│   │   │   └── tools - Various tools for Mycodo
│   │   │       ├── info.html - Information about your system
│   │   │       ├── logview.html - Display log files
│   │   │       ├── usage.html - Calculate relay usage/power consumtion
│   │   │       └── ...
│   │   └── translations - Language translations
│   ├── - Communicates with the running daemon
│   ├── - Mycodo daemon (core of the system)
│   ├── - Flask startup script
│   ├── scripts - Miscellaneous helper and test scripts and functions
│   │   ├── mycodo_wrapper.c - Source to binary that's setuid, for upgrades 
│   │   ├── - Script to restore a backed-up Mycodo version
│   │   ├── - Updates Mycodo to the latest release
│   │   ├── - Post update commands (from the latest release)
│   │   └── ...
│   ├── sensors - Python modules for sensors
│   │   ├──
│   │   ├──
│   │   ├──
│   │   └── ...
│   └── tests - Software and Hardware Tests 
│       ├── manual_tests - Scripts to test various sensors or devices
│       │   ├──
│       │   ├──
│       │   ├──
│       │   └──...
│       └── software_tests - Automated Tests for Software
├── mycodo_flask.wsgi - Start script for Apache2 mod_wsgi
├── old - Archived milestone versions of Mycodo


Mycodo is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Mycodo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

A full copy of the GNU General Public License can be found at

This software includes third party open source software components: Discrete PID Controller. Each of these software components have their own license. Please see Mycodo/mycodo/ for license information.

Screenshots (may be outdated)

See the status of all sensors on one page

Create custom live graphs

Add sensors

Configure and manipulate relays

Create PID controllers

Output to LCDs

Change settings


Thanks for using and supporting Mycodo, however it may not be the latest version or it may have been altered if not obtained through an official distribution site. You should be able to find the latest version on github or my web site.