├── .gitattributes
├── .gitignore
├── 6f2.py
├── README.md
├── bms.py
├── dcdc.py
├── fps.py
├── logger.py
├── logger_spc.py
└── thc.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # Windows shortcuts
18 | *.lnk
19 |
20 | # =========================
21 | # Operating System Files
22 | # =========================
23 |
24 | # OSX
25 | # =========================
26 |
27 | .DS_Store
28 | .AppleDouble
29 | .LSOverride
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear in the root of a volume
35 | .DocumentRevisions-V100
36 | .fseventsd
37 | .Spotlight-V100
38 | .TemporaryItems
39 | .Trashes
40 | .VolumeIcon.icns
41 |
42 | # Directories potentially created on remote AFP share
43 | .AppleDB
44 | .AppleDesktop
45 | Network Trash Folder
46 | Temporary Items
47 | .apdisk
48 |
--------------------------------------------------------------------------------
/6f2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | import can
4 | import os
5 |
6 | #Global Variables
7 | frame_counter = 0
8 | MAX_NUMBER_OF_FRAMES = 6000
9 |
10 | print('Content-type: text/html\n\n')
11 |
12 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
13 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
14 |
15 | volts = []
16 | temp = []
17 |
18 | #Run through the capture loop until the maximum number of frames is reached
19 | while frame_counter <= MAX_NUMBER_OF_FRAMES:
20 | frame_counter = frame_counter + 1
21 | message = dev.recv()
22 |
23 | #ID6F2
24 | if message.arbitration_id == 1778:
25 | if message.data[0] == 0 or len(volts) != 0:
26 | d1 = (message.data[1] | ((message.data[2] & 0x03F)<<8))
27 | d2 = ((message.data[2]>>6) | ((message.data[3]<<2) | ((message.data[4] & 0xF)<<10)))
28 | d3 = ((message.data[4]>>4) | ((message.data[5]<<4) | ((message.data[6] & 3)<<12)))
29 | d4 = ((message.data[6]>>2) | ((message.data[7])<<6))
30 | if message.data[0] < 24:
31 | volts.append(round(d1 * 0.000305, 3))
32 | volts.append(round(d2 * 0.000305, 3))
33 | volts.append(round(d3 * 0.000305, 3))
34 | volts.append(round(d4 * 0.000305, 3))
35 | else:
36 | temp.append(round(d1 * 0.0122, 3))
37 | temp.append(round(d2 * 0.0122, 3))
38 | temp.append(round(d3 * 0.0122, 3))
39 | temp.append(round(d4 * 0.0122, 3))
40 | if message.data[0] == 31:
41 | break
42 | # i = 0
43 | # while i < len(volts):
44 | # print("Brick " + str(i) + " " + str(volts[i]))
45 | # i += 1
46 | l_volts = len(volts)
47 | l_temp = len(temp)
48 |
49 | i = 0
50 | n = 1
51 | while i < l_volts:
52 | if (i % 6 == 0 and i + 1 != l_volts):
53 | print("
Module " + str(n) + "")
54 | n += 1
55 | print(str(volts[i]) + " V ")
56 | i += 1
57 | print("
Average: " + str(round((sum(volts) / len(volts)), 2))) 58 | print("Min: " + str(min(volts))) 59 | print("Max: " + str(max(volts))) 60 | print("
Average: " + str(round((sum(temp) / len(temp)), 2)))
71 | print("Min: " + str(min(temp)))
72 | print("Max: " + str(max(temp)))
73 |
74 | os.system("sudo /sbin/ip link set can0 down")
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## CAN3 Interfacing a Pi 3 with PiCAN2
2 |
3 | Features several scripts written in python to interface with Model S CAN Bus 3 (powertrain).
4 | I execute these scripts as CGI and output through an Apache HTTP server.
--------------------------------------------------------------------------------
/bms.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | import can
4 | import os
5 | import time
6 |
7 | #Global Variables
8 | frame_counter = 0
9 | timeout = time.time() + 5
10 |
11 | # battery data
12 | batt_odo = 0
13 | wh_dis_tot = 0
14 | wh_chrg_tot = 0
15 | soc_ui = 0
16 | nom_energy_remain = 0
17 | exp_energy_remain = 0
18 | ideal_energy_remain = 0
19 | nom_packfull_energy = 0
20 | energy_buffer = 0
21 | pack_volt = 0
22 | energy_till_chargedone = 0
23 | maxDischarge = 0
24 | maxRegen = 0
25 |
26 | print('Content-type: text/html\n\n')
27 |
28 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
29 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
30 |
31 | while True:
32 | if time.time() > timeout:
33 | break
34 | message = dev.recv()
35 |
36 | #ID382
37 | if message.arbitration_id == 898:
38 | nom_energy_remain = ((message.data[1]>>2) + ((message.data[2] & 0x0F) * 64)) * 0.1
39 | exp_energy_remain = ((message.data[2]>>4) + ((message.data[3] & 0x3F) * 16)) * 0.1
40 | ideal_energy_remain = ((message.data[3]>>6) + ((message.data[4] & 0xFF) * 4)) * 0.1
41 | nom_packfull_energy = (message.data[0] + ((message.data[1] & 0x03)<<8)) * 0.1
42 | # energy_till_chargedone = (message.data[5] + ((message.data[6] & 0x03)<<8)) * 0.1
43 | energy_buffer = ((message.data[6]>>2) + ((message.data[7] & 0x03) * 64)) * 0.1
44 |
45 | #ID302
46 | if message.arbitration_id == 770:
47 | soc_ui = ((message.data[1]>>2) + ((message.data[2] & 0xF)<<6)) / 10
48 |
49 | #ID562
50 | # if message.arbitration_id == 1378:
51 | # batt_odo = (message.data[0] + (message.data[1]<<8) + (message.data[2]<<16) + (message.data[3]<<24))/1000
52 |
53 | #ID102
54 | # if message.arbitration_id == 546:
55 | # pack_volt = '%.2f' %(float((message.data[3]*256.0 + message.data[2])/100.0))
56 |
57 | #ID
58 | if message.arbitration_id == 258:
59 | pack_volt = (message.data[0] | (message.data[1]<<8))/100
60 | pack_current = (((message.data[2] + ((message.data[3] & 0x3F)<<8)) - ((message.data[3] & 0x40)<<8))-10000)/10
61 |
62 | #ID232
63 | if message.arbitration_id == 562:
64 | maxDischarge = (message.data[2] + (message.data[3]<<8))/100
65 | maxRegen = (message.data[0] + (message.data[1]<<8))/100
66 |
67 | if maxDischarge != 0 and pack_volt != 0 and nom_energy_remain != 0 and soc_ui != 0:
68 | break
69 |
70 | print("Nom Pack Full Energy (kWh): " + str(nom_packfull_energy))
71 | print("
Nom Energy Remain (kWh): " + str(nom_energy_remain))
72 | print("
Expected Energy Remain (kWh): " + str(exp_energy_remain))
73 | print("
Ideal Energy Remain (kWh): " + str(ideal_energy_remain))
74 | # print("
Energy to Charge Comp (kWh): " + str(energy_till_chargedone))
75 | print("
Energy buffer (kWh): " + str(energy_buffer))
76 | print("
SoC UI (%): " + str(soc_ui))
77 | print("
Max Discharge (kW): " + str(maxDischarge))
78 | print("
Max Regen (kW): " + str(maxRegen))
79 | print("
Pack Voltage: " + str(pack_volt))
80 | print("
Pack Current: " + str(pack_current))
81 |
82 | os.system("sudo /sbin/ip link set can0 down")
--------------------------------------------------------------------------------
/dcdc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | import can
4 | import os
5 |
6 | #Global Variables
7 | frame_counter = 0
8 | MAX_NUMBER_OF_FRAMES = 2000
9 |
10 | #DC-to-DC vars
11 | inletTemperature = 0
12 | inputPower = 0
13 | outputCurrent = 0
14 | outputPower = 0
15 | outputVoltage = 0
16 |
17 | print('Content-type: text/html\n\n')
18 |
19 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
20 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
21 |
22 | while frame_counter <= MAX_NUMBER_OF_FRAMES:
23 | frame_counter = frame_counter + 1
24 | message = dev.recv()
25 |
26 | #ID0210
27 | if message.arbitration_id == 528:
28 | inputPower = message.data[3] * 16
29 | outputCurrent = message.data[4]
30 | outputVoltage = message.data[5] / 10
31 | inletTemperature = (((message.data[2] - (2 * (message.data[2] & 0x80))) * 0.5) + 40)
32 | outputPower = message.data[4] * (message.data[5] / 10)
33 |
34 | print("Input (W): " + str(inputPower))
35 | print("
Output (A): " + str(outputCurrent))
36 | print("
Output (V): " + str(outputVoltage))
37 | print("
Output (W): " + str(outputPower))
38 | print("
Temp (C): " + str(inletTemperature))
39 |
40 | os.system("sudo /sbin/ip link set can0 down")
--------------------------------------------------------------------------------
/fps.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | #Global Variables
4 | frame_counter = 0
5 | MAX_NUMBER_OF_FRAMES = 10000
6 |
7 | import RPi.GPIO as GPIO
8 | import can
9 | import time, datetime
10 | import os
11 |
12 | led = 22
13 | GPIO.setmode(GPIO.BCM)
14 | GPIO.setwarnings(False)
15 | GPIO.setup(led,GPIO.OUT)
16 | GPIO.output(led,True)
17 |
18 | # Bring up can0 interface at 500kbps
19 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
20 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
21 |
22 | print('Content-type: text/html\n\n')
23 | startTime = datetime.datetime.now()
24 |
25 | while frame_counter <= MAX_NUMBER_OF_FRAMES:
26 | frame_counter = frame_counter + 1
27 | message = dev.recv()
28 | print(str(message.arbitration_id) + "
")
29 |
30 | print ("10,000 frames in " + str(datetime.datetime.now() - startTime))
31 |
32 | GPIO.output(led,False)
33 | os.system("sudo /sbin/ip link set can0 down")
--------------------------------------------------------------------------------
/logger.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # basic logging to file.
3 |
4 | print('Content-type: text/html\n\n')
5 |
6 | #Main Import
7 | import sys
8 | import glob
9 | import time, datetime
10 | import io
11 | import os
12 | import can
13 |
14 | #Logging/Viewing Settings
15 | SHOW_ALL_IDs = False
16 | WRITE_TO_FILE = True
17 | SHOW_REAR_POWER_DATA = True
18 | SHOW_FRNT_POWER_DATA = False
19 | SHOW_BATT_DATA = True
20 | LOGGING_ENABLED = False
21 | FILE_NAME = '' #Defaults to current date and time
22 |
23 | #Global Variables
24 | frame_counter = 0
25 | MAX_NUMBER_OF_FRAMES = 20000
26 |
27 | #Motor/Power Vars
28 | pDiss = 0.0
29 | mechPower = 0.0
30 | statorCurr = 0.0
31 | torqMeas = 0.0
32 | torqEst = 0.0
33 | pedalPos = 0
34 | speedMPH = 0.0
35 | mtrRPM = 0
36 |
37 | #battery data
38 | batt_odo = 0
39 | wh_dis_tot = 0
40 | wh_chrg_tot = 0
41 | soc_ui = 0
42 | nom_energy_remain = 0
43 | exp_energy_remain = 0
44 | ideal_energy_remain = 0
45 | nom_packfull_energy = 0
46 | pack_volt = 0
47 | pack_current = 0
48 | pack_temp = 0
49 |
50 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
51 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
52 |
53 |
54 | if WRITE_TO_FILE == True:
55 | if FILE_NAME != '':
56 | st = FILE_NAME
57 | else:
58 | st = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H.%M.%S')
59 | file_ = open('../log/' + st + '.csv', 'w')
60 | print('New File Opened, now logging data. ')
61 |
62 | #Run through the capture loop until the maximum number of frames is reached
63 | while frame_counter <= MAX_NUMBER_OF_FRAMES:
64 | frame_counter = frame_counter + 1
65 | message = dev.recv()
66 |
67 | if SHOW_BATT_DATA == True:
68 |
69 | #ID 302
70 | if message.arbitration_id == 770:
71 | soc_ui = ((message.data[1]>>2) + ((message.data[2] & 0xF)<<6)) / 10
72 |
73 | if message.arbitration_id == 258:
74 | pack_volt = (message.data[0] | (message.data[1]<<8))/100
75 | # pack_current = (((message.data[2] | (message.data[3]<<8)) - ((message.data[2] | (message.data[3]<<8)) & 0x8000))-10000)/10
76 | pack_current = (((message.data[2] + ((message.data[3] & 0x3F)<<8)) - ((message.data[3] & 0x40)<<8))-10000)/10
77 |
78 | if message.arbitration_id == 1778 and message.data[0] > 23:
79 | d1 = (message.data[1] | ((message.data[2] & 0x03F)<<8))
80 | pack_temp = (d1 * 0.0122)
81 |
82 | if SHOW_REAR_POWER_DATA == True:
83 | if message.arbitration_id == 614:
84 | #All power units in kW
85 | # pDiss = message.data[1] * 125
86 | mechPower = ((message.data[2] + ((message.data[3] & 0x7)<<8))-(512 * (message.data[3] & 0x4))) / 2
87 | statorCurr = message.data[4] + ((message.data[5] & 0x7)<<8)
88 |
89 | if message.arbitration_id == 340:
90 | #Nm
91 | torqMeas = (message.data[5] + ((message.data[6] & 0x1F)<<8)-(512 * (message.data[6] & 0x10))) * 0.25
92 | #percent
93 | pedalPos = (message.data[2] * 0.4)
94 |
95 | #ID116
96 | if message.arbitration_id == 278:
97 | speedMPH = ((message.data[2] + ((message.data[3] & 0xF)<<8))-500) / 20
98 | # torqEst = ((message.data[0] + ((message.data[1] & 0xF)<<8))-(512 * (message.data[1] & 0x8))) / 2
99 |
100 | #ID106
101 | if message.arbitration_id == 262:
102 | mtrRPM = (message.data[4] + (message.data[5]<<8))-(512 * (message.data[5]&0x80))
103 |
104 | if WRITE_TO_FILE == True:
105 | if frame_counter == 1:
106 | write_data = ("time, msg_id, soc, temp, pedal_pos, pack_volt, pack_current, torque, mechPower, speedMPH\n")
107 | else:
108 | write_data = ("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" % (time.time(), hex(message.arbitration_id)[2:], soc_ui, pack_temp, pedalPos, pack_volt, pack_current, torqMeas, mechPower, speedMPH))
109 | file_.write(write_data)
110 |
111 | if WRITE_TO_FILE == True:
112 | file_.close()
113 | print("File " + st + '.csv closed. ')
114 |
115 | os.system("sudo /sbin/ip link set can0 down")
116 | print("Connection Closed")
--------------------------------------------------------------------------------
/logger_spc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # extended period logging to file.
3 |
4 | print('Content-type: text/html\n\n')
5 |
6 | #Main Import
7 | import sys
8 | import glob
9 | import time, datetime
10 | import io
11 | import os
12 | import can
13 |
14 | #Logging/Viewing Settings
15 | SHOW_ALL_IDs = False
16 | WRITE_TO_FILE = True
17 | SHOW_BATT_DATA = True
18 | FILE_NAME = '' #Defaults to current date and time
19 |
20 | #Global Variables
21 | MAX_NUMBER_OF_FRAMES = 6000
22 | loop_counter = 0
23 | SEC_BETWEEN_LOOP = 15
24 | MAX_LOOPS = 165
25 |
26 | #battery data
27 | batt_odo = 0
28 | wh_dis_tot = 0
29 | wh_chrg_tot = 0
30 | soc_ui = 0
31 | nom_energy_remain = 0
32 | exp_energy_remain = 0
33 | ideal_energy_remain = 0
34 | nom_packfull_energy = 0
35 | pack_volt = 0
36 | pack_current = 0
37 | pack_temp = 0
38 |
39 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
40 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
41 |
42 |
43 | if WRITE_TO_FILE == True:
44 | if FILE_NAME != '':
45 | st = FILE_NAME
46 | else:
47 | st = datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H.%M.%S')
48 | file_ = open('../log/' + st + '_bat_health.csv', 'w')
49 | print('New File Opened, now logging data. ')
50 |
51 | #Run through the capture loop
52 | def capture(dev, frame_counter, MAX_NUMBER_OF_FRAMES):
53 | volts = []
54 | temp = []
55 |
56 | while frame_counter <= MAX_NUMBER_OF_FRAMES:
57 | frame_counter = frame_counter + 1
58 | message = dev.recv()
59 |
60 | if SHOW_BATT_DATA == True:
61 |
62 | #ID 302
63 | if message.arbitration_id == 770:
64 | soc_ui = ((message.data[1]>>2) + ((message.data[2] & 0xF)<<6)) / 10
65 |
66 | if message.arbitration_id == 258:
67 | pack_volt = (message.data[0] | (message.data[1]<<8))/100
68 | # pack_current = (((message.data[2] | (message.data[3]<<8)) - ((message.data[2] | (message.data[3]<<8)) & 0x8000))-10000)/10
69 | pack_current = (((message.data[2] + ((message.data[3] & 0x3F)<<8)) - ((message.data[3] & 0x40)<<8))-10000)/10
70 |
71 | #ID6F2
72 | if message.arbitration_id == 1778:
73 | if message.data[0] == 0 or len(volts) != 0:
74 | d1 = (message.data[1] | ((message.data[2] & 0x03F)<<8))
75 | d2 = ((message.data[2]>>6) | ((message.data[3]<<2) | ((message.data[4] & 0xF)<<10)))
76 | d3 = ((message.data[4]>>4) | ((message.data[5]<<4) | ((message.data[6] & 3)<<12)))
77 | d4 = ((message.data[6]>>2) | ((message.data[7])<<6))
78 | if message.data[0] < 24:
79 | volts.append(round(d1 * 0.000305, 3))
80 | volts.append(round(d2 * 0.000305, 3))
81 | volts.append(round(d3 * 0.000305, 3))
82 | volts.append(round(d4 * 0.000305, 3))
83 | else:
84 | temp.append(round(d1 * 0.0122, 3))
85 | temp.append(round(d2 * 0.0122, 3))
86 | temp.append(round(d3 * 0.0122, 3))
87 | temp.append(round(d4 * 0.0122, 3))
88 | if message.data[0] == 31:
89 | break
90 |
91 | write_data = ("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n" % (time.time(), soc_ui, pack_volt, pack_current, round((sum(temp) / len(temp)), 2), min(temp), max(temp), round((sum(volts) / len(volts)), 2), min(volts), max(volts)))
92 | file_.write(write_data)
93 |
94 | while loop_counter < MAX_LOOPS:
95 | print("
Loop iteration: " + str(loop_counter))
96 | loop_counter = loop_counter + 1
97 | frame_counter = 0
98 | capture(dev, frame_counter, MAX_NUMBER_OF_FRAMES)
99 | time.sleep(SEC_BETWEEN_LOOP)
100 |
101 | if WRITE_TO_FILE == True:
102 | file_.close()
103 | print("File " + st + '.csv closed. ')
104 |
105 | os.system("sudo /sbin/ip link set can0 down")
106 | print("Connection Closed")
--------------------------------------------------------------------------------
/thc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | import can
4 | import os
5 |
6 | #Global Variables
7 | frame_counter = 0
8 | MAX_NUMBER_OF_FRAMES = 2000
9 |
10 | #THC human decode
11 | THC_batteryHeaterState = "Undefined"
12 | heater_state = []
13 | heater_state.append("Off")
14 | heater_state.append("Startup")
15 | heater_state.append("BAT_IN_HEAT_CK")
16 | heater_state.append("Run")
17 | heater_state.append("Overtemp")
18 | heater_state.append("Suspended")
19 | heater_state.append("Undefined")
20 | heater_state.append("Undefined")
21 |
22 | THC_batteryHeaterTemp = 0
23 | THC_batteryHeaterReq = 0
24 |
25 | THC_totalPowerConsumedHV = 0
26 | THC_totalPowerConsumed12V = 0
27 | THC_HVPowerLimit = 0
28 | THC_limitedBatteryHeater = 0
29 | THC_limitedCompressor = 0
30 | THC_limitedPtcHeater = 0
31 |
32 | print('Content-type: text/html\n\n')
33 |
34 | os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
35 | dev = can.interface.Bus(channel='can0', bustype='socketcan_native')
36 |
37 | while frame_counter <= MAX_NUMBER_OF_FRAMES:
38 | frame_counter = frame_counter + 1
39 | message = dev.recv()
40 |
41 | #ID26A
42 | if message.arbitration_id == 618:
43 | THC_batteryHeaterTemp = ((message.data[0] + ((message.data[1]&0x7)<<8)) * 0.125) - 40
44 | THC_batteryHeaterReq = (message.data[1] & 0x8)>>3
45 | THC_batteryHeaterState = (message.data[2] & 0x70)>>4
46 | THC_batteryHeaterState_Human = heater_state[THC_batteryHeaterState]
47 |
48 | #ID35A
49 | if message.arbitration_id == 858:
50 | THC_totalPowerConsumedHV = (message.data[2] + (message.data[3]<<8))
51 | THC_totalPowerConsumed12V = (message.data[4] + ((message.data[5] & 0xF)<<8))
52 | THC_HVPowerLimit = (message.data[6] + (message.data[7]<<8)) / 100
53 | THC_limitedBatteryHeater = (message.data[5] & 0x10)>>4
54 | THC_limitedCompressor = (message.data[5] & 0x20)>>5
55 | THC_limitedPtcHeater = (message.data[5] & 0x40)>>6
56 |
57 | print("Heater Temp (C): " + str(THC_batteryHeaterTemp))
58 | print("
Active Heating Target (C): " + str(THC_batteryHeaterReq))
59 | print("
Heater State: " + THC_batteryHeaterState_Human)
60 | print("
Total consumption HV: " + str(THC_totalPowerConsumedHV))
61 | print("
Total consumption 12V: " + str(THC_totalPowerConsumed12V))
62 | print("
HV Power Limit: " + str(THC_HVPowerLimit))
63 | print("
is limited heating: " + str(THC_limitedBatteryHeater))
64 | print("
is limited cooling: " + str(THC_limitedCompressor))
65 | print("
is limited PTC: " + str(THC_limitedPtcHeater))
66 |
67 | os.system("sudo /sbin/ip link set can0 down")
--------------------------------------------------------------------------------