From 9b997b83487bb64ae2bdca5beebd0cf7210b2737 Mon Sep 17 00:00:00 2001 From: jens Date: Mon, 18 Oct 2021 14:32:56 +0200 Subject: [PATCH] - generalized heaters --- components/actor/heater_hendi.py | 7 ++++-- components/actor/heater_sim.py | 8 +++++-- components/actor/hendiCtrl.py | 15 ++++++++----- components/aheater.py | 4 ++++ tasks/heater.py | 38 +++++++++++++++++++++++--------- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/components/actor/heater_hendi.py b/components/actor/heater_hendi.py index a634dac..df96fa7 100644 --- a/components/actor/heater_hendi.py +++ b/components/actor/heater_hendi.py @@ -10,13 +10,16 @@ class HeaterHendi(AHeater): self.power_eff = 0 def get_power_min(self): - caps = self.hendi.getCapabilties() - return caps['pwr_watts_min'] + return 0 def get_power_max(self): caps = self.hendi.getCapabilties() return caps['pwr_watts_max'] + def get_powers(self): + caps = self.hendi.getCapabilties() + return [0].extend(caps['pwr_list']) + def activate(self, enable): if enable: self.hendi.remoteEnable(1) diff --git a/components/actor/heater_sim.py b/components/actor/heater_sim.py index 1fddc82..0e438a4 100644 --- a/components/actor/heater_sim.py +++ b/components/actor/heater_sim.py @@ -6,12 +6,16 @@ class HeaterSim(AHeater): AHeater.__init__(self) self.power_set = 0 self.power_eff = 0 + self.powers = [0, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400, 3500] def get_power_min(self): - return 500 + return self.powers[0] def get_power_max(self): - return 3500 + return self.powers[-1] + + def get_powers(self): + return self.powers def process(self): power = 100*round(self.power_set/100, 0) diff --git a/components/actor/hendiCtrl.py b/components/actor/hendiCtrl.py index c78d56f..0c2c194 100644 --- a/components/actor/hendiCtrl.py +++ b/components/actor/hendiCtrl.py @@ -18,17 +18,20 @@ class HendiCtrl: self.ser.timeout = 1.000 self.prompt = b':' + + powers = [500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,3400, 3500] + digits = [4092, 3840, 3700, 3440, 3300, 3060, 3000, 2930, 2860, 2780, 2640, 2510, 2430, 2360, 2190, 2130, 2030, 1980, 1880, 1730, 1630, 1560, 1480, 1400, 1240, 1150, 1150, 1080, 920, 740, 670] self.caps = { "sw_id" : self.getSoftwareIdentifier(), "sw_ver" : self.getSoftwareVersion(), - "pwr_watts_min" : 500, - "pwr_watts_max" : 3500, + "pwr_watts_min" : powers[0], + "pwr_watts_max" : powers[-1], + "pwr_list" : powers, "pwr_watts_step" : 100, - "pwr_digits_min" : 4092, - "pwr_digits_max" : 670 + "pwr_digits_min" : digits[0], + "pwr_digits_max" : digits[-1], + "digit_list" : digits } - powers = [ 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,3400, 3500] - digits = [4092, 3840, 3700, 3440, 3300, 3060, 3000, 2930, 2860, 2780, 2640, 2510, 2430, 2360, 2190, 2130, 2030, 1980, 1880, 1730, 1630, 1560, 1480, 1400, 1240, 1150, 1150, 1080, 920, 740, 670] self.poly_w2d = np.polyfit(powers, digits, 5) self.poly_d2w = np.polyfit(digits, powers, 5) self.sw_id = self.getSoftwareIdentifier() diff --git a/components/aheater.py b/components/aheater.py index 427187c..a3ced03 100644 --- a/components/aheater.py +++ b/components/aheater.py @@ -16,6 +16,10 @@ class AHeater(AttributeChange): def get_power_max(self): pass + @abc.abstractmethod + def get_powers(self): + pass + @contextmanager def open(self): try: diff --git a/tasks/heater.py b/tasks/heater.py index ae3d9f4..7a7f58c 100755 --- a/tasks/heater.py +++ b/tasks/heater.py @@ -34,6 +34,20 @@ class HeaterTask(ATask): async def send(self, data): await self.msg_handler.send(data) + def get_next_smaller_power(self, power): + result = self.device.get_power_min() + p_list = [p for p in self.device.get_powers() if p <= power] + if len(p_list) > 0: + result = p_list[-1] + return result + + def get_next_greater_power(self, power): + result = self.device.get_power_min() + p_list = [p for p in self.device.get_powers() if p > power] + if len(p_list) > 0: + result = p_list[0] + return result + async def on_process(self): print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval)) await self.send({'Capabilities': {'Power': {'Min': 0, 'Max': self.device.get_power_max()}}}) @@ -45,22 +59,26 @@ class HeaterTask(ATask): with self.device.open(): while True: + # Combine power set from different sources power_soll = max(self.power_soll, self.power_actor) - on_count = pulse_period_count - if self.device.get_power_min() > 0: - on_count = pulse_period_count*min(1, power_soll / self.device.get_power_min()) + + # Calculate duty cycle + power_low = self.get_next_smaller_power(power_soll) + power_high = self.get_next_greater_power(power_soll) + power_step = power_high - power_low + power_diff = power_soll - power_low + duty = power_diff / power_step + + on_count = pulse_period_count*duty self.pulse_counter += 1 if self.pulse_counter >= pulse_period_count: self.pulse_counter = 0 - if power_soll < self.device.get_power_min(): - if power_soll == 0 or self.pulse_counter >= on_count: - self.device.set_power(0) - elif self.pulse_counter < on_count: - self.device.set_power(self.device.get_power_min()) - else: - self.device.set_power(power_soll) + if power_soll == 0 or self.pulse_counter >= on_count: + self.device.set_power(power_low) + elif self.pulse_counter < on_count: + self.device.set_power(power_high) self.device.process() await asyncio.sleep(self.interval)