PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Roboter Linienverfolgung



Andy11jj
30.04.2010, 21:51
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


'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


;**********************************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

Zwerwelfliescher
01.05.2010, 09:15
Hast du eventuell einen Schaltplan?

Gruß

Andy11jj
01.05.2010, 12:32
ich habe hier mal ein Prinzipschaltbild reingemacht die Sensoren liefern korrekte Werte und mit dem Basic Programm funktioniert es auch

Zwerwelfliescher
02.05.2010, 08:58
So wie ich das jetzt sehe, hast du das Quarz falsch angeschlossen. Es muss zwischen PB6 unf PB7 angeschlossen sein und noch mit einem 22pf Kondensator gegen GND.
Ich habe früher in ASM programmiert und mache heute eigentlich nur noch Basic. Der Basic Code sieht in ordnung aus.

Gruß

Andy11jj
02.05.2010, 10:36
So wie ich das jetzt sehe, hast du das Quarz falsch angeschlossen. Es muss zwischen PB6 unf PB7 angeschlossen sein und noch mit einem 22pf Kondensator gegen GND.

ich glaub schon, dass er richtig angeschlossen ist, es ist nämlich ein Quarzoszillator, hast sicher überlesen



Ich habe früher in ASM programmiert und mache heute eigentlich nur noch Basic. Der Basic Code sieht in ordnung aus.

Bis jetzt hat mir kein einziges FOrum weiterhelfen können, schön langsam verzweifle ich an dem Assembler

mare_crisium
02.05.2010, 13:07
Andy11jj,

na, zum Verzweifeln ist's aber noch viel zu früh :-)! Erkläre doch 'mal näher, warum Du meinst, die Schwellwertmessung funktioniere nicht richtig!

Ausserdem würde mich interessieren, was diese Zeilen


cbi PORTB, 1
cbi PORTB, 2
rcall Wait1
sbi PORTB, 1
rcall Wait3
cbi PORTB, 1

bedeuten sollen. Die hast Du gar nicht kommentiert. Ist denn an den Pins 1 und 2 von PORTB ausser den Motoren sonst noch was angeschlossen?

Ciao,

mare_crisium

Andy11jj
02.05.2010, 13:13
Erkläre doch 'mal näher, warum Du meinst, die Schwellwertmessung funktioniere nicht richtig!
Die Messung macht er zwar durch und zurückspringen tut er scheinbar auch, aber wenn den robo dann hin und her über die linie bewege dann haben die motoren immer nur einen Zustand, keine ahnung warum.



Ausserdem würde mich interessieren, was diese Zeilen
Code:

cbi PORTB, 1
cbi PORTB, 2
rcall Wait1
sbi PORTB, 1
rcall Wait3
cbi PORTB, 1

bedeuten sollen. Die hast Du gar nicht kommentiert. Ist denn an den Pins 1 und 2 von PORTB ausser den Motoren sonst noch was angeschlossen?

naja parallel (und vor der Treiberschaltung) sind noch 2 LEDs mit Rv geschalten, diese sagen mir beim Messen welcher Sensor ausgemessen wird, und wenns die LEDs ausgehen dann hat er die Messung durchgeführt und im nächsten schritt gehen beide auf, dh für mich: Stell den Roboter in die Mitte um den mittleren Sensor auszumessen, ...

Das Hauptprogramm funktioniert. Das habe ich im AVR Studio simuliert und es haut hin, alle werte natürlich manuell eingetragen usw, aber beim Messeschwellwert geht es iwie nicht, wobei es Softwaremäßig passen sollte

lg andy

mare_crisium
02.05.2010, 13:33
Andyj11,

nee, Deine Erklärung für die "cbi"- und "sbi"-Anweisungen verstehe ich nicht. Weiter oben im Programm steuerst Du die Motoren so an



;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


Das lese ich so, dass der rechte Motor an Pin1 (r28 = 0b00000010) angeschlossen ist und der linke an Pin2 (r28 = 0b00000100).
Wenn PORTB aus Ausgang konfiguriert ist, haben die Anweisungen



ldi r28, 0b00000010 ;Motor = Rechts
out PORTB, r28

exakt dieselbe Wirkung wie


sbi PORTB,1

d.h. es sieht so aus, als schaltetest Du mit dem Codestück, mit dem Du die LEDs steuern willst, auch die Motoren ein und aus.

Ciao,

mare_crisium

Andy11jj
02.05.2010, 13:43
d.h. es sieht so aus, als schaltetest Du mit dem Codestück, mit dem Du die LEDs steuern willst, auch die Motoren ein und aus.
Ja das ist schon richtig, aber nur während der Messung, das hat überhaupt keine Auswirkung auf das Hauptprogramm.

Nochmal wegen dem sbi und cbi beim Messen:
Da ich ja jeden der 3 Sensoren einzeln ausmessen will, kann ich den Roboter nicht einfach auf die Linie Stellen und dann messen. Also habe ich mir folgendes überlegt:
zuerst messe ich alle Werte der Sensoren wenn sie auf Weiß stehen

dann jeden einzelnen auf Schwarz.

Da ich aber jetzt jeden einzelnen auf schwarz messen muss, und ich mir schwertuhe Zeiten zu merken, symbolisiere ich das einfach am PORTB (dort wo die Motoren sind (diese sind aber zudem Zeitpunkt von Stromkreis getrennt damit sie sich nicht drehen während der Messung))
also Schritte:
-Messe alle auf weiß das geht ja einfach, da ich ihn nur hinstelle und dann den Taster drücke

