Need help with 2 buttons on one Pin

I have been working on an Automatic Transmission Shifter for a while now, and I need some help.

Here is my post that started the project > http://arduino.cc/forum/index.php/topic,84997.0.html

Basically, I have 2 switches already installed in my steering wheel that I want to control the gears with. One has an 820 ohm resistor, and the other has a 2.7k ohm resistor. I’m hoping to use these factory installed switches, because there are a limited number of wires I can use that run thru the clockspring (which allows the steering wheel to turn without tangling up wires). If I can use just one wire to one pin on the arduino, then I will still have one wire to supply +5v.

I’m new to this, so I was wondering if anyone can help me rewrite this code, or a new one? I don’t really understand the current code I’m using, just enough that I have made some minor changes.

Here is the current code a member here helped me with (I believe his name was TechOne?). It uses normal momentary push button switches with pull-up resistors, and controls a 7-segment display and two relays.

/*
Gear:    Solenoid A:   B:
 1st               1   1
 2nd               0   1
 3rd               0   0
 4th               1   0
 
 
 How it works :
 
 1. Initialize the gear at 3 (incase power is interupted to the controller, this
 prevents the transmission from going back to 1st gear at high speeds).
 2. Press Upshift Button to increase the gears.
 3. Press Downshift Button to decrease the gears.
 
 Pinout:
 pin 12 = f, pin 11 = g, pin 10 = e, pin 9 = d, pin 8 = c, pin 7 = b, 
 pin 6 = a, pin 5 = selenoid B, pin 4 = selenoid A, upshift button= pin 2, 
 downshift button= pin 3
 
7-segment display

 1= b,c
 2= a,b,d,e,g
 3= a,b,c,d,g
 4= b,c,f,g
 
 */

// Arduino Digital pins
const byte outpin[9] = {4,5,6,7,8,9,10,11,12};
const byte inpin[2] = {2,3};
// Selenoid and Display array pattern
boolean gearone[9] = {1,1,0,1,1,0,0,0,0};
boolean geartwo[9] = {0,1,1,1,0,1,1,1,0};
boolean gearthree[9] = {0,0,1,1,1,1,0,1,0};
boolean gearfour[9] = {1,0,0,1,1,0,0,1,1};

byte gear;

int upshift=1;
int downshift=1;
int oldupshift=1;
int olddownshift=1;

boolean state=0;

void setup()
{
  // initializes the digital pins
  for (int i=0; i<9; i++)
  {
    pinMode(outpin[i],OUTPUT);
  }
  pinMode(inpin[0],INPUT);
  pinMode(inpin[1],INPUT);
  // Put in gear three for safety
  gear=3;

  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearthree[i]);
  } 
}

void loop()
{
  readswitch(); 
  while(state==0)
  {
    readswitch();     
  }
  // a switch has been pressed
  // Check for the upshift
  if ((upshift==0) && (state==1))
  {  
    gear++;
    if ((gear>=1) && (gear<=4))
    {
      switch(gear)
      {
      case 1: 
        selectone();
        break;
      case 2: 
        selecttwo();
        break;
      case 3: 
        selectthree();
        break;
      case 4: 
        selectfour();
        break;
      }
    }
    else gear=4;
  }
  // check for the downshift  
  if ((downshift==0) && (state==1))
  {  
    gear--;
    if ((gear>=1) && (gear<=4))
    {
      switch(gear)
      {
      case 1: 
        selectone();
        break;
      case 2: 
        selecttwo();
        break;
      case 3: 
        selectthree();
        break;
      case 4: 
        selectfour();
        break;
      }
    }
    else gear=1;
  }   

}

void selectone()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearone[i]);
  }
  state=0;  
}

void selecttwo()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],geartwo[i]);
  }
  state=0;  
}

void selectthree()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearthree[i]);
  }
  state=0;  
}

void selectfour()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearfour[i]);
  }
  state=0;  
}

