Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

02 Lost in Space

16. Oktober 2012

Video

LostInSpac360

Ideenfindung

1. Fitness Uhr Eine sportliche Aktivität eines Users wird von einem Bewegunssensor erfasst und die relevante Daten an einer Armbanduhr angezeigt. Der Bewegungssensor wird davor an das Nutzer Objekt angebracht 1.Modus Digitalanzeige = Zählt die gewünschte Wiederholungsanzahl der Übung. 0 = Ende der Übung LED Ring = Wiederholungsfrequenz (Taktrate) der Übung 2.Modus Digitalanzeige = Abstrakte Streckendistanz. 0.0 = Ziel. LED Ring = Rückstand oder Vorsprung zum Mitstreiter. 2. Wendeltreppen Lampe Begleitet eine Person auf seinem Weg die Wendeltreppe hoch oder runter.

Konzept

Lost in Space Hilf dem orientierungslosen Roboter „Roll E“ nach Hause zu finden. Roboter Ist Roll E erst einmal eingeschaltet, fährt dieser in Blickrichtung gerade aus. Sein Fahrverhalten kann nur über sogenannte CardTags beeinflusst werden. Roll E verfügt über einen am Unterboden eingebauten RFiD Reader (Leseeinheit), mit der er überfahrene TagCards auslesen und die entsprechenden Kommandos ausführen kann. TagCards Diese Spielkarten können frei auf der Bewegungsfläche von Roll E platziert werden. Icons auf den Karten zeigen dem Nutzer die Funktion der einzelnen Karten. Im Zentrum einer jeder Karte ist jeweils ein RFiD Tag (Transponder) unterlegt. Ziel Erreiche mit Roll E die zu beginn gelegte HomeCard. Must Have Roll E - Ein und aus Schalter - Ungefähres, absehbares Fahrverhalten in 90° Winkeln - Blickrichtung = Fahrtrichtung - Funktionierender RFiD Reader - Optisch ansprechend CardTags - Klare, unverwechselbare Icons - Optisch ansprechend - Right Card (Fahrtrichtungsänderung  um 90° Uhrzeigersinn) - Left Card (Fahrtrichtungsänderung um 90° Gegenuhrzeigersinn) - HomeCard (Ziel des Roboters) Nice to Have Roll E - Eingebauter Kartenzähler - Energieanzeige (Treibstoff) die sich über die Zeit entleert - Aufladetimer CardTags - BackCard (Fahrtrichtungsänderung  um 180°) - VirusCard (Nachfolgende Karte wird gegenteilig ausgelesen) - OilCard(Fahrtrichtungsänderung  um 0°, 90° Uhrzeigersinn, 90° Gegenuhrzeigersinn oder 180°) - RepeatCard (Letzte Card Funktion wird wiederholt) - PausCard (Roll E wird kurzzeitig gestoppt) - Speed Card (Fahrtgeschwindigkeit erhöhen) - Slow Card (Fahrtgeschwindigkeit verringern) - Charging+ (Erhöht den Energiezustand) - Charging- (Verringert den Energiezustand)

Umsetzung

1. Antriebsmechanik aus Lego Technik Bauteilen und zwei 9Volt DC-Motoren. Verdrahtung der elektrischen Komponenten. 2. Coding der verschiedenen Tag Funktionen in Arduino. CODE:
#include

int RFIDResetPin = 13;
SoftwareSerial mySerial(2,3);

char lastTagCard[] = "BBBBBBBBBBBB";
//Gruppen zum Vergleichen
const int anzahlDerGruppen = 10;
const int anzahlDerEintraege = 4;

char* tagCards[anzahlDerGruppen][anzahlDerEintraege] ={
  {
    "35021E5DD8AC", "", "", ""                                                                                                                                                                                } // TagCardHome
  ,
  {
    "84003399CFE1", "35021CF723FF", "08B0A4210D30", "89B0A4A15C60"                                                                                                                                            } // TagCardR
  ,
  {
    "21A12600983E", "840033973111", "81B186A1C9DE", "29B1060020BE"                                                                                                                                            } // TagCardL
  ,
  {
    "35021E7C0055", "", "", ""                                                                                                                                                                                } // TagCardZ
  ,
  {
    "35021D1F0336", "", "", ""                                                                                                                                                                                } // TagCardAusruhen
  ,
  {
    "35021EB149D1", "", "", ""                                                                                                                                                                                } // TagCardSD
  ,
  {
    "35021D00163C", "", "", ""                                                                                                                                                                                } // TagCardOelspur
  ,
  {
    "01B3A4A15DEA", "", "", ""                                                                                                                                                                                } // TagCardVirus
  ,
  {
    "", "", "", ""                                                                                                                                                                                } // TagCardSpeedPlus
  ,
  {
    "00B0A6A1C770", "", "", ""                                                                                                                                                                                } // TagCardSpeedMinus
  ,
};

boolean tagCardHome = false;
boolean tagCardR = false;
boolean tagCardL = false;
boolean tagCardZ = false;
boolean tagCardAusruhen = false;
boolean tagCardSD = false;
boolean tagCardOelspur = false;
boolean tagCardVirus = false;
boolean tagCardSpeedPlus = false;
boolean tagCardSpeedMinus = false;

boolean run360 = false;
boolean erstesMal = true;
int geschwindigkeit = 150; //100

char SDlastTagCard[] = "BBBBBBBBBBBB";
char nullNummer[] = "BBBBBBBBBBBB";

const int motor01AnschlussRechts = 5;
const int motor01AnschlussLinks = 6;
const int motor02AnschlussRechts = 10;
const int motor02AnschlussLinks = 11;

long vorherigeMillis = 0;
long timerOnOff = 1;
long Timer90Grad = 800; //310
long Timer180Grad = 2000; //800
long Timer360Grad = 3200; //1600
long Timer1080Grad = 4800; //4800
long TimerAusruhen = 3000; //3000
long TimerPause = 1000; // 1000

boolean roboEingeschaltet = false;
const int buttonPin = 7;
const int led01 = 8;
const int led02 = 4;
const int led03 = 12;
int buttonState = 0;
boolean loslassen = true;

void setup(){
  Serial.begin(9600);
  pinMode(motor01AnschlussLinks, OUTPUT);
  pinMode(motor01AnschlussRechts, OUTPUT);
  pinMode(motor02AnschlussLinks, OUTPUT);
  pinMode(motor02AnschlussRechts, OUTPUT);
  mySerial.begin(9600);
  pinMode(RFIDResetPin, OUTPUT);
  digitalWrite(RFIDResetPin, HIGH);
  pinMode(buttonPin, INPUT);
  pinMode(led01, OUTPUT);
  pinMode(led02, OUTPUT);
  pinMode(led03, OUTPUT);
}

//-----------------------------------------------------------------------------------
void loop(){
  onOff();
  if (roboEingeschaltet == true){
    RFiDreader();
    if (tagCardHome == true){
      roboHome();
    }
    else if (tagCardR == true){
      roboDrehungRechts();
    }
    else if (tagCardL == true){
      roboDrehungLinks();
    }
    else if (tagCardZ == true){
      roboDrehungZurueck();
    }
    else if (tagCardSD == true){
      roboSdCard();
    }
    else if (tagCardAusruhen == true){
      roboAusruhen();
    }
    else if (tagCardOelspur == true){
      roboOelspur();
    }
    else if (tagCardSpeedPlus == true){
      roboSpeedPlus();
    }
    else if (tagCardSpeedMinus == true){
      roboSpeedMinus();
    }
    else{
      roboVorwaerts();
    }
  }
  else{
    roboStillstand();
    for(int n=0; n TimerPause){
    erstesMal = true;
  }
  else{
    roboPause();
  }
}

void roboStillstand(){
  Serial.println("Robo stop");
  digitalWrite(motor01AnschlussLinks, LOW);
  digitalWrite(motor01AnschlussRechts, LOW);
  digitalWrite(motor02AnschlussLinks, LOW);
  digitalWrite(motor02AnschlussRechts, LOW);
}

void roboVorwaerts(){
  Serial.println("Robo vorwaerts");
  analogWrite(motor01AnschlussLinks, geschwindigkeit);
  analogWrite(motor01AnschlussRechts, LOW);
  analogWrite(motor02AnschlussLinks, geschwindigkeit);
  analogWrite(motor02AnschlussRechts, LOW);
}

void roboAusruhen(){
  Serial.println("robo ausruhen");
  if (erstesMal == true){
    erstesMal = false;
    vorherigeMillis = millis();
  }
  if(millis() - vorherigeMillis > TimerAusruhen){
    tagCardAusruhen = false;
    erstesMal = true;
    roboPause();
    TimerAusruhen = 3000;
    return;
  }
  digitalWrite(motor01AnschlussLinks, LOW);
  digitalWrite(motor01AnschlussRechts, LOW);
  digitalWrite(motor02AnschlussLinks, LOW);
  digitalWrite(motor02AnschlussRechts, LOW);
}

void roboHome(){
  Serial.println("Robo Home");
  if (erstesMal == true){
    erstesMal = false;
    vorherigeMillis = millis();
  }
  if(millis() - vorherigeMillis > Timer1080Grad){
    tagCardHome = false;
    erstesMal = true;
    roboPause();
    roboEingeschaltet = false;
    return;
  }
  digitalWrite(motor01AnschlussLinks, HIGH);
  digitalWrite(motor01AnschlussRechts, LOW);
  digitalWrite(motor02AnschlussLinks, LOW);
  digitalWrite(motor02AnschlussRechts, HIGH);
}

void roboDrehungRechts(){
  if (tagCardVirus == true){
    tagCardR = false;
    tagCardL = true;
    tagCardVirus = false;
  }
  else{
    Serial.println("Robo nach rechts");
    if (erstesMal == true){
      erstesMal = false;
      vorherigeMillis = millis();
    }
    if(millis() - vorherigeMillis > Timer90Grad){
      tagCardR = false;
      erstesMal = true;
      roboPause();
      return;
    }
    digitalWrite(motor01AnschlussLinks, HIGH);
    digitalWrite(motor01AnschlussRechts, LOW);
    digitalWrite(motor02AnschlussLinks, LOW);
    digitalWrite(motor02AnschlussRechts, HIGH);
  }
}

void roboDrehungLinks(){
  if (tagCardVirus == true){
    tagCardL = false;
    tagCardR = true;
    tagCardVirus = false;
  }
  else{
    Serial.println("Robo nach links");
    if (erstesMal == true){
      erstesMal = false;
      vorherigeMillis = millis();
    }
    if(millis() - vorherigeMillis > Timer90Grad){
      tagCardL = false;
      erstesMal = true;
      roboPause();
      return;
    }
    digitalWrite(motor01AnschlussLinks, LOW);
    digitalWrite(motor01AnschlussRechts, HIGH);
    digitalWrite(motor02AnschlussLinks, HIGH);
    digitalWrite(motor02AnschlussRechts, LOW);
  }
}

void roboDrehungZurueck(){
  if (tagCardVirus == true){
    tagCardZ = false;
    tagCardAusruhen = true;
    TimerAusruhen = 0;
    tagCardVirus = false;
  }
  else{
    Serial.println("Robo umkehren");
    if (erstesMal == true){
      erstesMal = false;
      vorherigeMillis = millis();
    }
    if(millis() - vorherigeMillis > Timer180Grad){
      tagCardZ = false;
      erstesMal = true;
      roboPause();
      return;
    }
    digitalWrite(motor01AnschlussLinks, HIGH);
    digitalWrite(motor01AnschlussRechts, LOW);
    digitalWrite(motor02AnschlussLinks, LOW);
    digitalWrite(motor02AnschlussRechts, HIGH);
  }
}

void roboOelspur(){
  Serial.println("Robo Zufallswert");
  if (run360 == true){
    robo360();
  }
  else{
    int _wuerfel = random(1,5);
    Serial.print("XXXX XXXXXXX xXXXXXX xXXXX xX   xXXXXXX  _wuerfel = ");
    Serial.println(_wuerfel);
    if (_wuerfel == 1){
      tagCardOelspur = false;
      tagCardR = true;
    }
    else if (_wuerfel == 2){
      tagCardOelspur = false;
      tagCardL = true;
    }
    else if (_wuerfel == 3){
      tagCardOelspur = false;
      tagCardZ = true;
    }
    else if (_wuerfel == 4){
      run360 = true;
    }
  }
}

void robo360(){
  Serial.println("Robo 360 Drehung");
  if (erstesMal == true){
    erstesMal = false;
    vorherigeMillis = millis();
  }
  if(millis() - vorherigeMillis > Timer360Grad){
    run360 = false;
    tagCardOelspur = false;
    erstesMal = true;
    roboPause();
    return;
  }
  digitalWrite(motor01AnschlussLinks, HIGH);
  digitalWrite(motor01AnschlussRechts, LOW);
  digitalWrite(motor02AnschlussLinks, LOW);
  digitalWrite(motor02AnschlussRechts, HIGH);
}

void roboSpeedPlus(){
  Serial.println("robo Speed Plus");
  geschwindigkeit = 150;
  TimerAusruhen = 0;
  if (erstesMal == true){
    erstesMal = false;
    vorherigeMillis = millis();
  }
  if(millis() - vorherigeMillis > TimerAusruhen){
    tagCardSpeedPlus = false;
    erstesMal = true;
    TimerAusruhen = 3000;
    roboPause();
    return;
  }
  digitalWrite(motor01AnschlussLinks, LOW);
  digitalWrite(motor01AnschlussRechts, LOW);
  digitalWrite(motor02AnschlussLinks, LOW);
  digitalWrite(motor02AnschlussRechts, LOW);
}

void roboSpeedMinus(){
  Serial.println("robo Speed Minus");
  geschwindigkeit = 75;
  TimerAusruhen = 0;
  if (erstesMal == true){
    erstesMal = false;
    vorherigeMillis = millis();
  }
  if(millis() - vorherigeMillis > TimerAusruhen){
    tagCardSpeedMinus = false;
    erstesMal = true;
    TimerAusruhen = 3000;
    roboPause();
    return;
  }
  digitalWrite(motor01AnschlussLinks, LOW);
  digitalWrite(motor01AnschlussRechts, LOW);
  digitalWrite(motor02AnschlussLinks, LOW);
  digitalWrite(motor02AnschlussRechts, LOW);
}

void roboSdCard(){
  Serial.println("Robo SD Setzen");
  tagCardSD = false;
  for(int i = 0; i    for(int j = 0; j < anzahlDerEintraege; j++){
      if(strcmp(SDlastTagCard, tagCards[i][j]) == 0){
        aktionAusfuehren(i);
      }
    }
  }
}

void RFiDreader() {

  char tagString[12];
  int index = 0;
  boolean reading = false;

  while(mySerial.available())
  {

    int readByte = mySerial.read(); // Nächstes Byte lesen

    if(readByte == 2) reading = true; //Indentifizierung für den Anfang des Tags
    if(readByte == 3) reading = false; //Indentifizierung für das Ende des Tags

    if(reading && readByte != 2 && readByte != 10 && readByte != 13)
    {
      tagString[index] = readByte; // Tag speichern
      index ++;
    }
  }

  if(tagString[0] != 0)
  {
    Serial.print("tagString = ");
    Serial.println(tagString);
    for(int i = 0; i      for(int j = 0; j < anzahlDerEintraege; j++) // Check Eintrag nach Tag-Nummer
      {
        if(strcmp(tagString, lastTagCard) != 0) //Neue Tag-Nummer?
        {
          if(strcmp(tagString, tagCards[i][j]) == 0) //Die neue Nummer hat welche Aktion?
          {
            for(int m=0; m            {
              SDlastTagCard[m] = lastTagCard[m];
            }
            for(int k=0; k            {
              lastTagCard[k] = tagString[k];
            }
            roboPause();
            aktionAusfuehren(i); //Aktion starten
            break;
          }
        }
      }
    }
  }
  memset(tagString,0,strlen(tagString)); //Tag freigeben (mit NULL überschreiben)
  resetReader(); //Den RFiD Reader resetten
}

void resetReader() { // Reset Funktion
  digitalWrite(RFIDResetPin, LOW);
  digitalWrite(RFIDResetPin, HIGH);
  delay(150);
}

void aktionAusfuehren(int aktionsNummer) {
  switch(aktionsNummer)
  {
  case 0:
    tagCardHome = true;
    break;
  case 1:
    tagCardR = true;
    break;
  case 2:
    tagCardL = true;
    break;
  case 3:
    tagCardZ = true;
    break;
  case 4:
    tagCardAusruhen = true;
    break;
  case 5:
    tagCardSD = true;
    break;
  case 6:
    tagCardOelspur = true;
    break;
  case 7:
    tagCardVirus = true;
    break;
  case 8:
    tagCardSpeedPlus = true;
    break;
  case 9:
    tagCardSpeedMinus = true;
    break;
  default:
    break;
  }
}

void onOff() {
  buttonState = digitalRead(buttonPin);
  Serial.print("buttonState = ");
  Serial.println(buttonState);
  if (buttonState == LOW){
    loslassen = true;
  }
  else if (buttonState == HIGH && loslassen == true){
    roboEingeschaltet = !roboEingeschaltet;
    loslassen = false;
    ledEins();
  }
}

void ledEins() {
  if (roboEingeschaltet == true) {
    digitalWrite(led01, HIGH);
    digitalWrite(led02, HIGH);
    digitalWrite(led03, HIGH);
  }
  else {
    digitalWrite(led01, LOW);
    digitalWrite(led02, LOW);
    digitalWrite(led03, LOW);
  }
}
3. Erstellen der Roll E Aussenhülle und der Tag Icons in Illustrator. 4. Laser Cutter Nutzung in der Werkstatt. 5. Kleben und bemalen der Roll E Abdeckung 6. Fertigstellung der Tag Cards 7. Kalibrieren der Fahrwerte von Roll E  

Post Mortem

Projekt Lost In Space stellte sich bei weitem komplexer und umfangreicher dar als erwartet. Gerade die Erweiterung der eigenen Programmierung durch ein selbst konstruiertes, physisches Objekt erschwert die Fehlersuche oder Lösungsumsetzung um ein vielfaches. Das Verhältnis der Motorendrehzahl zu Drehmoment, drittes Stabilisationsrad und Spannungsabfall am RFiD Reader waren nur einige der zeitfressenden und unerwarteten Fehlerquellen. Auch das Arduino einige Spracheigenheiten gegenüber Processing aufweist machte die Sache nicht gerade einfacher. Ohne regelmässigen Input und Hilfestellung des Dozenten (Moritz Kemper) wäre die Umsetzung des Projekts in diesem Umfang unmöglich gewesen.