diff --git a/blinka.py b/blinka.py deleted file mode 100755 index da1f7d7..0000000 --- a/blinka.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python -import adafruit_max31855 -from digitalio import DigitalInOut - -try: - import board -except NotImplementedError: - print("not running on Raspberry PI, assuming simulation") - - -spi = board.SPI() -cs = DigitalInOut(board.D5) -sensor = adafruit_max31855.MAX31855(spi, cs) -print(sensor.temperature) diff --git a/config.py b/config.py index 77d3736..1b90f34 100644 --- a/config.py +++ b/config.py @@ -1,8 +1,12 @@ import logging import os +from digitalio import DigitalInOut +import busio -# uncomment this if using MAX-31856 -#from lib.max31856 import MAX31856 +try: + import board +except NotImplementedError: + print("not running on Raspberry PI, assuming simulation") ######################################################################## # @@ -28,30 +32,51 @@ currency_type = "$" # Currency Symbol to show when calculating cost to run j ######################################################################## # -# GPIO Setup (BCM SoC Numbering Schema) +# Hardware Setup (uses BCM Pin Numbering) # -# Check the RasPi docs to see where these GPIOs are -# connected on the P1 header for your board type/rev. -# These were tested on a Pi B Rev2 but of course you -# can use whichever GPIO you prefer/have available. +# kiln-controller.py uses SPI interface from the blinka library to read +# temperature data from the adafruit-31855 or adafruit-31856. +# Blinka supports many different boards. I've only tested raspberry pi. +# +# SPI uses 3 or 4 pins. On the raspberry pi, you MUST use predefined +# pins. In the case of the adafruit-31855, only 3 pins are used: +# +# SPI0_SCLK = BCM pin 11 = CLK on the adafruit-31855 +# SPI0_MOSI = BCM pin 10 = not connected +# SPI0_MISO = BCM pin 9 = D0 on the adafruit-31855 +# +# plus a GPIO output to connect to CS. You can use any GPIO pin you want. +# I chose gpio pin 5: +# +# GPIO5 = BCM pin 5 = CS on the adafruit-31855 +# +# To control the kiln, one gpio pin is used as an output. Pick any +# you like. I chose gpio pin 23. This output is used to control a +# zero-cross solid-state-relay. + +spi_sclk = board.D11 #spi clock +spi_mosi = board.D10 #spi Microcomputer Out Serial In (not connected) +spi_miso = board.D9 #spi Microcomputer In Serial Out +spi_cs = board.D5 #spi Chip Select +gpio_heat = board.D23 #output that controls relay ### Outputs -gpio_heat = 23 # Switches zero-cross solid-state-relay +#gpio_heat = 23 # Switches zero-cross solid-state-relay ### Thermocouple Adapter selection: # max31855 - bitbang SPI interface # max31856 - bitbang SPI interface. must specify thermocouple_type. -max31855 = 1 -max31856 = 0 +#max31855 = 1 +#max31856 = 0 # see lib/max31856.py for other thermocouple_type, only applies to max31856 # uncomment this if using MAX-31856 #thermocouple_type = MAX31856.MAX31856_S_TYPE ### Thermocouple Connection (using bitbang interfaces) -gpio_sensor_cs = 27 -gpio_sensor_clock = 22 -gpio_sensor_data = 17 -gpio_sensor_di = 10 # only used with max31856 +#gpio_sensor_cs = 27 +#gpio_sensor_clock = 22 +#gpio_sensor_data = 17 +#gpio_sensor_di = 10 # only used with max31856 ######################################################################## # diff --git a/gpioreadall.py b/gpioreadall.py new file mode 100755 index 0000000..2816b45 --- /dev/null +++ b/gpioreadall.py @@ -0,0 +1,147 @@ +#! /usr/bin/env python3 +# 2021-04-02 +# 2021-04-13 Fix Wrong model for Old Style revision codes +# 2021-12-20 Improve Old Style revision codes; ignore unwanted status bits +# 2022-03-25 Zero 2 W +# 2022-04-07 typo +""" +Read all GPIO +This version for raspi-gpio debug tool +""" +import sys, os, time +import subprocess + +MODES=["IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"] +HEADER = ('3.3v', '5v', 2, '5v', 3, 'GND', 4, 14, 'GND', 15, 17, 18, 27, 'GND', 22, 23, '3.3v', 24, 10, 'GND', 9, 25, 11, 8, 'GND', 7, 0, 1, 5, 'GND', 6, 12, 13, 'GND', 19, 16, 26, 20, 'GND', 21) + +# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#new-style-revision-codes +PiModel = { +0: 'A', +1: 'B', +2: 'A+', +3: 'B+', +4: '2B', +6: 'CM1', +8: '3B', +9: 'Zero', +0xa: 'CM3', +0xc: 'ZeroW', +0xd: '3B+', +0xe: '3A+', +0x10: 'CM3+', +0x11: '4B', +0x12: 'Zero2W', +0x13: '400', +0x14: 'CM4' +} + +RED = '\033[1;31m' +GREEN = '\033[1;32m' +ORANGE = '\033[1;33m' +BLUE = '\033[1;34m' +LRED = '\033[1;91m' +YELLOW = '\033[1;93m' +RESET = '\033[0;0m' +COL = { + '3.3v': LRED, + '5v': RED, + 'GND': GREEN +} + +TYPE = 0 +rev = 0 + +def pin_state(g): + """ + Return "state" of BCM g + Return is tuple (name, mode, value) + """ + result = subprocess.run(['raspi-gpio', 'get', ascii(g)], stdout=subprocess.PIPE).stdout.decode('utf-8') + + D = {} # Convert output of raspi-gpio get to dict for convenience + paras = result.split() + for par in paras[2:] : + p, v = par.split('=') + if (v.isdigit()): + D[p] = int(v) + else: + D[p] = v + + if(D['fsel'] < 2): # i.e. IN or OUT + name = 'GPIO{}'.format(g) + else: + name = D['func'] + + mode = MODES[D['fsel']] + if(D['fsel'] == 0 and 'pull' in D): + if(D['pull'] == 'UP'): + mode = 'IN ^' + if(D['pull'] == 'DOWN'): + mode = 'IN v' + + return name, mode, D['level'] + +def print_gpio(pin_state): + """ + Print listing of Raspberry pins, state & value + Layout matching Pi 2 row Header + """ + global TYPE, rev + GPIOPINS = 40 + try: + Model = 'Pi ' + PiModel[TYPE] + except: + Model = 'Pi ??' + if rev < 16 : # older models (pre PiB+) + GPIOPINS = 26 + + print('+-----+------------+------+---+{:^10}+---+------+-----------+-----+'.format(Model) ) + print('| BCM | Name | Mode | V | Board | V | Mode | Name | BCM |') + print('+-----+------------+------+---+----++----+---+------+-----------+-----+') + + for h in range(1, GPIOPINS, 2): + # odd pin + hh = HEADER[h-1] + if(type(hh)==type(1)): + print('|{0:4} | {1[0]:<10} | {1[1]:<4} | {1[2]} |{2:3} '.format(hh, pin_state(hh), h), end='|| ') + else: +# print('| {:18} | {:2}'.format(hh, h), end=' || ') # non-coloured output + print('| {}{:18} | {:2}{}'.format(COL[hh], hh, h, RESET), end=' || ') # coloured output + # even pin + hh = HEADER[h] + if(type(hh)==type(1)): + print('{0:2} | {1[2]:<2}| {1[1]:<5}| {1[0]:<10}|{2:4} |'.format(h+1, pin_state(hh), hh)) + else: +# print('{:2} | {:9} |'.format(h+1, hh)) # non-coloured output + print('{}{:2} | {:9}{} |'.format(COL[hh], h+1, hh, RESET)) # coloured output + print('+-----+------------+------+---+----++----+---+------+-----------+-----+') + print('| BCM | Name | Mode | V | Board | V | Mode | Name | BCM |') + print('+-----+------------+------+---+{:^10}+---+------+-----------+-----+'.format(Model) ) + +def get_hardware_revision(): + """ + Returns the Pi's hardware revision number. + """ + with open('/proc/cpuinfo', 'r') as f: + for line in f.readlines(): + if 'Revision' in line: + REV = line.split(':')[1] + REV = REV.strip() # Revision as string + return int(REV, base=16) + +def main(): + global TYPE, rev + rev = get_hardware_revision() + + if(rev & 0x800000): # New Style + TYPE = (rev&0x00000FF0)>>4 + else: # Old Style + rev &= 0x1F + MM = [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 6, 2, 3, 6, 2] + TYPE = MM[rev] # Map Old Style revision to TYPE + + print_gpio(pin_state) + +if __name__ == '__main__': + main() + diff --git a/test-output.py b/test-output.py new file mode 100755 index 0000000..0e1b6d8 --- /dev/null +++ b/test-output.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +import config +import adafruit_max31855 +import digitalio +import time +import datetime + +######################################################################## +# +# To test your output... +# +# Edit config.py and set the following in that file to match your +# hardware setup: GPIO_HEAT +# +# then run this script... +# +# ./test-output.py +# +# This will switch the output on for five seconds and then off for five +# seconds. Measure the voltage between the output and any ground pin. +######################################################################## + +heater = digitalio.DigitalInOut(config.gpio_heat) +heater.direction = digitalio.Direction.OUTPUT + +print("\nheater configured as config.gpio_heat = %s BCM pin\n" % (config.gpio_heat)) + +while True: + heater.value = True + print("%s heater on" % datetime.datetime.now()) + time.sleep(5) + heater.value = False + print("%s heater off" % datetime.datetime.now()) + time.sleep(5) diff --git a/test-thermocouple.py b/test-thermocouple.py new file mode 100755 index 0000000..96902a9 --- /dev/null +++ b/test-thermocouple.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +import config +import adafruit_max31855 +from digitalio import DigitalInOut +import time +import datetime +import busio + +######################################################################## +# +# To test your thermocouple... +# +# Edit config.py and set the following in that file to match your +# hardware setup: SPI_SCLK, SPI_MOSI, SPI_MISO, SPI_CS +# +# then run this script... +# +# ./test-thermocouple.py +# +# It will output a temperature in degrees every second. Touch your +# thermocouple to heat it up and make sure the value changes. Accuracy +# of my thermocouple is .25C. +######################################################################## + +spi = busio.SPI(config.spi_sclk, config.spi_mosi, config.spi_miso) +cs = DigitalInOut(config.spi_cs) +sensor = adafruit_max31855.MAX31855(spi, cs) + +print("\nSPI configured as:\n") +print(" config.spi_sclk = %s BCM pin" % (config.spi_sclk)); +print(" config.spi_mosi = %s BCM pin" % (config.spi_mosi)); +print(" config.spi_miso = %s BCM pin" % (config.spi_miso)); +print(" config.spi_cs = %s BCM pin\n" % (config.spi_cs)); + +while(True): + time.sleep(1) + temp = sensor.temperature + scale = "C" + if config.temp_scale == "f": + temp = temp * (9/5) + 32 + scale ="F" + print("%s %0.2f%s" %(datetime.datetime.now(),temp,scale))