Saturday, July 5, 2014

Tektronix MDO3000 Motorcycle Gear Position Indicator

-----
This project is a variant of my ultra-low cost DIY Suzuki DL1000 DIY Gear Position Indicator (GPI) with a few changes:
  • For a microcontroller the Ardunio Nano is used to digitize the signal from the bike's ECM instead of a PICAXE 18M2.
  • The gear position output is displayed on a Tektronix MDO3000 oscilloscope instead of a two dollar seven segment LED.  The MDO3000 is an amazing instrument from Tektronix; read about it here.
This is probably the only oscilloscope based motorcycle GPI on the planet.  It is also perhaps the most impractical and expensive way to build a motorcycle GPI but that was really the entire point of the project. ;)
-----
For those that are not interested in the project details and just want to see the result take a look at this 60 second video:
-----
Basically, here is what is going on....  Analog input A1 on the Arduino microcontroller is configured as a ADC pin and monitors an output on the bike's ECM.  See the yellow wire in the video?  That is patched into a signal on the ECM that outputs a value of 0-5VDC depending on the gear that the bike is in.  

We digitize that ECM voltage on the yellow wire and depending on the voltage of that signal (what gear the bike is in) branch to code that Pulse Width Modulates (PWM) two Arduino digital output (digital output Pin 6 and 5, see code below).  Pin 6 and Pin 5 of the Arduino are connected to Channel 1 and Channel 2 of the Tek MDO3000.  The scope is put into XY Display mode.  Then like "magic" you have the world's most impractical motorcycle gear position indicator ever constructed!
----
Like most of my projects this could not have been accomplished without the help of those much smarter than me posting examples and inspiration on the web.  I tried to credit them in my source code comments.  In the unlikely event you duplicate this project, please try to give credit where credit is due. 
----
Source code is below.  I'm a hacker, not a SW Engineer.  Plus, I cobbled the code together in a few hours.  I know the code can be better written (much better written).

/*
 * Oscilloscope GPI for Suzuki VSTROM DL1000
 *
 *   Created: Jun 2014
 *  
 * WhiskeTangoHotel.Com
 *        with special thanks to John M. De Cristofaro
 *        with special thanks to johngineer   
 *         (http://www.flickr.com/photos/johngineer/6496005491/sizes/z/in/photostream/)
 *
 */

/* ****************************************************************************
Circuit for both PWM ports:

                          R
PWM OUT ----/\/\/\-----+------------ OUTPUT
                                    |
                                 === C
                                      |
                                 GND

R = 10k
C = 0.1uF

**************************************************************************** */

#define TRACE_DELAY 2500  // trace delay in uS (start with 2500). making this longer will
     // result in a straighter drawing, but slower
     // refresh rate. making it too short will result
     // in an angular blob.

#define X               6     // attach scope channel 1 (X) to pin 6
#define Y               5     // attach scope channel 2 (y) to pin 5

int gearvoltage = 1;     // define analog input A1 as ADC that monitors the ECM on the bike
int gearval = 0;            // reading from gearvoltage ADC is converted into the gear to display.  1-6 and 7=N.  Set to 0 to get into M3 self Test Loop
int i;                 // counter for M3 self test delay loop


void setup()
{
  pinMode(X, OUTPUT);
  pinMode(Y, OUTPUT);

  // The following sets the PWM clock to maximum on the Arduino(no CPU clock division)
  // DO NOT CHANGE THESE UNLESS YOU KNOW WHAT YOU ARE DOING!
  
  TCCR0A = ( 1<<COM0A1 | 0<<COM0A0 | // clear OC0A on compare match (hi-lo PWM)
1<<COM0B1 | 0<<COM0B0 | // clear OC0B on compare match (hi-lo PWM)
1<<WGM01  | 1<<WGM00); // set PWM lines at 0xFF

  TCCR0B = ( 0<<FOC0A | 0<<FOC0B | // no force compare match
0<<WGM02 | // set PWM lines at 0xFF
0<<CS02 | 0<<CS01 | // use system clock (no divider)
1<<CS00 );

  TIMSK0 = ( 0<<OCIE0B | 0<<TOIE0 |
0<<OCIE0A );  

  //All Serial statements in loops are for debug only.
  Serial.begin(9600);

} // end void setup ***********************************************************


