Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektesose2016:schrottbot:dokumentation

Dies ist eine alte Version des Dokuments!




Dokumentation

Einleitung

Unsere erste Idee, war es einen Roboter zu bauen, der Müll erkennt und diesen einsammelt. Dieses kam durch den Film Wall-E zustande. Einen Roboter zu haben, der Müll einsammelt erschien uns als sehr praktisch und sinnvoll, weil man diesen in Parks verwenden könnte und dieser der Umwelt helfen könnte. Es hat sich jedoch herausgestellt, dass diese Idee nicht leicht umsetzbar ist. Wir mussten diese Idee somit leider verwerfen und etwas ändern. Die Fähigkeit Müll zu erkennen ist für einen Roboter wesentlich schwieriger als für einen Menschen, weil Müll aus allen verschiedenen Gegenständen bestehen kann. Deshalb haben wir uns darauf beschränkt, dass unser Roboter metallene Gegenstände aufspüren und aufsammeln sollte. Da man Metall mit einem Metalldetektor aufspüren und mit einem Magneten diese aufsammeln kann, erschien uns diese Variante besser umsetzbar als einen Roboter der Müll erkennt und aufsammelt. Unser Interesse liegt hierbei beim Fahren und dem Sammelmechanismus des Roboters.

Aufbau

Das Grundgerüst vom SchrottBot besteht aus einer runden Holzplatte. Darauf befinden sich drei Entfernungsmesser, ein Servo, ein Auffangbehälter, ein Breadboard mit einem Arduino und einem Akkumulator. Auf der Unterseite der Grundplatte sind die Motoren, die Räder und ein Stützrad angebracht. Am Servo ist eine Stange mit einem Elektromagneten befestigt. Die Entfernungsmesser sind vorne platziert, einer etwas rechts, einer etwas links und der dritte in der Mitte. Under dem mittleren Entfernungsmesser hängt der Metalldetektor. Sowohl der Elektromagnet als auch der Metalldetektor hängen knapp über dem Boden, damit sie metallene Gegenstände finden und einsammeln können. Hauptsächlich haben wir Teile von alten Roboterprojekten benutzt.

Fahrwerk: Schrittmotoren

Zur Fortbewegung unseres Roboters haben wir Steppenmotoren verwendet und mit Microsteps gearbeitet.

Kommentar Felix:

Gibt es daztu sonst noch etwas zu sagen?

Sammelmechanismus: Servo und Elektromagnet

Für das Einsammeln metallener Gegenstände haben wir einen Elektromagneten an eine Stange befestigt und diese wiederrum an einen Servo. Unsere Anfangsidee jedoch war eine Art Schienensystem, welches den metallenen Gegenstand einsammelt, zurückfährt und in den Auffangbehälter fallen lässt. Diese Idee verwarfen wir jedoch, da die Konstruktion mit einem Schienensystem uns doch kompliziert erschien. Unsere neue Idee war dann ein Kransystem, welches das metallene Gegenstände einsammelt, sich um 180° dreht und dieses in den Behälter fallen lässt. Durch einen Servo, war die neue Idee einfacher umsetzbar als ein Schienensystem.

Wegfindung

Unser Roboter hat nur eine sehr simple Wegfindung. Er fährt eine bestimmte, in einer Variable festgelegte Strecke geradeaus und sucht und sammelt dabei Metall. Wichtig hierbei ist, das der Roboter nur eine Bewegung forwärts zählt und somit immer die gleiche Strecke von aktuell 40cm vorwärts fährt. Programmdurchläufe, bei denen der Roboter Metall einsammelt oder sich anderweitig auf das Metall ausrichtet werden nicht als Vorwärtsbewegung gezählt. Nachdem er die vordefinierte Strecke von 40cm gefahren ist macht der Roboter eine linksdrehung um 90°. Anschließenend fährt er 2cm forwärts und macht eine erneute Linksdrehung um 90°. Danach fährt der Roboter wieder 40cm und machte dann eine Rechtsdrehung um 90°, fährt 2cm vorwärts und machte eine erneute Rechtdrehung um 90°. Ab diesem Punkt wird das Programm endlos wiederholt. Wichtig dabei zu beachten ist, das der Roboter nur auf den langen und kurzen geraden Metall finden kann, nicht in den Drehungen.

