Auto trans controller

Hey all. I have one project that I am working on currently. My previous post has been put on the back burner for now.

However I am stuck. It may seem to be an easy project for some but i have been pulling hair out trying to get this to work.

I need to control 6 relays.

Components used:
Arduino Nano
12v 8 channel solid state relay (High Trigger)
2 of micro (Limit) Switches (Gear Up and Gear down)
1 of 12mm momentary switch. (Coil Cut)

The problem im having is getting the relays to trigger how I need. Basically I am using 4 relays to control the auto trans (Shift solenoids 1&2, Trans lock up and a clutch pack. All run) and 2 to trigger the ignition coils for "flat shift"

The prompt I used for Chat GPT is:

***PinOut
D2 - SS1R (Shift solenoid 1)
D3 - SS2R (Shift Solenoid 2)
D4 - FCSR (Forward clutch solenoid)
D5 - LUSR (Lock up solenoid)
D7 - GUS (Gear Up) (Configure that pin as a digital input with pull up enabled)
D8 - GDS (Gear Down) (Configure that pin as a digital input with pull up enabled)
D11- 4 neopixel bar
D13 - ICRS (coilcut switch) (Configure that pin as a digital input with pull up enabled)
A2 - 1&4 Coil relay
A3 - 2&3 Coil relay

Relay layout
G1
D2 - High
D3 - High
D4 - High
D5 - Low
A2 LOW for 125ms
A3 LOW for 125ms
Neopixel - 1 purple

G2
D2 - High
D3 - low
D4 - High
D5 - Low
A2 LOW for 125ms
A3 LOW for 125ms
Neopixel - 2 purple

G3
D2 - low
D3 - low
D4 - High
D5 - High
A2 LOW for 125ms
A3 LOW for 125ms
Neopixel - 3 purple

G4
D2 - low
D3 - High
D4 - low
D5 - High
A2 LOW for 125ms
A3 LOW for 125ms
Neopixel - 4 purple

When arduino is powered on trigger a2 and a3 HIGH and start at G1

When arduino has triggered G1 and D7 is triggered Low, transition necessary pins to G2.

When arduino has triggered G2 and D7 is triggered Low, transition necessary pins to G3.

When arduino has triggered G3 and D7 is triggered Low, transition necessary pins to G4.

When arduino has triggered G4 and D8 is triggered Low, transition necessary pins to G3.

When arduino has triggered G3 and D8 is triggered Low, transition necessary pins to G2.

When arduino has triggered G2 and D8 is triggered Low, transition necessary pins to G1.

If d13 is triggered LOW trigger, Trigger a2 and a3 Low while D13 is LOW. ***

and the code i got is as follows

#include <Adafruit_NeoPixel.h>

#define NEOPIXEL_PIN 11
#define NUM_PIXELS 4

// Pin Definitions
const int SS1R = 2;
const int SS2R = 3;
const int FCSR = 4;
const int LUSR = 5;
const int GUS = 7;
const int GDS = 8;
const int ICRS = 13;
const int COIL1_4 = A2;
const int COIL2_3 = A3;

Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
    pinMode(SS1R, OUTPUT);
    pinMode(SS2R, OUTPUT);
    pinMode(FCSR, OUTPUT);
    pinMode(LUSR, OUTPUT);
    pinMode(GUS, INPUT_PULLUP);
    pinMode(GDS, INPUT_PULLUP);
    pinMode(ICRS, INPUT_PULLUP);
    pinMode(COIL1_4, OUTPUT);
    pinMode(COIL2_3, OUTPUT);
    
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'

    // Start at G1
    triggerG1();
}

void loop() {
    if (digitalRead(GUS) == LOW) {
        transitionToNextState();
    }
    if (digitalRead(ICRS) == LOW) {
        digitalWrite(COIL1_4, LOW);
        digitalWrite(COIL2_3, LOW);
    }
}

void triggerG1() {
    digitalWrite(SS1R, HIGH);
    digitalWrite(SS2R, HIGH);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, LOW);
    digitalWrite(COIL1_4, LOW);
    digitalWrite(COIL2_3, LOW);
    setNeopixelColor(1);
    delay(125);
}

void triggerG2() {
    digitalWrite(SS1R, HIGH);
    digitalWrite(SS2R, LOW);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, LOW);
    digitalWrite(COIL1_4, LOW);
    digitalWrite(COIL2_3, LOW);
    setNeopixelColor(2);
    delay(125);
}

