From 20d622d3d7e35052a19d97858f2e22378fdbb2b1 Mon Sep 17 00:00:00 2001 From: su530201 <olivier.kaufmann@umons.ac.be> Date: Sat, 8 Apr 2023 16:01:55 +0200 Subject: [PATCH] Updates the rewriting of the _compute_tx_volt() method of OhmPiHardware in measure.py --- hardware/mb_2024_rev_0_0.py | 10 +- measure.py | 228 +++++++++++------------------------- 2 files changed, 74 insertions(+), 164 deletions(-) diff --git a/hardware/mb_2024_rev_0_0.py b/hardware/mb_2024_rev_0_0.py index c547165d..2f2b072e 100644 --- a/hardware/mb_2024_rev_0_0.py +++ b/hardware/mb_2024_rev_0_0.py @@ -167,6 +167,11 @@ class Tx(TxAbstract): self.exec_logger.warning(f'Sorry, cannot inject more than {TX_CONFIG["voltage_max"]} V, ' f'set it back to {TX_CONFIG["default_voltage"]} V (default value).') value = TX_CONFIG['default_voltage'] + if value < 0.: + self.exec_logger.warning(f'Voltage should be given as a positive number. ' + f'Set polarity to -1 to reverse voltage...') + value = np.abs(value) + self.DPS.write_register(0x0000, value, 2) def turn_off(self): @@ -240,5 +245,6 @@ class Rx(RxAbstract): """ u0 = AnalogIn(self.ads_voltage, ads.P0).voltage * 1000. u2 = AnalogIn(self.ads_voltage, ads.P2).voltage * 1000. - self.exec_logger.debug(f'Reading voltages {u0} V and {u2} V on RX. Returning {np.max([u0, u2])} V') - return np.max([u0,u2]) \ No newline at end of file + u = np.max([u0,u2]) * (np.heaviside(u0-u2, 1.) * 2 - 1.) # gets the max between u0 & u2 and set the sign + self.exec_logger.debug(f'Reading voltages {u0} V and {u2} V on RX. Returning {u} V') + return u \ No newline at end of file diff --git a/measure.py b/measure.py index a65fc18b..d691c2f3 100644 --- a/measure.py +++ b/measure.py @@ -1,5 +1,6 @@ import importlib from time import gmtime +import numpy as np import sys import logging from config import OHMPI_CONFIG @@ -9,13 +10,14 @@ rx_module = importlib.import_module(f'{OHMPI_CONFIG["hardware"]["rx"]["model"]}' mux_module = importlib.import_module(f'{OHMPI_CONFIG["hardware"]["mux"]["model"]}') TX_CONFIG = tx_module.TX_CONFIG RX_CONFIG = rx_module.RX_CONFIG +MUX_CONFIG = mux_module.MUX_CONFIG -class OhmPiHardware(): +current_max = np.min([TX_CONFIG['current_max'], MUX_CONFIG['current_max']]) +voltage_max = np.min([TX_CONFIG['voltage_max'], MUX_CONFIG['voltage_max']]) +voltage_min = RX_CONFIG['voltage_min'] + +class OhmPiHardware: def __init__(self, **kwargs): - self.tx = kwargs.pop('controller', tx_module.Controller()) - self.rx = kwargs.pop('tx', tx_module.Rx()) - self.tx = kwargs.pop('rx', tx_module.Tx()) - self.rx = kwargs.pop('mux', tx_module.Mux()) self.exec_logger = kwargs.pop('exec_logger', None) self.data_logger = kwargs.pop('exec_logger', None) self.soh_logger = kwargs.pop('soh_logger', None) @@ -49,8 +51,35 @@ class OhmPiHardware(): soh_handler.setFormatter(soh_formatter) self.soh_logger.addHandler(soh_handler) self.soh_logger.setLevel('debug') - - def _compute_tx_volt(self, best_tx_injtime=0.1, strategy='vmax', tx_volt=5): + self.controller = kwargs.pop('controller', + controller_module.Controller({'exec_logger' : self.exec_logger, + 'data_logger': self.data_logger, + 'soh_logger': self.soh_logger})) + self.rx = kwargs.pop('tx', tx_module.Rx({'exec_logger' : self.exec_logger, + 'data_logger': self.data_logger, + 'soh_logger': self.soh_logger})) + self.tx = kwargs.pop('rx', tx_module.Tx({'exec_logger' : self.exec_logger, + 'data_logger': self.data_logger, + 'soh_logger': self.soh_logger})) + self.mux = kwargs.pop('mux', mux_module.Mux({'exec_logger' : self.exec_logger, + 'data_logger': self.data_logger, + 'soh_logger': self.soh_logger})) + def _vab_pulse(self, vab, length, polarity=None): + """ Gets VMN and IAB from a single voltage pulse + """ + if polarity is not None and polarity != self.tx.polarity: + self.tx.polarity = polarity + self.tx.voltage = vab + self.tx.voltage_pulse(length=length) + # set gains automatically + self.tx.adc_gain_auto() + self.rx.adc_gain_auto() + iab = self.tx.current # measure current + vmn = self.rx.voltage + return vmn, iab + + def _compute_tx_volt(self, best_tx_injtime=0.1, strategy='vmax', tx_volt=5, + vab_max=voltage_max, vmn_min=voltage_min): """Estimates best Tx voltage based on different strategies. At first a half-cycle is made for a short duration with a fixed known voltage. This gives us Iab and Rab. We also measure Vmn. @@ -68,177 +97,52 @@ class OhmPiHardware(): Time in milliseconds for the half-cycle used to compute Rab. strategy : str, optional Either: - - vmax : compute Vab to reach a maximum Iab and Vmn + - vmax : compute Vab to reach a maximum Iab without exceeding vab_max + - vmin : compute Vab to reach at least vmn_min - constant : apply given Vab tx_volt : float, optional Voltage to apply for guessing the best voltage. 5 V applied by default. If strategy "constant" is chosen, constant voltage to applied is "tx_volt". + vab_max : float, optional + Maximum injection voltage to apply to tx (used by all strategies) + vmn_min : float, optional + Minimum voltage target for rx (used by vmin strategy) Returns ------- vab : float Proposed Vab according to the given strategy. - polarity : int - Either 1 or -1 to know on which pin of the ADS the Vmn is measured. + polarity: + Polarity of VMN relative to polarity of VAB + rab : float + Resistance between injection electrodes """ - + vab_max = np.abs(vab_max) + vmn_min = np.abs(vmn_min) + vab = np.min(np.abs(tx_volt), vab_max) self.tx.polarity = 1 self.tx.turn_on() - if strategy == 'constant': - vab = tx_volt - self.tx.voltage = vab - self.tx.voltage_pulse(length=best_tx_injtime) - # set gains automatically - self.tx.adc_gain_auto() - self.rx.adc_gain_auto() - I = self.tx.current # measure current - vmn = self.rx.voltage - - elif strategy == 'vmax': - """ + vmn, iab = self._vab_pulse(vab=vab, length=best_tx_injtime) + if strategy == 'vmax': # implement different strategies - I = 0 - vmn = 0 - count = 0 - while I < TX_CONFIG['current_max'] or abs(vmn) < RX_CONFIG['?']: # TODO: hardware related - place in config - - if count > 0: - # print('o', volt) - volt = volt + 2 - # print('>', volt) - count = count + 1 - if volt > 50: - break - - # set voltage for test - if count == 1: - self.DPS.write_register(0x09, 1) # DPS5005 on - time.sleep(best_tx_injtime) # inject for given tx time - self.DPS.write_register(0x0000, volt, 2) - # autogain - self.ads_current = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=860, address=self.ads_current_address) - self.ads_voltage = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=860, address=self.ads_voltage_address) - gain_current = self._gain_auto(AnalogIn(self.ads_current, ads.P0)) - gain_voltage0 = self._gain_auto(AnalogIn(self.ads_voltage, ads.P0)) - gain_voltage2 = self._gain_auto(AnalogIn(self.ads_voltage, ads.P2)) - gain_voltage = np.min([gain_voltage0, gain_voltage2]) # TODO: separate gain for P0 and P2 - self.ads_current = ads.ADS1115(self.i2c, gain=gain_current, data_rate=860, address=self.ads_current_address) - self.ads_voltage = ads.ADS1115(self.i2c, gain=gain_voltage, data_rate=860, address=self.ads_voltage_address) - # we measure the voltage on both A0 and A2 to guess the polarity - for i in range(10): - I = AnalogIn(self.ads_current, ads.P0).voltage * 1000. / 50 / self.r_shunt # noqa measure current - U0 = AnalogIn(self.ads_voltage, ads.P0).voltage * 1000. # noqa measure voltage - U2 = AnalogIn(self.ads_voltage, ads.P2).voltage * 1000. # noqa - time.sleep(best_tx_injtime) - - # check polarity - polarity = 1 # by default, we guessed it right - vmn = U0 - if U0 < 0: # we guessed it wrong, let's use a correction factor - polarity = -1 - vmn = U2 - - n = 0 - while ( - abs(vmn) > voltage_max or I > current_max) and volt > 0: # If starting voltage is too high, need to lower it down - # print('we are out of range! so decreasing volt') - volt = volt - 2 - self.DPS.write_register(0x0000, volt, 2) - # self.DPS.write_register(0x09, 1) # DPS5005 on - I = AnalogIn(self.ads_current, ads.P0).voltage * 1000. / 50 / self.r_shunt - U0 = AnalogIn(self.ads_voltage, ads.P0).voltage * 1000. - U2 = AnalogIn(self.ads_voltage, ads.P2).voltage * 1000. - polarity = 1 # by default, we guessed it right - vmn = U0 - if U0 < 0: # we guessed it wrong, let's use a correction factor - polarity = -1 - vmn = U2 - n += 1 - if n > 25: - break - - factor_I = (current_max) / I - factor_vmn = voltage_max / vmn - factor = factor_I - if factor_I > factor_vmn: - factor = factor_vmn - # print('factor', factor_I, factor_vmn) - vab = factor * volt * 0.9 - if vab > tx_max: - vab = tx_max - print(factor_I, factor_vmn, 'factor!!')""" - pass - + if vab < vab_max and iab < current_max : + vab = vab * np.min([0.9 * vab_max / vab, 0.9 * current_max / iab]) # TODO: check if setting at 90% of max as a safety margin is OK + self.tx.exec_logger.debug(f'vmax strategy: setting VAB to {vab} V.') elif strategy == 'vmin': - """# implement different strategy - I = 20 - vmn = 400 - count = 0 - while I > 10 or abs(vmn) > 300: # TODO: hardware related - place in config - if count > 0: - volt = volt - 2 - print(volt, count) - count = count + 1 - if volt > 50: - break - - # set voltage for test - self.DPS.write_register(0x0000, volt, 2) - if count == 1: - self.DPS.write_register(0x09, 1) # DPS5005 on - time.sleep(best_tx_injtime) # inject for given tx time - - # autogain - self.ads_current = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=860, address=self.ads_current_address) - self.ads_voltage = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=860, address=self.ads_voltage_address) - gain_current = self._gain_auto(AnalogIn(self.ads_current, ads.P0)) - gain_voltage0 = self._gain_auto(AnalogIn(self.ads_voltage, ads.P0)) - gain_voltage2 = self._gain_auto(AnalogIn(self.ads_voltage, ads.P2)) - gain_voltage = np.min([gain_voltage0, gain_voltage2]) # TODO: separate gain for P0 and P2 - self.ads_current = ads.ADS1115(self.i2c, gain=gain_current, data_rate=860, address=self.ads_current_address) - self.ads_voltage = ads.ADS1115(self.i2c, gain=gain_voltage, data_rate=860, address=self.ads_voltage_address) - # we measure the voltage on both A0 and A2 to guess the polarity - I = AnalogIn(self.ads_current, ads.P0).voltage * 1000. / 50 / self.r_shunt # noqa measure current - U0 = AnalogIn(self.ads_voltage, ads.P0).voltage * 1000. # noqa measure voltage - U2 = AnalogIn(self.ads_voltage, ads.P2).voltage * 1000. # noqa - - # check polarity - polarity = 1 # by default, we guessed it right - vmn = U0 - if U0 < 0: # we guessed it wrong, let's use a correction factor - polarity = -1 - vmn = U2 - - n = 0 - while ( - abs(vmn) < voltage_min or I < current_min) and volt > 0: # If starting voltage is too high, need to lower it down - # print('we are out of range! so increasing volt') - volt = volt + 2 - print(volt) - self.DPS.write_register(0x0000, volt, 2) - # self.DPS.write_register(0x09, 1) # DPS5005 on - # time.sleep(best_tx_injtime) - I = AnalogIn(self.ads_current, ads.P0).voltage * 1000. / 50 / self.r_shunt - U0 = AnalogIn(self.ads_voltage, ads.P0).voltage * 1000. - U2 = AnalogIn(self.ads_voltage, ads.P2).voltage * 1000. - polarity = 1 # by default, we guessed it right - vmn = U0 - if U0 < 0: # we guessed it wrong, let's use a correction factor - polarity = -1 - vmn = U2 - n += 1 - if n > 25: - break - - vab = volt""" - pass - + if vab < vab_max and iab < current_max: + vab = vab * np.min([0.9 * vab_max / vab, vmn_min / np.abs(vmn), 0.9 * current_max / iab]) # TODO: check if setting at 90% of max as a safety margin is OK + elif strategy != 'constant': + self.tx.exec_logger.warning(f'Unknown strategy {strategy} for setting VAB! Using {vab} V') + else: + self.tx.exec_logger.debug(f'Constant strategy for setting VAB, using {vab} V') self.tx.turn_off() self.tx.polarity = 0 - rab = (vab * 1000.) / I # noqa - + rab = (np.abs(vab) * 1000.) / iab self.exec_logger.debug(f'RAB = {rab:.2f} Ohms') - - return vab, rab \ No newline at end of file + if vmn < 0: + polarity = -1 # TODO: check if we really need to return polarity + else: + polarity = 1 + return vab, polarity, rab \ No newline at end of file -- GitLab