Tom's Carnivores

How to Build a Raspberry Pi
Terrarium Controller

Tom Bennet
By Tom Bennet
Last updated
I've been growing a wide variety of carnivorous plants for over 2 decades. I got my first Venus flytrap at age 10 and now have an entire greenhouse full of carnivores.

Whether you’re growing tropical pitcher plants or Mexican butterworts, an electronic controller can provide a more stable environment than you can ever hope to achieve using regular timers. By integrating your terrarium into the Internet-of-Things using a Raspberry Pi, it’s possible to create a highly-extensible system which offers automation, data visualisation, alerts, and pretty much anything you or your plants (or even pets!) could want.

Here’s an example of the live conditions inside my own terrarium:

In this guide, I’ll be giving step-by-step instructions for building a simple Terrarium Controller using the new Raspberry Pi 3 and a few off-the-shelf parts for a total cost of less than £100 (or $130 USD). You don’t have to be an electrician or a programmer - I’m certainly not. The only skills required are basic wiring and experience with the Raspberry Pi and its GPIO. Let’s get started.

Parts Required

Note: Where possible, links are to ModMyPi.com, ThePiHut.com, and Pimoroni.com, all good UK-based specialists, plus Amazon (UK or US, depending on your location). As an Amazon Associate I earn from qualifying purchases. For US readers, most products (or close alternatives) are also available from Adafruit or RadioShack.

Prerequisites

Variables

The four main variables in any terrarium are temperature, humidity, light, and water. These are the things which you need to monitor and control if your plants or pets are going to be happy. For the purposes of our Terrarium Controller, we’ll assume you have watering under control; it’s an easy task and infrequently required in terrariums which are sealed or nearly-sealed. Instead, we’ll be focusing on the first three.

Light is probably easiest to control. Most terrarium owners set fluorescent lights along the top of their tank and then switch these on and off at regular intervals. Lighting will be simple to automate, since we needn’t respond to anything other than the time.

My terrarium, with T-5 flourescent lights mounted on the top and the controller installed.
My terrarium, with T-5 flourescent lights mounted on the top and the controller installed.

Temperature is more difficult. Most lighting fixtures provide a certain amount of heat, and this usually needs to be dissipated or supplemented depending the type of plants or animals you’re keeping. If your home is already quite warm, fans may be necessary to blow away excess heat from the fixtures. If your home tends towards the chilly side, you’ll probably need a heating mat under your terrarium. Under some circumstances, it might be necessary to alternate between both.

Finally, there’s humidity: in a sealed environment it’s generally quite easy to keep humidity above 80%. While owners of larger terrariums might consider humidifiers or foggers, occasional watering and misting should provide your terrarium with all the moisture it needs. If, on the other hand, you need to lower the humidity, you’ll probably need a small interior fan to circulate the steamy air and increase ventilation.

Whichever route you go down, the key point is this: we need to switch numerous mains-powered components on or off depending on (a) the time, and (b) the current conditions inside the terrarium.

Hardware

The first component which we’ll be wiring into our Pi’s GPIO is a combined temperature and humidity sensor. The AM2302 is a wired version of the common DHT22 sensor in a convenient plastic housing. It’s very easy to use and fairly cheap (about £10 / $15).

AM2302 temperature and humidity sensor.
AM2302 temperature and humidity sensor.

How are we to switch other components on or off based on our sensor readings? While it’s possible to run a very small fan off the Pi’s minimal power output, all of our terrarium’s components (fluorescent lights, heaters, etc.) are mains powered. Using relays to control mains electricity can be extremely dangerous, but thankfully, remote-controlled mains sockets provide us with an easier and safer alternative.

Energenie’s Pi-mote starter kit is ideal for our purposes. It includes two electrical sockets and a controller chip, which plugs into the Pi’s GPIO and communicates with the sockets using 433mHz radio frequency. You can buy unlimited additional sockets up to a maximum of four ‘groups’, providing us with control over four ’things’ at once (e.g. fans as one group, heating pads as another).

The only real downside of Energenie sockets is that you need to ensure sufficient physical separation between sockets - the Energenie manual suggests 2 metres. In the interest of keeping things simple and avoiding potential complications, I recommend that you use standard mechanical timers to control components which follow a set routine (e.g. lights, circulation fans), and only use Energenie for things which depend on your sensor reading (e.g. cooling fans, heating pads).

