-
Notifications
You must be signed in to change notification settings - Fork 417
Description
I run a Chevy Bolt as a race car in 24 Hours of Lemons.
It’s useful for our racing drivers to see some additional gauges, such as the exact battery state-of-charge, the battery temperature, and the motor temperature. For these gauges, we initially used an Android phone with the Torque app and a CSV file of Bolt PIDs which I found here, and can be downloaded here.
But, we recently transitioned to using a Raspberry Pi instead of the Android phone, because the Pi gives us more options for data logging and it has enabled us to add custom gauges such as “how much battery did we use in the current lap?”
On the Raspberry Pi, our setup is:
- We get the OBD2 with an ELM327 bluetooth device
- We connect the Raspberry Pi to the ELM327 via a bluetooth USB dongle
- We read the OBD2 data using the python-OBD
Success story with OBD gauges on the Raspberry Pi
For some things, our Raspberry Pi setup works great. For instance, here is a code example of how we read the exact battery percent, and we did this by reimplementing the formula from the OBD2 CSV in Python as follows.
import obd
from obd import Unit
from obd.OBDCommand import OBDCommand
from obd.protocols import ECU
OBD_PORT = "/dev/serial/by-id/<the_device>”
connection = obd.OBD(OBD_PORT)
def soc_hd_decoder(messages):
# 5 bytes of response; we use the last 2 bytes.
d = messages[0].data[3:]
A = float(d[0])
B = float(d[1])
v = ((((A*256)+B)*100)/65535)
return v * Unit.percent
c = OBDCommand("HYBRID_BATTERY_REMAINING_HD",
"Hybrid battery pack remaining life HD",
b"2243AF",
5, # bytes of expected response
soc_hd_decoder,
ECU.UNKNOWN,
True,
header=b"7E4")
connection.supported_commands.add(c)
response = connection.query(c)
print(response.value)
The above prints prints 66.01815823605708 percent, which roughly matches the car’s built-in display on the dashboard.
Failure case that we want help to debug
However, when we try to read the motor temperature, it does not work properly. Here is what we tried:
def raw_decoder(messages):
# for debugging, print the OBD2 response
d = messages[0].data
print(f" Hex: {[hex(byte) for byte in d]}")
return d
c = OBDCommand("MOTOR_TEMP",
"Motor Temperature",
b"2228CB",
4, # bytes of expected response
raw_decoder,
ECU.UNKNOWN,
True,
header=b"7E4" # spreadsheet says 7E1, but 7E4 actually gives a response.
)
connection.supported_commands.add(c)
response = connection.query(c)
print(response.value)
This prints:
Hex: ['0x7f', '0x22', '0x31', '0x0']
In other words, it responds with the hexidecimal code 7f2231. When I google 7f2231, I see that it is a code that means “Request out of range,” in other words the request is not supported. But, what’s strange is that using the same ELM327 device with Torque on Android, I get a reasonable response for the motor temp. And in the Torque app, when I drive the car fast on the track, the motor temperature goes up, so I think it's really working properly in the Torque app. But, when I read this motor temperature signal (2228CB) in python-OBD, I always get the same error code, no matter how I have been driving the car.
Any advice on this? Thanks!
P.S. If you’re curious about our EV racing stuff, this video gives a bit more info.