diff --git a/config.json b/config.json new file mode 100644 index 0000000..47ac94d --- /dev/null +++ b/config.json @@ -0,0 +1,86 @@ +{ + "sensors": { + "0":{ + "BCM": 20, + "GPIO": 20, + "header-pin": 38, + "pre-resistance": 9770.0 + }, + "1":{ + "BCM": 26, + "GPIO": 26, + "header-pin": 37, + "pre-resistance": 10000.0 + }, + "2":{ + "BCM": 19, + "GPIO": 19, + "header-pin": 35, + "pre-resistance": 10000.0 + }, + "3":{ + "BCM": 16, + "GPIO": 16, + "header-pin": 36, + "pre-resistance": 10000.0 + }, + "4":{ + "BCM": 13, + "GPIO": 13, + "header-pin": 33, + "pre-resistance": 10000.0 + }, + "5":{ + "BCM": 12, + "GPIO": 12, + "header-pin": 32, + "pre-resistance": 10000.0 + }, + "6":{ + "BCM": 6, + "GPIO": 6, + "header-pin": 31, + "pre-resistance": 10000.0 + }, + "7": { + "BCM": 5, + "GPIO": 5, + "header-pin": 29, + "pre-resistance": 10000.0 + } + }, + "sensor-defaults": { + "temperature_nominal": 25, + "resistance_nominal": 10000, + "correction_resistance": 4800 + }, + "pwm": { + "upper-fan": { + "on-off": { + "BCM": 22, + "GPIO": 22, + "header-pin": 15 + }, + "pwm": { + "BCM": 23, + "GPIO": 23, + "header-pin": 16 + } + }, + "lower-fans": { + "on-off": { + "BCM": 17, + "GPIO": 17, + "header-pin": 11 + }, + "pwm": { + "BCM": 18, + "GPIO": 18, + "header-pin": 12 + } + } + }, + "pwm-defaults":{ + "frequency": 25000 + } +} \ No newline at end of file diff --git a/src/pwm.py b/scripts/pwm.py similarity index 100% rename from src/pwm.py rename to scripts/pwm.py diff --git a/src/test.py b/scripts/test.py similarity index 100% rename from src/test.py rename to scripts/test.py diff --git a/src/config.py b/src/config.py index 5a0ce96..152c728 100644 --- a/src/config.py +++ b/src/config.py @@ -1,2 +1,40 @@ -from abc import Singleton +from singleton import Singleton +import json +import os +from lowlevel import LowLevel + +class Config(metaclass=Singleton): + def __init__(self, cwd=None): + self.__data = None + self.__cwd = None + if not self.__cwd: + self.__cwd = os.getcwd() + with open(os.path.join(self.__cwd, "config.json"), "r") as f: + self.__data = json.load(f) + pass + + def reload(self): + if not self.__cwd: + self.__cwd = os.getcwd() + with open(os.path.join(self.__cwd, "config.json"), "r") as f: + self.__data = json.load(f) + LowLevel().init() # reinitialize + + def get_data(self): + return self.__data + + def get_sensors_dict(self): + return self.__data["sensors"] + + def get_sensor_defaults(self): + return self.__data["sensor-defaults"] + + def get_pwm_defaults(self): + return self.__data["pwm-defaults"] + + def get_pwm_upper(self): + return self.__data["pwm"]["upper-fan"] + + def get_pwm_lower(self): + return self.__data["pwm"]["lower-fans"] diff --git a/src/lowlevel.py b/src/lowlevel.py new file mode 100644 index 0000000..de9afa9 --- /dev/null +++ b/src/lowlevel.py @@ -0,0 +1,71 @@ +from singleton import Singleton +import RPi.GPIO as GPIO +import spidev +from config import Config + + +class LowLevel(metaclass=Singleton): + def __init__(self): + self.__spi = spidev.SpiDev() + self.__spi.open(0, 0) + self.__spi.mode = 0 + self.__spi.max_speed_hz = 1000000 + self.__pwmu = None + self.__pwml = None + self.__cfg = Config() + self.init() + + def init(self): + GPIO.setmode(GPIO.BCM) + sensors = self.__cfg.get_sensors_dict() + for k in sensors: + GPIO.setup(sensors[k]["BCM"], GPIO.OUT) + GPIO.output(sensors[k]["BCM"], False) + ufan = self.__cfg.get_pwm_upper() + GPIO.setup(ufan["on-off"]["BCM"], GPIO.OUT) + GPIO.output(ufan["on-off"]["BCM"], False) + lfans = self.__cfg.get_pwm_lower() + GPIO.setup(lfans["on-off"]["BCM"], GPIO.OUT) + GPIO.output(lfans["on-off"]["BCM"], False) + GPIO.setup(lfans["pwm"]["BCM"], GPIO.OUT) + GPIO.setup(ufan["pwm"]["BCM"], GPIO.OUT) + self.__pwmu = GPIO.PWM(ufan["pwm"]["BCM"], self.__cfg.get_pwm_defaults()["frequency"]) + self.__pwml = GPIO.PWM(lfans["pwm"]["BCM"], self.__cfg.get_pwm_defaults()["frequency"]) + self.__pwmu.start(0) + self.__pwml.start(0) + + def __activate(self): + self.__spi.cshigh = False + + def __deactivate(self): + self.__spi.cshigh = True + + def retrieve_adc(self, channel): + if channel > 7 or channel < 0: + return None + pin = self.__cfg.get_sensors_dict()[str(channel)]["BCM"] + GPIO.output(pin, True) + hchbit = channel >> 2 + lchbits = channel & 0x03 + to_send = [hchbit | 0x06, lchbits << 6, 0x00] + self.__activate() + r=self.__spi.xfer(to_send) + self.__deactivate() + GPIO.output(pin, False) + highbyte = r[1] + lowbyte = r[2] + value = (highbyte << 8) | lowbyte + return value + + def upper_fan(self, on): + GPIO.output(self.__cfg.get_pwm_upper()["on-off"]["BCM"], on) + + def upper_fan_pwm(self, percent): + self.__pwmu.ChangeDutyCycle(percent) + + def lower_fan(self, on): + GPIO.output(self.__cfg.get_pwm_lower()["on-off"]["BCM"], on) + + def lower_fan_pwm(self, percent): + self.__pwml.ChangeDutyCycle(percent) + diff --git a/src/singleton.py b/src/singleton.py new file mode 100644 index 0000000..3776cb9 --- /dev/null +++ b/src/singleton.py @@ -0,0 +1,7 @@ +class Singleton(type): + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instances[cls] diff --git a/src/spi/spi.py b/src/spi/spi.py deleted file mode 100644 index ae55a49..0000000 --- a/src/spi/spi.py +++ /dev/null @@ -1,36 +0,0 @@ -from abc import Singleton -import RPi.GPIO as GPIO -import spidev - - -class LowLevel(metaclass=Singleton) - def __init__(self): - self.__spi = spidev.SpiDev() - self.__spi.open(0,0) - self.__spi.mode = 0 - self.__spi.max_speed_hz = 1000000 - GPIO.setmode(GPIO.BCM) - - - def __activate(self): - self.__spi.cshigh = False - - def __deactivate(self): - self.__spi.cshigh = True - - def retrieve_adc(self, channel): - if channel > 7 or channel < 0: - return None - - GPIO.output(pin, True) - hchbit=channel >> 2 - lchbits = channel & 0x03 - to_send = [ hchbit | 0x06, lchbits << 6, 0x00 ] - self.__activate() - r=spi.xfer(to_send) - self.__deactivate() - GPIO.output(pin, False) - highbyte = r[1] - lowbyte = r[2] - value = (highbyte << 8) | lowbyte - return value diff --git a/src/temperature.py b/src/temperature.py new file mode 100644 index 0000000..7baf858 --- /dev/null +++ b/src/temperature.py @@ -0,0 +1,26 @@ + + +from decimal import * +from lowlevel import LowLevel +from config import Config + +class Temperature: + def __init__(self, channel): + self.__channel = channel + self.__cfg = Config() + self.__const_resistance = self.__cfg.get_sensors_dict()[str(channel)]["pre-resistance"] + self.__nom_temp = self.__cfg.get_sensor_defaults()["temperature_nominal"] + self.__nom_resistance = self.__cfg.get_sensor_defaults()["resistance_nominal"] + self.__correction = self.__cfg.get_sensor_defaults()["correction_resistance"] + + def read(self): + ll = LowLevel() + r = (self.__const_resistance/(4095/ll.retrieve_adc(self.__channel) - 1)) + r = r - self.__correction + t = r/self.__nom_resistance + if t < 0: + t = t * -1 + t = float(Decimal(t).ln())/4050 + 1.0/(self.__nom_temp + 273.15) + t = 1/t + t = t - 273.15 + return t