2 button servo controll

Hi

So i have been fiddling with a code.

Im trying to set up paddle shifter for an old automatic BMW. so i only need a single actuator/ servo to move in 7 different location. (I’m trying to have the servo positions “hardcoded” instead of just giving every movement the same degree)

The oem safety setup on the car is intact. And I’m using a servo saver. So if the servo trying to get to reverse or park in speed, the servo itself wont self destruct.

I need som advice on how to get my code working properly. I off to work and dont have an arduino with me. But would like to fiddle with the code and maby get it to work before im home again.

I have borrowed another servo code. Mine probably has a lot of flaws. Would be nice if one of you skilled guys could help me out a bit. Tell me if waht im doing is wrong.

#include <servo.h> 

Servo TransmissionServo;  

int pos = 0;     
const int 2ndGear = 180;
const int 3rdGear = 150;
const int 4thGear = 120:
const int Drive   = 90:
const int Neutral = 60:
const int Reverse = 30:
const int Park    = 0;


const int leftPin = 3;
const int rightPin = 2;

const int led1Pin = 6; // indicator
const int led2Pin = 5; // indicator

const int outputPin = 9; 

int ShiftDOWN = 0;
int ShiftUP = 0;

void setup() 
{ 
TransmissionServo.attach(outputPin);  
pinMode(leftPin, INPUT);
pinMode(rightPin, INPUT);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
} 




void loop() 
{ 
ShiftDOWN = digitalRead(leftPin);
ShiftUP = digitalRead(rightPin);
 
 if(ShiftDOWN){
 if(pos < Park) pos += 3;
TransmissionServo.write(Reverse);              
digitalWrite(led1Pin,HIGH);
 }
 else
digitalWrite(led1Pin,LOW);

 if(ShiftDOWN){
 if(pos < Reverse) pos += 3;
TransmissionServo.write(Neutral);             
digitalWrite(led1Pin,HIGH);
 }
 else
digitalWrite(led1Pin,LOW);

 if(ShiftDOWN){
 if(pos < Neutral) pos += 3;
TransmissionServo.write(Drive);             
digitalWrite(led1Pin,HIGH);
 }
 else
digitalWrite(led1Pin,LOW);

 if(ShiftDOWN){
 if(pos < Drive) pos += 3;
TransmissionServo.write(4thGear);              
digitalWrite(led1Pin,HIGH);
 }
 else
digitalWrite(led1Pin,LOW);

 if(ShiftDOWN){
 if(pos < 4thGear) pos += 3;
TransmissionServo.write(3rdGear);              
digitalWrite(led1Pin,HIGH);
 }
 else
digitalWrite(led1Pin,LOW);

 if(ShiftDOWN){
 if(pos < 3rdGear) pos += 3;
TransmissionServo.write(2ndGear);              
digitalWrite(led1Pin,HIGH);
 }
 else
digitalWrite(led1Pin,LOW);



 if(ShiftUP){
 if(pos > Reverse) pos -= 3;
TransmissionServo.write(Park);             
digitalWrite(led2Pin,HIGH);
 }
 else
digitalWrite(led2Pin,LOW);


 if(ShiftUP){
 if(pos > Neutral) pos -= 3;
TransmissionServo.write(Reverse);
digitalWrite(led2Pin,HIGH);             
 }
 else
digitalWrite(led2Pin,LOW);


 if(ShiftUP){
 if(pos > Drive) pos -= 3;
TransmissionServo.write(Neutral);              
digitalWrite(led2Pin,HIGH);
 }
 else
digitalWrite(led2Pin,LOW);


 if(ShiftUP){
 if(pos > 4thGear) pos -= 3;
TransmissionServo.write(Drive);              
digitalWrite(led2Pin,HIGH);
 }
 else
digitalWrite(led2Pin,LOW);


 if(ShiftUP){
 if(pos > 3rdGear) pos -= 3;
TransmissionServo.write(4thGear);              
digitalWrite(led2Pin,HIGH);
 }
 else
digitalWrite(led2Pin,LOW);


 if(ShiftUP){
 if(pos > 2ndGear) pos -= 3;
TransmissionServo.write(3rdGear);              
digitalWrite(led2Pin,HIGH);
 }
 else
digitalWrite(led2Pin,LOW);


delay(100);                      
}

