Seiten

Montag, 30. März 2015

Getting Started: Line Follower mit Arduino


Line Follower mit Arduino

Bei dieser Übung erfahren Sie, wie Sie einen einfachen "Line Follower" bauen und programmieren können.

Verwendete Bauteile:

Batterien
Schrauben, Muttern



Aufbau des Magician Chassis:














Bauen Sie das Chassis nach beiliegender Schritt-für-Schritt Anleitung auf.

Vorbereitung Motordriver:
Brechen Sie 2x8 Pin´s von der Stiftleiste ab und löten Sie diese in das Breakoutboard des Motordrivers.















Line Sensoren:
Brechen Sie 2x3 Pin´s von der Stiftleiste ab und löten Sie diese jeweils in die Line Sensoren. Die Anschlüsse der Stiftleiste sollen dabei auf die gegenüberliegende Seite des Sensors zeigen.















Nehmen Sie nun eine beiliegende Schraube M3 x 45mm und stecken Sie den Line Sensor darauf. Der Schraubenkopf muss auf der gleichen Seite sein, wie der Sensor. Dann kommt eine Mutter drauf. Ziehen Sie diese dann fest, so dass der Sensor eingeklemmt wird. Seien Sie aber vorsichtig, so dass der Sensor nicht beschädigt wird. Jetzt können Sie drei Drahtbügel auf den Sensor aufstecken (GND schwarz, VCC rot, OUT gelb). Die Schraube mit dem Sensor wird nun am Chassis befestigt. Der ideale Abstand des Sensors zum Boden beträgt 3mm.
Wiederholen Sie das für den 2. Sensor.















Montage Breadboard:
Das kleine Breadboard kann mit dem doppelseitigen Klebeband am Chassis befestigt werden. Der Motortreiber wird nun auf das Breadboard aufgesteckt.


Montage Arduino:
Der Arduino kann mit kleinen Schrauben am Chassis befestigt werden.

Verkabelung:
Verbinden Sie die Bauteile mit den Drahtbügeln nach folgendem Schaltplan:

Motor Driver:
PWM A-> Arduino Pin3
AIN2 -> Arduino Pin8
AIN1 -> Arduino Pin9
STBY -> Arduino Pin12
BIN1 -> Arduino Pin11
BIN2 -> Arduino Pin7
PWMB-> Arduino Pin5
GND -> GND

VM -> Arduino Vin
VCC -> 5V
A01-> Rechter Motor - (schwarz)
A02 -> Rechter Motor + (rot)
B02 -> Linker Motor + (rot)
B01 -> Linker Motoer - (schwarz)


Linker Line Sensor:
VCC -> 5V
OUT -> Arduino Pin4
GND -> GND

Rechter Line Sensor:
VCC -> 5V
OUT-> Arduino Pin2
GND -> GND















Das Prinzip des Line Followers:
Die beiden Sensoren  senden ein Infrarot-Licht aus, das je nach Untergrund (hell - Boden / dunkel - Linie) wird unterschiedlich viel Licht reflektiert. Dies ergibt unterschiedliche Werte für den Arduino.
Die beiden Motoren sind unterschiedlich ansteuerbar. 
Je nach Stellung des Sensors zur Linie kann sich ein Motor nach vorne drehen, still stehen oder zurück drehen. In Kombination mit dem 2. Motor gibt es 


Programmstruktur:
Es werden zuerst die Sensoren ausgelesen
Je nach Sensorwerten werden die Motoren unterschiedlich angesteuert

Zur Übersichtlichkeit werden die unterschiedlichen Zustände in Funktionen programmiert und dann individuell aufgerufen.

Diese Funktion lässt mit der Motorgeschwindigkeit s beide Motoren vorwärts drehen:
int moveforward(int s){
  digitalWrite(out_A_in_1,LOW);
  digitalWrite(out_A_in_2,HIGH);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,LOW);
  digitalWrite(out_B_in_2,HIGH);
  analogWrite(out_B_pwm,s);
}

Diese Funktion lässt mit der Motorgeschwindigkeit s beide Motoren rückwärts drehen
int movebackward(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}

Diese Funktion lässt mit der Motorgeschwindigkeit s den linken Motor vorwärts drehen und den rechten still stehen (leichte Kurve vorwärts, rechts)
int moveforwardright(int s){
  digitalWrite(out_A_in_1,LOW);
  digitalWrite(out_A_in_2,HIGH);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,LOW);
  digitalWrite(out_B_in_2,HIGH);
  analogWrite(out_B_pwm,0);
}


Diese Funktion lässt mit der Motorgeschwindigkeit s den rechten Motor vorwärts drehen und den linken still stehen (leichte Kurve rückwärts, rechts)
int moveforwardleft(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,0);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}



Diese Funktion lässt mit der Motorgeschwindigkeit s den rechten Motor vorwärts drehen und den linken rückwärts drehen (Auf der Stelle drehen, rechtsrum)
int movebackright(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,0);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}


Diese Funktion lässt mit der Motorgeschwindigkeit s den linken Motor vorwärts drehen und den rechten rückwärts drehen (Auf der Stelle drehen, linksrum)
int movebackleft(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,0);
}


Beispielprogramm:
Kopieren Sie dieses Beispiel in Ihre Arduino IDE und laden Sie es hoch und schon folgt Ihr Roboter der Linie.

/* Line Follower von www.physicalcomputing.at
by Benny, 2012
*/

// Pin Belegung

int QD1_Pin = 2;
int QD2_Pin = 4;
int out_A_pwm = 3;
int out_B_pwm = 5;
int out_A_in_1 = 9;
int out_A_in_2 = 8;
int out_B_in_1 = 11;
int out_B_in_2 = 7;
int out_stby = 12;


