Controlling a transfer case motor position

So this is a lot to explain. Also my first arduino project, and its a big one. Essentially i swapped the transfer case(controls the four wheel drive) in my truck to a completely different one. Problem is they're both electronically controlled and the new t-case wont work with the control module in the truck.

Basically there is a motor on the t-case that shifts it into 2wd, 4wd, 4 low, and neutral depending on the motors position. Motor position is monitored via a 3 wire potentiometer built in.

Im monitoring the 4 ground-trigger leds on the control panel in the truck to determine the mode it needs to be in using the digital pins and pullup function. This part works perfectly.

Im moving the motor via two relays that can rotate the motor either way. They're connected to pins 2 and 3. It is very important that once the motor is in the correct position that it doesn't try to move even if the potentiometer value changes. It should only move once when the mode selection(led's) change, then stay put unless a new mode is selected.

Problem I'm having now is the relays aren't doing anything. They work when manually triggered but there's no output to trigger them from the arduino.
The second problem im having is the motor will move when it isnt supposed to when the potentiometer value is changed. It should stay in the while loop under //hold until the selection(leds) change right?

I hope any of this made sense lol.

// C++ code
//
int twohled = 0;

int fourhled = 0;

int fourlled = 0;

int nled = 0;

int pot = 0;

void setup()
{
  delay(3000);
  pinMode(13, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(A0, INPUT);
  Serial.begin(9600);
}

void loop()
{
  twohled = digitalRead(13);
  fourhled = digitalRead(12);
  fourlled = digitalRead(11);
  nled = digitalRead(10);
  //TWO HIGH MODE
  if (twohled == 0 && (fourhled == 1 && (fourlled == 1 && nled == 1))) {
    Serial.println("2HI");
    //add analogue read
    pot = analogRead(A0);
    //Below
    if (pot < 535) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      Serial.println(pot);
      while (pot < 535) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 555) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      Serial.println(pot);
      while (pot > 555) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //STOP
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    //add analogue read
    pot = analogRead(A0);
    Serial.println(pot);
    //HOLD
    while (twohled == 0 && (fourhled == 1 && (fourlled == 1 && nled == 1))) {
      delay(1000);
      pot = analogRead(A0);
      Serial.print("2HL Pot:");
      Serial.println(pot);
      twohled = digitalRead(13);
      fourhled = digitalRead(12);
      fourlled = digitalRead(11);
      nled = digitalRead(10);
    }
  }
  //FOUR HIGH MODE
  if (twohled == 1 && (fourhled == 0 && (fourlled == 1 && nled == 1))) {
    Serial.println("4HI");
    //add analogue read
    pot = analogRead(A0);
    if (pot < 383) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      Serial.println(pot);
      while (pot < 383) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 403) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      Serial.println(pot);
      while (pot > 403) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //STOP
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    pot = analogRead(A0);
    Serial.println(pot);
    //HOLD
    while (twohled == 1 && (fourhled == 0 && (fourlled == 1 && nled == 1))) {
      delay(1000);
      pot = analogRead(A0);
      Serial.print("4HIL Pot:");
      Serial.println(pot);
      twohled = digitalRead(13);
      fourhled = digitalRead(12);
      fourlled = digitalRead(11);
      nled = digitalRead(10);
    }
  }
  //FOUR LOW MODE
  if (twohled == 1 && (fourhled == 1 && (fourlled == 0 && nled == 1))) {
    Serial.println("4LO");
    //add analogue read
    pot = analogRead(A0);
    //Below
    if (pot < 760) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      while (pot < 760) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 780) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      while (pot > 780) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //STOP
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    pot = analogRead(A0);
    Serial.println(pot);
    //HOLD
    while (twohled == 1 && (fourhled == 1 && (fourlled == 0 && nled == 1))) {
      delay(1000);
      pot = analogRead(A0);
      Serial.print("4LL Pot:");
      Serial.println(pot);
      twohled = digitalRead(13);
      fourhled = digitalRead(12);
      fourlled = digitalRead(11);
      nled = digitalRead(10);
    }
  }
  //NEUTRAL MODE
  if (twohled == 1 && (fourhled == 1 && (fourlled == 1 && nled == 0))) {
    Serial.println("NEUTRAL");
    //add analogue read
    pot = analogRead(A0);
    //Below
    if (pot < 694) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      while (pot < 694) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 714) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      while (pot > 714) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //STOP
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    //add analogue read
    pot = analogRead(A0);
    Serial.println(pot);
    //HOLD
    while (twohled == 1 && (fourhled == 1 && (fourlled == 0 && nled == 1))) {
      delay(1000);
      pot = analogRead(A0);
      Serial.print("NEUTRAL Pot:");
      Serial.println(pot);
      twohled = digitalRead(13);
      fourhled = digitalRead(12);
      fourlled = digitalRead(11);
      nled = digitalRead(10);
    }
  }
  delay(10);
   // Delay a little bit to improve simulation performance
}

