Hacking an Equinox electric power steering ( EPS ) unit

itstallion

Newbie
Original poster
Dec 2, 2021
6
Cincinnati
Hello everyone,


So let me start by saying I stumbled across your forum while searching the internet for any information regarding GM class 2 data network over J1850 bus. You see the rabbit hole I voluntarily threw myself down brought me here. I've victoriously resurfaced and I'm here to share everything I learned so that the next guy/gal who is starting down that hole doesn't have as far to go as I did.

I have a 65 Chevy II SS that I've had the privilege of owning and driving since 1993. Bought from the original owners for $900.00. Since then, she’s had 2 paint jobs and lots of modifications. Right now, she's way back on the back burner because of life and the many kids that I have now. I'm always yearning to get her back on the road, but life seems to be winning that tug-a-war for now. I've always wanted to add power steering to my Nova and since I'm now running a Fat Man Strut conversion kit on her with rack and pinion steering, I really wanted that extra help when maneuvering in tight spaces. I just recently learned of this anomaly called Electric Power Steering which has been available for some time unbeknownst to me. After doing some research I discovered that most of the options out there are manufactured by Koyo Seiko. They basically own the market on Electric Power Steering. So, after looking at all the options of using one from a Toyota model or some other import models. I decided on a model from a 2006 Chevy Equinox. I decided on this model as I had learned that there were ready made solutions available on E-Bay that would allow you to connect to your Equinox EPS unit and wake it up. I’m a tinkerer at heart and if there’s an opportunity for me to achieve a goal and gain knowledge in the process then I’m all for it versus just shelling out the bucks for a solution to be handed to me. I have experience with Arduino so I decided to take the plunge. So here we go.


I set off to the salvage yard to pull one of these new-fangled EPS’s from a 2006 Blue Equinox. The hardest part of removing it was removing the airbag from the steering wheel. After that it basically fell out from under the dash. The unit has 3 connectors going to it. One connector has ground and power to the motor and one connector has ground and power to the controller. This power wire goes directly to the battery. The third smaller connector has two tiny wires coming out of it. One of the small wires is a pink wire which takes 12v when the ignition is on, and it tells the unit to come on or go off when the car is turned on and off. This causes a relay inside the unit to click. The second tiny wire is a purple wire and this wire comes from the J1850 transceiver chip inside the EPS controller. This connects to the J1850 bus. You can find a document for the SAE J1850 Bus specification if you want some heavy reading. I found multiple Arduino libraries and examples that talk on a J1850 bus.



After you grab one of these Arduino libraries/examples and you hook up your Arduino to the purple wire you should start receiving hex codes like the following.


08FF30032D​
8AEA3020C90064​
C952300437​
A9283002E0​
49FE3006C2​
C9FA300285​
What you’re looking at here is data that’s being sent out over the one wire bus. This data protocol is defined by the SAE J2178 document. There are 4 parts of this document, and you should be able to find all 4 of them on the Internet. You don’t need to purchase the latest copy from SAE. Each line of the data is called a frame and the frame is made up of data in Hex format and 2 characters represents a Byte of data. The first 3 bytes of the frame are defined as the header and depending on that header and the function that is specified in the header, the next several bytes can be defined as the data that goes along with that function. The last byte of the frame is called the CRC byte. Using the SAE2178 documents you will decipher these packets of data and determine what the controller is saying or asking for.

There are two pieces of information that the controller requires to wake up and start providing power assistance to the input shaft of the EPS unit. One is the vehicle speed and two is the request for the status of the engine being on. Using the J2178 documents you will find that the frame of data in the above example (C952300437) contains the second byte Hex 0x52 and is the message from the EPS asking if the engine is on. After looking through the SAE J2178 documents and online resources I discovered that the message/frame (88531184AE) is a valid response to send to the EPS and tell it that the engine is indeed on. The next request from the EPS is the frame (A9283002E0) and that the message from the EPS is asking for the vehicle speed. After looking through the SAE J2178 documents and online resources I discovered that the message (8829110200003B) is a valid response to send to the EPS and tell it that the speed of the vehicle is 0MPH which will provide you with the maximum assistance from the EPS.