Update: Energenie now offer a multi-outlet mains lead, meaning you no longer need to ensure physical separation between individual components. Each socket is individually controllable. You can buy it on Amazon here, and the official quick-start guide is here.

As you may have guessed, installing the Pi-mote transmitter and the AM2302 sensor simultaneously is a little tricky; the Pi-mote is designed to sit directly on the GPIO, occupying almost the entire header and leaving no power pins for our lowly sensor. To avoid this problem, we can use an extra-short ribbon cable of male-female jumper wires to connect the required GPIO pins to their respective sockets on the transmitter.

The AM2302 sensor and Energenie transmitter wired to the same Raspberry Pi GPIO.
The AM2302 sensor and Energenie transmitter wired to the same Raspberry Pi GPIO.

Despite hogging the entire GPIO, the Pi-mote transmitter only needs nine pins to function. Manufacturer Energenie has kindly provided details in a blog post, which I have prepared into an easily-readable diagram below.

The Raspberry Pi GPIO viewed from above. Squares mark Energenie Pi-mote pins.
The Raspberry Pi GPIO viewed from above. Squares mark Energenie Pi-mote pins.

The Pi-mote transmittor would normally sit on top of the dark blue section of the GPIO, so you need only wire the pins marked with squares to their corresponding sockets on the Pi-mote. As you’ll see, the transmitter requires physical pins 1, 2, and 6 (power and grounding), and 11, 13, 15, 16, 18, and 22 (data).

As for the AM2302 sensor, this requires three pins: power, ground, and a data pin. The official specification lists 3 to 5V power with a built-in 5.1K resister, and the documentation recommends using the higher voltage for wire lengths of over 1 meter. If you’re mounting your Terrarium Controller on the back of your tank it’s unlikely you’ll need more than a meter of cabling. As such, I suggest you wire your sensor as follows: yellow to physical pin 7 (data), black to 9 (ground), and red to 17 (3v3 power). These are marked in the diagram below with circles.

The Raspberry Pi GPIO viewed from above. Squares mark Energenie Pi-mote pins, and circles mark AM2302 sensor pins.
The Raspberry Pi GPIO viewed from above. Squares mark Energenie Pi-mote pins, and circles mark AM2302 sensor pins.

I suggest that you wire these connections on a breadboard so you can prototype your circuits before final assembly. Before you fire up the soldering iron, though, you’ll need to prepare the software for your Terrarium Controller.

Software

Make sure your Pi is up-to-date and that you have the required dependencies by running the following commands:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential python3-dev
sudo apt-get install python3-gpiozero

The excellent GPIO Zero library - which now comes preinstalled with Raspbian - recently added built-in support for Energenie sockets. As a result, we need only install two additional pieces of software to power the Terrarium Controller:

The first can be downloaded directly from GitHub. Navigate to a suitable directory (cd /home/pi), then download the files:

git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT

Install the library, so that our Terrarium Controller’s Python script will be able to access the sensor. Note that we’re using Python 3, support for which was recently added to the library by Adafruit:

sudo python3 setup.py install

The library includes several examples which we can use to test our sensor. With the sensor connected to the GPIO as described in the previous section, head to the library’s examples folder (cd Adafruit_Python_DHT/examples) and execute the following command:

sudo python3 AdafruitDHT.py 2302 4

The first argument is the model of the sensor. The second is the GPIO pin number to which you’ve hooked up the yellow data wire; note that we’re referring to it by its BCM number (4), not its corresponding physical number (7). If you’ve done everything correctly, the script should print the sensor readings to your terminal:

Temp=26.1*C Humidity=52.1%

Success!

It’s worth noting that this command can sometimes return an error even if you have wired everything correctly. As explained by Adafruit, this is a limitation of using DHT sensors on Linux: “there’s no guarantee the program will be given enough priority and time by the Linux kernel to reliably read the sensor.” If you see an error, just try again. Thankfully the Adafruit library’s read_retry method automatically makes repeat attempts, so this issue doesn’t pose too much of a problem for us.

Next, it’s time to configure the Energenie mains sockets.