void triggerG3() {
    digitalWrite(SS1R, LOW);
    digitalWrite(SS2R, LOW);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, HIGH);
    digitalWrite(COIL1_4, LOW);
    digitalWrite(COIL2_3, LOW);
    setNeopixelColor(3);
    delay(125);
}

void triggerG4() {
    digitalWrite(SS1R, LOW);
    digitalWrite(SS2R, HIGH);
    digitalWrite(FCSR, LOW);
    digitalWrite(LUSR, HIGH);
    digitalWrite(COIL1_4, LOW);
    digitalWrite(COIL2_3, LOW);
    setNeopixelColor(4);
    delay(125);
}

void transitionToNextState() {
    static int currentState = 1;
    switch (currentState) {
        case 1:
            triggerG1();
            currentState = 2;
            break;
        case 2:
            triggerG2();
            currentState = 3;
            break;
        case 3:
            triggerG3();
            currentState = 4;
            break;
        case 4:
            triggerG4();
            currentState = 3; // Loop back to G3
            break;
    }
}

void setNeopixelColor(int index) {
    for (int i = 0; i < NUM_PIXELS; i++) {
        if (i == index - 1) {
            strip.setPixelColor(i, strip.Color(128, 0, 128)); // Purple
        } else {
            strip.setPixelColor(i, strip.Color(0, 0, 0)); // Off
        }
    }
    strip.show();
}

I have added everything to wowki and i am unable to get it to work. Can anyone please shed some light or modify the code so i can upload it and stop pulling out my hair. More than happy to answer any questions.

Regards
Nick.

Have you asked ChatGPT what is wrong ?

Multiple times, I have changed the prompt multiple times. tried braking it down multiple ways and still no luck. Im slightly ashamed that i have asked chatgpt for the code but im getting nowhere

Please post a link to the wokwi simulation, that will be a time saver.

a7

Please describe as accurate as what that means.

One thing I noticed is that you never make your coils high again. They start with LOW (by default) and in triggerGx() you make them LOW again.

Black switch is gear up
White is gear down.

And I see transitionToNextState() not at all implementing 1 2 3 4 3 2 1 2 3 4 3 2 1, which is what I think you are asking for.

At least that function would need to know which way it was going shifting up or down.

The solenoids aren't written HIGH to begin with as you asked , and never get written HIGH as @sterretje observes.

Set them HIGH in setuo(), and HIGH again after the 125 millisecond delays making the pulses.

a7

1 Like

So when i emulate the exact code in Wowki. the gear up works only once. But once its in g3 or g4 it bounces between the two. I am unable to shift down.

I will modify the coil code. all i really need is for some help or even a code written that i can switch between with the use of the limit switches which i operate manually.

That is a very poor description of the problem. What does the code actually do ?

I am glad that ChatGPT could understand your requirements because I certainly can't

For instance, what is G1 ?

Hey @UKHeliBob

G1,2,3,4 is for Gear1,2,3,4

I have managed to make the code work over once the arduino is in G4 i am unable to transition back down to G3. 123 up and down work now but for some reason i am locked out of changing down from g4 to g3. everything else is working perfectly

#include <Adafruit_NeoPixel.h>

#define NEOPIXEL_PIN 11
#define NUM_PIXELS 4

// Pin Definitions
const int SS1R = 2;
const int SS2R = 3;
const int FCSR = 4;
const int LUSR = 5;
const int GUS = 7;
const int GDS = 8;
const int ICRS = 13;
const int COIL1_4 = A2;
const int COIL2_3 = A3;

Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
    // Initialize pins
    pinMode(SS1R, OUTPUT);
    pinMode(SS2R, OUTPUT);
    pinMode(FCSR, OUTPUT);
    pinMode(LUSR, OUTPUT);
    pinMode(GUS, INPUT_PULLUP);
    pinMode(GDS, INPUT_PULLUP);
    pinMode(ICRS, INPUT_PULLUP);
    pinMode(COIL1_4, OUTPUT);
    pinMode(COIL2_3, OUTPUT);
    
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'

    // Start at G1
    transitionToG1();
}