After some trial and error, I was able to send these two messages/responses to the EPS using my Arduino and all of a sudden my EPS was alive and working. My plan is to read the data from the speed sending unit that came with my aftermarket gauges and send real time vehicle speed messages to the EPS so that the power assist will lower as the speed of the car increases and the power assist is not needed.

Tip: I had my EPS unit hooked up to a benchtop Power Supply and it would show how many milliamps it was drawing which helps in determining what the controller is doing. You’ll notice the controller before it get’s turned on will hang around 350-380 milliamps and once it turns on you’ll see it jump up into 400 milliamps.

Here are some links to the online resources I relied on and that you may find helpful.

Thanks and happy tinkering!


Great info here with real examples of J2178 data, especially the Google Sheets

ELM327 & Class 2 Serial Data | GMTNation


Good introduction to J2178

Digital Tachometer for Harley Davidson Sportster (Part 3 - Harley Davidson and SAE J1850 VPW) · Momex


CRC page to generate the CRC byte if you choose to create your own responses for your application.

Use for the CRC parametrization option CRC8_SAE_J1850

Sunshine's Homepage - Online CRC Calculator Javascript (sunshine2k.de)


Arduino Code used to capture and transmit data on the J1850 bus

GitHub - matsekberg/j1850decoder: An Arduino based OBD2/J1850 decoder.

GitHub - matsekberg/j1850emitter: Arduino that emits J1850 messages used for testing of j1850decoder
 

Mooseman

Master Blaster
Moderator
Dec 4, 2011
21,822
Ottawa, ON
One helluva first post. Welcome! Although most of that went over my head, I think we have a couple of guys that might be interested in the J1850 and SAE 2178 info (paging Dr. @TJBaker57 )

That must have been a really deep rabbit hole!
 

NJTB

Platinum Donor
Aug 27, 2012
542
Flemington, NJ
How much fabrication was involved to get the steering column to fit? Were the splines the same for the shaft, or was welding involved, did you have to make plates to mount it to the firewall? Mounts under the dash?
Sounds like a fun project.
 
OP
I

itstallion

Newbie
Original poster
Dec 2, 2021
6
Cincinnati
Hi,
My plan originally was to install the EPS in line with the existing linkage in the engine compartment. After acquiring one it was apparent it's not weather proof. So now the plan is to modify the 70's GM van tilt column that I have in the car right now. Bringing it inside is where it was designed to live. I have a lathe so some modification will be made to the column shaft to interface (weld and pin) to the EPS units column shaft that engages with the splines of the input shaft on the EPS. The output shaft of the EPS I believe is 16.5 mm - 36 spline. I'll either go back and grab the rest of the steering linkage off the equinox rack or purchase an adapter to convert to double D shifting. I already have a plate for the firewall to support the shaft through the firewall. Here's a picture of my bench test.
20211211_102441.jpg
 
  • Like
Reactions: azswiss and Mektek

TJBaker57

Guru
Aug 16, 2015
1,999
Colorado
I have experience with Arduino so I decided to take the plunge


My knowledge of Arduino or similar devices is doodley-squat/zip/nada. But I have had for some time an idea for a project. Let me throw this at you.

Your Arduino can interface with the J1850 bus and both request and receive data as set forth in J2178. Can such a device/project also be outfitted to read a user supplied analog sensor (or two or three), similar to say a coolant temperature sensor. And can the device be programmed to respond to a properly formatted J1850 data bus request for said sensor?? I am of the mind that these things are possible.

The notion is that with such a project a user could add a sensor like a temp sensor on any part of a vehicle they wanted to monitor, wire it to the Arduino project and have the Arduino respond to requests for said data sent by an App like Torque Pro, OBD Fusion, etc. using the existing vehicle data bus.
 
OP
I

itstallion

Newbie
Original poster
Dec 2, 2021
6
Cincinnati
That would be possible as long as the data PID is defined by J2178 for said sensor/s. You would also have to use a data PID not in use as an existing module on the bus would be sending conflicting answers. My arduino is basically mimicking the ECU and sending speed/engine status messages so there are no other modules on the bus to contend with. I guess you could use a data pid for a non-existing sensor on the vehicle to ensure no over lap.
 

TJBaker57

Guru
Aug 16, 2015
1,999
Colorado
That would be possible as long as the data PID is defined by J2178 for said sensor/s. You would also have to use a data PID not in use as an existing module on the bus would be sending conflicting answers


