Hi
>rcall ADC_Kanal0>rcall StartADC>in Messergebnisleft, ADCH
Diese Aufteilung der ADC-Messung ist relativ sinnfrei.
>cp Messergebnisleft, Schwellwertleft>brsh LinksGroesser>MessungZW05: ;LINIENERKENNUNG linker LDR>cp Messergebnisleft, Schwellwertleft>brlo LinksKleiner
Wenn Messergebnisleft nicht >= Schwellwertleft ist, ist es
zwangsläufig kleiner. Da es keine dritte Möglichkeit gibt, ist der
zweite Vergleich überflüssig.
>;Setze Bits in Byte für die Linienerkennung########>....
Warum macht du das nicht sofort nach dem Vergleich. Das Herumgespringe
ist unübersichtlich.
MfG Spess
>Diese Aufteilung der ADC-Messung ist relativ sinnfrei.
ich finde, wenn ich es auskommentiere ist es viel unübersichtlicher als
wie ernn ich dafür eigene unterprogramme schreibe
>Wenn Messergebnisleft nicht >= Schwellwertleft ist, ist es>zwangsläufig kleiner. Da es keine dritte Möglichkeit gibt, ist der>zweite Vergleich überflüssig.
Richtig, da is mal gleich ein fehler drinn, denn richtig ist es so:
spess53 schrieb:> Warum macht du das nicht sofort nach dem Vergleich. Das Herumgespringe> ist unübersichtlich.
weil, wenn ich die Marke gleich nach dem Vergleich aufschreibe, er dann
so oder so hineinspringt, denn wenn die bedingung nicht eintrifft,dann
macht er weiter im coding, es wäre natürlich viel schöner.
wie wärs damit:
PROGRAMM:
S1:
falls ADC1 kleiner Wert, springe zu S2
Mach was (ADC1>Wert)
S2:
falls ADC2 kleiner Wert, springe zu S3
Mach was (ADC2>Wert)
S3:
falls ADC3 kleiner Wert, springe zu ENDE
Mach was (ADC3>Wert)
ENDE:
zurück zu S1
;-)
Flo schrieb:> PROGRAMM:> S1:> falls ADC1 kleiner Wert, springe zu S2>> Mach was (ADC1>Wert)>> S2:> falls ADC2 kleiner Wert, springe zu S3>> Mach was (ADC2>Wert)>> S3:> falls ADC3 kleiner Wert, springe zu ENDE>> Mach was (ADC3>Wert)>> ENDE:
das funktioniert leider nicht
siehdir mal diesen Bascom code an, nach dem habe ich mich gerichtet:
1
Do
2
Start Adc
3
4
Messergebnisleft = Getadc(0)
5
If Messergebnisleft > Schwellwertleft Then Zustand.0 = 1 'Else Zustand = 0
6
If Messergebnisleft < Linksaus Then Zustand.0 = 0 'schreibe Information von sensor rechts in Byte Zustand
7
8
Messergebnismiddle = Getadc(1)
9
If Messergebnismiddle > Schwellwertmiddle Then Zustand.1 = 1 'Else Zustand = 0
10
If Messergebnismiddle < Mitteaus Then Zustand.1 = 0 'schreibe Information von sensor mitte in Byte Zustand
11
12
Messergebnisright = Getadc(2)
13
If Messergebnisright > Schwellwertright Then Zustand.2 = 1 'Else Zustand = 0
14
If Messergebnisright < Rechtsaus Then Zustand.2 = 0 'schreibe Information von sensor links in Byte Zustand
15
16
Select Case Zustand
17
18
Case &B00000001 :
19
Portb = &B00000100
20
Letzterzustand = "Links" 'Merke dir den letzten Zustand
21
22
Case &B00000100 :
23
Portb = &B00000010
24
Letzterzustand = "Rechts"
25
26
Case &B00000010 :
27
Portb = &B00000110
28
Letzterzustand = "Mitte"
29
30
Case &B00000000 'Falls undefinierter Zustand dann behalte letzten Zustand
31
If Letzterzustand = "Links" Then
32
Portb = &B00000100
33
End If
34
35
If Letzterzustand = "Rechts" Then
36
Portb = &B00000010
37
End If
38
39
End Select
40
41
Debounce Pind.2 , 0 , Messeschwellwert 'Gehe zu Messeschwellwert wenn PinD2= 1
Ok, das Programm haste mit deinem Assemblercode noch nicht ganz
getroffen ;-)
Es fehlt noch die Behandlung für den Fall, dass sich nichts ändert.
Ohne diesen wäre ein Statusspeicher nämlich überhaupt nicht nötig
gewesen, deshalb mein Ansatz.
Du willst ner Linie hinterher, oder?
Flo schrieb:> Es fehlt noch die Behandlung für den Fall, dass sich nichts ändert.
wenn sich nichts ändert, wie meinst du das denn?
meinst du jetzt den letzten Fall case Zustand = 0b00000000
wenn ja, dann brauch ich diesen nicht, denn ohne abfrage ändert sich
auch nicht am letzten Zustand, theoretisch könnt eich den weglassen
>Du willst ner Linie hinterher, oder?
das ist richtig, und das Bascom programm funktioniert, jedoch habe ich
einwenig probleme mit assembler, uch mein das programm funktioniert so
aus irgendeinem grund noch nicht, aber deshalb ja diese Fragen
Hi
>weil, wenn ich die Marke gleich nach dem Vergleich aufschreibe, er dann>so oder so hineinspringt, denn wenn die bedingung nicht eintrifft,dann>macht er weiter im coding, es wäre natürlich viel schöner.
Dann mach die Bedingung passend.
Der nachfolgende Code ist ohne Gewähr:
spess53 schrieb:> Hauptprogramm:> rcall ADC_Kanal0> rcall StartADC> in Messergebnisleft, ADCH> cp Messergebnisleft, Schwellwertleft> brlo MssungZW05>> MessungZW05: ;LINIENERKENNUNG linker LDR> cp Messergebnisleft, Linksaus> brshlo MessungZW1> cbr Linienerkennung, 1
Das Problem hierbei ist, dass wenn die Bedingung eintrifft oder auch
nicht er bei der Marke MessungZW05 weitermacht
habe ich neulich getestet, und deswegen die zusätzlichen Rücksprünge
Hi
>Das Problem hierbei ist, dass wenn die Bedingung eintrifft oder auch>nicht er bei der Marke MessungZW05 weitermacht>habe ich neulich getestet, und deswegen die zusätzlichen Rücksprünge
Bei dir doch auch. Du solltest aber beachten, das ich brsh und brlo
vertauscht habe.
MfG Spess
P.S. Beachte meine Korrektur.
>Bei dir doch auch.
nein, denn bei mir springt er bei eintreffen des Ereignisses auf die
richtige Marke und anschließend wieder zur richtigen Stelle zurück, und
bei nicht eintreffen macht er einfach weiter im Programmcode und lasst
den Sprung weg
>Du solltest aber beachten, das ich brsh und brlo>vertauscht habe.
ok, du kommst aber trotzdem nicht drum herum, denn in deinem Fall hast
du keine Verzweigung mehr, denn du machst es so und so durch
Hi
Dein Code:
> cp Messergebnisleft, Schwellwertleft> brsh LinksGroesser>MessungZW05: ;LINIENERKENNUNG linker LDR>LinksGroesser:> sbr Linienerkennung, 1>rjmp MessungZW05
Du landest in jedem Fall bei 'MessungZW05'
Mein Code:
> cp Messergebnisleft, Schwellwertleft> brlo MssungZW05> sbr Linienerkennung, 1>MessungZW05: ;LINIENERKENNUNG linker LDR
Ich lande auch immer bei 'MessungZW05'. Nur ohne Umwege.
MfG Spess
spess53 schrieb:> Ich lande auch immer bei 'MessungZW05'. Nur ohne Umwege.
es geht hier nicht um ZW05, denn das ist nur eine Hilfsmarke
es ging mir um sbr Linienerkennung, aber ich sehe grad, dass du das doch
umangen hast. Deine Methode ist sicher besser, aber ich möchte jetzt mal
wissen wieso meins nicht hinhaut, denn im endeffekt laufts ja aufs selbe
hinaus oder nicht?
Hi
>aber ich möchte jetzt mal wissen wieso meins nicht hinhaut, denn im>endeffekt laufts ja aufs selbe hinaus oder nicht?...
Wenn ich mich nicht vertan habe, ja.
Ich habe dein Programm nicht auf die logische Richtigkeit überprüft. Was
geht denn nicht?
MfG Spess
spess53 schrieb:> Wenn ich mich nicht vertan habe, ja.> Ich habe dein Programm nicht auf die logische Richtigkeit überprüft. Was> geht denn nicht?
tja nun jetzt weiß ich halt wieder nicht ob ich das ganze Programm
posten soll oder nicht, großteils wurde das Programm schon teilweise im
FOrum korriegiert, also Problem ist halt, dass er bei pind = 1 (siehe
Abfrage unten) er die Messungen macht, das nehme ich jedenfalls an, denn
er simbolisiert die LEDs und wenn die Messung fertig ist, dann tut sich
nichts mehr, ich hoffe das coding ist ausreichend auskommentiert:
spess53 schrieb:> Das muss ich mir erst mal in Ruhe zu Gemüte führen. Allerdings ein> erzeugt ein erster Überblick gesträubte Nackenhaare.
ok, das
HH:
RJMP HH
vergiss mal, das hab ich nur wegen vorhin reingemacht wegen den Sprüngen
Andy11 schrieb:> spess53 schrieb:>> Das muss ich mir erst mal in Ruhe zu Gemüte führen. Allerdings ein>> erzeugt ein erster Überblick gesträubte Nackenhaare.>> ok, das> HH:>>>> RJMP HH>> vergiss mal, das hab ich nur wegen vorhin reingemacht wegen den Sprüngen
Das ist es nicht, es ist Dein Programmierstil. Dein Spaghetticode ist
extrem schwer nachvollziehbar. Es ist zuviel Hinundherspringerei zu
Sprungzielen, die auch noch in anderen Dateien liegen. Das ist unnötig
unübersichtlich. Und effizient ist Deine Vorgehensweise auch nicht, Du
hast zuviel Wartezeit auf den ADC. Wenn man mehrere Kanäle messen muss,
dann lohnt es sich, dies in einer Statemachine im Hintergrund zu tun.
Klar, als Anfänger kann man das noch nicht, aber als Anfänger beginnt
man auch nicht gleich mir einer Robotersteuerung mit Linienverfolgung.
Ehe man das macht, erarbeitet man sich an kleineren Basteleien das
nötige Knowhow (Statemachine, Timer-Interrupt, ...).
Dazu kommt noch die grauenhafte Formatierung (Einrückung). Hier mal ein
Beispiel, wie man einen ASM-Quelltext formatieren kann damit er halbwegs
lesbar bleibt:
http://www.mikrocontroller.net/attachment/67466/IR8_V12_SAA3008.asm
Noch ein Tip zur Formatierung: Solltest Du Interesse daran haben, dass
die Formatierung auch außerhalb von AVR-Studio korrekt angezeigt wird,
dann könntest Du in den Einstellungen zum Editor mal die Tabs durch
Spaces ersetzen lassen. Das macht den Quelltext zwar geringfügig größer,
wird dann aber von jedem Textbetrachterprogramm korrekt dargestellt.
Ich weiß nicht, wo Du Dir diesen Programmierstil abgeschaut hast, mir
ist das jedenfalls zu unübersichtlich. Deshalb habe ich mich auch bisher
aus diesem Thread herausgehalten.
Mir geht es nicht darum, Dich "niederzumachen". Aber wenn es Dir keiner
sagt, dann kannst Du es ja nicht ändern...
...
Hannes Lux schrieb:> Mir geht es nicht darum, Dich "niederzumachen". Aber wenn es Dir keiner> sagt, dann kannst Du es ja nicht ändern...
Puuh, bin ich froh.
Ich hab mich zurückgehalten, damit ich nicht schon wieder als Nörgler
dastehe.
Meines Erachtens wurde zuviel Wert darauf gelegt, den BASCOM Code
möglichst 1:1 zu übernehmen (in dem Fall frag ich mich dann, warum
bleibt man nicht gleich bei BASCOM, das könnte man wenigstens lesen),
anstatt sich die Idee des Codes, das Prinzip, herauszuextrahieren und
mit dieser Idee im Hinterkopf ein Assemblerprogramm zu konzipieren. Ich
sag absichtlich 'konzipieren', denn wenn man einfach drauflos
programmiert, dann kommt genau sowas raus.
Zum Thema 100-tausend Files mit 'Funktionen' die aus 3 Anweisungen
bestehen, sag ich nichts mehr, das wurde in einem anderen Thread schon
angesprochen, dass das Murks ist. Nicht notwendigerweise die Funktion an
sich, sondern das Auslagern in die vielen Files. Da findet man doch
nichts mehr.
An den TO
Sieh dir auch an, wie Hannes kommentiert.
Einen Kommentar wie diesen hier
1
rcall Write_EEPROM ;schreibe Wert in EEPROM
kannst du dir schenken. Ich nenn das gerne einen Alibi-Kommentar. Das da
etwas ins EEPROM geschrieben wird, kann ich zur Not auch erraten, wenn
ich mich frage, welche Funktionalität sich hinter einer Funktion
'Write_EEPROM' verstecken wird. Man muss nicht Uri Geller heissen um das
zu erraten. Kommentier lieber was im EEPROM wo abgelegt wird. Generell:
Kommentiere das Warum und nicht das Wie. Ein Kommentar soll mir erzählen
warum etwas passiert, welche Nebenbedingungen es gibt, was sich aus
einer höheren Sichtweise gesehen an dieser Stelle abspielt. Wie das
gemacht wird steht im Code.
Zum Teil laufen deine Kommentare schon in diese Richtung, aber die
meisten sind von der ersten Sorte.
Hi
Hannes und Karl Heinz haben meine Meinung zu deinem Programm schon auf
den Punkt gebracht. Erspart mir einige Schreiberei. Danke.
Ein paar Bemerkungen zu deinem Programm:
>;*************************Variablendeklarationen*********************** ********>.def Messergebnisleft = r16>.def Messergebnisright = r17>.....>.def Rechtsaus = r24>.def Linienerkennung = r29
Was soll das in den Registern? Dein AVR hat Ram.
>;*****************************Hauptprogramm**************************** ********>Hauptprogramm:>rcall ADC_Kanal0>rcall StartADC
Mach dir ein Unterprogramm das die AD-Wandlung macht. Übergabe des
Kanals in
einem Register und Rückgabe des Wertes in einem/dem Register.
.....
>RechtsKleiner:> cbr Linienerkennung, 4>rjmp MessungZW3>;##################################################
Das hatten wir schon. (sinnloses herumgehüpfe)
>in Messergebnisleft, ADCH ;Messe Wert auf schwarz vom linken LDR>add r25, Messergebnisleft ;Summe von Wert auf Schwarz und Wert auf Weiß>in r28, SREG>sbrc r28, 0
Das ist No go
Lesbar und auch noch kürzer:
1
add r25, Messergebnisleft ;Summe von Wert auf Schwarz und Wert auf Weiß
2
brnc xyz
3
ldi r28, 0b10000000
4
xyz: mov r30, r25
>ldi r28, 0b10000000>mov r30, r25>ldi r31, 2>rcall division
Die Division kannst du dir sparen. Ein 'lsr r25' reicht.
>mov Schwellwertleft, Ergebnis>add Schwellwertleft, r28
Bist du sicher, das du u.U. SREG addieren willst (->in r28, SREG) ?
>push Ergebnis
Ich habe nicht alle deine Threads komplett verfolgt, aber etliche
Vorschläge kommen mir bekannt vor. Kann es sein, das du etwas
beratungsresistent bist.
MfG Spess
Wie ist das der Programmfluss?
Wenn Linienerkennung 0x01, 0x02, 0x04 ist, dann geht es einmal runter zu
einem Label, da sind dann 2 Befehle und es wird wieder hochgesprungen.
Ziel der Sache ist es, dass diese Befehle nur dann ausgeführt werden,
wenn eine bestimmte Bedinungung wahr ist.
Das kann man auch in der Logik umdrehen: Wenn die entsprechende Bedinung
nicht wahr ist, dann werden ganz einfach die beiden Befehle
übersprungen.
Das sieht dann so aus
Die ganze Sequenz ist fast um die Hälfte kürzer geworden. Ausserdem muss
man nicht mehr ständig auf und ab scrollen um zu sehen, was die Abfragen
bei Linienerkennung überhaupt bewirken. Auf einer halben Bildschirmseite
kann man mit '3 Augenbewegungen' sowohl die Bedingungen als auch die
davon abhängige Operation überblicken. In der Logik hat sich nichts
geändert, aber durch die Schreibweise hat alles an Klarheit gewonnen.
Warum wir auf solchen Dingen so dermassen rumreiten:
Weil ein gutes, möglichst fehlerfreies Programm auch immer eine Frage
des Programmierstils ist. Programme die unübersichtlich sind, bei denen
wie wild herumgespungen wird, es schwierig ist den Programmfluss zu
verfolgen, sind tendenziell genau die Programme, bei denen laufend
irgendwelche Fehler auftreten. Fehler die dann nicht dadurch behoben
werden, dass man zunächst die Programmstruktur bereinigt, sondern
dadurch, dass wieder irgendwo ein 'Heftpflaster' aufgeklebt wird,
welches sich dann oft genug als neuer Quell von neuen Fehlern entpuppt.
Man würde ja gerne sauber korrigieren aber in der Jump-Flut findet man
die Stelle gar nicht, wo mein eigentlich ansetzen muss.
Programme hingegen, die eine saubere äussere Form haben, bei denen der
Programmfluss im wesentlichen von oben nach unten verfläuft und nur in
Ausnahmefällen kommt ab und zu ein Sprung vor (der dann meistens auch
nicht sehr weit geht), das sind die Programme, die man im Kopf gut
verfolgen kann, bei denen sich einem die dahintersteckende Logik
förmlich aufdrängt und das sind auch die Programme, die meistens
wesentlich weniger Probleme machen.
Ob Programme mmöglichst fehlerfrei sind oder nicht, ist nicht nur eine
Frage der Logik, sondern auch oft eine Frage der äußeren Form und wie
kompliziert ein Programm aufgebaut ist. Je verwickelter desto
wahrscheinlicher ist es, das Problemstellen unentdeckt bleiben. Je
geradliniger, desto besser sieht man Probleme.
Ein Programm in kleinere Blöcke zu zerteilen ist grundsätzlich eine gute
Sache, keine Frage. Aber du hast es ganz einfach übertrieben. Deine 2
Zeilen Unterprogramme ADC_Kanal0, ADC_Kanal1, ADC_Start und was da noch
so alles kreucht und fleucht, verschleiern mehr als sie Klarheit ins
Programm bringen. Man muss ständig rumscrollen (oder Files wechseln) um
sich zu vergewissern ob und wenn ja welche Register verändert werden, ob
sie ordnungsgemäss gesichert werden oder nicht, welche global
verwendeten Register verändert werden, etc ...
Andy11 schrieb:> sry fürs 2mal posten is mir unabsichtlich passiert
Ich habe (nach Lesen des Anhangs) den Eindruck, Du operierst hier an
etwas herum, was Du nicht selbst ausgedacht hast und was Du auch nicht
verstehst.
Ich traue mich zu behaupten, dass ich AVR-ASM halbwegs verstehe, mir
gelingt es aber nicht, den Sinn Deines Programms bzw. Deiner Algorithmen
zu erschließen. Gut, ich könnte mir mehr Mühe geben, Dein Programm zu
analysieren. Aber einige Dinge sind dermaßen unsinnig, dass sich in mir
etwas wehrt, weiterzumachen.
Wenn Dir einer helfen soll, dann wirf das Programm weg und beginne von
vorn. Aber nicht gleich mit Programmcode, sondern erstmal mit dem
Konzept, also mit einer klaren und eindeutigen Beschreibung der zu
erledigenden Aufgaben in deutscher Sprache. Es muss ja nicht unbedingt
ein genormter Programmablaufplan oder Struktogramm sein, aber man sollte
die Gesamtaufgabe und die Aufteilung in einzelne Jobs (und deren
Abhängigkeiten voneinander) klar und unmissverständlich erkennen können.
Es schadet auch nicht, im ersten Schritt eine Auflistung zu machen,
welche verschiedenen Aufgaben das Programm erledigen soll/muss.
...
Hannes Lux schrieb:> Ich habe (nach Lesen des Anhangs) den Eindruck, Du operierst hier an> etwas herum, was Du nicht selbst ausgedacht hast und was Du auch nicht> verstehst.
den Eindruck bekomme ich bei deinem Schreiben allerdings auch schon!!
>Ich traue mich zu behaupten, dass ich AVR-ASM halbwegs verstehe,
scheinbar tust du es nicht!
>Gut, ich könnte mir mehr Mühe geben, Dein Programm zu>analysieren.
hättest du vielleicht zuerst machen müssen und dann posten
>Aber einige Dinge sind dermaßen unsinnig, dass sich in mir>etwas wehrt, weiterzumachen.
argumente?!!?
>Wenn Dir einer helfen soll, dann wirf das Programm weg und beginne von>vorn.
das habe ich mit dem vorigen schon gemacht: Das erkennt man auch daran
das ich viel weniger code verbrauche und fast alle unterprogramme
optimiert habe
>Aber nicht gleich mit Programmcode, sondern erstmal mit dem>Konzept, also mit einer klaren und eindeutigen Beschreibung der zu>erledigenden Aufgaben in deutscher Sprache.
Meiner MEinung nach ist das neue coding, das allerdings ich geschrieben
habe, viel lesbarer als das ältere und mehr Kommentare passen erstens
mal nicht rein und zweitens sind sie nicht notwendig.
Ich habe alles was spess gesagt hat gemacht ohne noch zu wissen, dass er
es gesagt hat. Erst als ich es gepostet habe ist es mir aufgefallen.
>Es schadet auch nicht, im ersten Schritt eine Auflistung zu machen,>welche verschiedenen Aufgaben das Programm erledigen soll/muss.
Wenn du meinst, dass ich das noch nicht gemacht habe, dann nehme ich das
in Kenntniss
spess53 schrieb:> Dein Wort in Gottes Ohr.
anscheinend hast du mein neues coding auch noch nicht wirklich
durchgeschaut, daher die Bemerkung wahrscheinlich.
Ich erwarte mir jetzt sicher keine Antworten mehr, ich wollte lediglich
manche Dinge klarstellen.