Motorcycle Current Gear Indicator

Hi!
First of all, I apologize for my English, I'm from Portugal.
I'm a newbie on Arduino, and I am trying to build a Motorcycle Current Gear Indicator with a 7-segment display, 3 sensors (pedal +; pedal -; Neutral).
I've written this code but my arduino hasn't arrived yet, could you see if the code makes sense for the purpose?

Thank you all

/*
MOTORCYCLE SHIFT INDICATOR 
by Filipe Dias
Pins:
D2 - 7 (A)
D3 - 6 (B)
D4 - 4 (C)
D5 - 2 (D)
D6 - 1 (E)
D7 - 9 (F)
D8 - 10 (G)
D9 - 5 (DP)
D10 - Neutral Switch
D11 - Sensor +
D12 - Sensor -
*/
void setup() {  
  // Define Pins  
  pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  
  // All leds test
  digitalWrite(2, 1);
  digitalWrite(3, 1);
  digitalWrite(4, 1);
  digitalWrite(5, 1);
  digitalWrite(6, 1);
  digitalWrite(7, 1);
  digitalWrite(8, 1);
  delay(1000);
  digitalWrite(2, 0);
  digitalWrite(3, 0);
  digitalWrite(4, 0);
  digitalWrite(5, 0);
  digitalWrite(6, 0);
  digitalWrite(7, 0);
  digitalWrite(8, 0);
  delay(1000);
}

void loop(){
  byte mudanca=7;
  
  // Display waiting for neutral, all leds off
  while (mudanca=7){
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    if (digitalRead(10)==LOW){
    byte mudanca = 0;
    delay(100);
    break;
    } 
  }
  
  // Neutral position
  while (byte mudanca=0){
    if(digitalRead(11)==LOW){
      byte mudanca = 2;
      delay(100);
      break;
    }
    if(digitalRead(12)==LOW){
      byte mudanca = 1;
      delay(100);
      break;
    }
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH); 
  }
  
    // 1st Gear
    while (byte mudanca=1){
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW); 
    if(digitalRead(10)==LOW){
      byte mudanca = 0;
      delay(100);
      break;
    }
  }
  
    // 2nd Gear
    while (byte mudanca=2){
    if(digitalRead(11)==LOW){
      byte mudanca = 3;
      delay(100);
      break;
    }
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH); 
    if(digitalRead(10)==LOW){
      byte mudanca = 0;
      delay(100);
      break;
    }
  }
  
    // 3rd Gear
    while (byte mudanca=3){
    if(digitalRead(11)==LOW){
      byte mudanca = 4;
      delay(100);
      break;
    }
    if(digitalRead(12)==LOW){
      byte mudanca = 2;
      delay(100);
      break;
    }
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH); 
  }
  
    // 4th Gear
    while (byte mudanca=4){
    if(digitalRead(11)==LOW){
      byte mudanca = 5;
      delay(100);
      break;
    }
    if(digitalRead(12)==LOW){
      byte mudanca = 3;
      delay(100);
      break;
    }
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH); 
    }
  
    // 5th Gear
    while (byte mudanca=5){
    if(digitalRead(11)==LOW){
      byte mudanca = 6;
      delay(100);
      break;
    }
    if(digitalRead(12)==LOW){
      byte mudanca = 4;
      delay(100);
      break;
    }
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
  }
  
    // 6th Gear
    while (byte mudanca=6){
    if(digitalRead(12)==LOW){
      byte mudanca = 5;
      delay(100);
      break;
    }
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, HIGH); 
  }
}

When doing checking make sure to use == and not =. Also don't redefine your variable in the while expression, while(byte mudanca = 1) is probably gonna cause an infinite loop. If is simpler and easier to read if you just do if statements and not while loops. Also just handle shifting up and shifting down in one location. Hope this helps.

