Skip to content
Snippets Groups Projects

NTC Readout with BDAQ board

Merged Ghost User requested to merge bdaq_ntc into development
All threads resolved!
Files
11
+ 107
10
@@ -9,6 +9,7 @@ import yaml
import logging
import os
import time
import math
import struct
import coloredlogs
import numpy as np
@@ -77,15 +78,17 @@ class BDAQ53(Dut):
def __init__(self, conf=None, bench_config=None):
self.proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
self.configuration = {}
try:
if bench_config is None:
bench_config = os.path.join(self.proj_dir, 'bdaq53' + os.sep + 'testbench.yaml')
with open(bench_config) as f:
self.configuration['bench'] = yaml.full_load(f)
self.configuration = yaml.full_load(f)
except TypeError:
self.configuration['bench'] = bench_config
self.configuration = bench_config
# Calibration settings, e.g. resistor values for NTC readout on BDAQ board
self.calibration = self.configuration.pop('calibration', {})
if not conf:
conf = os.path.join(self.proj_dir, 'bdaq53' + os.sep + 'bdaq53.yaml')
@@ -126,8 +129,14 @@ class BDAQ53(Dut):
self['cmd'].reset()
time.sleep(0.1)
# Wait for the chip (model) PLL to lock before establishing a link
if self.board_version == 'SIMULATION':
for _ in range(100):
self['rx'].get_rx_ready()
# Configure the Aurora link
self.wait_for_pll_lock()
self.setup_aurora()
self.print_powered_dp_connectors()
@@ -295,32 +304,120 @@ class BDAQ53(Dut):
return round(T_ntc, 3)
def get_temperature_NTC(self):
def _bdaq_set_NTC_MUX(self, connector=0):
'''
Sets the NTC readout route on the BDAQ board
'''
_BDAQ_ntc_mux_map = {
# Connector ID: MUX channel
0: 2, # DP1 (DP connector '1')
1: 3, # DP3 (DP connector '2')
2: 4, # DP4 (DP connector '3')
3: 5, # DP5 (DP connector '4')
4: 7, # DP2 (DP connector '5', hitor)
5: 6, # mDP (miniDP connector)
6: 0, # NTC_RJ45_A
7: 1 # NTC_RJ45_B
}
self['BDAQ_CONTROL']['NTC_MUX'] = _BDAQ_ntc_mux_map[connector]
self['BDAQ_CONTROL'].write()
logger.debug('Set NTC_MUX to %s', _BDAQ_ntc_mux_map[connector])
time.sleep(0.001)
def _bdaq_get_temperature_NTC(self, connector=0, NTC_type='TDK_NTCG163JF103FT1'):
if not self.configuration['enable_NTC']:
return 99.
if NTC_type == 'TDK_NTCG16H' or 'TDK_NTCG163JF103FT1':
R_RATIO = np.array([18.85, 14.429, 11.133, 8.656, 6.779, 5.346, 4.245, 3.393, 2.728, 2.207, 1.796, 1.47, 1.209, 1.0, 0.831, 0.694, 0.583, 0.491, 0.416, 0.354, 0.302, 0.259, 0.223, 0.192, 0.167, 0.145, 0.127, 0.111, 0.0975, 0.086, 0.076, 0.0674, 0.0599, 0.0534])
B_CONST = np.array([3140, 3159, 3176, 3194, 3210, 3226, 3241, 3256, 3270, 3283, 3296, 3308, 3320, 3332, 3343, 3353, 3363, 3373, 3382, 3390, 3399, 3407, 3414, 3422, 3428, 3435, 3441, 3447, 3453, 3458, 3463, 3468, 3473, 3478])
TEMP = np.arange(-40 + 273.15, 130 + 273.15, 5)
R0 = 10000 # R at 25C
else:
raise ValueError('NTC_type %s is not supported.' % NTC_type)
self._bdaq_set_NTC_MUX(connector=connector)
vpvn_raw = self['gpio_xadc_vpvn'].get_data() # reads VP - VN voltage generated by NTC readout circuit on BDAQ53 pcb vpvn_raw is /16 becauses XADC is 12bit
Vmeas = float((vpvn_raw[1] + vpvn_raw[0] * 255) / 16) * 1 / (2 ** 12 - 1)
if 0.26 < Vmeas < 0.28: # Very old BDAQ: No MUX, resistors, ... mounted
logger.warning('NTC measurement is ambiguous! Are you sure you have all necessary devices mounted on your BDAQ board?')
elif 0.017 < Vmeas < 0.02: # Wrong resistor values or solder jumpers open
logger.warning('NTC measurement is ambiguous! Are you sure you have the correct resistors mounted on your BDAQ board?')
# r = NTC resistance, is measured by unity gain opamp on BDAQ53 PCB
# R names taken from BDAQ53 PCB rev. 1.1, adjust to fit input xADC input rage [0-1V]
# Vmeas = VntcP - VntcN
R16 = float(self.calibration['bdaq_ntc']['R16'])
R17 = float(self.calibration['bdaq_ntc']['R17'])
R19 = float(self.calibration['bdaq_ntc']['R19'])
VCC_3V3 = 3.3
VntcP = VCC_3V3 * R19 / (R17 + R19)
VntcN = VntcP - Vmeas
r = VntcN * R16 / (VCC_3V3 - VntcN)
r_ratio = r / R0
arg = np.argwhere(R_RATIO <= r_ratio)
if len(arg) == 0:
j = -1
else:
j = arg[0]
k = 1.0 / (math.log(r_ratio / R_RATIO[j]) / B_CONST[j] + 1 / TEMP[j])[0]
logger.debug("Temperature of NTC %s connected to connector %s: %.2f [°C]", NTC_type, connector, k - 273.15)
return round(k - 273.15, 3)
def _bdaq_get_temperature_FPGA(self):
'''
Return temperature of BDAQ FPGA
'''
# temp_raw is /16 becauses XADC is 12bit
# -0x767) * 0.123 - 40 from XADC manual
fpga_temp_raw = self['gpio_xadc_fpga_temp'].get_data()
fpga_temp = (float(fpga_temp_raw[1] + fpga_temp_raw[0] * 255) / 16 - 0x767) * 0.123 - 40
logger.debug('Internal FPGA temperature: %.2f [°C]', fpga_temp)
return round(fpga_temp, 3)
def get_temperature_NTC(self, connector=0):
if self.board_version == 'KC705':
return self._kc705_get_temperature_NTC_CERNFMC()
elif self.board_version == 'BDAQ53':
raise NotImplementedError('NTC readout is not yet implemented with BDAQ board.')
return self._bdaq_get_temperature_NTC(connector=connector)
else:
logger.error('NTC readout is not not supported on this hardware platform.')
def get_temperature_FPGA(self):
if self.board_version == 'BDAQ53':
return self._bdaq_get_temperature_FPGA()
else:
raise NotImplementedError('NTC readout is not not supported on this hardware platform.')
logger.error('FPGA temperature readout is not not supported on this hardware platform.')
def get_DP_SENSE(self, DP_ID):
''' Read back the vddd_sense lines to identify powered chips '''
if self.board_version == 'BDAQ53':
sense = self['DP_CONTROL'].get_data()
sense = self['BDAQ_CONTROL'].get_data()
logging.debug('Slow_control sense: %s' % bin(sense[0]))
if 0 <= DP_ID < 4:
return ((sense[0] & (1 << DP_ID)) is False)
else:
logger.error('Invalid DP_ID (0..3)')
else:
logger.warning('RD53A slow control is only available for BDAQ53 hardware')
logger.error('RD53A slow control is only available for BDAQ53 hardware')
return False
def set_DP_RESET(self, DP_ID, value):
''' Controls the POR lines. if set to 1, the POR is pulled to local chip ground via opto-coupler '''
if self.board_version == 'BDAQ53':
if 0 <= DP_ID < 4:
self['DP_CONTROL'].set_data([value << (4 + DP_ID)])
self['BDAQ_CONTROL'].set_data([value << (4 + DP_ID)])
else:
logger.error('Invalid DP_ID (0..3)')
else:
@@ -362,7 +459,7 @@ class BDAQ53(Dut):
return False
def setup_aurora(self):
if self.configuration['bench']['bypass_mode'] is True:
if self.configuration['bypass_mode'] is True:
if self.board_version == 'KC705'and self.connector_version == 'FMC_LPC' and self.board_options & self.board_options_map['640Mbps']:
logger.info("Switching FMC card to BYPASS MODE @ 640Mb/s")
self['cmd'].set_bypass_mode(True)
Loading