From 67a7363225f2bac5628641bb1581d273a30b3a66 Mon Sep 17 00:00:00 2001 From: Philipp Klaus Date: Mon, 3 Feb 2020 15:19:59 +0100 Subject: [PATCH] pt100 refactoring code / improve board calibration --- .../pt100_board/pt100_config.py | 140 ++++++++++++++---- .../pt100_board/pt100_csv_readback.py | 0 sensors/pt100-board-python-package/setup.py | 0 3 files changed, 110 insertions(+), 30 deletions(-) mode change 100644 => 100755 sensors/pt100-board-python-package/pt100_board/pt100_csv_readback.py mode change 100644 => 100755 sensors/pt100-board-python-package/setup.py diff --git a/sensors/pt100-board-python-package/pt100_board/pt100_config.py b/sensors/pt100-board-python-package/pt100_board/pt100_config.py index dd65fd6..6b41879 100755 --- a/sensors/pt100-board-python-package/pt100_board/pt100_config.py +++ b/sensors/pt100-board-python-package/pt100_board/pt100_config.py @@ -3,6 +3,7 @@ import argparse import sys import time +import struct from pt100_board import PT100BoardDatagram @@ -34,6 +35,25 @@ REGISTER_NAMES = { 0xd: 'multiplex', } +default_register_values = [ + (0x0, 0x0057), # Channel configuration = 87 + (0x1, 0x0057), + (0x2, 0x0057), + (0x3, 0x0057), + (0x4, 0x0057), + (0x5, 0x0057), + (0x6, 0x0057), + (0x7, 0x0057), + (0x8, 0x0000), # nominal offset + (0x9, 0xd260), # gain*current = 53856 + (0xA, 0x00fa), # sample period 250 + (0xB, 0x0000), # lcd off + (0xC, 0x0000), # averaging over (0x1 + 1 =) 2 samples + (0xD, 0x0001), # multiplexing the channels is ON + ] + +DEFAULT_TIMEOUT = 0.1 + def parse_uint_tuple(text): return tuple(parse_uint(el) for el in text.split(',')) @@ -58,7 +78,7 @@ def main(): parser.add_argument('--reload-configuration', '-r', action='store_true', help='Reload the configuration of the board') args = parser.parse_args() - ser = serial.Serial(args.device, baudrate=38400, timeout=0.1) + ser = serial.Serial(args.device, baudrate=38400, timeout=DEFAULT_TIMEOUT) ser.read(1024) # clear input buffers when opening device... def send(cmd, verbose=True): @@ -69,6 +89,12 @@ def main(): print('Writing 0x{2:04X} = {2:d} to address 0x{1:02X} of board 0x{0:01X}'.format(board_id, address, value)) send('WE{:1X}0{:02X}{:04X}\n'.format(board_id, address, value)) + def reload(board_id): + time.sleep(.2) + send('WR{:1X}0000000\n'.format(board_id)) + ser.flush() + time.sleep(.2) + def read_eeprom(board_id, address, verbose=True): ser.read(1024) # clear input buffers before sending new command... send('WG{:1X}0{:02X}0000\n'.format(board_id, address), verbose=verbose) @@ -77,7 +103,7 @@ def main(): answer = False while (time.time() - start) < 0.99: recv = ser.readline() - if recv: + if recv and len(recv) >= 10: if verbose: print('Received answer:', recv) recv = recv.strip(b'\x00').decode('ascii').strip() if not recv.startswith('AG'): continue @@ -91,6 +117,32 @@ def main(): return val raise TimeoutError('No answer received. Old board without read eeprom support?') + def read_temperature(board_id, sensor, averages=1, timeout=10): + start = time.time() + ser.timeout = 0.001 + while (time.time() - start) < 0.5: + recv = ser.readline() + ser.timeout = DEFAULT_TIMEOUT + values = [] + start = time.time() + while (time.time() - start) < timeout: + recv = ser.readline() + if recv: + try: + dg = PT100BoardDatagram(recv) + except: + continue + if dg.kind == 'temperature' and dg.sensor == sensor and dg.connected: + values.append(dg.temperature) + if len(values) == averages: + return sum(values)/averages + if len(values) == 0: + sys.stdout.write("Didn't receive any temperature samples\n") + else: + sys.stdout.write("Didn't receive enough temperature samples ({} instead of {})\n".format(len(values), averages)) + sys.stdout.flush() + return None + if args.read_eeprom is not None: read_eeprom(args.board_id, args.read_eeprom, verbose=True) @@ -115,28 +167,13 @@ def main(): print('Do you really want to initialize the board with a new set of EEPROM configuration data?') print('Your current values will be lost!!! This only makes sense for brand new boards!') input('Press enter to continue or Ctrl-c to abort.') - new_vals = [ - (0x0, 0x0057), # Channel configuration = 87 - (0x1, 0x0057), - (0x2, 0x0057), - (0x3, 0x0057), - (0x4, 0x0057), - (0x5, 0x0057), - (0x6, 0x0057), - (0x7, 0x0057), - (0x8, 0x0000), # nominal offset - (0x9, 0xd260), # gain*current = 53856 - (0xA, 0x00fa), # sample period 250 - (0xB, 0x0000), # lcd off - (0xC, 0x0000), # averaging over (0x1 + 1 =) 2 samples - ] print("Current values of the EEPROM:") - for reg_addr, new_reg_val in new_vals: + for reg_addr, default_reg_val in default_register_values: old_reg_val = read_eeprom(args.board_id, reg_addr, verbose=False) - print("Address: 0x{:02X} Old Value: 0x{:04X} New Value: 0x{:04X}".format(reg_addr, old_reg_val, new_reg_val)) + print("Address: 0x{:02X} Old Value: 0x{:04X} New Value: 0x{:04X}".format(reg_addr, old_reg_val, default_reg_val)) input('Press enter to continue or Ctrl-c to abort.') - for reg_addr, reg_val in new_vals: - write_register(args.board_id, reg_addr, reg_val) + for reg_addr, default_reg_val in default_register_values: + write_register(args.board_id, reg_addr, default_reg_val) print("Done initializing the EEPROM") @@ -147,18 +184,61 @@ def main(): time.sleep(0.1) if args.calibrate: + print("Current values of the EEPROM:") + for reg_addr, default_reg_val in default_register_values: + old_reg_val = read_eeprom(args.board_id, reg_addr, verbose=False) + print("Address: 0x{:02X} Old Value: 0x{:04X}".format(reg_addr, old_reg_val)) + input('Press enter to continue or Ctrl-c to abort.') + print("OK, starting the calibration.") - for channel in range(8): - print("Channel", channel) - inp = input("Enter [c] to continue, anything else will skip this channel.") - if inp != 'c': - print("Skipping channel", channel) + + print("starting with default values") + # set channel offsets to zero: + for reg_addr in range(8): + write_register(args.board_id, reg_addr, 0x0000) + time.sleep(0.1) + # reset gain to default value: + write_register(args.board_id, default_register_values[0x9][0], default_register_values[0x9][1]) + reload(args.board_id) + + print("calibrating the gain") + + def calibrate_offset(board_id, sensor, averages=5): + input("Connect the 100 Ohm reference to sensor slot #{} (and wiggle the plug around to asure a good contact)! Press [Enter], when ready.".format(sensor)) + mean_temperature_before = read_temperature(board_id, sensor, averages=averages, timeout=20) + print("mean temperature before correction: {}".format(mean_temperature_before)) + offset_value = int(round( - mean_temperature_before * 396)) + tc_number = (num for num in struct.pack('>h', offset_value)) + offset_value = int('{:02X}{:02X}'.format(*tc_number), 16) + write_register(board_id, 0x00 + sensor, offset_value) + reload(args.board_id) + mean_temperature_after = read_temperature(board_id, sensor, averages=averages, timeout=20) + print("mean temperature after correction: {}".format(mean_temperature_after)) + + calibrate_offset(args.board_id, 0) + + input("Connect the 120 Ohm reference to sensor slot 0 (and wiggle the plug around to asure a good contact)! Press [Enter], when ready.") + mean_temperature_120_before = read_temperature(args.board_id, 0, averages=5, timeout=20) + print("mean temperature (120 Ohm) before correction: {}".format(mean_temperature_120_before)) + expected_value = 51.578 + new_gain = int( round( expected_value / mean_temperature_120_before * default_register_values[0x9][1] ) ) + write_register(args.board_id, default_register_values[0x9][0], new_gain) + reload(args.board_id) + mean_temperature_120_after = read_temperature(args.board_id, 0, averages=5, timeout=20) + print("mean temperature after correction: {}".format(mean_temperature_120_after)) + print("deviation from expected: {}".format(mean_temperature_120_after - expected_value)) + + print("calibrating the individual channel offsets") + for sensor in range(1, 8): + print("Sensor #", sensor) + inp = input("Enter [Enter] to continue, anything else (+ [Enter]) will skip this sensor.") + if inp != '': + print("Skipping sensor #", sensor) continue - print("Connect the 100Ohm reference!") - print("Connect the 120Ohm reference!") - print("Done with channel", channel) + calibrate_offset(args.board_id, sensor) + print("Done with sensor #", sensor) if args.reload_configuration: - send('WR{:1X}0000000\n'.format(args.board_id)) + reload(args.board_id) if __name__ == "__main__": main() diff --git a/sensors/pt100-board-python-package/pt100_board/pt100_csv_readback.py b/sensors/pt100-board-python-package/pt100_board/pt100_csv_readback.py old mode 100644 new mode 100755 diff --git a/sensors/pt100-board-python-package/setup.py b/sensors/pt100-board-python-package/setup.py old mode 100644 new mode 100755 -- 2.43.0