I have fixed the relays not working. Didn't have pinMode OUTPUT set for 2 and 3 at the beginning. Still cant figure out how to make it stop moving until another mode is selected.

In other words after //hold I want just that while loop to loop, but its like it loops all the way back to the beginning of the void loop. it even prints the "2HI" again along with "2HIL"

I did some research and some chat-gpting. It seems the most likely situation is that there is some interference of some kind causing the while loop condition to be false for a millisecond or so causing the loop to exit. I suspect it could be because these led's are pwm controlled for whatever reason general motors felt that was necessary.

Chatgpt actually came up with this solution that uses millis() to create a grace period of 50ms or so where the condition can be false without exiting the loop. Here is the code it wrote ill put in place of the while loop under //hold. Does it seem like this could work?

unsigned long lastStableTime = millis();

while (true) {
    // Check if the condition is currently true
    if (twohled == 0 && (fourhled == 1 && (fourlled == 1 && nled == 1))) {
        lastStableTime = millis(); // Update the last stable time
    }

    // Check if the condition has been false for too long
    if (millis() - lastStableTime > 50) { // Grace period: 50 ms
        break; // Exit the loop if the condition is unstable for too long
    }

    // Perform actions inside the loop
    pot = analogRead(A0);
    Serial.print("2HL Pot: ");
    Serial.println(pot);

    // Update the input states
    twohled = digitalRead(13);
    fourhled = digitalRead(12);
    fourlled = digitalRead(11);
    nled = digitalRead(10);

    delay(1); // Optional: Prevent excessive CPU usage
}

I don't understand how you want to control 4 wheels by a single motor.

Did you consider different wheel speed, slip and other effects in curves?

Please describe better what you want to do, not how you want to do it.

1 Like

I think this explains it nicely.

The motor drives the transfer-case selector, there is a feedback pot to display what mode the case is in.

@gavinh2 can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

We need to see how you have wired the pot and the relays to the motor.

What pot analog readings represent each t-case mode?

What are the four inputs?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

I'm thinking the "pot" is internal to the transfer case and used to feed back the control shaft position similar to an RC servo. Is that a correct assumption?

yes exactly

Did my best on the hand drawings. Just to clarify the potentiometer is inside the motor to determine the shaft's position. The range of motion is less than 180 degrees.

I was actually able to get the whole thing working perfectly and the motor would move to the correct position depending on which led was lit up.

The only issue I have is once the motor completes its movement, it must not move until another mode is selected. For example if the motor is manually moved and the potentiometer value becomes out of range for the selected mode, it must not try and adjust back.
This is extremely important because if there is a temperature change or vibration causing the potentiometer's value to change, and the Arduino tries to adjust the motor position while the vehicle is in motion, it could destroy the transfer case. Especially if a relay were to stick and it overshoots the value.

Well, I would think you could set a boolean "in position" flag that would lockout the relays as long as the switch positions do not change.
BTW, you cannot put 12V on the UNO's input pins, you need voltage dividers or level shifting transistors down to 4V.

That’s what I was thinking.

As for the 12v on the Arduino pins. It’s on the ground side of the leds which have a resistance of 500 ohms. It’s also using the internal pull up resistors to detect whether the ground is present or not since the leds are ground switched. It hasnt blown up yet so idk. And it correctly identifies which lights are lit.

You will be driving about 10mA through the pin's ESD protection diode, I believe they're rated about 1mA. Might work for a while. I would rethink that arrangement.