byte mudanca = 7;
void setup() {  
  // Define Pins  
  pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  
  // All leds test
  digitalWrite(2, 1);
  digitalWrite(3, 1);
  digitalWrite(4, 1);
  digitalWrite(5, 1);
  digitalWrite(6, 1);
  digitalWrite(7, 1);
  digitalWrite(8, 1);
  delay(1000);
  digitalWrite(2, 0);
  digitalWrite(3, 0);
  digitalWrite(4, 0);
  digitalWrite(5, 0);
  digitalWrite(6, 0);
  digitalWrite(7, 0);
  digitalWrite(8, 0);
  delay(1000);
}
void loop(){
	if(mudanca == 7){
		 //set LED values
		 if(digitalRead(10)==LOW){
			  mudanca=0;
		 }
	}else{
		 if(digitalRead(11)==LOW){
			  if(mudanca==0){
				   mudanca = 2;  //shift up from neutral to 2nd
			  }else if(mudanca == 1){
				   //do nothing check for pin 10 later
			  }else if(mudanca<6){
				   mudanca=mudanca + 1; //shift up from any other gear
			  }
		 }else if(digitalRead(12)==LOW){
			  if(mudanca ==2){
				   //do nothing check for pin 10 later
			  }else if(mudanca == 0){
				   mudanca = 1; //shift down from neutral into 1st
			  }else if(mudanca>0){
				   mudanca=mudanca-1;
			  }
		 }else if(digitalRead(10)==LOW && (mudanca == 2 || mudanca == 1)){
			  mudanca = 0;
		 }
		 updateLED();
		 delay(100);
	}
}
void updateLED(){
     switch(mudanca){
     case 0:
         digitalWrite(2, LOW);
         digitalWrite(3, LOW);
         digitalWrite(4, HIGH);
         digitalWrite(5, LOW);
         digitalWrite(6, HIGH);
         digitalWrite(7, LOW);
         digitalWrite(8, HIGH);
         break;
     case 1:
          digitalWrite(2, LOW);
          digitalWrite(3, HIGH);
          digitalWrite(4, HIGH);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          digitalWrite(7, LOW);
          digitalWrite(8, LOW);
          break;
     case 2:
          digitalWrite(2, HIGH);
         digitalWrite(3, HIGH);
         digitalWrite(4, LOW);
         digitalWrite(5, HIGH);
         digitalWrite(6, HIGH);
         digitalWrite(7, LOW);
         digitalWrite(8, HIGH); 
          break;
     case 3:
          digitalWrite(2, HIGH);
          digitalWrite(3, HIGH);
          digitalWrite(4, HIGH);
          digitalWrite(5, HIGH);
          digitalWrite(6, LOW);
          digitalWrite(7, LOW);
          digitalWrite(8, HIGH);
          break;
     case 4:
          digitalWrite(2, LOW);
          digitalWrite(3, HIGH);
          digitalWrite(4, HIGH);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          digitalWrite(7, HIGH);
          digitalWrite(8, HIGH);
          break;
     case 5:
          digitalWrite(2, HIGH);
          digitalWrite(3, LOW);
          digitalWrite(4, HIGH);
          digitalWrite(5, HIGH);
          digitalWrite(6, LOW);
          digitalWrite(7, HIGH);
          digitalWrite(8, HIGH);
          break;
     case 6:
          digitalWrite(2, LOW);
          digitalWrite(3, LOW);
          digitalWrite(4, HIGH);
          digitalWrite(5, LOW);
          digitalWrite(6, HIGH);
          digitalWrite(7, LOW);
          digitalWrite(8, HIGH); 
          break;
     default:
     }
}

Define some consts to indicate what your pin numbers mean. Don't make us remember that pin 11 means the neutral switch, and so on.

