Motorcycle Gear Position Indicator

I have built and installed a Nano based multi-function display for my WeeStrom motorcycle, a Suzuki DL650. It works great for the most part, displaying the current gear or bike voltage (at a point near the battery) depending on selection from a push button. I am having a slight issue with the gear position indicator (GPI) display, however; once in a great while the display will momentarily jump to the next higher gear before returning to the correct gear. For instance, if in 2nd, the display will momentarily show that I am in 3rd and switch right back down to 2. Generally not a big deal, but I would like to figure out why it does this, and then fix it.

This project was a good starter for me since the Wee transmission generates a voltage based on what gear it's in. The ranges are known so a simple process of reading that voltage and then selecting the correct display. My theory is that a voltage spike occurs sporadically and that spike causes the display to pop up and then back. My question is how to capture the data so that I can then analyze it.

  1. Am I right that I should be looking into using polling to somehow capture the data, or is there another function?

  2. Do I need other hardware to store data; my thought is to take the bike for a ride until I see a blip, then analyze the data. Not sure how to store it.

Thanks folks. I'm obviously new to this stuff but I'm enjoying it.

Do you currently do a single analogRead and derive the gear from that or are you doing multiple reads and averaging the result to work out the gear position?

Totally off-topic, but my son's work bike is one of those 650 Suzukis. He's a paramedic with our national roads agency and responds on one. He covers a stretch of highway about 20km end to end, one of the busiest bits of road around. Typically gets on scene 10 minutes before his colleagues in the truck.

One problem.... even if he leaves it idling at a scene, the flashing lights have the better of the charging circuit and it runs the battery flat. He uses this as an excuse to go the long way back to base to charge it up....

(His own bike is a Royal Enfield 500 single thump thump thump....)

even if he leaves it idling at a scene,

Most police cars have the idle adjusted higher than usual. I bet the bike can be modified, even with a temporary shim that is stuck in the linkage, to run fast enough to charge. I used to use a piece of a clothespin on one truck I had...

If you post your code, perhaps somebody will spot something that makes it vulnerable to this sort of error.

It would be easy to smooth the signal in software which would make it much less vulnerable to noise and electrical glitches.

Thank you for your consideration, all. FWIW, the old Wees can be had at very reasonable prices and they seem to hold up well. The newer bikes have GPI and volt meters built in - having built one for my older 07 makes it just that much better! Ride safe.

The Wee generates the required signal as a discreet value - no need to manipulate rpm and speed to figure out the gear (that said, my next project for another bike will do that.) That made this project easier.

I've posted the code below. There are two computations going on; the top portion is reading the GPI input, figuring the gear, and displaying it. (I'm using a 4 digit 7 segment LCD display with backlighting - it's large so my tired old eyes can see it.) The bottom portion is figuring out the battery volt level from a voltage divider in my project box and displaying that. There is a push button on the project box to select the GPI or voltage.

There is a delay in the code that allows me to switch to the desired display more easily. I avoided any averaging of GPI data because I want to see that display change quickly - such as when I am coasting and downshifting into a stop light or stop sign.

// note that the backlight draws 3.5 ma and can be run directly from the arduino

#include <SPI.h>

// 0 1 2 3 4 5 6 7 8 9 -
const uint8_t nums[] = {
0xEE, 0x22, 0x7C, 0x76, 0xB2, 0xD6, 0xDE, 0x62, 0xFE, 0xF6, 0x10 };
const uint8_t dot = 0x01;
bool column = true;
uint8_t display[5];

int GearPin = 0; // The Gear "pink" wire is connected to analog pin 0
int BatteryPin = 2; // The Battery wire is connected to analog pin 2
int ButtonPin = 7; // The button is connected to digital pin 7 as an input
// use a pull down resistor
int BLAPin = 5; // The LCD display backlight is connected to digital pin 5 as a PWM output

int Gear = 0;
int ButtonPushCounter = 0; // counter for the number of button presses
int ButtonValue = 0; // current state of the button
int LastButtonValue = 0; // previous state of the button
int GearValue; // to store the value of the Gear

int BatteryValue;
int GrossedUpBatVal;
int ConvBatVal2;
int ConvBatVal = 1400;
void setup()
{
pinMode(ButtonPin, INPUT);
pinMode(BLAPin, OUTPUT);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV128); //this line slows the clock down
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE2);
/*
At CPOL=1 the base value of the clock is one (inversion of CPOL=0)
For CPHA=0, data is captured on clock's falling edge and data is propagated on a rising edge.
Mode CPOL CPHA
0 0 0
1 0 1
2 1 0
3 1 1
*/
//Serial.begin(9600);
// analogWrite values from 0 to 255
analogWrite(BLAPin, 100); // this turns on the backlighting at reduced level

}

