Exemplo n.º 1
0
	def CN2(self):
		"""
		Sent CAN Message Sentence
		reports the CAN messages sent on CAN bus if "Send to RS232/USB function is enabled.
		"""
		#construct the sentence.
		sentence = "CN2,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		#receive the response.
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "CN2"
		CANIdentifier = int(r[1],16)
		identifierExtensionFlag = True if r[2] == '1' else False
		remoteTransmissionRequestFlag = True if r[3] == '1' else False
		dataLength = int(r[4],10)
		line = [r[5][i:i+2] for i in range(0,len(r[5]),2)]
		data = {}
		data['CAN Identifier'] = CANIdentifier
		data['Identifier Extension Used'] = identifierExtensionFlag
		data['Remote Transmission Used'] = remoteTransmissionRequestFlag
		data['Data Length'] = dataLength
		data['Unprocessed CAN Data'] = line
		return data
Exemplo n.º 2
0
	def BB1(self):
		sentence = "BB1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BB1"
		
		if r[1] == '':
			#EMUS BMS control unit cannot communicate to cells.
			print("BMS cannot communicate to the cells.")
			return {"BMS cannot communicate to the cells."}
		else:
			numberOfCells = int(r[1])
			minCellBalancingRate = int(r[2],16)*100/255
			maxCellBalancingRate = int(r[3],16)*100/255
			averageCellBalancingRate = int(r[3],16)*100/255
			#r[4] is always empty
			balancingVoltageThreshold = (int(r[4],16)+200)*0.01
			data = {}
			data['number of cells'] = numberOfCells
			data['minimum cell balancing rate'] = minCellBalancingRate
			data['maximum cell balancing rate'] = maxCellBalancingRate
			data['average cell balancing rate'] = averageCellBalancingRate
			data['balancing voltage threshold'] = balancingVoltageThreshold
			return data
Exemplo n.º 3
0
	def BV1(self):
		sentence = "BV1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BV1"
		
		if r[1] == '':
			return {"Cannot communicate to cells."}
		else:
			numberOfCells = int(r[1],16)
			minCellVoltage = (int(r[2],16) + 200 ) * 0.01
			maxCellVoltage = (int(r[3],16) + 200 ) * 0.01
			averageCellVoltage = (int(r[4],16) + 200 ) * 0.01
			totalVoltage = (int(r[2],16) ) * 0.01
			data = {}
			data['number of cells'] = numberOfCells
			data['minimum cell voltage'] = minCellVoltage
			data['maximum cell voltage'] = maxCellVoltage
			data['average cell voltage'] = averageCellVoltage
			data['total voltage'] = totalVoltage 
			return data
Exemplo n.º 4
0
	def BT3(self):
		"""
		Battery Cell Temperature Summary Sentence
		This sentence contains the summary of cell temperature values of the battery pack. It is sent periodically with configurable time intervals for active and sleep states (Data Transmission to Display Period).		
		"""
		sentence = "BT3,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BT3"
		
		if r[1] == '':
			return {"Cells cannot be communicated to."}
		else:
			data = {}
			numberOfCells = int(r[1],16)
			minCellTemp = int(r[2],16) - 100
			maxCellTemp = int(r[3],16) - 100
			averageCellTemp = int(r[4],16) - 100
			data['number of cells'] = numberOfCells
			data['minimum cell temperature'] = minCellTemp
			data['maximum cell temperature'] = maxCellTemp
			data['average cell temperature'] = averageCellTemp
			return data
Exemplo n.º 5
0
	def BT1(self):
		"""
		Battery Cell Module Temperature Summary Sentence
		This sentence contains the summary of cell module temperature values of the battery pack.
		
		"""
		sentence = "BT1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BT1"
		if r[1] == '':
			return []
		else:	
			numberOfCells = int(r[1],16)
			minCellModuleTemp = int(r[2],16) - 100
			maxCellModuleTemp = int(r[3],16) - 100
			averageCellModuleTemp = int(r[4],16) - 100
			data = {}
			data['number of cells'] = numberOfCells
			data['minimum cell module temperature'] = minCellModuleTemp
			data['maximum cell module temperature'] = maxCellModuleTemp
			data['average cell module temperature'] = averageCellModuleTemp
			return data
