]> jspc29.x-matter.uni-frankfurt.de Git - labtools.git/commitdiff
pt100 refactoring code / improve board calibration
authorPhilipp Klaus <klaus@physik.uni-frankfurt.de>
Mon, 3 Feb 2020 14:19:59 +0000 (15:19 +0100)
committerPhilipp Klaus <klaus@physik.uni-frankfurt.de>
Mon, 3 Feb 2020 14:20:42 +0000 (15:20 +0100)
sensors/pt100-board-python-package/pt100_board/pt100_config.py
sensors/pt100-board-python-package/pt100_board/pt100_csv_readback.py [changed mode: 0644->0755]
sensors/pt100-board-python-package/setup.py [changed mode: 0644->0755]

index dd65fd6ce5485fb03d074bc44262193ae3e677c8..6b418793db89775da108c54907b2646e32e1af64 100755 (executable)
@@ -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()
old mode 100644 (file)
new mode 100755 (executable)