Programmierung: Elektronik

Für die Programmierung haben wir einen Arduino Nano benutzt, da wir den Servo ansteuern wollen und außerdem schon im Kurs damit gearbeitet haben.

Sensorik: Entfernungsmesser

Zum Ausweichen benutzen wir drei Entfernungsmesser. Falls der Roboter zu nah an ein Hindernis fährt soll dieser nach rechts oder gegebenfalls links ausweichen.

Metalldetektor:

Der Metalldetektor war einer der herausforderndsten Komponenten unseres Roboters und wir haben viel Anleitung und Hilfe gebraucht um den Metalldetektor am Ende zum laufen zu Bringen. Im Grundprinzip ist unser Metalldetektor ein elektromagnetischer Schwingkreis mit einer Spule und einem Kondensator. Dieser Schwingkreis wird durch ein Signal vom Aduino angestoßen und der Aduino zählt anschließend die CPU-Cyclen des Aduino während zehn Schwingungen. Befindet sich ein Gegenstand aus Metall in der nähe der Spule (welche wird aufgrund dessen vorne am Roboter, kurz über dem Boden anbringen mussten) so Verändert sich deren Induktivität der Spule und damit die Anzahl an CPU-Cyclen während der 10 Schwingungen. Diesen Unterschied kann man nun auswerten und eine Aussage darüber treffen, ob sich ein metallener Gegenstand in der Nähe der Spule befindet.

Beispielwerte: CPU-Cyclen ohne Metall: ca. 169000 CPU-Cyclen mit Metall: ca. 171000

Bei den ersten Versuchen mit dem Metalldetektor, damals noch eine Improvisierte Drahtrolle, ergab sich aber schnell ein neues Problem: Der Unterschied in CPU-Cyclen war anfangs kaum messbar und selbst bei unmittelbarer Nähe des Metalls zu Spule einfach zu gering. Deshalb mussten wir den Umweg über einen Comperator nehmen. Dieser macht macht ledigtlich Schwingungen mit sehr kleiner Amplitude für den Arduino einfacher messbar.

Kommentar Felix:

Der Comparator beeinflusst nicht die Resonsnzfrequenz des Schwingkreises (und damit auch nicht den Unterschied zwischen „Metall“ und „kein Metall“) - er macht ledigtlich Schwingungen mit sehr kleiner Amplitude für den Arduino einfacher messbar!

Die finale Spule die wir dann in unserem Roboter verbaut haben erforderte auch einige Anpassungen. Zwar sind Unterschiede zwischen Metall und nicht-Metall Messungen klarer Erkennbar aber aufgrund des großen Innenwiederstandes der Spule flaut diese Schwingung noch noch schneller ab als zuvor. Glücklicherweise lässt sich trotzdem mit der Spule arbeiten, wir haben einfach die Anzahl der Schwingungen über die der Aduino die CPU-Cyclen zählt von 50 auf 10 verringert.

Auf dieser Abbildung erkennt man eine Messung unseres Metalldetektors visualisiert an einem Oszilloskop. Die dunkelblaue Linie ist das Signal vom Aduino, welches zu beginn der Schwingung von 5V auf 0V geschaltet wird. Die hellblaue Linie ist die durch das vom Aduino kommende Signal angeregte Schwingung, welche relativ schnell abflaut. Die gelbe Linie hingegen ist der Output des Comperators – eine gut auswertbare und stabile Rechteckspannung.

Diese Abbildung zeigt den Unterschied zwischen Messungen mit Metall neben der Spule und ohne. Wie man sieht sind die Werte erfreulich weit auseinander und somit leicht auszuwerten und im Programm zu trennen.

Diese Abbildung zeigt unseren ursprünglichen Testaufbau mit der improvisierten Spule.

fastpulseinicr.zip

Das ist das Testprogramm um die Spule zu testen.

Abschätzung des Aufwandes:

Das Bauen der Grundkonstruktion sollte wenig aufwendig sein, da wir die Grundplatte mit vorhandenen Aussparungen für die Räder von älteren Robotern verwenden können. Das Fahren schätzen wir auch eher als einfach ein, wohingegen wir das Bauen eines Metalldetektors als komplizierter sehen, da wir damit keine Erfahrung haben und den Aufwand somit nicht abschätzen können. Das Ansteuern des Magneten wird kaum Zeit in Anspruch nehmen, da wir nur einen Pin auf HIGH oder LOW setzen müssen.