Exemplo n.º 6
0
	def TD1(self):
		"""
		Time and date according to the BMS unit.
		"""
		sentence = "TD1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
	
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == 'TD1'
		year = int(r[1],10)
		month = int(r[2],10)
		day = int(r[3],10)
		hour = int(r[4],10)
		minute = int(r[5],10)
		second = int(r[6],10)
		uptime = int(r[7],16)
		data = {}
		data['year'] = year
		data['month'] = month
		data['day'] = day
		data['hour'] = hour
		data['minute'] = minute
		data['second'] = second
		data['uptime'] = uptime
		return data
Exemplo n.º 7
0
	def CS1(self):
		"""
			contains the parameters and status of the charger.
			
		"""
		sentence = "CS1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "CS1"
		
		numberOfConnectedChargers = int(r[1],16)
		CANChargerStatus = int(r[2],16) #consult the CAN charger manual for the meaning.
		setVoltage = int(r[3],16)*0.1
		setCurrent = int(r[4],16)*0.1
		actualVoltage = int(r[5],16)*0.1
		actualCurrent = int(r[6],16)*0.1
		data = {}
		data['set voltage'] = setVoltage
		data['set current'] = setCurrent
		data['actual voltage'] = actualVoltage
		data['actual current'] = actualCurrent
		data['number of connected chargers'] = numberOfConnectedChargers
		data['CAN Charger Status'] = CANChargerStatus
		return data
Exemplo n.º 8
0
	def	ST1(self):
		"""
			BMS Status sentence
		"""
		#construct the sentence, and send it.
		sentence = "ST1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
	
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == 'ST1'
		#let's use a dictionary for easy reading.
		chargingStageDict = {
			0 : "Charger Disconnected",
			1 : "Pre-Heating Stage",
			2 : "Pre-Charging Stage",
			3 : "Main Charging Stage",
			4 : "Balancing Stage",
			5 : "Charging Finished",
			6 : "Charging Error"
		}
		chargingErrorDict = { 
			0 : "No error",
			1 : " No cell communication at the start of charging or communication lost during Pre-charging (using CAN charger), cannot charge",
			2 : " No cell communication (using non-CAN charger), cannot charge",
			3 : " Maximum charging stage duration expired;",
			4 : " Cell communication lost during Main Charging or Balancing stage (using CAN charger), cannot continue charging",
			5 : " Cannot set cell module balancing threshold; ",
			6 : " Cell or cell module temperature too high;",
			7 : " Cell communication lost during Pre-heating stage (using CAN charger);",
			8 : " Number of cells mismatch;",
			9 : " Cell over-voltage;",
			10 : " Cell protection event occurred."
		}
		data = {}
		#find all the errors using the dictionaries above.
		data['charging stage'] = chargingStageDict[int(r[1],16)]
		data['last charging error'] = chargingErrorDict[int(r[2],16)]
		data['last charging error parameter'] = int(r[3],16)
		data['stage duration'] = int(r[4],16) # in seconds.
		
		#bitfields.
		status_bitfield = int(r[5],16)
		
			
		data['Valid cell voltages'],data['Valid balancing rates'],data['valid number of live cells'], data['battery charging finished'],data['valid cell temperatures']=bitAt(status_bitfield,0),bitAt(status_bitfield,1),bitAt(status_bitfield,2),bitAt(status_bitfield,3),bitAt(status_bitfield,4),bitAt(status_bitfield,5)
		
		protection_bitfield = int(r[6],16)
		
		data['undervoltage'],data['overvoltage'],data['discharge overcurrent'],data['charge overcurrent'],data['cell module overheat'],data['leakage'],data['no_cell_comm,cell_overheat'] = bitAt(protection_bitfield,0),bitAt(protection_bitfield,1),bitAt(protection_bitfield,2),bitAt(protection_bitfield,3),bitAt(protection_bitfield,4),bitAt(protection_bitfield,5),bitAt(protection_bitfield,6),bitAt(protection_bitfield,11)
		
		power_bitfield = int(r[7],16)
		data['warning: power reduction: low voltage'],data['warning: power reduction: high current'],data['warning: power reduction: high cell module temperature'], data['warning: power reduction: high cell temperature'] = bitAt(power_bitfield,0),bitAt(power_bitfield,1),bitAt(power_bitfield,2),bitAt(power_bitfield,5)
		
		pin_bitfield = int(r[8],16)
		data['no_function'],data['speed_sensor'],data['fast_charge_switch'],data['ign_key'],data['charger_mains_AC_sense'],data[' heater_enable'],data['sound_buzzer'],data['battery_low'],data['charging_indication'],data['charger_enable_output'],data['state_of_charge'],data['battery_contactor'],data['battery_fan'],data['current_sensor'],data['leakage_sensor'],data['power_reduction'],data['charging_interlock'],data[' analog_charger_control'],data[' ZVU_boost_charge'],data['ZVU_slow_charge'],data['ZVU_buffer_mode'],data['BMS_failure'],data['equalization_enable'],data['DCDC_control'],data['ESM_rectifier_current_limit'],data['contactor_precharge'] = bitAt(pin_bitfield,0),bitAt(pin_bitfield,1),bitAt(pin_bitfield,2),bitAt(pin_bitfield,3),bitAt(pin_bitfield,4),bitAt(pin_bitfield,5),bitAt(pin_bitfield,6),bitAt(pin_bitfield,7),bitAt(pin_bitfield,8),bitAt(pin_bitfield,9),bitAt(pin_bitfield,10),bitAt(pin_bitfield,11),bitAt(pin_bitfield,12),bitAt(pin_bitfield,13),bitAt(pin_bitfield,14),bitAt(pin_bitfield,15),bitAt(pin_bitfield,16),bitAt(pin_bitfield,17),bitAt(pin_bitfield,18),bitAt(pin_bitfield,19),bitAt(pin_bitfield,20),bitAt(pin_bitfield,21),bitAt(pin_bitfield,22),bitAt(pin_bitfield,23),bitAt(pin_bitfield,24),bitAt(pin_bitfield,25),bitAt(pin_bitfield,26),
		return data
