My Dad is concerned that the stress of towing a caravan across the desert (or coastal highway, whatever) will put extra strain on the towing vehicle (Mazda BT 50).
So, I figure I can watch the CAN bus with an Arduino & CAN chip, and beep when an alarm threshold is reached on whatever parameters we decide are worth monitoring (transmission oil temperature, for example).
There's already a "ScanGauge" in the car that can monitor things visually, but doesn't have an alarm. Much better to keep your eyes on the road!
Arduino Pro Micro
MCP2515 CAN module
It's just a buzzer and a transistor, but for about $1 shipped it's a bargain
The CAN module comes with an 8MHz one which doesn't suit 500kb/s comms
Without the right car to test on, programming the manufacturer-specific messages is essentially coding blindfolded. I've got some information from Scangauge which I have roughly reverse-engineered, but the true test will have to wait until I have access to the car. Or a Scangauge, which may be able to confirm the (in)accuracy of my reverse engineering / forum searching.
Frank's MCP2515 library is easy to work with, so I'm pretty confident that what I program will make it onto the CAN bus, but is it the right thing? What will the response look like? The software will probably have to go on hold until I can test on the right vehicle.
Next step: assemble everything in a nice neat package. Might add a "buzzer silence" button too.
Today I swapped the 8MHz crystal on the CAN module for a 16MHz one, and funnily enough, the speed of communications doubled. I'm now able to talk at 500kb/s, the standard speed used on the OBD-II port.
The CAN -H & -L signals didn't look very good at all on my scope,
but I decided to plug it into the car anyway, and it worked! (I can't
really scope it in the car so not sure if termination resistors or
something make the signals look any better)
I strapped my laptop in and went for a lap around the block.
There's a ton of failed reads (nothing returned for whatever reason) and a few false readings (it's completely impossible for my car to do 2144km/h), but things are looking promising. After pulling apart the test rig I noticed that I was hooked in to chassis ground (pin 4), instead of signal ground (pin 5), which might explain some glitches.
Sample log data: (dot indicates nothing returned, requests every ~500ms)
Vehicle Speed: 25 km/h
Engine Speed: 0 rpm
.Vehicle Speed: 27 km/h
Engine Speed: 1950 rpm
..Vehicle Speed: 36 km/h
Engine Speed: 2617 rpm
Vehicle Speed: 38 km/h
Engine Speed: 0 rpm
.Vehicle Speed: 7 km/h
Engine Speed: 872 rpm
Vehicle Speed: 2144 km/h
Engine Speed: 0 rpm
Interestingly, the vehicle speed seems to get a response a lot more often than the RPM - this may be because I request the vehicle speed first, and then RPM immediately after, I should put a small delay in between to avoid congesting the bus. Anyway, now I have enough confidence to move onto to building something more permanent and writing software for the final application.
Initially had a lot of trouble because the SparkFun library used the same file names - my code would compile fine, but just crash the Arduino. Deleted the SparkFun library and things improved.
Now I at least have some SPI data going across to the MCP2515. I've written a minimal test on the Arduino (just reads the vehicle speed and rpm), but it didn't work on my car. I'm not 100% sure that my car even does speak CAN on its OBD port, but I am 98% confident...
Looking at the CAN H & L pins on the scope, H is moving between 2.33 & 3.94V, L is doing the inverse between 2.33 & 0.70V, which seems within spec. Not sure if it's doing the right speed though, the pulses I'm seeing look more like 250kHz than the 500kHz I was expecting.
Next steps: Try setting different speeds, check CAN on logic analyser or USB dongle
Edit: My speed woes are due to my cheap board using an 8MHz crystal. Need to study the MCP2515 datasheet to see if it can do 500kbps with an 8MHz clock, or swap in a 16MHz crystal.