Im Nachhinein mussten wir feststellen, dass das Ansteuern der Räder aufgrund verschiedener Probleme am aufwendigsten war.

Probleme & Fehleranalyse:

Unser größtes Problem hatten wir leider mit kaputten Bauteilen. So hatten wir kaputte Entfernungsmesser, ein kaputtes Rad und ein kaputtes Breadboard. Da wir den Fehler zuerst in der Schaltung und der Programmierung suchten, haben uns diese viel Zeit gekostet.

Ein weiteres Problem stellen die Entfernungsmesser dar, da sie nur Abstände zu geraden Objekten messen können. Würde der Roboter schräg auf eine Wand zufahren, so würde er diese nicht erkennen. Um dieses Problem zu umgehen, haben wir zusätzlich zu dem gerade ausgerichteten Entfernungsmesser noch zwei weitere angebracht, die nach schräg links und rechts ausgerichtet sind.

Konstruktion und Aufbau:

Schaltung:

Pinbelegung:

Da wir für unsere Schaltung mehr digitale Pins benötigen, als der Arduino hat, mussten wir zwei analoge Pins umfunktionieren, was glücklicherweise sehr einfach ist. Hierzu wird der Pin einfach mit einem „A“ versehen.

const int Pin          = 3; // digitaler Pin 3
 
const int Pin          = A3; // analoger Pin A3 als digitaler Pin
Pinnummer Name im Programm Funktion
13 magnetPin Elektromagnet
2 directionRight rechtes Rad
3 fahrenRight rechtes Rad
4 directionLeft linkes Rad
5 fahrenLeft linkes Rad
6 servoPin Servo
7 rechtsEcho Entfernungsmesser
8 inputCapturePin Metalldetektor
9 mitteTrigger Entfernungsmesser
10 mitteEcho Entfernungsmesser
11 linksTrigger Entfernungsmesser
12 linksEcho Entfernungsmesser
A1 outPin Metalldetektor
A3 rechtsTrigger Entfernungsmesser

Code:

// Unser Roboter Schrottbot soll selbstständig durch einen Raum fahren
// Dabei soll er mithilfe eines Metalldetektors metallene Gegenstände auf dem Boden finden und diese mit einem Elektromagneten aufsammeln und in einen Auffangbehäter fallen lassen.
 
#include <Servo.h>
#include "inputCaptureBlocking.h"
 
Servo myservo;
 
// Pin_Belegung Servo
const int servoPin = 6;
 
 
// Werte des Metalldetektors
const int inputCapturePin = 8;     // Digital-Pin 8 ist mit der hardware des Aduino Nano verbunden und muss deswegen zwingend verwendet werden
const int outPin          = A1;     // Gibt das Signal an, das den Schwingkreis anstößt
unsigned long curPulseLength = 0;   // Variable zum Speichern der Anzahl der Schwingungen des Schwingkreises
unsigned long wert = 0;             // Variblae für Bilden von einem Mittelwert von curPulseLength
 
 
// Variablen fürs Durchzählen von Schleifen
int zahl = 0;
int l = 0;
 
 
// Festlegung der Pins für die Ansteurung der Räder
const int fahrenRight = 3;
const int directionRight = 2;
 
const int fahrenLeft = 5;
const int directionLeft = 4;
 
 
// Variablen für die Entfernungsmessungen
long laenge;
long abstandLinks;
long abstandMitte;
long abstandRechts;
 
 
// Pin-Belegung für die Entfernungsmesser
const int linksEcho = 12;
const int linksTrigger = 11;
 
const int mitteEcho = 10;
const int mitteTrigger = 9;
 
const int rechtsEcho = 7;
const int rechtsTrigger = A3;
 
 
// Elektromagnet Pin
const int magnetPin = 13;
 
 
 