Exemplo n.º 9
0
	def IN1(self):
		"""
			Input Pins status.
			AC Sense plugged in,
			IGN. In plugged in,
			Fast Chg plugged in.
		"""
		sentence = "IN1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "IN1"
		bitField = int(r[1],16)
		AC_SENSE = True if (bitField & 0x08) else False 
		IGN_IN  = True if (bitField & 0x10) else False 
		FAST_CHG = True if (bitField & 0x20) else False
		data = {}
		data['AC SENSE'] = AC_SENSE
		data['IGN IN'] = IGN_IN
		data['FAST CHG'] = FAST_CHG
		return data
Exemplo n.º 10
0
	def OT1(self):
		"""
			Returns status of output pins.
			[Charger pin, heater, bat. low, buzzer, chg. ind.]
		"""
		sentence = "OT1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "OT1"
		
		CHARGER_PIN = True if (int(r[1],16) & 0x40) else False
		bitfield = int(r[3],16)
		HEATER = True if (bitfield & 0x08) else False
		BAT_LOW = True if (bitfield & 0x10) else False
		BUZZER = True if (bitfield & 0x20) else False
		CHG_IND = True if (bitfield & 0x40) else False 
		data = {}
		data['CHARGER_PIN'] = CHARGER_PIN
		data['HEATER'] = HEATER
		data['BAT_LOW'] = BAT_LOW
		data['BUZZER'] = BUZZER
		data['CHG_IND'] = CHG_IND
		return data
Exemplo n.º 11
0
	def CN1(self):	
		"""
		Received CAN Message Sentence	
		This sentence reports the CAN messages received on CAN bus by Emus BMS Control Unit, if “Send to RS232/USB” function is enabled.

		"""
		#construct the sentence, and send it.
		sentence = "CN1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		#get the response. should only be 1 line.
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "CN1"
		data = {}
		CANIdentifier = int(r[1],16)
		identifierExtensionFlag = True if r[2] == '1' else False
		remoteTransmissionRequestFlag = True if r[3] == '1' else False
		dataLength = int(r[4],10)
		data['CAN Identifier'] = CANIdentifier
		data['Identifier Extension Used'] = identifierExtensionFlag
		data['Remote Transmission Used'] = remoteTransmissionRequestFlag
		data['Data Length'] = dataLength
		line = [r[5][i:i+2] for i in range(0,len(r[5]),2)]
		data['Unprocessed CAN Data'] = line
		return data