Precisely what I was thinking. Use of a functional target address for a parameter that is non-existant on the vehicle, maybe even use one designated as manufacturer defined. Easy enough to query the existing network to be certain no other module answered.

For the physical node address of the Arduino that too should be simple to assign it a node address that is not in use.

Years ago I had some third gen Trans Ams and had issues with overheated fuel causing the pump to cavitate. I would lose pressure and stall out if stopped in traffic. I bought some indoor-outdoor remote sensing thermometers and routed the sensors through the firewall to attach to the fuel supply and return lines (insulating them as well) so I could tell when I was nearing the temperature when the trouble would surface.

This Arduino project would be a more flexible modern day equivalent.
 
OP
I

itstallion

Newbie
Original poster
Dec 2, 2021
6
Cincinnati
For the physical node address of the Arduino that
Years ago I had some third gen Trans Ams and had issues with overheated fuel causing the pump to cavitate. I would lose pressure and stall out if stopped in traffic. I bought some indoor-outdoor remote sensing thermometers and routed the sensors through the firewall to attach to the fel supply and return lines (insulating them as well) so I could tell when I was nearing the temperature when the tre would surface.
This Arduino project would be a more flexible modern day equivalent.
The Arduino is very powerful. My first project with the Arduino was a controller for my power windows. It would monitor the current to each motor for an all down/up function via remote. I also had a touchscreen to operate each window but ultimately decided a touch screen to operate the windows was not such a good idea.
 
  • Like
Reactions: TJBaker57

TJBaker57

Guru
Aug 16, 2015
1,999
Colorado
After some trial and error, I was able to send these two messages/responses to the EPS using my Arduino and all of a sudden my EPS was alive and working.


@itstallion

Care to share insights into getting the Arduino communicating with J1850?? I am getting nowhere rapidly! I have tried several different Github projects and have only succeeded in one attempt which only reads the data stream.
 
OP
I

itstallion

Newbie
Original poster
Dec 2, 2021
6
Cincinnati
Here's a copy of my code that I'm running on my nano for this project. It waits for certain messages/requests and then sends the appropriate response. I'm using 3 pins on my arduino. One pin for sending data (8), one pin for receiving data (9) and one pin for monitoring the bus and triggering the interrupt to read the data (3). All three pins are tied to the bus. I did manage to fry a Nano by trying to use an old school battery charger that can put out 120 amps but not at 12volts. It does it at 18 volts which fried the Arduino's onboard voltage regulator. Documentation is all over the place but I found the datasheet for that specific voltage regulator and it specified 15 volts is the max so I'm incorporating a buck converter that can handle up to 28 volts and bring it down to 5volts. I guess connecting the car electrical directly to an Arduino is a bit 'how ya doin' - Davy Jones. I'm using an MP1584EN buck converter now.
 

Attachments

  • Arduino_J1850.txt
    7.8 KB · Views: 5

TJBaker57

Guru
Aug 16, 2015
1,999
Colorado
Here's a copy of my code that I'm running on my nano for this project


Thanks so much! It will take me quite some time to wade into this. A portion of the code you shared is the one that I got to read after some trial.

The readme for the code stated to connect to pins D2 & D9 so there I was trying to get anything to work and getting nothing. Eventually looked at the code and it at least looked to me that I should be connected to pins D3 & D9....

Screenshot_20211231-181641.png

Screenshot_20211231-181715.png

Another thing I altered may or may not be correct. I found an instance where the code did not match the comment. I changed the code to match the comment.

Screenshot_20211231-181538.png


I have also tried some other codes/libraries from Github as well as some circuitry to interface between the J1850 bus and the Arduino. I had read somewhere that connecting the Arduino directly to the J1850 bus might not work due to the voltage differences but at least for reading the bus it seems to work with the code you shared. And thus far I have nothing working with the circuitry I have tried. That circuitry was copied from the ELM327 datasheet.

Screenshot_20211219-091141.png

I'll keep tinkering with various approaches. Today I received some optocouplers to try that approach!! Saw them used on an old "Nerdkits" video.

 
OP
I

itstallion

Newbie
Original poster
Dec 2, 2021
6
Cincinnati
Thanks so much! It will take me quite some time to wade into this. A portion of the code you shared is the one that I got to read after some trial.