void loop()  
{

// Main loop.  Reads the Gear Position Signal from the Vstrom ECM.  Displays X-Y to o'scope

// x, y coordinates range from 0 to 255.  0,0 is lower left.  255,255 is upper right

if (gearval == 0) {  // M3 Self Test Loop----------------------------
  int NUM_POINTS = 38;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("M3 Self Test Loop");
  Serial.println(NUM_POINTS);      
  // x coords for drawing the gear number
  unsigned char x_points[38] = {140, 140, 140,  90,  75,  60,  10,  10, 10, 40, 40,  40, 60, 90, 110, 110, 110, 140, 205, 250, 250, 230, 250, 250, 160, 160, 190, 190, 220, 220, 200, 200, 220, 220, 190, 190, 160, 160 };  
  // y coords
  unsigned char y_points[38] = {50, 110, 170, 170, 100, 170, 170, 110, 50, 50, 95, 140, 50, 50, 140,  95, 50,  50,   50,  50, 110, 115, 120, 170, 170, 140, 140, 150, 150, 130, 130, 100, 100,  80,  80,  90,  90,  50};

    unsigned char t;
    for (i = 0; i < 50; i++) //M3 self test delay loop  count of 100 is ~ 5 secs.
      {
        for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
        {
          analogWrite(X, x_points[t]);
          analogWrite(Y, y_points[t]);
          /*
          while (! Serial);
          Serial.println("t loop");
          Serial.println(t);       
          Serial.println(x_points[t]);
          Serial.println(y_points[t]);
          Serial.println("-----------");
          */     
  delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
        }  // end if t   
    }  //end unsigned    
} // end M3 Self Test Loop -------------------------------------



gearval = analogRead(gearvoltage); //read the ECM and covert to a gearval 1-6 or 7 for N


if ( (gearval >= 0)   &&  (gearval < 346)  ) {gearval = 1; }
if ( (gearval >= 347) &&  (gearval < 451)  ) {gearval = 2; }
if ( (gearval >= 452) &&  (gearval < 600)  ) {gearval = 3; }
if ( (gearval >= 601) &&  (gearval < 756)  ) {gearval = 4; }
if ( (gearval >= 757) &&  (gearval < 886)  ) {gearval = 5; }
if ( (gearval >= 887) &&  (gearval < 974)  ) {gearval = 6; }
if ( (gearval >= 975) &&  (gearval < 1024) ) {gearval = 7; }

//gearval = 0;

while (! Serial);
Serial.println("gearval is:");
Serial.println(gearval);
Serial.println("-----------");

if (gearval == 1) {  // ----------------------------
  int NUM_POINTS = 12;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("1G Loop");
  Serial.println(NUM_POINTS);      
  // x coords for drawing the gear number
  unsigned char x_points[12] = {60, 90, 120, 120, 120, 120, 120, 60, 170, 120, 120, 60};  
  // y coords
  unsigned char y_points[12] = {180, 200, 220, 170, 130, 80, 30, 30, 30, 30, 220, 180};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */     
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t   
      
    }  //end unsigned    
} // end Gear 1 loop -------------------------------------

if (gearval == 2) {  // ----------------------------
  int NUM_POINTS = 19;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("2G Loop");
  Serial.println(NUM_POINTS);      
  // x coords for drawing the gear number
  unsigned char x_points[19] = {60, 85, 120, 150, 160, 140, 100, 60, 120, 170, 120, 60, 100, 140, 160, 150, 120, 85, 60};  
  // y coords
  unsigned char y_points[19] = {200, 215, 220, 200, 180, 130, 80, 30, 30, 30, 30, 30, 80, 130, 180, 200, 220, 215, 200};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t
      
    }  //end unsigned    
} // end Gear 2 loop -------------------------------------

