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
Also ich bin auch ganz start geneigt zu Sagen das das Problem am Programm liegt! Wie Karl Heinz shcon sagte..
>Du traust der Lichtschranke ? Ich nicht.
Was soll die Hardware schon falsch machen?
Noch eine Stimme für ein Softwareproblem!
> 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
>Shannon ist hier vollkommen deplaziert.
Nö, finde ich nicht.
@ 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?
>Nun, ein analoges Signal von einem Photosensor geht auf einen >Komparator. Wie sieht denn eigentlich die Hardware aus? Gibt es dazu einen Link?
> 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).
Wen die Hardware interessiert -> Anhang Das links unten ist die Schaltung für den Reset-Taster
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.
>Wen die Hardware interessiert -> Anhang
Wie ein Mikrocontroller beschaltet wird, weiß ich selbst.
Ich meinte eher die Messapparatur.
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 ....
>- und der timer interrupt unterbricht den uart interrupt.
Niemals! Außer du gibst am Anfang der Timer-INT-Routine den globalen INT
frei.
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
probier's mal mit Gemütlichkeit ... waren wohl ein paar 'Erfrischungen' zuviel heute ???
> 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)
@ Dieter Werner Danke, dann wissen wir ja endlich mit was wir es zu tun haben. Anstiegs-/Abfallzeit: 5.5 - 8 µs
@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
|
33 | // Interruptroutine beträgt ca. 20 % --> OK!
|
34 | //
|
35 | // --------------------------------------------------
|
36 | // Aktion # Instruktionen
|
37 | // --------------------------------------------------
|
38 | // IF TimeMeasRunning 3
|
39 | // Inc _t_ 4
|
40 | // IF (_t_<_Grenzwert_) 6
|
41 | // PortState = PORTXXX 4
|
42 | // FOR (i = 0...8-1) 6
|
43 | // IF (Bit i in PortState gesetzt) 4*8
|
44 | // _Time_[i] = _t_ 4*8
|
45 | //
|
46 | // MainFlag = 0 1
|
47 | // inc k 1
|
48 | // IF (k=200) 4
|
49 | // k = 0 1
|
50 | // MainFlag = 1 1
|
51 | // -----
|
52 | // total: 95
|
53 | // --------------------------------------------------
|
54 | |
55 | |
56 | TimerOverflow: |
57 | {
|
58 | // Passiert alle 0.1 ms
|
59 | |
60 | IF TimeMeasRunning |
61 | {
|
62 | Inc _t_ |
63 | |
64 | IF (_t_<_Grenzwert_) |
65 | {
|
66 | PortState = PORTX |
67 | |
68 | FOR (i = 0...8-1) // 8 = Anzahl der Lichtschranken |
69 | {
|
70 | IF (Bit i in PortState gesetzt) |
71 | {
|
72 | _Time_[i] = _t_ // Auslösezeit protokollieren |
73 | }
|
74 | }
|
75 | }
|
76 | }
|
77 | |
78 | //-----------------------
|
79 | |
80 | MainFlag = 0 |
81 | |
82 | inc k |
83 | |
84 | IF (k=200) |
85 | {
|
86 | // Passiert alle 20 ms
|
87 | |
88 | k = 0 |
89 | |
90 | MainFlag = 1 |
91 | }
|
92 | }
|
93 | |
94 | reti
|
95 | |
96 | |
97 | //=============================================
|
98 | |
99 | ResetTimer: |
100 | {
|
101 | _t_ = 0 |
102 | |
103 | FOR (i = 0...8-1) // 8 = Anzahl der Lichtschranken |
104 | {
|
105 | _Time_[i] = -1 |
106 | }
|
107 | }
|
108 | |
109 | |
110 | //=============================================
|
111 | |
112 | Init: |
113 | // Um Initialisierungskram kümmern
|
114 | // ...
|
115 | // ...
|
116 | |
117 | |
118 | Main: |
119 | IF (MainFlag=1) |
120 | {
|
121 | // Passiert alle 20 ms
|
122 | |
123 | // Alles Zeitunkritische erledigen was zu erledigen ist
|
124 | //
|
125 | // - Benutzertasten-Abfragen
|
126 | //
|
127 | // - entsprechend Zeitmessung enablen/disablen
|
128 | // durch Setzen/Löschen von TimeMeasRunning
|
129 | //
|
130 | // - Wenn Zeitmessungslauf gestoppt, _Time_-Werte
|
131 | // für alle ausgelösten Lichtschranken verrechnen
|
132 | //
|
133 | // - Prüfen, ob UART-Ringpuffer voll ist,
|
134 | // gegebenenfalls auswerten
|
135 | //
|
136 | // - Falls nötig Daten über UART an PC senden
|
137 | //
|
138 | // - irgendwelche Kontroll- und Status-LEDs schalten
|
139 | //
|
140 | // - ...
|
141 | }
|
142 | |
143 | sleep
|
144 | |
145 | rjmp Main |
ich hab mir auch nochmal was überlegt ... und zwar auf einem Blatt Papier bitte auseinandernehmen :-) Schönen Abend noch. Ich bin jetzt Fernsehen.
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.
>nur sollte man dann wissen was man tut!
Ja, sollte man. Man sollte das Programm so auslegen, dass man ohne das
SEI auskommt...
Der von Johannes oben gepostete Programmablaufplan sieht das ja eigentlich so auch vor...
> 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
Hab ich den Ursprungsthread gefunden: Beitrag "Re: Suche Konzept für Messprogramm (+Schaltplan überprüfe" ?
> 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.
@ avr fan: Aber mit genau 8mhz habe ich dann weider ein Problem mit dem UART ;-) Also lassen wird das so ;-)
@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 %
Ach, ist ja alles egal, wenns mit 14,7456 MHz auch funktioniert (das wird jetzt dann getestet :-)
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
Die 19 die ich oben gezählt habe waren nur der 'variable' Teil. Bei den 34 Takten ist dann auch das dabei, was in allen 3 Zweigen gleich gemacht wird.
@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 nix
zustimm 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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.