The readme for the code stated to connect to pins D2 & D9 so there I was trying to get anything to work and getting nothing. Eventually looked at the code and it at least looked to me that I should be connected to pins D3 & D9....

View attachment 102598

View attachment 102599

Another thing I altered may or may not be correct. I found an instance where the code did not match the comment. I changed the code to match the comment.

View attachment 102600


I have also tried some other codes/libraries from Github as well as some circuitry to interface between the J1850 bus and the Arduino. I had read somewhere that connecting the Arduino directly to the J1850 bus might not work due to the voltage differences but at least for reading the bus it seems to work with the code you shared. And thus far I have nothing working with the circuitry I have tried. That circuitry was copied from the ELM327 datasheet.

View attachment 102601

I'll keep tinkering with various approaches. Today I received some optocouplers to try that approach!! Saw them used on an old "Nerdkits" video.


Thanks so much! It will take me quite some time to wade into this. A portion of the code you shared is the one that I got to read after some trial.

The readme for the code stated to connect to pins D2 & D9 so there I was trying to get anything to work and getting nothing. Eventually looked at the code and it at least looked to me that I should be connected to pins D3 & D9....

View attachment 102598

View attachment 102599

Another thing I altered may or may not be correct. I found an instance where the code did not match the comment. I changed the code to match the comment.

View attachment 102600


I have also tried some other codes/libraries from Github as well as some circuitry to interface between the J1850 bus and the Arduino. I had read somewhere that connecting the Arduino directly to the J1850 bus might not work due to the voltage differences but at least for reading the bus it seems to work with the code you shared. And thus far I have nothing working with the circuitry I have tried. That circuitry was copied from the ELM327 datasheet.

View attachment 102601

I'll keep tinkering with various approaches. Today I received some optocouplers to try that approach!! Saw them used on an old "Nerdkits" video.


I initially attempted an insulating circuit design between the Arduino and the bus using transistors but was unsuccessful. I then hooked the Arduino pins directly to the J1850 bus (purple wire) after referring to the sae_j1850.pdf the dc parameters basically specify a TTL voltage range of 5v so the Arduino is able to talk directly on the bus. I know this doesn't provide any protection between the two but it's something I'm willing to live with.

Regarding the code I uploaded you can ignore the analog pin code that's something I was playing with the last time I was working in the code. I was starting to incorporate a potentiometer to adjust the speed reported to the Koyo controller. I've since stopped developement on that and I'm now working on designing an enclosure in FreeCAD to 3D print to hold the nano + buck converter and mount to the Koyo controller. When I get it finished I'll post the link to it on Thingiverse.

I eventually plan on reading the speed sensor output that came with my aftermarket gauges and correlating that to a speed and reporting it to the Koyo to fully implement an automated self adjusting power steering system like factory. For now my Nova is 900 miles away from me so it'll have to wait till I can get a place to have the car here with me.

My next project after all this is to develop an electric fan controller to adjust the fan speed (PWM) based on the radiator output temperature. Basically a homegrown Derale Fan controller. Right now my fan just turns on and off based off the temperature sensor located on the output side of the intake manifold. Adding variable speed to the fan will be a nice addition.
 
  • Like
Reactions: TJBaker57

TJBaker57

Guru
Aug 16, 2015
1,999
Colorado
Well I haven't been fiddling with any interface circuitry but I have been noodling about your posted code trying to learn how this all works. I have made some progress here and there. Much is still beyond me and there are things on the horizon that I will struggle with when I need to add them like CRC checking and generation and message arbitration.

I have changed the message monitoring to resolve the full addressing of Primary ID, Secondary ID, and where required for message types 9 & 10, Extended address.

Here is a screenshot showing 3 "load command extended" messages for 'change engine oil' (5th byte 0x82), 'check gauges' (5th byte 0x85), and 'reduced engine power' (5th byte 0xB7) and their respective "status report" messages in response. The first two lights are off and the last light, 'reduced engine power" is on. Currently the reports are still fixed as I cannot yet do the CRC generation.

Screenshot_20220104-130545_Serial Bluetooth Terminal.jpg
 

Forum Statistics

Threads
21,828
Posts
617,965
Members
16,061
Latest member
flog