Skip to content
Snippets Groups Projects
Commit 40cf81b4 authored by Gijs Schoonderbeek's avatar Gijs Schoonderbeek
Browse files

Clean-up code

parent 5c793370
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
......@@ -22,10 +41,10 @@ IOUT_POLS = {"CTR_LBA" : 0.45,
"CTR_RCU2_A": 0.7,
"CTR_RCU2_D": 0.3}
LP_VIN = 0x88 #
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
......@@ -38,14 +57,14 @@ 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
......@@ -56,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
......@@ -76,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
......@@ -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,20 +21,21 @@ import sys
sys.path.insert(0, '.')
import os
import math
from APSPU_I2C import *
if os.name == "posix":
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 = 1
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
......@@ -46,7 +47,7 @@ class ApspuClass:
def read_all(self):
#
# Function to read all monitoring points of the UniBoard
# Function to read all monitoring points of the APSPU
#
print("--------- \nRead APSPU Status\n---------")
for pol in self.pols:
......@@ -64,6 +65,10 @@ class ApspuClass:
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])
......@@ -77,6 +82,11 @@ class ApspuClass:
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:
......@@ -89,6 +99,12 @@ class ApspuClass:
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:
......@@ -97,13 +113,14 @@ class ApspuClass:
pol.on_off(on)
return True
class EepromClass:
#
# Class to handle EEPROM communication
#
def __init__(self):
#
# All monitoring points Point of Load DC/DC converter
# All monitor. read and write functions for the EEPROM
#
self.dev_i2c_eeprom = I2C(EEPROM)
self.dev_i2c_eeprom.bus_nr = I2CBUSNR
......@@ -112,6 +129,10 @@ class EepromClass:
#
# 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")
......@@ -127,6 +148,10 @@ class EepromClass:
#
# 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")
......@@ -140,6 +165,10 @@ class EepromClass:
#
# Write and Read the EEPROM to check functionality
#
# value = string with data to write
# address = address to write the data to
# return True if read back is same as write value
#
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)
......@@ -170,16 +199,16 @@ 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 = []
ret_value = int(raw_value[2:], 16) * 2**8
ret_value += int(raw_value[:2], 16)
output_value = ret_value * 2**-11
......@@ -193,6 +222,9 @@ class PolClass:
#
# 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)
......@@ -204,16 +236,28 @@ class PolClass:
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 True
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)
......@@ -224,12 +268,16 @@ class PolClass:
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 True
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)
......@@ -240,9 +288,14 @@ class PolClass:
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 True
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
......@@ -256,8 +309,8 @@ class PolClass:
raw_value = '0' + raw_value
ret_value = []
ret_value.append(int(raw_value[:2], 16))
ret_value.append(int(raw_value[2:], 16)) # * 2**8
output_value = calc_lin_2bytes(ret_value) #ret_value * 2**-11
ret_value.append(int(raw_value[2:], 16))
output_value = calc_lin_2bytes(ret_value)
self.vin = output_value
def read_vout(self):
......@@ -281,21 +334,27 @@ class PolClass:
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 = []
ret_value = int(raw_value[2:], 16) * 2**8
ret_value += int(raw_value[:2], 16)
output_value = ret_value * 2**-11
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:
......@@ -307,7 +366,7 @@ class PolClass:
print(f"Output UV limit is set to: = {output_value:5.2f} V using hex value {raw_value}")
return output_value
else:
return 9999
return False
def read_iout(self):
#
......@@ -346,6 +405,11 @@ class PolClass:
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
......@@ -378,10 +442,10 @@ class PolClass:
check_ok = True
else:
check_ok = False
print(f"POL {self.name:10} Iout not OK, expected {i_low:4.2f} A - {i_high:4.2f} A, measured {self.iout:4.2f} A ")
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
......@@ -395,13 +459,14 @@ class PolClass:
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)
......@@ -426,7 +491,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):
......@@ -436,13 +502,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)
......@@ -463,6 +532,9 @@ class FanmonitorClass:
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):
......
"""
Copyright 2021 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten,
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.
......@@ -12,17 +12,15 @@ 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-12-07
This file contains the APSPU production script.
"""
import sys
sys.path.insert(0, '.')
import os
import math
from apspu_lib import *
from apspu_lib import *
if len(sys.argv) < 2:
......@@ -32,11 +30,11 @@ if len(sys.argv)<2:
apspu = ApspuClass()
apspu.apspu_on_off(False)
sleep(5)
sleep(5) # Wait for outputs to be stable off
apspu.set_pols()
x = input("Change dipswitches and press key to continue..")
input("Change dipswitches and press key to continue..")
apspu.apspu_on_off(True)
sleep(10)
sleep(5) # Wait for outputs to be stable on
apspu.read_all()
apspu.print_status()
if apspu.check_apspu():
......@@ -45,7 +43,7 @@ if apspu.check_apspu():
apspu.read_all()
apspu.print_status()
apspu.apspu_on_off(True)
id = "APSPU-" + sys.argv[1]
apspu_id = "APSPU-" + sys.argv[1]
serial = sys.argv[2]
apspu.eeprom.wr_rd_eeprom(id, address=0)
apspu.eeprom.wr_rd_eeprom(apspu_id, address=0)
apspu.eeprom.wr_rd_eeprom(serial, address=0x20)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment