hitl_tester.modules.bms.charger

Provides controls for the Rigol DL711 Power Supply.

(c) 2020-2024 TurnAround Factor, Inc.

#

CUI DISTRIBUTION CONTROL

Controlled by: DLA J68 R&D SBIP

CUI Category: Small Business Research and Technology

Distribution/Dissemination Controls: PROTECTED BY SBIR DATA RIGHTS

POC: GOV SBIP Program Manager Denise Price, 571-767-0111

Distribution authorized to U.S. Government Agencies only, to protect information not owned by the

U.S. Government and protected by a contractor’s ‘limited rights’ statement, or received with the understanding that

it is not routinely transmitted outside the U.S. Government (determination made September 14, 2024). Other requests

for this document shall be referred to ACOR DLA Logistics Operations (J-68), 8725 John J. Kingman Rd., Suite 4317,

Fort Belvoir, VA 22060-6221

#

SBIR DATA RIGHTS

Contract No.:SP4701-23-C-0083

Contractor Name: TurnAround Factor, Inc.

Contractor Address: 10365 Wood Park Ct. Suite 313 / Ashland, VA 23005

Expiration of SBIR Data Rights Period: September 24, 2029

The Government's rights to use, modify, reproduce, release, perform, display, or disclose technical data or computer

software marked with this legend are restricted during the period shown as provided in paragraph (b)(4) of the Rights

in Noncommercial Technical Data and Computer Software--Small Business Innovative Research (SBIR) Program clause

contained in the above identified contract. No restrictions apply after the expiration date shown above. Any

reproduction of technical data, computer software, or portions thereof marked with this legend must also reproduce

the markings.

  1"""
  2Provides controls for the Rigol DL711 Power Supply.
  3
  4# (c) 2020-2024 TurnAround Factor, Inc.
  5#
  6# CUI DISTRIBUTION CONTROL
  7# Controlled by: DLA J68 R&D SBIP
  8# CUI Category: Small Business Research and Technology
  9# Distribution/Dissemination Controls: PROTECTED BY SBIR DATA RIGHTS
 10# POC: GOV SBIP Program Manager Denise Price, 571-767-0111
 11# Distribution authorized to U.S. Government Agencies only, to protect information not owned by the
 12# U.S. Government and protected by a contractor’s ‘limited rights’ statement, or received with the understanding that
 13# it is not routinely transmitted outside the U.S. Government (determination made September 14, 2024). Other requests
 14# for this document shall be referred to ACOR DLA Logistics Operations (J-68), 8725 John J. Kingman Rd., Suite 4317,
 15# Fort Belvoir, VA 22060-6221
 16#
 17# SBIR DATA RIGHTS
 18# Contract No.:SP4701-23-C-0083
 19# Contractor Name: TurnAround Factor, Inc.
 20# Contractor Address: 10365 Wood Park Ct. Suite 313 / Ashland, VA 23005
 21# Expiration of SBIR Data Rights Period: September 24, 2029
 22# The Government's rights to use, modify, reproduce, release, perform, display, or disclose technical data or computer
 23# software marked with this legend are restricted during the period shown as provided in paragraph (b)(4) of the Rights
 24# in Noncommercial Technical Data and Computer Software--Small Business Innovative Research (SBIR) Program clause
 25# contained in the above identified contract. No restrictions apply after the expiration date shown above. Any
 26# reproduction of technical data, computer software, or portions thereof marked with this legend must also reproduce
 27# the markings.
 28"""
 29
 30from __future__ import annotations
 31
 32import atexit
 33from time import sleep
 34
 35from hitl_tester.modules.bms.plateset import Plateset
 36from hitl_tester.modules.bms_types import SafeResource
 37from hitl_tester.modules.logger import logger
 38
 39MAX_ATTEMPTS = 60
 40
 41
 42class Charger:
 43    """Rigol DL711 Power Supply command wrapper."""
 44
 45    def __init__(self, resource: SafeResource):
 46        """
 47        Initialize the DL711 wrapper with a specific PyVISA resource.
 48        This class does NOT open the resource, you have to open it for yourself!
 49        """
 50        self.resource = resource
 51        self.target_amps: float = 0
 52        self.target_volts: float = 0
 53        self.reset()
 54
 55        @atexit.register
 56        def __atexit__():
 57            """Configure a safe shut down for when the class instance is destroyed."""
 58            self.disable()
 59
 60    def __call__(self, volts: float, amps: float, ce_switch: bool = True):
 61        self.set_profile(volts, amps)
 62        Plateset().ce_switch = ce_switch
 63        return self
 64
 65    def __enter__(self):
 66        self.enable()
 67        return self
 68
 69    def __exit__(self, exc_type, exc_value, exc_traceback):
 70        self.disable()
 71        Plateset().ce_switch = False
 72
 73    def set_profile(self, volts: float, amps: float):
 74        """Sets charging profile"""
 75        self.target_volts = volts
 76        self.target_amps = amps
 77        self.resource.write(f":APPL {volts}, {amps}")
 78        sleep(1)  # The charger needs time to process the previous commands
 79
 80    def _amps_limit(self, new_amps_limit: float):
 81        """Sets output current limit"""
 82        self.resource.write(f":CURR:PROT {new_amps_limit}")
 83
 84    def _volts_limit(self, new_volts_limit: float):
 85        """Sets output voltage limit"""
 86        self.resource.write(f":VOLT:PROT {new_volts_limit}")
 87
 88    amps_limit = property(None, _amps_limit)  # make this function accessible as a write-only attribute
 89    volts_limit = property(None, _volts_limit)  # make this function accessible as a write-only attribute
 90
 91    @property
 92    def amps(self) -> float:
 93        """Reads the current being sourced"""
 94        return float(self.resource.query(":MEAS:CURR?"))
 95
 96    @amps.setter
 97    def amps(self, new_amps: float):
 98        """Sets the power supply output current"""
 99        self.target_amps = new_amps
100        self.resource.write(f":CURR {new_amps}")
101
102    @property
103    def volts(self) -> float:
104        """Reads the volts being sourced"""
105        return float(self.resource.query(":MEAS:VOLT?"))
106
107    @volts.setter
108    def volts(self, new_volts: float):
109        """Sets the power supply output voltage"""
110        self.target_volts = new_volts
111        self.resource.write(f":VOLT {new_volts}")
112
113    def enable(self):
114        """Enables power supply output"""
115        logger.write_info_to_report("Enabling charger")
116        sleep(1)
117        Plateset().charger_switch = True  # Turn on the charger switch
118        sleep(1)
119        self.resource.write(":OUTP:STAT ON")
120        sleep(1)  # This instrument needs time to initialize
121
122    def disable(self):
123        """Disables power supply output"""
124        logger.write_info_to_report("Disabling charger")
125        Plateset().charger_switch = False  # Turn off the charger switch
126        self.resource.write(":OUTP:STAT OFF")
127        sleep(1)  # The charger needs time to process the previous commands
128
129    def reset(self):
130        """Resets the instrument"""
131        self.resource.write("*RST")
132        sleep(3)
MAX_ATTEMPTS = 60
class Charger:
 43class Charger:
 44    """Rigol DL711 Power Supply command wrapper."""
 45
 46    def __init__(self, resource: SafeResource):
 47        """
 48        Initialize the DL711 wrapper with a specific PyVISA resource.
 49        This class does NOT open the resource, you have to open it for yourself!
 50        """
 51        self.resource = resource
 52        self.target_amps: float = 0
 53        self.target_volts: float = 0
 54        self.reset()
 55
 56        @atexit.register
 57        def __atexit__():
 58            """Configure a safe shut down for when the class instance is destroyed."""
 59            self.disable()
 60
 61    def __call__(self, volts: float, amps: float, ce_switch: bool = True):
 62        self.set_profile(volts, amps)
 63        Plateset().ce_switch = ce_switch
 64        return self
 65
 66    def __enter__(self):
 67        self.enable()
 68        return self
 69
 70    def __exit__(self, exc_type, exc_value, exc_traceback):
 71        self.disable()
 72        Plateset().ce_switch = False
 73
 74    def set_profile(self, volts: float, amps: float):
 75        """Sets charging profile"""
 76        self.target_volts = volts
 77        self.target_amps = amps
 78        self.resource.write(f":APPL {volts}, {amps}")
 79        sleep(1)  # The charger needs time to process the previous commands
 80
 81    def _amps_limit(self, new_amps_limit: float):
 82        """Sets output current limit"""
 83        self.resource.write(f":CURR:PROT {new_amps_limit}")
 84
 85    def _volts_limit(self, new_volts_limit: float):
 86        """Sets output voltage limit"""
 87        self.resource.write(f":VOLT:PROT {new_volts_limit}")
 88
 89    amps_limit = property(None, _amps_limit)  # make this function accessible as a write-only attribute
 90    volts_limit = property(None, _volts_limit)  # make this function accessible as a write-only attribute
 91
 92    @property
 93    def amps(self) -> float:
 94        """Reads the current being sourced"""
 95        return float(self.resource.query(":MEAS:CURR?"))
 96
 97    @amps.setter
 98    def amps(self, new_amps: float):
 99        """Sets the power supply output current"""
100        self.target_amps = new_amps
101        self.resource.write(f":CURR {new_amps}")
102
103    @property
104    def volts(self) -> float:
105        """Reads the volts being sourced"""
106        return float(self.resource.query(":MEAS:VOLT?"))
107
108    @volts.setter
109    def volts(self, new_volts: float):
110        """Sets the power supply output voltage"""
111        self.target_volts = new_volts
112        self.resource.write(f":VOLT {new_volts}")
113
114    def enable(self):
115        """Enables power supply output"""
116        logger.write_info_to_report("Enabling charger")
117        sleep(1)
118        Plateset().charger_switch = True  # Turn on the charger switch
119        sleep(1)
120        self.resource.write(":OUTP:STAT ON")
121        sleep(1)  # This instrument needs time to initialize
122
123    def disable(self):
124        """Disables power supply output"""
125        logger.write_info_to_report("Disabling charger")
126        Plateset().charger_switch = False  # Turn off the charger switch
127        self.resource.write(":OUTP:STAT OFF")
128        sleep(1)  # The charger needs time to process the previous commands
129
130    def reset(self):
131        """Resets the instrument"""
132        self.resource.write("*RST")
133        sleep(3)

Rigol DL711 Power Supply command wrapper.

Charger(resource: hitl_tester.modules.bms_types.SafeResource)
46    def __init__(self, resource: SafeResource):
47        """
48        Initialize the DL711 wrapper with a specific PyVISA resource.
49        This class does NOT open the resource, you have to open it for yourself!
50        """
51        self.resource = resource
52        self.target_amps: float = 0
53        self.target_volts: float = 0
54        self.reset()
55
56        @atexit.register
57        def __atexit__():
58            """Configure a safe shut down for when the class instance is destroyed."""
59            self.disable()

Initialize the DL711 wrapper with a specific PyVISA resource. This class does NOT open the resource, you have to open it for yourself!

resource
target_amps: float
target_volts: float
def set_profile(self, volts: float, amps: float):
74    def set_profile(self, volts: float, amps: float):
75        """Sets charging profile"""
76        self.target_volts = volts
77        self.target_amps = amps
78        self.resource.write(f":APPL {volts}, {amps}")
79        sleep(1)  # The charger needs time to process the previous commands

Sets charging profile

amps_limit
volts_limit
amps: float
92    @property
93    def amps(self) -> float:
94        """Reads the current being sourced"""
95        return float(self.resource.query(":MEAS:CURR?"))

Reads the current being sourced

volts: float
103    @property
104    def volts(self) -> float:
105        """Reads the volts being sourced"""
106        return float(self.resource.query(":MEAS:VOLT?"))

Reads the volts being sourced

def enable(self):
114    def enable(self):
115        """Enables power supply output"""
116        logger.write_info_to_report("Enabling charger")
117        sleep(1)
118        Plateset().charger_switch = True  # Turn on the charger switch
119        sleep(1)
120        self.resource.write(":OUTP:STAT ON")
121        sleep(1)  # This instrument needs time to initialize

Enables power supply output

def disable(self):
123    def disable(self):
124        """Disables power supply output"""
125        logger.write_info_to_report("Disabling charger")
126        Plateset().charger_switch = False  # Turn off the charger switch
127        self.resource.write(":OUTP:STAT OFF")
128        sleep(1)  # The charger needs time to process the previous commands

Disables power supply output

def reset(self):
130    def reset(self):
131        """Resets the instrument"""
132        self.resource.write("*RST")
133        sleep(3)

Resets the instrument