Exemplo n.º 12
0
	def BV2(self):
		"""
		Battery Voltage Detail Sentence
		This sentence contains individual voltages of a group of cells. Each group consists of 1 to 8 cells.
		"""
		#construct the sentence, then send it.
		sentence = "BV2,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		#get the response, and check if it's valid.
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BV2"
		
		#check for empty string. if it's empty, return an empty array.
		if r[1] == '':
			return {"Cannot communicate to cells."}
		else:
			data = {}
			cell_group_1 = {}
			cell_group_1['cell string number'] = int(r[1],16)
			cell_group_1['cell number of first cell in group'] = int(r[2],16)
			cell_group_1['size of group'] = int(r[3],16)
			line = r[4]
			n = 2
			individual_cells = [line[i:i+n] for i in range(0, len(line), n)]
			individual_cells_dict = {}
			i = 1
			for cell in individual_cells:	
				individual_cells_dict['cell '+str(i)] = int(cell, 16)
				i += 1
			cell_group_1['individual cell voltages'] = individual_cells_dict
			data['cell group 1'] = cell_group_1
			limit = int(r[3],16)
			for x in range(limit-1):
				#read the next sentence, and intepret it
				response = self.ser.readline().decode('ascii')
				assert crc8(response[:2]) == int(response[-2:]) # crc check
				r = response.split(',')
				assert r[0] == "BV2"
				
				cell_group_x = {}
				cell_group_x['cell string number'] = int(r[1],16)
				cell_group_x['cell number of first cell in group'] = int(r[2],16)
				cell_group_x['size of group'] = int(r[3],16)
				line = r[4]
				n = 2
				individual_cells = [line[i:i+n] for i in range(0, len(line), n)]
				individual_cells_dict = {}
				i = 1
				for cell in individual_cells:	
					individual_cells_dict['cell '+str(i)] = int(cell, 16)
					i += 1
				cell_group_x['individual cell voltages'] = individual_cells_dict
				data['cell group ' + str(x+2)] = cell_group_x				
			return data
Exemplo n.º 13
0
	def BT2(self):
		"""
			Battery Cell Module Temperature Detail Sentence
			
			This sentence contains individual cell module temperatures of a group of cells. Each group consists of 1 to 8 cells. This sentence is sent only after Control Unit receives a request sentence from external device, where the only data field is ‘?’ symbol. The normal response to BT2 request message, when battery pack is made up of two parallel cell strings:

		"""
		sentence = "BT2,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BT2"
		if r[1] == '':
			return {"Cells cannot be communicated to."}
		else:
			data = {}
			cell_group_1 = {}
			cell_group_1['cell string number'] = int(r[1],16)
			cell_group_1['cell number of first cell in group'] = int(r[2],16)
			cell_group_1['size of group'] = int(r[3],16)
			# individual cell module temperatures
			line = r[4]
			n = 2
			individual_cells = [line[i:i+n] for i in range(0, len(line), n)]
			individual_cells_dict = {}
			i = 1
			for cell in individual_cells:	
				individual_cells_dict['cell '+str(i)] = int(cell, 16)
				i += 1
			cell_group_1['individual cell module temperatures'] = individual_cells_dict
			data['cell group 1'] = cell_group_1
			limit = int(r[3],16)
			for i in range(limit-1):
				response = self.ser.readline().decode('ascii')
				assert crc8(response[:2]) == int(response[-2:]) # crc check
				r = response.split(',')
				assert r[0] == "BT2"
				cell_group_x = {}
				cell_group_x['cell string number'] = int(r[1],16)
				cell_group_x['cell number of first cell in group'] = int(r[2],16)
				cell_group_x['size of group'] = int(r[3],16)
				# individual cell module temperatures
				line = r[4]
				n = 2
				individual_cells = [line[i:i+n] for i in range(0, len(line), n)]
				individual_cells_dict = {}
				i = 1
				for cell in individual_cells:	
					individual_cells_dict['cell '+str(i)] = int(cell, 16)
					i += 1
				cell_group_1['individual cell module temperatures'] = individual_cells_dict
				data['cell group '+str(x+2)] = cell_group_x
			return data