-Jetzt nach der Messung leuchtet Portb,1 auf, dh für mich und für das Programm heißt das, dass er nach den 3 Sekunden den linken Sensor ausmessen wird, also stelle ich ihn so auf die Linie, damit der linke Sensor auf der Linie steht

-Nach dieser Messung leuchten beide auf, dh Mittlerer Sensor ist dran, ich stelle ihn also so auf, damit der mittlere Sensor auf der Linie steht.

-Und zu allerletzt leuchtet der rechte auf, --> Rechter Sensor auf Linie, weil in 3 Sek der rechte gemessen wird


------------------------------------

Wenn PORTB aus Ausgang konfiguriert ist, haben die Anweisungen

Code:

ldi r28, 0b00000010 ;Motor = Rechts
out PORTB, r28

exakt dieselbe Wirkung wie
Code:
sbi PORTB,1

Problem ist jetzt halt bei deinem Vorschlag, dass ich das sbrc streichen kann und sich wahrscheinlich der Wert im nächsten Befehl ändert^^

das ganze kannst du dir auch im Basic Programm anschauen, ist vielleicht übersichtlicher. Im Assembler ist es wirklich unübersichtlich, daher auch vielleicht das Missverständnis von dir

lg andy

mare_crisium
02.05.2010, 14:42
Andy11jj,

nee, Assembler ist nur unübersichtlich, wenn man unübersichtlich schreibt ;-) ! Guck' mal: Die Neuberechnung der Schwellwerte kannst Du doch locker in je eine Prozedur auslagern. Z.B.



/*
PROZEDUR UPDATE_SCHWELLE_LINKS

*/

UPDATE_SCHWELLE_LINKS
push r25
in r25,SREG
push xl
push xh

; Messung links signalisieren
cbi PORTB, 1 ; LEDs an PORTB.1 und PORTB.2 aussschalten
cbi PORTB, 2
rcall Wait1 ; Pause mit LEDs dunkel
sbi PORTB, 1 ; LED an PORTB.1 einschalten
rcall Wait3 ; Pause mit LED hell
cbi PORTB, 1 ; LED an PORTB.1 ausschalten

; Messung durchführen. Messwert des linken LDR auf weißem Untergrund steht
; in Register WeissWertLinks
rcall StartADConChanel0_8bit ;
in xl, ADCH ; Schwarzmesswert nach xl

; Mittelwert von Weiss- und Schwarzwert bilden
clr xh ;
add xl,WeissWertLinks ; 2-Byte Addition ausführen
adc xh,xh ; Übertrag nach xh berücksichtigen
lsr xh ; Division durch 2 entspricht Rechtsschieben um ein Bit
ror xl ; neuer Schwellwert links steht jetzt in xl

; neuen Schwellwert nach SchwelleLinks verschieben
mov SchwelleLinks,xl

pop xh
pop xl
out SREG,r25
pop r25
ret

;*************************************


Analog kannst Du das auch für Mitte und Rechts machen. Weil hier xh:xl verwendet werden, sparst Du Dir eine Menge Jongliererei mit den Registern (das kommt davon, wenn man .defs arbeitet ;-) ). Durch das Auslagern in Prozeduren, bei denen Du die benutzten Register sauber (mit "push" und "pop") sichern kannst, brauchst Du Dir keine Sorgen zu machen, dass Du aus Versehen mal ein mit ".def" belegtes Register überschreibst.

Die Stelle, die jetzt so unübersichtlich aussieht, wird dann ganz übersichtlich:



; TEIL4...................START..................... ..
; Falls neue Messung vorgesehen dann mache sie zuerst
sbic PIND, 2 ;Überprüfe PIND.0
rjmp Hauptprogramm ; Wenn PIND.0 = 1 (Taster nicht betätigt) -> keine Messung

; Taster betätigt -> Messung
; zuerst die WeissWerte messen
rcall StartADConChanel0_8bit ;Messe linken LDR bei weißem Untergrund
in WeissWertLinks, ADCH
rcall StartADConChanel1_8bit ;Messe mittleren LDR bei weißem Untergrund
in WeissWertMitte, ADCH
rcall StartADConChanel2_8bit ;Messe rechten LDR bei weißem Untergrund
in WeissWertRechts, ADCH
; jetzt die neuen SchwellWerte berechnen
rcall UPDATE_SCHWELLE_LINKS ; Schwellwert Links fertig
rcall UPDATE_SCHWELLE_MITTE ; Schwellwert Mitte fertig
rcall UPDATE_SCHWELLE_RECHTS ; Schwellwert Rechts fertig

rjmp Hauptprogramm ; ...und wieder von vorne


Es kann sein, dass Dein Problem damit zu tun hat, dass Du den Inhalt von SREG nicht sicherst. Nur keine Bange vor "push" und "pop" :-) !

Ciao,

mare_crisium

Andy11jj
02.05.2010, 14:52
Es kann sein, dass Dein Problem damit zu tun hat, dass Du den Inhalt von SREG nicht sicherst. Nur keine Bange vor "push" und "pop" Freudig !
Wie denn? Ich verändere ja SREG nicht

Dein Code welches du gepostet hast ist zwar recht nett, aber nicht wirklich gut auskommentiert für einen ASM Anfänger.
Jedoch weiß ich immer noch nicht wieso mein Coding, das mir jetzt im Moment übersichtlicher scheint nicht funktioniert.

Das mit den einzelnen Prozeduren werde ich vielleicht machen, ist auch sicherlich gut so.
Danke, dass du mir bis jetzt geholfen hast
lg andy