empowering creative people

Showcase Image

Introduction

YAM (or YetAnotherMonitor)

I keep more than 20 enclosures of Australian native lizards and turtles and I want to make sure they are all in an appropriate environment. To that end, I built a microcontroller-based system to monitor the temperature and water flow rates for each tank, showing me up to date information and time trends from the convenience of my phone, tablet or PC.


Project Description

YAM (or YetAnotherMonitor)

Parts used (all available from Core Electronics):

Software and libraries used:

  • Python3
  • Flask
  • Bokeh
  • Boto (DynamoDB interface)
  • Mosquitto
  • AWS
  • Lambda (MQTT interface) DynamoDB (NoSQL database) Elastic Beanstalk (web host)

Temperature Sensors

DS18B20 based temperature sensors provide a digital temperature over a 3 wire bus called 1wire. The 3 pins are red (5V power), black/gray (ground), yellow (data). Multiple sensors can be connected together on the same 3 wire bus to supply multiple temperature inputs via 1 digital input pin. Technically they work without the power on the red wire, using parasitic power from the data line but I found it to be flaky without it. Each sensor comes with a hard-coded unique ID to distinguish them. I print a label with the ID and stick it to the sensor to keep track of the mapping.

As I have a lot of enclosures and change things about I wanted it to be flexible. I decided to use 3-pin JST XHP connectors to plug it all together. I created splitter units with 1" prototyping boards to connect multiple sensors to a "node" and then nodes together and to the microcontroller using cut telephone cord with more XHP-3 connectors. TIP: Buy a good pair of JST crimpers unless you are much better with a pair of pliers than I am.

Prototyping board 3-pin JST connectors

Microcontrollers

I initially used an Arduino Uno Wifi board as it was the cheapest Wifi enabled Arduino. I found the device a little cumbersome to use MQTT (more on that later) but it does the job.

The second I used a Particle Photon which was much more straightforward (and cheaper). Using a standard JSON format in the MQTT messages means I can publish data from many different types of hardware without any issue.

I have 1 microcontroller on each side of the room servicing a bank of enclosures with the temperature sensors feeding back to them via the 1wire bus.

I used a prototyping shield on the Arduino with a JST connector and the pull-up resistor required between power and data for the bus.

Arduino prototyping board JST 3-pin connectors

For the Particle Photon, I simply soldered it to a prototyping board which also had enough room to solder on 4 JST ports for 4 sensors to reduce the number of splitters I need by 1. Notice only 1 I/O port is used for the bus and I use the VIN to provide 4.8V to the temperature sensors rather than the native 3.3V of the Photon (which should work anyway). Try not to notice the terrible soldering all around.

Particle Photon prototyping board

Each microcontroller has a simple program to read the temperatures for each connected sensor (it does not need to know which, or how many sensors are connected) and broadcast their values and matching sensor ID over wifi via the MQTT protocol.

Note: It would be very simple to add one these sensors to a raspberry pi as well.

The code can be found here for both devices (Devices directory):

https://github.com/namezmud/YetAnotherMonitor

Both use open source libraries for decoding the sensor data and the MQTT protocol. MQTT is an IoT (Internet of Things) protocol based on a publish-subscribe architecture. I won't go into detail here but for the sake of this project, it means the microcontrollers publish data on a "topic" in this case called "YarraRiverReptiles/data/temperature/" with an ID and temperature from each sensor every 10 seconds. It does not need to know what is connected to it or who is using this data or how it simply broadcasts. I do this to avoid having to re-flash the microcontrollers when something changes.

Easy to understand MQTT overview and a site with a free public MQTT server to use for testing.

http://www.hivemq.com/blog/how-to-get-started-with-mqtt

Brokers (somewhat optional)

MQTT over a wider area uses "brokers" to service subscription requests and routing of MQTT data. You _could_ send it directly to the cloud from the microcontroller but to have a bit more control (and security) I set up a broker on my always-on Raspberry Pi 3 (at least it was always on until I broke it today :( ). I used the open source MQTT broker Mosquitto (yes, 2 t's). This allows me to set up the AWS authentication to privatise the data.

Processing (optional)

To avoid the microcontroller needing to know details about the location of sensors (and to brush up on my python), I decided to process the data on my raspberry pi before sending it to the cloud. This listens to all the received temperature data and performs a lookup to add an enclosure label and timestamp to the data before sending it to "the cloud", also via MQTT. This could have been done on the microcontroller or in "the cloud".

Anyway, you can check out the code here:

https://github.com/namezmud/YetAnotherMonitor/blob/master/YAMprocess_sensors.py

"The Cloud"

Given this is an electronics site I will skim over the rest. The options are nearly endless in what can be done with the data now: display, chart, tweet (5 lines of python code), push notify etc.

What I did (mostly to investigate the topic), is send the data to Amazon Web Services (AWS) using the lambda product to push it into a database (DynamoDB).

I created an empty AWS DynamoDB table called "YAM" with a primary partition key "name" and primary sort order "time_ms".

I then configured lambda to listen to my MQTT feed and run some python code:

from __future__ import print_function # Python 2/3 compatibility
import boto3
import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('YAM')
print(table.creation_date_time)

response = table.put_item(
Item=event
)

logger.info('got event{}'.format(event))
return 'Done'

The Display

I wanted to view the data in a web page (to prove I can) and to view it on multiple devices. Hosting it "in the cloud" allows me to view it anywhere without having to handle security etc. myself.

Again, many ways to skin a cat, again solution chosen to trial some technology:

    Python Flask: A basic python web framework, running on AWS. Python Bokeh: A python charting library that can be run with Flask. Hugo: Static HTML generator using templates.

These can be run anywhere from AWS Elastic Beanstalk to a raspberry pi or laptop PC.

I built a basic static site using Hugo to get a site that looks like it is from this century without any graphic design or web design skills. The python script extracts the data from the database, builds an interactive chart using the Bokeh library and then inserts it into the static HTML generated by Hugo.

Python scripts and generated HTML code. The Hugo configuration wasn't committed when my computer was stolen so I'll have to re-do it :(.

https://github.com/namezmud/YetAnotherMonitor

Conclusion

Temperature monitored enclosure

The project could have been done simpler but it gave me an application to try some things such as python micro web frameworks and charting as well as AWS. Feel free to look at, copy, repurpose some or all of the code. It is not wrapped up so neatly as to be reused blindly as some things (such as MQTT topic names and DB tables are hardcoded) so you'll need to be willing to get your hands a little dirty to reuse it. Anyway, I hope it at least provides some inspiration.