.

.

Home

Start-UP

Roboter

IWAN
BORIS
LISA
TESA
KONRAD
TORA
MICROTORA

Technik

Schaltungen
Platinenherstellung
Sharp-Sensor Bilder
Infrarot Radar
Software
Verluste

Bilder & Links

Links
Bilder
Videos
Wettbewerbe
Archiv

Team Mitglieder

Impressum

Valid HTML 4.01

Software-Icon

Linienverfolgung mit IWAN in Bascom-Basic

Normalerweise verwendet man an einem Roboter für die Erkennung einer Linie mehrere Lichtsensoren, die in einer Reihe angeordnet sind. Bei einem 8bit-Mikrocontroller bietet es sich natürlich an, derer 8 zu nehmen. Jeder Sensor liefert nur 1 Bit, entweder die Linie ist da, oder nicht.
Bei IWAN 2003 haben wir die Linie im PortC des Atmels eingelesen.
Die Motoren werden, da mit L297 angesteuert, nur mit Richtung und Clock bedient.
Für die bessere Lesbarkeit habe ich die Farben so wie in Bascom gewählt, die Kommentare sind also grün.
Der Leser kann sich das Programm per Drag & Drop in sein Bascom kopieren.
Ich erlaube das hiermit, da das Programm sowieso nicht zum Einsatz kam, es war zu langsam.
Als Beispiel kommt es aber gerade recht.

'*****************************
'* Linienverfolgung mit IWAN *
'****** www.team-iwan.de *****
'******** Michael Kinz *******
'*****************************
'Zuerst die Quarzfrequenz:
$crystal = 8000000
'Und der AT90S8515-Controller:
$regfile = "8515def.dat"

'LCD initialisieren:
Config Lcdpin = Pin , Db4 = Pa.2 , Db5 = Pa.3 , Db6 = Pa.4 , Db7 = Pa.5 , E = Pa.0 , Rs = Pa.1
Config Lcd = 16 * 2
'Es ist sinnvoll den Controller und die LCD-Pins unter Options--Compiler--Chip
'bzw. unter Options--Compiler--LCD einzustellen. Bascom ist da manchmal etwas zickig.
'Jetzt folgen Hilfstexte, um beim Programmieren immer zu wissen, wo die Ports hingehen:

'Portd.0 = Enable, Enable =1
'Portd.1 = CW/CCW = rechts
'Portd.2 = CW/CCW = links
'Portd.3 = Clock rechts
'Portd.4 = Clock links
'Portd.5 = Half/Full beide , Full=0, Half=1
'Portd.6 = Reset beide
'Pinb.0 = Taster

'An Port A kommt das LCD:
Config Porta = Output
'An Port B kommen Taster:
Config Portb = Input
'An Port C ist der Liniensensor:
Config Portc = Input
'Port D ist der Ausgang für die Motoren:
Config Portd = Output
'Jetzt werden die Pullup-Widerstände von Port B eingeschaltet, damit die Taster sauber nach GND schalten können.
Portb = 255
'Und die Motorausgänge bekommen auch definierte Pegel:
Portd.0 = 0
Portd.1 = 0
Portd.2 = 0
Portd.3 = 0
Portd.4 = 0
Portd.5 = 1
Portd.6 = 0

'Nun werden die Variablen definiert:
Dim Temp As Byte
Dim Temp1 As Byte
Dim Temp2 As Byte
Dim Temp3 As Byte
Dim Gleich As Byte
Dim I As Byte
Dim A As Byte
Dim Millisec As Byte
Dim Fehlerzaehler As Byte
'Und das Display gelöscht:
Cls
'Der Cursor soll in die 1. Zeile an die 1. Stelle:
Locate 1 , 1
'In Bascom gibt es keine gescheite Definition für ein 1*16-Display.
'Dazu kommt noch, daß das Display in Wirklichkeit als 2x8 organisiert ist.
'Man muss also für das 9. Zeichen in der 2. Zeile weitermachen:

Lcd "Linienve"
Locate 2 , 1
Lcd "rfolgung"

'Damit IWAN nach dem Einschalten nicht gleich losfährt
'wird einer der 4 Taster benutzt, um das Programm zu starten.
'In Wirklichkeit läuft das Programm aber schon und wartet hier auf den Tastendruck:

