I really enjoy keeping fish as pets. At current count we have ten in two aquariums. Shown above is Ziggy, our largest fantail, and a few of our smaller (and faster moving) ones.

Unfortunately, over the years we have also lost a few – and when this happens, one is left wanting to know exactly why this happens. Particularly frustrating is when a fish is lost, yet the others in the same aquarium appear completely unaffected.

The obvious thing to do, though is to ensure that one knows the full details of the conditions in which the fish are living. There are various standard chemical tests that can be done, and at times I’ve been regularly testing the water for ammonia, nitrates and nitrites to ensure that the fish are not living in a poisonous environment. These chemical tests are however completely ‘analogue’ and have to be done by hand. There are (very) expensive digital versions of some of these tests, though the probes and sensors are not really worth using on small domestic aquariums.

An obvious and easy thing to keep an eye on is the water temperature. The type of fish we keep are relatively tolerant to a range of temperatures, however any sudden changes can be harmful.

To this end, I went and bought a DS18B20 one-wire digital temperature sensor. My initial thought was to hook it up to a Raspberry Pi, and have the temperature logged for viewing on something like a web dashboard. I had this up and running for a while, using RPiMonitor. The issue with this was that the network connection to the Raspberry Pi over WiFi proved unreliable, and even when it was working, I had to use another device even to see the current temperature reading. The benefit though was having a full time-series history of the aquarium temperature.

More useful would be to have an immediate live view of the current temperature, and whether that temperature has changed rapidly recently.

It was then that I remembered that I had an FRDM-KL25Z MCU board and an Adafruit RGB LCD shield both sitting in a drawer, just waiting for an application. I acquired these boards as part of my on-going modular synth project, hoping that they’d be useful as a PC or digital interface to the instrument. Realistically, the KL25Z is unsuitable for real-time audio processing. The LCD could still be useful, but the RGB backlight gave me an idea…

To pull off this idea, I would have to get the LCD working with the KL25Z, a task that I had previously failed. This time around, I went to the mbed online compiler and started looking for libraries that other people had already written for working with the LCD (and, while I was at it, the DS18B20). I got lucky, and found a few libraries that did in fact work.

Now, all I needed to do was clean the code up a bit, and invent a main() loop that does what I want. With limited RAM, and no persistent storage at all on the KL25Z I needed to figure out how long a time-series I can keep active for the purposes of averaging the temperature readings.

Just for fun, I also wanted to program a few custom graphics for the LCD and make a little swimming fishy animation to show that the unit is in fact still alive and recording the temperature.

The main() loop therefore does this:

  • Maintain a counter for the current position of the fish animating across the top row of the screen
  • Draw the fish graphic at the appropriate location
  • As the fish exits the right-hand side of the screen, take a temperature reading
  • Store the temperature reading in a circular buffer
  • Take the average of the values in the circular buffer
  • Display the current reading and the average on the bottom row of the screen
  • Change the back-light colour to reflect the relationship between the current reading and the average:
    • If they are within 1 degree celcius, display green (safe)
    • Else, if they are within 2.5 degrees celcius:
      • If current > average, display magenta (warm)
      • If current < average, display cyan (cool)
    • Else, if the difference is greater than 2.5 degrees celcius:
      • If current > average, display red (hot)
      • If current < average, display blue (cold)

By making use of the LED colour like this, I can actually see at a glance if there’s anything to even worry about on the temperature front without even having to read the temperature numbers.


The whole thing is powered via a USB cable, and it fits snugly in the space between the back of the large aquarium and the wall. Thankfully, the aquarium being made of glass, allows the screen to shine right through. Above, the display is showing a 25 hour average of 21.2 degrees celcius and a current reading of 20.2 degrees celcius. Since this is not more than one degree from the average, the light is showing a nice safe green colour.

During the first few days of operation, I did notice the magenta colour a couple of times, but recently the temperature is largely stable and green.

All of the code is on my bitbucket: fishy-monitor – and this does also include all of the library code written by other people.

Leave a Reply

%d bloggers like this: