Skip to content
Snippets Groups Projects
Commit f841e10c authored by Gijs Schoonderbeek's avatar Gijs Schoonderbeek
Browse files
parents c5e36e98 c598bda2
No related branches found
No related tags found
No related merge requests found
#******************************************#
# I2C address, registers and ports for UNB2c
# Created: 2021-05-11
#******************************************#
"""
Copyright 2022 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten,
ASTRON Netherlands Institute for Radio Astronomy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
###################################
Created: 2022-12-07
This file contains the definitions of the APSPU registers etc.
"""
#
# I2C address, registers and ports for APSPU
# Created: 2022-12-07
#
#
# General, Point of load converters
###################################
#
CTR_LBA = 0x3C
CTR_RCU2_A = 0x3D
......@@ -14,19 +33,38 @@ CTR_POLS = {"CTR_LBA" : 0x3C,
"CTR_RCU2_A": 0x3D,
"CTR_RCU2_D": 0x3E}
VOUT_POLS = {"CTR_LBA": 8.0,
"CTR_RCU2_A": 5.60009765625,
"CTR_RCU2_D": 3.2998046875}
IOUT_POLS = {"CTR_LBA": 0.45,
"CTR_RCU2_A": 0.7,
"CTR_RCU2_D": 0.3}
LP_VIN = 0x88
LP_VOUT_MODE = 0x20
LP_VOUT = 0x8B #
LP_temp = 0x8D #
LP_VOUT = 0x8B
LP_temp = 0x8D
LP_IOUT = 0x8C
LP_VOUT_COMMAND = 0x21
LP_VOUT_TRIM = 0x22
LP_VOUT_MAX = 0x24
LP_VOUT_SCALE_LOOP = 0x29
LP_VOUT_SCALE_MON = 0x2A
LP_VOUT_OV_LIMIT = 0x40
LP_VOUT_UV_LIMIT = 0x44
LP_STORE_USER_ALL = 0x15
LP_ON_OFF_CONFIG = 0x02
LP_OPERATION = 0x01
###################################
#
# Central I2C Devices
###################################
#
EEPROM = 0x50
###################################
#
# FAN speed
###################################
#
MAX6620 = 0x29
REG_GLOBAL = 0x00
......@@ -37,15 +75,20 @@ TACH_COUNT_FREQ = 8192
FAN_TACHS = 1
RUN_MONITOR = 0x02
NOF_APS_FANS = 3
######################
#
# Functions
######################
#
# Calculate floating point value according PMBus lineair
def calc_lin_2bytes(data):
#
# Calculate floating point value according PMBus lineair
#
# input data (Byte array)
# return value (float)
#
expo = ((data[1] & 0xf8) >> 3)
if expo == 1:
expo = -7
......@@ -57,14 +100,17 @@ def calc_lin_2bytes(data):
output = mantisse * 2**expo
return output
# Calculate floating point value according PMBus lineair
def calc_lin_3bytes(data, mode):
#
# Calculate floating point value according PMBus lineair
#
# input data (Byte array)
# return value (float)
#
expo = (mode[0] & 0x1F)
if expo > 2**4:
expo = expo - 2**5
mant = (data[1]*256 + data[0])
output = mant * 2**expo
return output
'''
Copyright 2021 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten,
ASTRON Netherlands Institute for Radio Astronomy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Set CCD
'''
import sys
import time
import math
sys.path.insert(0,'.')
import os
if os.name =="posix":
from I2C_serial_pi2 import *
else:
from I2C_serial import *
DEBUG = False
I2CBUSNR=1
sleep_time = 0.05
SET_PLL = True
READ_LOCK = True
READ_ALL = False
CHECK_EEPROM = True
PWR_RST = False
READ_SENSOR = False
READ_SET_FAN = True
CLK_FREQ = '200MHz'
dev_i2c_eeprom = I2C(0x50)
dev_i2c_eeprom.bus_nr = I2CBUSNR
CS = 6
SCLK = 4
SDO = 5
SDI = 7
PLL_addr = 0x20
def Write_byte_PLL(reg_address, wr_data, ADDRESS=0x20):
#
# Write Byte to the ADC
#
I2C_device = I2C(ADDRESS, BUSNR=I2CBUSNR)
PLL_rw = 0x00 # 0 for write, 1 for read
stri = "Write : 0x{0:{fill}2x} to Address : 0x{1:{fill}2x}".format(wr_data, reg_address, fill='0')
print(stri)
I2C_device.write_bytes(0x06, 0x2C)
if DEBUG:
rd_bytes = I2C_device.read_bytes(0x06, 1)
stri = "IO expander wrote 0x{0:x}, read 0x{1}".format(0x2C, rd_bytes[1])
print(stri)
data = (reg_address << 9) + (PLL_rw << 8) + wr_data
bit_array = "{0:{fill}16b}".format(data, fill='0')
I2C_device.write_bytes(0x02, 0x02 | (0x1 << CS))
for bit in bit_array:
for clk in range(2):
Write_data = 0x02 | (0 << CS) | (clk << SCLK) | (int(bit) << SDI)
I2C_device.write_bytes(0x02, Write_data)
for clk in range(2):
Write_data = 0x02 | (0 << CS) | (clk << SCLK)
I2C_device.write_bytes(0x02, Write_data)
for clk in range(2):
Write_data = 0x02 | (1 << CS) | (clk << SCLK)
I2C_device.write_bytes(0x02, Write_data)
Write_data = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI)
I2C_device.write_bytes(0x02, Write_data)
if DEBUG:
read_bits = Read_byte_PLL(reg_address, nof_bytes=1, ADDRESS=ADDRESS)
# stri = "Bits written 0x{0:x} to register 0x{1:x} read from PLL are {2}".format(wr_data, reg_address, read_bits)
# print(stri)
def Read_byte_PLL(reg_address, nof_bytes=1, ADDRESS=0x20 ):
#
# Read Byte from the ADC
#
I2C_device = I2C(ADDRESS, BUSNR=I2CBUSNR)
PLL_rw = 0x01 # 0 for write, 1 for read
I2C_device.write_bytes(0x06, 0x2C)
data = ( reg_address << 7 ) + PLL_rw
bit_array = "{0:{fill}8b}".format(data, fill='0')
for bit in bit_array:
for clk in range(2):
Write_data = 0x02 | (0 << CS) | (clk << SCLK) | ( int(bit) << SDI)
I2C_device.write_bytes(0x02, Write_data)
# sleep(sleep_time)
# print("read byte")
read_bit = ''
for cnt in range(8*nof_bytes):
for clk in [0, 1]: # Read after rizing edge
Write_data = 0x02 | (clk << SCLK) | ( int(bit) << SDI )
I2C_device.write_bytes(0x02, Write_data)
ret_ack, ret_value = I2C_device.read_bytes(0x00, 1)
# stri= "ret_value = {}".format(int(ret_value,16))
# print(stri)
if ret_ack:
read_bit += str((int(ret_value, 16) >> SDO) & 0x01)
else:
print("ACK nok")
Write_data = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI)
I2C_device.write_bytes(0x02, Write_data)
stri = "Read back at address 0x{0:{fill}2x} result : 0x{1:{fill}2x} ".format(reg_address, int(read_bit, 2), fill='0')
print(stri)
return read_bit;
def setup_pll() :
I2C_device = I2C(0x20, BUSNR=I2CBUSNR) #clock selection
I2C_device.write_bytes(0x07, 0x00)
Write_byte_PLL(0x03, 0x08, PLL_addr)
Write_byte_PLL(0x04, 0xFF, PLL_addr) # CF disable not used outputs, 00 enable all
Write_byte_PLL(0x05, 0xD7, PLL_addr)
Write_byte_PLL(0x06, 0xE0, PLL_addr) # cp inv = 0xF4 other 0xE4
Write_byte_PLL(0x07, 0x04, PLL_addr) # Divider R = 1 dec
Write_byte_PLL(0x08, 0x01, PLL_addr)
Write_byte_PLL(0x07, 0x00, PLL_addr)
Write_byte_PLL(0x09, 0x10, PLL_addr)
Write_byte_PLL(0x0A, 0x01, PLL_addr)
Write_byte_PLL(0x09, 0x00, PLL_addr)
Write_byte_PLL(0x0B, 0x00, PLL_addr)
Write_byte_PLL(0x0D, 0x01, PLL_addr)
Write_byte_PLL(0x0E, 0x00, PLL_addr)
Write_byte_PLL(0x0F, 0x01, PLL_addr)
Write_byte_PLL(0x10, 0x00, PLL_addr)
Write_byte_PLL(0x11, 0x01, PLL_addr)
Write_byte_PLL(0x12, 0x00, PLL_addr)
Write_byte_PLL(0x13, 0x01, PLL_addr)
Write_byte_PLL(0x14, 0x01, PLL_addr)
def power(state):
I2C_IO_device_A = I2C(0x20, BUSNR=I2CBUSNR)
I2C_IO_device_A.write_bytes(0x06, 0x2C) # '0' is output
I2C_IO_device_A.write_bytes(0x07, 0x00) # '0' is output
I2C_IO_device_B = I2C(0x21, BUSNR=I2CBUSNR)
I2C_IO_device_B.write_bytes(0x06, 0x2C) # '0' is output
if state:
bits_to_set_A1 = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI)
bits_to_set_A2 = 0x04
bits_to_set_B1 = 0x02 | (1 << CS) | (0 << SCLK) | (0 << SDI)
else:
bits_to_set_A1 = 0x00 | (1 << CS) | (0 << SCLK) | (0 << SDI)
bits_to_set_A2 = 0x00
bits_to_set_B1 = 0x00 | (1 << CS) | (0 << SCLK) | (0 << SDI)
if DEBUG :
stri = "Bits to reg 0 0x{0:x}".format(bits_to_set_A1)
print(stri)
I2C_IO_device_A.write_bytes(0x02, bits_to_set_A1)
I2C_IO_device_A.write_bytes(0x03, bits_to_set_A2)
I2C_IO_device_B.write_bytes(0x02, bits_to_set_B1)
def write_eeprom( data=0x01):
#
# Write the EEPROM with the serial number etc.
#
ret_ack, ret_value = dev_i2c_eeprom.read_bytes(0)
if ret_ack < 1:
print("EEPROM not found during write")
return False
else:
dev_i2c_eeprom.write_bytes(0x00, data)
sleep(0.1)
return True
def read_eeprom():
#
# Read the EEPROM with the serial number etc.
#
ret_ack, ret_value = dev_i2c_eeprom.read_last_reg(1)
if ret_ack < 1:
print("no EEPROM found during read")
return False
else:
ret_ack, ret_value = dev_i2c_eeprom.read_bytes(0x00, 1)
return ret_value
def wr_rd_eeprom(value=0x34):
#
# Write and Read the EEPROM to check functionality
#
if write_eeprom(value):
ret_value = read_eeprom()
stri = "Wrote to EEPROM: 0x{0:X}, Read from EEPROM: 0x{1} ".format(value, ret_value)
print(stri)
return True
def ccd_sensors():
for sens_line in range(7):
read_voltage(sens_line)
read_temp()
def read_voltage(input_channel=0):
addr = 0x74
Vref = 3.0
one_step = Vref/(2**(16))
I2C_device = I2C(addr, BUSNR=I2CBUSNR)
channel_select_word = 0xB0 | ((input_channel%2) << 3) | ((input_channel >> 1) & 0x7)
if DEBUG:
stri = "Word to select sens input is 0x{0:x}".format(channel_select_word)
print(stri)
sleep(0.5)
I2C_device.write_bytes(channel_select_word, 0xB8)
sleep(0.5)
ret_ack, ret_value = I2C_device.read_last_reg(3)
if 1: #ret_ack:
if DEBUG:
stri = "Return value input 0 : 0x{0} ".format(ret_value)
print(stri)
if int(ret_value, 16) >= 0xC00000:
print("over range")
else:
steps = (int(ret_value, 16) & 0x1FFFFF) >> 6
voltage = one_step * steps
voltage = ((4.7+2.2)/2.2)*2*voltage
string = "Voltage sens line {1} is {0:.4f} V".format(voltage, input_channel)
print(string)
else:
stri = " No ACK on device 0x{0:x} ".format(addr)
print(stri)
def read_temp():
Vref = 3.0
addr = 0x74
one_step = Vref/(2**(16))
I2C_device = I2C(addr, BUSNR=I2CBUSNR)
temp_slope = 93.5E-6 * 2**(16+1) / Vref
sleep(0.5)
I2C_device.write_bytes(0xA0, 0xC0)
sleep(0.5)
ret_ack, ret_value = I2C_device.read_last_reg(3)
if ret_ack:
raw_value = (int(ret_value, 16) & 0x1FFFFF) >> 6
temperature_K = (raw_value/temp_slope)
temperature = temperature_K-273
stri = "Temperature : {0:.2f} gr. C".format(temperature)
print(stri)
else:
print("Error reading tempeature")
def set_fan_off():
#
# Switch CCD fan off
#
print("Switch fan off")
MAX6620 = 0x29
fanmonitor_dev = I2C(MAX6620)
fanmonitor_dev.bus_nr = 3
fanmonitor_dev.write_bytes(0x00, 0x10)
fanmonitor_dev.write_bytes(0x02, 0x08)
fanmonitor_dev.write_bytes(0x28, 0x00)
fanmonitor_dev.write_bytes(0x29, 0x00)
def set_fan_speed(speed):
#
# Set control voltage of fan PNP
#
stri = "Set fan to {} %".format(speed)
print(stri)
MAX6620 = 0x29
reg_a = ((0xFF*speed)/100) & 0xFF
fanmonitor_dev = I2C(MAX6620)
fanmonitor_dev.bus_nr = 3
fanmonitor_dev.write_bytes(0x00, 0x00)
fanmonitor_dev.write_bytes(0x02, 0x08)
fanmonitor_dev.write_bytes(0x01, 0x0F)
fanmonitor_dev.write_bytes(0x06, 0x60)
fanmonitor_dev.write_bytes(0x28, reg_a)
fanmonitor_dev.write_bytes(0x29, 0x80)
def read_tacho():
#
# Read the fan speed
#
MAX6620 = 0x29
REG_TACH_MSP_REGS = [ 0x10, 0x12, 0x14]
REG_TACH_LSP_REGS = [ 0x11, 0x13, 0x15]
TACH_PERIODS = 16
TACH_COUNT_FREQ = 8192
FAN_TACHS = 1
DEBUG=1
fanmonitor_dev = I2C(MAX6620)
fanmonitor_dev.bus_nr = 3
fan_nr=0
ret_ack, ret_value = fanmonitor_dev.read_bytes(1)
if ret_ack < 1:
stri = " Device {0} at address 0x{1:X} not found".format("MAX6620", MAX6620)
print(stri)
status = False
ret_ack, tach_msb = fanmonitor_dev.read_bytes(REG_TACH_MSP_REGS[0], 1)
tach_msb = int(tach_msb, 16) & 0xFF
if tach_msb > 254:
if DEBUG :
tach_lsb = 255
tach = 99999
rpm = 0
else:
ret_ack, tach_lsb = fanmonitor_dev.read_bytes(REG_TACH_LSP_REGS[0], 1)
tach_lsb = int(tach_lsb, 16) & 0xE0
tach = tach_msb*16 + tach_lsb/8
rpm = float((TACH_COUNT_FREQ*TACH_PERIODS*60))/(FAN_TACHS*tach)
if DEBUG:
stri = "MSP: {0}, LSB: {1}, TACH : {2}, RPM : {3:6.2f}".format(tach_msb, tach_lsb, tach, rpm)
print(stri)
if CHECK_EEPROM :
wr_rd_eeprom()
if PWR_RST :
power(False)
sleep(10)
power(True)
if SET_PLL :
setup_pll()
if READ_LOCK:
ret_value = Read_byte_PLL(0x00, nof_bytes = 1, ADDRESS=PLL_addr)
status_pll = int(ret_value,2)
if status_pll == 0x04:
print("PLL in lock")
elif (status_pll & 0x10) > 0:
print("Not Locked --> No 10 MHz ref")
else:
print("Not locked --> PLL Error")
if READ_SET_FAN :
read_tacho()
set_fan_off()
sleep(10)
read_tacho()
set_fan_speed(75)
sleep(10)
read_tacho()
set_fan_speed(100)
sleep(10)
read_tacho()
if READ_SENSOR:
ccd_sensors()
......@@ -38,12 +38,14 @@ class I2C:
try:
(count, rd_value) = pi.i2c_read_i2c_block_data(bus, register, bytes_to_read)
ret_value = ''
if len(rd_value) < bytes_to_read:
return False, 999
for cnt in range(bytes_to_read):
ret_value += (hex(rd_value[cnt])[2:])
ret_ack = 1
if SLOW:
sleep(0.2)
except IOError, err:
except IOError:
ret_ack = 0
ret_value = 'ffff'
if DEBUG:
......@@ -65,7 +67,7 @@ class I2C:
ret_ack = 1
if SLOW:
sleep(0.2)
except IOError, err:
except IOError:
ret_ack = 0
rd_value = [0]*bytes_to_read
if DEBUG:
......@@ -77,12 +79,14 @@ class I2C:
def write_bytes(self, register, data):
bus = pi.i2c_open(self.bus_nr, self.I2C_Address)
if type(data) is not list:
data = [data]
try:
pi.i2c_write_i2c_block_data(bus, register, [data])
pi.i2c_write_i2c_block_data(bus, register, data)
ret_ack = 1
if SLOW:
sleep(0.3)
except IOError, err:
except IOError:
ret_ack = 0
ret_value = 0
if DEBUG:
......@@ -97,7 +101,7 @@ class I2C:
ret_ack = 1
if SLOW:
sleep(0.3)
except IOError, err:
except IOError:
ret_ack = 0
ret_value = 0
if DEBUG:
......@@ -113,7 +117,7 @@ class I2C:
ret_ack = 1
if SLOW:
sleep(0.3)
except IOError, err:
except IOError:
ret_ack = 0
ret_value = 0
if DEBUG:
......
......@@ -12,8 +12,8 @@ See the License for the specific language governing permissions and
limitations under the License.
Created: 2021-05-10
This file contains the UniBoard2 class with all monitoring function. It can be used stand-alone to test it.
Created: 2022-17-12
This file contains the APSPU class with all monitoring function. It can be used stand-alone to test it.
"""
......@@ -21,85 +21,169 @@ import sys
sys.path.insert(0, '.')
import os
import math
# import time
from APSPU_I2C import *
if os.name == "posix":
from I2C_serial_pi import *
from I2C_serial_pi2 import *
else:
from I2C_serial import *
I2CBUSNR = 1 # Bus used on the Pi
DEBUG = False # Set True to print debug information on the screen
I2CBUSNR = 3
DEBUG = False
class ApspuClass:
#
# Class that contains all parts on a UniBoard2
# Toplevel Class that contains all parts on a APSU
#
def __init__(self):
self.status = False
self.pols = []
for pol in list(CTR_POLS.keys()):
self.pols.append(PolClass(pol))
self.fans = FanmonitorClass()
self.eeprom = EepromClass()
def read_all(self):
#
# Function to read all monitoring points of the APSPU
#
print("--------- \nRead APSPU Status\n---------")
for pol in self.pols:
pol.read_all()
self.fans.read_all()
return True
def print_status(self):
#
# Function to dump monitoring information on the screen
#
for pol in self.pols:
pol.print_status()
self.fans.print_status()
return True
def set_pols(self):
#
# Function to set output voltage level on the APSPU
# Values are read from the APSPU_I2C
#
print("--------- \nProgram Pols\n---------")
for pol in self.pols:
pol.set_vout_pol(VOUT_POLS[pol.name])
vout = pol.read_vout_set()
if not (0.9*VOUT_POLS[pol.name] < vout < 1.1*VOUT_POLS[pol.name]):
print(f"POL {pol.name:10} Error setting Vout, "
f"set to {VOUT_POLS[pol.name]} read back {vout}")
exit()
pol.set_vout_ov_limit_pol(1.2*VOUT_POLS[pol.name])
ov_out = pol.read_ov_limit()
if not (1.1*VOUT_POLS[pol.name] < ov_out < 1.3*VOUT_POLS[pol.name]):
print(f"POL {pol.name:10} Error setting output overvoltage"
f"set {1.2*VOUT_POLS[pol.name]} read back {ov_out}")
exit()
pol.set_on_off_config()
pol.write_to_nvm()
print("Done")
def check_apspu(self):
#
# Function to check values of read_all() Used during production
#
# Return True is OK, False if not OK
#
print("--------- \nCheck APSPU \n---------")
check_ok = True
for pol in self.pols:
check_ok = check_ok & pol.check_pol()
check_ok = check_ok & self.fans.check_fans()
check_ok = check_ok & self.eeprom.wr_rd_eeprom(value="PROD_CHECK", address=0x30)
if check_ok:
print("APSPU OK")
else:
print(">>> APSPU NOT OK <<<")
return check_ok
def apspu_on_off(self, on):
#
# Function to switch off the POLs on APSPU
# on = True to switch APSU on
# on = False to switch APSU off
# Return: always True
#
if on:
print(f">> Switch APSPU ON")
else:
print(">> Switch APSPU OFF")
for pol in self.pols:
pol.on_off(on)
return True
class EepromClass:
#
# Class to handle EEPROM communication
#
def __init__(self):
#
# All monitor. read and write functions for the EEPROM
#
self.dev_i2c_eeprom = I2C(EEPROM)
self.dev_i2c_eeprom.bus_nr = I2CBUSNR
self.fans = FanmonitorClass()
def write_eeprom(self, data=0x01):
def write_eeprom(self, data="APSPU", address=0):
#
# Write the EEPROM with the serial number etc.
#
# Data = data to write in string formal
# Address = address to write the data to
# Return True if successfully
#
ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(0)
if ret_ack < 1:
print("EEPROM not found during write")
return False
else:
self.dev_i2c_eeprom.write_bytes(0x00, data)
wr_data = bytearray(data.encode("utf-8", errors="ignore"))
for loc, data_byte in enumerate(wr_data):
self.dev_i2c_eeprom.write_bytes(address+loc, data_byte)
sleep(0.1)
return True
def read_eeprom(self):
def read_eeprom(self, address=0, nof_bytes=5):
#
# Read the EEPROM with the serial number etc.
#
# Address = address to read from
# nof_bytes = number of bytes to read
# return string with the data from the flash
#
ret_ack, ret_value = self.dev_i2c_eeprom.read_last_reg(1)
if ret_ack < 1:
print("no EEPROM found during read")
return False
else:
ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(0x00, 1)
return ret_value
ret_ack, ret_value = self.dev_i2c_eeprom.read_bytes(address, nof_bytes)
str_return = bytes.fromhex(ret_value[:nof_bytes*2]).decode('UTF-8')
return str_return
def wr_rd_eeprom(self, value=0x34):
def wr_rd_eeprom(self, value="APSPU-1", address=0):
#
# Write and Read the EEPROM to check functionality
#
if self.write_eeprom(value):
ret_value = self.read_eeprom()
stri = "Wrote to EEPROM: 0x{0:X}, Read from EEPROM: 0x{1} ".format(value, ret_value)
print(stri)
return True
def read_all(self):
#
# Function to read all monitoring points of the UniBoard
#
print("Read POLs")
for pol in self.pols:
pol.read_all()
self.fans.read_all()
return True
def print_status(self):
# value = string with data to write
# address = address to write the data to
# return True if read back is same as write value
#
# Function to dump monitoring information on the screen
#
print("Power supplies")
for pol in self.pols:
pol.print_status()
self.wr_rd_eeprom()
self.fans.print_status()
if self.write_eeprom(value, address=0):
ret_value = self.read_eeprom(address=0, nof_bytes=len(value))
stri = "Wrote to EEPROM register 0x{2:x} : {0}, Read from EEPROM: {1}".format(value, ret_value, address)
print(stri)
if ret_value == value:
return True
else:
return False
class PolClass:
......@@ -112,6 +196,7 @@ class PolClass:
#
self.name = name
self.vout = 0
self.vin = 0
self.iout = 0
self.temp = 0
self.pol_dev = I2C(CTR_POLS[self.name])
......@@ -124,6 +209,123 @@ class PolClass:
else:
self.status = True
def read_vout_set(self):
#
# Function to read the output voltage of the Point of Load DC/DC converter
#
# Return: output value is of else 999
#
if self.status:
ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT_COMMAND, 2)
if len(raw_value) < 4:
raw_value = '0' + raw_value
ret_value = int(raw_value[2:], 16) * 2**8
ret_value += int(raw_value[:2], 16)
output_value = ret_value * 2**-11
if DEBUG:
print(f"Output set to: = {output_value:5.2f} V using hex value {raw_value}")
return output_value
else:
return 999
def set_on_off_config(self):
#
# Function to set the output of the DC/DC converter
#
# Return always I2C ack
#
ret_ack = False
if self.status:
if DEBUG:
ret_ack, raw_value = self.pol_dev.read_bytes(LP_ON_OFF_CONFIG, 1)
print(f"Current setting ON/OFF register 0x{int(raw_value, 16):02x}")
on_off_bit = not 1 << 0
polarity_pin = 1 << 1
use_external = 0 << 2
use_soft = 1 << 3
default_off = 1 << 4
wr_data = on_off_bit + polarity_pin + use_external + use_soft + default_off
ret_ack = self.pol_dev.write_bytes(LP_ON_OFF_CONFIG, wr_data)
return ret_ack
def on_off(self, on=True):
#
# Function to switch on or off a POL
#
# if on = True switch on the POL
# if on = Flase swtich off the POL
# Return I2C ack
#
wr_data = (on << 7) + 0
ret_ack = self.pol_dev.write_bytes(LP_OPERATION, wr_data)
return ret_ack
def set_vout_pol(self, value):
#
# Function to read the output voltage of the Point of Load DC/DC converter
#
# value is the output voltage level in V
# return I2C ack
#
ret_ack = False
if self.status:
set_value = int(value * (2**11))
hex_set_value = hex(set_value)
wr_value = (hex_set_value[4:6] + hex_set_value[2:4])
if DEBUG:
print(f"Calculated wr_value is {wr_value}")
wr_data = []
wr_data.append(int(hex_set_value[4:6], 16))
wr_data.append(int(hex_set_value[2:4], 16))
ret_ack = self.pol_dev.write_bytes(LP_VOUT_COMMAND, wr_data)
return ret_ack
def set_vout_ov_limit_pol(self, value):
#
# Function to read the output voltage of the Point of Load DC/DC converter
#
# value is the overvoltage level of the output
# return I2C ack
#
ret_ack = False
if self.status:
set_value = int(value * (2**11))
hex_set_value = hex(set_value)
wr_value = (hex_set_value[4:6] + hex_set_value[2:4])
if DEBUG:
print(f"Calculated wr_value is {wr_value}")
wr_data = []
wr_data.append(int(hex_set_value[4:6], 16))
wr_data.append(int(hex_set_value[2:4], 16))
ret_ack = self.pol_dev.write_bytes(LP_VOUT_OV_LIMIT, wr_data)
return ret_ack
def write_to_nvm(self):
#
# Function to write the POL's registers to NVM memory
#
# return is always True
#
ret_ack = self.pol_dev.write_bytes(LP_STORE_USER_ALL, 0)
return True
def read_vin(self):
#
# Function to read the output voltage of the Point of Load DC/DC converter
#
if self.status:
ret_ack, raw_value = self.pol_dev.read_bytes(LP_VIN, 2)
if not ret_ack:
self.iout=999
return False
if len(raw_value) < 4:
raw_value = '0' + raw_value
ret_value = []
ret_value.append(int(raw_value[:2], 16))
ret_value.append(int(raw_value[2:], 16))
output_value = calc_lin_2bytes(ret_value)
self.vin = output_value
return True
def read_vout(self):
#
......@@ -131,14 +333,64 @@ class PolClass:
#
if self.status:
ret_ack, vout_mod = self.pol_dev.read_bytes(LP_VOUT_MODE, 1)
if not ret_ack:
self.vout=999
return False
ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT, 2)
if not ret_ack:
self.vout=999
return False
vout_mod = int(vout_mod, 16)
ret_value = []
ret_value.append(int(raw_value[:2], 16))
try:
ret_value.append(int(raw_value[2:], 16))
except:
ret_value.append(0)
self.vout = calc_lin_3bytes(ret_value, [vout_mod])
return True
else:
self.vout = 999
return False
def read_ov_limit(self):
#
# Function to read the output voltage of the Point of Load DC/DC converter
# and print on the screen
#
# Return OV limit
#
output_value = 0
if self.status:
ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT_OV_LIMIT, 2)
if len(raw_value) < 4:
raw_value = '0' + raw_value
ret_value = int(raw_value[2:], 16) * 2**8
ret_value += int(raw_value[:2], 16)
output_value = ret_value * 2**-11
if DEBUG:
print(f"Output OV limit is set to: = {output_value:5.2f} V using hex value {raw_value}")
return output_value
def read_uv_limit(self):
#
# Function to read the output voltage of the Point of Load DC/DC converter
#
# Return UV limit if OK else False
#
if self.status:
ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT_UV_LIMIT, 2)
if len(raw_value) < 4:
raw_value = '0' + raw_value
ret_value = []
ret_value = int(raw_value[2:], 16) * 2**8
ret_value += int(raw_value[:2], 16)
output_value = ret_value * 2**-11
if DEBUG:
print(f"Output UV limit is set to: = {output_value:5.2f} V using hex value {raw_value}")
return output_value
else:
return False
def read_iout(self):
#
......@@ -174,26 +426,71 @@ class PolClass:
self.read_vout()
self.read_iout()
self.read_temp()
self.read_vin()
def check_pol(self):
#
# Function to read all monitoring points of the Point of Load DC/DC converter
#
# Return True if OK, False if not OK
#
self.read_all()
self.on_off(on=True)
check_ok = False
expected_vout = VOUT_POLS[self.name]
if 0.9*expected_vout < self.vout < 1.1*expected_vout:
check_ok = True
else:
check_ok = False
print(f"POL {self.name:10} Vout not OK, expected {expected_vout} V, measured {self.vout} V")
return check_ok
vin_low = 45
vin_high = 50
if vin_low < self.vin < vin_high:
check_ok = True
else:
check_ok = False
print(f"POL {self.name:10} Vin not OK, expected {vin_low} V - {vin_high} V, measured {self.vout} V ")
return check_ok
temp_low = 20
temp_high = 50
if temp_low < self.temp < temp_high:
check_ok = True
else:
check_ok = False
print(f"POL {self.name:10} TEMP not OK, expected {temp_low} C - {temp_high} C, measured {self.temp} C ")
return check_ok
i_low = 0.75*IOUT_POLS[self.name]
i_high = 1.25*IOUT_POLS[self.name]
if i_low < self.iout < i_high:
check_ok = True
else:
check_ok = False
print(f"POL {self.name:10} Iout not OK,"
f" expected {i_low:4.2f} A - {i_high:4.2f} A, measured {self.iout:4.2f} A ")
return check_ok
def print_status(self):
#
# Function to dump all monitoring points of the Point of Load DC/DC converter on the screen
#
if self.status:
stri = "POL: " + self.name + " "
stri += "Output voltage :{0: <5.2f} V ".format(self.vout)
stri += "Output Current :{0: <5.2f} A ".format(self.iout)
stri += "temperature :{0: <5.2f} Deg C".format(self.temp)
stri = f"POL: {self.name:10} :"
stri += "Vin :{0: >5.2f} V ".format(self.vin)
stri += "Vout :{0: >5.2f} V ".format(self.vout)
stri += "Iout :{0: >5.2f} A ".format(self.iout)
stri += "Temp :{0: >5.2f} \N{DEGREE SIGN}C".format(self.temp)
print(stri)
self.read_vout_set()
class FanmonitorClass:
#
# Class to read all monitoring points Point of Load DC/DC converter
# Class to read all monitoring points fan units in the APS
#
def __init__(self):
#
# All monitoring points Point of Load DC/DC converter
# All monitoring points for the fans
#
self.rpm = []
self.fanmonitor_dev = I2C(MAX6620)
......@@ -218,7 +515,8 @@ class FanmonitorClass:
self.fanmonitor_dev.write_bytes(REG_GLOBAL, RUN_MONITOR)
ret_ack, reg_after = self.fanmonitor_dev.read_bytes(REG_GLOBAL, 1)
if DEBUG:
stri = "Reg at address 0x{0} before : {1} and after write action {2}".format(REG_GLOBAL, reg_before, reg_after)
stri = "Reg at address 0x{0} before : {1} and after write action {2}"\
.format(REG_GLOBAL, reg_before, reg_after)
print(stri)
fan_config_reg = int((math.log(TACH_PERIODS) / math.log(2))) << 5
for fan_cnt in range(NOF_APS_FANS):
......@@ -228,13 +526,16 @@ class FanmonitorClass:
def read_fan(self, fan_nr):
#
# Function to a single fan
# fan_nr is the fan to read ranging from 0 till 2
# return the speed of the fan
#
if fan_nr > NOF_APS_FANS:
return 0
ret_ack, tach_msb = self.fanmonitor_dev.read_bytes(REG_TACH_MSP_REGS[fan_nr], 1)
tach_msb = int(tach_msb, 16) & 0xFF
if tach_msb > 254:
if DEBUG :
tach_lsb = 255
tach = 99999
if tach_msb > 254:
rpm = 0
else:
ret_ack, tach_lsb = self.fanmonitor_dev.read_bytes(REG_TACH_LSP_REGS[fan_nr], 1)
......@@ -250,9 +551,22 @@ class FanmonitorClass:
#
# Function to read all fan's
#
self.rpm = []
for fan_counter in range(NOF_APS_FANS):
self.rpm.append(self.read_fan(fan_counter))
def check_fans(self):
#
# Function to check fan speeds
#
self.read_all()
check_ok = True
for cnt, speed in enumerate(self.rpm):
if speed < 10:
print(f"Low speed on fan {cnt}")
check_ok = False
return check_ok
def print_status(self):
#
# Function to dump all monitoring points of the Point of Load DC/DC converter on the screen
......@@ -270,10 +584,19 @@ def main():
# Function to test the class, read all info and dump on the screen
#
apspu = ApspuClass()
print("read / write EEPROM")
apspu.wr_rd_eeprom(value=0x34)
apspu.apspu_on_off(False)
sleep(5)
apspu.set_pols()
apspu.apspu_on_off(True)
sleep(10)
apspu.read_all()
apspu.print_status()
apspu.check_apspu()
apspu.apspu_on_off(False)
sleep(10)
apspu.read_all()
apspu.print_status()
apspu.apspu_on_off(True)
if __name__ == "__main__":
......
"""
Copyright 2022 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten,
ASTRON Netherlands Institute for Radio Astronomy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Created: 2022-12-07
This file contains the APSPU production script.
"""
import sys
sys.path.insert(0, '.')
from apspu_lib import *
if len(sys.argv) < 2:
print("Production_apspy.py <ASTRON NR> <Serial number>")
print("e.g. python production_apspy.py 2022-01 1234")
exit()
apspu = ApspuClass()
apspu.apspu_on_off(False)
sleep(5) # Wait for outputs to be stable off
apspu.set_pols()
input("Change dipswitches and press key to continue..")
apspu.apspu_on_off(True)
sleep(5) # Wait for outputs to be stable on
apspu.read_all()
apspu.print_status()
if apspu.check_apspu():
apspu_id = "APSPU-" + sys.argv[1]
serial = sys.argv[2]
rw_ok = apspu.eeprom.wr_rd_eeprom(apspu_id, address=0)
if rw_ok:
rw_ok = apspu.eeprom.wr_rd_eeprom(serial, address=0x20)
if not rw_ok:
print("EEPROM Error")
......@@ -31,6 +31,7 @@ import sys
import spidev
DEBUG=False
CRC = False #True # CRC or packet counter
# We only have SPI bus 0 available to us on the Pi
bus = 0
......@@ -136,7 +137,7 @@ def read_link_status():
stri = "| "
for cnt_port in range(16):
if ret[3] & (0x8000 >> cnt_port) :
stri += "U | "
stri += "P | "
else:
stri += " | "
print(stri)
......@@ -166,6 +167,9 @@ def read_link_status():
stri += "Rx: Er "
if ret[2] & 0x40:
stri += "Rx FIFO Er "
# ret_err = read_switch(0x10+cnt,0x2E, pr_stri = False)
# stri += f"CRC errs: 0x{ret_err[1]:2x}"
# rest = write_switch_bytes(0x01,0x23, [0x40], pr_stri = False)
else:
stri += "link down "
print(stri)
......@@ -208,7 +212,7 @@ def read_link_status():
read_switch(0x10+cnt,0x2e)
if 1:
# alternative status read out, works better for SerDes lines.
for prt_cnt in [9, 10, 11,12, 13,14, 15]:
for prt_cnt in [8, 9, 10, 11,12, 13,14, 15]:
ret = read_switch(0x10+prt_cnt,0x28, pr_stri = False)
stri = "Port status of " + str(prt_cnt) + " "
if ret[1] & 0x02:
......@@ -235,6 +239,19 @@ def read_link_status():
stri += "Rx Fifo Err "
if ret[2] & 0x80:
stri += "Tx Fifo Err "
ret = read_switch(0x10+prt_cnt,0x2E, pr_stri = False)
if CRC:
rest = write_switch_bytes(0x10+prt_cnt,0x34, [0x20, 0x10], pr_stri = False)
rest = write_switch_bytes(0x10+prt_cnt,0x3e, [0x00, 0x00], pr_stri = False)
rest = write_switch_bytes(0x10+prt_cnt,0x20, [0xD0, 0x01], pr_stri = False)
stri += f"CRC err: {ret[0]} "
else:
rest = write_switch_bytes(0x10+prt_cnt,0x3e, [0x00, 0x00], pr_stri = False)
rest = write_switch_bytes(0x10+prt_cnt,0x20, [0xD0, 0x09], pr_stri = False)
stri += f"Rx packet count: {ret[0]} "
rest = write_switch_bytes(0x10+prt_cnt,0x22, [0x41, 0x41], pr_stri = False)
rest = write_switch_bytes(0x10+prt_cnt,0x3e, [0x00, 0x00], pr_stri = False)
rest = write_switch_bytes(0x10+prt_cnt,0x2E, [0x00, 0x00], pr_stri = False)
else:
stri += "Down "
print(stri)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment