Mit diesem Programm wurde der erste Testlauf durchgeführt.

Zuvor mussten jedoch einige Änderungen vorgenommen werden. Sowohl das CANdiy Shield, als auch das LCD-Display verwenden die selben Pins am Arduino Board. Wir beseitigten dieses Problem durch das Umlöten einiger Pins.

Dieser Testversuch lief jedoch leider nicht so ab wie wir es geplant hatten. Aufgrund eines Kurzschlusses brannte der Chip am CANdiy Shield durch und es war keine Kommunikation mehr mit dem Auto möglich.

Hier unser GUI-Design:

Und hier unser Source Code:

#include 
#include 
 
ObdInterface obd;
ObdMessage msg;
 
LiquidCrystal lcd(11,9,4,5,6,3);
 
int modeHorizontal = 0;
int modeVertical = -1;
 
String drivingMenu[][3] = {
                            {"Speed", " km/h","0"},
                            {"Engine RPM", " RPM","1"},
                            {"Engine Temp.", " °C","0"},
                            {"Turbo. Temp. 1", " °C","0"},
                            {"Turbo. Temp. 2", " °C","0"},
                            {"Turbo. RPM", " RPM","0"}
                          };
int drivingMenuPids[] = {0x0d,0x0c,0x05,0x75,0x76,0x74};
boolean drivingMenuPidsSupported[] = {false,false,false,false,false,false};
 
String generalMenu[][3] = {
                            {"Codes del. since", " km","0"},
                            {"Fuel", " %","1"},
                          };
int generalMenuPids[] = {0x31,0x2F};
boolean generalMenuPidsSupported[] = {false,false};
 
void setup()
{
  lcd.begin(16,2);
  lcd.print("Welcome!");
  lcd.setCursor(0,1);
  lcd.print("Starting...");
 
  Serial.begin(9600);
  Serial.println("Probing Bus settings...");
  //probing bus settings
  if (probe(false,false))
  {
    obd.setSlow(false);
    obd.setExtended(false);
    Serial.println("Bus settings found: false false");
  }
  else
  {
    if (probe(true,false))
    {
      obd.setSlow(true);
      obd.setExtended(false);
      Serial.println("Bus settings found: true false");
    }
    else
    {
      if (probe(false,true))
      {
        obd.setSlow(false);
        obd.setExtended(true);
        Serial.println("Bus settings found: false true");
      }
      else
      {
        if (probe(true,true))
        {
          obd.setSlow(true);
          obd.setExtended(true);
          Serial.println("Bus settings found: true true");
        }
        else
        {
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("No Connection!");
        }
      }
    }
  }
 
  obd.begin();
 
  //check which pids are supported
  for (int i = 0;i<sizeof(drivingMenuPidsSupported);i++)
  {
    boolean supported;
    obd.isPidSupported(drivingMenuPids[i],supported);
    if (supported)
      drivingMenuPidsSupported[i] = true;
  }
  for (int i = 0;i<sizeof(generalMenuPidsSupported);i++)
  {
    boolean supported;
    obd.isPidSupported(generalMenuPids[i],supported);
    if (supported)
      generalMenuPidsSupported[i] = true;
  }
}
 
void loop()
{
  lcd.clear();
  if (analogRead(A0)<20)    //right button
  {
    if (modeHorizontal <2)       modeHorizontal++;     else       modeHorizontal = 0;     modeVertical = -1;   }   if (analogRead(A0)>380 && analogRead(A0)<430)    //right button   {     if (modeHorizontal >0)
      modeHorizontal--;
    else
      modeHorizontal = 2;
    modeVertical = -1;
  }
  switch (modeHorizontal)
  {
    case 0:    //Driving values
      if (analogRead(A0)>220&&analogRead(A0)<300)    //down button
      {
        if (modeVertical<sizeof(drivingMenuPidsSupported)-1)         {           modeVertical++;           while (!drivingMenuPidsSupported[modeVertical])           {             if (modeVertical>=sizeof(drivingMenuPidsSupported))
              modeVertical = 0;
            modeVertical++;
          }
        }
        else
        {
          modeVertical=0;
        }
      }
      else if (analogRead(A0)<150&&analogRead(A0)>80)  //up button
      {
        if (modeVertical>0)
        {        
          modeVertical--;
          while(!drivingMenuPidsSupported[modeVertical])
          {
            if (modeVertical>0)
              modeVertical--;
            else
            {
              modeVertical = -1;
              break;
            }
 
          }
        }
        else
        {
          modeVertical = -1;
        }
      }
      if (modeVertical == -1)
      {
        lcd.setCursor(0,0);
        lcd.print("Driving values");
        lcd.setCursor(0,1);
        lcd.print("Press Down...");
      }
      else
      {
        lcd.setCursor(0,0);
        lcd.print(drivingMenu[modeVertical][0]);
        lcd.setCursor(0,1);
 
        if (generalMenu[modeVertical][2] == "0")
        {
          word value = 0;
          Serial.println("Calling " + drivingMenu[modeVertical][0]);
          if (!obd.getPidAsInteger(drivingMenuPids[modeVertical],value))
           value = 666;
           lcd.print(value);
           lcd.print(drivingMenu[modeVertical][1]);
        }
        else if (drivingMenu[modeVertical][2] = "1")
        {
//          Serial.println("Calling " + drivingMenu[modeVertical][0]);
          float value = 0;
          if (!obd.getPidAsFloat(drivingMenuPids[modeVertical],0.0f,16383.75f,value))
            value = 666;
          lcd.print(value);
          lcd.print(drivingMenu[modeVertical][1]);
        }
      }
    break;
 
    case 1:  //general infos
    if (analogRead(A0)>220&&analogRead(A0)<300)    //down button     {         if (modeVertical >= sizeof(generalMenuPidsSupported)-1)
          modeVertical = 0;
        else
          modeVertical++;
        while (!generalMenuPidsSupported[modeVertical])
        {
          if (modeVertical>=sizeof(generalMenuPidsSupported)-1)    
          {
            modeVertical = 0;
          }
          else
          {
            modeVertical++;
          }
        }
    }
    else if (analogRead(A0)<150&&analogRead(A0)>80)  //up button
    {
            if (modeVertical == 0)
        modeVertical = -1;
      else
      {
      if (modeVertical>0)
      {        
        modeVertical--;
        while(!generalMenuPidsSupported[modeVertical])
        {
          if (modeVertical>0)
            modeVertical--;
          else
          {
            modeVertical = -1;
          }
        }
      }
      }
    }
    if (modeVertical == -1)
    {
      lcd.setCursor(0,0);
      lcd.print("General infos");
      lcd.setCursor(0,1);
      lcd.print("Press Down...");
    }
    else
    {
      lcd.setCursor(0,0);
      lcd.print(generalMenu[modeVertical][0]);
      lcd.setCursor(0,1);
      if (generalMenu[modeVertical][2] == "0")
      {
        word value = 0;
        //Serial.println("Calling " + generalMenu[modeVertical][0]);
        if (!obd.getPidAsInteger(generalMenuPids[modeVertical],value))
         value = 666;
         lcd.print(value);
         lcd.print(generalMenu[modeVertical][1]);
      }
      else if (generalMenu[modeVertical][2] = "1")
      {
//        Serial.println("Calling " + generalMenu[modeVertical][0]);
        float value = 0;
        if (!obd.getPidAsFloat(generalMenuPids[modeVertical],0.0f,16383.75f,value))
          value = 666;
        lcd.print(value);
        lcd.print(generalMenu[modeVertical][1]);
      }
    }
    break;
 
    case 2:  //errors
    if (modeVertical == -1)
    {
      lcd.setCursor(0,0);
      lcd.print("Errors");
      lcd.setCursor(0,1);
      lcd.print("Press Down...");
    }
    break;
  }
  delay(125);
}
 
boolean probe(boolean slow, boolean extended) {
  ObdInterface obd;
  boolean dummy;
 
  obd.setSlow(slow);
  obd.setExtended(extended);
 
  obd.begin();
  boolean result = obd.isPidSupported(1, dummy);
  obd.end();
 
  delay(250);
 
  return result;
}

Die Ansteuerung für das LCD-Display, auf der später Informationen wie Motorauslastung und Turbodruck angezeigt werden, ist fertig. Zum Test haben wir ein kleines Spiel für das 16*2 Display programmiert.

Wenn jemand Lust hat es auszuprobieren, hier ist der Sourcecode:

 

 

/*
Autoren: Daniel Wuggenig & Michelle Kilzer
Datum: 09.07.2014 11:35
Beschreibung: Minispiel bei dem man Gegenständen ausweichen muss.
Blöcke spawnen random und kommen von links nach rechts.
Zwischen den Blöcken ist mindestens 2 Blöcke nichts.
Kommt man bei einem Block an, hat man verloren.
*/
 
#include <LiquidCrystal.h>  //Bibliothek für Display Ansteuerung
 
LiquidCrystal lcd(8,9,4,5,6,7);  //Pinbelegung Display
 
boolean brick[16][2];    //2D-Array das speichert, ob sich an jeder Position ein Block befindet oder nicht. True=ein Block, False = kein Block
 
boolean player = true;  //True = Player ist in der oberen Reihe, False = Player ist in der unteren Reihe
 
void setup() {
	lcd.begin(16, 2);  //16*2 Display initialisieren
	lcd.print("Starting...");  //Start auf Display ausgeben
 
	for (int i = 0;i<16;i++)  //ganzes 2D-Array auf false setzen (kein Block am Anfang)
	{
		for (int j = 0;j<2;j++)
		{
			brick[i][j] = false;
		}
	}
}
int modTime = 100;    //Gibt die Anzahl der Durchläufe an
boolean lost = false;  //False = nicht verloren, True = verloren (Spielende)
 
void loop() {
	if (!lost)  //Überprüfen ob das Spiel aus ist
	{
		modTime++;  //modTime um eins erhöhen, da neuer Durchlauf
		delay((1/((float)modTime/100))*250);  //delay abhängig wie lange das Spiel bereits läuft
		if (modTime%2 == 0)  //in jeden 2. Durchlauf werden die Blöcke eine Position nach rechts verschoben
		{
			for (int i = 15;i>=0;i--)
			{
				for (int j = 0;j<2;j++)
				{
					brick[i][j] = brick[i-1][j];  //Blöcke nach rechts verschieben
				}
			}
			brick[0][0] = false;  //in der ersten Spalte sind keine Blöcke, da sie gerade nach rechts verschoben wurden
			brick[0][1] = false;
		}
		if (modTime%6==0)  //Alle 6 Durchläufe wird ein neuer Block gespawnt
		{
			int rN = random(2);  //zufällige Zahl, die angibt ob der Block in der oberen oder unteren Zeile landet.
			brick[0][rN] = true;  //erzeugt den Block
		}
		lcd.clear();    //Display wird gecleared, damit keine Übereste von alten Blöcken übrig bleiben
		for (int i = 0;i<16;i++)  // Array wird durchgegangen, wenn true wird ein block gezeichnet
		{
			for (int j = 0;j<2;j++)
			{
				lcd.setCursor(i,j);
				if (brick[i][j])
					lcd.print((char)219);  //Block wird gezeichnet (█)
			}
		}
		if (analogRead(A0)<110&&analogRead(A0)>90)  //Wenn der obere Knopf gedrückt wird
			player = true;    //Player wird auf die obere Zeile gesetzt
		else if (analogRead(A0)>240 && analogRead(A0)<270)  //Wenn der untere Knopf gedrückt wird
			player = false;  //Player wird auf die untere Zeile gesetzt
		if (player)  //Spieler zeichnen
		{
			lcd.setCursor(13,0);
			lcd.print((char)181);
			if (brick[13][0])  //Wenn an der Spielerposition ein Block ist, ist das Spiel aus
			{
				lost = true;
				lcd.clear();
			}
		}
		else
		{
 
			lcd.setCursor(13,1);  //Gleich wie oben nur für untere Zeile
			lcd.print((char)181);
			if (brick[13][1])
			{
				lost = true;
				lcd.clear();
			}
		}
	}
	else    //Spiel verloren
	{
		lcd.setCursor(0,0);
		lcd.print("Highscore:");    //Highscore ausgeben
		lcd.print(((modTime-100)/6)-4);  //1 Punkt für jeden Block, -4 weil am Anfang keine Blöcke sind
	}
}