/* 
 The switch is configure with a pull-up resistor,
 so it is always a 1, when pressed, it grounds and reads as a 0. 
 */
void readswitch()
{
  upshift=digitalRead(inpin[0]);
  // check upshift transition
  if ((upshift==0) && (oldupshift==1))
  {
    state=1;
    delay(200);
  }  
  oldupshift=upshift;
  downshift=digitalRead(inpin[1]);
  // check downshift transition
  if ((downshift==0) && (olddownshift==1))
  {
    state=1;
    delay(200);
  }  
  olddownshift=downshift;  
}

Thank you for any help!

Take a look @ this post on Arduino Forum on how to read multiple switches using analogRead() on a single Analog Pin instead of Digital Pin.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1226896251

The post uses equal 1k resistors with switches but there's no reason why your existing switch resistors won't work -> just the values returned by analogRead() will change.

More info on this technique from this application note from MiroChip

http://ww1.microchip.com/downloads/en/appnotes/00234a.pdf

This question though should be on the electronics or the projects board :-)

I have been working on an Automatic Transmission Shifter for a while now, and I need some help.

Here is my post that started the project > http://arduino.cc/forum/index.php/topic,84997.0.html

Basically, I have 2 switches already installed in my steering wheel that I want to control the gears with. One has an 820 ohm resistor, and the other has a 2.7k ohm resistor. I’m hoping to use these factory installed switches, because there are a limited number of wires I can use that run thru the clockspring (which allows the steering wheel to turn without tangling up wires). If I can use just one wire to one pin on the arduino, then I will still have one wire to supply +5v.

I’m new to this, so I was wondering if anyone can help me rewrite this code, or a new one? I don’t really understand the current code I’m using, just enough that I have made some minor changes.

Here is the current code a member here helped me with (I believe his name was TechOne?). It uses normal momentary push button switches with pull-up resistors, and controls a 7-segment display and two relays.

Not sure if it would need debouncing?

/*
Gear:    Solenoid A:   B:
 1st               1   1
 2nd               0   1
 3rd               0   0
 4th               1   0
 
 
 How it works :
 
 1. Initialize the gear at 3 (incase power is interupted to the controller, this
 prevents the transmission from going back to 1st gear at high speeds).
 2. Press Upshift Button to increase the gears.
 3. Press Downshift Button to decrease the gears.
 
 Pinout:
 pin 12 = f, pin 11 = g, pin 10 = e, pin 9 = d, pin 8 = c, pin 7 = b, 
 pin 6 = a, pin 5 = selenoid B, pin 4 = selenoid A, upshift button= pin 2, 
 downshift button= pin 3
 
7-segment display

 1= b,c
 2= a,b,d,e,g
 3= a,b,c,d,g
 4= b,c,f,g
 
 */

// Arduino Digital pins
const byte outpin[9] = {4,5,6,7,8,9,10,11,12};
const byte inpin[2] = {2,3};
// Selenoid and Display array pattern
boolean gearone[9] = {1,1,0,1,1,0,0,0,0};
boolean geartwo[9] = {0,1,1,1,0,1,1,1,0};
boolean gearthree[9] = {0,0,1,1,1,1,0,1,0};
boolean gearfour[9] = {1,0,0,1,1,0,0,1,1};

byte gear;

int upshift=1;
int downshift=1;
int oldupshift=1;
int olddownshift=1;

boolean state=0;

void setup()
{
  // initializes the digital pins
  for (int i=0; i<9; i++)
  {
    pinMode(outpin[i],OUTPUT);
  }
  pinMode(inpin[0],INPUT);
  pinMode(inpin[1],INPUT);
  // Put in gear three for safety
  gear=3;

  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearthree[i]);
  } 
}

