Liste der Anhänge anzeigen (Anzahl: 1)
Roboter Linienverfolgung
die Logik habe ich zuerst in Basic geschrieben und dann in Assembler, ich habe im Folgenden auch den Basic Code gepostet, damit man die Logik selbst rauslesen kann und ich sie nicht in einen Text irgendwie verschlüsseln muss.
Der Hauptalgorithmus [Hauptprogramm ... JMP Hauptprogramm] funktioniert, aber scheinbar hat es noch Probleme mit der Messung der Schwellwerte auf sich, nur weis ich nicht was, bitte um Hilfe.
basic code
Code:
'Erstellungsdatum: 21.Feb 2010
'Ein Roboter, der einer 1,5cm breiten Linie nachfährt
'
'Initialisierungen*************************************************************
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 64
$framesize = 64
'ADC-init
Config Adc = Single , Prescaler = Auto , Reference = Avcc 'Konfiguriere ADC
'--> Deklarationen von HP*******************
Dim Messergebnisleft As Word 'Miss Spannung am linken LDR
Dim Messergebnismiddle As Word 'Miss Spannung am mittleren LDR
Dim Messergebnisright As Word 'Miss Spannung am rechten LDR
Dim Summe As Word
Dim Schwellwertgespeichertmiddle As Eram Word
Dim Speichermitteaus As Eram Word
Dim Schwellwertmiddle As Word
Dim Mitteaus As Word
Dim Schwellwertgespeichertleft As Eram Word
Dim Speicherlinksaus As Eram Word
Dim Schwellwertleft As Word
Dim Linksaus As Word
Dim Schwellwertgespeichertright As Eram Word
Dim Speicherrechtsaus As Eram Word
Dim Schwellwertright As Word
Dim Rechtsaus As Word
Dim Weisslinks As Word
Dim Weissmitte As Word
Dim Weissrechts As Word
Dim Zustand As Byte 'Hier wird der Aktuelle Stand der Sensren reingeschrieben
Dim Letzterzustand As String * 10
Config Debounce = 30 'Debaonce verzögerungszeit 30ms
Schwellwertleft = Schwellwertgespeichertleft
Schwellwertmiddle = Schwellwertgespeichertmiddle
Schwellwertright = Schwellwertgespeichertright
Linksaus = Speicherlinksaus
Mitteaus = Speichermitteaus
Rechtsaus = Speicherrechtsaus
'EIN-AUSgänge******************************************************************
Config Portb.1 = Output 'oc1a
Config Portb.2 = Output 'oc1b
Config Portc.3 = Output
Config Pind.2 = Input
'Hauptprogramm*****************************************************************
Do
Start Adc
Messergebnisleft = Getadc(0)
If Messergebnisleft > Schwellwertleft Then Zustand.0 = 1 'Else Zustand = 0
If Messergebnisleft < Linksaus Then Zustand.0 = 0 'schreibe Information von sensor rechts in Byte Zustand
Messergebnismiddle = Getadc(1)
If Messergebnismiddle > Schwellwertmiddle Then Zustand.1 = 1 'Else Zustand = 0
If Messergebnismiddle < Mitteaus Then Zustand.1 = 0 'schreibe Information von sensor mitte in Byte Zustand
Messergebnisright = Getadc(2)
If Messergebnisright > Schwellwertright Then Zustand.2 = 1 'Else Zustand = 0
If Messergebnisright < Rechtsaus Then Zustand.2 = 0 'schreibe Information von sensor links in Byte Zustand
Select Case Zustand
Case &B00000001 :
Portb = &B00000100
Letzterzustand = "Links" 'Merke dir den letzten Zustand
Case &B00000100 :
Portb = &B00000010
Letzterzustand = "Rechts"
Case &B00000010 :
Portb = &B00000110
Letzterzustand = "Mitte"
Case &B00000000 'Falls undefinierter Zustand dann behalte letzten Zustand
If Letzterzustand = "Links" Then
Portb = &B00000100
End If
If Letzterzustand = "Rechts" Then
Portb = &B00000010
End If
End Select
Debounce Pind.2 , 0 , Messeschwellwert 'Gehe zu Messeschwellwert wenn PinD2= 1
Loop
'*****************************InterruptRoutinen*******************************
Messeschwellwert:
Start Adc
Weisslinks = Getadc(0) 'Zuerst alle 3 auf weißen Untergrund ausmessen
Weissmitte = Getadc(1) 'Zuerst alle 3 auf weißen Untergrund ausmessen
Weissrechts = Getadc(2) 'Zuerst alle 3 auf weißen Untergrund ausmessen
Wait 1
Portb = &B00000010
Wait 3
Portb = 0
'Linker Schwellwert--------------
Messergebnisleft = Getadc(0) 'Schwarzer Untergrund wird ausgemessen
Summe = Messergebnisleft + Weisslinks
Schwellwertleft = Summe / 2 'Bilde Mittelwert(Einschaltschwelle)
Linksaus = Schwellwertleft - 20 'Ausschaltschwelle
Speicherlinksaus = Linksaus 'Speichere in Eprom
Schwellwertgespeichertleft = Schwellwertleft 'Speichere diesen im Eprom
Wait 1
'--------------------------------
Portb = &B00000110 'Vorbereitung auf mittleren Schwellwert
Wait 3
Portb = 0
'Mittlerer Schwellwert-----------
Messergebnismiddle = Getadc(1)
Summe = Messergebnismiddle + Weissmitte 'Bilde Summe
Schwellwertmiddle = Summe / 2 'Bilde Mittelwert
Mitteaus = Schwellwertmiddle - 20 'Ausschaltschwelle
Speichermitteaus = Mitteaus 'Speichere in Eprom
Schwellwertgespeichertmiddle = Schwellwertmiddle 'Speichere diesen im Eprom
Wait 1
'--------------------------------
Portb = &B00000100 'Vorbereitung auf rechten Schwellwert
Wait 3
Portb = 0
'Rechter Schwellwert-------------
Messergebnisright = Getadc(2)
Summe = Messergebnisright + Weissrechts
Schwellwertright = Summe / 2
Rechtsaus = Schwellwertright - 20 'Ausschaltschwelle
Speicherrechtsaus = Rechtsaus 'Speichere in Eprom
Schwellwertgespeichertright = Schwellwertright 'Schreibe Wert in EPROM
Wait 1
'--------------------------------
Portb = &B00000100
Waitms 500
Portb = &B00000010
Waitms 500
Portb = &B00000100
Waitms 500
Portb = &B00000010
Waitms 500
Return
assembler code
Code:
;**********************************Header**************************************
;* Projektname: Roboter-Linienverfolgung *
;* Name des Erstellers: *
;* Zuletzt aktualisiert: 7.4.2010 *
;* Beschreibung: Ein ROboter, der einer ca1,5-2cm breiten Linie nachfaährt *
;******************************************************************************
;*****************************Initialisierungen********************************
.include "m8def.inc" ;Definitionsdatei des Mega8
;Stackpointer-init***********
ldi r16, High(Ramend)
out SPH, r16
ldi r16, Low(Ramend)
out SPL, r16
;ADC-init***********
sbi ADCSRA, ADEN ;ADC erlauben
cbi ADCSRA, ADPS0
sbi ADCSRA, ADPS1
sbi ADCSRA, ADPS2 ;PRESCALER 64
;*************************Variablendeklarationen*******************************
.def Messergebnisleft = r16
.def Messergebnisright = r17
.def Messergebnismiddle = r18
.def Schwellwertleft = r19
.def Schwellwertmiddle = r20
.def Schwellwertright = r21
.def Linksaus = r22
.def Mitteaus = r23
.def Rechtsaus = r24
.def Linienerkennung = r29
;*****************************Ein-Ausgänge*************************************
sbi DDRB, 1 ;PORTB.1 als Ausgabeport
sbi DDRB, 2 ;PORTB.2 als Ausgabeport
cbi DDRD, 2 ;PORTD.2 als Eingabeport
sbi PORTD, 2 ;Pullups aktivieren
;*****************************Hauptprogramm************************************
Hauptprogramm:
clr Linienerkennung ;Virbereitung auf neue Messung
;TEIL1...................START.......................Messe aktuelle Werte der Linie aus
rcall StartADConChanel0_8bit
in Messergebnisleft, ADCH
rcall StartADConChanel1_8bit
in Messergebnismiddle, ADCH
rcall StartADConChanel2_8bit
in Messergebnisright, ADCH
;TEIL2...................START.......................Erstelle aktuelle Werte für Linienerkennung
cp Messergebnisleft, Schwellwertleft ;Vergleiche LDR links aktuell mit vorher ausgerechnetem
;Schwellwert
brlo FahreFort0
ldi Linienerkennung, 0b00000100 ;Wenn nicht kleiner, sprich wenn größer dann setze Bit auf 1
FahreFort0:
cp Messergebnismiddle, Schwellwertmiddle ;Vergleiche LDR mitte aktuell mit vorher ausgerechnetem
;Schwellwert
brlo FahreFort1
ldi Linienerkennung, 0b00000010 ;Wenn nicht kleiner, sprich wenn größer dann setze Bit auf 1
FahreFort1: ;wenn kleiner dann lass es auf Null
cp Messergebnisright, Schwellwertright ;Vergleiche LDR rechts aktuell mit vorher ausgerechnetem
;Schwellwert
brlo FahreFort2
ldi Linienerkennung, 0b00000001 ;Wenn nicht kleiner, sprich wenn größer dann setze Bit auf 1
FahreFort2: ;wenn kleiner dann lass es auf Null
;TEIL3...................START.......................Auswertung-->Motorsteuerung
sbrc Linienerkennung, 2
ldi r28, 0b00000010 ;Motor = Rechts
out PORTB, r28
sbrc Linienerkennung, 1
ldi r28, 0b00000110 ;Motor = Beide
out PORTB, r28
sbrc Linienerkennung, 0
ldi r28, 0b00000100 ;Motor = Links
out PORTB, r28
;TEIL4...................START.......................Falls neie Messung vorgesehen dann mache sie zuerst
sbis PIND, 2 ;Überprüfe PIND.0
rcall Messeschwellwert ;Wenn PIND.0 = 0 (Taster betätigt)--> Messung
rjmp Hauptprogramm ;ansosnten wieder von vorne
;*********************************************************************************
;***********************Unterprogramme/Funktionen******************************
Messeschwellwert:
rcall StartADConChanel0_8bit ;Messe linken LDR bei weißem Untergrund
in r25, ADCH
rcall StartADConChanel1_8bit ;Messe mittleren LDR bei weißem Untergrund
in r26, ADCH
rcall StartADConChanel2_8bit ;Messe rechten LDR bei weißem Untergrund
in r27, ADCH
cbi PORTB, 1
cbi PORTB, 2
rcall Wait1
sbi PORTB, 1
rcall Wait3
cbi PORTB, 1
;Linker Schwellwert--------------
push r28 ;In diesem Register wird das Carry einer Addition geprüft, deswegen ist sicherung nötig
clr r28 ;lösche registerinhalt in r28 zur neuen Anwendung
rcall StartADConChanel0_8bit
in Messergebnisleft, ADCH ;Messe LDRleft bei schwarzem Untergrund
add r25, Messergebnisleft ;Addiere Weißen Wert mit Schwarzen Wert
BRCC RechneWeiter0;Teste Carry Flag wegen Addition, wenn 1 dann war ein Überlauf und lade
;128 in ein Register weil nachher der Mittelwert gebildet wird und dafür
;eine 9 Bit Zahl notwendig ist, dh: r27/2 + (Register mit Carry = 255/2)
;ergibt den richtigen Schwellwert
ldi r28, 128 ;wenn Carry 1 dann lade 128 in carry-register
RechneWeiter0: ;wenn Carry 0 dann lasse carry-Register auf 0 (wenn Schwellwerte niedrig)
mov r16, r25 ;Den Dividenten ins Register der Division kopieren
;Diese Register ist als Messergebnisleft definiert
;jedoch hats keine auswirkung, denn dies wird hier nicht verwendet
ldi r17, 2 ;Den Divisor ins Register der Division laden
;Dieses Register ist Messergebnismiddle, dass tört aber keinen
;da hier nicht verwendet
rcall Division
;Ergebnis steht jetzt in Register Ergebnis (r30)
add r28, Ergebnis ;Korrektur falls Carry 1 war, dies dinet dazu, falls der Schwellwert
;bei verschiedenen Linienfarben unterschiedlich, kann es sein
;dass es kleinere Spannungen auch geben kann, daher muss
;ein möglicher Überlauf berücksichtigt werden
;Endergebnis steht jetzt in r28
mov Schwellwertleft, r28 ;Kopiere den Schwellwert in definiertes Register
;für diesen Wert
rcall Wait1
pop r28
;--------------------------------
sbi PORTB, 1
sbi PORTB, 2
rcall Wait3
cbi PORTB, 1
cbi PORTB, 2
;Mittlerer Schwellwert-----------
push r28 ;In diesem Register wird das Carry einer Addition geprüft, deswegen ist sicherung nötig
clr r28 ;lösche registerinhalt in r28 zur neuen Anwendung
rcall StartADConChanel1_8bit
in Messergebnismiddle, ADCH ;Messe LDRleft bei schwarzem Untergrund
add r26, Messergebnismiddle ;Addiere Weißen Wert mit Schwarzen Wert
BRCC RechneWeiter1;Teste Carry Flag wegen Addition, wenn 1 dann war ein Überlauf und lade
;128 in ein Register weil nachher der Mittelwert gebildet wird und dafür
;eine 9 Bit Zahl notwendig ist, dh: r27/2 + (Register mit Carry = 255/2)
;ergibt den richtigen Schwellwert
ldi r28, 128 ;wenn Carry 1 dann lade 128 in carry-register
RechneWeiter1: ;wenn Carry 0 dann lasse carry-Register auf 0 (wenn Schwellwerte niedrig)
mov r16, r26 ;Den Dividenten ins Register der Division kopieren
;Diese Register ist als Messergebnisleft definiert
;jedoch hats keine auswirkung, denn dies wird hier nicht verwendet
ldi r17, 2 ;Den Divisor ins Register der Division laden
;Dieses Register ist Messergebnismiddle, dass tört aber keinen
;da hier nicht verwendet
rcall Division
;Ergebnis steht jetzt in Register Ergebnis (r30)
add r28, Ergebnis ;Korrektur falls Carry 1 war, dies dinet dazu, falls der Schwellwert
;bei verschiedenen Linienfarben unterschiedlich, kann es sein
;dass es kleinere Spannungen auch geben kann, daher muss
;ein möglicher Überlauf berücksichtigt werden
;Endergebnis steht jetzt in r28
mov Schwellwertmiddle, r28 ;Kopiere den Schwellwert in definiertes Register
;für diesen Wert
rcall Wait1
pop r28
;--------------------------------
sbi PORTB, 2
rcall Wait3
cbi PORTB, 2
;Rechter Schwellwert-------------
push r28 ;In diesem Register wird das Carry einer Addition geprüft, deswegen ist sicherung nötig
clr r28 ;lösche registerinhalt in r28 zur neuen Anwendung
rcall StartADConChanel2_8bit
in Messergebnisright, ADCH ;Messe LDRleft bei schwarzem Untergrund
add r27, Messergebnisright ;Addiere Weißen Wert mit Schwarzen Wert
BRCC RechneWeiter2;Teste Carry Flag wegen Addition, wenn 1 dann war ein Überlauf und lade
;128 in ein Register weil nachher der Mittelwert gebildet wird und dafür
;eine 9 Bit Zahl notwendig ist, dh: r27/2 + (Register mit Carry = 255/2)
;ergibt den richtigen Schwellwert
ldi r28, 128 ;wenn Carry 1 dann lade 128 in carry-register
RechneWeiter2: ;wenn Carry 0 dann lasse carry-Register auf 0 (wenn Schwellwerte niedrig)
mov r16, r27 ;Den Dividenten ins Register der Division kopieren
;Diese Register ist als Messergebnisleft definiert
;jedoch hats keine auswirkung, denn dies wird hier nicht verwendet
ldi r17, 2 ;Den Divisor ins Register der Division laden
;Dieses Register ist Messergebnismiddle, dass tört aber keinen
;da hier nicht verwendet
rcall Division
;Ergebnis steht jetzt in Register Ergebnis (r30)
add r28, Ergebnis ;Korrektur falls Carry 1 war, dies dinet dazu, falls der Schwellwert
;bei verschiedenen Linienfarben unterschiedlich, kann es sein
;dass es kleinere Spannungen auch geben kann, daher muss
;ein möglicher Überlauf berücksichtigt werden
;Endergebnis steht jetzt in r28
mov Schwellwertright, r28 ;Kopiere den Schwellwert in definiertes Register
;für diesen Wert
rcall Wait1
pop r28
;--------------------------------
ret
;*************************************
;*************************************
;################################################################################
.include "Division8Bit+Rest.asm" ;8 Bit division //call division
.include "wait1.asm"
.include "wait3.asm"
.include "ReadEEPROM.asm" ; //call Read_EEPROM
.include "WriteEEPROM.asm" ; //call Write_EEPROM
.include "StartADConCHANEL0_8bit.asm"
.include "StartADConCHANEL1_8bit.asm"
.include "StartADConCHANEL2_8bit.asm"
;################################################################################
In Aufrufe.txt sind die Unterprogramme die ich geschrieben habe
ich habe auch ausführlichst rauskommentiert
lg andy
Liste der Anhänge anzeigen (Anzahl: 1)
ich habe hier mal ein Prinzipschaltbild reingemacht die Sensoren liefern korrekte Werte und mit dem Basic Programm funktioniert es auch