Exemplo n.º 14
0
	def BT4(self):
		"""
		BT4 – Battery Cell Temperature Detail Sentence
		This sentence contains individual cell temperatures of a group of cells. Each group consists of 1 to 8 cells. 
		"""
		#construct the sentence
		sentence = "BT4,?,"
		number = crc8(sentence)
		sentence += number
		#send it
		self.execute(sentence)
		
		#ask for a response.
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BT4"
		
		#return an empty dictionary with this error message
		if r[1] == '':
			return {"Cells cannot be communicated to."}
		else:
			data = {}
			cell_group_1 = {}
			cell_group_1['cell string number'] = int(r[1],16)
			cell_group_1['cell number of first cell in group'] = int(r[2],16)
			cell_group_1['size of group'] = int(r[3],16)
			line = r[4]
			n = 2
			individual_cells = [line[i:i+n] for i in range(0, len(line), n)]
			individual_cells_dict = {}
			i = 1
			for cell in individual_cells:	
				individual_cells_dict['cell '+str(i)] = int(cell, 16)
				i += 1
			cell_group_1['individual cell temperatures'] = individual_cells_dict
			data['cell group 1'] = cell_group_1
			limit = int(r[3],16)
			for x in range(limit-1):
				cell_group_x = {}
				cell_group_x['cell string number'] = int(r[1],16)
				cell_group_x['cell number of first cell in group'] = int(r[2],16)
				cell_group_x['size of group'] = int(r[3],16)
				line = r[4]
				n = 2
				individual_cells = [line[i:i+n] for i in range(0, len(line), n)]
				individual_cells_dict = {}
				i = 1
				for cell in individual_cells:	
					individual_cells_dict['cell '+str(i)] = int(cell, 16)
					i += 1
				cell_group_x['individual cell temperatures'] = individual_cells_dict
				data['cell group ' + str(x+2)] = cell_group_x
			return data
Exemplo n.º 15
0
	def BC1(self):
		sentence = "BC1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BC1"
		data = {}
		data['battery charge'] = int(r[1],16)
		data['battery capacity'] = int(r[2],16)
		data['state of charge'] = int(r[3],16)*0.01
		return data
Exemplo n.º 16
0
	def BB2(self):
		sentence = "BB2,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "BB2"
		
		if r[1] == '':
			#EMUS BMS control unit cannot communicate to cells.
			print("BMS cannot communicate to the cells.")
			return {"BMS cannot communicate to the cells."}
		else:
			data = {}
			cellGroups = []
			cellStringNumber = int(r[1],16)
			firstCellNumber = int(r[2],16)
			sizeOfGroup = int(r[3],16)
			individualCellModuleBalancingRate = int(r[4],16)*100/255
			cell_group_1 = {}
			cell_group_1['cell string number'] = cellStringNumber
			cell_group_1['first cell number'] = firstCellNumber
			cell_group_1['size of group'] = sizeOfGroup
			cell_group_1['individual cell module balancing rage'] = individualCellModuleBalancingRate
			data['cell group 1'] = cell_group_1
			for x in range(sizeOfGroup-1):
				response = self.ser.readline().decode('ascii')
				assert crc8(response[:2]) == int(response[-2:]) # crc check
				r = response.split(',')
				assert r[0] == "BB2"
				
				cellStringNumber = int(r[1],16)
				firstCellNumber = int(r[2],16)
				sizeOfGroup = int(r[3],16)
				individualCellModuleBalancingRate = int(r[4],16)*100/255
				cell_group_x = {}
				cell_group_x['cell string number'] = cellStringNumber
				cell_group_x['first cell number'] = firstCellNumber
				cell_group_x['size of group'] = sizeOfGroup
				cell_group_x['individual cell module balancing rage'] = individualCellModuleBalancingRate
				data['cell group ' + str(x+2)] = cell_group_x
			return data
Exemplo n.º 17
0
	def RC1(self):
		"""
			Resets the current sensor reading to zero. Used after current sensor is initially installed.
		"""
		sentence = "RC1,,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		return
Exemplo n.º 18
0
	def FD1(self):
		"""
			This function resets the unit to factory defaults. Use at your own risk.
		"""
		sentence = "FD1,,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		return True
Exemplo n.º 19
0
def c2_add_crc(payload, valido=True):

    hash = crc8()
    hash.update(bytes(payload, 'utf-8'))
    crc = hash.hexdigest()
    if valido:
        payload += str(crc).upper()
    else:
        payload += str(~(hash.hexdigest())).upper()
    return payload
Exemplo n.º 20
0
	def RS1(self):
		"""
			Resets the Emus BMS control unit entirely. Like a sudo reboot on a
			linux machine.
		"""
		sentence = "RS1,,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		return
Exemplo n.º 21
0
	def CV1(self):
		"""
			contains the values of total voltage of battery pack,
			and current flowing through the battery pack.
		"""
		sentence = "CV1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "CV1"
		totalVoltage = int(r[1],16)*0.01
		current = int(r[2],16)*0.1
		data = {}
		data['total voltage'] = totalVoltage
		data['current'] = current
		return data