The GPIO Zero library makes the sockets easy to control by providing a convenient class: Energenie(1, initial_value=True), where the number represents the socket group to be activated or deactivated using the boolean. Instances of this class can be used to switch our devices on or off. You can read about the class in the GPIO Zero documentation. If this is your first time working with remote sockets, it’s probably worth taking a look at the Energenie manual, too.

Setting up an Energenie socket involves putting it into learning mode and assigning it to a group. When a socket is in learning mode, the light on the front of the socket will flash slowly. If the first of your new sockets does not automatically enter learning mode when it is plugged in, press and hold the green button on the front of the socket for 5 seconds, releasing it when the light starts to flash slowly. The socket will then react to the first signal it receives.

To assign it to group 2, for example, simply run the following Python 3 script. Your Pi-mote transmitter should be wired to your GPIO pins using a short ribbon cable, as described in the previous section.

from gpiozero import Energenie
newsocket = Energenie(2, initial_value=True)

Program the sockets one at a time (i.e. with only one socket in learning mode at a time), otherwise they will react to the same signal. If you’re starting with two independently-controlled sockets - lights and fans, for example - simply assign one to group 1 and then the other to group 2. Run several tests to make sure everything works as expected.

Finally, you’ll want to install the Requests HTTP library, so that your data can be pushed to the cloud. This can be done using pip, the Python Package Index. Run the following commands to install pip and the Requests library.

sudo apt-get install python3-pip
sudo pip-3.2 install requests

Once this has been done and your sockets and sensor are all functioning correctly, it’s time to write a program for your Terrarium Controller.

Scheduling & Data Viz

We’re going to write three separate scripts which the Terrarium Controller will execute on a schedule.

The first two scripts will control our lighting. These will be called lights-on.py and lights-off.py, and each will be set to run once a day at an appropriate time. Thanks to Energenie support in GPIO Zero, these scripts can be as simple as one line of code. As I said earlier, using scripts to control components which follow a set routine (such as lights) is completely optional; in fact, in most situations I’d suggest using regular mechanical timers to control these components.

The last script - which we’ll call monitor.py - will run once every two minutes. It needs to do the following things:

One caveat, before we continue: in this section I’ve used my own terrarium as an example. I live in southern England where it’s pretty cold most of the year, and grow half a dozen species of intermediate and lowland Nepenthes - these require warm days, cool nights, and constant high humidity. As such, the only component which is dependant on my sensor reading - at least for the purposes of this starter script - is a set of cooling fans for my lighting fixture. While the principles of my script are broadly relevant to setups of all kinds, you’ll obviously need to make changes depending on your local climate and the kinds of plants you’re growing.

The code is below, and all the scripts are available in the GitHub repository for this project.

#!/usr/bin/python3

# monitor.py - For Terrarium Controllers using Adafruit
# DHT sensors, Energenie Pimote sockets, and ThingSpeak.
# MIT license.
# https://tomscarnivores.com/resources/raspberry-pi-terrarium-controller/

# Imports
from gpiozero import Energenie
import Adafruit_DHT
import requests

# Attempt to get a sensor reading. The read_retry method will 
# retry up to 15 times, waiting 2 seconds between attempts
sensormodel = Adafruit_DHT.AM2302
sensorpin = 4
humidity, temperature = Adafruit_DHT.read_retry(sensormodel, sensorpin)

# If either reading has failed after repeated retries,
# abort and log message to ThingSpeak
thingspeak_key = 'XXXXXXXXXXXXXXXX'
if humidity is None or temperature is None:
	f = requests.post('https://api.thingspeak.com/update.json', data = {'api_key':thingspeak_key, 'status':'failed to get reading'})

# Otherwise, check if temperature is above threshold,
# and if so, activate Energenie socket for cooling fan
else:
	fansocket = 1
	tempthreshold = 28

	if temperature > tempthreshold:
		# Activate cooling fans
		f = Energenie(fansocket, initial_value=True)

	else:
		# Deactivate cooling fans
		f = Energenie(fansocket, initial_value=False)

	# Send the data to Thingspeak
	r = requests.post('https://api.thingspeak.com/update.json', data = {'api_key':thingspeak_key, 'field1':temperature, 'field2':humidity})

We’re recording both temperature & humidity, and activating cooling fans when the temperature is above 28°C. By adding or changing thresholds and socket numbers, it should be fairly easy to modify this script to control heating pads, humidifiers, circulation fans, and any other components in your terrarium.