void loop()
{
  readswitch(); 
  while(state==0)
  {
    readswitch();     
  }
  // a switch has been pressed
  // Check for the upshift
  if ((upshift==0) && (state==1))
  {  
    gear++;
    if ((gear>=1) && (gear<=4))
    {
      switch(gear)
      {
      case 1: 
        selectone();
        break;
      case 2: 
        selecttwo();
        break;
      case 3: 
        selectthree();
        break;
      case 4: 
        selectfour();
        break;
      }
    }
    else gear=4;
  }
  // check for the downshift  
  if ((downshift==0) && (state==1))
  {  
    gear--;
    if ((gear>=1) && (gear<=4))
    {
      switch(gear)
      {
      case 1: 
        selectone();
        break;
      case 2: 
        selecttwo();
        break;
      case 3: 
        selectthree();
        break;
      case 4: 
        selectfour();
        break;
      }
    }
    else gear=1;
  }   

}

void selectone()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearone[i]);
  }
  state=0;  
}

void selecttwo()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],geartwo[i]);
  }
  state=0;  
}

void selectthree()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearthree[i]);
  }
  state=0;  
}

void selectfour()
{
  for (int i=0;i<9;i++)
  {
    digitalWrite(outpin[i],gearfour[i]);
  }
  state=0;  
}

/* 
 The switch is configure with a pull-up resistor,
 so it is always a 1, when pressed, it grounds and reads as a 0. 
 */
void readswitch()
{
  upshift=digitalRead(inpin[0]);
  // check upshift transition
  if ((upshift==0) && (oldupshift==1))
  {
    state=1;
    delay(200);
  }  
  oldupshift=upshift;
  downshift=digitalRead(inpin[1]);
  // check downshift transition
  if ((downshift==0) && (olddownshift==1))
  {
    state=1;
    delay(200);
  }  
  olddownshift=downshift;  
}

Thank you for any help!

Did you count the ground wire too? That will be 3 wires.

Not a really decent way to ask the same question on two separate sub-forum, is it?

http://arduino.cc/forum/index.php/board,4.0.html

Hi,

Is there a specific error or issue you’re seeing? Looking at the sketch there’s a lot of areas where it could be streamlined, but it’s not bad. It’s very hard to help you debug it though without knowing what you’re expecting it to do and, importantly, what it’s actually doing wrong.

If you want to use the resistors with the buttons to identify which button was depressed, you’ll need to use an analogRead() which will return a value depending on the voltage at the Arduino pin, rather than the digitalRead you’re presently using which is seeing whether you have a button pressed on either of two input pins.
More detail: http://arduino.cc/en/Reference/analogRead

What you’re implementing is a simple resistor ladder - http://en.wikipedia.org/wiki/Resistor_ladder

To work out what values to test for, create a little sketch that just outputs an analogRead() of the pin you’ve hooked them up to out to the serial monitor. Then run it and press each button (and both) in turn. You’ll use one less wire, but remember it will need to be hooked up to an analog pin.

Unless I’m mistaken, it appears to me you could have an upshift and downshift at the same time with this sketch. Not sure what commercial boxes do in that special case as I’ve not driven a flappy-paddle shifter but your sketch would shift up then down if both buttons are depressed.

The code does have several areas that could be simplified - I like the idea for example of taking your gear selection arrays, and rolling them into a single 2D array, like this

boolean shiftPattern [4] [9] = {
   {1,1,0,1,1,0,0,0,0},
   {0,1,1,1,0,1,1,1,0},
   {0,0,1,1,1,1,0,1,0},
   {1,0,0,1,1,0,0,1,1}
};

Then rather than having lots of functions for setting your triggers, you could have one something like this

void selectThisGear(int gearToSelect) {
  for (int i=0;i<9;i++)  digitalWrite(outpin[i],shiftPattern[gearToSelect-1] [i]);
  state=0;  
}

And by calling selectThisGear(4) it would load up all the right pin values for 4th gear…unless I’ve done something silly :slight_smile:

And yes, debouncing will be required too.

This looks like a very interesting project!
Geoff

I can ground from just about anywhere metal on the vehicle, including inside the steering wheel.

Liudr - Look at the figure on top right corner in Microchip's pdf file.... 2 wires... you can always ground through a resistor near the Arduino itself ... you don't have to have a separate ground wire :-)