if (gearval == 3) {  // ----------------------------
  int NUM_POINTS = 29;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("3G Loop");
  Serial.println(NUM_POINTS);      
  // x coords for drawing the gear number
  unsigned char x_points[29] = {60, 85, 120, 150, 160, 150, 120, 80, 120, 150, 160, 155, 120, 85, 60, 85, 120, 155, 160, 150, 120, 80, 120, 150, 160, 150, 120, 85, 60};  
  // y coords
  unsigned char y_points[29] = {200, 215, 220, 200, 180, 145, 130, 130, 130, 110, 80, 50, 30, 30, 50, 30, 30, 50, 80, 110, 130, 130, 130, 145, 180, 200, 220, 215, 200};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t
      
    }  //end unsigned    
} // end Gear 3 loop -------------------------------------

if (gearval == 4) {  // ----------------------------
  int NUM_POINTS = 19;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("4G Loop");
  Serial.println(NUM_POINTS);      
  // x coords for drawing the gear number
  unsigned char x_points[19] = {140, 140, 140, 140, 90, 65, 30, 80, 140, 180, 140, 80, 30, 65, 90, 140, 140, 140, 140};
  // y coords
  unsigned char y_points[19] = {10, 65, 110, 210, 160, 120, 65, 65, 65, 65, 65, 65, 65, 120, 160, 210, 110, 65, 10};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t
      
    }  //end unsigned    
} // end Gear 4 loop -------------------------------------

if (gearval == 5) {  // ----------------------------
  int NUM_POINTS = 21;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("5G Loop");
  Serial.println(NUM_POINTS);       
  // x coords for drawing the gear number
  unsigned char x_points[21] = {160, 90, 60, 61, 65, 140, 155, 155, 130, 85, 40, 85, 130, 155, 155, 140, 65, 61, 60, 90, 160}; 
  // y coords
  unsigned char y_points[21] = {200, 200, 200, 180, 120, 110, 80, 45, 20, 10, 30, 10, 20, 45, 80, 110, 120, 180, 200, 200, 200};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t
      
    }  //end unsigned    
} // end Gear 5 loop -------------------------------------


if (gearval == 6) {  // ----------------------------
  int NUM_POINTS = 29;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("6G Loop");
  Serial.println(NUM_POINTS);     
  // x coords for drawing the gear number
  unsigned char x_points[29] = {160, 140, 90, 61, 30, 30, 35, 65, 85, 130, 155, 155, 140, 65, 30, 65, 140, 155, 155, 130, 85, 65, 35, 30, 30, 61, 90, 140, 160};  
  // y coords
  unsigned char y_points[29] = {200, 210, 200, 180, 140, 105, 65, 15, 10, 20, 45, 80, 110, 120, 105, 120, 110, 80, 45, 20, 10, 15, 65, 105, 140, 180, 200, 210, 200};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t
      
    }  //end unsigned    
} // end Gear 6 loop -------------------------------------

if (gearval == 7) {  // 7 is for N ----------------------------
  int NUM_POINTS = 15;    // display output (trace) is defined by this many x/y coord. pairs
  while (! Serial);
  Serial.println("N Loop");
  Serial.println(NUM_POINTS);
  // x coords for drawing the gear number
  unsigned char x_points[15] = {50, 50, 50, 90, 140, 170, 170, 170, 170, 170, 140, 90, 50, 50, 50};
  // y coords
  unsigned char y_points[15] = {30, 120, 220, 160, 80, 30, 120, 220, 120, 30, 80, 160, 220, 120, 30};

    unsigned char t;
    {
      for(t = 0; t < NUM_POINTS; t++) // run through the points in x & y
      {
        analogWrite(X, x_points[t]);
        analogWrite(Y, y_points[t]);
        /*
        while (! Serial);
        Serial.println("t loop");
        Serial.println(t);       
        Serial.println(x_points[t]);
        Serial.println(y_points[t]);
        Serial.println("-----------");
        */
delayMicroseconds(TRACE_DELAY); // wait TRACE_DELAY microseconds
      }  // end if t
      
    }  //end unsigned    
} // end Gear 7 = N loop -------------------------------------
    
}  // end void loop
----
If you're still with us, thanks for the visit and check out our other 'stuff' at WhiskeyTangoHotel.Com.