Moin!
Danke für die motivierende Wörte.
Da ch noch auf paar Equipemntteile warte, habe ich inzwischen für die geplante Applikation ein Protytyp der Software-Basis geschrieben. Neben Demo-Sensor, welchen ich für Testzwecke nutze, ist aktuell der interne Pico Temperatursensor und HC-HR501 über json-Datei konfigurierbar. Sicherlich gibt es im Quellcode noch paar Fehler, aber für diese Phase reicht erstmal für mich.
Als nächstes plane ich die Kommunikation über Modbus zu implementieren und dann weitere Sensoren… soweit ich was zusammengelöttet bekomme 
Falls keine Interesse an dem Quellcode gibt, werde ich das Forum natürlich nicht noch mal vermüllen.
Datei: config.json
{
"system" : {
"loop_time": "1.0"
},
"board": {
"name": "Steckbrett",
"location": "Labor",
"device": {
"model": "breadboard"
},
"microcontroller": {
"name": "Raspberry Pico 2",
"location": "Steckbrett",
"device" : {
"model": "PICO2",
"pinout": {
"22":{
"$ref": "#/board/sensors/3/device/pinout/2",
"logical_pin": 17,
"desc": "GP17"
}
}
}
},
"sensors": {
"1": {
"disable": "yes",
"device" : {
"model": "DEMO"
},
"name": "Demo-Sensor",
"location": "Demo-Raum"
},
"2": {
"device": {
"model": "RP2050"
},
"name": "Pico Temperatur",
"location": "pico2 chip"
},
"3": {
"disable": "yes",
"device": {
"model": "HC-SR501",
"pinout": {
"1":{
"desc": "VCC"
},
"2":{
"$ref": "#/board/microcontroller/device/pinout/22",
"function" : "out_pin",
"logical_pin" : "17",
"desc": "OUT"
},
"3":{
"desc": "GND"
}
}
},
"name": "Präsenz im Raum",
"location": "Steckbrett GP17"
}
}
}
}
Datei main.py
from bootloader import Bootloader, ShutdownException, RebootException
system = None
def start() -> None:
try:
system = Bootloader()
system.start()
except ShutdownException as e:
print('The system is shutting down...')
except RebootException as e:
print('The system is restarting...')
system = None
system = Bootloader()
system.start()
else:
print('The system is up.')
finally:
print('The system is down.')
start()
Datei bootloader.py
import devices
import json
import time
import re
class ShutdownException(Exception):
pass
class RebootException(Exception):
pass
class Bootloader:
config_path : str
board : devices.Board
def __init__(self, config_path : str = "./config.json") -> None:
self.config_path = config_path
def _read_config(self) -> None:
with open(self.config_path) as f:
self.config = json.load(f)
def _create_port(self, number : str, json_data) -> devices.Port:
lp = -1
if "logical_pin" in json_data:
lp = int(json_data["logical_pin"])
func = ''
if "function" in json_data:
func = json_data["function"]
dsc = ''
if "desc" in json_data:
dsc = json_data["desc"]
return devices.Port(physical_pin=int(number), logical_pin=lp, function=func, desc=dsc)
def _create_pinout(self, json_data) -> devices.Pinout:
pinout = devices.Pinout()
for key, value in json_data.items():
pinout.add_port(self._create_port(key, value))
return pinout
def _create_device(self, json_data) -> devices.Device:
device = devices.Device(model=json_data["model"])
for k, v in json_data.items():
if k == "pinout":
device.set_pinout(self._create_pinout(v))
break
return device
def _create_microcontroller(self, json_data) -> devices.Microcontroller:
microcontroller = devices.Microcontroller(name=json_data["name"], location=json_data["location"])
microcontroller.set_device(self._create_device(json_data["device"]))
return microcontroller
def _create_sensor(self, json_data) -> devices.Sensor:
d = self._create_device(json_data["device"])
args = ''
if "pinout" in json_data["device"]:
args = d.get_pinout().get_functions()
sensor_class = 'devices.'+re.sub('[^a-z0-9]', '', json_data["device"]["model"].lower())+'('+args+')'
sensor = eval(sensor_class)
sensor.set_name(json_data["name"])
sensor.set_location(json_data["location"])
sensor.set_device(d)
return sensor
def _create_board(self, json_data) -> devices.Board:
board = devices.Board(name=json_data["name"], location=json_data["location"])
board.set_device(self._create_device(json_data["device"]))
for id, v in json_data["sensors"].items():
if 'disable' in v and v["disable"] == "yes":
continue
else:
board.add_sensor(self._create_sensor(v))
return board
def _run(self) -> None:
loop_time = float(self.config["system"]["loop_time"])
self.board = self._create_board(self.config["board"])
while True:
self.board.print_info()
time.sleep(loop_time)
def start(self) -> None:
self._read_config()
self._run()
def shutdown(self) -> None:
raise ShutdownException("Hard system shutdown.")
def reboot(self) -> None:
raise RebootException("System reboot.")
Datei: devices.py
from machine import ADC, Pin
from random import uniform, choice, randint
import time
class Port:
physical_pin : int # e.g. by pico2 21
logical_pin: int # e.g. by pico2 16
desc : str # e.g. by pico2 GP16
function : str
def __init__(self, physical_pin : int, logical_pin : int, function : str = '', desc = '') -> None:
self.physical_pin = physical_pin
self.logical_pin = logical_pin
self.desc = desc
self.function = function
def has_function(self) -> bool:
if len(self.function) > 0:
return True
return False
def get_function(self) -> str:
return self.function
def get_logical_pin(self) -> int:
return self.logical_pin
class Pinout:
pins : list[Port] = []
def __init__(self) -> None:
pass
def add_port(self, port : Port):
self.pins.append(port)
def get_functions(self) -> str:
args = ''
c = 0
for port in self.pins:
if port.has_function():
a = port.get_function() + ' = ' + str(port.get_logical_pin())
c = c + 1
if c > 1:
args = args + ', ' + a
args = a
return args
class Device:
model : str
pinout : Pinout
def __init__(self, model : str) -> None:
self.model = model
def SerialNum(self) -> int:
return hash(self)
def set_pinout(self, pinout : Pinout):
self.pinout = pinout
def get_pinout(self) -> Pinout:
return self.pinout
# --------------------------------------------------------------------------- #
# ----- MICROCONTROLLERS ----- #
# --------------------------------------------------------------------------- #
class Microcontroller:
name : str
location : str
def __init__(self, name : str, location : str) -> None:
self.name = name
self.location = location
def set_device(self, device : Device) -> None:
self.device = device
# --------------------------------------------------------------------------- #
# ---------- SENSORS --------- #
# --------------------------------------------------------------------------- #
class Sensor:
name : str
location : str
device : Device
def set_device(self, device: Device) -> None:
self.device = device
def set_name(self, name: str) -> None:
self.name = name
def set_location(self, location: str) -> None:
self.location = location
class Temperature:
def get_temperature(self) -> float:
return 0.0
class Presence:
def get_presence(self) -> bool:
return False
# return timestamp of last detection
def get_presence_time(self) -> int:
return 0
# return tuple timestamp of last detection and presence state
def get_presence_info(self) -> list:
return [0, False]
class demo(Sensor, Temperature, Presence):
def __init__(self) -> None:
super().__init__()
self.device = Device('DEMO-DEVICE')
self.name = 'demo sensor'
self.location = 'demo'
def get_temperature(self) -> float:
lower = -40.00
upper = 180.00
return round(uniform(lower, upper), 2)
def get_presence(self) -> bool:
sequence = [True, False]
return choice(sequence)
def get_presence_time(self) -> int:
lower = time.time() - 120
upper = time.time() - 10
return randint(lower, upper)
def get_presence_info(self) -> list:
return [self.get_presence_time(), self.get_presence()]
def __str__(self) -> str:
s = "\t/"+self.location+"/"+self.device.model+"/"+self.name+"/temperature/"+str(self.get_temperature())
s = s+'\n\t'+"/"+self.location+"/"+self.device.model+"/"+self.name+"/presence/"+str(self.get_presence())+"/time/"+str(self.get_presence_time())
return s
class rp2050(Sensor, Temperature):
sensor : ADC
def __init__(self) -> None:
adc_pin = 4 # internal temperature sensor in RP2050 chip
self.sensor = ADC(adc_pin)
self.device = Device('RP2050')
self.name = 'pico internal'
self.location = 'onboard'
def get_temperature(self) -> float:
adc_value = self.sensor.read_u16()
volt = (3.3/65535)*adc_value
temperature = 27 - (volt - 0.706)/0.001721
return round(temperature, 2)
def __str__(self) -> str:
return "\t/"+self.location+"/"+self.device.model+"/"+self.name+"/temperature/"+str(self.get_temperature())
class hcsr501(Sensor, Presence):
motion_detected : bool = False
detection_timestamp : int = 0
gpio_pin : Pin
def _callback(self, *args) -> None:
self.detection_timestamp = time.time()
if self.gpio_pin.value() == 1: # motion detected
self.motion_detected = True
else:
self.motion_detected = False
def __init__(self, out_pin : int) -> None:
if out_pin == 16:
raise ValueError('pin.irq no support this GPIO pin:', out_pin)
else:
self.gpio_pin = Pin(out_pin, Pin.IN)
self.gpio_pin.irq(trigger=(Pin.IRQ_RISING | Pin.IRQ_FALLING), handler=self._callback)
self.device = Device('HC-SR501')
self.name = 'PIR'
self.location = 'somewhere'
def get_presence(self) -> bool:
return self.motion_detected
def get_presence_time(self) -> int:
return self.detection_timestamp
def get_presence_info(self) -> list:
return [self.detection_timestamp, self.motion_detected]
def __str__(self) -> str:
return "\t/"+self.location+"/"+self.device.model+"/"+self.name+"/presence/"+str(self.get_presence())+"/time/"+str(self.get_presence_time())
# --------------------------------------------------------------------------- #
# ---------- BOARDS ---------- #
# --------------------------------------------------------------------------- #
class Board:
name : str
location : str
sensors : list[Sensor]
def __init__(self, name : str, location : str) -> None:
self.name = name
self.location = location
self.sensors = []
def add_sensor(self, sensor : Sensor) -> None:
self.sensors.append(sensor)
def set_device(self, device : Device) -> None:
self.device = device
def set_microcontroller(self, microcontroller : Device) -> None:
self.microcontroller = microcontroller
def __str__(self) -> str:
return "\ninfo/"+self.location+"/"+self.name
def print_info(self) -> None:
if self.sensors.count == 0:
print("board have not any sensors")
return
print(str(self))
for s in self.sensors:
print(str(s))
Beispiel Ausgebe:
Viele Grüße
Bauherr