The basic idea looks OK but it could be greatly simplified up by putting the servo positions in an array and using the up/down buttons to change the array index appropriately.

However you have a big problem in the way that you are reading the inputs. Think what will happen if one of the buttons is held down. You need to move the servo when one of the buttons BECOMES pressed not when it IS pressed otherwise things will happen very fast. Look at the StateChangeDetection example to see how to do it.

Ok. gonna give it a try. I havent tried to setup a servo like this before.

and you mean i should have a code so that i actually have to press and release for every gear change right?

Thanx for the quick reply

#include <servo.h> 

Servo TransmissionServo;  

// int pos = 0; // In this case, I just don't like the variable name. :)
// const int 2ndGear = 180; // Makes logic needlessly complicated. set up an array instead.
// const int 3rdGear = 150;
// const int 4thGear = 120:
// const int Drive   = 90:
// const int Neutral = 60:
// const int Reverse = 30:
// const int Park    = 0;
int currentGear=6; // rem assume that we start in park.
const int gearOut = {180, 150, 120, 90, 60, 30, 0}; // 2nd, 3rd, 4th, D, N, R, P

const int leftPin = 3;
const int rightPin = 2;

const int led1Pin = 6; // indicator
const int led2Pin = 5; // indicator

const int outputPin = 9; 

int ShiftDOWN = 0;
int ShiftUP = 0;

unsigned long buttonDown; // because delay() loops are stupid in control systems.
unsigned long currentMillis;
unsigned long lightOn;
bool releaseWait = false; // Flag to prevent multiple shifts by holding the paddle
const int debounce = 10; // because debouncing the circuit is important, too.
const int lightTime=500 // 500ms display of LED for shift direction.

void setup() 
{ 
TransmissionServo.attach(outputPin);  
pinMode(leftPin, INPUT);
pinMode(rightPin, INPUT);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
} 




void loop() 
{ 
ShiftDOWN = digitalRead(leftPin);
ShiftUP = digitalRead(rightPin);
currentMillis = millis();

if (ShiftDOWN || ShiftUP) {
 if (buttonDown == 0) {
  buttonDown = millis();
 }
 else {
  if ((currentMillis - buttonDown > debounce) && !releaseWait) {
   releaseWait = true;
   if (ShiftDOWN) {
    if (currentGear > 0) {
     currentGear--;
     lightOn = millis();
     digitalWrite(led1Pin, HIGH);
    }
   }
   if (ShiftUP) {
    if (currentGear < 6) {
     currentGear++;
     lightOn = millis();
     digitalWrite(led2Pin, HIGH);
    }
   }
   TransmissionServo.write(gearOut[currentGear]);
   buttonDown=0; // reset timer
  }
 }
 if ((lightOn > 0) && (currentMillis - lightOn > lightTime) {
  digitalWrite(led1Pin, LOW); // set both lights off.
  digitalWrite(led2Pin, LOW); // Or you could keep track of each one's on time separately.
  lightOn = 0;
 }
 else {
  if (releaseWait) {
   releaseWait = false;
  }
 }
}

Potential issues which may or may not be a problem.

It is possible to hold down BOTH paddles, which will result in the gear being shifted both down and up. If this is the case and the car is in 2nd, it will shift to 3rd. Other values will result in a null operation (Gear goes up, gear goes down, servo doesn’t move, but both LEDs light.)

This will allow you to double shift by holding the paddle for a minimum of 10ms, releasing it then hitting it again for another 10ms, but hopefully prevent a double shift because the buttons bounce.

I also left the lights on for a bit longer than your 100ms, but without the delay loop, so you can actually shift faster than that if you want/need.

I wrote this off the top of my head, so it may not be bug-free. I may have missed a bracket somewhere…

Heh. Ninja'd.

The code I provided does wait for the button to be released after the debounce, and uses the array for the gear as well. (Though it probably could also just be worked out by math if it really is intervals of 30.)

For the time shift, the 100ms delay loop that you had would be the saving grace against holding down the paddle, but that's still 10 shifts per second while holding down... (In retrospect, my debounce time of 10ms is probably too short, but at lest it's easy to adjust, and is independant of the time that the indicators are on.

and you mean i should have a code so that i actually have to press and release for every gear change right?

Yes, or arrange it so that a long press is detected and the gear shifts again when the button is held down.

SupraGuy: Heh. Ninja'd.

The code I provided does wait for the button to be released after the debounce, and uses the array for the gear as well. (Though it probably could also just be worked out by math if it really is intervals of 30.)

Actually I have no idea what the intervals is going to be. But i believe it will be some sort of mismatch between every shift. One can be 35 and another 25. Its a powerfull engine. So Im gonna do massive testing before i bolt it on.

[/quote] For the time shift, the 100ms delay loop that you had would be the saving grace against holding down the paddle, but that's still 10 shifts per second while holding down... (In retrospect, my debounce time of 10ms is probably too short, but at lest it's easy to adjust, and is independant of the time that the indicators are on. [/quote]

Ill have to test what i like and what makes sense. actually, after i get this working. Ill try to set up a single number led with 14 pins. And code it so every gear gets its own letter. The reason for this is that the oem instrument shows things opposite than whats normal at shift paddling. Also both paddles can work together as its own signal?

Ill have to say great job guys. Im a dedicated hardware and hands on guy. And always have trouble with things like these. With this speed im able to put it in my car in record time.

UKHeliBob:
Yes, or arrange it so that a long press is detected and the gear shifts again when the button is held down.

Im not shure what you mean?

Wracul: Im not shure what you mean?

What I had in mind was if you press and release one of the buttons then one shift would take place but if the button was held down for a period of time then a series of shifts would take place at intervals.

I see. I actually dont want that. But maybe setting a long double button press would be interesting. Make it go in park?.

Engine power has nothing to do with shifting...

Some suggestions: you should get something that gives you access to the vehicle speed sensor, and not allow shifting into or out of reverse if the vehicle speed is non-zero.

For the display, you can use a 7 segment LED array and keep another table of values whose binary value corresponds to the digits you want lit up. 2, 3, 4, d, n, P will work with 7 segment, and not need too many I/O pins. The same "currentGear" variable could be used as an index to this array.

If it were my car, I'd want quick response, probably not more than 50ms before the car started to react to the paddle shift. I would NOT want it to do more than one shift, no matter how long I held the paddle for. This is the way that I coded my example. Once the shift happens, it must be released in order to begin a new shift process.

SupraGuy: Engine power has nothing to do with shifting...

Some suggestions: you should get something that gives you access to the vehicle speed sensor, and not allow shifting into or out of reverse if the vehicle speed is non-zero.

For the display, you can use a 7 segment LED array and keep another table of values whose binary value corresponds to the digits you want lit up. 2, 3, 4, d, n, P will work with 7 segment, and not need too many I/O pins. The same "currentGear" variable could be used as an index to this array.

If it were my car, I'd want quick response, probably not more than 50ms before the car started to react to the paddle shift. I would NOT want it to do more than one shift, no matter how long I held the paddle for. This is the way that I coded my example. Once the shift happens, it must be released in order to begin a new shift process.

Maybe tapping into the rear diff hall sensor for anti R and P in speed?

I actually was looking at the 14 segment lights. This due to the nicer output of letters. I'll be better off not messing with that part of the code at this point. I do already have the oem mirrored instrument, so its not a must have.

I totally agree on the how to shift solution. I dont want to mess this up. This was actually what i meant about power of the car. I understand that the power has nothing to do with the shifting. But it has something to do with safety, and how the car is driven.

I was actually looking at linear actuators instead of servos. But im not very familiar with them. If i found a fast enough, small and strong linear actuator that fitted my needs i could probably drop the servo servo with the servo saver and have a bit more profesional setup. Off course this would make the tap into speed sensor very important.