void setup() {
 
  delay(500);
 
  // Pins für den ersten Entfernungsmesser (links in Fahrtrichtung)
  pinMode(linksTrigger, OUTPUT); //Trigger-Pin als Output definieren
  pinMode(linksEcho, INPUT); // Echo als Input defnieren
 
  // Pins für den zweiten Entfernungsmesser (mittig in Fahrtrichtung)
  pinMode(mitteTrigger, OUTPUT); //Trig-PIn als Output definieren
  pinMode(mitteEcho, INPUT); // Echo als Input defnieren
 
  // Pins für den dritten Entfernungsmesser (rechts in Fahrtrichtung)
  pinMode(rechtsTrigger, OUTPUT); //Trig-PIn als Output definieren
  pinMode(rechtsEcho, INPUT); // Echo als Input defnieren
 
  // Serielle kommunikation für Anzeige der Abstände
  Serial.begin(115200);
 
  // Festlegung der Pins für die Räder
  pinMode(fahrenRight, OUTPUT);
  pinMode(directionRight, OUTPUT);
 
  pinMode(fahrenLeft, OUTPUT);
  pinMode(directionLeft, OUTPUT);
 
  // Metalldetektor
  pinMode(outPin, OUTPUT);
  pinMode(inputCapturePin, INPUT);
  myservo.attach(6, 800, 2100);
}
 
 
//Hauptprogramm: Der Roboter fährt eine Zick-Zacklinie mit festgelegter Länge in eine Richtung des Raumes um alles Metall im Raum zu finden und aufzusammeln
void loop() {
  lang();             //fährt eine lange Strecke geradeaus
  linksdreh();        //macht eine Linksdrehung um 90°
  kurz();             //fährt eine kurze Strecke geradeaus
  linksdreh();
  lang();
  rechtsdreh();       //macht eine Rechtsdrehung um 90°
  kurz();
  rechtsdreh();
}
 
 
//Früheres Hauptprogramm, nun in eine Funktion ausgelagert um die Verschiedenne Bewegungen im neuen Hauptprogramm zu ermöglichen
void lang() {
  for (int t = 0; t < 1112;) {                //führt das Programm 1112 mal aus (dieser Zähler wird nur erhöht wenn der Roboter geradeaus fährt, nicht wenn er Metall einsammlet oder Rückwärts fährt). 1112 Steps vorwärts = 40cm.
    wert = 0;                                 //setzt wert auf 0
    finden();                                 //führt die Funktion finden aus
    for (int m = 0; m < 10; m++) {            //bildet aus 10 Messungen mit dem Wert "curPulseLength" den Mittelwert "wert"
      wert = wert + curPulseLength;
    }
    wert = wert / 10;
    if (wert > 169700) {                      //wenn der Mittelwert "wert" einen bestimmten Mindestwert überschreitet, so wird das aus "Metall gefunden" gezählt. Die Anzahl an Durchläufen mit gefunden Metall wird in der Variable "Zahl" gespeichert.
      zahl++;
    }
    if (zahl < 10) {                          //wenn der Roboter weniger als 10 mal Metall gefunden hat fährt er einfach geradeaus und erhöht den Zähler der Anfänglichen for-Schleife
      linksFahren();                          //dreht das linke Rad
      rechtsFahren();                         //dreht das rechte Rad
      t++;
    }
    else {                                    //sobald 10 mal Metall gefunden wurde (10 mal um unnötige Aussführungen dieses Programmteils durch flasche Detektierung des Metalldetektors zu vermeiden) wird der zweite Teil des Programms ausgeführt
      l = 0;
      while (l < 135) {
        RlinksFahren();                       //fährt 135 Stücke rückwärts um in Position zum Aufsammeln zu kommen
        RrechtsFahren();
        l++;
        t--;
      }
      einsammeln();                           //führt die Aufsammeln-Funktion aus
      zahl = 0;                               //setzt die Anzahl an Durchläufen mit gefunden Metall zurück auf 0
    }
  }
}
 
 
//Die Funktion "kurz" funktioniert analog zur Funktion "lang", wird aber nur 56 mal statt 1112 mal ausgeführt.
void kurz() {
  for (int t = 0; t < 56;) {
    //einsammeln();
 
    wert = 0;
    finden();
    for (int m = 0; m < 10; m++) {
      wert = wert + curPulseLength;
    }
    wert = wert / 10;
    if (wert > 169700) {
      zahl++;
    }
    if (zahl < 10) {
      linksFahren();
      rechtsFahren();
      t++;
    }
    else {
      while (l < 135) {
        RlinksFahren();
        RrechtsFahren();
        l++;
        t--;
      }
      einsammeln();
      zahl = 0;
      l = 0;
    }
  }
}
 
 
//diese Funtion dreht den Roboter um 90° nach rechts (Räder werden in entgegengesetzte Richtungen gedreht)
void rechtsdreh() {
  for (int o = 0; o < 475; o++) {
    RlinksFahren();
    rechtsFahren();
  }
}
 
 
//diese Funtion dreht den Roboter um 90° nach links (Räder werden in entgegengesetzte Richtungen gedreht)
void linksdreh() {
  for (int o = 0; o < 475; o++) {
    linksFahren();
    RrechtsFahren();
  }
}
 
 
// Abstände der drei Entfernungsmesser werden in der Funktion "abstandMessung" gemessen (Diese Funktion wird in unserem finalen Programm nicht verwendet)
int abstandMessung() {
 
  // abstandLinks
  digitalWrite(linksTrigger, LOW); //Input auf LOw setzen und 2Mikrosekunden warten
  delayMicroseconds(2);
  digitalWrite(linksTrigger, HIGH); //Input für 5 Sekunden auf HIgh setzen, um Messung im Ultrschallgerät auszulösen
  delayMicroseconds(5);
  digitalWrite(linksTrigger, LOW); // Dann wiedr ausschalten
 
  laenge = pulseIn(linksEcho, HIGH); // Erhalte Messergebnis vom Input in Pulsweitenmodulation
 
  abstandLinks = (laenge * 34) / 2000;
 
  digitalWrite(mitteTrigger, LOW); //Input auf LOw setzen und 2Mikrosekunden warten
  delayMicroseconds(2);
  digitalWrite(mitteTrigger, HIGH); //Input für 5 Sekunden auf HIgh setzen, um Messung im Ultrschallgerät auszulösen
  delayMicroseconds(5);
  digitalWrite(mitteTrigger, LOW); // Dann wiedr ausschalten
 
  laenge = pulseIn(mitteEcho, HIGH); // Erhalte Messergebnis vom Input in Pulsweitenmodulation
 
  abstandMitte = (laenge * 34) / 2000;
 
  digitalWrite(rechtsTrigger, LOW); //Input auf LOw setzen und 2Mikrosekunden warten
  delayMicroseconds(2);
  digitalWrite(rechtsTrigger, HIGH); //Input für 5 Sekunden auf HIgh setzen, um Messung im Ultrschallgerät auszulösen
  delayMicroseconds(5);
  digitalWrite(rechtsTrigger, LOW); // Dann wieder ausschalten
 
  laenge = pulseIn(rechtsEcho, HIGH); // Erhalte Messergebnis vom Input in Pulsweitenmodulation
 
  abstandRechts = (laenge * 34) / 2000;
 
  return abstandLinks;
  //  return abstandMitte;
  //  return abstandRechts;
}
 
//Nachfoldend sind die Funktionen fürs Vor- und Rückwärtsfahren für das linke und das rechte Rad
 
//dreht das linke Rad vorwärts
void linksFahren() {
  digitalWrite(directionLeft, LOW);
  digitalWrite(fahrenLeft, HIGH);
  delayMicroseconds(10);
  digitalWrite(fahrenLeft, LOW);
  delay(5);
 
}
 
 
//dreht das rechte Rad vorwärts
void rechtsFahren() {
  digitalWrite(directionRight, HIGH);
  digitalWrite(fahrenRight, HIGH);
  delayMicroseconds(10);
  digitalWrite(fahrenRight, LOW);
  delay(5);
 
}
 
 
//dreht das linke Rad rückwärts
void RlinksFahren() {
  digitalWrite(directionLeft, HIGH);
  digitalWrite(fahrenLeft, HIGH);
  delayMicroseconds(10);
  digitalWrite(fahrenLeft, LOW);
  delay(5);
 
}
 
 
//dreht das rechte Rad rückwärts
void RrechtsFahren() {
  digitalWrite(directionRight, LOW);
  digitalWrite(fahrenRight, HIGH);
  delayMicroseconds(10);
  digitalWrite(fahrenRight, LOW);
  delay(5);
 
}
 
 
// Bewegt Rohr mithilfe des Servos nach vorne
// Schaltet den Elektromagneten ein und sammelt somit das Metall unter sich ein.
// Bewegt Magneten über Auffangbehälter und schaltet Magneten ab, sodass Metall in Auffangbehälter landet.
 
