Hallo zusammen,
ich hab mal wieder ein Frage an die Gemeinde. Nach dem mir hier mit
meinem Handler Problem super geholfen wurde, stehe ich vor dem nächsten.
Vermende einen Atmega16, 16Mhz, AVR Studio, Pollin Board und Ponyprog
Zur Projekt-Beschreibung:
Ich möchte ein Codeblech einlesen. Dieses hat drei horizontale Spuren
und wird mit drei Lichtschranken die vertikal angeordnet sind
eingelesen. Die obere Spur stellt eine binär Zahl dar. Die mittlere
dient quasi als Taktgeber und die unter ist wieder eine binärzahl
interveniert zur oberen Spur. Das sieht dann etwa so aus:
dritte und Vierte Zeile = Spur1
fünfte und sechste = Spur2
siebte und achte = Spur3
1
1 *********************************
2
2 *
3
3 * **** ** **
4
4 * **** ** **
5
5 * ** ** ** ** **
6
6 * ** ** ** ** **
7
7 * **** **
8
8 * **** **
9
9 *
10
0 ********************
Ich wollte Spur 2 über den Int0 laufen lassen. Als erstes muss er mal
überhaupt das Blech erkennen. Int0 erkennt was springt zu Unterprogramm
"Blech". (r22 soll als Merker fungieren) Im ersten durchlauf ist r22=0
also liest er die anderen Lichtschranken ein und erkennt das ein Blech
da ist. Am Ende der Schleife soll er in r22 zB eine 1 schreiben. Wird
der Int0 wieder ausgelöst soll er schauen welchen Wert r22 hat und
entsprechend in ein Unterprogramm springen. Also etwa so:
r22=0 macht er nix (loop
r22=1 (Blech erkannt, als springe zu Abfrage bit0)
r22=2 (bit0 gelesen also springe zu bit1
r22=3 usw. usw.
Mein Problem ist jetzt, das er beim ersten Int0 zwar die Lichtschranken
einliest, aber bei einem zweiten nichts mehr macht.
1. Frage: Wieso regiert Int0 beim zweiten mal nicht mehr?
2. Frage: Wie gestalte ich diese Abfrage am schlauesten?
Viel Text und etwas umfangreich aber ich hoffe ich konnte erklären was
ich machen will. Falls nicht gerne nachfragen.
PS: Die Texte dienen mir im Moment nur zur Kontrolle.
Vielen Dank schon mal an alle konstruktiven Posts
Gruß Suschi
S. Landolt schrieb:> Frage 1: Der globale Interrupt wird nicht mehr freigegeben. Das /reti/> in EXT_INT0 wird ja nie erreicht, vorher steht rjmp Blech.
Und von Blech gehts weiter zu loop und dort sehe ich auch noch
Displayausgaben - und das alles im Interrupt.
@Thomas
dein Bild schein nicht zu recht zu deiner Beschreibung zu passen, die
Spur für den Takt sollte doch in gleichmäßigen Abständen Löscher haben
und von invertiert sehe ich auch nichts. Ein Bild vom Blech hätte die
Sache vereinfacht.
Sag mal wie du mit den Daten weiterarbeiten willst und wie viele Bits
verarbeitet werden müssen. Ich würde mit dem Int (Takt) den Zustand aus
(1) und (3) einlesen, prüfen ob die ungleich sind und dann das Bit in
ein Byte schieben. Wenn 8 Bit gelesen sind das Byte im RAM in eine
Tabelle schreiben, Byte löschen und warten das x-Bits/Bytes (alle)
gelesen sind.
Sascha
> Und von Blech gehts weiter zu loop und dort sehe ich auch> noch Displayausgaben - und das alles im Interrupt.
Richtig, und irgendwann geht es zu
loop1: rjmp loop1
und das war es dann.
Hallo ihr beide,
danke erstmal für eure Antworten. Mein erster grundlegender
Gedankenfehler war das ich dachte ich könnte aus der Interruptroutine
springen und die sich von selbst beendet. Jetzt wo ich es schreibe merke
ich wie , sagen wir mal einfältig, das war. Die ganzen loops und
textausgaben sind nur da, damit ich auf dem lcd sehe wo ich mich
befinde, bzw bis wohin es funzt.
Das gezeichnete Blech ist nur der Anfang. Es sind insgesamt 8 bits
einzulesen. Das "C" förmige Loch dient nur zur sicherstellung das es ein
codeblech ist und keine andere Störkontur.
die verarbeitung hab ich mir so in der Art gedacht:
sbis PIND,2
rjmp bit1
rjmp start_lesen ; weiter fortsetzen
bit1:
sbis PIND,2 ;wenn gesetzt, Abfrage wiederholen
rjmp bit1 ;wiederholt so lange bis LS2 frei ist
rjmp bit1_1 ;wenn gsetzt dann zu bit1_1 springen
bit1_1:
sbis PIND,1 ;Abfrage LS1
rjmp bit1_1_1 ;wenn LS1 gesetzt, dann zu bit1_1_1 springen
sbis PIND,2 ;Abfrage LS2
rjmp bit2 ;inzwischen gesetzt? dann weiter zu bit2
rjmp bit1_1 ;nicht gesetzt dann weiter abfragen
bit1_1_1:
sbis PIND,1 ;wirklich gesetzt?
rjmp bit1add ;wennja springe nach bit1add
rjmp bit1_1 ;wenn nein springe nach bit1_1
bit1add:
add r20, r21 ;ja, dann addiere r21 zu r20
push r20
rjmp bit1_sub
bit1_sub:
hier stand noch eine subtraktion.. kann nur gerade nicht in den keller
an den laptop. Aber ich habe von r21 1 abgezogen. beim nächsten bit 2 zu
r20 addiert und 2 von r21 abgezogen. Am Ende beide register vergleichen
und die Zahl ausgeben bzw. einen Fehler ausgeben.
Zu Frage 2 vom Anfang: als Grundgerüst könnte das Programm im Anhang
dienen. Es beinhaltet noch keinerlei Fehlerkontrolle, da ließe sich viel
machen, speziell, wie von Ihnen angedacht, die Auswertung der negativen
Spur mit einem 'BlechByte_neg' o.ä.
(Irrtum vorbehalten, ausprobiert habe ich es nicht)
Nur am Rande, Ihr
> ldi temp1, (1<<ISC00) ; INT0 und INT1 auf fallende Flanke konfigurieren
ist nicht richtig, es ergäbe "Any logical change on INT0 generates an
interrupt request".
Du hast ein Oszilloskop ? Ohne ist's einfach viel schwieriger.
Falls du Einfluss auf das code Blech hast, verwendet man dafuer
normalerweise einen "Gray Code", der aendert von Position zu Position
nur ein einzelnes Bit.
Thomas S. schrieb:> Wie mach ich das am schlausten?
Bitte gib das nächste Mal einen sinnvollen und aussagefähigen
Threadtitel an. Denn nur "Wie mach ich das am schlausten?" könnten viele
schreiben...
Zum eigentlichen Problem: ich würde dafür keinen Interrupt nehmen,
sondern das Ganze einfach per Polling in einem 1ms Timerinterrupt
machen.
Und noch einer, sorry (ohne Kaffee ist das einfach nichts): statt
brtc INT0_Ende
muss es natürlich heißen
brcc INT0_Ende
(wo sollte auch das T-Flag herkommen)
Thomas S. schrieb:> Wie gestalte ich diese Abfrage am schlauesten?
Ohne Interrupts (oder wenn, dann nur einen regelmässigen TIMER).
regelmässig die 3 Eingänge simultan abfragen
track=PORTB;
dann die Zustandswechsel auf Spur2 beachten.
Wenn ich das richtig sehe, ist der versetzt zur Spur1 und Spur3 und das
Ende des Lochs ist der Trigger
changed=track^oldtrack;
if((changed&2)&&!(track&2)) data=data+data+(track&1);
und vor dem nächsten Durchlauf
oldtrack=track;
So entstehen in data die hineingeschobenen Bits (die man irgendwann
wieder rausholen muss). Man kann auch die invertierten Data Bits
einlesen und mit den nicht-invertierten zur Fehlerprüfung verbinden,
falls du weissst, was du im Fehlerfall machen sollst.
Oh D. schrieb:> Falls du Einfluss auf das code Blech hast, verwendet man dafuer> normalerweise einen "Gray Code", der aendert von Position zu Position> nur ein einzelnes Bit.
Das ist doch Unfug. Da es eine Clock-Spur gibt, positioniert man den
Sensor für diese Spur so, dass z.B. mit der steigenden Flanke die Daten
auf den anderen Spuren gerade stabil sind. So hat man über Jahrzehnte
Lochstreifen mit direkter Binärkodierung ausgelesen. Was soll der
Gray-Code da für Vorteile bringen?
Der Gray-Code wird verwendet, wenn die Spuren ohne zusätzliches
Taktsignal gelesen werden sollen/müssen.
@Thomas
Hast Du Dir mal einen alten Lochstreifen angesehen? Die hatten insgesamt
9 Lochreihen, so wie in dem Schema unten
1 X X X X X
2 X X X X
3 X X X X X X X X
4 X X X
5 X X X X X X
6 x x x x x x x x
7 X X X X
8 X X X X X
9 X X
Die Reihen 1-5 und 7-9 waren Datenbits (große Löcher) und 6 war die
Synchronspur (kleine Löcher). Bei jedem Synchronimpuls wurden die
Datenbits der Reihe gelesen.
Genau so würde ich das realisieren. Du mußt ja nicht 6 Datenreihen
nehmen. Mit 3 Reihen ginge es auch. Bei jedem Synchronimpuls wird Reihe
1 und 3 ausgelesen und in einen Puffer geschrieben, nach 8
Synchronimpulsen werden der Puffer gelesen und weiter verarbeitet.
Nach jedem Byte kann man den Punktabstand ja größer machen so zur
Trennung oder ein Leerbyte folgen lassen oder ... .
Und da bin ich mit MaWin einer Meinung Interrupts braucht es dann nicht.
Den Lesetakt gibt die Synchronspur vor.
Wie man das in Assembler realisiert kann ich Dir nicht sagen, da hab ich
zu wenig Ahnung von. War auch eher als Gedankenanstoß gedacht.
Zeno
Erstmal herzlichen Dank an alle für eure ganzen Ideen und Anregungen.
Ich versuche mal alle Fragen zu beantworten.
Ich habe nur einfachstes Equipment. Multimeter usw. kein Oszilloskop
oder ähnliche "Profi" Geräte. Ich habe mal ein Bild angehängt dieses
zeigt ein Blech mit der Zahl 14. Damit kann man glaube ich gut erkennen,
wie das Programm vorgehen muss. Ich hänge auch mal ein kurzes Prog an,
das bis zur ersten bitabfrage auch schon funktioniert. Wie gesagt, die
meisten Texte sind für mich um zu erkennen wo das Programm steht, oder
falls mal was nicht funktioniert. Alles seht Laienhaft ich weiß, aber so
komme ich Gedanklich wenigstens mit. Leider habe ich selten mal ne
Stunde am Stück Zeit um mal wirklich voran zu kommen.
Ich bin wirklich am überlegen das ganze ohne Handler aufzuziehen. Ich
dachte erst, das wäre der Stein der Weisen, inzwischen bin ich mir da
nicht mehr so sicher. Eine einfache Abfrage der Pins dürfte ohne
weiteres auch gehen. Hintergrund ist a) die Geschwindigkeit, mir der das
Blech an den Lichtschranken vorbeifährt. Die Ausstanzungen sind 10mm
breit. Bei 6m/min sind das gerade mal eine Zehntel Sekunde Zeit zum
auswerten. Ziel sind aber 12m/min was dann gerade mal 0,05s Zeit wäre.
Hinzu kommt das ich nicht gerade über die umfangreichsten Assembler
Kenntnisse verfüge. Eine Logik Abfrage mit den Pins bekomme ich aber
sicher hin. Habe gestern Abend mal einen Gedankengang umgesetzt der aber
leider an der Hardware gescheitert ist. Die Lichtschranken stehen nicht
genau vertikal zueinander. Das muss ich erst mal in Ordnung bringen.
Außerdem sind die Lichtschranken uralt (2003 schon von ifm abgekündigt
^^ ) Zum probieren wirds aber reichen.
Vielen Dank nochmals an alle
Gruß Thomas
Thomas S. schrieb:> Ich bin wirklich am überlegen das ganze ohne Handler aufzuziehen. Ich> dachte erst, das wäre der Stein der Weisen, inzwischen bin ich mir da> nicht mehr so sicher. Eine einfache Abfrage der Pins dürfte ohne> weiteres auch gehen. Hintergrund ist a) die Geschwindigkeit, mir der das> Blech an den Lichtschranken vorbeifährt. Die Ausstanzungen sind 10mm> breit. Bei 6m/min sind das gerade mal eine Zehntel Sekunde Zeit zum> auswerten. Ziel sind aber 12m/min was dann gerade mal 0,05s Zeit wäre.
Und ?
50ms sind unheimlich viel Zeit fur einen uC. Ausserdem interessiert
dich die Geschwindigkeit überhaupt nicht. Die mittlere Spur (Clock)
fängt vor dem bit an und endet genau in der Mitte.
Deswegen kannst du den ClockPin in einer Schleife abfragen, wenn
auf Log.1 (Ausstanzung für Clock am Anfang) wird die Routine aufgerufen
welche die entsprechende Pointer und Bitzähler vorbereitet und auf das
Ende der Ausstanzung wartet (Log.0 am ClockPin).
Wenn es soweit ist, werden die Spuren 1 und 3 eingelesen, um eine
Stelle verschoben, Spur 3 wird invertiert und mit Spur 1 verglichen.
Habe keine Lust zum Rechnen, schätze aber, dass dein Blech auf diese
Weise ohne Probleme mit 1000-facher Geschwindigkeit vorbeisausen kann,
also mit mehr als 700Km/h, ohne das irgendein bit verloren geht.
Und Bit0 kann mit 500Km/h anfangen und Bit7 mit 5m/h enden, trotzdem
wird es richtig erfasst.
P.S.
Int0 kann man sowohl auf fallende als auch auf steigende Flanke
einstellen, wenn du das für ClockPin nutzt, kannst du sogar die LCD
Ausgabe soweit vorbereiten, dass die auch mitkommt.
Ob du das auch lesen kannst, ist eine andere Frage ;)
Thomas S. schrieb:> Die Ausstanzungen sind 10mm> breit. Bei 6m/min sind das gerade mal eine Zehntel Sekunde Zeit zum> auswerten. Ziel sind aber 12m/min was dann gerade mal 0,05s Zeit wäre.
Wow !
Da macht der uC ca. 400000 Instruktionen. Was soll er nach den 40
machen, die er zur Erkennung braucht ? Aus Langeweile noch die grösste
aller Primzahlen ausrechen ?
Ein effektives Auswerteprogramm könnte den Streifen mit bis zu 300000
m/min auswerten. Wenn nach dem Streifen Zeit ist und man nur die Daten
erfassen muss und hinterher auswerten kann sogar mit 2400000 m/min.
Hi,
ich werde das mit der Schleife und Clockpin mal ausprobieren, mal sehen
wie weit ich komme. Gebe dann eine Rückmeldung. Der "Flaschenhals" der
Auslesung wird demnach nicht der uC sein, sondern die Lichtschranken.
Thomas S. schrieb:> Der "Flaschenhals" der Auslesung wird demnach nicht der uC sein,> sondern die Lichtschranken.
Warum könnten die Lichtschranken ein Flaschenhals sein?
Genau, hab das Datenblatt gerade nicht zur Hand, aber es sind IFM
OG5045. Glaube 500Hz können die maximal. Problem ist dort eher die
Streuung der Linse. je weiter das Blech weg ist, umso größer ist der
Lichtfleck. Sind seit 2003 abgekündigt. Hatte die aber noch hier
rumliegen und zum versuchen tun sie es allemal. Passt dann mal alles wie
es soll, werde ich wohl 3 Leuze Laserlichtschranken kaufen. Aber jetzt
sind mir die 300 Euronen noch zu teuer.
Gruß Thomas
Michael B. schrieb:> Lothar M. schrieb:>> Warum könnten die Lichtschranken ein Flaschenhals sein?>> Phototransisoren sind langsam.
Relativ.
Normalerweise zwischen 1-50us, selbst das reicht vollkommen, aber
es wird sowohl der Anfang der Ausstanzung, als auch das Ende um die
selbe Zeit verzogert, somit ist es absolut uninteressant.
Und selbst wenn - die Lichtschranken für Spur1 und Spur3 haben auf
jeden Fall genügend Zeit, um die Ausstanzung richtig zu registrieren,
da diese schon 1/2 bit vorher angefangen hat.
Thomas S. schrieb:> werde ich wohl 3 Leuze Laserlichtschranken kaufen. Aber jetzt> sind mir die 300 Euronen noch zu teuer.
Mit stinknormalen BPW-40 Fototransistoren und einem hellen Licht drüber
kannst du locker ein ein 10-20 kHz Signal auswerten. Und mit Fotodioden
ists sowieso kein Problem.
Aber wenn du gerne viel Geld ausgibst ...
Thomas S. schrieb:> Ich möchte ein Codeblech einlesen
Was soll das sein, ein "Codeblech"?
Oben schreibst du, dass du einen Lochstreifen einlesen willst.
Wo kommt der her?
Am besten machst du mal ein Foto davon.
Hi,
die Überschrift wurde vom Admin erweitert, weil sie nicht aussagekräftig
war. Mein Fehler. Es ist weniger ein Lochstreifen wie man es von den
alten NC Maschinen her kennt, sonder ein Blech. Etwa in der Mitte des
Threads hab ich ein Bild angehängt.
@derAndere
Natürlich gebe ich nicht gerne mehr Geld aus als nötig. Funktioniert
dein Vorschlag auch wenn zwischen Lichtschranke und Reflektor 1m Spalt
ist und das Blech dann mittig vorbei fährt? also 50cm Abstand zum
Sender? Ich kenne da nur die Lichtschranken als Industriestandard.
LG
Thomas S. schrieb:> Natürlich gebe ich nicht gerne mehr Geld aus als nötig. Funktioniert> dein Vorschlag auch wenn zwischen Lichtschranke und Reflektor 1m Spalt> ist und das Blech dann mittig vorbei fährt? also 50cm Abstand zum> Sender? Ich kenne da nur die Lichtschranken als Industriestandard.
Nimm doch 3 Module mit Laserdioden, kosten zusammen nicht mal zwei
Euro.
Mit Empfangsmodulen kommst du auf weniger als 5 Euro für alles.
Thomas S. schrieb:> Ziel sind aber 12m/min was dann gerade mal 0,05s Zeit wäre.
Und was soll der µC hauptamtlich machen. Alle 50 ms eine Bitposition
wird ihn langweilen und selbst bei der 50-fachen Geschwindigkeit wird er
nicht ins grübeln kommen, wenn du das Programm vernünftig aufbaust.
Thomas S. schrieb:> Ich habe nur einfachstes Equipment. Multimeter usw. kein Oszilloskop> oder ähnliche "Profi" Geräte.
Dann solltest du vielleicht mal in einen Logikanalysator investieren.
Kleine, aber durchaus sehr nützliche Dinger gibt es auf Basis des
CY3684 von Cypress als USB-LA mit 8 Kanälen und bis zu 24MSa/s z.B. bei
Ebay ("8Ch 24MHz") für mittlerweile unter 7€. Das wäre doch was für
Weihnachten ;-)
@Mark: Das mit den Lasermodulen ist eine interessante Idee. Ich werde
das mal im Hinterkopf behalten. Die Hardware steht für mich im Moment
noch an zweiter stelle. Zuerst soll mal das Programm ordentlich laufen.
@Wolfgang: Preislich im Rahmen des möglichen ^^. Aber was macht das
Dingen denn oder anders gefragt wie hilft es mir beim simulieren o.ä.?
Wenn ich das richtig interpretiere, wird der Analyser an die Pins
angeschlossen, oder gibt es auch eine Möglichkeit Werte einzelner
Register zu prüfen?
Thomas S. schrieb:> @Wolfgang: Preislich im Rahmen des möglichen ^^. Aber was macht das> Dingen denn oder anders gefragt wie hilft es mir beim simulieren o.ä.?> Wenn ich das richtig interpretiere, wird der Analyser an die Pins> angeschlossen, oder gibt es auch eine Möglichkeit Werte einzelner
Zumindest kann man sehen, was als Signal reinkommt und kann das
zeitlich einordnen, d.h. wenn der LA den richtigen Signal aufzeichnet,
dann sind eventuelle Fehler beim Auswerten in deinem Programm zu
suchen.
Thomas S. schrieb:> @Mark: Das mit den Lasermodulen ist eine interessante Idee. Ich werde> das mal im Hinterkopf behalten. Die Hardware steht für mich im Moment> noch an zweiter stelle. Zuerst soll mal das Programm ordentlich laufen.
Du kannst mit einem Arduino als Hardware ohne Probleme den ganzen
Prozess simulieren, d.h. mit 3 Arduino Pins werden die Lichtschranken
simuliert.
Von Überschallgeschwindigkeit bis zum Stillstand, von überhaupt keiner
Verzögerung bis zur 1-20ms, usw, usw.
Probiere es doch erst mal so, ist viel einfacher.
Ich werde mir so ein Ding auf jeden Fall mal bestellen. Bei dem Preis
kann man nichts verkehrt machen. Allerdings habe ich bereits einen
Versuchsaufbau mit den Lichtschranken im Keller stehen. Ich kann also
direkt sehen was passiert. Falls ich das nicht erwähnt habe, dann sorry.
Ich habe auch mal wieder etwas an dem Prog gebastelt. Allerdings bin ich
mir nicht sicher ob ich das so richtig aufziehe.
Ich wollte das ganze mit 2 Merkern machen. r22 als
"Initialisierungsmerker" und r23 als Merker für die Bit Einlesung.
Gedacht war eigentlich, das ich bei einem Handleraufruf in eine Abfrage
springe und den Merker r22 abfrage. Dieser ist am Anfang =0 und dann
sollte abgefragt werden ob es wirklich ein Blech ist. Wenn ja, dann wird
der Merker auf 1 gesetzt, ansonsten soll er wieder zurück springen in
die "Wartestellung". Kommt wieder ein Handleraufruf und der Merker =1
dann soll er den Zwischensteg abfragen und dann den Merker=2 setzen und
zurück springen. Am LCD kann ich im Moment auch sehen was passiert, und
die Lichtschranken haben auch LED´s an den ich den Zustandswechsel
erkennen kann.
Mein erster Fehler war ja das ich aus der Handlerabfrage mit rjmp
herausgesprungen bin und den nicht beendet habe. Ist das jetzt so besser
mit rcall?
Und jetzt die Überraschung... leider funktioniert es nicht ganz so wie
es soll. Auch wenn ich nur die Lichtschranke2 betätige, wird das UP
"test" aufgerufen. Ich kapier nur nicht warum denn um das anzuzeigen,
muss er ja das UP "Blech_Anfang" durchlaufen haben was ja eigentlich
nicht sein kann wenn Lichtschranke 1 und 3 nicht belegt sind. Liegt es
an den "ret"´s?
Thomas S. schrieb:> Und jetzt die Überraschung... leider funktioniert es nicht ganz so wie> es soll. Auch wenn ich nur die Lichtschranke2 betätige, wird das UP> "test" aufgerufen. Ich kapier nur nicht warum denn um das anzuzeigen,
Mal abgesehen davon, dass dein Programm total unübersichtlich und ein
Schulbeispiel für Spaghetticode ist - wie kriegst du überhaupt etwas
auf dem LCD angezeigt ?
Alle Ports werden als Eingänge gesetzt bis auf PortA und bei dem
werden nur 3 bits als Ausgang gesetzt ?
Werde mir mal später dein Programm genauer anschauen.
Das LCD hängt an PortA. Falls du Zeit und Lust hast, kannst du mir gerne
mal näher bringen wie man es besser strukturieren kann. Ich bin da
wirklich gerne lernbereit. Ich kenne halt nur die kurzen Prog-Schnipsel
aus dem tutorial. Aber zugegebener Maßen habe auch ich teilweise
Probleme alles nachzuvollziehen, deswegen auch der ganze Haufen
kommentare (sind aber teilweise veraltet)
Gruß Thomas
Thomas S. schrieb:> Das LCD hängt an PortA.
Das ist mir schon klar, aber es werden nur 3 Pins als Ausgang gesetzt
und das reicht eben nicht.
> Falls du Zeit und Lust hast, kannst du mir gerne> mal näher bringen wie man es besser strukturieren kann.
Muss jetzt raus, erst am Nachmittag, aber an deiner Stelle würde ich
(zumindest am Anfang) die Pins in einer Schleife abfragen, anstatt mit
Int zu arbeiten.
Ist viel leichter für Anfänger.
In der ISR "EXT_INT0" wird SREG im Register "temp1" gesichert. Da keine
verschachtelten Interrupts vorgesehen sind, kann man das so machen, auch
wenn ich für das Register einen treffenderen Namen als "temp1" wählen
würde.
In der ISR wird "Abfrage_Merker_init" aufgerufen und dort u.a. "test".
Und in "test" ("test1", "test2") wird "temp1" jeweils überschrieben!
Wahrscheinlich spielt das aber überhaupt keine Rolle da ja Dein
komplettes Programm in der ISR abläuft, und daher der zerstörte
SREG-Inhalt sowieso nie gebraucht wird. Ist nur ein Beispiel dafür, wie
chaotisch das ganze Programm ist.
Vorschlag:
Ganz von vorne anfangen. Programmablaufplan erstellen. Danach ein
Programmgerüst, bei dem man sich z.B. eine sinnvolle Registerbelegung
überlegt, und alle Register, Konstanten, Ports und Portbits, etc., mit
sprechenden Namen versieht.
Dazwischen/davor einen Algorithmus für die Dekodierung überlegen.
Statemachine würde sich hier anbieten (Zustandsgraph/
Zustandsübergangtabelle erstellen.)
Das ganze wird eine Weile dauern, aber danach weißt Du wie geht. Wenn
das Programm schneller fertig werden muß, such Dir jemanden, der es für
Dich oder mit Dir macht.
Oder lass Dir das jetztige Gestrüpp durch Zurufe und "trial and error"
Vorschläge hier im Forum so lange zurecht biegen, bis es irgendwann
zufälling irgendwie funktioniert.
> Thomas S. schrieb:>> Das LCD hängt an PortA.>> Das ist mir schon klar, aber es werden nur 3 Pins als Ausgang gesetzt> und das reicht eben nicht.>>> Falls du Zeit und Lust hast, kannst du mir gerne>> mal näher bringen wie man es besser strukturieren kann.
Ich komme nicht klar mit deinem Programm, hier ist etwas zum
ausprobieren, ohne INT. Kannst nachher immer noch auf INT umsteigen.
Routinen für LCD sind auskommentiert.
Marc V. schrieb:> Ich komme nicht klar mit deinem Programm, hier ist etwas zum> ausprobieren, ohne INT. Kannst nachher immer noch auf INT umsteigen.
Und schon einen Fehler entdeckt:
1
;****************** MAIN LOOP ***********************************
Hi Marc,
erstmal vielen Dank für dein Prog. Ich werde mir das mal genau ansehen,
wie du das gemacht hast. Wird aber eine Weile dauern, da du einige
Befehle verwendest die ich nicht kenne. Ich melde mich dann wieder. Thx
und Gruß
Thomas S. schrieb:> @Marc: Hab dir eine PN geschickt
Hab es gesehen, aber:
a) Vielleicht kann das Ganze noch jemandem nützlich sein.
b) Vielleicht entdeckt jemand noch Fehler in meinem Programm.
Deswegen mache ich so etwas grundsätzlich nicht über email.
Anbei ein Bild mit zeitlichem Ablauf, vielleicht wird dir das Ganze
dadurch etwas klarer.
> verstehe zum Beispiel nicht, in welchem Register die eingelesene Zahl> liegt und wie das abläuft.
Ich habe versucht, das Ganze so übersichtlich wie nur möglich zu
gestalten, aber...
Probiere erstmal das Bild zu verstehen, wenn etwas mit Befehlen
unklar ist, beim ATMEl steht folgendes zum Download bereit:
http://www.atmel.com/images/atmel-0856-avr-instruction-set-manual.pdf
P.S.
Natürlich werde ich deine Fragen beantworten, kein Problem.
Hi Marc,
sorry hat leider ein bischen gedauert. Ich denke mal den Großteil habe
ich verstanden, einige Sachen sind mir jedoch unklar. Das Bild hat mir
dabei sehr geholfen. Ich fang einfach mal an:
1.
.ORG SRAM_START
NormByt: .byte 1
InvByt: .byte 1
Flag: .byte 1
Das sagt mir leider garnichts. Ich habe bisher nichts mit SRAM gemacht.
Für was ist das und warum macht man das so?
2.
Wenn ich das Blech durchschiebe kommt erstmal garnichts. Ich habe darauf
hin eine Textausgabe Stück für Stück verschoben um zu erkennen bis wohin
es funktioniert. Die "Initialisierung" des Blechs funktioniert tadellos.
Bis zu dem rcall test auch.
GetBytWert:
clr temp1
clr temp2 ;* Normalerweise unnoetig, aber zum Verstaendnis...
ldi BitCnt, 8
GBW_1:
rcall GetClkStart
rcall delay50us
rcall GetClkEnd
rcall delay50us
rcall test ;*meine Kontrollausgabe an das LCD
rcall delay1s ;*meine Kontrollausgabe an das LCD
***bis hier her alles prima ***
clc
sbic Licht, Spur1 ;* auch hier wird nur ein Sample genommen
sec
ror temp1
clc
sbis Licht, Spur2
sec
ror temp2
dec BitCnt
brne GBW_1
;* Die beiden Register muessen den gleichen Wert aufweisen, ansonsten
ist es ein Fehler
sts NormByt, temp1
sts InvByt, temp2
ret
Das Blech steht jetzt bei c0 auf dem bild. Müsste ich jetzt nicht erst
sbis Licht,clock abfragen um dann das erste Bit einzulesen? Was der
Befehl "ror" genau macht, habe ich bis jetzt auch noch nicht verstanden.
Er rotiert das Register temp1 und später temp2. Das habe ich verstanden.
Aber die habe ich doch mit clr auf 0 gesetzt. Für was ist das dann gut?
Und dann noch ein Frage:
dec BitCnt reduziert bei jedem Durchlauf um -1, dadurch das vorher der
Wert 8 eingestellt wurde, wiederholt er quasi 8x um alle 8 bits
einzulesen. Wenn BitCnt dann mal 0 ist, wird der Befehl dann einfach
übersprungen?
Ich weiß, viele viele Fragen. Wäre nett wenn du mir das mal näher
bringen könntest. Wie immer, vielen Dank erstmal.
Thomas S. schrieb:> Das sagt mir leider garnichts. Ich habe bisher nichts mit SRAM gemacht.> Für was ist das und warum macht man das so?
Da schreibt man Werte hin, Mega16 hat 1024 Bytes RAM, da passt einiges
mehr rein als in 32 Register. Und wenn man einen Wert aus dem Register
ins RAM geschrieben hat, ist der Register wieder frei für andere
Aufgaben.
> Wenn ich das Blech durchschiebe kommt erstmal garnichts. Ich habe darauf> hin eine Textausgabe Stück für Stück verschoben um zu erkennen bis wohin> es funktioniert.
Und genau so etwas sollte man nicht machen, weil dadurch Register und
deren Inhalt verändert werden, aber vielleicht werden genau diese
Register in dieser Routine noch gebraucht.
Solange man nicht genau versteht was da im einzelnen vor sich geht,
sollte man auch nichts ändern oder neue Befehle dazwischen schreiben.
> Die "Initialisierung" des Blechs funktioniert tadellos.> Bis zu dem rcall test auch.
Es funktioniert auch danach...
Grundsätzlich sollte man am gepostetem Prog nichts ändern, sondern
nur schreiben, dass es bis dahin geht, bis dorthin nicht, usw.
Und wenn man trotzdem etwas ändert, sollte man auch das geänderte
Prog posten.
> Das Blech steht jetzt bei c0 auf dem bild. Müsste ich jetzt nicht erst> sbis Licht,clock abfragen um dann das erste Bit einzulesen?
Nein, denn dein Blech steht jetzt nicht bei c0, sondern bei b0.
> Was der> Befehl "ror" genau macht, habe ich bis jetzt auch noch nicht verstanden.> Er rotiert das Register temp1 und später temp2. Das habe ich verstanden.> Aber die habe ich doch mit clr auf 0 gesetzt. Für was ist das dann gut?
Ich habe dir doch den Link auf .pdf geschickt, da ist es genau
beschrieben, aber hier:
Mit ror wird Carry reingezogen, wenn eine Ausstanzung da ist, wird
Carry auf 1 gesetzt, ansonsten wird Carry auf 0 gesetzt und dieser
Wert wird dann ins temp1 reingeschoben. Für temp2 ist es umgekehrt.
> dec BitCnt reduziert bei jedem Durchlauf um -1, dadurch das vorher der> Wert 8 eingestellt wurde, wiederholt er quasi 8x um alle 8 bits> einzulesen. Wenn BitCnt dann mal 0 ist, wird der Befehl dann einfach> übersprungen?
1
decBitCnt
2
brneGBW_1;*WennBitCntnochnichtNullist,gehezuGBW_1
3
;*BitCntistNull,hierdurchgefallen
4
stsNormByt,temp1;*WertfuerNormalinsRAMschreiben
5
stsInvByt,temp1;*WertfuerInvertedinsRAMschreiben
Und noch etwas:
Die Ausgabe sollte doch erst erfolgen wenn das Blech ganz durch ist,
nicht mitten in der Ausleseroutine, zumindest solange alles noch nicht
ausgetestet ist.
Ich habe dir doch am Anfang die zwei Zeilen für Ausgabe vorgesehen,
die solltest du auskommentieren und probieren.
Also, Blech ganz durchschieben und abwarten ob die Routine auch wieder
hierher zurückkehrt:
1
Byt_OK:
2
;***LCDAusgabefuerOK...
3
rcalllcd_ShowByt_OK;*VorerstnurMeldung"OK"
4
rjmpRdBlech
5
Byt_Err:
6
;***LCDAusgabefuerFehler...
7
rcalllcd_ShowByt_ERR;*VorerstnurMeldung"ERR"
8
rjmpRdBlech
Falls ja, werden wir den Rest ohne Probleme hinkriegen, aber wie
gesagt, ausser den beiden Zeilen für LCD-Ausgabe nichts ändern !
Und Blech mindestens bis sp1 durchschieben, sonst kehrt die Routine
niemals zurück.
Guten Morgen Marc,
danke für die Antwort. Ich hatte als erstes im Prog die beiden o.g.
Textausgaben ergänzt. Wenn ich das Blech durchschiebe, wird allerdings
nichts auf dem LCD ausgegeben. Weder ok, noch Error. Das ich ganz
durchschieben muss hab ich verstanden, da sonst niemals GetByteStop und
folglich auch nicht RdBlech erreicht wird. Anbei das geänderte Prog,
ohne meine LCD Ausgabe zwischendrin (diese steht ganz am Ende
ausgeklammert)
Ich werde heute Abend mal ein Foto der Versuchsanordnung machen und
einstellen.
Update:
Das Programm läuft jetzt durch. Problem sind die Steinzeit
Lichtschranken. Diese haben eine große Streuung. Einen LEO2 kann man
bestimmt super erkennen, aber das ausrichten ist schwierig. Ich habe den
Reflektor mit horizontalen Pappstreifen beklebt, damit sich die
Lichtkegel nicht gegenseitig stören. Wenn ich mich recht erinnere,
sollte man auch nicht mehrere Lichtschranken auf einen Reflektor gehen
lassen. Also ist ein Hardwarwechsel fällig. Die besagten Leuze
Lichtschranken mit Sender und Empfänger sind super, wir setzten die in
der Firma auch ein. Leider haben wir im Moment keine da, die ich zum
testen nehmen könnte. Kaufen scheidet im Moment immernoch aus. Weiter
oben kam der Tip mit Lasermodul und Fotodiode. Ist zwar wieder etwas
Bastellei, aber zumindest das ausrichten wäre dank sichtbaren Punkt
wesentlich einfacher und ich denke auch genauer als der Einsatz eines
Reflektors. Hab hier schonmal das Forum überflogen, aber noch nichts
wirklich passendes gefunden. Da ich eh was bei Pollin bestellen muss,
werde ich einfach mal 3 einfache Laserpointer zu 2,95€ mitbestellen.
Wenn jemand was fertiges in der Kiste hat, Schaltplan oder auch ein
fertiges Empfangsmodul empfehlen kann, dann immer her damit.
In der Zwischenzeit werde ich mich wohl mal etwas mit SRAM,
Schieberegister und UART beschäftigen. Das soll später noch Schritt für
Schritt mit einfliessen. Aber ein Kloß nach dem anderen. Thx
Thomas S. schrieb:> Problem sind die Steinzeit Lichtschranken. Diese haben eine große> Streuung. Einen LEO2 kann man bestimmt super erkennen, aber das> ausrichten ist schwierig.
Bei Blech kommen vielleicht auch Hallgeber in Frage.
Hi Wolfgang. In der Praxis können zwischen Sender Blech Empfänger je
1 Meter liegen, also 2m von Sender zu Empfänger. Das wird für einen
Hallgeber zuviel sein. Ausserdem sitzt das Blech auf einem Stahlgestell,
was auch ein Problem sein könnte. Ich denke ein Laser wäre schon prima,
soll ja auch was gescheites werden.
Thomas S. schrieb:> Hi Wolfgang. In der Praxis können zwischen Sender Blech Empfänger je> 1 Meter liegen, also 2m von Sender zu Empfänger.
Das hatte ich nicht mitbekommen. Dann funktioniert ein Hallgeber
natürlich nicht.
Mit Lichtschanken muss du dir bei solchen Entfernungen die Optik etwas
genauer ansehen. Du kannst z.B. eine einzelne helle Lichtquelle hinter
dem Blech aufstellen und benutzt dann auf der Empfängerseite eine Optik,
die dir ein scharfes Bild von dem Lochmuster auf deine Empfängerzeile
wirft.
Du kannst auch mehrere Lichtquellen in Höhe der Spuren hinter dem Blech
anordnen und auf einen einzigen Detektor leuchten lassen. Die
Lichtquellen werden dann nacheinander eingeschaltet und die Software
weiss dann, von welcher Lochreihe das Licht gerade kommt, i.e. Abtastung
mit Zeitmultplex. Da gibt es verschiedene Möglichkeiten, die von deinen
örtlichen Gegebenheiten abhängen.
Endlich ist es soweit. Die Bauteile sind gestern angekommen und ich habe
heute mal was zusammengebastelt.
Der Versuchsaufbau für die Lichtschranken sieht jetzt wie folgt aus:
Sender ist ein Laserpointer mit einer Wellenlänge von 630nm und < 1mW
Leistung. Als Empfänger habe ich eine Diode BPW34 die mit einem 270KOhm
Widerstand an Masse liegt. Zwischen Diode und Widerstand gehe ich über
einen 680kOhm Wiederstand an den Eingang des Atmega. (Prinzip
Spannungsteiler)
Ich habe ein Miniprog geschrieben, das mir den Schaltwechsel optisch auf
dem LCD ausgibt.(siehe Anhang)
Generell funktioniert das schon ganz gut, aber nicht 100%ig. Ich habe
bei Lichteinfall eine Spannung von 4,95V am Eingang des Atmega, ohne
Lichteinfall etwa max 150mV.
Kann man jetzt die Schaltung noch verbessern, bzw. Betriebssicherer
machen? ich werde jetzt noch mal die anderen beiden Spuren nach gleichem
Schema löten.
Thomas S. schrieb:> Kann man jetzt die Schaltung noch verbessern, bzw. Betriebssicherer> machen?
IMHO sind die Widerstände arg groß. Statt 680kΩ kannst du 10kΩ nehmen
und bei dem Serienwiderstand kannst du bestimmt auf 100kΩ runter gehen,
ohne dass der H-Pegel zu sehr einbricht.
Hab leider den Anhang vergessen. So nun mal ein Bild vom Versuchsaufbau
und anbei auch das Minitestprog. Auf der Clock Spur werden die 11 Stege
sauber erfasst. Auf der ersten und dritten Spur jeweils die 7 Stege. Ich
hab das Prog von Marc jetzt auch mal auf den Atmega geflasht. Es läuft
soweit durch, jedoch kommt am Ende immer die Fehler Routine. Aber
zumindest insoweit schonmal positiv, das es durchläuft. Kann es sein,
das low und high vertauscht sind? Sobald das Blech die Schranke
unterbricht geht der Zähler eins hoch
Thomas S. schrieb:> hab das Prog von Marc jetzt auch mal auf den Atmega geflasht. Es läuft> soweit durch, jedoch kommt am Ende immer die Fehler Routine. Aber
Habe mit einem Tiny deine Lichtschranken simuliert, es funktioniert
ohne Probleme, von 12m/min bis 1694 Km/h.
Bilder im Anhang.
Sende den geflashten Prog nochmal.
Guten Abend Marc,
anbei das Prog. Ich habe schon herausgefunden das der Wert, der in
"Getbytwert" gelesen ist richtig ist. Er liest die Zahl 46 was richtig
ist. Eventuell hängt es mit dem Stopbit zusammen?
Ich habe das Blech eben mal ganz langsam durch die Schranken gezogen.
Dabei ist mir aufgefallen, das wenn die Linie b7 von deinem Bild
erreicht wird, zeigt er wieder "betriebsbereit046" wie ganz am Anfang in
der Init: an. geht die Schranke Clock dann von sp1 runter kommt
"Fehler046".
Ich muss jetzt leider pennen gehen, muss um 5 wieder raus. Bin aber auf
jeden Fall morgen Abend wieder da um weiter zu machen.
Vielen Dank erstmal
Hi,
das mit dem "Betriebsbereit046" tritt seltsamerweise nicht mehr auf. Ich
habe Spur 1 und 2 mal ausgelesen und es wird der richtige Wert
ermittelt. Klebe ich auf einer Spur eine Stanzung zu, erkennt er das und
in temp1 und temp2 werden verschiedene Werte ausgegeben. Das
funktioniert also auch prima. Werde jetzt nochmal bischen probieren
Thomas S. schrieb:> in temp1 und temp2 werden verschiedene Werte ausgegeben. Das> funktioniert also auch prima. Werde jetzt nochmal bischen probieren
Es wird schon gehen.
Wenn es soweit ist, kannst du es mit INT probieren, damit geht die
CPU Auslastung gegen Null ;-)
Hi Marc,
ehrlich gesagt werde ich kein bischen schlauer wo´s hängt.
GetByte:
clr temp1
sts Flag, temp1 ;* Fuer Fehler [aber erst ab Ver.2.x ;) ]
rcall GetBytStart ;* Startbit einlesen
rcall GetBytWert ;* 8 bits Data einlesen
*************************************************
rcall GetBytStop ;* Stoppbit abwarten
ret
Ich weiß nur, das bis zu den *** alles läuft. Bin mir sicher das es am
GetBytStop liegt.
Ich hab mal ein Bild angehängt. Dort sieht man den Laserpunkt auf der
Clockspur. Sobald der vom Blech geht, kommt die Fehlermeldung. Irgendwie
stehe ich "wie der Ochs vorm Berg" ^^
Thomas S. schrieb:> Ich weiß nur, das bis zu den *** alles läuft. Bin mir sicher das es am> GetBytStop liegt.
Du hast die zwei Zeilen nicht ausgetauscht, sondern dringelassen.
Bei mir geht es ohne Probleme durch.
Vom MAIN LOOP bis MAIN LOOP komplett austauschen und probieren.
Ob es daran liegt, weiss ich nicht, aber wenn du sonst nichts
geändert hast...
Wie gesagt, bei mir läuft das Ganze ohne Probleme durch.
Hallo miteinander,
sorry das es eine Weile gedauert hat, bis ich mich wieder gemeldet habe,
ich hatte leider beruflich viel um die Ohren. Zuerst mal was positives.
Alles läuft jetzt. Ich hatte wohl beim rüberkopieren eine Zeile
mittendrin nicht markiert. Keine Ahnung wie das geht, war aber leider
so. Beim Zeile für Zeile durchgehen ist es mir dann endlich aufgefallen.
Inzwischen habe ich es auch hinbekommen, das ganze über den Interrupt
auszulösen. Erste Sahne, ganz wie es sein soll. Hiermit erstmal
herzlichen Dank an alle die sich hier beteiligt haben und nochmal ein
ganz dickes Dankeschön an Marc. Ohne dich wäre ich nicht hier
angekommen.
Mal für die Leute die mit dem Gedanken spielen sich eine Lichtschranke
zu bauen. Ich habe die Pollin Lasermodule in Verbindung mit einer BPW34
verbaut und das funktioniert wirklich super. Allerdings haben die Module
wirklich eine wesentlich Stärkere Leistung als die Laserpointer. Selbst
die Rückreflektion von der BPW34 geht noch mehrer Meter weit. Hier kann
ich mich nur der oftbesagten Mahnung auf Vorsicht anschliessen. Ich
würde nichtmal in den Strahl der Reflektion schauen wollen.
Die Abfrageroutine ist nur ein Teil des Gesamtprojekts, was es später
mal werden soll. Nächstes Teilprojekt ist es nun, verschiedene Taster
und einen Jumper mit einzubinden um zwischen dem "Lauf" der Routine und
einem Menü über das LCD auszuwählen. Das Menü soll mehrere Punkte
bekommen, die dann mittels Taster bedient und verändert werden können.
So nach diesem Schema:
sbic PINB,0 ;** Jumper **
rjmp run
rjmp menue
run: ;**Routine zum einlesen***
menue: ;**Mehrere Punkte. u.A Passwortabfrage, Tests der
Hardware, event. IP-Adresse über Menue eingeben usw. usw
Ich werde euch auf dem laufenden halten.
Falls jemand Fragen hat, einfach hier schreiben.
LG und schönen Abend noch
Thomas S. schrieb:> Inzwischen habe ich es auch hinbekommen, das ganze über den Interrupt> auszulösen. Erste Sahne, ganz wie es sein soll. Hiermit erstmal> herzlichen Dank an alle die sich hier beteiligt haben und nochmal ein> ganz dickes Dankeschön an Marc. Ohne dich wäre ich nicht hier> angekommen.
Freut mich, gern geschehen.
> menue: ;**Mehrere Punkte. u.A Passwortabfrage, Tests der> Hardware, event. IP-Adresse über Menue eingeben usw. usw
Wozu die IP-Adresse und was soll das werden, wenn es fertig ist ?