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()
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()
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()
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()
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()
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()
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
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')
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)