void einsammeln() {
  myservo.detach();                               //Servo wird ab- und dann wieder angeschaltet da er Durch die Messung des MEtalldetektors automatisch deaktiviert wird
  myservo.attach(6, 800, 2100);
  for (int u = 0; u < 40; u++) {                  //der Roboter dreht sich ein Stück um mit dem Elektromagnet näher am Metall zu sein
    RlinksFahren();
    rechtsFahren();
  }
  for (int x = 180; x > 0; x--) {                 //bewegt Rohr nach oben (Servo Position 0)
    myservo.write(x);
    delay(20);
  }
  digitalWrite(magnetPin, HIGH);                 //schlatet den Elektromagnet ein
  for (int u = 0; u < 160; u++) {                //beweget den Roboter nach links und rechts um die Reichweite des Elektromagents zu erhöhen
    RlinksFahren();
    rechtsFahren();
  }
  for (int u = 0; u < 320; u++) {
    linksFahren();
    RrechtsFahren();
  }
  for (int u = 0; u < 160; u++) {
    RlinksFahren();
    rechtsFahren();
  }
  delay(1000);                                    //wartet 5 Sekunden
  for (int x = 0; x < 180; x++) {                 //bewegt Rohr nach oben (Servo Position 180)
    myservo.write(x);
    delay(20);
  }
  digitalWrite(magnetPin, LOW);                   //schaltet den Elektromagneten aus
  delay(1000);
  for (int u = 0; u < 40; u++) {                  //dreht sich wieder zurück in die Anfangsposition
    linksFahren();
    RrechtsFahren();
  }
}
 
 
//wertet Informationen des Metalldetektors aus und gibt die Anzahl an CPU-Cyclen wärend 10 Schwingen des Schwingkreises in der Variablen "curPulseLength" zurück
unsigned long finden() {
  digitalWrite(outPin, HIGH);                     //stößt den Schwingkreis an
  delay(2);
  digitalWrite(outPin, LOW);
  curPulseLength = measrePulseByICP();            //misst die Anzahl an CPU-Cyclen während 10 Schwingungen des Schwingkreises und schreibt diese in die Variable "curPulseLength"
  delay(2);
  return curPulseLength;                          //returnt "curPulseLength"
}
//dieser Quelltext ist nicht von der Gruppe Schrottbot sondern von Felix
//der Quelltext wurde lediglich für unsere Zwecke leicht angepasst
 
 
 
#pragma once
/*
   Measure Times using AVR Timer1 Input Capture
 
   Timer One counts CPU-Cycles.
   After enabling "Input Capture", it will save the current cycle count in the ICR1 Register whenever a Rising/Falling Signal flank is detected on pin 8
   This will break the servo library
 
*/
 
#include "Arduino.h"
 
// some bit-masking shortcuts
#define sbi(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
#define cbi(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
#define outp(VAL,ADRESS) ((ADRESS) = (VAL))
#define inp(VAL) (VAL)
 
