Last fall I purchased a Cadillac ELR to keep my Tesla company in the garage. I am a huge fan of this car for the striking good looks and the fact that it is a 2-door coupe. I had also never experienced a PHEV (Plug-In Hybrid Electric Vehicle) and really wanted to try out the GM Voltec platform. The prices of the Cadillac ELR are plummeting due to their relatively short-lived time on the market and the fact that they are a little unknown in the eyes of the average consumer.
![]() |
Cadillac ELR at Cardinale GMC in Seaside, California |
The Cadillac ELR (and Chevy Volt - they share the same powertrain and a similar UI) tend to shield you from these details. I wanted more and without having to do quick mental math based on the limited information available from the built-in infotainment system.
![]() |
Speed, Distance, Total Energy and Wh/mi Top | State of Charge (SoC) kWh Left | Speed mph Right |
![]() |
CAN Bus Interface Cable |
Decoding the CAN bus(es)
The first thing I did before spending any time on a fancy UI was make sure that I would be able to read the required data from a CAN bus in the car. This vehicle has two OBD-II-style connectors: one is in the drivers foot well and another in the passenger foot well.
I decided to use the Viewtool Ginkgo USB-CAN interface. Unfortunately, Linux support comes in the form of a binary blob shared object, but I was able to make it work. I wrote a wrapper around this in C to make it easier to call from Python with CFFI. Before ordering any connectors and spending time building a neat cable, I just probed the connectors using spade connectors with one leg removed.
![]() |
"Half-Spade" Connectors, Inserted into the OBD-II connector. It's a great fit! |
I started out with the OBD-II connector in the drivers foot well. I went for a brief drive around my neighborhood, stepping heavily on the accelerator in order to generate some waveforms that I can try to reason with.
I wrote a python script that takes all of the captured data and for each CAN address tries to interpret the packets in a variety of ways. Data is sent on the bus in "network-order", aka big-endian. If a CAN packet contains a multi-byte word, it is sent most-significant byte first. This is also obvious from just inspecting the captured data in a hex editor. The bits most frequently change in the later-received bytes.
The script tries to parse the bytes in a few ways:
- Each byte individually
- First byte << 8 | second byte (and third/fourth, fifth/sixth, etc)
- First byte << 24 | second byte << 16 | third byte << 8 | fourth byte (and fifth/sixth/etc.)
Each of these interpretations are plotted with matplotlib on a separate plot. This generates about 500 images for each trace of CAN data on the bus. It is very easy to open all of them with an image viewer and cull off the obviously useless messages.
![]() |
Contents of 0x348 plotted |
There are a lot of less interesting plots to wade through, such as the following:
![]() |
Contents of 0x589 plotted |
I have no idea what this is. It could be a misinterpreted packet or something I just don't understand about the vehicle. In any event, it is easy to say that this is neither speed nor state of charge. It is quite easy to search through a few hundred of these in just a few minutes sorting out the unknown packets from the packets where some further interpretation might yield a useful data point.
What data exists?
The short answer is "a lot". I found curves that vaguely resemble voltage, something that looks like temperature, throttle position and I even managed to decode GPS latitude and longitude which was super interesting.
The GPS lat/long are encoded as a 31-bit signed milliarcsecond values. I had to extend the sign to the 32nd bit in order to get the value to match to my current location. Super unusual, but very interesting. The GPS is of particular interest because it may be quite precise if it is performing dead reckoning. It would allow the location to be very accurate even in locations with poor GPS signal strength such as urban canyons or long tunnels.
Enough about GPS though, I was able to find all of the data that I wanted between the two OBD-II ports so here's a quick breakdown:
- Primary, 0x3E9, bytes 0 - 1 Speed in 1/100mph
- Primary, 0x1A1, byte 6, Throttle Position Percent, 0-254
- Primary, 0x32A, bytes 0 - 3 GPS Latitude, 31-bit signed milliarcseconds
- Primary, 0x32A, bytes 4 - 7 GPS Longitude, 31-bit signed milliarcseconds
- Primary, 0x120, bytes 0 - 3, Odometer in 1/100mi
- Alt, 0x20A, byte 7, State of Charge Percent, 0-254
![]() |
Lots of data analysis :] |
Improving the Hardware
Once I had proven that the necessary data was available, I ordered two OBD-II connectors and wired them up. The primary OBD-II connector is just the standard ISO pinout:
- Pin 4 - Ground
- Pin 6 - Can High
- Pin 14 - Can Low
The secondary connector is proprietary and I found some details on another webpage: EVtools.info - Chevy Volt OBD2 CAN Data. The alternate connector uses the following pinout:
- Pin 3 - Can High
- Pin 4 - Ground
- Pin 11 - Can Low
![]() |
Incomplete Alternate OBD-II Connector |
I made liberal use of heat shrink tubing and nylon cable sheathing to keep things neat and professional looking. I also printed out some labels for keeping track of which connector each cable mates with.
![]() |
Neatly Labelled Connectors :] |
I left some slack in the cables to allow positioning the CAN to USB adapter on the floor. The last missing component is on the way: a RAM Sony Vaio UX windshield mount.
![]() |
CAN Bus Monitor Connected |
Displaying the Data
I opted to use PyQt in order to build a simple interface for rendering the UI. I started with a basic setup like the following:
![]() |
Speed Plot and Non-Functional Quit Button |
I needed just a simple plot in order to test the real-time plotting implementation. I want this application to run full screen so a quit button of sorts is necessary.
After some iteration, I arrived at the more refined UI below. I use white text on a black background to keep the brightness down for night-time driving. The high-contrast is highly readable. The small EV symbol in the top left can be tapped to quit.
![]() |
More Refined UI |
At this time, state of charge and speed are plotted with other numeric statistics shown above: current speed, distance traveled, energy used and Wh/mi. I would like to continue iterating on the design and add a histogram of speed, which is handy for hypermiling. It also needs a reset button and labels for the displayed statistics.
I can also build a simple range estimator based on current efficiency and rated state of charge. Different algorithms can be used to try to make a more accurate estimate. Another interesting UI feature would be a warning for accelerations that are too fast. This would coach me into driving more efficiently.
Does it work?
Of course it does! Here is a screenshot from a recent hypermiling run from Mountain View, CA to the Golden Gate Bridge.
![]() |
Hypermiling from Mountain View to Golden Gate Bridge |
The Cadillac ELR has a rated range of 35 miles but I was able to push it to 44 in this case with some energy to spare. It is not an incredible run, but cool nonetheless.
![]() |
Sony Vaio UX Resting on the Dash |
It was quite cold with single-digit Celsius outdoor temperatures. The tires could use a little more air too. They are at 35-36psi now, but could stand to be increased to 40psi for further efficiency improvements.
Overall, the ELR is a really fun car to drive. These stats scratch my itch to see more metrics about my driving. Maybe I will take another pass at the data and find some more useful data points to render.
In the meantime, I look forward to the arrival of my windshield mount and more adventures/projects with this car. Thanks for reading!
i love this car!!! truly the first beautiful electric car unlike the Leaf or even Prius.
ReplyDeletefirst off, some questions...what year, how much mileage, and amount after tax you paid for it?
like you, im fascinated with EV. got an electric skateboard to have fun with the boys. got an electric stand up scooter for daily commute. i think the scooter is ideal because the wheels can go over any terrain. with the handlebar, anyone can feel confident not falling or taking a nose dive. it can fold down easily to be tucked away when not in use.
Now can you change the software to get the extra performance of the 2016 model? ;)
ReplyDeleteI'd really like to have a display showing the state of the 2 traction motors, and the clutches that control them. Plus overall KW used, KW for climate control, battery SOC, etc.
ReplyDeleteI'm buying a Cadillac ELR tomorrow! (2018-10-15) and I was looking for what I could potentially do to help me get more electric only mileage. So glad I found this page. Keep up the great work!
ReplyDeleteVery cool project. I have a Viewtool USB-CAN adapter like yours but I cannot see any traffic. Could you share what settings you used to capture CAN messages?
ReplyDeleteHello - Here is a working example of a project that uses the Viewtool. https://github.com/aarossig/can-joystick
DeleteIf I had to pick a CAN adapter again, I would probably pick something else, but it works. I am using libusbcan which is really just some neat wrappers around the Viewtool stuff.
Best of luck!
Hi, This is a nice article you shared great information i have read it thanks for giving such a wonderful Blog for the reader. tree trimmers palm beach county
ReplyDeleteI think this is one of the most significant information for me. And i’m glad reading your article. But should remark on some general things, The web site style is perfect, the articles is really great : D. Good job, cheers.
ReplyDeletetree removal pembroke pines
I think this is one of the most significant information for me. And i’m glad reading your article.tree removal services fort lauderdale
ReplyDeleteThis post is good enough to make somebody understand this amazing thing, and I’m sure everyone will appreciate this interesting things.
ReplyDeletetree trimming companies miami fl
I have read your article, it is very informative and helpful for me.I admire the valuable information you offer in your articles. Thanks for posting it..
ReplyDeletetree trimming west palm beach
Thanks for the wonderful share. Your article has proved your hard work and experience you have got in this field. Brilliant .i love it reading. tree trimming services fort lauderdale
ReplyDeleteA superbly written article, if only all bloggers offered the same content as you, the internet would be a far better place. residential tree services north lauderdale
ReplyDeleteHi, This is a nice article you shared great information i have read it thanks for giving such a wonderful blog for the reader. tree services near me in hallandale beach
ReplyDeleteI have read your article, it is very informative and helpful for me.I admire the valuable information you offer in your articles. Thanks for posting it..tree care companies oakland park fl
ReplyDeleteI think this is one of the most significant information for me. And i’m glad reading your article. emergency tree services margate
ReplyDeleteThis post is good enough to make somebody understand this amazing thing, and I’m sure everyone will appreciate this interesting things.palm tree services weston fl
ReplyDeleteI think this is one of the most significant information for me. And i’m glad reading your article. commercial tree services deerfield beach
ReplyDeleteHello, I have browsed most of your posts. This post is probably where I got the most useful information for my research. Thanks for posting, maybe we can see more on this. Are you aware of any other websites on this subject?
ReplyDeletestump grinding sunrise fl
Great article and a nice way to promote online. I’m satisfied with the information that you provided stump removal pompano beach
ReplyDeleteHTML stands for HyperText Markup Language. ... Therefore, writing HTML is coding, because you write code, but it's not programming, because you don't write an algorithm, steps that lead to a solution of a problem.
ReplyDeleteinternship in chennai for mechanical
internship in chennai for cse students
internship in chennai for eee
internship in chennai for ece students
internship in chennai for bcom students
internship in chennai for mechanical engineering students
python internship in chennai
internship in chennai for it students
companies offering internship in chennai
internship in chennai for it
Amazing Article,Really useful information to all So, I hope you will share more information to be check and share here.
ReplyDeleteInplant Training for cse
Inplant Training for IT
Inplant Training for ECE Students
Inplant Training for EEE Students
Inplant Training for Mechanical Students
Inplant Training for CIVIL Students
Inplant Training for Aeronautical Engineering Students
Inplant Training for ICE Students
Inplant Training for BIOMEDICAL Engineering Students
Inplant Training for BBA Students