void loop() {
    static int currentState = 1;

    if (digitalRead(GUS) == LOW) {
        switch (currentState) {
            case 1: transitionToG2(); currentState = 2; break;
            case 2: transitionToG3(); currentState = 3; break;
            case 3: transitionToG4(); currentState = 4; break;
            case 4: transitionToG3(); currentState = 3; break;
        }
    }

    if (digitalRead(GDS) == LOW) {
        switch (currentState) {
            case 1: transitionToG4(); currentState = 4; break;
            case 2: transitionToG1(); currentState = 1; break;
            case 3: transitionToG2(); currentState = 2; break;
        }
    }

    if (digitalRead(ICRS) == LOW) {
        digitalWrite(COIL1_4, LOW);
        digitalWrite(COIL2_3, LOW);
        while (digitalRead(ICRS) == LOW); // Wait until ICRS goes HIGH
        digitalWrite(COIL1_4, HIGH);
        digitalWrite(COIL2_3, HIGH);
    }
}

void transitionToG1() {
    digitalWrite(SS1R, HIGH);
    digitalWrite(SS2R, HIGH);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, LOW);
    triggerCoils();
    setNeopixelColor(1);
}

void transitionToG2() {
    digitalWrite(SS1R, HIGH);
    digitalWrite(SS2R, LOW);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, LOW);
    triggerCoils();
    setNeopixelColor(2);
}

void transitionToG3() {
    digitalWrite(SS1R, LOW);
    digitalWrite(SS2R, LOW);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, HIGH);
    triggerCoils();
    setNeopixelColor(3);
}

void transitionToG4() {
    digitalWrite(SS1R, LOW);
    digitalWrite(SS2R, HIGH);
    digitalWrite(FCSR, LOW);
    digitalWrite(LUSR, HIGH);
    triggerCoils();
    setNeopixelColor(4);
}

void triggerCoils() {
    digitalWrite(COIL1_4, LOW);
    delay(125);
    digitalWrite(COIL1_4, HIGH);
    digitalWrite(COIL2_3, LOW);
    delay(125);
    digitalWrite(COIL2_3, HIGH);
}

void setNeopixelColor(int index) {
    for (int i = 0; i < NUM_PIXELS; i++) {
        if (i == index - 1) {
            strip.setPixelColor(i, strip.Color(128, 0, 128)); // Purple
        } else {
            strip.setPixelColor(i, strip.Color(0, 0, 0)); // Off
        }
    }
    strip.show();
}

You don't have a case 4 in your downshift switch/case. Do you understand what the code does ?

I also find this very odd

    if (digitalRead(GDS) == LOW)
    {
        switch (currentState)
        {
            case 1:
                transitionToG4();
                currentState = 4;
                break;

Do you really want to go from case 1 to case 4 ?, ie gear 1 to gear 4 when pressing downshift in gear 1 ?

You also need to consider what should happen if either the up or down button is held down. I think that you should detect when one of the buttons becomes pressed rather than when one of the is pressed

@UKHeliBob I dont want to go from gear 4 to gear 1 or gear1 to gear 4.

the button is only able to be pressed once. I am running a sim sequential shifter which is on a spring return to centre. However if its possible is there a way to add a function incase one of the switches decides to malfunction? This is my second arduino project so please excuse my lack of knowledge for basic functions of switches and relays.

How would i add a case for switching from gear 4 down to gear 3? I am still learning code so any help would be greatly appreciated

The section of your code that I posted says "if the user presses the button to shift down and the system is in gear 1 and then move to gear 4"

As I said

@UKHeliBob I understand a some of it however the small things like what to do if the limit switches malfunction and are held low continuously and how to limit the code fro changing from 1st gear to 4th gear.

Is there a way to code the button to be released/opened before the next state change? and limit it so it cant loop from 1st to 4th or the other way round

Yes. Look at the StateChangeDetection example in the IDE

Yes, only code the gear changes that you want to happen. Presumably gears 1 to 2 to 3 to 4 for up changes and 4 to 3 to 2 to 1 for down changes

Look at the code segment that I posted. It is plainly wrong as I have explained. Can you see why it is wrong ?

Here's code that works on your hardware in the wokwi.

Press the up button, gear goes up if possible.

Press the down button, gear goes down if possiuble.

If the gear changes, a function to do the gear change is called.

#include <Adafruit_NeoPixel.h>

#define NEOPIXEL_PIN 11
#define NUM_PIXELS 4

// Pin Definitions
const int SS1R = 2;
const int SS2R = 3;
const int FCSR = 4;
const int LUSR = 5;
const int GUS = 7;
const int GDS = 8;
const int ICRS = 13;
const int COIL1_4 = A2;
const int COIL2_3 = A3;

Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(115200);
  Serial.println("\nGear Shifter\n");

  // Initialize pins
  pinMode(SS1R, OUTPUT);
  pinMode(SS2R, OUTPUT);
  pinMode(FCSR, OUTPUT);
  pinMode(LUSR, OUTPUT);
  pinMode(GUS, INPUT_PULLUP);
  pinMode(GDS, INPUT_PULLUP);
  pinMode(ICRS, INPUT_PULLUP);
  pinMode(COIL1_4, OUTPUT);
  pinMode(COIL2_3, OUTPUT);
  
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  // Start at G1
  transitionToG1();
}

int theGear = 1;    // what gear are we in global

void loop() {
    static int currentState = 1;

    if (digitalRead(GUS) == LOW) {
      theGear++; if (theGear >= 4) theGear = 4;
    }

    if (digitalRead(GDS) == LOW) {
      theGear--; if (theGear <= 0) theGear = 1;
    }

    static int currentGear = -1;    // no, it does not!

// new gear?
    if (theGear != currentGear) {
      currentGear = theGear;

      switch (theGear) {
      case 1 :
        transitionToG1();
        break;
      case 2 :
        transitionToG2();
        break;
      case 3 :
        transitionToG3();
        break;
      case 4 :
        transitionToG4();
        break;

      default :
        Serial.println("logic error");
        for (; ; );
        break;
      }
    }

    if (digitalRead(ICRS) == LOW) {
        digitalWrite(COIL1_4, LOW);
        digitalWrite(COIL2_3, LOW);
        while (digitalRead(ICRS) == LOW); // Wait until ICRS goes HIGH
        digitalWrite(COIL1_4, HIGH);
        digitalWrite(COIL2_3, HIGH);
    }
}

void transitionToG1() {
    digitalWrite(SS1R, HIGH);
    digitalWrite(SS2R, HIGH);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, LOW);
    triggerCoils();
    setNeopixelColor(1);
}

