Example #1
0
 def writeIntReg(self, adx, value):
     with self.factoryContext():
         reg = IntReg('x', adx, Unit.NONE, 1)
         reg.set('x', int(value))
         cmd = self.writeCmd(reg.adx, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
Example #2
0
 def setPackCapRem(self, value):
     with self.factoryContext():
         reg = IntReg('mah', self.CAP_REM_REG, Unit.MAH, 10)
         reg.set('mah', value)
         cmd = self.writeCmd(reg.adx, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
Example #3
0
 def calDsgCurrent(self, value):
     with self.factoryContext(True):
         reg = IntReg('ma', self.I_CAL_DSG_REG, Unit.MA, 10)
         reg.set('ma', value)
         cmd = self.writeCmd(reg.adx, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
Example #4
0
 def calIdleCurrent(self):
     with self.factoryContext():
         reg = IntReg('ma', self.I_CAL_IDLE_REG, Unit.MA, 10)
         reg.set('ma', 0)
         cmd = self.writeCmd(self.I_CAL_IDLE_REG, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
Example #5
0
 def chgDsgEnable(self, chgEnable, dsgEnable):
     ce = 0 if chgEnable else 1
     de = 0 if dsgEnable else 1
     value = ce | (de << 1)
     with self.factoryContext():
         reg = IntReg('x', self.CHG_DSG_EN_REG, Unit.NONE, 1)
         reg.set('x', value)
         cmd = self.writeCmd(reg.adx, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
Example #6
0
 def _balTestWrite(self, value):
     # Intentionally don't exit factory here
     try:
         self.open()
         self.enterFactory()
         reg = IntReg('x', self.BAL_CTRL_REG, Unit.NONE, 1)
         reg.set('x', value)
         cmd = self.writeCmd(reg.adx, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
     finally:
         self.close()
Example #7
0
 def calCell(self, cells, progressFunc=None):
     'cells is a dict of cell # (base 0) to mV'
     with self.factoryContext():
         cur = 0
         cnt = len(cells)
         for n, v in cells.items():
             adx = self.CELL_CAL_REG_START + n
             if adx > self.CELL_CAL_REG_END: continue
             reg = IntReg('cal', adx, Unit.MV, 1)
             reg.set('cal', v)
             cmd = self.writeCmd(adx, reg.pack())
             self.s.write(cmd)
             #print(' '.join(f'{i:02X}' for i in cmd))
             ok, payload = self.readPacket()
             if not ok: raise BMSError()
             if payload is None: raise TimeoutError()
             if progressFunc: progressFunc(cur / cnt)
             cur += 1
Example #8
0
 def readIntReg(self, adx):
     with self.factoryContext():
         reg = IntReg('x', adx, Unit.NONE, 1)
         cmd = self.readCmd(reg.adx, reg.pack())
         self.s.write(cmd)
         ok, payload = self.readPacket()
         if not ok: raise BMSError()
         if payload is None: raise TimeoutError()
         reg.unpack(payload)
         return reg.get('x')
Example #9
0
    def __init__(self, s, timeout=1, debug=False):
        self.s = serial.Serial(port=s,
                               baudrate=9600,
                               bytesize=8,
                               parity='N',
                               stopbits=1,
                               timeout=1)
        try:
            self.s.close()
            s.timeout = timeout
        except:
            pass
        self._open_cnt = 0
        #self._lock = threading.RLock()
        self.timeout = timeout
        self.debug = debug
        self.writeNVMOnExit = False

        self.eeprom_regs = [
            ### EEPROM settings
            ## Settings
            # Basic Parameters
            IntReg('covp', 0x24, Unit.MV, 1),
            IntReg('covp_rel', 0x25, Unit.MV, 1),
            IntReg('cuvp', 0x26, Unit.MV, 1),
            IntReg('cuvp_rel', 0x27, Unit.MV, 1),
            IntReg('povp', 0x20, Unit.MV, 10),
            IntReg('povp_rel', 0x21, Unit.MV, 10),
            IntReg('puvp', 0x22, Unit.MV, 10),
            IntReg('puvp_rel', 0x23, Unit.MV, 10),
            TempReg('chgot', 0x18),
            TempReg('chgot_rel', 0x19),
            TempReg('chgut', 0x1a),
            TempReg('chgut_rel', 0x1b),
            TempReg('dsgot', 0x1c),
            TempReg('dsgot_rel', 0x1d),
            TempReg('dsgut', 0x1e),
            TempReg('dsgut_rel', 0x1f),
            IntReg('chgoc', 0x28, Unit.MA, 10),
            IntReg('dsgoc', 0x29, Unit.MA, 10),
            DelayReg('cell_v_delays', 0x3d, 'cuvp_delay', 'covp_delay'),
            DelayReg('pack_v_delays', 0x3c, 'puvp_delay', 'povp_delay'),
            DelayReg('chg_t_delays', 0x3a, 'chgut_delay', 'chgot_delay'),
            DelayReg('dsg_t_delays', 0x3b, 'dsgut_delay', 'dsgot_delay'),
            DelayReg('chgoc_delays', 0x3e, 'chgoc_delay', 'chgoc_rel'),
            DelayReg('dsgoc_delays', 0x3f, 'dsgoc_delay', 'dsgoc_rel'),

            # High Protection Configuration
            IntReg('covp_high', 0x36, Unit.MV, 1),
            IntReg('cuvp_high', 0x37, Unit.MV, 1),
            ScDsgoc2Reg('sc_dsgoc2', 0x38),
            CxvpHighDelayScRelReg('cxvp_high_delay_sc_rel', 0x39),

            # Function Configuration
            BitfieldReg('func_config', 0x2d, 'switch', 'scrl', 'balance_en',
                        'chg_balance_en', 'led_en', 'led_num'),

            # NTC Configuration
            BitfieldReg('ntc_config', 0x2e, *(f'ntc{i+1}' for i in range(8))),

            # Balance Configuration
            IntReg('bal_start', 0x2a, Unit.MV, 1),
            IntReg('bal_window', 0x2b, Unit.MV, 1),

            # Other Configuration
            IntReg('shunt_res', 0x2c, Unit.MO, .1),
            IntReg('cell_cnt', 0x2f, int, 1),
            IntReg('cycle_cnt', 0x17, int, 1),
            IntReg('serial_num', 0x16, int, 1),
            StringReg('mfg_name', 0xa0),
            StringReg('device_name', 0xa1),
            StringReg('barcode', 0xa2),
            DateReg('mfg_date', 0x15),

            # Capacity Config
            IntReg('design_cap', 0x10, Unit.MAH, 10),
            IntReg('cycle_cap', 0x11, Unit.MAH, 10),
            IntReg('dsg_rate', 0x14, Unit.PCT,
                   .1),  # presuming this means rate of self-discharge
            IntReg('cap_100', 0x12, Unit.MV, 1),  # AKA "Full Chg Vol"
            IntReg('cap_80', 0x32, Unit.MV, 1),
            IntReg('cap_60', 0x33, Unit.MV, 1),
            IntReg('cap_40', 0x34, Unit.MV, 1),
            IntReg('cap_20', 0x35, Unit.MV, 1),
            IntReg('cap_0', 0x13, Unit.MV, 1),  # AKA "End of Dsg VOL"
            IntReg('fet_ctrl', 0x30, Unit.S, 1),
            IntReg('led_timer', 0x31, Unit.S, 1),

            # Errors
            ErrorCountReg('error_cnts', 0xaa),
        ]
        self.eeprom_reg_by_valuename = {}
        for reg in self.eeprom_regs:
            map = {k: reg for k in reg.valueNames}
            self.eeprom_reg_by_valuename.update(map)

        self.basicInfoReg = BasicInfoReg('basic_info', 0x03)
        self.cellInfoReg = CellInfoReg('cell_info', 0x04)
        self.deviceInfoReg = DeviceInfoReg('device_info', 0x05)