You’ll also notice we’re pushing our data to a service called ThingSpeak. ThingSpeak is an open data platform for the Internet of Things, enabling real-time data collection, visualisations, alerts and so on. It’s completely free, and the API limits are very generous. Sign-up at the ThingSpeak website and create a channel with two fields for your data; field 1 should be labelled temperature, and field 2 humidity. Next, grab your Write API Key and paste it into the variable in your monitor.py script.

Recording terrarium conditions and monitoring fluctuations using
Recording terrarium conditions and monitoring fluctuations using ThingSpeak

Run the script several times as sudo to make sure that your mains sockets switch on and off as expected based on your ambient conditions. Check that your data is being logged to your ThingSpeak channel. Try altering your thresholds to ensure that everything behaves exactly as expected.

Once you’re happy, you can set the three scripts to run at the required times using cron. This is very simple, and you don’t need to install anything new. If you’ve never used cron before, check out this handy guide from The Pi Hut.

Open your Pi’s crontab by running sudo crontab -e. For reference, a template crontab is provided below. This would provide a 14 hour photoperiod - lights switch on at 7:01 and off at 21:01 - and the monitor runs once every 2 minutes. The 1 minute offset is simply to avoid the monitor routine and lighting routine from ever running at the same moment. Keeps things simple.

*/2 * * * * python3 '/home/pi/terrarium/monitor.py'
1 7 * * * python3 '/home/pi/terrarium/lights-on.py'
1 21 * * * python3 '/home/pi/terrarium/lights-off.py'

Wiring & Installation

It’s time to install your Terrarium Controller.

You could do a quick and dirty job with insulation tape, but the resulting mess would just distract from the plants or animals in your terrarium. What’s more, the high humidity would probably cause any tape to become unstuck quite quickly. I suggest you fire up the soldering iron and buy some heat shrink tubing, since it doesn’t take much effort to create something that’s tidy and unobtrusive.

First, decide where your Terrarium Controller is going to live. Assuming the sensor wire will be entering through the top of your terrarium, it should be possible to mount the Controller on the back of your tank and route the cable through a port or other narrow gap. As for the sensor itself, the AM2302 has a small hole which is perfect for holding a small suction cup, allowing you to mount it in an appropriate position.

Mounted Terrarium Controller and sensor
Mounted Terrarium Controller and sensor

Measure the lengths of wire you’ll require, make the necessary connections using a soldering iron, and cut some heat shrink tubing to group the sensor wires together. I found 5mm tubing to be ideal - shrinking it would require a heat gun, but it’s generally not necessary.

As for the Energenie transmitter, this can be sealed away inside the Raspberry Pi case. Many Pi cases (including ModMyPi’s and Pimoroni’s) offer spacer plates which can be used to extend the available headroom. In the photo above, the transmitter and its ribbon cable live inside a case extended with two spacers, while the wires for the sensor - and several other components not covered in this guide - exit through the case’s GPIO slot.

Mount your Terrarium Controller on the back of the tank using adhesive-backing Velcro, route your sensor into the growing area, connect the Pi’s AC adaptor, and you should be good to go!

Future Extensibility

One of the best things about this project is its potential for extensibility. The initial build offers a great level of automation, but remember you’ve got the ability to control four sets of mains outlets, and half a dozen GPIO pins still available for use. There are also countless things which could be done with the live temperature and humidity data being pushed to the cloud.

Terrarium with a mounted LED night light
Terrarium with a mounted LED night light

You could build a small alphanumeric screen to display a read-out of the current conditions; install a soil sensor to monitor your plants’ moisture levels; design a web interface or app to control your mains sockets remotely; hook up a camera module so you can check on your pets when you’re not around; or - as I’ve done in the picture above - wire a spare GPIO pin to an ultra-bright LED mounted in the terrarium lid and program a night-time moonlight effect. Just remember to calculate the power requirements of any components you install.

Any questions or comments, just send me an email at tom@tomscarnivores.com, or if you have suggestions, please send pull requests to the GitHub repository for this project. Finally, if you’d like to share a photo of your finished terrarium and controller, feel free to email them to me and I’ll put the best ones at the end of this guide.

Thanks for reading!

Guide last updated: March 11, 2017