Da bin ich wieder, ich und meine Schiene mit den 8 IR-Lichtschranken.
Waren letztens im 'Labor' und haben das Ding ausprobiert, funktioniert
auch ganz gut, gibt schöne Kurven für lineare und beschleunigte
Bewegungen (diese 'Bewegungen' durchbrechen auf ihrer Fahrt die
Lichtschranken nacheinander).
Dann bin ich noch auf die glorreiche Idee gekommen, die Zeitmessung doch
mal mit einem anderen Gerät zu vergleichen.
Also haben wir nach der lezten Lichtschranke noch eine zusätzliche
Lichtschranke hingebaut, die dann an den Messverstärker angeschlossen
wurde.
Nach den Messungen machte sich dann doch allgemeine Sprachlosigkeit
breit, besonders bei mir, denn ich hatte das Ding ja gebaut.
Messergebnisse: Bei Zeiten von ca. 0,4 s gab es eine Abweichung von 20%
zwischen den Ergebnissen. Diese Abweichung hat sich aber nicht auf
längere Zeiten ausgewirkt. Als wir beide Schranken ca. 30 Sekunden lang
unterbrochen haben, kan bei beiden so ziemlich das gleiche raus (30sek
und 29,9 sek).
An was kann das also liegen?
Das Messprogramm vom ATmega8 hab ich mal veröffentlicht, falls jemand
einen Fehler in der Software vermutet.
http://home.arcor.de/kreuzfeuer/fa1.html
Zum Programm: Nach der ganzen Initialisierung befindet sich das Programm
solange in einer Endlosschleife (f_loop) bis, zum ersten mal eine
Schranke unterbrochen wird, sich also das Ergebnis von GET_P_C ändert.
Dann fragt das Programm in der Hauptschleife alle 96 Taktzyklen die
Lichtschranken ab und speichert den Zustand und die Anzahl der
Schleifendurchläufe im RAM aber, falls sich etwas geändert hat.
Zuerst mal ein Pendel messen, das gibt gleichmaessige Werte und Zeiten.
Dabei zuerst mal den Messausgang am Scope anschauen. Stimmt das Signal
da noch ?
rene
@rene
> Zuerst mal ein Pendel messen, das gibt gleichmaessige Werte und Zeiten.
Na, ich würde lieber nen (elektronischen) Taktgenerator nehmen.
MfG
Falk
Sehe ich das richtig, dass du während der MessungÜbertragung auf der
seriellen macht, während gleichzeitig die Messung gemacht wird in
dem du die Anzahl der Schleifendurchläufe mitzählst.
Warum machst du es nicht einfach so:
Alle Lichtschranken hängst du zusätzlich an den Input Capture
Eingang vom Timer 1.
Messung startet: Timer auf 0 setzen, Input Capture freigeben.
Jetzt zählt der Timer klammheimlich vor sich hin. Sobald
am Input capture Eingang etwas vor sich geht, kopiert
der Timer seinen aktuellen Wert in ein spezielles Register
und benachrichtigt dich mit einem Interrupt. Im Interrupt
hast du alle Zeit der Welt, den Wert aus dem speziellen
Register zu holen und zu speichern (oder per RS232 zu
verschicken). Auf die Art misst dir der Timer ganz von
alleine die verstrichene Zeit zwischen 2 Ereignissen.
Du brauchst keine Takte zählen, es ist einfacher, in
der Zwischenzeit hast du genügend Zeit was anderes zu tun,
du kriegst die Zeit in Quarzauflösung (dividiert durch den
Prescaler) und nicht zuletzt: Du kannst das bequem in
C programmieren.
> Zuerst mal ein Pendel messen, das gibt gleichmaessige Werte und Zeiten.
Na, ich würde lieber nen (elektronischen) Taktgenerator nehmen.
Falk
@Falk
Du traust der Lichtschranke ? Ich nicht.
rene
> Zuerst mal ein Pendel messen, das gibt gleichmaessige Werte und Zeiten.
Danke das ist eine Gute Idee
> Dabei zuerst mal den Messausgang am Scope anschauen. Stimmt das Signal> da noch ?
Da siehst zur Zeit schlecht aus, da müsste ich wieder ins 'Labor' (was
eigentlich kein Labor ist, sondern der Nebenraum vom Physiksaal :-) )
> Na, ich würde lieber nen (elektronischen) Taktgenerator nehmen.
Den ich zufällig in der Hosentasche hab ;-)
> Sehe ich das richtig, dass du während der MessungÜbertragung auf der> seriellen macht, während gleichzeitig die Messung gemacht wird in> dem du die Anzahl der Schleifendurchläufe mitzählst.
?? MessungÜbertragung auf der seriellen ??
Zu der anderen Messmöglichekeit von Karl Heinz:
Ich denke, dass das daran scheitern wird, dass die gemessenen Zeiten
sehr unterschiedlich sein können, also von 10 s bis 0,001 s und dann
entweder der Timer überläuft oder die Messung auf Grund des Prescalers
zu ungenau wird (wahrscheinlich eher ersteres da mit Prescaler 1024 und
einem Takt von 14MHz Timer1 nach 4,5 sek voll ist)
> Ich denke, dass das daran scheitern wird, dass die gemessenen> Zeiten sehr unterschiedlich sein können, also von 10 s bis 0,001 s> und dann entweder der Timer überläuft
Und wozu denkst du gibt es den Overflow Interrupt?
Deine gemessene Zeit ist dann halt:
Input Capture Wert + Anzahl der Overflows * 65536
Bei 32 Bit Arithemtik, dauert es dann bei einem
Prescaler von 1 und 14 Mhz immerhin 5 Minuten bis
das überlauft. Bei einer Auflösung von 7 * 10^-8 Sekunden
(theoretisch).
> > Na, ich würde lieber nen (elektronischen) Taktgenerator nehmen.> Den ich zufällig in der Hosentasche hab ;-)74HC14 + Widerstand + Kondensator.
MfG
Falk
Hab grad eine Messung mit einem Pendel gemacht (ca. 1,5m Faden, schwarze
Glaskugel unten dran, Amplitude 5 - 10cm)
Der Durchschnittswert der Zeiten ist 0,09804 s
Die maximal Abweichung der Meswerte vom Durchschnitt ist 6%
Die Abweichung vom minimalen zu maximalem Messwert ist 10%.
Ist das jetzt gut oder schlecht? :-?
nochmal @ karl heinz
Jetzt ist mir noch was eingefallen, warum ich nicht deine Methode
verwenden kann: Es können auch zwei Bewegungen gleichzeitig auf der
Schranke ablaufen. D.h. dass unter Umständen eine Schranke unterbrochen
wird, wenn woanders schon länger eine Schranke unterbrochen ist. Das
würde ja dann vom Interrupt nicht erfasst werden und somit würde diesem
Ergebnis auch kein Messwert zugeordnet werden, oder?
>> Den ich zufällig in der Hosentasche hab ;-)>74HC14 + Widerstand + Kondensator.
Sowas hast du in der Tasche?
Das würde mir zu doll pieksen...
>D.h. dass unter Umständen eine Schranke unterbrochen>wird, wenn woanders schon länger eine Schranke unterbrochen ist. Das>würde ja dann vom Interrupt nicht erfasst werden und somit würde diesem>Ergebnis auch kein Messwert zugeordnet werden, oder?
Dafür haben diverse Controller Pinchange-Interrupts. Da wäre es dann
egal, ob ein Eingang ein statisches Signal liefert.
Da könnte man dann nämlich den ganzen Spass so realsieren:
Timer starten, bei Überlauf wird eine weitere Variable (16Bit)
inkrmentiert.
Sobald ein Pinchange-Interrupt auftritt, wird der Timer und die
Überlaufvariable ausgelesen (Da muß man dann den Übertragsmoment noch
beachten) und der Zustand der Eingänge.
Dann guckt man sich den letzten Zustand an, stellt fest, welcher Eingang
sich verändert hat und berechnet für diesen die Differenzzeit (Man muß
sich also den Zeitpunkt jedes Eingangs in einem Feld merken.).
Oder man fragt die Lichtschranken in einem regelmässig auftretenden
Timer-Interrupt ab, der mindestens zweimal so häufig auftritt, wie die
höchste Geschwindigkeit ist (Shannon-Theorem).
> Dafür haben diverse Controller Pinchange-Interrupts.
Meiner aber nicht :-) (ATmega8)
Mir wäre es viel lieber, wenn jemand den Fehler in meinem Programm
finden würde oder eine Idee für eine anderes Programm (das aber mit dem
gleichen Controllerbeschaltung läuft, die ja jetzt wirklich nicht
speziell ist) hätte.
Das mit den anderen Lösungen ist zwar auch interessant, aber bringt
micht jetzt nicht wirklich weiter, da ich nicht mehr die Zeit habe einen
ganz neuen Aufbau anzufangen.
>wenn jemand den Fehler in meinem Programm finden würde
Hat Karl Heinz doch schon gemacht: Dir kommt das USART in die Quere.
Du kannst die Abfrage der Lichtschranken auch in der Hauptschleife
machen und da dann die "Uhrablesen".
Ich habe mir dein Programm (noch) nicht weiter angeguckt.
@Johannes
> Hab grad eine Messung mit einem Pendel gemacht (ca. 1,5m Faden, schwarze> Glaskugel unten dran, Amplitude 5 - 10cm)> Der Durchschnittswert der Zeiten ist 0,09804 s> Die maximal Abweichung der Meswerte vom Durchschnitt ist 6%> Die Abweichung vom minimalen zu maximalem Messwert ist 10%.> Ist das jetzt gut oder schlecht? :-?
Für ne Zeitmessung ist das grotenschlecht.
@fieser Rahul
> >74HC14 + Widerstand + Kondensator.> Sowas hast du in der Tasche?> Das würde mir zu doll pieksen...
Wieso? Hast du keine Haare am Sack? ;-)
> Oder man fragt die Lichtschranken in einem regelmässig auftretenden> Timer-Interrupt ab, der mindestens zweimal so häufig auftritt, wie die> höchste Geschwindigkeit ist (Shannon-Theorem).
Shannon ist hier vollkommen deplaziert.
MfG
Falk
@ oskar
> Dir kommt das USART in die Quere.
Inwiefern?
> Du kannst die Abfrage der Lichtschranken auch in der Hauptschleife> machen und da dann die "Uhrablesen".
Mache ich doch, oder? In der Hauptschleife (main) wird das Macro GET_P_C
doch aufgerufen.
> Ich habe mir dein Programm (noch) nicht weiter angeguckt.
Wäre nett, wenn du das machen würdest. Ich wollte es nicht kürzen, weil
ich sonst sicher die Fehler weg editiert hätte.
@ karl heinz:
Würdest du mir das bitte nochmal genauer erklären: An was denkst du
scheitert die Messung?
Die Zeitmessung hat doch höchste Priorität, oder? Dann den INT mit der
höchsten Priorität zum Messen benutzen: INT0. Wie ein Zähler >16 bit zu
realisieren ist sollte wohl kein Problem sein. Alle anderen Vorgänge
(USART usw.) sind Nebensache und können ausgeführt werden wenn Zeit ist.
Ich würde das Programm zuerst auf Papier strukturieren und dann neu
aufbauen. 75% der Programmierarbeit erfolgt bei mir auf dem
Konzeptblock, wegen der Übersichtlichkeit.
> Jetzt ist mir noch was eingefallen, warum ich nicht deine Methode> verwenden kann: Es können auch zwei Bewegungen gleichzeitig auf der> Schranke ablaufen. D.h. dass unter Umständen eine Schranke unterbrochen> wird, wenn woanders schon länger eine Schranke unterbrochen ist. Das> würde ja dann vom Interrupt nicht erfasst werden und somit würde diesem> Ergebnis auch kein Messwert zugeordnet werden, oder?
Monoflops hinter die Lichtschranken.
> Hab grad eine Messung mit einem Pendel gemacht (ca. 1,5m Faden,> schwarze Glaskugel unten dran, Amplitude 5 - 10cm)>> Der Durchschnittswert der Zeiten ist 0,09804 s
Das ist schlecht.
Ein Pendel von 1m Länge hat eine Schwingungsdauer von
ca. 1 Sekunde. Bei 1m Länge wird die Schwingungsdauer
größer. Wenn deine 1.5 Meter als eine knappe 10-tel
Sekunde dauern, ist was oberfaul.
> Das ist schlecht.> Ein Pendel von 1m Länge hat eine Schwingungsdauer von> ca. 1 Sekunde. Bei 1m Länge wird die Schwingungsdauer> größer. Wenn deine 1.5 Meter als eine knappe 10-tel> Sekunde dauern, ist was oberfaul.
Nein, ich hatte die Unterbrechungsdauer der Lichtschranken betrachtet.
(Das das nicht allzu sinnvoll ist, ist mir auch gerade aufgefallen)
> Ich würde das Programm zuerst auf Papier strukturieren und dann neu> aufbauen. 75% der Programmierarbeit erfolgt bei mir auf dem> Konzeptblock, wegen der Übersichtlichkeit.
Das habe ich auch gemacht und rausgekommen ist das obige.
> Monoflops hinter die Lichtschranken.
Mir ist auch klar, dass man es anders auch lösen kann. Aber wenn ihr
hier so viele Lösungen findet, wie man es anders machen kann, dann
sollte es doch kein Problem sein, eine Lösung für meinen Aufbau zu
finden.
Kann mir denn niemand mal den konkreten Fehler im obigen Programm sagen?
Also was wo nicht stehen darf/soll und wo es dann hinkommt.
Na, steht doch in meinem Beitrag, andere haben's auch schon geschrieben:
Zeitmessung Interruptgesteuert machen. Alles Andere produziert Fehler im
unteren Zeitbereich.
> Na, steht doch in meinem Beitrag, andere haben's auch schon geschrieben:> Zeitmessung Interruptgesteuert machen.
Aber wie soll ich das machen, wenn ich 2 Bewegungen erfassen will aber
keine Zeit / Platz für Monoflops habe?
>Du traust der Lichtschranke ? Ich nicht.
Rahul:
Was soll die Hardware schon falsch machen?
Noch eine Stimme für ein Softwareproblem!
Nun, ein analoges Signal von einem Photosensor geht auf einen
Komparator. Da kann vieles Schiefgehen. Das Umgebungslicht kann den
Level verschieben, usw. Daher zuerst den Sensor ueberpruefen. Der muss
am Scope bockstabil sein. Ein Pendel sollte auf mikrosekunden
reproduzierbar sein.
Aber zuerst sollte die Zeit mit Hardware, dh dem Capture interrupt
gemessenn werden.
rene
Mehrere Eingänge (Lichtschranken) diodenentkoppelt auf einen INT-Pin und
auf einzelne Portpins legen, die INT-Routine so kurz wie möglich halten
und in dieser abfragen welcher Pin den INT ausgelöst hat. Das geht im
µs-Bereich, ich denke nicht dass die Lichtschranken gleichzeitig
auslösen (< 5µs z.B.).
Und selbst wenn, wenn man den Interupt ausreichend kurz macht
und den Wert nur speichert (z.b. nen buffer von 100bytes/Lichtschranke
im RAM) dann ist die Reaktionszeit der Lichtschranke warscheinlich um
ein vielfaches größer als die Interuptlaufzeit.
> Nun, ein analoges Signal von einem Photosensor geht auf einen> Komparator. Da kann vieles Schiefgehen. Das Umgebungslicht kann den> Level verschieben, usw.
Nun, den hab nicht ich gebaut, daher kann da nicht viel schiefgehen.
> Mehrere Eingänge (Lichtschranken) diodenentkoppelt auf einen INT-Pin und> auf einzelne Portpins legen.
Wie meinst du das mit den Dioden?
>Wie meinst du das mit den Dioden?
Na, eine ODER-Verknüpfung der einzelnen Lichtschranken, deren Ausgang
einen Interrupt auslösen soll. Soll heißen: jede Lichtschranke löst den
selben INT aus, in dessen Routine wird festgestellt welche Lichtschranke
wann (Zeitstempel) den INT ausgelöst hat. Das Ganze, wie Läubi
gschrieben hat, in einen Buffer, dann haste nach den INTs Zeit das Ganze
auszuwerten.
So, auch auf die Gefahr hin mich hier unbeliebt zu machen, möchte ich es
nochmal sagen:
Es muss doch eine Möglichkeit geben das Programm zu verbessern ohne dass
ich den Aufbau verändern muss.
Grund:
1. Die Platine ist eh schon voll
2. Wenn ich da jetzt wieder mit meinem Halbwissen anfange rumzubauen,
könnte es sein, dass ich in einem Monat mit gar nichts dastehe und das
wäre schlecht ... sehr schlecht
Gibt es denn keine Lösung die ohne zusätliche Interrups mit einfachem
Eingänge-Pollen annehembare Ergebnisse bringt?
> Gibt es denn keine Lösung die ohne zusätliche Interrups mit einfachem> Eingänge-Pollen annehembare Ergebnisse bringt?
Nur dann, wenn deine Pollroutine
* möglichst kurz ist
* und nur das tut, was unbedingt notwendig ist.
Sprich: Die Eingänge überwachen, bei einem Ereignis
den Timerwert wegspeichern. Und sonst nichts
In dem Moment, indem deine Funktion mehr tut, zb zwischendurch
Messwerte verschicken etc. -> Ask for troubles.
Das einfachste ist aber sicherlich: Das ganze Zeitmessgefrickel
dem Timer, sprich der Hardware, überlassen. Denn: Der Timer
macht das auch wenn dein Programm anderweitig beschäftigt ist.
Und um ehrlich zu sein: Dein Assemblerprogramm will ich mir
nicht antun.
Wie schon gesagt: Polling produziert IMMER Fehler im Timing!
Wenn du noch einen Monat Zeit hast, entwickle lieber eine neue Platine.
Neu aufbauen geht oft schneller als was vorhandenes umzustricken. Ich
kenne deinen Termindruck nicht, aber so würde ich es machen.
ja absolut definierte verhältnisse
ich hab deim prog nur überfolgen aber du springst wild rum. du rufst
immer mal deine kommunikation auf in dieser wir auf einen zustand
gewarte wenn das kein grund für ungenauigkeit is naja.
also
0. das bisherige prog und dessen bestandteile nichtmehr anguggen am
besten vergessen
1. zettel nehmen PAP oder sonstwas mahlen was einenm schema gleichkommt
2. das programmtechnisch umsetzen
noch was
initialisieren
messen
wenn messen bendet kommunizieren und schluss
> * möglichst kurz ist
Also im Normalfall passt das meine Pollroutine auch locker in die 96
Zyklen.
> * und nur das tut, was unbedingt notwendig ist.> Sprich: Die Eingänge überwachen, bei einem Ereignis> den Timerwert wegspeichern. * Und sonst nichts *
Dann gibt es natürlich eine Problem: Wie kann ich der Schranke dann
sagen, dass sie mir die Messwerte schicken soll, wenn sie auf nichts
reagiert?
> In dem Moment, indem deine Funktion mehr tut, zb zwischendurch> Messwerte verschicken etc.
Tut mein Programm das? Wenn der µC während der Messung nichts übers UART
empfängt, dann macht er das auch nicht (Er springt ja nur in den
Kommunikationsteil, wenn er vorher ein Byte empfangen hat). Und wenn er
schließlich das Byte zum Übertragen der Messwerte empfängt, dann ist es
egal ob das dann noch die Messwerte dich noch aufgezeichnet werden
würden verfälscht, denn dann ist die Messung für den Benutzer eh
beendet.
Ich sehe immer noch nicht das Problem mit meinem Programm (es sei denn,
der Computer schickt dem µC ständig irgendwas).
Wenn dir eine Genauigkeit von 1 tausendstel Sekunde reicht,
sehe ich eigentlich keinen Grund, das Ganze nicht in C
zu schreiben. Das sollte eigentlich auch mit Pollen
ausreichend schnell sein.
In der Warteschleife nur auf die Lichtschranke warten, sonst
nichts! Das Zeitzählen kannst du wieder einem Timer überlassen,
das ist sein Spezialgebiet.
> du rufst immer mal deine kommunikation auf in dieser wir auf einen zustand
gewarte wenn das kein grund für ungenauigkeit is naja.
könntest du das mal am code belegen, dass ich z.b. immer wieder die
Kommunikation aufrufe? Ich rufe die Kommunikation nur, dann auf, wenn
was empfangen wurde, und das passiert nicht so oft.
> initialisieren - messen - wenn messen bendet kommunizieren - schluss
Leider weiß der µC nicht wann Schluss, das wird vom Benutzer erst
während der Laufzeit festgelegt.
Wie oft denn noch?
Miss die Zeiten INT-gesteuert!
Mach' doch einfach einen Versuchsaufbau auf'm Steckbrett und probier's
aus, dauert auch nicht länger als hier auf eine Antwort zu warten, die
dir gefällt. Nix für ungut, aber ein bischen experimentieren ist nie ein
Fehler.
Johannes wrote:
>> In dem Moment, indem deine Funktion mehr tut, zb zwischendurch>> Messwerte verschicken etc.>> Tut mein Programm das? Wenn der µC während der Messung nichts übers UART> empfängt, dann macht er das auch nicht (Er springt ja nur in den> Kommunikationsteil, wenn er vorher ein Byte empfangen hat). Und wenn er> schließlich das Byte zum Übertragen der Messwerte empfängt, dann ist es> egal ob das dann noch die Messwerte dich noch aufgezeichnet werden> würden verfälscht, denn dann ist die Messung für den Benutzer eh> beendet.>> Ich sehe immer noch nicht das Problem mit meinem Programm (es sei denn,> der Computer schickt dem µC ständig irgendwas).
Wo hast du eigentlich die 96 Takte her?
Im Grunde ist dein Pgm ja clever aufgebaut.
Du benutzt den CTC Mode im Timer um alle 96 Takte
einen Interrupt zu provozieren. Am Ende der Messschleife
wartest du auf das Auftreten des Interrupts und weist
somit, dass 96 Takte vergangen sind (mal einer mehr, mal
einer weniger, weil du ja den Interrupt nicht exakt im
Moment des Auftretens erwischt).
Aber: Ist sichergestellt, dass ein Durchgang durch die
Schleife nie länger als 96 Takte dauert? Ich hab jetzt
keine Takte gezählt.
@ sonic:
um mal dabei zu bleiben:
Wie oft denn noch? Ich möchte nichts am Aufbau verändern. Und ich weiß,
dass es Leute gibt die so eine Platine in einer Woche nachbauen. Ich
zähle nicht dazu weil ich halt nicht im Keller ätzen kann und ich nicht
alle Teile doppelt dahab'.
Grund:
1. Die Platine ist eh schon voll
2. Wenn ich da jetzt wieder mit meinem Halbwissen anfange rumzubauen,
könnte es sein, dass ich in einem Monat mit gar nichts dastehe und das
wäre schlecht ... sehr schlecht
Sorry, kenne deinen Kenntnisstand natürlich nicht. Ich mache in so einem
Fall eine neue Platine (EAGLE) und lasse sie mir bei PCBPool o.Ä.
fertigen. Kostet ein paar € aber das Resultat ist erstklassig.
In deinem Fall kann ich dann leider nicht weiterhelfen.
Also ich würde es so machen:
- Interupts AUS!
- Counter starten
- Die Lichtschranken pollen, wenn sich was ändert Timerwert (natürlich
mit überlaufzähler) Speichern+Pollresult
(also z.B. einfach den Port kontinuierlich mit "in temp, PORT" einlesen,
vergleichen ob sich was geändert hat. (cp last, temp).
Wenn ja, Timerwert einlesen+speichern+den eingeselen PORT wert.
- Auf tastendruck endet die Messung und alle gespeicherten werte werden
an den PC gesendet, erneuter Tastendruck starte alles wieder von vorne.
Sollte einfach funktionieren (auch mit deiner bestehenden Hardware) und
ausreichend genau sein.
- Du kannst dann etwa mit einem 10tel des Taktes pollen
(in 1 takt, cp 1 takt, branch+ggf speicher naja so etwa halt) was
ausreichend genau sein müßte.
- Du mußt nicht mitzählen
- dir kann eigentlich nix dazwischen kommen
- die Messung kann zu einer beliebigen Zeit ausgelesen werden und am PC
dann die Meßwerte den Lichtschranken zugeordnet werden.
mit 24 Zeitstempel und 8 bit Port kannst du dann (rechne rechne) 32
Zustandsänderungen im Internem SRAM speichern.
Hilft dir der Ansatz?
> Im Grunde ist dein Pgm ja clever aufgebaut.
Danke :-)
> Ich hab jetzt keine Takte gezählt.
Ich aber grad. Hab jetzt mal den worst case während einer Messung
angenommen. Also die Messwerte haben sich verändert und das Programm hat
ein unbekanntes Zeichen erhalten (eins, für das keine Antwort in der
Kommunikation vorgesehen ist). Rausgekommen sind 54 Zyklen, also da wäre
theor. noch Luft.
Eine Frage hätte ich dann noch.
Wenn ich jetzt das Programm neu entwerfe, wie soll ich das dann mit der
Kommunikation machen? Denn auch wenn das Programm misst, dann muss der
µC ja noch ansprechbar sein, ich also die Messung beenden können. Hast
du da eine Idee, meine Lösung scheint ja nicht so 'prickelnd' zu sein.
@ Läubi
> - Interupts AUS!> - Counter starten> - Die Lichtschranken pollen, wenn sich was ändert Timerwert (natürlich> mit überlaufzähler) Speichern+Pollresult> (also z.B. einfach den Port kontinuierlich mit "in temp, PORT" einlesen,> vergleichen ob sich was geändert hat. (cp last, temp).> Wenn ja, Timerwert einlesen+speichern+den eingeselen PORT wert.> - Auf tastendruck endet die Messung und alle gespeicherten werte werden> an den PC gesendet, erneuter Tastendruck starte alles wieder von vorne.
Danke für deine Hilfe. Mit Tastendruck meinst du eine echte Taste am µC,
oder? Kann man das auch mit einem Zeichen per UART realisieren?
> Eine Frage hätte ich dann noch.> Wenn ich jetzt das Programm neu entwerfe, wie soll ich das dann mit der> Kommunikation machen? Denn auch wenn das Programm misst, dann muss der> µC ja noch ansprechbar sein, ich also die Messung beenden können. Hast> du da eine Idee, meine Lösung scheint ja nicht so 'prickelnd' zu sein.
Ich würde es so machen
Bevor noch irgendwas gemessen wird:
Vom PC (oder der Gegenstelle) muss ein Kommando kommen, dass
ab jetzt gemessen werden kann und zwar n Messwerte.
Eventuell würde ich noch die Maximalzeit dafür bekanntgeben.
Danach wartet das Pgm darauf, dass die Lichtschranken n
mal unterbrochen werden und speichert die Zeitstempel
dafür weg. Während der Messzeit gibt es keine Unterbrechung,
durch nichts und niemanden. Der µC ist nur damit beschäftigt
die Zeit weiterzuzählen, die Lichtschranken zu überwachen
und bei Bedarf den Zeitstempel zu speichern. Ach ja: Wenn
eine maximale Messzeit bekannt ist, dann beendet der µC
auch noch vorzeitig die Messung. Aber ansonsten gibt es
nichts in der Schleife was mich noch interessieren könnte.
(Ev. vielleicht noch ein 'Reset' Taster, falls eine Messung
durch Hardwareprobleme in die Hose geht und die maximale
Messzeit auf 0.5 Stunden eingestellt ist).
Johannes wrote:
> @ Läubi>>> - Interupts AUS!>> - Counter starten>> - Die Lichtschranken pollen, wenn sich was ändert Timerwert (natürlich>> mit überlaufzähler) Speichern+Pollresult>> (also z.B. einfach den Port kontinuierlich mit "in temp, PORT" einlesen,>> vergleichen ob sich was geändert hat. (cp last, temp).>> Wenn ja, Timerwert einlesen+speichern+den eingeselen PORT wert.>> - Auf tastendruck endet die Messung und alle gespeicherten werte werden>> an den PC gesendet, erneuter Tastendruck starte alles wieder von vorne.>> Danke für deine Hilfe. Mit Tastendruck meinst du eine echte Taste am µC,> oder? Kann man das auch mit einem Zeichen per UART realisieren?
Lass blos die UART raus!
> Vom PC (oder der Gegenstelle) muss ein Kommando kommen, dass> ab jetzt gemessen werden kann und zwar n Messwerte.> Eventuell würde ich noch die Maximalzeit dafür bekanntgeben.
Das ist eben beides nicht bekannt.
Du kannst prüfen ob ein Zeichen am UART empfangen wurde, ja.
Das würde ja reichen das du die Meßdaten rausgibst sobald irgeneien
Zeichen vom UART empfangen wurde.
Ansonsten, miß auf jedenfall mal nach was die Lichtschranken so bringen!
Ich weiß das einige Infarotsensoren eine ReaktionsZeit von 20(!!!)ms
haben.
Wenn vom Sensor schon so eine lahme Reaktionszeit kommt wirds mit der
Zeitmessung halt recht schwer.
Johannes wrote:
>> Vom PC (oder der Gegenstelle) muss ein Kommando kommen, dass>> ab jetzt gemessen werden kann und zwar n Messwerte.>> Eventuell würde ich noch die Maximalzeit dafür bekanntgeben.>> Das ist eben beides nicht bekannt.
Ach komm, du wirst doch eine ungefähre Abschätzung haben?
Sind das 10 Sekunden oder 2 Minuten.
Es geht lediglich darum, dass sich die Messaperatur selbstständig
wieder abschaltet, wenn mal nicht alle Lichtschranken
ausgelöst wurden, weil dein zb. deine Kugel aus der Rille
gefallen ist. Ansonsten hängt der µC und wartet bis auch tatsächlich
alle 5 Lichtschranken durchgeschaltet haben.
> Ich meinte eher die Messapparatur.
Sags halt gleich :-)
> Das würde ja reichen das du die Meßdaten rausgibst sobald irgeneien> Zeichen vom UART empfangen wurde.
Dann müsste ich aber auf einige mehr oder weniger wichtige Funtkionen,
wie z.b. die automatische Erkennung des verwendeten COM-Ports oder eine
Funktion zur sofortigen Status-Übermittelung an den PC (ist für das
PC-Programm wichtig) verzichten.
> Ansonsten, miß auf jedenfall mal nach was die Lichtschranken so bringen!
Kein Scope in der Hosentasche :-)
> Ich weiß das einige Infarotsensoren eine ReaktionsZeit von 20(!!!)ms> haben. Wenn vom Sensor schon so eine lahme Reaktionszeit kommt wirds mit> der Zeitmessung halt recht schwer.
Es werden Phototransistioren eines Typs verwendet, der heute anscheinend
nicht mehr existiert. Kannst ja mal schaun, was du auf dem Bild erkennen
kannst. Ich lese BPA01II, finde aber dazu nichts.
> Ach komm, du wirst doch eine ungefähre Abschätzung haben?
Ja ca. 10 sek.
> Es geht lediglich darum, dass sich die Messaperatur selbstständig> wieder abschaltet, wenn mal nicht alle Lichtschranken ausgelöst wurden
Es kann aber auch vorkommen, dass einigen Lichtschranken öfters
durchbrochen werden. Das ist für den Benutzer vorher nicht vorhersagbar.
> tatsächlich alle 5 Lichtschranken durchgeschaltet haben
es waren 8 ;-)
was ist denn nun deine kürzesteze gewünschte zeiteinheit ?
meine aus der hüfte geschossene variante.
unter folgenden vorrausetzungen:
- der interrupt für den timer überlauf ist höher priorisiert als die
uart
- und der timer interrupt unterbricht den uart interrupt.
- der inhalt des timer interrupts is kürzer al ser selbst (logischer
weise)
dann kannst du im Timer pollen, auf veränderung prüfen
sowie speichern bei bedarf
die uart kann alles übertragen und auf "posteingang warten"
in der hauptschleife wird dann der restliche mist gemacht zb den
posteingang auswerten und ggf aktionen vormerken ....
also gehts doch oder
ich hab eben schon länger nicht mehr so defizile sachen gemacht
in c gabs doch den unterschied zwischen
signal ()
und
interrupt()
gelle der eine war zu unterbrechen und der andere nicht aber aus gutem
grund habe ich das bisher immer gemieden einen solchen konstruckt zu
friemeln damit macht man sich wenn nicht alles 100% bekannt is schnell
ein loch ins knie solle aber bei den paar zeilen hier gehen
Vergleich C und ASM:
C: SIGNAL verlässt die INT-Routine mit 'reti'
INTERRUPT verlässt die INT-Routine mit 'ret'
Dann muss der globale INT 'von Hand' freigegeben werden.
ehm meinst du nicht
außer man gibt am anfang der uart routine den globalen INT wieder frei?
und meien asm zeiten liegen 5 j zurück also ret und reti sind für mich
rücksprünge naja
egal mal sehen was wird
> Es werden Phototransistioren eines Typs verwendet, der heute anscheinend> nicht mehr existiert. Kannst ja mal schaun, was du auf dem Bild erkennen> kannst. Ich lese BPA01II, finde aber dazu nichts.
Ich lese da BPX81IX (römisch 9)
@Johannes:
Vielleicht ist Dir folgender Pseudocode für ein paar Anregungen
dienlich.
t und _Time_[] verstehen sich darin als 24 Bit-Variablen. Damit
kannst Du Dich dann über eine maximale Messzeit von 0.1 ms * 2^24 =
1677721 ms = 1677 s = 28 min bei einer Messauflösung von 0.1 ms freuen.
1
// Interrupt-Tabelle
2
// ...
3
// ...
4
5
6
//=============================================
7
8
// Da "TimerOverflow" sehr zeitkritisch ist,
9
// darf es "USARTInput" unterbrechen;
10
// deshalb hier ein "sei" am Anfang!
11
12
13
USARTInput:
14
{
15
sei
16
17
// Eingetroffenes Byte aus Hardware abholen und
18
// in Ringpuffer abspeichern
19
}
20
21
reti
22
23
24
//=============================================
25
26
// Interrupt-Routine
27
28
// Geschätzte Anzahl Instruktionen für den Fall dass jede
29
// Zeile abgearbeitet wird: ca. 100 (siehe Tabelle)
30
// ATmega8 @ 8 MHz schafft innerhalb 0.1 ms ca. 500
31
// Instruktionen
32
// --> zu erwartende relative Prozessorlast durch diese
So, nu sach ich auch mal wat:
Du mußt die Lichtschranken im Timerinterrupt pollen.
D.h. der Pollzyklus muß kürzer als die kürzeste Unterbrechungszeit sein,
sonst geht sie Dir duch die Lappen.
Oder Du nimmst nen ATmega168, ist pinkompatibel, aber mit
Pin-Change-Interrupt.
Die UART darf dann auch kein Interrupt sein, da die AVRs leider keine
Prioritäten haben.
Also die UART im Main pollen, 3 Bytes werden ja gepuffert.
Notfalls die Baudrate runter setzen.
Dann müßte es gehen, Layoutänderung ist unnötig.
Peter
@ Peter Dannegger
Verstehe ich das richtig, dass deine Anmerkungen sich nicht auf das
Programm beziehe, das ich im Beitrag über dir vorgeschlagen habe.
Du meinst das also so:
Ich stelle einen Timer so ein, das er z.b. alle 64 (oder auch mehr oder
weniger) Taktzyklen überläuft und mir einen Interrupt gibt. In der
Interruptroutine frage ich dann 1mal die Lichtschranken ab und spiechere
den Zustand (wenn sich etwas geändert hat) mit der Anzahl der Überläufen
seit Messungsbeginn (die ich irgendwo anders speichere und bei jedem
Interrupt des Timers erhöhe).
Dann habe ich noch eine Hauptschleife in der so Sachen wie die
Kommunikation mit dem PC erledigt wird (ohne Interrupt).
Alles richtig wiedergegeben?
Das mit dem Atmega168 ist natürlich die eleganteste Lösung, die machen
ich/wir wenn das nächste Programm auch keine guten Ergebnisse liefert.
Aber eigentlich müsste es der Atmega88 [sic] doch auch tun,
unterscheiden sich dann ja nur noch in der Größe des Flash-Speichers.
> Aber eigentlich müsste es der Atmega88 [sic] doch auch tun,
Da hast du recht.
Was mich allerdings noch etwas stutzig macht sind deine
Abweichungen beim Pendelexperiment. 20% ist schon ne
Menge Holz.
>Doch! Bitte nochmal ins Dateblatt gucken.
Nicht in der Art, wie die 8051er sie haben:
Da kann ein Interrupt höherer Priorität einen mit niedrigerer
unterbrechen.
Beim AVR sind grundsätzlich alle anderen Interrupts während einer
ISR-Bearbeitung gesperrt.
Bei solchen zeitkritischen Sachen muß man ISR extrem kurz halten.
@fieser Rahul
> > Doch! Bitte nochmal ins Dateblatt gucken.> Nicht in der Art, wie die 8051er sie haben:> Da kann ein Interrupt höherer Priorität einen mit niedrigerer> unterbrechen.> Beim AVR sind grundsätzlich alle anderen Interrupts während einer> ISR-Bearbeitung gesperrt.
Nööö, man kann einfach in niederpriorisierten Interrupts ein SEI zu
Begin ausführen. Dadurch ist dieser Interrupt durch andere
unterbrechbar.
OK, eine richtige Interuptpriorität wie sie andere uC oder CPUs haben
ist das nicht ganz.
MfG
Falk
>OK, eine richtige Interuptpriorität wie sie andere uC oder CPUs haben>ist das nicht ganz.
Genau das meinte ich. (Und wusste auch, dass das kommt.)
>Nööö, man kann einfach in niederpriorisierten Interrupts ein SEI zu>Begin ausführen
"Gebastel".
Da könnte man in C-Programmen auch ein "goto" verwenden...
Zum Thema:
Im Prinzip ist es doch nichts anderes als ein Frequenzmesser.
Da kann man entweder abfragen, ob sich etwas am Eingang gändert hat und
die Zeit zwischen zwei Änderungen messen, oder innerhalb einer
bestimmten Torzeit die Anzahl der Ereignisse feststellen.
Kann es sein, dass man diese (Schul-)Versuche früher mit nur einer
Lichtschranke gemacht hat, die in der Höhe variable war?
(Oder habe ich den praktischen Anwedungszweck immer noch nicht
verstanden?)
>"Gebastel".>Da könnte man in C-Programmen auch ein "goto" verwenden...
Falsch! Die Prioritäten wurden von Atmel absichtlich so aufgebaut, um
einen versehentliche Stacküberlauf zu vermeiden, was bei den 8051ern
öfter mal vorkommen kann. Das mit dem SEI ist schon richtig und gängige
Praxis, nur sollte man dann wissen was man tut! Das Ergebnis ist das
gleiche wie bei den 8051ern.
> Kann es sein, dass man diese (Schul-)Versuche früher mit nur einer> Lichtschranke gemacht hat, die in der Höhe variable war?> (Oder habe ich den praktischen Anwedungszweck immer noch nicht> verstanden?)
Jetzt noch mal genau:
Man stelle sich eine Schwebebahn vor, auf der sich bis zu 2 Gleiter
befinden können. Diese Gleiter haben obendruaf ein kleines Fähnchen mit
dem sie die Lichtschranken durchbrechen die entlang der Bahn aufgebaut
sind.
Könnte mir vielleicht noch mal jemand die Aufgabenstellung ansich
verklickern?
Soweit ich das bis jetzt verstanden habe, bezieht sich das o.g. Problem
auf einen älteren Thread (den ich nicht finde / nach dem ich nicht
weiter suchen will...).
Die Aufgabe scheint eine Stoppuhr für einen Versuchsaufbau für den
Physik-Unterricht zu sein, bei dem es um Pendel geht.
Richtig?
Ahaj, es dämmert wieder.
Das haben wir damals mit einem Hochspannungsnetzteil gemacht, das mit
einer bestimmten Frequenz gepulst wurde. Die Impulse sorgten für Löcher
in einer Folie. Die Abstände der Impulse waren dann ein Maß für die
Geschwindigkeit...(t = const, s = variable => v = variable).
Sonic wrote:
> Falsch! Die Prioritäten wurden von Atmel absichtlich so aufgebaut, um> einen versehentliche Stacküberlauf zu vermeiden, was bei den 8051ern> öfter mal vorkommen kann. Das mit dem SEI ist schon richtig und gängige> Praxis, nur sollte man dann wissen was man tut! Das Ergebnis ist das> gleiche wie bei den 8051ern.
Nein, da ist ein grundsätzlicher Unterschied !
Bei den 8051 kann es zu keinem Stacküberlauf kommen, da die Prioritäten
in Hardware gemacht werden. Es können also immer nur soviel Instanzen an
Interrupts gleichzeitig auftreten, wie verschiedene Prioritäten
zugewiesen wurden. Ein gleiche Interruptpriorität kann sich daher nie
selber unterbrechen.
Wenn Du dagegen beim AVR im UART-Interrupt ein sei() machst, um den
Timerinterupt wieder zu erlauben, läuft sofort der Stack über, da ja das
Pending-Flag beim Eintritt nicht gelöscht wird.
Das hat mich bei den AVRs auch schon oft geärgert, daß ausgerechnet die
zeitunkritischen Interrupts (UART, EEPROM, I2C usw.) ihre Flags nicht
löschen und daher Priorität in Software äußerst kompliziert wird.
Peter
@Peter Dannegger
> Nein, da ist ein grundsätzlicher Unterschied !
Ja.
> Wenn Du dagegen beim AVR im UART-Interrupt ein sei() machst, um den> Timerinterupt wieder zu erlauben, läuft sofort der Stack über, da ja das> Pending-Flag beim Eintritt nicht gelöscht wird.
Kommt auf den Interrupt an. Einige löschen per Hardware automatisch die
Bits, andere müssen "per Hand" gelöscht werden. Es sollte klar sein,
dass bei diesen erstmal das Löschen angesagt ist, bevor man SEI
ausführt.
> Das hat mich bei den AVRs auch schon oft geärgert, daß ausgerechnet die> zeitunkritischen Interrupts (UART, EEPROM, I2C usw.) ihre Flags nicht> löschen und daher Priorität in Software äußerst kompliziert wird.
Naja, als "äußerst kompliziert" würde ich das nicht bezeichnen.
MfG
Falk
> Wenn Du dagegen beim AVR im UART-Interrupt ein sei() machst, um den> Timerinterupt wieder zu erlauben, läuft sofort der Stack über, da ja das> Pending-Flag beim Eintritt nicht gelöscht wird.
Bei denen wo's automatisch gelöscht wird geschieht dies beim Aufruf der
INT-Routine, er kann sich also nicht selbt wieder aufrufen wenn in der
ISR das SEI ausgeführt wird.
OK, habs mir nochmal durchgelesen. Ich rekapituliere mal.
Die Zustandsänderung eines 8 Bit Ports soll mit einer Auflösung von 5us
protokolliert werden. Innerhalb einer maximalen Messzeit von 20s können
maximal 40 Zustandswechsel auftreten. Die Liste der Zustandswechsel soll
am Ende der Messzeit zum PC per UART übertragen werden.
Richtig?
OK, hier mein Vorschlag.
theoretisch bräuchte man 8 Capture-Compare-Eingänge. Da wir die im AVR
nciht haben, muss es eben per Polling gemacht werden.
Kleiner Pseudocode.
Warte aus Startsignal für Messung
Schleifenanfang:
Port einlesen
Vergleich mit vorherigem Wert
Wenn verschieden, aktuellen Zeitstempel und Portwert per Z-pointer in
SRAM schreiben
Zeitstempel hochzählen
Wenn Schleifenzähler ungleich null, Sprung zum Schleifenanfang
Messwerte zum PC schieben
Der Trick dabei ist, dass die beiden Zweige (Vergleich positiv oder
negativ) mittels NOP auf gleich lange Ausführungszeiten getrimmt werden
müssen(Takte), um eine konstante Zykluszeit zu erreichen. Logo, dass man
hier Assembler braucht. Man kann den Zeitstempel und Schleifenzähler
kombinieren und muss nur eine Variable bearbeiten. Spart ein paar Takte.
20s / 5us = 4000000, wir brauchen also einen 3 Byte Zeitstempel
+ 1 Byte für den Portwert, macht 4 Byte/Eintrag
Macht bei 1k RAM max. 256 Einträge
Das sollte passen.
MfG
Falk
So, hab mich heute früh hingesetzt und die 'Version 2' des Programms
geschrieben (bitte ab jetzt immer dazuschreiben, auf was man sich
bezieht).
Ablauf:
nach der ganze Initialisierung läuft das Programm in einer Hauptschleife
in der die Kommunikation abgearbeitet wird.
Ein Interrupt tritt alle 96 Zyklen auf und unterbricht diese
Hauptschleife. In der Interruptroutine werden die LS abgefragt und wenn
nötig mit dem Überlaufzähler gespeichert.
http://home.arcor.de/kreuzfeuer/fa2.html
Bitte wieder bewerten. Eine Messung habe ich noch nicht durchgeführt,
möchte erst noch erste Rückmeldungen abwarten.
@ fieser Rahul
Ja, ich glaube das war der erste Beitrag den ich hier zur Zeitmessung
gemacht habe. Du bekommst nochmal 100 extra Punkte, wenn du mir den
Beitrag aus dem Usenet ausgräbst, in dem mir die Leute die ersten
Hinweise für mein Vorhaben gegeben haben :-)
Sonic wrote:
>> Wenn Du dagegen beim AVR im UART-Interrupt ein sei() machst ...> Bei denen wo's automatisch gelöscht wird ...
Der UART-Interrupt wird bei keinem AVR automatisch gelöscht !
Das ist es ja. Wenn wenigstens dann das Enable-Flag gelöscht würde.
So aber braucht man unter AVR-GCC immer noch etwa weitere 20 Zyklen, ehe
man andere Interrupts wieder erlauben kann.
Und naked Interrupts sind wirklich ne Krücke.
Ich habs dann daher mit nem 2.Timer gemacht, ist aber auch irgendwie
"von hinten durch die Brust ins Auge".
Peter
@Johannes
> So, hab mich heute früh hingesetzt und die 'Version 2' des Programms> geschrieben (bitte ab jetzt immer dazuschreiben, auf was man sich> bezieht).
Naja, sieht erstmal brauchbar aus. ABER!
Warum mit Interrupt?
Das kostet dich 4+4+2 Takte jedesmal für Interrupt aufrufen, SREG
sichern und Interuptverlassen. Ich würde ne normale Poll-Schleife
machen.
Zweitens, das mit der Endlosschleife forever find ich hier unbrauchbar.
Ich würde in einer Schleife auf ein Zeichen waren (Start der Messung),
dann die Pollschleife anspringen. Innerhalb der der Poll-Schleife kannst
du dann per Polling prüfen ob ein weiteres Zeichen empfangen wurde (Ende
der Messung, Wert ist egal). Das alles ohne Interrupts. Dann ist das
Timing auch absolut deterministisch und überschaubar.
MfG
Falk
> Warum mit Interrupt?
Weil ich mir dann sicher sein kann, dass das Abfragen der Lichtschranken
immer im gleichen (zeitl.) Abstand geschieht.
> Ich würde ne normale Poll-Schleife machen.
Dann hab ich wieder das Problem, dass ich das Pollen der Lichtschranken
und das Abfragen ob ein Byte empfangen wurdeunter einen Hut zu bekommen,
ohne dass das UART die Messung blockiert.
> Zweitens, das mit der Endlosschleife forever find ich hier unbrauchbar.> Ich würde in einer Schleife auf ein Zeichen waren (Start der Messung),> dann die Pollschleife anspringen. Innerhalb der der Poll-Schleife kannst> du dann per Polling prüfen ob ein weiteres Zeichen empfangen wurde (Ende> der Messung, Wert ist egal). Das alles ohne Interrupts. Dann ist das> Timing auch absolut deterministisch und überschaubar.
Mach ich auch gleich mal ein Programm dazu, wird dann Version 3 :-)
@Johannes
> > Warum mit Interrupt?> Weil ich mir dann sicher sein kann, dass das Abfragen der Lichtschranken> immer im gleichen (zeitl.) Abstand geschieht.
Geht wunderbar mit ner Schleife.
> > Ich würde ne normale Poll-Schleife machen.> Dann hab ich wieder das Problem, dass ich das Pollen der Lichtschranken> und das Abfragen ob ein Byte empfangen wurdeunter einen Hut zu bekommen,> ohne dass das UART die Messung blockiert.
nein, weil die Messwertübertragung nach der MEssung statt findet.
> > Timing auch absolut deterministisch und überschaubar.> Mach ich auch gleich mal ein Programm dazu, wird dann Version 3 :-)
Hier mal mein Versuch. Ist nicht durch den Assembler gejagt, hat sicher
noch Tippfehler.
MfG
Falk
@Johannes:
Du wünschst eine Zeitauflösung von 5 µs? Hast Du mal ausgerechnet, wie
genau Du die Lichtschranken für eine gegebene Maximalgeschwindigkeit
(wie groß ist die bei Deinem Projekt?) räumlich positionieren müsstest,
damit diese Auflösung Sinn macht?
Außerdem gebe ich zu bedenken, dass ein ATmega8 @ 8 MHz während 5 µs
lediglich noch ca. 30 Instruktionen abarbeiten kann. Meinst Du, das
reicht für die Durchführung aller erforderlichen Aktionen (Port
einlesen, auf Änderung überprüfen, Lichtschrankenzustände an richtigem
Platz im SRAM abspeichern, evtl. noch "Messung abbrechen"-Taster
abfragen...)?
@Peter Dannegger:
Dein Einwand mit dem "sei", das man nicht so wie von mir in dem
Pseudocode dargestellt ohne weitere Maßnahmen am Anfang einfügen darf,
weil das Interruptflag beim UART-Interrupt nicht automatisch gelöscht
wird, ist berechtigt. Daran hab ich nicht gedacht. Danke für den
Hinweis!
@Falk:
ich habe deinen Logger mal angepasst und die Durchlaufzeiten in den 3
Pfaden (keine Änderung, Änderung mit Speichern, Änderung ohne Speichern,
weil schon 150 Messwerte gespeichert wurden) auf immer 19 Zyklen
gebracht.
Außerdem habe ich wieder auf einen 4 Byte Zeitstempel umgestellt, da mit
3 Byte und 17 Zyklen nur ca 17 Sekunden drin gewesen wären und das wäre
mir etwas zu knapp geworden.
Bitte drüberschauen.
DANKE AN ALLE DIE MIR BISHER GEHOLFEN HABEN
>und die Durchlaufzeiten in den 3 Pfaden (...) auf immer 19 Zyklen>gebracht.
Na dann funzt es ja bestens. Wenn Du die Schleifendurchläufe durch
weitere "nop"s auf exakt 40 Zyklen justierst, kannst Du bei 8 MHz
Systemtakt ein Messintervall von quarzgenauen 5 µs erreichen. Damit
bleibst Du zwar etwas unterhalb der maximal möglichen Auflösung, hast es
dafür aber bei der späteren Auswertung sicher bequemer als mit einem
"krummen" Wert.
@Johannes
> ich habe deinen Logger mal angepasst und die Durchlaufzeiten in den 3> Außerdem habe ich wieder auf einen 4 Byte Zeitstempel umgestellt, da mit> Bitte drüberschauen.
Sieht gut aus. Du magst wohl meine r_ Notation nicht? ;-)
Aber cnt3 würde ich noch definieren, um konsequent zu bleiben. Das fällt
einem sonst beim nächsten, grösseren Projekt auf die Füsse.
> Aber mit genau 8mhz habe ich dann weider ein Problem mit dem UART ;-)> Also lassen wird das so ;-)
Wieso?
Mit 8 MHz kann ich alle normalen Baudraten ausser 28k8, 57k6, 76k8 und
115k2. Reicht das nicht?
@AVRFan
> Du wünschst eine Zeitauflösung von 5 µs? Hast Du mal ausgerechnet, wie> genau Du die Lichtschranken für eine gegebene Maximalgeschwindigkeit> (wie groß ist die bei Deinem Projekt?) räumlich positionieren müsstest,> damit diese Auflösung Sinn macht?
Keine Ahnung wie die Anforderungen sind, aber mal mal als Orientierung.
1 m/s = 1mm / 1ms (das metrische System ist schon was feines ;-)
= 5um / 5us
So breit ist wahrscheinlich der Bonddraht ;-)
Wenn sich die Objekte schneller bewegen siehts natürlich anders aus.
Aber unabhängig davon ist die Zeitmessung korrekt. Nur sollte man sich
bei der Umrechnung von Zeit in Geschwindigkeit in Acht nehmen, da der
Weg (Abstand der Lichtschranken, bzw. des effektiven Lichtstrahls) nicht
so genau ist ;-)
MfG
Falk
>Aber mit genau 8mhz habe ich dann weider ein Problem mit dem UART ;-)
Überhaupt nicht ;-). Bei den Baudraten 2400, 4800 und 9600 beträgt die
relative Abweichung der UART-Frequenz nur 0.2 % und das ist völlig
belanglos. Siehe Data Sheet zum ATmega8 [*], Seite 159 ff. Dort stehen
auch die passenden UBRR-Werte.
[*] http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf
> Aber cnt3 würde ich noch definieren, um konsequent zu bleiben. Das fällt> einem sonst beim nächsten, grösseren Projekt auf die Füsse.
Naja, gibt halt eine Warnung, weil XL schon als r26 definiert ist.
> Mit 8 MHz kann ich alle normalen Baudraten ausser 28k8, 57k6, 76k8 und> 115k2.
Datenblatt Atmega8, Seite 158
Da steht, dass man mit 8Mhz schon bis 0M5 hochkommt, aber dann hat man
Fehlerwahrscheinlichkeiten von 0.2 - 8.5 %
So, hab gerade wieder eine Pendelmessung mit Version 3 gemacht, die alle
34 Zyklen die Schranken abfragt. Die Ergebnisse sind überzeugend :-)
Alle Werte beziehen sich jetzt auf T (Periodendauer), es wurden 7
Unterbrechungen gemessen, woraus sich 5 Periodendauern berechnen lassen:
Abweichung größter - kleinster gemessener Wert: 3 Promille
Größte Abweichung zum theoretischen Wert: 2 Promille
Ich denke, das ist ziemlich gut :-)
NOCHMAL DANKE AN ALLE DIE MIR GEHOLFEN HABEN
@ Johannes
> So, hab gerade wieder eine Pendelmessung mit Version 3 gemacht, die alle> 34 Zyklen die Schranken abfragt. Die Ergebnisse sind überzeugend :-)
Warum nun wieder 34 Takte?
MfG
Falk
@Johannes:
Noch Lust auf ne knifflige Rätselfrage? Bitteschön:
Wenn Du alle acht Lichtschranken durch einen Taster ersetzt, der alle
Lichtschranken-Signalleitungen parallel bedient, wirst Du nicht immer
für alle Leitungen die genau gleichen Zeiten protokolliert finden,
sondern...
Wie ist der Satz fortzusetzen und warum? Na? ;-)
@Johannes:
Wenn du für jede Lichtschranke eine genaue Zeitmessung haben willst geht
das nur über einen anderen µC.
Du musst dann für jede Lichtschranke einen extern getriggerten
Hardwaretimer haben, der einen Zeitstempel der Flanke speichert. Diese
Zeitstempel kannst du dann zeitunkritisch Auswerten.
Darüber kannst du dann eine Auflösung im unteren µs eventuell ns Bereich
erzielen.
Solange du nicht jedem Eingang einen eigenen Zeitstempel zuordnen
kannst, egal ob getriggerter Timer oder Interrupt, wirst du immer mehr
oder weniger große Abweichungen erhalten.
Und du kannst auch nie ausschließen das Impulse der Lichtschranken
"übersehen" werden.
Ein möglicher µC für dein Problem wäre der TMS 470 vom TI.
Das ist ein AMR 7 Controller der zusätzlich einen HighEndTimer Modul mit
bis zu 32 einzel triggerbare IO Leitungen hat.
Ralph
>Darüber kannst du dann eine Auflösung im unteren µs eventuell ns Bereich>erzielen.
Wozu?
>Ein möglicher µC für dein Problem wäre der TMS 470 vom TI.>Das ist ein AMR 7 Controller der zusätzlich einen HighEndTimer Modul mit>bis zu 32 einzel triggerbare IO Leitungen hat.
Klingt nach großkalibrigen Waffen und kleinen Vögeln...
Wie Falk oben schon schrieb: 5µs ergeben eine Auflösung von 5µm. So
ganau wird man die Lichtschranken nicht mal positionieren können...
>Ein möglicher µC für dein Problem wäre der TMS 470 vom TI.>Das ist ein AMR 7 Controller der zusätzlich einen HighEndTimer Modul mit>bis zu 32 einzel triggerbare IO Leitungen hat.
Johannes hatte ein Modifikation der Platine schon abgelehnt...
@Ralph
> Du musst dann für jede Lichtschranke einen extern getriggerten> Hardwaretimer haben, der einen Zeitstempel der Flanke speichert. Diese> Zeitstempel kannst du dann zeitunkritisch Auswerten.
Soweit waren wir alle schon lange. Und wenn schon richtig, dann gleich
FPGA.
> Solange du nicht jedem Eingang einen eigenen Zeitstempel zuordnen> kannst, egal ob getriggerter Timer oder Interrupt, wirst du immer mehr
Kann er doch. Nur eben mit einer maximalen Auflösung von 5us.
> oder weniger große Abweichungen erhalten.> Und du kannst auch nie ausschließen das Impulse der Lichtschranken> "übersehen" werden.
Ach, und wie macht das ein schnellerer Prozessor? Der ist auch nur
schneller, und auch den kann man dann pratisch mit noch kürzeren
Impulsen aus dem Konzept bringen.
Wenn wirklich mehr Auflösung nötig ist, würde ich erstmal die
Lichtschranken untersuchen.
MFG
Falk
P.S. @Johannes: Bei deinen letzten Messungen sprachst du von 2 Promille
Abweichung. Bei welchen Zählerdifferenzen?
> Wenn Du alle acht Lichtschranken durch einen Taster ersetzt, der alle> Lichtschranken-Signalleitungen parallel bedient, wirst Du nicht immer> für alle Leitungen die genau gleichen Zeiten protokolliert finden,> sondern...
Ja ... keine Ahnung :-)
> Und du kannst auch nie ausschließen das Impulse der Lichtschranken> "übersehen" werden.
Alles was in Meiner Anordnung eine Lichtschranke kürzer als mein
Abtastintervall unterbricht kann ich als Störung auffassen. (Da hätte
der Schlitten schon Überschallgeschwindikeit :-)
> Wenn Du alle acht Lichtschranken durch einen Taster ersetzt, der alle> Lichtschranken-Signalleitungen parallel bedient, wirst Du nicht immer> für alle Leitungen die genau gleichen Zeiten protokolliert finden,> sondern...
Noch ein Versuch: Da ich ja die Schranken an unterschiedlichen Ports
hängen habe, kann es sein, dass ich zuerst den ersten Port abfrage, da
ist noch alles 0, dann drückt jemand den Schalter, dann frage ich den
zweiten Port ab, da ist dann alles 1. So habe ich dann als Status 0011
1111 oder so. (Aber das macht nichts, weil ich ja die anderen zwei im
nächsetn Druchlauf erkenne, die 34/14745600 Sek. kann ich verkraften)
>Da ich ja die Schranken an unterschiedlichen Ports>hängen habe, kann es sein, dass [...]
So ist es. Und man kann sogar den zu erwartenden statistischen Anteil
der "inkonsistenten" Protokolle bei diesem Versuch angeben: 1/34.
>[...] weil ich ja die anderen zwei im nächsetn Druchlauf erkenne,
Selbstverständlich.
Um das Sampling korrekt zu bewerkstelligen, müsstest Du alle acht
Lichtschranken an einen einzigen Port hängen. Leider ist das bei Deinem
ATmega8 nicht ohne weiteres möglich, weil Du ja noch den Hardware-UART
nutzen willst, der die Pins 0 und 1 von Port D belegt. Damit bliebe Dir
als Möglichkeit, um den (kleinen) Makel zu beheben, ein externes
8-fach-Latch zur Zwischenspeicherung der Lichtschrankenzustände "an
einem Stück" einzusetzen.
> P.S. @Johannes: Bei deinen letzten Messungen sprachst du von 2 Promille> Abweichung. Bei welchen Zählerdifferenzen?
Ih hab mal die ganze Messauswertung angehängt (weil ich nicht genau
weiß, nach was du genau suchst)
>Wenn du für jede Lichtschranke eine genaue Zeitmessung haben willst geht>das nur über einen anderen µC.
Kannst Du mir genauer erklären, warum?
>Du musst dann für jede Lichtschranke einen extern getriggerten>Hardwaretimer haben, der einen Zeitstempel der Flanke speichert.
Wieso muss man das so machen, und warum sollte es so wie es jetzt
realisiert wurde, nicht einwandfrei funktionieren?
>Diese Zeitstempel kannst du dann zeitunkritisch Auswerten.
Eben dies geschieht doch bei Johannes' Lösung!?
>Darüber kannst du dann eine Auflösung im unteren µs eventuell ns Bereich>erzielen.
Na prima. Und wenn eine solche Auflösung gar keinen Sinn gibt? Ist für
Dich ein Routenplaner wertlos, wenn er Dir die Entfernung
München-Hamburg nicht auf den Meter, sondern nur auf den Kilometer genau
ausgibt?
>Solange du nicht jedem Eingang einen eigenen Zeitstempel zuordnen>kannst, egal ob getriggerter Timer oder Interrupt, wirst du immer mehr>oder weniger große Abweichungen erhalten.
Was bitte soll diese Abweichungen verursachen?
>Und du kannst auch nie ausschließen das Impulse der Lichtschranken>"übersehen" werden.
Siehe die Bemerkung von Johannes dazu.
>Ein möglicher µC für dein Problem wäre der TMS 470 vom TI.>Das ist ein AMR 7 Controller der zusätzlich einen HighEndTimer Modul mit>bis zu 32 einzel triggerbare IO Leitungen hat.
Manchmal sinnvoll - manchmal aber vielleicht auch schlicht oversized.
@AVRFan
> >Da ich ja die Schranken an unterschiedlichen Ports> >hängen habe, kann es sein, dass [...]> So ist es. Und man kann sogar den zu erwartenden statistischen Anteil> der "inkonsistenten" Protokolle bei diesem Versuch angeben: 1/34.
Naja, aber was bedeutet das real? Praktisch nix, denn das fällt unter
die Zeitauflösungsgrenze. Wenn die Schranke irgendwo anders innerhalb
der 34 Takte schaltet ist der Effekt der gleiche, auch wenn alle Pins an
einem Port hängen.
-> passt schon.
@Johannes
Die Differenz zwischen kleinster und grösster Periodendauer T beträgt in
deiner Tabelle 3967. Das ist auf jeden Fall ein Effekt der
Lichtschranken bzw. deren Auslösung.
MfG
Falk
>Naja, aber was bedeutet das real? Praktisch nixzustimm Die praktische Relevanz für Johannes ist gleich Null :-) Aber
ich wollte auch nicht sagen, dass da was ernsthaft im Argen liegt,
sondern nur darauf denkanstoßen, dass und wie man das
Auf-zwei-Porte-Aufgeteiltsein der Lichtschrankenabfrage in den
Protokollen "sichtbar" machen kann, wenn man es -
forschunginteressehalber - will.