Stargazy – Revisiting the smart fish tank

July 5, 2018

This article records our second attempt at building a smart aquarium monitoring system. The previous (Palantir) gave valuable experience in the selection of sensors and associated hardware, but wasn’t reliable or stable enough for permanent use. We’re hoping to build on what we learnt then and this time construct something more lasting. Key requirements are still: fish/human safety, reliability, and low cost.

Stargazy overview dashboard

Stargazy overview dashboard. A snapshot example is here.


So what were the key problems with Palantir?

  1. Unstable network stack: the previous approach (using an Arduino, with an ethernet shield, and a WiFi bridge) had multiple points of failure. The bridges in particular tended to overheat and crash, as did the shields occasionally. A further annoyance was that WiFi shields for the Arduino remained expensive so it was never cost effective to upgrade to them.
  2. Sensor effectiveness: The attempt to track filter flow rates via the Venturi effect and atmospheric pressure sensors wasn’t successful. The inclusion of the non-return valve (needed to protect the sensor) meant that the sensors never returned to ambient even if the filter was off.
  3. Software development effort: Our server side development (originally PHP/MySQL) stalled, simply due to the amount of time and effort required to implement it. Configuration remained network-specific and was difficult to make portable.

So what has changed in the last few (heh!) years?

  1. The Raspberry Pi project has provided a cheap, well supported, Linux platform for ‘Internet of Things’ developments. Early versions were a little limited/slow but recent ones are very capable. We’ve selected the Raspberry Pi Zero HW due to its price (£12!), tiny size and built-in WiFi support. Key specifications are: 1GHz CPU, 512MB RAM, micro USB power, HDMI and USB support, and running the Raspbian distribution of Linux. There are excellent libraries and examples describing how to access hardware sensors from the Pi via Python and reporting the results via a micro-webserver (Flask).
  2. Small Hall-effect based liquid flow sensors are now cheaply (~£3-10) and easily available on eBay/Amazon. Safely integrating them into the aquarium filter outlets is a key challenge.
  3. Production-quality software for storing and displaying time-series data has become freely available. It’s primarily intended for tracking the status of servers/VMs, but can also just as easily collect data from sensors via a web server running on a Raspberry Pi.
    • Prometheus is a open-source time series database and monitoring system, designed for the scraping of metrics from HTTP endpoints. The results can then be queried for display or processing of alerts.
    • Visualisation (graphing etc.) is supported by a dashboard system called Grafana, as is alerting for error states.

    We’ll run Prometheus & Grafana off the household server (Windows 7) but they could also be installed on a Linux box, or another Pi (addition of a hard drive / SSD for the data would be sensible).

So our new architecture is:

[sensors: temperature, light, air, flow etc.] - RP zero -(WiFi)- Prometheus - Grafana

