For those interested in the code, here it is!
Note: the code will not run unless you have the thermometers connected to the GPIO in accordance with the circuit diagram. Each thermometer has it's own physical address, and you will need to edit the script to set your own address (when you have your thermometers). I will explain how to do this on the How-To guide (or later on in this thread if someone acquires some thermometers before the guide is finished).
There are two files that need to be created, and put in the same directory. One is a simple copy of an Adafruit python script used to get the Slice of Pi/o working, and the other is the one that I have put together (this is the one you execute).
ADAfruit_I2C.py (must have this file name exactly as shown for my code to work).
Boiler_Controller.py
To run the program (assuming they are in /home/pi) type:
Note: the code will not run unless you have the thermometers connected to the GPIO in accordance with the circuit diagram. Each thermometer has it's own physical address, and you will need to edit the script to set your own address (when you have your thermometers). I will explain how to do this on the How-To guide (or later on in this thread if someone acquires some thermometers before the guide is finished).
There are two files that need to be created, and put in the same directory. One is a simple copy of an Adafruit python script used to get the Slice of Pi/o working, and the other is the one that I have put together (this is the one you execute).
ADAfruit_I2C.py (must have this file name exactly as shown for my code to work).
Code:
#!/usr/bin/python
import smbus
# ===========================================================================
# Adafruit_I2C Class
# ===========================================================================
class Adafruit_I2C :
@staticmethod
def getPiRevision():
"Gets the version number of the Raspberry Pi board"
# Courtesy quick2wire-python-api
# [url]https://github.com/quick2wire/quick2wire-python-api[/url]
try:
with open('/proc/cpuinfo','r') as f:
for line in f:
if line.startswith('Revision'):
return 1 if line.rstrip()[-1] in ['1','2'] else 2
except:
return 0
@staticmethod
def getPiI2CBusNumber():
# Gets the I2C bus number /dev/i2c#
return 1 if Adafruit_I2C.getPiRevision() > 1 else 0
def __init__(self, address, busnum=-1, debug=False):
self.address = address
# By default, the correct I2C bus is auto-detected using /proc/cpuinfo
# Alternatively, you can hard-code the bus version below:
# self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's)
# self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's)
self.bus = smbus.SMBus(
busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber())
self.debug = debug
def reverseByteOrder(self, data):
"Reverses the byte order of an int (16-bit) or long (32-bit) value"
# Courtesy Vishal Sapre
byteCount = len(hex(data)[2:].replace('L','')[::2])
val = 0
for i in range(byteCount):
val = (val << 8) | (data & 0xff)
data >>= 8
return val
def errMsg(self):
print "Error accessing 0x%02X: Check your I2C address" % self.address
return -1
def write8(self, reg, value):
"Writes an 8-bit value to the specified register/address"
try:
self.bus.write_byte_data(self.address, reg, value)
if self.debug:
print "I2C: Wrote 0x%02X to register 0x%02X" % (value, reg)
except IOError, err:
return self.errMsg()
def write16(self, reg, value):
"Writes a 16-bit value to the specified register/address pair"
try:
self.bus.write_word_data(self.address, reg, value)
if self.debug:
print ("I2C: Wrote 0x%02X to register pair 0x%02X,0x%02X" %
(value, reg, reg+1))
except IOError, err:
return self.errMsg()
def writeList(self, reg, list):
"Writes an array of bytes using I2C format"
try:
if self.debug:
print "I2C: Writing list to register 0x%02X:" % reg
print list
self.bus.write_i2c_block_data(self.address, reg, list)
except IOError, err:
return self.errMsg()
def readList(self, reg, length):
"Read a list of bytes from the I2C device"
try:
results = self.bus.read_i2c_block_data(self.address, reg, length)
if self.debug:
print ("I2C: Device 0x%02X returned the following from reg 0x%02X" %
(self.address, reg))
print results
return results
except IOError, err:
return self.errMsg()
def readU8(self, reg):
"Read an unsigned byte from the I2C device"
try:
result = self.bus.read_byte_data(self.address, reg)
if self.debug:
print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
(self.address, result & 0xFF, reg))
return result
except IOError, err:
return self.errMsg()
def readS8(self, reg):
"Reads a signed byte from the I2C device"
try:
result = self.bus.read_byte_data(self.address, reg)
if result > 127: result -= 256
if self.debug:
print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
(self.address, result & 0xFF, reg))
return result
except IOError, err:
return self.errMsg()
def readU16(self, reg):
"Reads an unsigned 16-bit value from the I2C device"
try:
result = self.bus.read_word_data(self.address,reg)
if (self.debug):
print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg)
return result
except IOError, err:
return self.errMsg()
def readS16(self, reg):
"Reads a signed 16-bit value from the I2C device"
try:
result = self.bus.read_word_data(self.address,reg)
if (self.debug):
print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg)
return result
except IOError, err:
return self.errMsg()
if __name__ == '__main__':
try:
bus = Adafruit_I2C(address=0)
print "Default I2C bus is accessible"
except:
print "Error accessing default I2C bus"
Boiler_Controller.py
Code:
#!/usr/bin/python
# /usr/share/adafruit/webide/repositories/my-pi-projects/boiler_Mk2/Boiler_Controller_LCD.py
#*************************************************************************************
#*************************************************************************************
#*************************************************************************************
# This HLT/Boiler Controller software has been written by Robbo100 (username from
# [url]www.thehomebrewforum.co.uk[/url]). This software uses elements of code from Daniel Berlin
# (with some changes by Adafruit Industries/Limor Fried) and Matt Hawkins.
#*************************************************************************************
#*************************************************************************************
#*************************************************************************************
# Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal MCP230XX_GPIO(1, 0xin
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#------------------------------------------------------------------------------
# IMPORT OTHER FUNCTIONS AND CLASSES
#------------------------------------------------------------------------------
from Adafruit_I2C import Adafruit_I2C
import smbus
import time
import os
import glob
import RPi.GPIO as GPIO
import threading
import datetime
from threading import Thread
#------------------------------------------------------------------------------
# SETUP THE ONE WIRE THERMOMETER SYSTEM
#------------------------------------------------------------------------------
# Initialise the One Wire Thermometer
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
# Setup Thermometer 1 Location
#*************************************************************************************
# The two device addresses MUST be changed to match the used device, otherwise the
# software WILL NOT RUN
#*************************************************************************************
device1_folder = glob.glob(base_dir + '28-0000057ce739')[0] #BOILER DEVICE - CHANGE TO MATCH YOUR DEVICE
device1_file = device1_folder + '/w1_slave'
# setup Thermomenter 2 Location
device2_folder = glob.glob(base_dir + '28-0000057dc7da')[0] #BOILER DEVICE - CHANGE TO MATCH YOUR DEVICE
device2_file = device2_folder + '/w1_slave'
def read_temp_raw_1():
f = open(device1_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp_1():
lines = read_temp_raw_1()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.001)
lines = read_temp_raw_1()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c_1 = float(temp_string) / 1000.0
temp_f_1 = temp_c_1 * 9.0 / 5.0 + 32.0
return temp_c_1
def read_temp_raw_2():
f = open(device2_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp_2():
lines = read_temp_raw_2()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.001)
lines = read_temp_raw_2()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c_2 = float(temp_string) / 1000.0
temp_f_2 = temp_c_2 * 9.0 / 5.0 + 32.0
return temp_c_2
#------------------------------------------------------------------------------
# INITIALISE THE SLICE OF PI/O
#------------------------------------------------------------------------------
MCP23017_IODIRA = 0x00
MCP23017_IODIRB = 0x01
MCP23017_GPIOA = 0x12
MCP23017_GPIOB = 0x13
MCP23017_GPPUA = 0x0C
MCP23017_GPPUB = 0x0D
MCP23017_OLATA = 0x14
MCP23017_OLATB = 0x15
MCP23008_GPIOA = 0x09
MCP23008_GPPUA = 0x06
MCP23008_OLATA = 0x0A
class Adafruit_MCP230XX(object):
OUTPUT = 0
INPUT = 1
def __init__(self, address, num_gpios):
assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16"
self.i2c = Adafruit_I2C(address=address)
self.address = address
self.num_gpios = num_gpios
# set defaults
if num_gpios <= 8:
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
self.direction = self.i2c.readU8(MCP23017_IODIRA)
self.i2c.write8(MCP23008_GPPUA, 0x00)
elif num_gpios > 8 and num_gpios <= 16:
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B
self.direction = self.i2c.readU8(MCP23017_IODIRA)
self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8
self.i2c.write8(MCP23017_GPPUA, 0x00)
self.i2c.write8(MCP23017_GPPUB, 0x00)
def _changebit(self, bitmap, bit, value):
assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value
if value == 0:
return bitmap & ~(1 << bit)
elif value == 1:
return bitmap | (1 << bit)
def _readandchangepin(self, port, pin, value, currvalue = None):
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
#assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
if not currvalue:
currvalue = self.i2c.readU8(port)
newvalue = self._changebit(currvalue, pin, value)
self.i2c.write8(port, newvalue)
return newvalue
def pullup(self, pin, value):
if self.num_gpios <= 8:
return self._readandchangepin(MCP23008_GPPUA, pin, value)
if self.num_gpios <= 16:
lvalue = self._readandchangepin(MCP23017_GPPUA, pin, value)
if (pin < 8):
return
else:
return self._readandchangepin(MCP23017_GPPUB, pin-8, value) << 8
# Set pin to either input or output mode
def config(self, pin, mode):
if self.num_gpios <= 8:
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
if self.num_gpios <= 16:
if (pin < 8):
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
else:
self.direction |= self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8
return self.direction
def output(self, pin, value):
# assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
if self.num_gpios <= 8:
self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA))
if self.num_gpios <= 16:
if (pin < 8):
self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA))
else:
self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) << 8
return self.outputvalue
self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue)
return self.outputvalue
def input(self, pin):
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin
if self.num_gpios <= 8:
value = self.i2c.readU8(MCP23008_GPIOA)
elif self.num_gpios > 8 and self.num_gpios <= 16:
value = self.i2c.readU8(MCP23017_GPIOA)
value |= self.i2c.readU8(MCP23017_GPIOB) << 8
return value & (1 << pin)
def readU8(self):
result = self.i2c.readU8(MCP23008_OLATA)
return(result)
def readS8(self):
result = self.i2c.readU8(MCP23008_OLATA)
if (result > 127): result -= 256
return result
def readU16(self):
assert self.num_gpios >= 16, "16bits required"
lo = self.i2c.readU8(MCP23017_OLATA)
hi = self.i2c.readU8(MCP23017_OLATB)
return((hi << 8) | lo)
def readS16(self):
assert self.num_gpios >= 16, "16bits required"
lo = self.i2c.readU8(MCP23017_OLATA)
hi = self.i2c.readU8(MCP23017_OLATB)
if (hi > 127): hi -= 256
return((hi << 8) | lo)
def write8(self, value):
self.i2c.write8(MCP23008_OLATA, value)
def write16(self, value):
assert self.num_gpios >= 16, "16bits required"
self.i2c.write8(MCP23017_OLATA, value & 0xFF)
self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF)
# RPi.GPIO compatible interface for MCP23017 and MCP23008
class MCP230XX_GPIO(object):
OUT = 0
IN = 1
BCM = 0
BOARD = 0
def __init__(self, busnum, address, num_gpios):
self.chip = Adafruit_MCP230XX(busnum, address, num_gpios)
def setmode(self, mode):
# do nothing
pass
def setup(self, pin, mode):
self.chip.config(pin, mode)
def input(self, pin):
return self.chip.input(pin)
def output(self, pin, value):
self.chip.output(pin, value)
def pullup(self, pin, value):
self.chip.pullup(pin, value)
if __name__ == '__main__':
#------------------------------------------------------------------------------
# CONFIGURE THE SLICE OF PI/O INPUT AND OUTPUTS
#------------------------------------------------------------------------------
# Set num_gpios to 8 for MCP23008 or 16 for MCP23017!
# mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) # MCP23008
mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 16) # MCP23017
# List outputs here
mcp.config(7, mcp.OUTPUT) # Buzzer
mcp.config(12, mcp.OUTPUT) # Relay 1 on
mcp.config(13, mcp.OUTPUT) # Relay 2 on
# Set inputs with the pullup resistor enabled here
mcp.config(14, mcp.INPUT)
mcp.pullup(14, 1)
mcp.config(15, mcp.INPUT)
mcp.pullup(15, 1)
# Set all outputs to off for startup (note - some outputs are reversed
# depending upon connected device)
mcp.output(7, 0)
mcp.output(12, 1)
mcp.output(13, 1)
#------------------------------------------------------------------------------
# HD44780 LCD SETUP
#------------------------------------------------------------------------------
# Author : Matt Hawkins
# Site : [url]http://www.raspberrypi-spy.co.uk[/url]
# Date : 26/07/2012
# The wiring for the LCD is as follows:
# 1 : GND
# 2 : 5V
# 3 : Contrast (0-5V)*
# 4 : RS (Register Select)
# 5 : R/W (Read Write) - GROUND THIS PIN
# 6 : Enable or Strobe
# 7 : Data Bit 0 - NOT USED
# 8 : Data Bit 1 - NOT USED
# 9 : Data Bit 2 - NOT USED
# 10: Data Bit 3 - NOT USED
# 11: Data Bit 4
# 12: Data Bit 5
# 13: Data Bit 6
# 14: Data Bit 7
# 15: LCD Backlight +5V**
# 16: LCD Backlight GND
# Define GPIO to LCD mapping
LCD_RS = 17
LCD_E = 18
LCD_D4 = 22
LCD_D5 = 23
LCD_D6 = 24
LCD_D7 = 25
# Define some device constants
LCD_WIDTH = 16 # Maximum characters per line
LCD_CHR = True
LCD_CMD = False
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
# Timing constants
E_PULSE = 0.00005
E_DELAY = 0.00005
#------------------------------------------------------------------------------
# HD44780 LCD INITIALISATION
#------------------------------------------------------------------------------
def lcd_init():
# Initialise display
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)
def lcd_string(message):
# Send string to display
message = message.ljust(LCD_WIDTH," ")
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)
def lcd_byte(bits, mode):
# Send byte to data pins
# bits = data
# mode = True for character
# False for command
GPIO.output(LCD_RS, mode) # RS
# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
GPIO.output(LCD_D7, True)
# Toggle 'Enable' pin
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)
# Toggle 'Enable' pin
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
#------------------------------------------------------------------------------
# BOIL FUNCTION
#------------------------------------------------------------------------------
def boil_mode(boil_temperature):
global target_temperature_glob
target_temperature_glob = boil_temperature
global Line1_String
global Line2_String
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = " FULL BOIL MODE "
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("Boiler Temp = " + (str(int(Temperature))))
lcd_string(Line2_String)
time.sleep(1);
target_temperature_glob = 120
while (True):
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = " FULL BOIL MODE "
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("Boiler Temp = " + (str(int(Temperature))))
lcd_string(Line2_String)
if (mcp.input(15) < 2):
lcd_init()
if (mcp.input(15) < 2) & (mcp.input(14) < 2):
time.sleep(1);
target_temperature_glob = 72
break
if (Temperature > 96): # SET TO 96 DEG
buzzer_count = 0
while (buzzer_count < 6):
mcp.output(7, 1)
time.sleep(1)
mcp.output(7, 0)
time.sleep(1)
buzzer_count = buzzer_count + 1
mcp.output(7, 0)
Boil_Start_Time = datetime.datetime.now()
Elapsed_Time = datetime.datetime.now()-Boil_Start_Time
Countdown = ((60*60)-Elapsed_Time.total_seconds())
#Countdown = ((60)-Elapsed_Time.total_seconds()) #Countdown Test Line
while (Countdown > 0):
Elapsed_Time = datetime.datetime.now()-Boil_Start_Time
Countdown = ((60*60)-Elapsed_Time.total_seconds())
#Countdown = ((60)-Elapsed_Time.total_seconds()) #Countdown Test Line
if ((int(Countdown//60))<10):
Countdown_Mins = ("0" + (str(int(Countdown//60))))
else:
Countdown_Mins = str(int(Countdown//60))
if (int((Countdown - (int((Countdown//60)*60))))<10):
Countdown_Secs = ("0" + str(int(Countdown - (int((Countdown//60)*60)))))
else:
Countdown_Secs = str(int(Countdown - (int((Countdown//60)*60))))
global Countdown_String
Countdown_String = "Boil Time " + Countdown_Mins + ":" + Countdown_Secs
# Display temperatures on LCD
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = " FULL BOIL MODE "
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = (Countdown_String)
lcd_string(Line2_String)
if (mcp.input(15) < 2):
lcd_init()
if ((Countdown < (60*15)) & (Countdown > ((60*15)-5))):
buzzer_count = 0
while (buzzer_count < 6):
mcp.output(7, 1)
time.sleep(1)
mcp.output(7, 0)
time.sleep(1)
buzzer_count = buzzer_count + 1
mcp.output(7, 0)
# Display temperatures on LCD
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = " FULL BOIL MODE "
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = (" Boil Complete ")
lcd_string(Line2_String)
buzzer_count = 0
while (buzzer_count < 6):
mcp.output(7, 1)
time.sleep(1)
mcp.output(7, 0)
time.sleep(1)
buzzer_count = buzzer_count + 1
mcp.output(7, 0)
while(mcp.input(14) > 2):
if (mcp.input(15) < 2):
lcd_init()
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = (" READY FOR COOL ")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("PRESS TEMP DOWN")
lcd_string(Line2_String)
# Start the cooling process
target_temperature_glob = 1 # This is needed to force the boiler to OFF in the main scropt
while(Temperature > 28): # SET TO 28 DEG
# Display temperatures on LCD
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = (" COOLING MODE ")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("Boiler Temp = " + (str(int(Temperature))))
lcd_string(Line2_String)
time.sleep(1)
if (mcp.input(15) < 2):
lcd_init()
buzzer_count = 0
while (buzzer_count < 6):
mcp.output(7, 1)
time.sleep(1)
mcp.output(7, 0)
time.sleep(1)
buzzer_count = buzzer_count + 1
mcp.output(7, 0)
while(mcp.input(14) > 2):
if (mcp.input(15) < 2):
lcd_init()
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = (" COOLING MODE ")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("Cooling Complete")
lcd_string(Line2_String)
time.sleep(3)
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = ("SHUTDOWN CONTLR?")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = (" HOLD TEMP DOWN ")
lcd_string(Line2_String)
time.sleep(3)
# Shutdown Pi
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = ("*****REMOVE*****")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("**BOILER POWER**")
lcd_string(Line2_String)
buzzer_count = 0
while (buzzer_count < 12):
mcp.output(7, 1)
time.sleep(0.5)
mcp.output(7, 0)
time.sleep(0.5)
buzzer_count = buzzer_count + 1
mcp.output(7, 0)
time.sleep(8)
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = (" SHUTTING DOWN ")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("Please Wait...")
lcd_string(Line2_String)
time.sleep(3)
os.system("sudo shutdown -r now")
#------------------------------------------------------------------------------
# DISPLAY AND BUTTON DETECTION FUNCTION
#------------------------------------------------------------------------------
def display(target_temperature):
global target_temperature_glob
target_temperature_glob = target_temperature
global Line1_String
global Line2_String
while (True):
# Detect Switch Presses
if (mcp.input(15) < 2):
target_temperature_glob = target_temperature_glob+1
lcd_init()
if (mcp.input(14) < 2):
target_temperature_glob = target_temperature_glob-1
if target_temperature_glob < 0:
target_temperature_glob = 0
if target_temperature_glob > 99:
target_temperature_glob = 99
if (mcp.input(15) < 2) & (mcp.input(14) < 2):
boil_temperature = target_temperature_glob
boil_mode(boil_temperature)
time.sleep(0.15)
# Display temperatures on LCD
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = ("Target Temp = " + (str(target_temperature_glob)))
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("Boiler Temp = " + (str(int(Temperature))))
lcd_string(Line2_String)
#------------------------------------------------------------------------------
# MAIN TEMPERATURE READING FUNCTION
#------------------------------------------------------------------------------
print "Starting Program (CTRL+Z to quit)"
# Startup Display
GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers
GPIO.setup(LCD_E, GPIO.OUT) # E
GPIO.setup(LCD_RS, GPIO.OUT) # RS
GPIO.setup(LCD_D4, GPIO.OUT) # DB4
GPIO.setup(LCD_D5, GPIO.OUT) # DB5
GPIO.setup(LCD_D6, GPIO.OUT) # DB6
GPIO.setup(LCD_D7, GPIO.OUT) # DB7
# Initialise display
lcd_init()
# Initialise the program parameters
temp_reached = 0
global Temperature
Temperature = 99
tens = 0
units = 0
target_temperature = 72
temp_reached = 0
Line1_String = ""
Line2_String = ""
# Wait for User to start boiler
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = ("ROBBO'S BREWERY") # You can change this (and any other text in "quotes") to anything you want to display on the screen
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = ("BOILER CONTROL")
lcd_string(Line2_String)
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print " Average Temperature = "
print " Target Temperature = "
print " ____________________________________"
print " ", Line1_String
print " ", Line2_String
print " ____________________________________"
time.sleep(5)
while(mcp.input(15) > 2):
lcd_byte(LCD_LINE_1, LCD_CMD)
Line1_String = (" READY TO START")
lcd_string(Line1_String)
lcd_byte(LCD_LINE_2, LCD_CMD)
Line2_String = (" PRESS TEMP UP")
lcd_string(Line2_String)
time.sleep(0.5)
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print " Average Temperature = "
print " Target Temperature = "
print " ____________________________________"
print " ", Line1_String
print " ", Line2_String
print " ____________________________________"
# Start Display Thread
display_thread = Thread(target = display, args = (target_temperature, ))
display_thread.start()
# Loop the following tasks forever
while(True):
# Read Temperatures From Thermometers, calculate the average, and print
# them, along with the current global target temperature parameter, to
# the terminl screen
temperature1 = read_temp_1()
temperature2 = read_temp_2()
Temperature = ((temperature2+temperature2)/2)
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print ""
print " Average Temperature = ", Temperature
print " Target Temperature = ", target_temperature_glob
print " ____________________________________"
print " ", Line1_String
print " ", Line2_String
print " ____________________________________"
# If the measured temperature is lower than the target temperature, then
# turn on the boilers (0 is ON, 1 os OFF)
# Boiler 1
if (Temperature < target_temperature_glob):
mcp.output(12, 0)
else:
mcp.output(12, 1)
# Boiler 2
if (Temperature < (target_temperature_glob-1)):
mcp.output(13, 0)
else:
mcp.output(13, 1)
# Heating Mode Temperature Reached Buzzer
if ((Temperature > target_temperature_glob) & (temp_reached == 0)) & (target_temperature_glob != 1):
buzzer_count=0
while (buzzer_count < 6):
mcp.output(7, 1)
time.sleep(1)
mcp.output(7, 0)
time.sleep(1)
buzzer_count = buzzer_count + 1
mcp.output(7, 0)
temp_reached=1
if ((temp_reached == 1) & (Temperature <(target_temperature_glob-4))):
temp_reached=0
GPIO.cleanup()
To run the program (assuming they are in /home/pi) type:
Code:
sudo python /home/pi/Boiler_Controller.py