IFD:GrundlagenElektronik2011/Project/Martin/Dokumentation

From Medien Wiki

Dokumentation | Martin | aRobot

Idee

Grundlage des Projekts war die Erstellung einer Roboterbasis, die es mir ermöglicht, verschiedene Sensoren für die Umfeldwahrnehmung und autonome Fortbewegung eines Rotobers zu testen. Im Rahmen der Veranstaltung wollte ich daher eine erste Variante implementieren. Um erste Erfahrungen zu sammeln, sollte ein Sensor eingesetzt werden, der mit einfachen Mitteln zu bauen ist und über die Programmierung gut gesteuert werden kann. Daher entschied ich mich für einen Linefollowing-Sensor basierend auf IR-LEDs und Phototransistoren.


Ablauf

Als Teil der Kettenreaktion erhielt der Roboter ein Piezo-Element, mit dem Druck gemessen werden kann. Gestartet wird der Roboter durch die Holzeisenbahn von Julia. Anschließend folgt er einer geschwungen Linie, an dessen Ende eine Wippe angebracht ist. Durch das Entlangfahren auf der Linie wird die Wippe ausgelöst, wodurch das Würstchen von Sebastian angehoben wird und die Musik startet.


Funktionsbeschreibung

Der Sensor besteht aus drei Bausteinpaaren, die jeweils aus einem IR-Phototransistor und einer IR-LED zusammengesetzt sind. Der Sensor wird knapp über dem Boden angebracht. Die IR-LEDs dienen als Lichtquelle und beleuchten die unmittelbare Umgebung. Je nach Oberflächenbeschaffenheit empfangen die IR-Phototransistoren das ausgesandte Licht und lassen dadurch mehr oder weniger Strom fließen. Mit einem 1 Kilo-Ohm Widerstand in Reihe und einem Abgriff zwischen beiden Elementen dient das Konstrukt als Spannungsteiler. Über jeweils einen analogen Port am Arduino kann dann für jedes Bausteinpaar die aktuelle Helligkeit ausgelesen werden.

Befindet sich nun eine schwarze Linie unter einem der Sensorelemente, verringert sich das zurückgestrahlte Licht signifikant gegenüber dem hellem Untergrund. Auf diese Weise kann die Linie detektiert werden. Je nachdem, welcher Sensor die Linie erkennt, werden die Motoren unterschiedlich angesprochen. Befindet sich die Linie unter dem mittleren Sensor, kann der Roboter mit konstanter Geschwindigkeit geradeaus fahren. Ist die Linie unter dem linken Sensor, folgt eine Linkskurve. Durch Anhalten der linken Kette folgt der Roboter dieser Kurve, bis sich die Linie wieder in der Mitte befindet. Für eine Rechtskurve verhält sich die Steuerung der Motoren analog mit der rechten Kette. Um nicht zu früh wieder gerade aus zu fahren, wurde eine Schwellwerthysterese implementiert, die einen niedrigen Schwellwert für die Fahrtrichtungsänderung und einen hohen Schwellwert für die Freigabe der Änderung beinhaltet.

Über ein Potentiometer an einem zusätzlichen analogen Eingangspin kann der Schwellwertbereich verschoben werden. So ist eine Anpassung an die äußeren Lichtverhältnisse möglich.

Die Ansteuerung des Motors erfolgt über einen Motortreiber. Dieser ermöglicht die Steuerung der Richtung, sowie der Geschwindigkeit von zwei DC-Motoren.

aRobot Schaltplan


Code


// init Motor Pins
int MOT_LEFT_SPEED_PIN = 5;
int MOT_RIGHT_SPEED_PIN = 6;

int MOT_LEFT_FW_PIN = 7;
int MOT_LEFT_RW_PIN = 8;

int MOT_RIGHT_FW_PIN = 9;
int MOT_RIGHT_RW_PIN = 10;

// init Line Sensor Pins
int LINE_FOLLOW_LEFT = A0;
int LINE_FOLLOW_MIDDLE = A1;
int LINE_FOLLOW_RIGHT = A2;

// init Poti Pin
int THRESHOLD_PIN = A5;

// init global variables
int global_engine_speed = 160;
int line_threshold_low = 120;
int line_threshold_high = 200;

int left = 1024;
int right = 1024;
int middle = 1024;

boolean go_left = false;
boolean go_straight = true;
boolean go_right = false;

boolean start = false;
int piezo = 0;
int last_piezo = 0;

//check all 3 Sensors, if Line is underneath them
void checkLine()
{
  while(go_straight)
  {
    analogWrite(MOT_LEFT_SPEED_PIN, global_engine_speed);
    analogWrite(MOT_RIGHT_SPEED_PIN, global_engine_speed);
    
    left = analogRead(LINE_FOLLOW_LEFT);
    middle = analogRead(LINE_FOLLOW_MIDDLE);
    right = analogRead(LINE_FOLLOW_RIGHT);
    
    if(left < line_threshold_low && middle > line_threshold_high)
    {
      go_left = true;
      go_straight = false;
    }
    else if(right < line_threshold_low && middle > line_threshold_high)
    {
      go_right = true;
      go_straight = false;
    }
  }
  
  while(go_left)
  {
    analogWrite(MOT_LEFT_SPEED_PIN, 0);
    analogWrite(MOT_RIGHT_SPEED_PIN, global_engine_speed);
    
    left = analogRead(LINE_FOLLOW_LEFT);
    middle = analogRead(LINE_FOLLOW_MIDDLE);
    right = analogRead(LINE_FOLLOW_RIGHT);
    
    if(middle < line_threshold_low && left > line_threshold_high)
    {
      go_straight = true;
      go_left = false;
    }
  }
  
  while(go_right)
  {
    analogWrite(MOT_LEFT_SPEED_PIN, global_engine_speed);
    analogWrite(MOT_RIGHT_SPEED_PIN, 0);
    
    left = analogRead(LINE_FOLLOW_LEFT);
    middle = analogRead(LINE_FOLLOW_MIDDLE);
    right = analogRead(LINE_FOLLOW_RIGHT);
    
    if(middle < line_threshold_low && right > line_threshold_high)
    {
      go_straight = true;
      go_right = false;
    }
  }
}


void setup()
{
  pinMode(MOT_LEFT_SPEED_PIN, OUTPUT);
  pinMode(MOT_RIGHT_SPEED_PIN, OUTPUT); 
  
  pinMode(MOT_LEFT_FW_PIN, OUTPUT); 
  pinMode(MOT_LEFT_RW_PIN, OUTPUT); 
  
  pinMode(MOT_RIGHT_FW_PIN, OUTPUT); 
  pinMode(MOT_RIGHT_RW_PIN, OUTPUT); 
  
  // initial forward
  digitalWrite(MOT_LEFT_RW_PIN, LOW);
  digitalWrite(MOT_RIGHT_RW_PIN, LOW);
  
  digitalWrite(MOT_LEFT_FW_PIN, HIGH);
  digitalWrite(MOT_RIGHT_FW_PIN, HIGH);
}

void loop()
{
  line_threshold_high = analogRead(THRESHOLD_PIN);
  line_threshold_low = line_threshold_high - 80;
  
  piezo = analogRead(A4);
  last_piezo = piezo;
  
  // wait until piezo senses some force
  while(!start)
  {
    piezo = analogRead(A4);
    if(abs(last_piezo - piezo) > 20)
    {
      start = true;
    }
    last_piezo = piezo;
  }

  checkLine();
}