void loop()
{
delay(500); // repeat once per .5 second (change as you wish!)
ButtonValue = digitalRead(ButtonPin);

if (ButtonValue != LastButtonValue) {
if (ButtonValue == HIGH) {
ButtonPushCounter++;
}
else {
}
}

if (ButtonPushCounter % 2 == 0) //even number of pushes will show gear, odd will be battery
{

GearValue = analogRead(GearPin);
GearValue = GearValue * 5/ 10.23; // this turns the volt value from 0 - 1023 to 0 - 5

if (GearValue < 166) {
Gear = 1;
} //these volt values have been multiplied by 100
if (GearValue >= 166 && GearValue < 218){
Gear = 2;
}
if (GearValue >= 218 && GearValue < 291.5) {
Gear = 3;
}
if (GearValue >= 291.5 && GearValue < 372) {
Gear = 4;
}
if (GearValue >= 372 && GearValue < 438.5) {
Gear = 5;
}
if (GearValue >= 438.5 && GearValue < 480) {
Gear = 6;
}
if (GearValue >= 480) {
Gear = 10;
}

display[00] = 0x00;
// the colon is off and note that 00 in the display is really 0

display[1] = 0x00;
display[2] = 0x00;
display[3] = nums[Gear];
display[4] = 0x00;
for (uint8_t i = 0; i < 5; i++)
SPI.transfer(~display*);*

  • column = !column;*

  • } *
    else

  • {*

  • BatteryValue = analogRead(BatteryPin);*
    _ GrossedUpBatVal = BatteryValue * 14.68/4.68; //gross up back to pre-divider value adjusted to give an accurate result _
    _ ConvBatVal2 = GrossedUpBatVal * 5/ 10.23;_
    _ ConvBatVal=ConvBatVal * .9 + ConvBatVal2 * .1;_

  • display[0] = 0x00; // the colon is off*

  • if (ConvBatVal <1000) {*

  • display[1] = 0x00;*

  • }*

  • else {*

  • display[1] = nums[((ConvBatVal - (ConvBatVal % 1000)) / 1000)];*

  • }*

  • display[2] = nums[((ConvBatVal % 1000) - (ConvBatVal % 100))/100] | dot; //Hundreds with decimal point on*

  • display[3] = nums[((ConvBatVal % 100) - (ConvBatVal % 10))/10]; // Tens*

  • display[4] = nums[(ConvBatVal % 10)]; //Ones*

  • for (uint8_t i = 0; i < 5; i++)*
    _ SPI.transfer(~display*);_
    _
    column = !column;_
    _
    }*_

* }*
[/quote]

I have two suggestions:

  1. Use delay ("BlinkWithoutDelay") to "debounce" the fluctations in voltage. That is, read the voltage, then wait for a while, then read it again. That should, give you the possibility to filter out any excess in voltage change.

  2. Since its a sequential gearbox, you cant jump between gears. That would make it possible to use something like this. Swap out the wait with "BlinkWithoutDelay" delays.

if (GearValue > PreviusGearValue) {
      Gear = Gear+1; 
*WAIT for 1000 ms*
}
if (GearValue < PreviusGearValue) {
      Gear = Gear-1; 
*WAIT for 1000 ms*
}

Hi,
Do you feed the gearbox output directly to the arduino input?
If so, it might be worth trying a series resistor of say 1K in series with the input and say 0.1uF cap between the arduino analog input and ground to act as a filter.
The fact that it is a brief occurence, it could be noise.

Tom..... :slight_smile:

TomGeorge:
it could be noise.

Yeah, you know what these bikers are like 8)

terryking228:
I bet the bike can be modified, even with a temporary shim that is stuck in the linkage

I've got a Suzuki GS500 and it's got a small lever next to the clutch that I can use to change the idle speed. I figure that's standard on most Suzuki's.

skeeter_mcbee:

terryking228:
I bet the bike can be modified, even with a temporary shim that is stuck in the linkage

I've got a Suzuki GS500 and it's got a small lever next to the clutch that I can use to change the idle speed. I figure that's standard on most Suzuki's.

I'll ask my son to check- maybe it has one too. Thanks.

I avoided any averaging of GPI data because I want to see that display change quickly - such as when I am coasting and downshifting into a stop light or stop sign.

There will be no perceptible delay in averaging several readings as the chip is capable of doing thousands of analogue reads per second and you probably only need to do about 3 to 10 readings to get an average (the more readings the more stable).

Thanks again, folk - you've given me some good suggestions.

Tom, IIRC the GPI feed does go into the nano directly after an attachment post. The post to nano connection is hardwired, but I will de-solder it and add the suggest cap and resistor. Thanks for that!

BobAgain:
I've posted the code below.

You have used the 'copy for forum' feature of the IDE, which is understandable but wrong. Unfortunately the Arduino forum and the Arduino IDE were developed by people who seem not to have talked to each other. To post code here you need to copy the code as plain text, and paste it into your message enclosed in [ code ] [ /code ] tags. The # button in the editor window will insert those tags for you.