Any browser on the local network can then access the Grafana dashboard and the server can send out email alerts as needed. External web access is via VPN (supported by our home router). The alternative architecture would be to run a local networked push gateway (see with a NAT bridge to Prometheus/Grafana servers installed in the cloud.

Hardware: Sensors

Not much has changed here as there are still three aquariums to monitor: the parrot tank, the catfish, and a small quarantine tank.

For each we’ll monitor temperatures, light level, the air pump and activity of the filters – either directly via a flow sensor or indirectly with a Hall-effect sensor on the magnetic pump.

The sensor requirements haven’t changed much either (see the previous article for details) but by delegating the alerting to Grafana we can simplify the Pi’s job to that of data collection and reporting. There’s no longer any need for local alarms or the ability to remotely update parameters.

Stargazy schematic

Since the Pi hardware is cheap, we’ll run a separate Pi monitor per aquarium with all three reporting to the same Prometheus/Grafana server. Configuration changes and other software updates for each Pi is done via SSH once initial setup is complete.


The Raspberry Pi Zero WH has a 40-pin interface that supplies a variety of power interfaces (ground, 3.3, and 5.0 volts) and digital GPIO ( Raspbian uses these to support several key communication protocols that we need: 1-Wire – primarily used for the DS18B20+ temperature sensors, and I2C – used to communicate to peripheral ICs or micro-controllers.

Unlike the Arduino the Pi doesn’t have any analogue pins. While we could use entirely digital sensors, these are often expensive and we already have a bunch of analogue sensors recovered from Palantir, so instead we’ll add a cheap analogue-digital converter (ADC) and report back to the Pi via I2C. This approach also allows us to use 5 volt inputs (the Pi is limited to 3.3) and gives some protection against shorts (the Pi pins are electrically delicate).

We use female-connector-ended coloured wire to connect the various add-ons to the Pi’s GPIO (see ‘DuPont Hook up’ rainbow ribbon cables) as this allows them to be removed or replaced. A cheaper permanent solution would be to use the Pi Zero W model (without the pin array) and solder wires into place.

Raspberry Pi Zero WH pinout

Raspberry Pi Zero WH pin out

Adafruit has some nice libraries supporting their ADS1015/1115 4-channel ADC boards ( These boards are a excellent option, but we selected a more compact (and cheaper) clone board available from eBay. Up to four of these could be attached to each Pi (giving 16 channels) but one ADC is sufficient for each aquarium. Since the sensors are scattered around the aquarium (and often taped into place) it’s convenient to have some way to unplug their cables from the Pi. We found audio jack plugs/sockets useful for this with Palantir so have stuck with them here.

A wide variety of cases are available for the Pi Zero, but most don’t have sufficient space to also contain the ADC and jack sockets. A good option is the tall version of the plastic UniPiCase ( and This is easy to drill and everything fits (just! :) )




Everything fits into a UniPiCase

Connections from the sensors to the Pi are via 3.5mm stereo jack plugs/sockets, in each case configured such that the tip of the plug is positive (V; red wired), the middle is signal (S; normally yellow/orange wired), and the base/surround is ground (g; black wired). One plug (right/bottom) is used for the temperature sensors, and four (A0-3; left to right) for the ADC channels. The former is digital and runs at 3.3 volt (3V3), the latter, analogue at up to 5.0 volts (5V), so they are not cross-compatible.

A small press-to-make button on the top of the case allows for the Pi to be reset (with a brief press) or shutdown (press & hold for 3s). The nearby 3 mm LED will light during this process and also blinks whenever the web server receives a request.


Prototype, showing Pi, ADC connected to the analogue jack sockets (bottom), the 1-Wire temperature daughter board and socket (right), the reset button, and LED (left). Two analogue sensors are also visible, light sensor (far left, with a black surround for easier handling), and Hall effect with a magnet(far right)
prototype details

Annotated details of the Pi and ADC
case faceplate details

Annotated details of the case face plate (back view), showing the ADC, sockets, and 1-Wire daughter board. Both boards and other bare contacts were insulated with electrical tape before continuing
ADC details:

  • Micro ADS1015 board; uses Adafruit_ADS1x15 library
  • Connection to Pi:
    • V (red) → 5V Pi pin 4
    • G (black) → Pi pin 6
    • SLC (green) → I2C1 SLC → Pi pin 5
    • SDA (blue) → I2C1 SDA → Pi pin 3
  • Connections to sensors A0-3 → jack sockets (middle).
    Sockets also spliced on V (tip) and G (base)
case top details

Annotated details of the case top, showing the reset button and LED

Power reset button:

  • Momentary connect button to safe shutdown (1 s restart, 3s+shutdown)
  • Across GPIO21 (Pi pin 40) and GND (Pi pin 39)


  • Blinks on scrapes and lights for reset/shutdown
  • LED + 330 Ω resistor across orange: GPIO16 (Pi pin 36)
    and white: GND (Pi pin 34)

Scripts to run the button and LED are based off examples at: and

Pi and face plate in place in the case, and the top’s wires connected


Previous experiences with failed aquarium equipment have included: heaters stuck ‘on’ (very serious!), air pump diaphragms spliting (no pressure), and total electrical failure of filter magnetic pumps. Jamming pump rotors can also be a problem, but are normally obvious as they are very noisy. We have selected sensors to try to detect the ‘invisible’ problems: in particular over-temperature or sudden electrical failure.

sensors overview of usefulness and costs

Overview of sensor usefulness and costs

All these sensors connect to the case via 3.5mm jack plugs and 4-core alarm/telephone cable (or equivalent). Where possible, we reused the previous Palantir units. In all cases joints need to be soldered and then covered with shrink tubing and/or electrical tape. Any metal contacts that might get wet need to be well sealed otherwise galvanic corrosion is likely to destroy them.

While the sensors are theoretically hot-swappable, in practice the voltage change upon plugging them in/out tends to reboot the Pi or start it up from shutdown. This risks damaging the file system, so it’s safer to shut down the Pi (hold the button for 3s; then wait for ~15s or until the green light by the power USB is no longer lit), then unplug the power before adding or removing sensors.


DS18B20+ sensors proved to be an easy and reliable way to track temperatures for Palantir and the previously expensive waterproofed modules are now £1.50 on eBay (and seem to be cased in stainless steel, instead of what appeared to be chromed copper – which corroded over time).

The sensors use a 1-Wire bus and multiple can be run in parallel (using a star architecture) with each sensor reporting back from an unique ID (e.g. 0517c45018ff). Only a single jack connection to the Pi is needed: socket tip (red): 3V3 (Pi pin 1), middle (yellow): GPIO4 (Pi pin 7), base (black): GND (Pi pin 9).

temperature sensors

AA bunch of waterproof temperature sensors. These can be cut to the required length, then joined in a star configuration to a length of cable that in turn connects to the jack plug at the Pi. At the join, all the same wires should be soldered together (e.g. all red to red, etc.) The joint can then be shrink-sleeved and sealed with electrical tape

jack plug/socket detail

Detail of the jack plug/socket and attached 1-Wire daughter board. The board carries a pull-up resistor (so the signal line is normally +ve) and another small temperature sensor which will report the temperature inside the case

Since 1-Wire needs the signal line to be a positive voltage instead of floating, a 4.6 kΩ resistor is needed between it and the 3V3 line. The easiest approach is to include a small, 3×5 Veroboard (copper strip prototyping board) between the jack socket and the Pi connection. This bears the pull-up resistor and another standalone DS18B20+ sensor (~ £0.70 on eBay), to monitor the internal case temperature. This also provides a useful sanity check, since the Pi will always have at least one sensor to report from even if nothing else is plugged in. This daughter board should also be well insulated with tape.

Python code to access these sensors is based on:

Some batches of sensors will have slightly different readings to others. If you wish to correct for this, once the sensors are set up and reporting, place them all in a cup of water. Once their readings are stable, adjust using the offset list in config.ini.


This uses a simple voltage divider between a light-dependent resistor / photoresistor (5V to S) and a 40 kΩ resistor (S to G). The S signal line is then fed to the ADC and the resulting voltage (~ 0 volts in the dark and ~ 4 volts in medium light) reported to the Pi.

We found it helpful to mount the LDR and its resistor on a small piece of veroboard, then insulate and tape to a small sheet of opaque plastic. This helps block light from outside the aquarium.

Air pump

Here we use the more sensitive of the solid state pressure differential sensors trialled for Palantir: the MPX5010DP ( This has two air ports, one of which is capped off with a small piece of air-tube blocked with tape, and the other connects to the aquarium air pump via a T-piece or manifold.

The electrical connection (867C-05 unibody) defines the pin ordering as: sensor pin 1 (notched) → signal; sensor pin 2 → G; sensor pin 3 → 5V; rest not connected. Soldering to the pins is difficult, but a 3-pin PC fan plug is a suitable socket (although note the wire colours will then be incorrect!).

The sensor output is a voltage relative to the difference between the two ports, which is then read by the ADC.

light sensor

Light sensor

air pressure sensor

Air pressure sensor

Water flow

Previous attempts to use the Venturi effect weren’t reliable, so we decided to use a more direct method. Recently two models of cheap liquid flow sensors which use the Hall effect have appeared on eBay at ~£3-10. These are the YF-S201 ( and YF-S201C ( The YF-S201C is smaller, lighter, and transparent but not waterproofed (the YF-S201 version is).

These sensors work by including a small, magnet-bearing rotor in the water flow. As this turns, the magnet passes a Hall sensor and gives a series of high/low voltage pulses. A pulse counter (in this case running in Python on the Pi, after the ADC) can convert the pulse per unit time to an approximate flow rate using equations, YF-S201: F (Hz) = 7.5 * W (L/min), and YF-S201C: F (Hz) = 5.0 * W (L/min).

Liquid flow sensors YF-S201C sealed and attached to the output spout
for a Juwel aquarium internal filter

Both sensors are intended to be plumbed into piping, and this would be a option for an external aquarium filter where it could be spliced into the water return line (see 13mm barb to 1/2 inch BSP thread fittings – – these require a additional rubber washer to tightly seal). We had some concerns with this: first the need for additional joints and hence risks of leaks outside the aquarium containment, second a blocked/jammed rotor would be difficult to clear without significant dismantling.

The physical size of the YF-S201 and its required fittings mean it’s difficult to fit within the aquarium hood (which would minimise the leak risk). Given these limitations, we decided to use only the smaller YF-S201C and fit them directly to the output spouts of the internal filters on the two Juwel aquaria. This keeps them inside the aquarium hood, avoiding floods, and they remain easily removable for cleaning. Connection to the filter spout is via a barb fitting and a short length of hose, and a second wider piece reduces the splash noise at the output.

Since the YF-S201C is not waterproofed, we potted and sealed it with aquatics silicone (remove screws and lid to the circuit board box; over-fill the box with silicone; replace and screw back the lid; seal the outside of the lid, where the wires connect and the screws with more silicone; leave overnight to harden and rinse well with water). However care should still be taken not to immerse the box area or the associated wiring, as any water ingress will rapidly destroy the sensor’s circuit board.

Hall effect

This uses a linear analogue sensor (A1301EUA-T; ~£3; to detect the changing magnetic field from the drive coils of a magnetic pump. This can’t tell you if the pump is actually moving water, but will give a warning if it shuts down entirely (either from a fault or if it’s been turned off).

The sensor is a small 3-legged chip that needs to be mounted onto a small piece of veroboard and then bent over so that its face may be placed as closely as possible to the casing of the pump. The pin ordering is: sensor pin 1 (left when viewer from front/upright)→ 5V, sensor pin 2 → G, sensor pin 3 → signal to the ADC. Warning: this chip has very little reverse voltage protection, it can burn out!

The sensor returns a signal voltage that’s above or below ~1.5V depending on the detected magnetic field, but it is very noisy. Since the pump drive electrics produce an alternating field, the detection script running on the Pi collects several hundred readings and reports the delta between the detected high and low voltages. A delta of 30-50 mV is seen from pumps we’ve tested, but this is very sensitive to the physical location of the sensor. We’ve found the highest readings are with it taped tightly to the pump casing, slightly off-axis to the pump’s rotor. Example locations are Tetratec EX600/800 – on the top, down/right off the central axis; EHEIM aquacompact: on the glass immediately behind the pumphead.

Once the Pi is set up and reporting from a Hall sensor, there’s a helper page here: http://x.x.x.18:5000/hall?id=2 that shows an auto-refreshing page with the detected delta. Once a good place is found, stick the sensor down with tape. Note: accessing this helper page will corrupt any normal data collection running concurrently on the Pi, and is only intended to be used briefly to find the best position for the sensor.


The Pis run a version of Debian Linux called Raspbian. This has a GUI, which is useful for the initial configuration and connection to the WiFi network but isn’t needed once SSH is available.

A Python-based webserver (Flask) running each the Pi is configured with a number of pages (e.g. ‘http://ip_address:5000/temperature’), which when polled will request and return data from the sensors. This polling is carried out at regular intervals by the Prometheus data store, which in turn supplies the combined results to the Grafana dashboard webapp. Both Prometheus and Grafana run on a separate Windows PC in this case.

software schematic

Schematic of the software stack

Setting up the Pi OS

The Pi will need to be set up initially with a screen, a keyboard/mouse, and access to WiFi. For succinctness some of the commands below have been concatenated to a single line like; this: these commands should be run individually.

  1. Download and copy Raspbian ( to an SD card using e.g. Etcher (Windows)
  2. Insert the card and boot the Pi to desktop
  3. Open a terminal; change Pi user’s password from ‘raspberry’ to something else: passwd
  4. Use the Pi configuration tool under menu option: “Boot” → configuration → hostname; interfaces → SSH, I2C, 1-Wire on; localisation → timezone GB, WiFi_country GB; reboot
  5. Setup and connect to WiFi
  6. Update: sudo apt-get update; sudo apt-get upgrade
  7. Note IP address: ifconfig

Note: The most recent version of Raspbian (June 2018) includes a setup wizard (piwiz) that steps through the process of localisation, password change, WiFi setup and updates on first start up. After rebooting it’ll still be necessary to turn on SSH, 1-Wire, and I2C also to change the Pi’s hostname (if desired). Reboot again after this.

Note 2: If connecting a screen is difficult, it’s possible to configure the Pi ‘headless’ – although troubleshooting is then a lot more difficult! After installing Raspbian to the SD card, some changes need to be made in the first partition. This is FAT32 and readable from most operating systems: (i) under /config.txt uncomment dtparam=i2c_arm=on and add to the bottom dtoverlay=w1-gpio; (ii) in the root folder add a new empty text file named ssh (no extension); (iii) next create a text file wpa_supplicant.conf with contents (using Unix line endings!):

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

     ssid="Your network name/SSID"
     psk="Your WPA/WPA2 security key"

You’ll need to get the Pi’s IP address once it connects. This can be found in your router’s log file or you can use a network scanner app e.g. Fing. Now boot up the Pi, ssh in and change password passwd and hostname (sudo nano /etc/hostname and sudo nano /etc/hosts), reboot and run updates.

Client software on the Pi

We’ll be using Python 3 to run our scripts and Flask as a micro webserver. Both of these should already be installed, but if not (or to check): sudo apt-get -y install python3-pip; sudo pip3 install flask.

We’ll also use another Linux PC to remotely access and configure the Pi. This could also be done from Windows (via Putty) or directly using the Pi’s desktop, although that’s a bit slow. We’ll describe our example Pi’s IP address as x.x.x.9

The public repository for the Stargazy scripts is here:

  1. Install Adafruit library: sudo pip3 install adafruit-ads1x15
  2. Optional: Copy ssh public key for easier login. On another Linux computer: ssh-copy-id -i ~/.ssh/ pi@x.x.x.9 Can then ssh without password: ssh pi@x.x.x.9
  3. Optional: If you expect to upload your changes to the scripts/config from the Pi to your own git repository (we use Bitbucket as the example):
    1. On the Pi, create a new SSH public/private keypair: ssh-keygen (do not add a passphrase: just press Enter). This will create the keys in /home/pi/.ssh
    2. Add the Pi’s public key to the Bitbucket account with write permission for this repository: cat ~/.ssh/ and copy this text which is the public key
    3. In Bitbucket, log into your account and go to the account Settings: find the “SSH Keys” section “Add Key”: paste in your public key here, and label it appropriately for your future reference (e.g. rpzero0)
    4. On the Pi, one-time setup of global git user (so commits can be attributed): git config --global ""; git config --global "Pi 0" (The email/name doesn’t have to match anything in bitbucket, it’s just for reference)
  4. Clone the ‘webserver’ and ‘cron’ directories from git repository: cd ~ (or cd /home/pi); git clone (substitute your own if you will be saving your changes to it later). You should now have /home/pi/stargazy containing ‘cron’ and ‘webserver’ directories
  5. Configure the webserver to match your specific sensor setup: cd ~/stargazy/webserver/; cp config.ini.example config.ini copies the provided example ini file to one you can edit for this Pi.
  6. Edit config.ini with any temperature sensor offsets and the order of ADC sensor inputs
  7. Test webserver works: cd ~/stargazy/webserver; ./; go to http://x.x.x.9:8080/test
  8. Set up the crontab: cd ~/stargazy/cron; crontab crontab.bak imports the crontab.bak to the user crontab. crontab -l ‘list’ the crontab: this displays it so you can check it imported ok
  9. Now reboot: sudo reboot and once the web server is running (~30s or so) you should get pages here: http://x.x.x.9:5000/config http://x.x.x.9:5000/temperature http://x.x.x.9:5000/adc
  10. In future, to get the latest versions: cd ~/stargazy (or cd /home/pi/stargazy); git pull

An example Stargazy config.ini:

# Some temperature sensors have a constant offset that can be corrected for
# Reference each sensor by its name in /sys/bus/w1/devices without the 28- prefix
0117c29082ff = 0.06
0517c46f57ff = 0.06

#ADC sensors needs to be configured here in order of ADC channels 0→3
#light - for a LDR against a 48kΩ resistor
#air - MPX5010DP pressure sensor in positive mode; to monitor an air pump
#hall - A1301 hall effect sensor; to monitor a magnetic impeller
#flow - YF-S201C flow sensor
#default - returns mean and stdev

The /temperature and /adc pages are the endpoints that are scraped by Prometheus. You can test them by e.g. warming one of the temperature sensors and refreshing the page. The other sensors can be tested with an air pump and a small water pump set up in a bucket. Examples of pages returned by the Pi are:

temperature{sensorid="0417b2b963ff",unit="C"} 29.44
temperature{sensorid="0517a0f0b3ff",unit="C"} 29.44
temperature{sensorid="0517c44c54ff",unit="C"} 28.31
temperature{sensorid="000002ec0ab8",unit="C"} 34.25

adc{type="light",adcid="0",unit="V"} 3.683
adc{type="light_stdev",adcid="0",unit="%"} 9.0
adc{type="light_time",adcid="0",unit="s"} 0.111
adc{type="air",adcid="1",unit="hPa"} 41.0
adc{type="air_stdev",adcid="1",unit="%"} 0.0
adc{type="air_time",adcid="1",unit="s"} 0.098
adc{type="hall",adcid="2",unit="mV"} 34.0
adc{type="hall_time",adcid="2",unit="s"} 0.854
adc{type="flow",adcid="3",unit="L/min"} 3.35
adc{type="flow_count",adcid="3"} 15
adc{type="flow_time",adcid="3",unit="s"} 0.894

Server software – Prometheus and Grafana

Full details are beyond the scope of this report (particularly for Grafana) – see the documentation for information on how to set up dashboards etc. Here we’ll cover the steps to install and bind as a service under Windows 7. Our example install directories are F:\stargazy\prometheus and F:\stargazy\grafana. Obviously the server needs to be able to see the Pis, it’s worth checking you can get to e.g. http://x.x.x.9:5000/temperature from it.

  1. Download and uncompress Prometheus ( to F:\stargazy\prometheus
  2. Download and uncompress Grafana ( to F:\stargazy\grafana
  3. Download and uncompress NSSM (; move appropriate exe to F:\stargazy
  4. Add NSSM to PATH: (see under system/advanced/environment variables/path):;F:\stargazy\nssm
  5. Install services. Open new cmd: nssm install prometheus
  6. In the resulting GUI, point at F:\stargazy\prometheus\prometheus.exe and set arg --config.file=prometheus.yml then install
  7. Repeat this with F:\stargazy\grafana\bin\grafana-server.exe (no arg)
  8. Check and manually start the services (see under services GUI tool). These should now survive reboots
  9. Add prometheus & grafana to the Windows firewall whitelist
  10. Setup Prometheus’ configuration.yml: you’ll have to restart the service to see changes
  11. Setup Grafana through its interface. You may also want to allow auth:anonymous in the grafana/conf/custom.ini and set up a suitable email SMTP server for alerts
  12. Optional: Prometheus’ default data retention is 15 days (‘15d’); this can be modified with arg --storage.tsdb.retention

An example Prometheus .yml is below (target IPs are generalised). No rules or alerts are defined here and a pair of temperature/adc ‘job_name’ definitions will be needed for each Pi:

# my global config
  scrape_interval:     30s
  evaluation_interval: 30s
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the 
# global 'evaluation_interval'.
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
  - job_name: 'rpzero0_temperature'
    metrics_path: '/temperature'
      - targets: ['x.x.x.18:5000']

  - job_name: 'rpzero0_adc'
    metrics_path: '/adc'
      - targets: ['x.x.x.18:5000']

Prometheus’ web interface can be accessed via http://x.x.x.16:9090/ where x.x.x.16 is the IP address of the server it’s running on. If it’s successfully scraping information from the Pi(s) then http://x.x.x.16:9090/graph?g0.range_input=1h&g0.expr=temperature& should list and graph results from all temperature sensors that have responded.

Example Prometheus temperature graphs

Example Prometheus temperature graphs

Grafana’s web interface is at http://x.x.x.16:3000/ and will take more extensive setup. At a minimum it needs one or more users, and to be attached to the Prometheus install as the default data source.

Connecting Grafana to Prometheus

Connecting Grafana to Prometheus

Once this is done, Grafana dashboards can be created to access data reported from the Pis, set up graphs or status boards and also to set up alerts. The dashboard configurations will be specific to the Pis and sensor setup, as data is labelled by Pi network ID and the temperature sensor unique IDs. Hence queries (‘metrics’) need to be set up in consultation with the appropriate Pi web end point. For example: temperature{sensorid="0417b2b963ff",unit="C"} or adc{job="rpzero0_adc",type="air",adcid="1",unit="hPa"}. Some additional information (e.g. if a temperature sensor is inside or outside of the aquarium) is not configured on the Pi, hence it’s helpful to recognise and add this at the dashboard stage.

The returned data is a time series, so most graphs or panels will want to either set the time range of the displayed results, or run some form of statistics (e.g. average, max, min). This is set up via the Grafana panel GUIs. Examples are shown here:


Graphing a week’s data from a single aquarium

Overview of min/current/max values over the last day for all three aquariums

A compact version of the overview page designed to fit the Raspberry Pi official touchscreen

The source JSON for these three dashboards types is here:

The individual Pi dashboards have alert values set up for critical errors e.g. outside temperature range, air/flow, or the Hall effect sensors show the equipment has stopped. Once Grafana is configured with an appropriate SMTP server (see ; we used Gmail) then alerts will be emailed to an appropriate recipient.

Note: It’s also possible to run Prometheus/Grafana off another Raspberry Pi (go for a full-fat version 2 or 3). Given the heavy Prometheus database it’s also good idea to use an external USB hard drive or pendrive for storing that. In brief the install process is: (i) install, configure Raspbian and get connected to your network; (ii) install and configure the Linux ARM7 binary for Prometheus ; (iii) set up a systemd service file and enable on start up. If you using an external drive use media-pi-0850-9F0E.mount where ‘0850-9FOE’ is its id and appropriate parameters for location and size limitation; (iv) install the Debian ARMv7 package for Grafana, part of this process includes setting up a systemd service for that as well; (v) configure Grafana via its web interface to point at Prometheus and set up dashboards etc.

Bill of Materials & Costs

Prices for these components vary a great deal by supplier and volume ordered. Some items can be scavenged – almost any micro-USB mobile phone adaptor will work for the Pi Zero. These costs are inc. VAT and often include shipping.

Item # Price: high Supplier Price: low Supplier
Rasp Pi Zero WH 1 £12.80 ModMyPi
USB power supply 1 £6.00 ModMyPi £2.50 eBay
8+ Gb micro SD + adapt. 1 £8.40 ModMyPi £5.30 Amazon
UniPiCase Zero (tall) 1 £10.00 ModMyPi
ADS1015 ADC 1 £4.00 eBay £1.50 eBay/China
F-F DuPont ribbon cable 1 £1.50 eBay
3.5 mm stereo jack plug 5 £4.00 eBay £1.00 eBay/China
3.5 mm stereo socket 5 £4.00 eBay £1.00 eBay/China
Momentary Push Button 1 £1.75 eBay
3 mm LED 1 £2.00/50 eBay
Veroboard/Stripboard 1 £1.00 eBay
330 Ω resistor 1 £1.00/20 eBay
4.6 kΩ resistor 1 £1.00/20 eBay
40 kΩ resistor 1 £1.00/20 eBay
10 m 4-core alarm cable 1 £5.70 eBay
waterproof DS18B20 3 £8.00/5 eBay £3.00/5 eBay/China
normal DS18B20 1 £5.00/5 eBay £1.00/5 eBay/China
LDR/photoresistor 1 £1.00/10 eBay
MPX5010DP air sensor 1 £11.25 eBay £7.35 eBay/China
YF-S201C flow counter clear 1 £13.0 Amazon £3.10 eBay/China
13 mm barb to female 1/2″ BSP 1 £1.20 Growinsane
A1301EUA-T Hall sensor 1 £3.00 eBay
total for 1x £106.50 £68.70
total for 3x ~£275 ~£175

Further cost reductions could be achieved by:

using the Rasp Pi Zero W and soldering to the GPIO save ~£4
using recovered mobile phone usb power supplies and/or micro SD cards save £8-14
using a cheap project or plastic/card case save £10
hard wiring the sensors (no jack plugs/sockets) save £2-8
using recovered 4-core cable (old mouse cables are good) save £5

This would bring the lower price down to about £44.

Also needed during Pi setup:

  • HDMI monitor with adaptor/cable for micro-HDMI
  • USB keyboard/mouse with adaptor for micro-USB
  • micro SD card reader, or normal reader plus adaptor

Tools and consumables needed: soldering iron & solder, multimeter, scalpel/Stanley knife, needle nose pliers and side cutters, electric drill & bits, hair dryer, heat shrink tubing, electrical tape.

Caveats & Problems

(This will probably get updated as we identify new issues!)

Pi’s SD card getting corrupted: this annoying problem may be caused by incorrect shutdown of Raspbian, normally due to sudden power loss. We’ve also had problems with several years old SD cards failing after a few days use (new Sandisk branded ones seem much better). It’s probably useful to have Raspbian installed on a spare card, ready to configure and use if this happens.

Flow sensor rotor stalling: this is caused by either the filter flow rate getting too low (clean it!) or fouling the sensor’s rotor with debris. Occasionally removing and back-washing the housing with a turkey baster fixes this. Also these rotors are more reliable if the output is tilted slightly down from horizontal.

Grafana’s alert emails don’t have images: this was tracked down to a missing render.js file in /grafana/tools/phantomjs/ – this version worked for us (Grafana v 5.1.3).