invintive - as long as you're powering your circuit through the car's electrical system (which is what you're likely doing) grounding through any metal chassis part would be fine. However, if your power supply source for arduino is different (eg. some battery - unlikely), then you shouldn't do this.

Nothing is really wrong with the code (other than debounce), just looking to change it to use 2 buttons on one analog pin. One with an 820 ohm resistor and one with 2.7k ohm resistor (switches that already exist in the cars steering wheel). I'm not very good at code, and this was written for me by someone else (TechOne ?). I don't understand it very well. Just enough that I have managed to change some simple things.

How would I integrate your suggested code simplifications?

Thank You!

srinathdevelopment- Yes, it is powered by the vehicle.

srinathdevelopment:
Liudr - Look at the figure on top right corner in Microchip’s pdf file… 2 wires… you can always ground through a resistor near the Arduino itself … you don’t have to have a separate ground wire :slight_smile:

There was a diagram the OP posted that’s missing the gnd. I didn’t mean it was your diagram. Where’s OP’s diagram? srinathdevelopment, your description makes sense with the vehicle grounding but will it work for all vehicles? I heard of some vehicle has 12V (right?) not gnd on the metal.

OP,BE A DECENT PERSON AND LOCK THAT OTHER THREAD YOU HAVE ALSO BEEN RECEIVING HELP FROM! YOU ARE CROSS-POSTING! :0

http://arduino.cc/forum/index.php/topic,99985.msg

Liudir - in general, i'd completely agree with you that caution may be better unless the electrical schematics of the car are available and very clear on line voltages..... in this specific case of course since a signal line us going back to arduino, the necessity to ground with chassis doesn't arise.... however as you rightly point out, it would be good to check out whether line voltages are within arduino specs. Also I've always wondered what voltage fluctuations happen when for eg. you start the engine... though i haven't researched it - but that's getting into a very different & unrelated topic on power line protection / conditioning

srinathdevelopment: Liudir - in general, i'd completely agree with you that caution may be better unless the electrical schematics of the car are available and very clear on line voltages..... in this specific case of course since a signal line us going back to arduino, the necessity to ground with chassis doesn't arise.... however as you rightly point out, it would be good to check out whether line voltages are within arduino specs. Also I've always wondered what voltage fluctuations happen when for eg. you start the engine... though i haven't researched it - but that's getting into a very different & unrelated topic on power line protection / conditioning

I do remember my arduino restarts when I start my car (a GPS logger project and a sonic parking sensor project). Maybe some isolation are necessary, such as large caps to smooth out that effects or have arduino run on alternative powers like it already knows when to switch between USB and power jack. If that can be made between power jack-car battery and power jack-small battery or just a super cap, that might work.

Sorry, I have locked the other post. :disappointed_relieved:

Being an automotive technician, I'm not concerned about understanding the vehicles power system. Your arduino probably restarted when you started the vehicle because the starter-motor draws a significant amount of amps (upwards of 800 amps I believe). In fact, during vehicle cranking most accessories turn off for that very reason (i.e. stereo). Once started power can fluctuate from, but not limited to, 8v+ to 18v+. However it typically stays around 12-14v+. These days it is very rare to see a car without a grounded chassis.

For the most part, it would work correctly how it is now if I new coding well enough to integrate debouncing into my current code. The current code was written for me, and I would like to understand it better, but I'm having trouble. I don't know if there is an easier way to write it or not.

The main reason I would like to have the switches connected to one analog pin is so that I can have them located on the steering wheel.

I understand the concept of using multiple buttons on one pin, but I don't know how to integrate in my code?

invintive: Sorry, I have locked the other post. :disappointed_relieved:

No sweat. As long as you respect rules of the forum, people are pretty easy on new comers. If you read this thread instead, you will know why some new comers don't get welcomes too much. Respect is two way street :)

http://arduino.cc/forum/index.php/topic,99313.msg

Being an automotive technician, I'm not concerned about understanding the vehicles power system. Your arduino probably restarted when you started the vehicle because the starter-motor draws a significant amount of amps (upwards of 800 amps I believe). In fact, during vehicle cranking most accessories turn off for that very reason (i.e. stereo). Once started power can fluctuate from, but not limited to, 8v+ to 18v+. However it typically stays around 12-14v+. These days it is very rare to see a car without a grounded chassis.

You should share a bit more often! I bought a new battery with cold-crank-amps of XXX. I think with your explanation I can understand what it means now. So while cranking, do accessories turn off because the battery voltage drops too much or is there a circuit to do that to concentrate power to starting the car?

For the most part, it would work correctly how it is now if I new coding well enough to integrate debouncing into my current code. The current code was written for me, and I would like to understand it better, but I'm having trouble. I don't know if there is an easier way to write it or not.

The main reason I would like to have the switches connected to one analog pin is so that I can have them located on the steering wheel.

I understand the concept of using multiple buttons on one pin, but I don't know how to integrate in my code?

Fair enough. That part we can help step by step.

You should share a bit more often! I bought a new battery with cold-crank-amps of XXX. I think with your explanation I can understand what it means now. So while cranking, do accessories turn off because the battery voltage drops too much or is there a circuit to do that to concentrate power to starting the car?

CCA are the amount of current a 12v lead-acid battery can deliver for 30 seconds at 0°F while maintaining at least 7.2v+. As far as accessories go, it depends on the manufacturer. Some accessories simply wont get enough power, however, most vehicles use the ingnition switch to kill the accessories when in the start position.

Feel free to ask me questions!

Thank you!

Great! Thanks for the answers. If the ignition key kills the accessories (assuming that means disconnecting from battery), then all you need is a diode and a super capacitor between the car ground and the cigarette lighter +12. When the accessories are on, the super cap is charged to the battery voltage (+12V). When the accessories are off, then the super cap discharges to keep arduino powered, while the diode prevents the super cap from feeding power to other parts of the accessories. I think this is the right circuit. Hopefully others can check the diagram :sweat_smile:

car_circuit.png

cool!

to get back to your original question… something like this should work… Note that given your switch resistor values, when you press 2 switches together in this circuit config, you should end up with a voltage of about 3V which is very close to what you’ll get pressing the switch with the 822 Ohm resistor.

analogRead will map in this case 0V to 5V into the range of integers 0 to 1023 - you need to experiment a bit to find the right ranges in the if statements which i’ve added to check whether upshift or downshift has been pressed… due to tolerences in resistors.If you’re using some R3 resistor other than 1K Ohm, just do the voltage divider math and change the ranges

PS: You need to check the rest of the code for other places the input pin gets referenced, set the pin A2 to input etc… i’ve just shown how to use analogRead & if statements in the switch reading function here

Arduino +5V ------------------------------------
                                |              |
                                |              |
                                R1             R2
                               822            2700  
                             upshift        downshift
                                |              |
                                |              |
                                S1             S2
                                |              |
                                |              |
Arduino Pin ------------------------------------
 Analog 2            |
                     |
                     R3
                    1000
                     |
                    GND
void readswitch()
{
  int shift=analogRead(A2);

  //if R1 is pressed, reading should be ~2.7V ~560
  //if R2 is pressed, reading should be ~1.3V ~280

  if(shift > 500 && shift < 600)
	upshift = 1;
  else
        upshift = 0;

  if ((upshift==0) && (oldupshift==1))
  {
    state=1;
    delay(200);
  }  
  oldupshift=upshift;
 
  if(shift > 350 && shift < 450)
	downshift = 1;
  else
        downshift = 0;

  // check downshift transition
  if ((downshift==0) && (olddownshift==1))
  {
    state=1;
    delay(200);
  }  
   olddownshift=downshift;  
}

liudr: Not a really decent way to ask the same question on two separate sub-forum, is it?

Moderator edit: Threads merged. (Nick Gammon)