Anfang:
If Pinb.0 = 0 Then
'Wenn der Taster auf "GND" gedrückt wird,
Bitwait Pinb.0 , Set
'dann warte, bis er wieder 1 ist und springe nach "Main"
Goto Main
Else
Goto Anfang
End If
Main:
'Jetzt passiert endlich was: die Enable- und die Resetbremse werden gelöst
Portd.0 = 1
Portd.6 = 1
'Damit stehen die Motoren unter Spannung und im 1.Schritt.

Do
'Das "Do" ist der Anfangspunkt einer Schleife, bei "Loop" springt das Programm an diese Stelle zurück.

Mainx:
Temp = Pinc
Temp1 = Pinc

'Wenn hier 2 mal der gleiche Wert gelesen wird, geht es weiter im Programm, sonst wird nochmals gelesen.
'Da die Motoren keine Impulse während der Zeit bekommen, ist das irgendwann zwangsläufig der Fall.


If Temp <> Temp1 Then
Goto Mainx
End If

'Die If-Anweisung braucht am Ende immer ein End If

'Jetzt kommt eine Routine, die nachträglich eingefügt wurde,
'da der Algorythmus bei scharfen Abzweigen Schwächen hat.
'Unten kommt dazu noch eine Beschreibung.

If Temp.0 <> Temp2.0 Then
'Wenn das erste Bit (Bit0) ungleich dem aus dem vorherigem Durchlauf ist,dann
Fehlerzaehler = Fehlerzaehler + 1
'wird der Fehlerzähler eröht,
Else
Fehlerzaehler = Fehlerzaehler - 1
End If
'ansonsten verringert
If Fehlerzaehler > 3 Then
'wenn der Fehler 3 mal hintereinander kommt,
Gosub Fehlerroutine
'geht's in die Fehlerroutine am Schluss, um aus der Situation zu entkommen.
Temp2 = Temp
'zurück aus der Fehlerbearbeitung wird die Hilfsvariable Temp2 für den nächsten Durchlauf gespeichert.
Goto Mainx
'und wieder zum Anfang gesprungen.
End If
If Fehlerzaehler < 1 Then
Fehlerzaehler = 1
End If
'Der Zähler darf natürlich nicht unter 0 kommen, sonst klappt die größer-kleiner-Abfrage nicht.
'Sollte keine der obigen Bedingungen zutreffen, wird die Hilfsvariable Temp2 natürlich auch wieder fit gemacht

Temp2 = Temp

'Hier gehts richtig los:

'Hilfsbit auf erstes bit Eingang setzen:

A.0 = Temp.0
'Hilfsvariable für die Erkennung der Wechsel schwarz-weiß löschen
Gleich = 0
'Flanken innerhalb des Eingangssignals zählen:
For I = 0 To 7
'Das Byte, in dem unsere Linie ist, wird jetzt Bit für Bit abgetastet.
If A.0 <> Temp.i Then
'Ist das danebenliegende Bit ungleich, haben wir einen Wechsel von schwarz/weiß
Gleich = Gleich + 1
'Das wird dann gleich gespeichert
End If
A.0 = Temp.i
'zum Schluss wird das Hilfsbit auch eins weitergerückt
Next

'Jetzt steht in der Variable "Gleich" die Anzahl der Wechsel von schwarz auf weiß, bzw. umgekehrt.
'das heisst, wenn z.B. eine schwarze Linie unter dem Sensor ist, haben wir 2 Wechsel,
'von weiß auf schwarz und wieder von schwarz auf weiß
'bei z.B. einer Linie in der Mitte und zusätzlich eine am rechten Rand haben wir 3 Wechsel.

'Jetzt können wir auswerten:

If Temp = 0 Then
'Wenn keine Linie da ist, dann fahre nach links:
Gosub Links
'und erhöhe die Geschwindigkeit:
Millisec = Millisec - 1
'Jetzt noch die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Wenn alle Sensoren das gleiche anzeigen gibt es keinen Flankenwechsel:
If Gleich = 0 And Temp.7 = 1 Then
'Weil aber alle schwarz sind fahren wir nach rechts:
Gosub Rechts
'und erniedrigen hier die Geschwindigkeit, da wir wohl quer zur Linie stehen und scharf abbiegen müssen:
Millisec = Millisec + 1
'Jetzt die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Ein Flankenwechsel und der linke Sensor zeigt weiß
'rechts am Rand ist also die Linie, oder es ist ein Abzweig:

If Gleich = 1 And Temp.7 = 0 Then
Gosub Rechts
'und erniedrigen hier die Geschwindigkeit, da wir wohl quer zur Linie stehen und scharf abbiegen müssen:
Millisec = Millisec + 1
'Jetzt die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Ein Flankenwechsel, aber diesesmal zeigt der linke Sensor schwarz.
'die Linie ist also am linken Rand, oder es ist ein Abzweig nach links:

If Gleich = 1 And Temp.7 = 1 Then
'Wir fahren natürlich nach links, weil wir ja in erster Linie dieselbe in die Mitte bringen wollen:
Gosub Links
'und erniedrigen hier die Geschwindigkeit, da wir wohl quer zur Linie stehen und scharf abbiegen müssen:
Millisec = Millisec + 1
'Jetzt die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Zwei Wechsel und der linke Sensor ist weiß.
If Gleich = 2 And Temp.7 = 0 Then
'Das heisst geradeaus und Speed:
Gosub Vorw
'schneller:
Millisec = Millisec - 1
'Jetzt die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Zwei Wechsel und der linke Sensor ist schwarz.
If Gleich = 2 And Temp.7 = 1 Then
'Links eine Linie, in der Mitte weiß und rechts eine Linie,
'es muss also ein Abzweig sein

Gosub Rechts
'langsamer:
Millisec = Millisec + 1
'Jetzt die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Jetzt kommen nur noch Fälle, die mehr als 2 Flankenwechsel haben.
If Gleich > 2 Then
'mehr als 2 Flanken bedeutet immer ein Abzweig,
'und da wir "Rechtsabbieger" sind, geht's nach rechts:

Gosub Rechts
'ABzweig = langsamer:
Millisec = Millisec + 1
'Jetzt die Clock-Leitungen auf High setzen, sie werden am Ende
'jedes Durchlaufs wieder gelöscht.

Portd.3 = 1
Portd.4 = 1
End If

'Die Pulszeiten der Clocks sollten gewisse Grenzen nicht überschreiten,
'da bei zu schnellen Pulsen die Motoren Schritte verlieren und zu langsam macht auch keinen Spaß

If Millisec < 2 Then
Millisec = 2
End If

If Millisec > 20 Then
Millisec = 10
End If
'Jetzt dürfen wir endlich warten:
Waitms Millisec
'Und die Clocks wieder ausschalten:
Portd.3 = 0
Portd.4 = 0
Waitms 4

'Damit ist das Programm zu Ende, bzw. es beginnt von vorn:
Loop
'Jetzt folgen nur noch Unterprogramme, aus denen wieder zurückgesprungen wird.

'Unterprogramme, die die Richtung an den beiden L297 umschalten:
Vorw:
Portd.1 = 1 'für den rechten Motor
Portd.2 = 0 'für den linken Motor
'Obwohl beide Motoren vorwärts drehen sollen, bekommen sie unterschiedliche
'Signale. Das wird klar, wenn man bedenkt, dass der eine Motor links und der andere rechts drehen muss, damit der Roboter vorwärts fährt

Return
'Dieser Befehl sorgt für den Rücksprung ins Hauptprogramm.

Rueckw:
Portd.1 = 0
Portd.2 = 1
Return

Links:
Portd.1 = 1
Portd.2 = 1
Return

Rechts:
Portd.1 = 0
Portd.2 = 0
Return

'Wie anfangs schon versprochen, hier die Erklärung für die Fehlerroutine:
'An bestimmten Stellen, speziell bei spitz zulaufenden Abzweigen hängt sich der Roboter quasi auf,
'd.h. der Roboter wackelt nur noch auf einer Stelle hrum, ohne sich nennenswert von der Stelle zu bewegen.
'Dieser Fall wurde am Anfang der Schleife festgestellt und wird hier durch eine zeitlang Rechtsfahren aufgelöst.

Fehlerroutine:
Gosub Rechts
For I = 0 To 15
'16 Pulse nur mit dem linken Motor vorwärts gibt eine sanfte Rechtskurve
Portd.4 = 1
Waitms Millisec
Portd.3 = 1
Portd.4 = 1
Waitms 4
Next I
'Zähler zurücksetzen:
Fehlerzaehler = 1
'und zählen, wie oft diese Routine schon angesprungen wurde:
Temp3 = Temp3 + 1
Return
'Hier ist das Ende des Programmes:
End

Noch Fragen? Mail