In this code, you are declaring TWO variables named mudanca. I'm sure that when you declared byte mudanca = 2 you meant to update the variable you had declared in the while loop, not declare a new variable.

  while (byte mudanca=0){
    if(digitalRead(11)==LOW){
      byte mudanca = 2;

I didn't really follow what the code was intended to do. I can see it looping waiting for an input to change, but it's not clear how that related to gear shifts. In fact, I suspect that it didn't relate at all.

I suggest you split the code up into :

  • Logic to work out what gear you are in
  • Logic to display the current gear

To work out what gear you are in you need to monitor all three inputs. If the neutral input is activated, set the gear to neutral (do you call that 'gear 0'?).

When the 'shift up' input changes from inactive to active, increment the gear unless you are already in the highest gear. (Note that you need to do this only on the transition - if the gear lever remains held in position, you don't want to keep incrementing the gear.)

When the 'shift down' input changes from inactive to active, decrement the gear unless you are already in the lowest gear. (Again, you are only looking for transitions.)

If you have reverse, then you could choose to represent this as 'gear -1'.

In order to display the current gear you need to turn on a set of segments corresponding to the number being displayed. I suggest you implement a function with an argument giving the number to be displayed, which contains the logic to work out which segments to turn on and turn them on. You could either hard-code this with in a switch statement, or define a const data array containing the required states for each number and use the current gear as an index into that array. The switch statement would require more code but the code would be simpler, so you might want to take that approach for your first attempt.

I also noticed your 6th gear LED set is the same as your neutral gear, you might want to change that.

I'm interested in how you are connecting the up/down switches to the shift linkage, and what kind of switches you are using. Hondas come (at least the Gold Wings) with gear indicators. My Harley lights up a 6 in 6th gear. If it can figure out that I'm in 6th, I don't know why it can't figure out that I'm in 3rd or 1st or 4th. But, it can't (or doesn't).

Thank you guys so much!
I used this code:

byte mudanca = 7;
void setup() {  
  // Define Pins  
  pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  
  // All leds test
  digitalWrite(2, 1);
  digitalWrite(3, 1);
  digitalWrite(4, 1);
  digitalWrite(5, 1);
  digitalWrite(6, 1);
  digitalWrite(7, 1);
  digitalWrite(8, 1);
  delay(1000);
  digitalWrite(2, 0);
  digitalWrite(3, 0);
  digitalWrite(4, 0);
  digitalWrite(5, 0);
  digitalWrite(6, 0);
  digitalWrite(7, 0);
  digitalWrite(8, 0);
  delay(1000);
}
void loop(){
	if(mudanca == 7){
		 //set LED values
		 if(digitalRead(10)==LOW){
			  mudanca=0;
		 }
	}else{
		 if(digitalRead(11)==LOW){
			  if(mudanca==0){
				   mudanca = 2;  //shift up from neutral to 2nd
			  }else if(mudanca == 1){
				   //do nothing check for pin 10 later
			  }else if(mudanca<6){
				   mudanca=mudanca + 1; //shift up from any other gear
			  }
		 }else if(digitalRead(12)==LOW){
			  if(mudanca ==2){
				   //do nothing check for pin 10 later
			  }else if(mudanca == 0){
				   mudanca = 1; //shift down from neutral into 1st
			  }else if(mudanca>1){
				   mudanca=mudanca-1;
			  }else if(mudanca == 1){
                                   //do nothing check for pin 10 later
                          }
		 }else if(digitalRead(10)==LOW && (mudanca == 2 || mudanca == 1)){
			  mudanca = 0;
		 }
		 updateLED();
		 delay(100);
	}
}
void updateLED(){
     switch(mudanca){
     case 0:
         digitalWrite(2, LOW);
         digitalWrite(3, LOW);
         digitalWrite(4, HIGH);
         digitalWrite(5, LOW);
         digitalWrite(6, HIGH);
         digitalWrite(7, LOW);
         digitalWrite(8, HIGH);
         break;
     case 1:
          digitalWrite(2, LOW);
          digitalWrite(3, HIGH);
          digitalWrite(4, HIGH);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          digitalWrite(7, LOW);
          digitalWrite(8, LOW);
          break;
     case 2:
          digitalWrite(2, HIGH);
         digitalWrite(3, HIGH);
         digitalWrite(4, LOW);
         digitalWrite(5, HIGH);
         digitalWrite(6, HIGH);
         digitalWrite(7, LOW);
         digitalWrite(8, HIGH); 
          break;
     case 3:
          digitalWrite(2, HIGH);
          digitalWrite(3, HIGH);
          digitalWrite(4, HIGH);
          digitalWrite(5, HIGH);
          digitalWrite(6, LOW);
          digitalWrite(7, LOW);
          digitalWrite(8, HIGH);
          break;
     case 4:
          digitalWrite(2, LOW);
          digitalWrite(3, HIGH);
          digitalWrite(4, HIGH);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          digitalWrite(7, HIGH);
          digitalWrite(8, HIGH);
          break;
     case 5:
          digitalWrite(2, HIGH);
          digitalWrite(3, LOW);
          digitalWrite(4, HIGH);
          digitalWrite(5, HIGH);
          digitalWrite(6, LOW);
          digitalWrite(7, HIGH);
          digitalWrite(8, HIGH);
          break;
     case 6:
          digitalWrite(2, HIGH);
          digitalWrite(3, LOW);
          digitalWrite(4, HIGH);
          digitalWrite(5, HIGH);
          digitalWrite(6, HIGH);
          digitalWrite(7, HIGH);
          digitalWrite(8, HIGH); 
          break;
     case 7:
          break;
     }
}

As you can see, laadams85, i've just changed some really small things to your code and it works! I owe you a beer!

PaulS:
I'm interested in how you are connecting the up/down switches to the shift linkage, and what kind of switches you are using. Hondas come (at least the Gold Wings) with gear indicators. My Harley lights up a 6 in 6th gear. If it can figure out that I'm in 6th, I don't know why it can't figure out that I'm in 3rd or 1st or 4th. But, it can't (or doesn't).

I'm using 2 hall sensors and a small magnet on the gear lever, and it works, at least on my desk, pretty soon I'll mount it on my motorcycle engined car and I will tell if it really works, hope so!

No problem, glad I could help. In your second if statement, downshifting, you should be able to drop this segment of code. A trailing if statement that doesn't do anything isn't necessary and that condition isn't encapsulated by your other if statements.

else if(mudanca == 1){
                                   //do nothing check for pin 10 later
                          }

Why not use vss pulse, tach pulse, and a little math to calculate which gear the bike is in? No need to hang any sensors or any extra wiring on your shift lever that way. If you can find out the gear ratios of your bike it should be easy to program.

SpAdam wrote:
Why not use vss pulse, tach pulse, and a little math to calculate which gear the bike is in?

I can't see how you could make that could work on a motorcycle. For example, if the OP has a BMW RR1000S, well, it's a totally stupid bike and the thing can get to around 145km/hr while still in first gear? The rpm indicator is past 15k. You really couldn't use the tacho signal even with clever maths to work out your gear.

In a car you might be able to do something as you mention, where it will display a calculated gear after some period of time, but a motorcycle is quite different, we are all over the place in terms of engine rpm in any gear.

The OP now has the code that will the best and how it usually done, that is, to use two hall effect sensors mounted on either side of the gear shifter and a connection into the neutral line which gives the absolute reference point to be able to know where to go on detection of the other two inputs.

@PaulS

My Harley lights up a 6 in 6th gear. If it can figure out that I'm in 6th, I don't know why it can't figure out that I'm in 3rd or 1st or 4th. But, it can't (or doesn't).

I think with your Harley, the indication lights up for 6th so that when you're cruising down that nice bit of road and think about shifting up to the invisible 7th, you don't look stupid amongst your riding mates because is so apparent what you are attempting, due to that loud compressor noise. :stuck_out_tongue:

Keep the rubber side down guys 8)

I think with your Harley, the indication lights up for 6th so that when you're cruising down that nice bit of road and think about shifting up to the invisible 7th, you don't look stupid amongst your riding mates because is so apparent what you are attempting, due to that loud compressor noise.

I ride by myself, so only I can see me look stupid. :slight_smile:

Light or no light, I'm still looking for 7th now and then.

PaulS:

I think with your Harley, the indication lights up for 6th so that when you're cruising down that nice bit of road and think about shifting up to the invisible 7th, you don't look stupid amongst your riding mates because is so apparent what you are attempting, due to that loud compressor noise.

I ride by myself, so only I can see me look stupid. :slight_smile:

Light or no light, I'm still looking for 7th now and then.

Harley, puf, my stereo volume knob goes to 11. :wink:

Pioneer SX-1980, they don't make em like that any more, 270 watts per channel RMS.


Lefty

rockwallaby:

SpAdam wrote:
Why not use vss pulse, tach pulse, and a little math to calculate which gear the bike is in?

I can't see how you could make that could work on a motorcycle. For example, if the OP has a BMW RR1000S, well, it's a totally stupid bike and the thing can get to around 145km/hr while still in first gear? The rpm indicator is past 15k. You really couldn't use the tacho signal even with clever maths to work out your gear.

In a car you might be able to do something as you mention, where it will display a calculated gear after some period of time, but a motorcycle is quite different, we are all over the place in terms of engine rpm in any gear.

The OP now has the code that will the best and how it usually done, that is, to use two hall effect sensors mounted on either side of the gear shifter and a connection into the neutral line which gives the absolute reference point to be able to know where to go on detection of the other two inputs.

Curious, is it a processing issue with the Arduino? That method is how every aftermarket engine management/datalogging system that I've ever seen handles gear detection and it works really well. There is only one gear that the bike can be in for every respective combination of rpm and vehicle speed. The only problem I could see would be sampling frequency with a 15000rpm motor, but in that case I see your point.

I'll have to look and see if I have access to the code for my school's FSAE air shifter setup from last year. I know that it had no physical sensor on the shift lever, but I'm not sure if it was just using a shift counter or if i calculated.

I feel like it would involve a lot of look-up tables or some sort of nonlinear equation. Certainly feasible but would be a lot of overhead for an uno. That being said it would be more stable as their is no way for it to be wrong.

rockwallaby:
I can't see how you could make that could work on a motorcycle.

I don't see any problem with it. You need to be able to measure the revs and road speed, calculate the current gearing and choose whichever ratio is nearest to that. Sure, when you're slipping the clutch or in neutral it would display a gear that might not actually be engaged, but only the rider could say whether that would be a problem.

laadams85:
I feel like it would involve a lot of look-up tables or some sort of nonlinear equation. Certainly feasible but would be a lot of overhead for an uno. That being said it would be more stable as their is no way for it to be wrong.

The functions are perfectly linear. The slope of the line is nothing but the ratio between engine rpm and vehicle speed, and is therefore fixed for each gear. This is what a gear chart looks like for an old Honda car transmission:

Obviously, for an automatic transmission vehicle that sees some degree of slip, this would be out the window. I'm also curious because I will be needing gear detection in the future as an expansion to a project that I'm currently working on. It will be on a regular old manual transmission car, so this is the only reasonable way to go about it.

The functions are perfectly linear.

Yeah for some reason I was thinking about the power/rev curve. Silly me, the slopes should be linear and a function of the gearing ratio.

Personally I'd probably just opt for two small switches on the shift lever. While you could definitely get it to work based on the current rpm/speed, it opens up other problems. For example, what will happen when the engine speed increases/decreases while shifting? Unless you were to somehow sense the clutch being pulled in, the gear inidcator would go up and down with it. That may be okay if you're making something for your personal ride but it would look amateurish at best. I guess you could use a micro switch on the clutch so when it is pulled in the gear inidcator doesn't change but I wouldn't doubt that introduces even more problems.