Jeep Cruise Control to GM Drive By Wire - Resistive Multiplexed Signals.

I'm starting work on a interface to retain the factory steering wheel mounted cruise control buttons for @LBarr2002 's LS Swapped LJ.

What the Jeep Has -
The jeep uses a pretty common multiplexed signal system to allow multiple buttons to share just two signal paths. The reason for this is basically a cheaper simple clock spring. How it works is all of the buttons share a common connection all in parallel with each other, just with different resister values being connected.

Basically like this....

We have located the signals and removed them from the factor harness, I have quickly verified that it operates as others claim it does. I have yet to measure the values for each button press but here are the values I have come across online.

------ 1998 ------ 2001
None-- Open --- 19K
On --- 920 --- 440
Set --- 6.6K --- 4.1K
Res --- 15K --- 8.35K
Coast - 3K --- 2.5K
Cancel-- 0K --- 1.15K

What the GM Harness Looks for - (Taken from )

Cruise Set/Coast Signal - This is a momentary switch signal which sends 12v+ down this wire. Momentary meaning, it only sends 12v+ when the switch is pressed, when you release the switch, it should turn off. Pressing this switch quickly will set the current speed and it will be maintained. Holding it on will let vehicle coast, when you release, that will be the new set speed to be maintained. After set, each quick press of the switch will lower set speed 1 mph.

Cruise On Signal - This is simply an on / off switch that enables or disables the cruise function. This needs to be switched 12v+ to this wire.

Cruise Resume/Accel Signal - This is a momentary switch signal which sends 12v+ down this wire. Momentary meaning, it only sends 12v+ when the switch is pressed, when you release the switch, it should turn off. This switch ONLY functions after you have previously pressed the SET/COAST switch. Resume will resume vehicle speed after hitting the brakes. Holding this switch will make vehicle accelerate until you release it. Each quick press of the switch will increase set speed 1 mph.

Stop Lamp Supply Voltage - This wire should be hooked to the same wire that feeds you're brake lights 12v+ when you press on the brake pedal. The TAC module checks this circuit by monitoring lamp bulb resistance to ground. So cruise will not function if you try to use LED bulbs, or a simple on/off switch for this signal. THIS IS NOT THE SAME WIRE AS TCC BRAKE SWITCH THAT THE PCM USES TO UNLOCK TORQUE CONVERTER.
After those are wired, you also MUST have the TCC brake switch signal to the PCM. If this signal is not received by the PCM, cruise will not function. TCC Brake Switch Signal is 12v+ when brakes are NOT pressed, and the switch OPENS when you hit the brakes. This signal wire is at PCM connector C1-Blue: Pin #33; Purple wire.

My Solution
My plan is to use a simple microprocessor fed by a voltage divider and driving a couple signal relays. Ive been developing test fixtures and other random gadgets with Arduino and Microchip Processors for over 5 years and have been writing code for more than 10 years, so this seems like a pretty straight forward project. I sketched up a basic schematic {by no means enough info to directly copy this design, yet} for reference and dug through my boxes of parts to see what I had around. I buy "knockoff" Arduino Nano boards in bulk, so i choose to use one of those for the design, I also decided to socket it to the lower board, just in case i need to swap it out at some point. When this is all built up, i will either drop it in a bud box or 3D Print a housing.

This is what i have come up with so far. Couple hours of work, extra detail in making it look good for the internet.
20200118_203113.jpg 20200118_203120.jpg 20200118_203131.jpg 20200118_203139.jpg
Still deciding on a good rugged Voltage regulator to use to power the micro, I have some regulators with supervisor circuits built in, probably use one of those with some extra diodes added for good measure.

Now on to the software.
I believe i have the code close enough to test with now.
REV 0.0
  Jeep Resistive Multiplexed Cruise Control control to GM DBW Interface
  Tripp Williamson 1/2020

const int inputPin = 7; //Resistive divider input - analogRead(inputPin)

const int ranges[6][4] = { //Lower Limit - Upper Limit - State True - State False
  {910,  930, 6, 6}, //No Button
  {150,  170, 1, 1}, //On
  {660,  680, 2, 3}, //Set
  {800,  820, 4, 5}, //Resume
  {530,  550, 2, 3}, //Coast
  {340,  360, 6, 6}  //Cancel

char *rangesText[] = {"No Button", "On", "Set", "Resume", "Coast", "Cancel"};

void setup() {
  Serial.begin(57600);  // Init Serial for debug
  pinMode(10, OUTPUT); //Relay - digitalWrite(12, HIGH);
  pinMode(11, OUTPUT); //Relay
  pinMode(12, OUTPUT); //Relay


void loop() {

  for (int i = 0; i <= 5; i++) {                                            //Sample for each of the 6 Button Presses 
    if (isBetween(sampleSwitch(), ranges[i][0], ranges[i][1]) == 1) {       //Pass the limits from the Ranges Array into the isBetween Function 

      Serial.println("~~~Valid~~~");                                        //A match has been found, Print some debug info to the Serial Port
      while (isBetween(sampleSwitch(), ranges[i][0], ranges[i][1]) == 1) {  //continue to sample the condition and activate the corosponding output
      States(ranges[i][3]);                                                 //The Button condition is over, set the button release state           

  delay(100);                                                                //Delay to help debounce 

//Function: sampleSwitch
//Description: Take measurements from adc, allowing for sample time, return average
int sampleSwitch () {
  unsigned int samples = 0;                     // used to hold samples
  for (int i = 0; i <= 25; i++) {               //take 26 samples of the adc add them together
    samples = samples + analogRead(inputPin);
  return samples / 26;                          //Divide the sample total for a average

//Function: Is Between
//Description: is value between lower and upper boundary?
bool isBetween (int value, int lowerBound, int upperBound) {
  if (value > lowerBound && value < upperBound) {
    return true;
  } else {
    return false;

//Function: States
//Description: State Machine - Opperators
void States (int state) {
  switch (state) {
    case 0:    //Cruise Off
      digitalWrite(10, LOW);
    case 1:    //Cruise On
      digitalWrite(10, HIGH);
    case 2:    //Set/Coast On
      digitalWrite(11, HIGH);
    case 3:    //Set/Coast Off
      digitalWrite(11, LOW);
    case 4:    //Resume On
      digitalWrite(12, HIGH);
    case 5:    //Resume Off
      digitalWrite(12, LOW);
    case 6:    //Do Nothing

Last edited:
Ok this is cool to me. I'm amazed by people doing this sort of thing.
I love doing this kinda stuff. I enjoy a good challenge.

The hardware is pretty close, Im working with a FieldApplicationEngineer on some recommendations for the DC/DC portion that drops the battery 12-14v down to the 5v the micro needs. Automotive applications are notorious difficult because of the voltage spikes associated with cranking etc, so getting this part right takes some specialized parts.