Exemplo n.º 22
0
	def VR1(self):
		"""
			Returns a dictionary of the hardware type, serial number, and firmware version.
		"""
		sentence = "VR1,?,"
		number = crc8(sentence)
		sentence += str(number)
		self.execute(sentence)
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "VR1"
		#r[1]: hardware type
		#r[2]: serial number
		#r[3]: firmware version
		data = {}
		data['hardware type'] = r[1]
		data['serial number'] = r[2]
		data['firmware version'] = r[3]
		return data
Exemplo n.º 23
0
	def CF2(self, parameterID):
		"""
		parameterID must be an integer.
		
		returns the parameter. Must be processed separately.
		"""
		sentence = "CF2," + str(parameterID.hex()) + ",?"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "CF2"
		assert r[1] == str(parameterID.hex())
		
		data = {}
		data['parameter ID'] = parameterID
		data['unprocessed data'] = r[2]
		return data
Exemplo n.º 24
0
	def CG1(self):
		"""
		Can Devices Status Sentence
		
		This sentence contains the statuses of Emus internal CAN peripherals.

		"""
		sentence = "CG1,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "CG1"
		
		CAN_current_dict = {
			0 :" Not configured",
			1 : "OK",
			2 : "Error",
			3 : "No Response."
		}
		CAN_current_sensor_status = CAN_current_dict[int(r[1],16)]
		
		data = {}
		data['CAN current sensor status'] = CAN_current_sensor_status
		X = 1
		for i in range(3,67,2):
			number_of_cells = int(r[i],16)
			status = CAN_current_dict(int(r[i+1],16))
			#create a separate dictionary for each cell.
			ii = {}
			ii['number of cells'] = number_of_cells
			ii['status'] = status
			#add that dictionary to the data pool as CAN cell group X.
			data['CAN cell group ' + str(X)] = ii 
			X += 1
		return data
Exemplo n.º 25
0
	def PW2(self, request, newPassword=None):
		"""
			Sets a new password, or clears a password.
			Set new password calling: PW2('S',"mynewpassword")
			Clear password: PW2('C')
			Returns true if successful, false if not successful.
		"""
		sentence = "PW2,"
		if request == 'C': #clear password
			sentence += ","
		elif request == 'S': #set a new password
			setence += str(newPassword) + ","
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		if r[0] == "PW2":
			setResult = int(r[1],16)
			return True if setResult == 1 else False
		else:
			return False
Exemplo n.º 26
0
	def PW1(self, request=None, password=None):
		"""
			Check the admin status with PW1('?').
			Log in to BMS system with PW1('P', password)
			Log out with PW1()
		"""
		sentence = "PW1,"
		if request == '?':
			sentence += "?,"
		elif request == 'P':
			sentence += str(password) + ","
		else:
			sentence += ","
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "PW1"
		
		authenticationCode = int(r[1],16)
		return {'authentication code': authenticationCode }
Exemplo n.º 27
0
	def RS2(self):
		"""
		Reset Source History Log Sentence
		This sentence is used to retrieve the reset source history log.
		"""
		sentence = "RS2,?,"
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == 'RS2'
		data = {}
		j = 1
		for i in range(1,10,2):
			timestamp =  int(r[i],16)+ self.y2kInEpoch
			x = int(r[i+1],16)
			POWER_ON_RESET = True if x & 0x1 else False
			EXTERNAL_RESET = True if x & 0x2 else False
			BROWN_OUT_RESET = True if x & 0x4 else False
			WATCHDOG_RESET = True if x & 0x8 else False
			JTAG_RESET = True if x & 0x10 else False
			STACK_OVERFLOW_RESET = True if x & 0x20 else False
			USER_CAUSED_RESET = True if x & 0x40 else False
			ii = {}
			ii['POWER_ON_RESET'] = POWER_ON_RESET
			ii['EXTERNAL_RESET'] = EXTERNAL_RESET
			ii['BROWN_OUT_RESET'] = BROWN_OUT_RESET
			ii['WATCHDOG_RESET'] = WATCHDOG_RESET
			ii['JTAG_RESET'] = JTAG_RESET
			ii['STACK_OVERFLOW_RESET'] = STACK_OVERFLOW_RESET
			ii['USER_CAUSED_RESET'] = USER_CAUSED_RESET
			data['record ' + str(j)] = ii
			j += 1
		return data