// Initialisierung der Pins und der Seriellen Schnittstelle

void setup(){

  Serial.begin(9600);
  pinMode(out_A_pwm,OUTPUT);
  pinMode(out_A_in_1,OUTPUT);
  pinMode(out_A_in_2,OUTPUT);
  pinMode(out_B_pwm,OUTPUT);
  pinMode(out_B_in_1,OUTPUT);
  pinMode(out_B_in_2,OUTPUT);
  pinMode(out_stby,OUTPUT);
  digitalWrite(out_stby,HIGH);
}

void loop(){
  // Lesen der Sensorwerte
  int QRE_Value = readqd1();
  int QRE_Value2 = readqd2();
  // Setzen der Motorstärke, je nach Volt und Schwierigkeit
  // des Terrains anpassen
  int motorst = 110;

  // Falls beide Sensoren schwarzen Untergrund liefern geradeaus
  // fahren

  if(QRE_Value > 3000 && QRE_Value2 > 3000)
  {
    moveforward(motorst);
  }

  // Falls beide Sensoren keinen schwarzen Untergrund liefern
  // anhalten und entscheiden welcher Sensor den dunkleren //Untergrund liefert, je nachdem eine Drehung mit Intervall
  // von 100 in die jeweilige Richtung.

  if(QRE_Value < 1000 && QRE_Value2 < 1000)
  {
    stopmove(); // Überarbeiten
    if(QRE_Value>QRE_Value2){
      moveforwsharpright(motorst);
      delay(100);
    }

    if(QRE_Value<QRE_Value2){
      moveforwsharpleft(motorst);
      delay(100);
    }
  }

  // Falls Sensor QD1 von dem schwarzen Untergrund stark //abweicht aber QD2 nicht, eine starke Drehung nach rechts.

  if(QRE_Value < 2500 && QRE_Value2 > 3000)
  {
    moveforwsharpright(motorst);
  }

  // Falls Sensor QD2 von dem schwarzen Untergrund stark
  // abweicht aber QD1 nicht, eine starke Drehung nach links.

  if(QRE_Value2 < 2500 && QRE_Value > 3000)
  {
    moveforwsharpleft(motorst);
  }

  // Falls Sensor QD1 schwarzen Untergrund meldet, QD2 aber
  // einen leichten Abfall des Wertes liefert, eine leichte links
  // Drehung.

  if(QRE_Value > 3000 && QRE_Value2 < 3000 && QRE_Value2 > 2500)
  {
    moveforwardleft(motorst);
  }

  // Falls Sensor QD2 schwarzen Untergrund meldet, QD1 aber
  // einen leichten Abfall des Wertes liefert, eine leichte rechts
  // Drehung.

  if(QRE_Value2 > 3000 && QRE_Value < 3000 && QRE_Value > 2500)
  {
    moveforwardright(motorst);
  }

  // Ausgabe der beiden Sensoren Werte auf dem Seriellen
  // Monitor

  Serial.print("1:");
  Serial.print(QRE_Value);
  Serial.print("2:");
  Serial.print(QRE_Value2);
}

// Die oben erklärten Funktionen

int readqd1(){
  pinMode(QD1_Pin,OUTPUT);
  digitalWrite(QD1_Pin,OUTPUT);
  delayMicroseconds(10);
  pinMode(QD1_Pin,INPUT);
  long time = micros();
  while(digitalRead(QD1_Pin) == HIGH && micros() - time < 3000);
  int diff = micros() - time;
  return diff;
}

int readqd2(){
  pinMode(QD2_Pin,OUTPUT);
  digitalWrite(QD2_Pin,OUTPUT);
  delayMicroseconds(10);
  pinMode(QD2_Pin,INPUT);
  long time = micros();
  while(digitalRead(QD2_Pin) == HIGH && micros() - time < 3000);
  int diff = micros() - time;
  return diff;
}

int moveforward(int s){
  digitalWrite(out_A_in_1,LOW);
  digitalWrite(out_A_in_2,HIGH);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,LOW);
  digitalWrite(out_B_in_2,HIGH);
  analogWrite(out_B_pwm,s);
}
int movebackward(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}
int moveforwardright(int s){
  digitalWrite(out_A_in_1,LOW);
  digitalWrite(out_A_in_2,HIGH);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,LOW);
  digitalWrite(out_B_in_2,HIGH);
  analogWrite(out_B_pwm,0);
}
int moveforwardleft(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,0);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}


int movebackright(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,0);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}

int movebackleft(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,0);
}

int moveforwsharpright(int s){
  digitalWrite(out_A_in_1,LOW);
  digitalWrite(out_A_in_2,HIGH);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,HIGH);
  digitalWrite(out_B_in_2,LOW);
  analogWrite(out_B_pwm,s);
}

int moveforwsharpleft(int s){
  digitalWrite(out_A_in_1,HIGH);
  digitalWrite(out_A_in_2,LOW);
  analogWrite(out_A_pwm,s);
  digitalWrite(out_B_in_1,LOW);
  digitalWrite(out_B_in_2,HIGH);
  analogWrite(out_B_pwm,s);
}
int stopmove(){
  int moveforwardright(int s);
  digitalWrite(out_A_in_1,LOW);
  digitalWrite(out_A_in_2,HIGH);
  analogWrite(out_A_pwm,0);
  digitalWrite(out_B_in_1,LOW);
  digitalWrite(out_B_in_2,HIGH);
  analogWrite(out_B_pwm,0);
}

Viel Spass bei der Umsetzung des Projektes.
Dies ist ein Beispielcode, der jederzeit gerne verbessert werden kann.


erstellt 31.5.2012




Keine Kommentare:

Kommentar veröffentlichen

Hinweis: Nur ein Mitglied dieses Blogs kann Kommentare posten.