-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from Honey-Pi/develop
v0.1.0 release
- Loading branch information
Showing
50 changed files
with
1,377 additions
and
974 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
#!/usr/bin/python | ||
import RPi.GPIO as GPIO | ||
|
||
class MAX31855(object): | ||
'''Python driver for [MAX38155 Cold-Junction Compensated Thermocouple-to-Digital Converter](http://www.maximintegrated.com/datasheet/index.mvp/id/7273) | ||
Requires: | ||
- The [GPIO Library](https://code.google.com/p/raspberry-gpio-python/) (Already on most Raspberry Pi OS builds) | ||
- A [Raspberry Pi](http://www.raspberrypi.org/) | ||
''' | ||
def __init__(self, cs_pin, clock_pin, data_pin, units = "c", board = GPIO.BCM): | ||
'''Initialize Soft (Bitbang) SPI bus | ||
Parameters: | ||
- cs_pin: Chip Select (CS) / Slave Select (SS) pin (Any GPIO) | ||
- clock_pin: Clock (SCLK / SCK) pin (Any GPIO) | ||
- data_pin: Data input (SO / MOSI) pin (Any GPIO) | ||
- units: (optional) unit of measurement to return. ("c" (default) | "k" | "f") | ||
- board: (optional) pin numbering method as per RPi.GPIO library (GPIO.BCM (default) | GPIO.BOARD) | ||
''' | ||
self.cs_pin = cs_pin | ||
self.clock_pin = clock_pin | ||
self.data_pin = data_pin | ||
self.units = units | ||
self.data = None | ||
self.board = board | ||
|
||
# Initialize needed GPIO | ||
GPIO.setmode(self.board) | ||
GPIO.setup(self.cs_pin, GPIO.OUT) | ||
GPIO.setup(self.clock_pin, GPIO.OUT) | ||
GPIO.setup(self.data_pin, GPIO.IN) | ||
|
||
# Pull chip select high to make chip inactive | ||
GPIO.output(self.cs_pin, GPIO.HIGH) | ||
|
||
def get(self): | ||
'''Reads SPI bus and returns current value of thermocouple.''' | ||
self.read() | ||
self.checkErrors() | ||
return getattr(self, "to_" + self.units)(self.data_to_tc_temperature()) | ||
|
||
def get_rj(self): | ||
'''Reads SPI bus and returns current value of reference junction.''' | ||
self.read() | ||
return getattr(self, "to_" + self.units)(self.data_to_rj_temperature()) | ||
|
||
def read(self): | ||
'''Reads 32 bits of the SPI bus & stores as an integer in self.data.''' | ||
bytesin = 0 | ||
# Select the chip | ||
GPIO.output(self.cs_pin, GPIO.LOW) | ||
# Read in 32 bits | ||
for i in range(32): | ||
GPIO.output(self.clock_pin, GPIO.LOW) | ||
bytesin = bytesin << 1 | ||
if (GPIO.input(self.data_pin)): | ||
bytesin = bytesin | 1 | ||
GPIO.output(self.clock_pin, GPIO.HIGH) | ||
# Unselect the chip | ||
GPIO.output(self.cs_pin, GPIO.HIGH) | ||
# Save data | ||
self.data = bytesin | ||
|
||
def checkErrors(self, data_32 = None): | ||
'''Checks error bits to see if there are any SCV, SCG, or OC faults''' | ||
if data_32 is None: | ||
data_32 = self.data | ||
anyErrors = (data_32 & 0x10000) != 0 # Fault bit, D16 | ||
noConnection = (data_32 & 0x00000001) != 0 # OC bit, D0 | ||
shortToGround = (data_32 & 0x00000002) != 0 # SCG bit, D1 | ||
shortToVCC = (data_32 & 0x00000004) != 0 # SCV bit, D2 | ||
if anyErrors: | ||
if noConnection: | ||
raise MAX31855Error("No Connection") | ||
elif shortToGround: | ||
raise MAX31855Error("Thermocouple short to ground") | ||
elif shortToVCC: | ||
raise MAX31855Error("Thermocouple short to VCC") | ||
else: | ||
# Perhaps another SPI device is trying to send data? | ||
# Did you remember to initialize all other SPI devices? | ||
raise MAX31855Error("Unknown Error") | ||
|
||
def data_to_tc_temperature(self, data_32 = None): | ||
'''Takes an integer and returns a thermocouple temperature in celsius.''' | ||
if data_32 is None: | ||
data_32 = self.data | ||
tc_data = ((data_32 >> 18) & 0x3FFF) | ||
return self.convert_tc_data(tc_data) | ||
|
||
def data_to_rj_temperature(self, data_32 = None): | ||
'''Takes an integer and returns a reference junction temperature in celsius.''' | ||
if data_32 is None: | ||
data_32 = self.data | ||
rj_data = ((data_32 >> 4) & 0xFFF) | ||
return self.convert_rj_data(rj_data) | ||
|
||
def convert_tc_data(self, tc_data): | ||
'''Convert thermocouple data to a useful number (celsius).''' | ||
if tc_data & 0x2000: | ||
# two's compliment | ||
without_resolution = ~tc_data & 0x1FFF | ||
without_resolution += 1 | ||
without_resolution *= -1 | ||
else: | ||
without_resolution = tc_data & 0x1FFF | ||
return without_resolution * 0.25 | ||
|
||
def convert_rj_data(self, rj_data): | ||
'''Convert reference junction data to a useful number (celsius).''' | ||
if rj_data & 0x800: | ||
without_resolution = ~rj_data & 0x7FF | ||
without_resolution += 1 | ||
without_resolution *= -1 | ||
else: | ||
without_resolution = rj_data & 0x7FF | ||
return without_resolution * 0.0625 | ||
|
||
def to_c(self, celsius): | ||
'''Celsius passthrough for generic to_* method.''' | ||
return celsius | ||
|
||
def to_k(self, celsius): | ||
'''Convert celsius to kelvin.''' | ||
return celsius + 273.15 | ||
|
||
def to_f(self, celsius): | ||
'''Convert celsius to fahrenheit.''' | ||
return celsius * 9.0/5.0 + 32 | ||
|
||
def cleanup(self): | ||
'''Selective GPIO cleanup''' | ||
GPIO.setup(self.cs_pin, GPIO.IN) | ||
GPIO.setup(self.clock_pin, GPIO.IN) | ||
|
||
class MAX31855Error(Exception): | ||
def __init__(self, value): | ||
self.value = value | ||
def __str__(self): | ||
return repr(self.value) | ||
|
||
if __name__ == "__main__": | ||
|
||
# Multi-chip example | ||
import time | ||
cs_pins = [4, 17, 18, 24] | ||
clock_pin = 23 | ||
data_pin = 22 | ||
units = "f" | ||
thermocouples = [] | ||
for cs_pin in cs_pins: | ||
thermocouples.append(MAX31855(cs_pin, clock_pin, data_pin, units)) | ||
running = True | ||
while(running): | ||
try: | ||
for thermocouple in thermocouples: | ||
rj = thermocouple.get_rj() | ||
try: | ||
tc = thermocouple.get() | ||
except MAX31855Error as e: | ||
tc = "Error: "+ e.value | ||
running = False | ||
print("tc: {} and rj: {}".format(tc, rj)) | ||
time.sleep(1) | ||
except KeyboardInterrupt: | ||
running = False | ||
for thermocouple in thermocouples: | ||
thermocouple.cleanup() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#!/usr/bin/python | ||
|
||
import RPi.GPIO as GPIO | ||
import time | ||
|
||
class MAX6675(object): | ||
'''Python driver for [MAX6675 Cold-Junction Compensated Thermocouple-to-Digital Converter](http://www.adafruit.com/datasheets/MAX6675.pdf) | ||
Requires: | ||
- The [GPIO Library](https://code.google.com/p/raspberry-gpio-python/) (Already on most Raspberry Pi OS builds) | ||
- A [Raspberry Pi](http://www.raspberrypi.org/) | ||
''' | ||
def __init__(self, cs_pin, clock_pin, data_pin, units = "c", board = GPIO.BCM): | ||
'''Initialize Soft (Bitbang) SPI bus | ||
Parameters: | ||
- cs_pin: Chip Select (CS) / Slave Select (SS) pin (Any GPIO) | ||
- clock_pin: Clock (SCLK / SCK) pin (Any GPIO) | ||
- data_pin: Data input (SO / MOSI) pin (Any GPIO) | ||
- units: (optional) unit of measurement to return. ("c" (default) | "k" | "f") | ||
- board: (optional) pin numbering method as per RPi.GPIO library (GPIO.BCM (default) | GPIO.BOARD) | ||
''' | ||
self.cs_pin = cs_pin | ||
self.clock_pin = clock_pin | ||
self.data_pin = data_pin | ||
self.units = units | ||
self.data = None | ||
self.board = board | ||
|
||
# Initialize needed GPIO | ||
GPIO.setmode(self.board) | ||
GPIO.setup(self.cs_pin, GPIO.OUT) | ||
GPIO.setup(self.clock_pin, GPIO.OUT) | ||
GPIO.setup(self.data_pin, GPIO.IN) | ||
|
||
# Pull chip select high to make chip inactive | ||
GPIO.output(self.cs_pin, GPIO.HIGH) | ||
|
||
def get(self): | ||
'''Reads SPI bus and returns current value of thermocouple.''' | ||
self.read() | ||
self.checkErrors() | ||
return getattr(self, "to_" + self.units)(self.data_to_tc_temperature()) | ||
|
||
def read(self): | ||
'''Reads 16 bits of the SPI bus & stores as an integer in self.data.''' | ||
bytesin = 0 | ||
# Select the chip | ||
GPIO.output(self.cs_pin, GPIO.LOW) | ||
# Read in 16 bits | ||
for i in range(16): | ||
GPIO.output(self.clock_pin, GPIO.LOW) | ||
time.sleep(0.001) | ||
bytesin = bytesin << 1 | ||
if (GPIO.input(self.data_pin)): | ||
bytesin = bytesin | 1 | ||
GPIO.output(self.clock_pin, GPIO.HIGH) | ||
time.sleep(0.001) | ||
# Unselect the chip | ||
GPIO.output(self.cs_pin, GPIO.HIGH) | ||
# Save data | ||
self.data = bytesin | ||
|
||
def checkErrors(self, data_16 = None): | ||
'''Checks errors on bit D2''' | ||
if data_16 is None: | ||
data_16 = self.data | ||
noConnection = (data_16 & 0x4) != 0 # tc input bit, D2 | ||
|
||
if noConnection: | ||
raise MAX6675Error("No Connection") # open thermocouple | ||
|
||
def data_to_tc_temperature(self, data_16 = None): | ||
'''Takes an integer and returns a thermocouple temperature in celsius.''' | ||
if data_16 is None: | ||
data_16 = self.data | ||
# Remove bits D0-3 | ||
tc_data = ((data_16 >> 3) & 0xFFF) | ||
# 12-bit resolution | ||
return (tc_data * 0.25) | ||
|
||
def to_c(self, celsius): | ||
'''Celsius passthrough for generic to_* method.''' | ||
return celsius | ||
|
||
def to_k(self, celsius): | ||
'''Convert celsius to kelvin.''' | ||
return celsius + 273.15 | ||
|
||
def to_f(self, celsius): | ||
'''Convert celsius to fahrenheit.''' | ||
return celsius * 9.0/5.0 + 32 | ||
|
||
def cleanup(self): | ||
'''Selective GPIO cleanup''' | ||
GPIO.setup(self.cs_pin, GPIO.IN) | ||
GPIO.setup(self.clock_pin, GPIO.IN) | ||
|
||
class MAX6675Error(Exception): | ||
def __init__(self, value): | ||
self.value = value | ||
def __str__(self): | ||
return repr(self.value) | ||
|
||
if __name__ == "__main__": | ||
|
||
# default example | ||
cs_pin = 26 | ||
clock_pin = 18 | ||
data_pin = 19 | ||
units = "c" | ||
thermocouple = MAX6675(cs_pin, clock_pin, data_pin, units) | ||
running = True | ||
while(running): | ||
try: | ||
try: | ||
tc = thermocouple.get() | ||
except MAX6675Error as e: | ||
tc = "Error: "+ e.value | ||
running = False | ||
print("tc: {}".format(tc)) | ||
print(tc) | ||
time.sleep(1) | ||
except KeyboardInterrupt: | ||
running = False | ||
thermocouple.cleanup() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,2 @@ | ||
# rpi-scripts | ||
Python Scripte, die zur Datenerfassung auf der Stockwaage ausgeführt werden. | ||
|
||
|
||
# ![alt text](https://licensebuttons.net/l/by-nc-sa/3.0/de/88x31.png) | ||
Dieses Werk ist lizenziert unter einer [Creative Commons Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Deutschland Lizenz](https://creativecommons.org/licenses/by-nc-sa/3.0/de/). | ||
HoneyPi is a measuring system based on the Raspberry Pi. It is an open source framework, which allows every beekeeper to monitor his bees. The data transfer takes place to the Internet of Things platform ThingSpeak. The measurement data is collected at the apiary and visualized in apps. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.