When you click on links to various merchants on this site and make a purchase, this can result in this site earning a commission. Affiliate programs and affiliations include, but are not limited to, the eBay Partner Network.
I figured it was worth breaking this project out into it's own thread instead of burying it in my build thread.
Overview
A quick overview of what we're looking at here. A small ESP32 dev board with a built in display that is pulling ECU data via CANBUS. It's currently setup to use OBDII from one of the CAN headers on the Link G4x in my car. I drew and 3d printed a housing to mount it on the steering column.
Why
The CAN/OBDII data was already able to be picked up by my phone using a bluetooth dongle, but I don't always want to have my phone out to view temps. If I'm on track I like to be able to monitor temps without worrying about my suction cup mount flying off mid corner or my phone's battery dying. Further, this allows me to tweak what sensors I want to use and any parameters related to those.
Cost
Cost is probably the biggest pro for this setup for now. The electronics side is an ESP32 ( $23) board drawing power through a buck converter (5 for $10). The CAN signaling is run through a transceiver ($4 + shipping). So, not including the cost of the 3d printer, protoboards, wiring, etc... You're looking at around $30. With a basic electronics kit from Amazon and a couple bucks to find someone to print a housing I'd expect most people could get this done for ~$50.
What CAN It Do?
So far, I've only got it set up to read 4 different values, Coolant temp, Intake temp, Oil Temp and RPM. I've set the code up in a way that makes adding a sensor pretty easy, it's about 5 lines of code or so. Being OBDII, you are limited to the sensors defined in that standard as far as I'm aware. Link's CAN support is pretty extensive, but I wanted to get things up and running so using a predefined standard like OBDII seemed like the quickest path forward. The code is also set up to record the peak values for the sensor, which happens for each sensor, not just the currently displayed one.
The ESP32 board also has a lot of I/O. I've got this set up to drive green, yellow and red LEDs depending on the state of the currently selected sensor and some Good, Warning and Error values in the code. I didn't end up getting those LEDs installed in the current prototype, but I should be able to wire those in and be good to go.
Further, the ESP32 has Wifi and Bluetooth. I haven't ever used this board, so I'm not sure exactly how this would go, but I believe a small Android app could be created reasonably easily using something like MIT App Inventor to allow a phone to visualize all sensor data at once. I did something similar in college with an android phone and a temperature sensor on an Arduino, so I don't imagine this would be significantly different.
What Now
The housing will likely be redesigned a couple times. I've got a new faceplate on the printer next to me as I type this. After a test drive yesterday I realized that the current setup blocks more of the speedo and warning light cluster than I care for. I also would like to figure out some way to package the circuitry in the housing, as right now it's mostly just flopping around. Also, if LED's are added, I'd like to add a hole/slot for those, but that's a ways away.
I believe there's a bug in the code right now that causes some sort of segmentation fault and resets the board, which resets the peak values. I'll need to look into that. I also haven't fully explored the capabilities of the display or how quickly I can read from the ECU. I'm mostly looking for temps that change relatively slowly, but this is more important for something like RPM that changes quickly.
I don't have a huge desire to move on from OBDII, but I wouldn't mind being able to monitor some Link specific parameters. I don't believe OBDII has a Current Gear PID (there's something, but I think it's gear ratio, not Gear 1-6), which would be neat to hook up to a 7 segment display. This could happen in the future, but for now I think I'll focus on refining what I have.
Finally got the housing redesigned and fitting decently. Not perfect, but it's slimmer and doesn't block as much of the speedo and warning lights. It also is more streamlined between the lid and the main housing.
For code updates, I allowed a default sensor to be set up, where it previously booted to a pseudo random sensor. I also found the bug that was causing the values to reset and added TPS and Ethanol %.
I received a big box of Deutsch connectors that were on sale, so I plan on swapping the ECU CAN wiring and the gauge CAN wiring over to that at some point, but the current Dupont style connectors held up at autocross last weekend, so they're doing alright.
Right now the protoboard that is housing some of the components is just floating around in the steering column shroud. It doesn't seem like it's going anywhere or going to get caught up in anything, but I don't really like it. I might try to design a PCB to get a smaller footprint, but if I go that route I'd also like to get the board into the housing and try to get the LEDs integrated somehow. Another redesign of the housing is not something I think I can handle mentally after wrestling with Fusion so much already this week.
Using OBDII means that I'm pretty sure this could be integrated into any car with CAN wiring on their OBDII port, you'd just need to wire the gauge power, ground and CAN H/L signals into an OBDII connector. One downside is that as far as I can tell the G4x will only do OBDII on one of the CAN headers, which means I can either use the gauge or the bluetooth dongle I've wired into the other CAN header. Not a huge deal, but it would be nice to have both available. I will also probably start looking into the other CAN protocols supported by the G4x, because while I can get most data I want over OBDII, it'd be nice to have access to any of the G4x parameters regardless of OBDII support.
Aside from that I'm really stoked on how this is working. I had it on the car for autocross last weekend and it was great to be able to glance down and see what my coolant or oil temp was. I also think it'll be useful for tuning, as I can see exactly what IATs or CLT is if I have a rough cold start, idle, etc...
I've had the gauge in the car for the past couple weeks now and it's been working great. No issues to report. I am curious to see how things will hold up in the summer, especially if the car is left parked in the sun. The housing has been a bit warm to the touch when I have checked, but I'm not sure if that's just ambient temps or the board getting hot.
Regardless, I may add some vent holes to the backside in the future to allow some heat to escape.
Initially when I started working on this project I wanted to put 3 LEDs on the board to act as warning lights. Those got scrapped in the first prototype mainly because they were full sized LEDs that all needed resistors and an IO pin to drive them. The packaging wasn't looking good and I didn't want to deal with the hassle, figuring I'd revisit it once things were working in their basic form. I recently realized that you can get Neopixel strips on Amazon at around $8 for 5 boards.
These are a massive upgrade from old static LEDs for a project like this. The strip has 8 RGB LEDs and a controller which only require power, ground and a single wire for control. Each LED is addressable and RBG, so any LED on the board can be turned on/off individually and set to any color and brightness. This opens up a whole range of effects and functionality as far as shift and/or warning lights. I've only been playing with these for a couple hours, so they might have more functionality I'm not aware of. I mean, at the end of the day they're LEDs, but still really neat tech.
Packaging on this isn't ideal, as the gauge is already encroaching upon the Odometer and warning lights, but I might try to add a chin at an angle to try to sneak them in at the bottom. I'm also going to need to splice a ground signal as the ESP32 only has 2 ground pins and I'm already using both, but that's not a huge deal. If/when I'm feeling a bit over the top, I should be able to add a photoresistor to add an autodimming feature, which would be nice, as these LEDs can get pretty bright. For now I'll likely add something like double pressing the button to turn them on/off so I'm not blinded by them at night.
I got the LED strip integrated into the display this weekend and did some testing. Overall I'm pretty happy with the results, although I might fine tune the LED/Sensor ranges a bit, as some of the sensors won't light any LEDs in some conditions due to the current ranges. I also should update the calculation functions to support things like Ethanol percentage. Currently it's in the "warning" stage at 65% since the low end is 10 and the high end is 85%, although I'd say 85 should be green/low and the 10% should be in the warning range. Shouldn't be too hard to update the calculation, I just haven't gotten around to it.
The refresh rate was also updated. There are two timers that are relevant here, timeout for receiving CAN messages and the delay between sending requests for the sensor data. If these are too slow the data is slow to update and the gauge seems laggy, but, as I found out this weekend, make these requests too quickly and the bus will overload and you'll get spotty responses. I found the Link seems to be happiest with requests every 100 MS (keep in mind that's a request for every sensor the gauge displays). I think it would make sense to update the sensor classes to have a polling/refresh frequency so that things like coolant can be updated once every second while TPS or RPM can be updated every 20 MS or so. That should alleviate a lot of the traffic on the bus and keep the sensors usable.
I updated the housing faceplate to add a slot for the LEDs to sit in. I have an unopened spool of black PETG but figured I'd use the translucent green spool I already had opened. I think it gives Jungle Green N64 vibes. Big fan of how this all turned out. I also added the ability to dim/brighten the LEDs by pressing and holding the button as seen in the video. I think the LEDs would be more visible if they were higher up honestly, but I think they work well enough where they're at. They flash red if the sensor value is over the error limit, which I think should be pretty obvious even with them being so low.
I also thought it might be cool to use each LED to represent a different sensor. They're individually programmable so one LED could be coolant, one could be IAT, Oil temp, tps, rpm, etc... I haven't implemented that, but I think it might be more useful to get a quick view of all sensors, even if it isn't obvious which is which. If one LED is flashing red you'd know to back off pretty quickly.
This is super cool! For warning lights, I'd suggest using different colours rather than different LEDs to give a quick reference for the nature of the warning e.g. blue for coolant temp, red for oil pressure, yellow for oil temp.
Thanks Paul! Glad to see others think so as well. I've been pretty excited about it. Not a bad idea to assign each sensor a color. It would definitely make it easier to recognize what each sensor was doing, and brightness could be ramped in to show where the value was at, flashing when it hits the upper limit (or flashing all LEDs in that specific color).
I spent all evening tinkering with this yesterday, and I did get the individual LEDs set up. I'm not totally satisfied with it, but I think it works for now. Ideally I'd like the unused LEDs to show the current sensors value, but I didn't get that implemented yet.
I also got the app mostly done
I was able to connect to the gauge over bluetooth and get data to transfer, but the formatting is getting screwed up so the data coming across is garbage. In theory you'll be able to choose which sensors to display as well as the LED style from the app. I haven't figured out how to save the configuration, but apparently the EPS32 has the ability to store data, so the idea is to save the setup when it changes. No sense having an app to configure the thing if you have to redo it every power cycle (in my opinion at least).
I'm pretty sure that 3.3V buck converter finally bit me as well. When the gauge is powered from the CAN header and bluetooth is enabled it won't boot properly. It works fine if it's powered from my laptop though, so I'm pretty sure the bluetooth module is unhappy with the weak power supply. 5 V converters should be here today (another $10 for 5 part), so I'll likely get that soldered up and do an overhaul on the general wiring.
The bluetooth/app side of things is tedious and as much as I'd like to be able to configure values for each sensor I think it would be a massive chore. Maybe someday in the future, but for now I'll leave those values hard coded in the ESP32.
In a previous post I mentioned increasing the frequency that the sensors requested data at. This was great because it seemed to make the sensors update much quicker, but after testing it seemed to overwhelm the bus and cause sensors to only update intermittently. Today I refactored some of the code which allows the sensor that is being displyed to update at 50 HZ, while the other sensors update at 10 HZ (IE 20 and 100 milliseconds respectively). This allows things like TPS and RPM to update smoothly and responsively, while still monitoring peak values of all sensors in the background, just slightly slower.
At some point I may go back and add a "refresh rate" variable for each sensor in the code, so things like temp sensor can update slowly while other sensors update quicker, but again, this seems pretty adequate for now. Depending on how many sensors are being monitored by the gauge I suppose it could become necessary at some point, but I don't think I'd add more than 8, especially since the 8 LEDs can each represent one sensor. Going above that would make that functionality less useful.
I also added MAP and Lambda sensor monitoring. When I wrote the initial code I hadn't thought about sensors that required decimal values. Not a huge consideration for coolant temps or RPM, but not having decimals would make a lambda reading pointless. I had to refactor a good deal of the code to support this, but it wasn't too invasive.
The Lambda sensor also exposed a bug around the flashing warning lights which caused them to stay illuminated and not flash (or were "flashing" too fast for the LEDs to actually show).
I had the car out this weekend in ~27 C (~ 80 F) temps. The 3d printed housing didn't seem to show any signs or warping or melting. I did briefly look into how to store data on the board, which doesn't seem too hard. In theory that would allow a configuration to be set up and saved from the phone app. Pretty low priority for me right now, but I figure I'll implement it at some point.
New voltage converts showed up this week, so I'll probably solder those in and redo the wiring this week to allow Bluetooth on the board to actually work. I might boost the brightness on the LEDs as well. They're plenty bright at night but not super noticeable in direct sunlight.
No crazy updates today, but I was able to remove the protoboard and solder the transceiver directly to the wiring, which took a lot out of the overall packaging. Originally the protoboard was going to house my warning LEDs, but the Neopixels have taken that job in stride.
I really should get a solder sucker, using this desoldering wick is pretty ineffective (likely user error).
I also swapped the 3 V buck converter out for a 5 V which did fix the issues with Bluetooth causing the board to fail to boot.
I built a little harness to get the gauge plugged into my Subaru's OBD2 port, but I couldn't get them to talk. I tried 500 Kbits and 1000, but no luck. I'll probably play with that again when I have time.
Next on the list
Update the app for the new sensors
Fix an issue with the LEDs in "Per Sensor". If one sensor triggers a warning and other sensors are in a state where they don't trigger an LED yet then they'll flash as well.
Build another gauge so I don't have to pull this one in and out of the car as often