Exemplo n.º 28
0
	def SC1(self, percentage):
		"""
		set the current state of the charge of the battery in %.
		send in an integer from 0 to 100.
		this method will convert to hexadecimal format first.
		returns False if not successful or invalid percentage is passed.
		returns True if successful.
		"""
		if not isinstance(percentage, int):
			return False
		elif (percentage < 0 or percentage > 100):
			return False
		else:
			sentence = "SC1," + hex(percentage)[2:].upper() + ","
			number = crc8(sentence)
			sentence += number
			self.execute(sentence)
			return True
Exemplo n.º 29
0
 def call_callback(self, *args):
     cb = self.functions[self.active_cb]
     
     # Start the package with the cmd id
     package = chr(cb.id)
     
     # Add each of the callback args
     for i in range(len(cb.args)):
         form = '<' + cb.args[i]
         package += struct.pack(form, args[i])
     
     # Append the CRC-8 checksum
     package += chr( crc8(package) )
     
     # Send the package
     self.ser.write(package)
     
     # Get the return data (if relevant)
     if cb.ret:
         form = '<' + cb.ret
         size = format_code_to_bytes[cb.ret]
         return struct.unpack(form, self.ser.read(size))[0]
Exemplo n.º 30
0
    def call_callback(self, *args):
        cb = self.functions[self.active_cb]

        # Start the package with the cmd id
        package = chr(cb.id)

        # Add each of the callback args
        for i in range(len(cb.args)):
            form = '<' + cb.args[i]
            package += struct.pack(form, args[i])

        # Append the CRC-8 checksum
        package += chr(crc8(package))

        # Send the package
        self.ser.write(package)

        # Get the return data (if relevant)
        if cb.ret:
            form = '<' + cb.ret
            size = format_code_to_bytes[cb.ret]
            return struct.unpack(form, self.ser.read(size))[0]
Exemplo n.º 31
0
	def LG1(self, clear='N'):
		"""
			Retrieve events logged.
			To clear the event logger, pass in a 'C', like
			BMS.LG1('C')
			
		"""
		sentence = "LG1,"
		if clear == 'C':
			sentence += 'c,'
		else:
			sentence += '?,'
		number = crc8(sentence)
		sentence += number
		self.execute(sentence)
		
		response = self.ser.readline().decode('ascii')
		assert crc8(response[:2]) == int(response[-2:]) # crc check
		r = response.split(',')
		assert r[0] == "LG1"
		logEventDictionary = {	0: 'No event',
								1: 'BMS Started',
								2: 'Lost Communication to Cells',
								3: 'Established communication to cells',
								4: 'Cells voltage critically low',
								5: 'Critical low voltage recovered',
								6: 'Cells voltage critically high',
								7: 'Critical high voltage recovered',
								8: 'Discharge Current critically high',
								9: 'Discharge cirtical high current recovered',
								10: 'Charge Current Critically high',
								11: 'Charge critical high current recovered',
								12: 'Cell module temperature critically high',
								13: 'Critical high cell module temperature recovered',
								14: 'Leakage detected',
								15: 'Leakage recovered',
								16: 'Warning: Low voltage - reducing power',
								17: 'Power reduction due to low voltage recovered',
								18: 'Warning: High current - reducing power',
								19: 'Power reduction due to high current recovered',
								20: 'Warning: High Cell module temperature - reducing power',
								21: 'Power reduction due to high cell module temperature recovered',
								22: 'Charger connected',
								23: 'Charger disconnected',
								24: 'Started pre-heating stage',
								25: 'Started pre-charging stage',
								26: 'Started main charging stage',
								27: 'Started Balancing stage',
								28: 'Charging finished',
								29: 'Charging error occurred',
								30: 'Retrying Chraging',
								31: 'Restarting Charging',
								42: 'Cell Temperature Critically High',
								43: 'Critically high cell temperature recovered',
								44: 'Warning: High cell temperature - reducing power'
							 }
		data = {}
		data['log event sequence number'] = int(r[1],16)
		data['log event'] = logEventDictionary[int(r[1],16)]
		y2kTimestamp = int(r[4],16) #coded in seconds since January 1, 2000 time 00:00 (Y2K)
		#Unix epoch is January 1, 1970 00:00
		#add Y2K in epoch time 
		epochTimestamp = y2kTimestamp + self.y2kInEpoch 
		data['unix timestamp'] = epochTimestamp
		
		#convert epoch time stamp into a real class from the time library.
		#import time
		#timestamp = str(time.gmtime(epochTimestamp))
		return data