Monthly Archives: May 2020

Greenhouse Monitoring

I have done a number of monitoring projects over the previous years and thought it was time to revisit greenhouse monitoring.


I choose to start by monitoring my little Ikea greenhouse located on my windowsill. To start I put together a basic monitoring board using an Arduino Nano clone and a DHT22 sensor.

arduino sensor

This is a breadboard with some older components I had from previous projects (hence the look).

Parts List

  • DHT 22 Humidity and temperature sensor
  • TSL2561 light sensor
  • Arduino Nano clone
  • Breadboard
  • 4.7k “pull up” resistor

The Arduino is connected to a Raspberry Pi using a serial USB cable. JSON is sent over the connection and read via cron every minute using a Python script.

Arduino Code

#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>

float humidity;
float temperature;
float light;

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

void setup() {

  if (!tsl.begin())
    /* There was a problem detecting the TSL2561 ... check your connections */
    Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
    while (1);

  /* Display some basic information on this sensor */

  /* Setup the sensor gain and integration time */


void loop() {

  humidity = dht.readHumidity();
  temperature = dht.readTemperature();

  sensors_event_t event;
  if (event.light)
    light = event.light;
    /* If event.light = 0 lux the sensor is probably saturated
       and no reliable data could be generated! */
    light = -1;
  //light = 0;


  delay(1000); //just here to slow down the output for easier reading


void displaySensorDetails(void)
  sensor_t sensor;
  Serial.print  ("Sensor:       "); Serial.println(;
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" lux");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" lux");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" lux");

void configureSensor(void)
  /* You can also manually set the gain or enable auto-gain support */
  tsl.setGain(TSL2561_GAIN_1X);      /* No gain ... use in bright light to avoid sensor saturation */
  // tsl.setGain(TSL2561_GAIN_16X);     /* 16x gain ... use in low light to boost sensitivity */
  //tsl.enableAutoRange(true);          /* Auto-gain ... switches automatically between 1x and 16x */

  /* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
  // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);  /* medium resolution and speed   */
  // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);  /* 16-bit data but slowest conversions */

  /* Update these values depending on what you've set above! */
  Serial.print  ("Gain:         "); Serial.println("Auto");
  Serial.print  ("Timing:       "); Serial.println("13 ms");

Python Code

Code below is a rough bit of Python using the Click and Influx libraries to save the output to an InfluxDB database on my remote server.

import logging
import serial
import json
import click
from influxdb import InfluxDBClient
from datetime import datetime
from time import sleep

    format="%(asctime)s.%(msecs)03d %(levelname)s: %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",

logger = logging.getLogger(__name__)

def update_influx(measurements, location):
    client = InfluxDBClient("", 8086, "root", "root", "greenhouse_outside")
    json_body = []

    for name, value in measurements.items():
                "measurement": name,
                "tags": {
                    "location": location
                "fields": {"value": round(value, 2)},
        )"Sending \n {json.dumps(json_body, indent=2)}")

def take_reading(port):"Using the port {port}")
    ser = serial.Serial(port)
    for i in range(0, 20):
        line = ser.readline().decode("utf-8")
        line = line.replace('nan', '0')"Raw fetch: {line}")
    errors = 0
    measurements = {}

    while True:
            if errors == 5:
            measurements = json.loads(line)
            if measurements['humidity'] == 0:
                measurements['humidity'] = 0.0
        except json.decoder.JSONDecodeError:

            line = ser.readline().decode("utf-8")
            line = line.replace('nan', '0')
  "Raw fetch: {line}")
            errors += 1

    update_influx(measurements, 'greenhouse_internal')"Processed Internal: {measurements}")"Complete")
    return measurements

if __name__ == "__main__":

Grafana and InfluxDB

To store the data I’m using an InfluxDB server running on an old Ubuntu powered laptop. has the official guide to installing and setup.

To display the data I use Grafana again installed on the same server as InfluxDB.

Max Image File Size Upload on WordPress

I hit an issue uploading my photos to this WordPress instance. None of my photos would upload due to having a file size maximum of 2MB.

I googled around and found a plugin called Increase Maximum Upload File Size available here It showed I was limited to “Maximum upload file size, set by your hosting provider 2MB”. As I’m my own hosting provider, this must mean something OS level.

Assuming it was PHP that might be the limiting factor I looked for the settings that affect the two ways files are uploaded. These are:

  • post_max_size
  • upload_max_filesize

Running PHP 7.1, the config file is at /etc/php/7.1/fpm/php.ini. There was an existing entry for upload_max_filesize which set it to 2MB.

Changing this to 128MB and restarting php7.1-fpm.service allowed large file uploads. This was comfirmed in the plugin:

F1 2019 and Python

I attended an excellent talk about how TIBCO and Mercedes work together for data science and building models.

The main takeaway for me was I could get realtime stats out of the F1 2019 Codemasters game!

Using this excellent library I was able to stream realtime data to my laptop.

I have had a few goes of graphing the data as the data is flowing in but so far all have been way too slow.

Currently I have the data flowing in a Docker image of InfluxDB and using Grafana for displaying.