-
Notifications
You must be signed in to change notification settings - Fork 21
/
bmstest.py
255 lines (235 loc) · 8.95 KB
/
bmstest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#!/usr/bin/python
# *****Program to retrieve and store data to BMS PCBs*****
# Copyright (C) 2017 Simon Richard Matthews
# Project loaction https://github.com/simat/BatteryMonitor
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import bmscore
import sys
import binascii
def getcmd():
"""gets command from user"""
command=str(input("Enter Command>"))
return command
def switchfets(port='/dev/ttyUSB0'):
""" switch charge and discharge fets """
print ('(03)=Both FETs off')
print ('(01)=Discharge FET on, Charge FET off')
print ('(02)=Discharge FET off, Charge FET on')
print ('(00)=Both FETs on')
usercmd = input("Enter numeric option> ")
ser = bmscore.openbms(port)
command = bytes.fromhex('DD A5 03 00 FF FD 77')
print ('command=',binascii.hexlify(command))
data=bmscore.getbmsdat(ser,command)
print ('reply=',binascii.hexlify(data))
command = bytes.fromhex('DD A5 04 00 FF FC 77')
print ('command=',binascii.hexlify(command))
data=bmscore.getbmsdat(ser,command)
print ('reply=',binascii.hexlify(data))
command = bytes.fromhex('DD 5A 00 02 56 78 FF 30 77')
data=bmscore.getbmsdat(ser,command)
print ('reply=',binascii.hexlify(data))
usercmd=b'\xE1\x02\x00'+bytes.fromhex(usercmd)
command = b'\xDD\x5A'+usercmd+bmscore.crccalc(usercmd).to_bytes(2, byteorder='big')+b'\x77'
print (binascii.hexlify(command))
bmscore.getbmsdat(ser,command)
command = bytes.fromhex('DD 5A 01 02 00 00 FF FD 77')
bmscore.getbmsdat(ser,command)
def getdat(port='/dev/ttyUSB0'):
""" Get data from BMS board"""
ser = bmscore.openbms(port)
command = bytes.fromhex('DD A5 03 00 FF FD 77')
dat = bmscore.getbmsdat(ser,command)
dat = bmscore.getbmsdat(ser,command)
rawi = int.from_bytes(dat[2:4], byteorder = 'big',signed=True)
rawv = int.from_bytes(dat[0:2], byteorder = 'big',signed=True)
balance = bin(int.from_bytes(dat[12:14], byteorder = 'big',signed=True))
state = int.from_bytes(dat[16:18], byteorder = 'big',signed=True)
fets = bin(int.from_bytes(dat[20:21], byteorder = 'big',signed=True))
print ("V={} I={} bal={} state={} fets={}".format(rawv,rawi,balance,bin(state),fets))
errors=['Cell Overvoltage','Cell Undervoltage','Battery Overvoltage', \
'Battery Undervoltage','Charge Overtemp','Charge Undertemp', \
'Discharge Overtemp','Discharge Undertemp','Charge Overcurrent' \
'Discharge Overcurrent','Short Circuit','IC Fault','Software MOS lock']
for i in range(state.bit_length()):
if 2**i & state:
print (errors[i])
# line1 = [ 0 for i in range(int(len(dat)))]
# for i in range(0,int(len(dat))):
# print (dat[i*2:i*2+2])
# print (int.from_bytes(dat[i:i+1], byteorder = 'big'))
# line1[i] = int.from_bytes(dat[i:i+1], byteorder = 'big')
print (binascii.hexlify(dat))
# print (line1)
# voltages
command = bytes.fromhex('DD A5 04 00 FF FC 77')
voltages = bmscore.getbmsdat(ser,command)
ser.close
print (binascii.hexlify(voltages))
rawv = [ 0.0 for i in range(15)]
for i in range(15):
rawv[i] = int.from_bytes(voltages[i*2:i*2+2], byteorder = 'big')/1000.00
# rawv[i] = rawv[i]+rawv[i-1]
print (rawv)
command = bytes.fromhex('DD A5 05 00 FF FB 77')
dat = bmscore.getbmsdat(ser,command)
# line1 = [ 0 for i in range(int(len(dat)))]
# for i in range(0,int(len(dat))):
# print (dat[i*2:i*2+2])
# print (int.from_bytes(dat[i:i+1], byteorder = 'big'))
# line1[i] = int.from_bytes(dat[i:i+1], byteorder = 'big')
print (binascii.hexlify(dat))
# print (line1)
def findregname(reg):
"""Find register name given register address"""
regname=None
for i in bmscore.configinmem:
if bmscore.configinmem[i]['reg']==reg:
regname=i
break
return regname
def enterreg():
"""Get user entry of register address and value"""
cmd=int(input('By Name (1) or by register number (2)?>'))
if cmd==1:
item=input("Enter Config Item Name>")
elif cmd==2:
item=str.upper(input("Enter Config Register Address>"))
item=findregname(item)
value=input("{} = {}, Enter New Value, [return] for don't write>" \
.format(item,bmscore.configinmem[item]['value']))
reginfo ={item:value}
return reginfo
def chgreg(reginfo):
"""Stores Values in reginfo dictionary"""
for reg in reginfo:
if reginfo[reg]:
if "valueint" in bmscore.configinmem[reg]['decode']:
reginfo[reg]=float(reginfo[reg])
bmscore.configinmem[reg]['value']=reginfo[reg]
def main():
print (sys.argv)
if len(sys.argv) == 2:
sendcmd(sys.argv[1])
elif len(sys.argv) == 3:
sendcmd(sys.argv[1],sys.argv[2])
elif len(sys.argv) == 1:
print ('Enter BMS port address option [3]')
print ('(1) /dev/ttyUSB0')
print ('(2) /dev/ttyUSB1')
print ('(3) other')
port=int(getcmd())
if port==1:
port='/dev/ttyUSB0'
elif port == 2:
port='/dev/ttyUSB1'
else:
port=str(input("Enter port name>"))
while True:
bmscore.openbms(port)
print('Enter option')
print('(1) Load all config data from BMS to memory')
print('(2) Read all config data from disk to memory')
print('(3) Write all config data from memory to BMS')
print('(4) Write all config data from memory to disk')
print('(5) Dump all config data in memory')
print('(6) Dump raw config data in memory')
print('(7) Read/Write config item in memory')
print('(8) Read/Write single register in memory and on BMS PCB')
print('(9) Read BMS data')
print('(10) Switch charge/discharge FETs')
print('(11) Calibrate BMS')
while True:
try:
cmd=int(getcmd())
except ValueError:
print('Invalid input')
break
if cmd==1:
bmscore.configitems(bmscore.fullconfiglist,port)
elif cmd==2:
file=str(input("Enter filename>"))
bmscore.configinmem=bmscore.rdjson(file)
elif cmd==3:
bmscore.configitems(bmscore.fullconfiglist,port,write=True)
elif cmd==4:
file=str(input("Enter filename>"))
bmscore.wrjson(file,bmscore.configinmem)
elif cmd ==5:
count = 0
for i in bmscore.configinmem:
print ('{}={}{} {}'.format \
(i,bmscore.configinmem[i]['value'],bmscore.configinmem[i]['units'],bmscore.configinmem[i]['comment']))
count=count+1
if count%30==0:
x=input("press return for next page")
elif cmd==7:
reg=enterreg()
chgreg(reg)
elif cmd==6:
count=0
for i in bmscore.configinmem:
print (i,bmscore.configinmem[i])
count=count+1
if count%30==0:
x=input("press return for next page")
elif cmd==8:
reg=enterreg()
val, =dict.values(reg)
if val:
chgreg(reg)
bmscore.configitems(reg,port,write=True)
elif cmd==9:
getdat(port)
elif cmd ==10:
switchfets(port)
elif cmd ==11:
print ('Enter Item to Calibrate?')
print ('(1) Cell Voltages')
print ('(2) Battery Current')
item=int(getcmd())
if item==1:
item=input("Enter cell number/s e.g. '1-4,5'?> ")
result=set()
for part in item.split(','):
x=part.split('-')
result.update(range(int(x[0]),int(x[-1])+1))
celllist=sorted(result)
cellvolts=int(input("Enter cell voltage/s in mV?> "))
reglist={}
for i in range(len(celllist)):
reg=findregname(str.upper(format(celllist[i]+0xAF,'02x')))
reglist[reg]=cellvolts
chgreg(reglist)
bmscore.configitems(reglist,port,write=True,calibrate=True)
elif item ==2:
print("Enter current type?> ")
print ('(1) Idle Current')
print ('(2) Charge Current')
print ('(3) Discharge Current')
item=int(getcmd())
if item==1:
reg='CalibrateIdleA'
elif item==2:
reg='CalibrateChgA'
elif item==3:
reg='CalibrateDchgA'
current=int(input("Enter Measured Current in A> "))
reginfo={reg:current}
chgreg(reginfo)
bmscore.configitems(reginfo,port,write=True,calibrate=True)
else:
print('No such Command')
if __name__ == "__main__":
"""if run from command line"""
main()