I’ll change it if it blows up the board. I can buy a board from the micro center down the road for $12.99 so I’m not too concerned. If it ain’t broke don’t fix it.

I thought those pins were good for 40ma each no? 12v/500ohm is .025 so in my mind it was fine.

Been playing with it for hours and it has yet to break but i'll keep y'all posted. In the mean time the chat-gpt solution worked on the code. Here's the full thing if that helps with anyone in the future basically what I did was move the while loop to the end rather than having it redundantly in each if statement, then swapped it out for the what chat gpt said would work. It essentially just checks to see if the statement is false for a certain amount of time before exiting the loop. I also replaced the binary led conditions with another set of variables that is defined according to what mode was selected.

// C++ code
// fix Hold indicator
//move while loop to beginning
//allow for a little adjustment before holding
//mode identification on startup to go straight into hold
int twohled = 0;

int fourhled = 0;

int fourlled = 0;

int nled = 0;

int pot = 0;

int twohreq = 0;

int fourhreq = 0;

int fourlreq = 0;

int nreq = 0;

unsigned long lastStableTime = 0;

void setup()
{
  delay(3000);
  pinMode(13, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(A0, INPUT);
  Serial.begin(9600);
}

void loop()
{
  twohled = digitalRead(13);
  fourhled = digitalRead(12);
  fourlled = digitalRead(11);
  nled = digitalRead(10);
  //TWO HIGH MODE
  if (twohled == 0 && (fourhled == 1 && (fourlled == 1 && nled == 1))) {
    Serial.println("2HI");
    pot = analogRead(A0);
    //Below
    if (pot < 515) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      Serial.println(pot);
      while (pot < 515) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 540) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      Serial.println(pot);
      while (pot > 540) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //what values should not be to exit hold
    twohreq = 0;
    fourhreq = 1;
    fourlreq = 1;
    nreq = 1;
  }
  //FOUR HIGH MODE
  if (twohled == 1 && (fourhled == 0 && (fourlled == 1 && nled == 1))) {
    Serial.println("4HI");
    //add analogue read
    pot = analogRead(A0);
    if (pot < 378) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      Serial.println(pot);
      while (pot < 378) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 408) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      Serial.println(pot);
      while (pot > 408) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //what values should not be to exit hold
    twohreq = 1;
    fourhreq = 0;
    fourlreq = 1;
    nreq = 1;
  }
  //FOUR LOW MODE
  if (twohled == 1 && (fourhled == 1 && (fourlled == 0 && nled == 1))) {
    Serial.println("4LO");
    //add analogue read
    pot = analogRead(A0);
    //Below
    if (pot < 755) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      while (pot < 755) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 785) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      while (pot > 785) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //what values should not be to exit hold
    twohreq = 1;
    fourhreq = 1;
    fourlreq = 0;
    nreq = 1;
  }
  //NEUTRAL MODE
  if (twohled == 1 && (fourhled == 1 && (fourlled == 1 && nled == 0))) {
    Serial.println("NEUTRAL");
    //add analogue read
    pot = analogRead(A0);
    //Below
    if (pot < 689) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      while (pot < 689) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //Above
    if (pot > 719) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      while (pot > 719) {
        pot = analogRead(A0);
        Serial.println(pot);
      }
    }
    //what values should not be to exit hold
    twohreq = 1;
    fourhreq = 1;
    fourlreq = 1;
    nreq = 0;
  }
  //STOP
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  //add analogue read
  pot = analogRead(A0);
  Serial.println(pot);
  //HOLD
  while (true) {
    // check if condition is currently true
    if (twohled == twohreq && (fourhled == fourhreq && (fourlled == fourlreq && nled == nreq))) {
        lastStableTime = millis(); // Update the last stable time
    }
    //check if condition has been false for too long
    if (millis() - lastStableTime > 500) { //50 ms grace period
        break;
    }
    //loop actions
    pot = analogRead(A0);
    Serial.print("2HL Pot: ");
    Serial.println(pot);
    // Update the input states
    twohled = digitalRead(13);
    fourhled = digitalRead(12);
    fourlled = digitalRead(11);
    nled = digitalRead(10);

    delay(1); // Optional: Prevent excessive CPU usage
  }
  delay(10);
   // Delay a little bit to improve simulation performance
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.