How to Control Beer Fermentation Temperature and Gravity From Your Smartphone
by Cloud4RPi in Circuits > Raspberry Pi
3069 Views, 40 Favorites, 0 Comments
How to Control Beer Fermentation Temperature and Gravity From Your Smartphone
When beer is fermenting, you should monitor its gravity and temperature daily. It is easy to forget to do so, and impossible if you are away.
After some googling, I found several solutions for automated gravity monitoring ( one, two, three). One of them, with very clever concept, called Tilt. Tilt is floating in your beer and is measuring its own tilt angle. This angle depends on liquid’s density, and therefore can measure gravity of the fermenting beer.
Tilt comes with a mobile app, that connects to it and can post data to any web service. The problem is that you need to be not far from Tilt to be able to do so. There is also a Raspberry Pi program that works with Tilt.
Getting Tilt Data in Python
I’m already using Raspberry Pi to monitor cellar temperature, and a cloud control panel service cloud4rpi.io. If Tilt can talk to Raspberry Pi, it should be possible connect cloud4rpi to it. Tilt is using a wireless protocol, so you’ll need Raspberry Pi with a wireless chip ( Rasbperry Pi 3 or Zero W).
Luckily, there is a GitHub repo for Tilt software with some samples. Looking at https://github.com/baronbrew/tilt-scan you can see that Tilt looks to others as BLE iBeacon, with “Color” coded in UUID, and temperature and gravity are in major and minor bytes.
Their sample code is for Node.js, and I have a Python control program based on cloud4rpi template https://github.com/cloud4rpi/cloud4rpi-raspberrypi-python/blob/master/control.py.
So I need to get Tilt data in Python. After some googling, I found https://github.com/switchdoclabs/iBeacon-Scanner- — Python iBeacon scanner. This is a program, not a library, so I modified it to return a dictionary instead of string. And I also wrote Tilt-specific module to get color, temperature and gravity of the first Tilt found (I have only one), and a simple test program to check if it can see my Tilt:
import time
import tiltwhile True: res = tilt.getFirstTilt() print res time.sleep(2)
Run and check that it works. Now I can plug it to my control program. I already have a python program connected to cloud4rpi.io, but let me show how to do so from the scratch.
Connecting Device to the Cloud
First, sign in to cloud4rpi.io, then create a new device.
You will be given a device token and installation instructions. For Raspberry Pi follow instructions here http://docs.cloud4rpi.io/start/rpi/ — make sure your system is up-to-date:
sudo apt update && sudo apt upgrade
Install prerequisites:
sudo apt install git python python-pip
Install cloud4rpi python packages:
sudo pip install cloud4rpi
then get a sample python app for Raspberry Pi (into control folder):
git clone https://github.com/cloud4rpi/cloud4rpi-raspberryp... control
cd control
modify control.py — specify your device token in the line
DEVICE_TOKEN = ‘__YOUR_DEVICE_TOKEN__’
Remove unnecessary entries from device variable declarations, leave only CPUTemp to test device connection:
# Put variable declarations here
variables = { 'CPU Temp': { 'type': 'numeric', 'bind': rpi.cpu_temp } }
Now do a test run:
sudo python control.py
If everything is ok, your device page will be immediately updated with diagnostic data.
Sending Data to the Cloud
Now we need to modify control.py to read and report Tilt’s color, temperature and gravity. Result looks like this:
from os import uname
from socket import gethostname import sys import time import cloud4rpi import rpi import tilt# Put your device token here. To get the token, # sign up at https://cloud4rpi.io and create a device. DEVICE_TOKEN = '__YOUR_DEVICE_TOKEN__'
# Constants DATA_SENDING_INTERVAL = 60 # secs DIAG_SENDING_INTERVAL = 600 # secs POLL_INTERVAL = 0.5 # 500 ms
beacon = {}
def F2C(degreesF): return (degreesF - 32) / 1.8
def getTemp(): return F2C(int(beacon['Temp'])) if beacon else None
def getGravity(): return beacon['Gravity'] if beacon else None
def main():
# Put variable declarations here variables = { 'Gravity': { 'type': 'numeric', 'bind': getGravity }, 'Beer Temp': { 'type': 'numeric', 'bind': getTemp } }
diagnostics = { 'CPU Temp': rpi.cpu_temp, 'IP Address': rpi.ip_address, 'Host': gethostname(), 'Operating System': " ".join(uname()) }
device = cloud4rpi.connect(DEVICE_TOKEN) device.declare(variables) device.declare_diag(diagnostics)
device.publish_config()
# Adds a 1 second delay to ensure device variables are created time.sleep(1)
try: data_timer = 0 diag_timer = 0 while True: if data_timer <= 0: global beacon beacon = tilt.getFirstTilt() device.publish_data() data_timer = DATA_SENDING_INTERVAL
if diag_timer <= 0: device.publish_diag() diag_timer = DIAG_SENDING_INTERVAL
time.sleep(POLL_INTERVAL) diag_timer -= POLL_INTERVAL data_timer -= POLL_INTERVAL
except KeyboardInterrupt: cloud4rpi.log.info('Keyboard interrupt received. Stopping...')
except Exception as e: error = cloud4rpi.get_error_message(e) cloud4rpi.log.error("ERROR! %s %s", error, sys.exc_info()[0])
finally: sys.exit(0)
if __name__ == '__main__': main()
Now run it manually to see if it works:
sudo python control.py
If everything is good, you will see your variables online.
To run control.py at system startup, install it as a service. Cloud4rpi provides an install script service_install.sh to do so. I’ve included it into my repo. To install control.py as a service, run
sudo bash service_install.sh control.py
Now you can start|stop|restart this service by running command
sudo systemctl start cloud4rpi.service
Service keeps its previous state on power up, so if it was running, it will be running after reboot or power loss.
Final Result
This is it, now I have my Tilt parameters being sent to the cloud, so I can set up a nice cloud control panel for it. Go to https://cloud4rpi.io/control-panels and create new control panel, add widget and select <your device>/Gravity and Beer Temp as data source. Now I can monitor what’s going on even if I’m away from home.
The code I copied and wrote is available here: https://github.com/superroma/tilt-cloud4rpi. It is far from perfect, it works only with a single Tilt, it doesn’t care about “Color” of the device, whatever it means, and I’m not a Python guy at all, so fixes, suggestions or forks are welcome!