From 515a9aa8beab0316869695855e5feb7b1a6a594d Mon Sep 17 00:00:00 2001 From: Gijs <schoonderbeek@astron.nl> Date: Tue, 11 Oct 2022 17:57:23 +0200 Subject: [PATCH] Added setting of the output voltage --- production_apspu.py | 318 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 production_apspu.py diff --git a/production_apspu.py b/production_apspu.py new file mode 100644 index 0000000..de71804 --- /dev/null +++ b/production_apspu.py @@ -0,0 +1,318 @@ +""" +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. + + + Created: 2021-05-10 +This file contains the UniBoard2 class with all monitoring function. It can be used stand-alone to test it. + +""" + +import sys +sys.path.insert(0, '.') +import os +import math +# import time +from APSPU_I2C import * +if os.name == "posix": + from I2C_serial_pi2 import * +else: + from I2C_serial import * + + +I2CBUSNR = 3 +DEBUG = False + +class ApspuClass: + # + # Class that contains all parts on a UniBoard2 + # + def __init__(self): + self.status = False + self.pols = [] + for pol in list(CTR_POLS.keys()): + self.pols.append(PolClass(pol)) + self.dev_i2c_eeprom = I2C(EEPROM) + self.dev_i2c_eeprom.bus_nr = I2CBUSNR + self.fans = FanmonitorClass() + + def write_eeprom(self, data=0x01): + # + # Write the EEPROM with the serial number etc. + # + 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) + sleep(0.1) + return True + + def read_eeprom(self): + # + # Read the EEPROM with the serial number etc. + # + 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 + + def wr_rd_eeprom(self, value=0x34): + # + # 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): + # + # 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() + return True + + def set_pols(self): + for pol in self.pols: + pol.set_vout_pol(VOUT_POLS[pol.name]) + pol.read_vout_set() + + + +class PolClass: + # + # Class to read all monitoring points Point of Load DC/DC converter + # + def __init__(self, name): + # + # All monitoring points Point of Load DC/DC converter + # + self.name = name + self.vout = 0 + self.iout = 0 + self.temp = 0 + self.pol_dev = I2C(CTR_POLS[self.name]) + self.pol_dev.bus_nr = I2CBUSNR + ret_ack, ret_value = self.pol_dev.read_bytes(1) + if ret_ack < 1: + stri = " Device {0} at address 0x{1:X} not found".format(self.name, CTR_POLS[self.name]) + print(stri) + self.status = False + else: + self.status = True + + + def read_vout_set(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_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 + print(f"Output set to: = {output_value} V using hex value {raw_value}") + return True + + def set_vout_pol(self, value): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + 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]) + 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 True + + + def read_vout(self): + # + # Function to read the output voltage of the Point of Load DC/DC converter + # + if self.status: + ret_ack, vout_mod = self.pol_dev.read_bytes(LP_VOUT_MODE, 1) + ret_ack, raw_value = self.pol_dev.read_bytes(LP_VOUT, 2) + vout_mod = int(vout_mod, 16) + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + ret_value.append(int(raw_value[2:], 16)) + self.vout = calc_lin_3bytes(ret_value, [vout_mod]) + else: + self.vout = 999 + + def read_iout(self): + # + # Function to read the output current of the Point of Load DC/DC converter + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(0x39,2) + ret_ack, raw_value = self.pol_dev.read_bytes(LP_IOUT, 2) + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + ret_value.append(int(raw_value[2:], 16)) + self.iout = calc_lin_2bytes(ret_value) + else: + self.iout = 999 + + def read_temp(self): + # + # Function to read the temperature of the Point of Load DC/DC converter + # + if self.status: + ret_ack, raw_value = self.pol_dev.read_bytes(LP_temp, 2) + ret_value = [] + ret_value.append(int(raw_value[:2], 16)) + ret_value.append(int(raw_value[2:], 16)) + self.temp = calc_lin_2bytes(ret_value) + else: + self.temp = 999 + + def read_all(self): + # + # Function to read all monitoring points of the Point of Load DC/DC converter + # + self.read_vout() + self.read_iout() + self.read_temp() + + 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) + print(stri) + self.read_vout_set() + +class FanmonitorClass: + # + # Class to read all monitoring points Point of Load DC/DC converter + # + def __init__(self): + # + # All monitoring points Point of Load DC/DC converter + # + self.rpm = [] + self.fanmonitor_dev = I2C(MAX6620) + self.fanmonitor_dev.bus_nr = I2CBUSNR + ret_ack, ret_value = self.fanmonitor_dev.read_bytes(1) + if ret_ack < 1: + stri = " Device {0} at address 0x{1:X} not found".format("MAX6620", MAX6620) + print(stri) + self.status = False + else: + if DEBUG: + stri = "Device {0} at address 0x{1:X} is found ".format("MAX6620", MAX6620) + print(stri) + self.set_active() + self.status = True + + def set_active(self): + # + # Function to activate monitoring + # + ret_ack, reg_before = self.fanmonitor_dev.read_bytes(REG_GLOBAL, 1) + 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) + print(stri) + fan_config_reg = int((math.log(TACH_PERIODS) / math.log(2))) << 5 + for fan_cnt in range(NOF_APS_FANS): + self.fanmonitor_dev.write_bytes(0x02 + fan_cnt, 0x88) + self.fanmonitor_dev.write_bytes(0x06 + fan_cnt, fan_config_reg) + + def read_fan(self, fan_nr): + # + # Function to a single fan + # + 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 + rpm = 0 + else: + ret_ack, tach_lsb = self.fanmonitor_dev.read_bytes(REG_TACH_LSP_REGS[fan_nr], 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}".format(tach_msb, tach_lsb, tach) + print(stri) + return rpm + + def read_all(self): + # + # Function to read all fan's + # + for fan_counter in range(NOF_APS_FANS): + self.rpm.append(self.read_fan(fan_counter)) + + 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 = "Fan speeds of " + for fan_cnt in range(len(self.rpm)): + stri += "FAN_" + str(fan_cnt+1) + stri += " :{0: <5.2f} RPM ".format(self.rpm[fan_cnt]) + print(stri) + + +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.set_pols() + apspu.read_all() + apspu.print_status() + + +if __name__ == "__main__": + main() -- GitLab