void transitionToG2() {
    digitalWrite(SS1R, HIGH);
    digitalWrite(SS2R, LOW);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, LOW);
    triggerCoils();
    setNeopixelColor(2);
}

void transitionToG3() {
    digitalWrite(SS1R, LOW);
    digitalWrite(SS2R, LOW);
    digitalWrite(FCSR, HIGH);
    digitalWrite(LUSR, HIGH);
    triggerCoils();
    setNeopixelColor(3);
}

void transitionToG4() {
    digitalWrite(SS1R, LOW);
    digitalWrite(SS2R, HIGH);
    digitalWrite(FCSR, LOW);
    digitalWrite(LUSR, HIGH);
    triggerCoils();
    setNeopixelColor(4);
}

void triggerCoils() {
    digitalWrite(COIL1_4, LOW);
    delay(125);
    digitalWrite(COIL1_4, HIGH);
    digitalWrite(COIL2_3, LOW);
    delay(125);
    digitalWrite(COIL2_3, HIGH);
}

void setNeopixelColor(int index) {
    for (int i = 0; i < NUM_PIXELS; i++) {
        if (i == index - 1) {
            strip.setPixelColor(i, strip.Color(128, 0, 128)); // Purple
        } else {
            strip.setPixelColor(i, strip.Color(0, 0, 0)); // Off
        }
    }
    strip.show();
}

I am surprised that chatGPT got anywhere, it is tempting to see if a more detailed description and constraints would get closer.

I came to as little understanding of the last code you posted as possible… I think the four functions might be done differently, but it is at the point where it is clear if a bit literal.

I left the problems of holding a button down or pressing both at the same time. They may not be problems, solving them would take you across some interesting learning which you will want to do one day. TBH here I would just use the ezButton library, a simple button handler that gets my highest praise for such libraries, "it doesn't suck".

a7

1 Like

In order to reduce the wear and tear on your transmission, do you need to engage the next gear before releasing the current gear?

StArt by just really reading my loop() function. Line by line, stop if something doesn't make sense.

Usually that's a good way to get right into what a sketch is doing and how. A glance at setup() will give you a sense of what the wiring must be. A good loop ends up being like an outline that hides all the details of how things get down on a lower level - setting ouputs and making pulses and stuff.

I left most of your (chatGPT's?) code untouched. if you read the older versions with the same care you would see quite soon why you couldn't shift very well, and perhaps see the
point of some of the questions that were more rhetorical in nature.

The only even mildly complicated thing I put in there was to notice and only do the actual shifting if the gear was successfully changed by the input buttons.

a7

1 Like