unsigned long measrePulseByICP() {
  int n = 5;                                                                                                                 //maximale anzahl an messungen
  noInterrupts(); // we don't want to be disturbed                                                                            Präampel
  // prepare timer 1 for input capture
  TCCR1A = 0 ;
  TCCR1B = (1 << ICNC1) +   // Normal counting mode
           (1 << CS10) +    // set prescaler to 1
           (1 << ICES1);    // trigger on rising edge
  TIMSK1 = 0;               // disable all Timer1 related interrupts
  TIFR1 =  (1 << TOV1) + (1 << ICF1); // clear the interrupt pending flags. Bizarre: The interrupt pending flags are set to ZERO by writing ONE to it (!!!)
  TCNT1 = 0;     // reset the timer counter so we start counting at zero
  unsigned int zeitamanfang = 0;                                                                                               //anzahl an CPU_cycelm am anfang der messung
  unsigned int zeitamende = 0;                                                                                                 //anzahl der CPU-cyclen am ende der messung
 
 
  unsigned int timerOverFlowCount = 0; // number of overflows since the pulse has started                                       deklarierte Variablen
 
  // here we could do anything that we need to create that pulse...
 
 
  register uint8_t tifrCached = TIFR1;    // read all flags at once to prevent race conditions
 
  // now we wait for the voltage at the pin to rise and count timer overflows while we do so.                                 wartet auf rising edge flag
  //digitalWrite(4, HIGH);
  while (!(tifrCached & (1 << ICF1))) {// repeat while input capture edge detect flag is not set
    if (tifrCached & (1 << TOV1)) {  // check if the timer overflow bit is set
      TIFR1 =  (1 << TOV1);          // clear overflow flag
    }
    tifrCached = TIFR1;               // read all flags at once to prevent race conditions
  }
  TIFR1 =  (1 << ICIE1);  // clear input edge detect flag
  zeitamanfang = ICR1;   // remember the timer value when the pin changed to HIGH                                           schreib CPU-Zählerstand
  // digitalWrite(4, LOW);
  for (int i = 0; i < n; i++) {                                                                                            //wiederholt die messung der nulldurchgänge 10 mal
    tifrCached = TIFR1;               // read all flags at once to prevent race conditions
    while (!(tifrCached & (1 << ICF1))) {// repeat while input capture edge detect flag is not set
      if (tifrCached & (1 << TOV1)) {  // check if the timer overflow bit is set
        timerOverFlowCount++;           // count timer overflows...
        TIFR1 =  (1 << TOV1);          // clear overflow flag
      }
      tifrCached = TIFR1;               // read all flags at once to prevent race conditions
 
    }
    TIFR1 =  (1 << ICIE1);  // clear input edge detect flag
  }
  zeitamende = ICR1;
 
 
  interrupts();                        // let the rest of the µC do it's work again...
 
  // now we can calculate the amount of CPU-cylces between rising and falling edge...
  // due to unsigned int arithmetics, we can just substract timer values regardless of overflows and add a bitshiftet overflow count.
  unsigned long pulseCycles = (unsigned long)(zeitamende - zeitamanfang) | (unsigned long)timerOverFlowCount << 16; // combine the number of overflows with the timer value when the flanc was detected.
  // Serial.println(timerOverFlowCount);
  // Serial.println(zeitamende);
  // Serial.println(zeitamanfang);
  // Serial.println(pulseCycles);
  return pulseCycles;
}

schrottbot.zip

Ergebnis und Diskussion

Zum Ende haben wir es geschafft, dass der Roboter rumfährt, metallene Gegenstände mit dem Metalldetektor aufspürt und diese dann Mithilfe des Elektromagneten einsammelt und im Auffangbehälter fallen lässt. Wir haben demnach die Dinge umgesetzt, die der Roboter können muss.

Der SchrottBot ist soweit fertig gebaut und zeigt, dass er metallene Gegenstände aufsammelt. Manchmal sammelt er die metallene Gegenstände nicht ein, da diese ungünstig liegen und der Sammelmechanismus es nicht aufnehmen kann. Es liegt entweder daran das der Kran den Gegenstand wegschiebt und nicht mehr rankommt oder daran, dass der Gegenstand nicht nah genug am Elektromagneten ist um ihn anzuziegen. Dieses Problem haben wir noch nicht behoben, da es schwierig ist den Roboterarm immer so auszurichten, dass dieser Schrauben oder Muttern aufsammelt. Die geringe Anziehungskraft erschwert uns diese Aufgabe, da die metallenen Gegenstände direkt darunter sein müssen. Hierbei haben wir versucht, dass der Kran auf dem Boden rumschwenkt um eventuell die Gegenstände besser zu finden. Manche Muttern kann dieser jetzt finden und aufheben, aber es kann passieren, dass diese durch das schwenken eher das Metall wegschiebt und nicht mehr aufsammeln kann. Dafür haben wir noch keine ideale Lösung gefunden.

Verbesserungswürdig wäre auf jedenfall das Ausweichen. Die Entfernungsmesser wurden nicht eingebunden, da wir es nicht zeitlich geschafft haben.

projektesose2016/schrottbot/dokumentation.1471472790.txt.gz · Zuletzt geändert: 2016/08/18 00:26 von diebitsch