Guten Morgen allerseits, ich habe eine komplexere Timer-ISR, in der ich auch float-Berechnungen machen muss. Daher wäre es wichtig zu wissen, wie lange die ISR (in CPU-Takten) braucht. Daher möchte ich die irgendwie "ausstoppen". Als "normale" Funktion wird das eher schwierig, da Prolog und Epilog u.U. anders aussehen... Meine Idee dazu wäre, die Funktion erstmal in eine andere spezielle ISR zu geben, welche ich per Instruktion triggern kann. Dann Timer1 entsprechend hoch auflösend programmieren, TCNT1 merken, ISR auslösen, TCNT1 nochmal auslesen, die Differenz sollte dann (mit etwas Offset) recht genau die Laufzeit ergeben. Welcher Interrupt wäre dafür geeignet? Ich kann mich dunkel erinnern, dass es da irgendwas mit EEPROM write gibt...
Du kannst die ISR im AVR-Studio simulieren und dabei die Takte zählen. Grundsätzlich sollte eine Interruptroutine aber so kompakt wie möglich sein und deine Fliesskommazahlberechnung in einer seperaten Funktion liegen die vom Hauptprogram aufgerufen wird. Die ISR setzt dann nur den Trigger.
@ Michael Reinelt (fisa) >machen muss. Daher wäre es wichtig zu wissen, wie lange die ISR (in >CPU-Takten) braucht. Daher möchte ich die irgendwie "ausstoppen". Früher hieß das schlicht "messen". Kann man im Simulator oder mit einem Testpin und Oszilloskop. >Meine Idee dazu wäre, die Funktion erstmal in eine andere spezielle ISR >zu geben, welche ich per Instruktion triggern kann. Dann Timer1 >entsprechend hoch auflösend programmieren, TCNT1 merken, ISR auslösen, >TCNT1 nochmal auslesen, die Differenz sollte dann (mit etwas Offset) >recht genau die Laufzeit ergeben. Nö.
:
Bearbeitet durch User
Wayne schrieb: > Du kannst die ISR im AVR-Studio simulieren und dabei die Takte > zählen. > Grundsätzlich sollte eine Interruptroutine aber so kompakt wie möglich > sein und deine Fliesskommazahlberechnung in einer seperaten Funktion > liegen die vom Hauptprogram aufgerufen wird. Die ISR setzt dann nur den > Trigger. verstehe auch immer nicht, was alle welt riesige berechungen und algorithmen in einen armen kleinen interrupt setzen will :-)
Falk Brunner schrieb: > Nö. Warum nicht? Simulator hab ich im Moment keinen (ich verwend kein AVR Studio), wenns sich vermeiden lässt möchte ich mir den auch nicht antun... Wayne schrieb: > Grundsätzlich sollte eine Interruptroutine aber so kompakt wie möglich > sein und deine Fliesskommazahlberechnung in einer seperaten Funktion > liegen die vom Hauptprogram aufgerufen wird. Die ISR setzt dann nur den > Trigger. Das stimmt grundsätzlich, es gibt aber Fälle wo es klüger ist solche Berechnungen in der ISR auszuführen (ist so wie mit dem "goto", das nicht immer böse ist)
Michael Reinelt schrieb: > Simulator hab ich im Moment keinen (ich verwend kein AVR Studio), wenns > sich vermeiden lässt möchte ich mir den auch nicht antun... Ist das irgendwie eine Glaubensfrage? Der Simulator jedenfalls ist kein Hexenwerk und ist für vieles unbrauchbar, aber gerade die Laufzeiten von Routinen sind etwas, das er recht gut kann, wenn man die Breakpoints richtig setzt. 'Türlich kannst du auch die Timernummer machen, aber das erfordert Eingriffe in den Code, den du messen willst.
Oszi oder Logikanalysator vorhanden, oder sonst irgendwas, das Zeiten eines Pins messen kann? Dann Pin am Anfang der ISR setzen, am Ende zurücksetzen. Da fehlt dann nur der Overhead des Handlers,
:
Bearbeitet durch User
Michael Reinelt schrieb: > Falk Brunner schrieb: >> Nö. > > Warum nicht? > > Simulator hab ich im Moment keinen (ich verwend kein AVR Studio), wenns > sich vermeiden lässt möchte ich mir den auch nicht antun... > > Wayne schrieb: >> Grundsätzlich sollte eine Interruptroutine aber so kompakt wie möglich >> sein und deine Fliesskommazahlberechnung in einer seperaten Funktion >> liegen die vom Hauptprogram aufgerufen wird. Die ISR setzt dann nur den >> Trigger. > > Das stimmt grundsätzlich, es gibt aber Fälle wo es klüger ist solche > Berechnungen in der ISR auszuführen (ist so wie mit dem "goto", das > nicht immer böse ist) ich bin neugierig... nenne mir bitte ein beispiel damit ich die logik dahinter verstehe meine intuition ist nach wie vor: was macht das programm bei langen IR routinen, wenn beispielsweise ein neuer IR und wieder ein neuer IR kommt... das ist dann nicht ganz sauber meiner meinung nach... ein IR gibt eigtl nur einen "anstoß"
tester schrieb: > meine intuition ist nach wie vor: was macht das programm bei langen IR > routinen, wenn beispielsweise ein neuer IR und wieder ein neuer IR > kommt... das ist doch exakt im Datenblatt beschrieben.
>meine intuition ist nach wie vor
Da ist ja Glaskugelschauen noch exakter. Man-o-man.
dann antwortet dem poster ihr klugscheißer, statt einem weiteren fragenden das obst hinter her zu werfen ;-)
A. K. schrieb: > Oszi oder Logikanalysator vorhanden, oder sonst irgendwas, das Zeiten > eines Pins messen kann? Dann Pin am Anfang der ISR setzen, am Ende > zurücksetzen. Da fehlt dann nur der Overhead des Handlers, So würde ich es auch machen. Falls die Frequenz des Interrupts konstant ist, kannst Du auch den Ausgangspin über ein RC-Glied 10k+100nF leicht filtern, die Spannung messen und daraus das Tastverhältnis und die eff. Ausführungszeit ermitteln. Selbst, wenn die Frequenz nicht konstant ist, zeigt das Tastverhältnis die Auslastung des Prozessors an; bei unter 50% bist Du im grünen Bereich. Und wenn Du float Berechnungen im Interrupt brauchst, dann mache es und laß Dich nicht von Anderen anmachen, die darin den Weltuntergang sehen. Das Thema Angsthasen hatten wir doch schon die Tage? :-)
Matthias Sch. schrieb: > Ist das irgendwie eine Glaubensfrage? Der Simulator jedenfalls ist kein > Hexenwerk und ist für vieles unbrauchbar, aber gerade die Laufzeiten von > Routinen sind etwas, das er recht gut kann, wenn man die Breakpoints > richtig setzt. Nicht jeder arbeitet unter Windows und hat damit Zugang zum AVR Studio, was aber leider, das muss man zugeben, den besten Simulator und Debugger mitbringt. simulavr ist da eine Krücke dagegen, wird (imho) nicht mehr gepflegt und Takte zählen konnte es sowieso noch nie. @ TO: du kannst natürlich die Timermethode verwenden. Dann würd ich das aber gleich konsequent zu Ende denken und das ganze sauber aufziehn. Routinen um Zeiten zu messen kann man öfter brauchen.
Michl schrieb: > Nicht jeder arbeitet unter Windows und hat damit Zugang zum AVR Studio, > was aber leider, das muss man zugeben, den besten Simulator und Debugger > mitbringt. also das eine Glaubensfrage. Welchen Grund gibt es kein Windows zu verwenden wenn es dort die passenden Tools für die Arbeit gibt? (Man kann Windows auch ohne Netzwerk betreiben, falls man Paranoid ist.) geht es wirklich um die Lizenzkosten von 40€?
Michl schrieb: > Routinen um Zeiten zu messen kann man öfter brauchen. Da war doch mal was? Beitrag "Stoppuhr – Geschwindigkeit – Pulsweite mit Atmega88"
Michael Reinelt schrieb: > ich habe eine komplexere Timer-ISR, in der ich auch float-Berechnungen > machen muss. Daher wäre es wichtig zu wissen, wie lange die ISR (in > CPU-Takten) braucht. Daher möchte ich die irgendwie "ausstoppen". Der Timer läuft doch mit. Einfach am Ende den Timer auslesen und in eine Variable speichern, wenn er größer als der vorherige Wert war.
Danke für die rege Beteiligung! Glaubensfrage ist das keine, ich arbeite halt eher "old school", linux, emacs und ein Makefile sind meine Freunde :-) Und ich hab einen Microsoft-freien Haushalt. Oszi wäre vorhanden, Logikanalysator nicht. Ist mir aber zu ungenau, zu umständlich, greift tatsächlich in den Code ein (ich muss ja schließlich einen Pin hoch-. und runterziehen). Vor allem ist es damit schwierig, Maximalwerte zu ermitteln (und die float-Berechnungen zeigen durchaus unterschiedliche laufzeiten) Dis Diskussion, ob float-Berechnungen in die ISR gehören, können wir gerne in einem anderen Thread führen, das gehört nicht unbedingt hierher. in meinem Fall ist es sinnvoll. Zur Klarstellung: ich rede von Laufzeiten von 600-800 Zyklen, also nix mörder-kompliziertes... trotzdem kann das eng werden, wenn der Timer alle 1000 Takte zuschlägt. Mittlerweile bin ich eh etwas schlauer: "Software-Interrupts" lautet das zauberwort, diese kennt der AVR aber direkt nciht. man kann sich aber helfen, indem man einen PinChange-Interrupt verwendet, und den Pin per Software ändert (löst dann auch den interrupt aus). Und da gab es eben eine zweite Methode, die mir Peter Dannegger mal verraten hat, irgendwas mit dem EEPROM... ich find aber den Thread nicht mehr. Ist aber egal, PCINT reicht mir vorerst. Pseudo-Code:
1 | ISR(PCINT) |
2 | {
|
3 | /* tu was kompliziertes */
|
4 | double x = 65535*sqrt(rand())); |
5 | /* verwende die Varia<ble auch */
|
6 | OCR1A = (uint16_t) x; |
7 | }
|
8 | |
9 | int main (void) |
10 | {
|
11 | |
12 | setup_timer(); /* Timer 1 ohne Prescaler initialisieren */ |
13 | setup_pcint(); /* PCINT initialisieren */ |
14 | |
15 | uint16_t min = 65535; |
16 | uint16_t max = 0; |
17 | |
18 | for (uint16_t n = 0; n < 1000; n++) { |
19 | uint16_t t1 = TCNT1; |
20 | trigger_pcint(); /* PCINT auslösen */ |
21 | uint16_t t2 = TCNT1; |
22 | uint16_t t = t2-t1; |
23 | if (t < min) min = t; |
24 | if (t > max) max = t; |
25 | uart_printf ("%d: t=%d min=%d max=%d\n", n, t, min, max); |
26 | _delay_ms (100); // for UART flush |
27 | }
|
28 | }
|
Michael Reinelt schrieb: > ich rede von Laufzeiten von 600-800 Zyklen, also nix > mörder-kompliziertes... trotzdem kann das eng werden, wenn der Timer > alle 1000 Takte zuschlägt. Für mich wäre das schon zu eng! Wenn ich nicht irre, geht es immer noch um Rampenberechnung für Schrittmotore. Da würde ich die Berechnung nicht bei jedem Schritt durchführen, sondern meinetwegen bei jedem 2. oder 5.. Damit wäre Alles viel entspannter.
m.n. schrieb: > Michael Reinelt schrieb: >> ich rede von Laufzeiten von 600-800 Zyklen, also nix >> mörder-kompliziertes... trotzdem kann das eng werden, wenn der Timer >> alle 1000 Takte zuschlägt. > > Für mich wäre das schon zu eng! > Wenn ich nicht irre, geht es immer noch um Rampenberechnung für > Schrittmotore. Da würde ich die Berechnung nicht bei jedem Schritt > durchführen, sondern meinetwegen bei jedem 2. oder 5.. > Damit wäre Alles viel entspannter. Du hast recht. Mit an Sicherheit grenzender Wahrscheinlichkeit werd ich aber nie in die Region 1000 Takte Timer kommen (so schnell muss mein Stepper nie im Leben drehen). Aber um das alles besser abschätzen zu können, müsste ich halt erstmal wissen wieviele takte die ISR tatsächlich (worst case) brauchen kann, dann weiss ich ob ich genug "Sicherheitsabstand" habe.
Hallo Michael, ich habe so etwas mal mit einem 16Bit Zähler und Vorteiler 1 realisiert. Am Anfang der ISR Routine wird der Timer gestartet und am Ende entsprechend gestoppt und das Ergebnis - die Takte für Start/Stop an das Hauptprogramm übergeben. Pseudocode
1 | Start() { |
2 | 16Bit-Timer Prescaler = 1 |
3 | }
|
4 | Stop() { |
5 | 16Bit-Timer Prescaler = 0 |
6 | Zaehler auslesen |
7 | Zaehler an das Hauptprogramm uebergeben |
8 | Zaehler=0 setzen |
9 | }
|
Im Hauptprogramm wurden die Taktzyklen dann auf einem LCD ausgegeben.
:
Bearbeitet durch User
Michael Reinelt schrieb: > m.n. schrieb: >> Michael Reinelt schrieb: >>> ich rede von Laufzeiten von 600-800 Zyklen, also nix >>> mörder-kompliziertes... trotzdem kann das eng werden, wenn der Timer >>> alle 1000 Takte zuschlägt. >> >> Für mich wäre das schon zu eng! >> Wenn ich nicht irre, geht es immer noch um Rampenberechnung für >> Schrittmotore. Da würde ich die Berechnung nicht bei jedem Schritt >> durchführen, sondern meinetwegen bei jedem 2. oder 5.. >> Damit wäre Alles viel entspannter. @ Michael Reinelt Ist das richtig? Geht es um eine Rampenberechnung für einen Schrittmotor? Falls ja, ist das eine lineare Rampe?
Michael Reinelt schrieb: > Aber um das alles besser abschätzen zu können, müsste ich halt erstmal > wissen wieviele takte die ISR tatsächlich (worst case) brauchen kann, > dann weiss ich ob ich genug "Sicherheitsabstand" habe. Das nutzt Dir solange nichts, solange Du nicht auch alle anderen Interrupts im Programm berücksichtigst. Für eine Abschätzung hast Du genug Vorschläge bekommen: such Dir einen aus und mache es einfach! Eine weitere Möglichkeit wäre noch, einen Pin zu setzen, wenn intern mehr als 800 Takte benötigt wurden (>= 80%). Im Betrieb kann man dann sehen, ob diese Grenze überschritten wird bzw. wurde. Um sicher zu gehen, Dein ATmega328 wird ja hoffentlich mit 20MHz betrieben?
Bitflüsterer schrieb: > Ist das richtig? Geht es um eine Rampenberechnung für einen > Schrittmotor? Falls ja, ist das eine lineare Rampe? Ja. Aber mit etwas "unüblichen" Randbedingungen: ich fahre keine Positionen an, sondern Geschwindigkeiten (Position ist völlig irrelevant). Berechnung nach Aryeh Eiderman siehe hier: http://www.hwml.com/LeibRamp.htm m.n. schrieb: > Das nutzt Dir solange nichts, solange Du nicht auch alle anderen > Interrupts im Programm berücksichtigst. Mach ich, bzw. gibt es deren wenige, und die sind sehr kurz. m.n. schrieb: > Um sicher zu gehen, Dein ATmega328 wird ja hoffentlich mit 20MHz > betrieben? Momentan 16, könnte aber noch auf 20 gehen. Hängt aber alles davon ab wie eng es dann tatsächlich wird...
Michael Reinelt schrieb: > greift tatsächlich in den Code ein (ich muss ja schließlich > einen Pin hoch-. und runterziehen). Kostet 2 Takte vorne, 2 Takte hinten. Bei 600-600 Takten. Ok. Wenn das wirklich auf den einzelnen Takt genau sein muss und 4 abziehen nicht in Frage kommt...
:
Bearbeitet durch User
Michael Reinelt schrieb: > Bitflüsterer schrieb: >> Ist das richtig? Geht es um eine Rampenberechnung für einen >> Schrittmotor? Falls ja, ist das eine lineare Rampe? > > Ja. Aber mit etwas "unüblichen" Randbedingungen: ich fahre keine > Positionen an, sondern Geschwindigkeiten (Position ist völlig > irrelevant). Berechnung nach Aryeh Eiderman siehe hier: > http://www.hwml.com/LeibRamp.htm @ Michael Reinelt Aha. Wärst Du denn grundsätzlich daran interessiert, die Fließkommarechnung zu vermeiden?
Bitflüsterer schrieb: > Aha. Wärst Du denn grundsätzlich daran interessiert, die > Fließkommarechnung zu vermeiden? Ja. Siehe hier: Beitrag "AVR: Floating Point => integer arithmetik"
Allenfalls kann man auch mit fixedpoint arbeiten, wenn man den dynamischen Bereich der float nicht benoetigt. Eine integer operation ist noch ein stueck schneller als eine float operation, da der Exponent nicht gerechnet(normalisiert) werden muss.
A. K. schrieb: > Michael Reinelt schrieb: >> greift tatsächlich in den Code ein (ich muss ja schließlich >> einen Pin hoch-. und runterziehen). > > Kostet 2 Takte vorne, 2 Takte hinten. Bei 600-600 Takten. Ok. Wenn das > wirklich auf den einzelnen Takt genau sein muss und 4 abziehen nicht in > Frage kommt... Die 2+2 Takte sind mir egal, aber der gesamte Pre- und Epilog fehlt mir (und der ist nichtmal konstant, je nachdem wieviele Register verwendet werden, fürchte ich) Obwohl das bei 600 Takten auch nicht wirklich ins Gewicht fallen wird <trotzig> aber trotzdem, ich wills wissen </trotzig> :-)
:
Bearbeitet durch User
Kein Troll schrieb: > Allenfalls kann man auch mit fixedpoint arbeiten, wenn man den > dynamischen Bereich der float nicht benoetigt. Eine integer operation > ist noch ein stueck schneller als eine float operation, da der Exponent > nicht gerechnet(normalisiert) werden muss. Ich brauch vermutlich den dynamischen Bereich. Ein großer Vorteil von Float ist, dass man Divisionen mit konstantem Divisor durch eine Multiplikation mit dem Kehrwert ersetzen kann. Wenn man im integer-Bereich dividieren muss, schmilzt der Geschwindigkeitsvorteil ziemlich dahin...
@ Michael Reinelt Ich will auf folgendes hinaus: Ganz allgemein gehe ich so vor, diese Werte nicht während des Laufs auszurechnen sondern vorher. (Es sei denn, es existieren noch dynamische Nebenbedingungen). Ich hatte selbst vor kurzer Zeit den Fall, das ich die Geschwindigkeit eines Schrittmotors, innerhalb einer vorgegebenen Schrittzahl von Null auf einen gewissen Wert bringen musste. Der "gewisse Wert" musste nahe genug an einem dynamischen Sollwert liegen; bei dem dann ein PI-Regler eingegriffen hat. Der zeitliche Verlauf der Geschwindigkeit aber, war nebensächlich. Konnte also auch linear sein. Daraus ergibt sich ein konstantes Dekrement für die Timerperiode. Der rechnerisch sich ergebende Rest der Division der Differenz der Impulsperioden durch die Anzahl der Schritte, kann entweder beim Initialwert oder beim Endwert berücksichtigt werden. Damit ergibt sich ein konstanter integer Dekrement für die Timerperiode.
Bitflüsterer schrieb: > @ Michael Reinelt > > Ich will auf folgendes hinaus: > Ganz allgemein gehe ich so vor, diese Werte nicht während des Laufs > auszurechnen sondern vorher. (Es sei denn, es existieren noch > dynamische Nebenbedingungen). > > Ich hatte selbst vor kurzer Zeit den Fall, das ich die Geschwindigkeit > eines Schrittmotors, innerhalb einer vorgegebenen Schrittzahl von Null > auf einen gewissen Wert bringen musste. Der "gewisse Wert" musste nahe > genug an einem dynamischen Sollwert liegen; bei dem dann ein PI-Regler > eingegriffen hat. > Der zeitliche Verlauf der Geschwindigkeit aber, war nebensächlich. > Konnte also auch linear sein. > > Daraus ergibt sich ein konstantes Dekrement für die Timerperiode. Der > rechnerisch sich ergebende Rest der Division der Differenz der > Impulsperioden durch die Anzahl der Schritte, kann entweder beim > Initialwert oder beim Endwert berücksichtigt werden. > Damit ergibt sich ein konstanter integer Dekrement für die Timerperiode. Das ist dann aber alles andere als eine lineare Rampe! Was ich brauche ist eine (zumindest annähernd) konstante Beschleunigung, die möglichst nahe an der maximal möglichen Beschleunigung liegt. Die dafür notwendige Mathematik beschriebt Eiderman sehr gut, inklusive einiger guter Optimierungen.
Michael Reinelt schrieb: > Was ich brauche ist eine (zumindest annähernd) konstante Beschleunigung, Die Du realistisch hervorragend in einer Lookup-Table hinterlegen kannst.
Walter Tarpan schrieb: > Michael Reinelt schrieb: >> Was ich brauche ist eine (zumindest annähernd) konstante Beschleunigung, > > Die Du realistisch hervorragend in einer Lookup-Table hinterlegen > kannst. Nein, eben nicht. Aber das hatten wir alles schon an anderer Stelle.
Dieter Frohnapfel schrieb im Beitrag #3655229: > Kennst Du das? > > http://hwml.com/LeibRamp.pdf Lieb von dir :-) Magst mal ein paar Beiträge nach oben scrollen (oder nach "LeibRamp" suchen?)
Michael Reinelt schrieb: > Bitflüsterer schrieb: >> @ Michael Reinelt >> ... >> Damit ergibt sich ein konstanter integer Dekrement für die Timerperiode. > > Das ist dann aber alles andere als eine lineare Rampe! Das ist durchaus eine lineare Rampe. Die Geschwindigkeit steigt linear an. :-) > Was ich brauche ist eine (zumindest annähernd) konstante Beschleunigung, > die möglichst nahe an der maximal möglichen Beschleunigung liegt. Aha. Die Beschleunigung soll konstant sein. (Daraus ergibt sich aber auch nichts lineares, oder?) Darf ich fragen, warum die Beschleunigung konstant sein soll? Als Bemerkung möchte ich noch hinzufügen, dass ein (allgemein üblicher) Schrittmotor keinen linear über die Drehzahl verlaufenden maximale Beschleunigung hat. Das ist zwar ein wenig um die Ecke ausgedrückt, ist aber das Äquivalent zu der Tatsache, dass das maximale Drehmoment (bei konstanter Last) über die Drehzahl nicht konstant ist. Im Stillstand ist der Drehmoment am höchsten und er sinkt mit steigender Drehzahl. Daraus würde folgen, dass eine konstante Beschleunigung nur mit der minimal auftretenden möglich ist; also bei Enddrehzahl und gegebener Last. Könnte das für Deine Aufgabe relevant sein?
Bitflüsterer schrieb: > Das ist durchaus eine lineare Rampe. Die Geschwindigkeit steigt linear > an. :-) Aber die Zeit nicht (in deinem Fall) > Aha. Die Beschleunigung soll konstant sein. (Daraus ergibt sich aber > auch nichts lineares, oder?) konstante beschleunigung heisst konstante geschwindigkeitsänderung pro zeiteinheit, oder? > Darf ich fragen, warum die Beschleunigung konstant sein soll? sie muss nicht konstant sein, aber maximal hoch (was idR auf konstant hinausläuft) Dein Einwand mit dem nicht konstanten Drehmoment ist korrekt. Das Drehmoment sinkt aber erst bei recht hohen Drehzahlen stark ab, ich bleib aber eh im unteren bereich, meine maximale Beschleunigung entspricht halt dem Drehmoment bei maximaldrehzahl.
Michael Reinelt schrieb: > Magst mal ein paar Beiträge nach oben scrollen (oder nach "LeibRamp" > suchen?) Habs leider zu spät gesehen - aber noch vor Deiner Antwort :-) Arbeite damit (ATMEGA32 mit 16 MHz) - wenn ich die Rampe berechne und den Schrittmotor rennen lasse muss ich alle anderen Interrupts etc. ausschalten :-(
Dieter Frohnapfel schrieb: > Michael Reinelt schrieb: >> Magst mal ein paar Beiträge nach oben scrollen (oder nach "LeibRamp" >> suchen?) > > Habs leider zu spät gesehen - aber noch vor Deiner Antwort :-) Und ich konnte meine Antwort nicht mehr löschen :-( > Arbeite damit (ATMEGA32 mit 16 MHz) - wenn ich die Rampe berechne und > den Schrittmotor rennen lasse muss ich alle anderen Interrupts etc. > ausschalten :-( Kannst/Darfst du mir Source zukommen lassen?
Michael Reinelt schrieb: > Bitflüsterer schrieb: >> Das ist durchaus eine lineare Rampe. Die Geschwindigkeit steigt linear >> an. :-) > > Aber die Zeit nicht (in deinem Fall) Huch?! Die Zeit ist per Axiom linear. Wahrscheinlich ein Missverständnis. Was meinst Du? >> Aha. Die Beschleunigung soll konstant sein. (Daraus ergibt sich aber >> auch nichts lineares, oder?) > > konstante beschleunigung heisst konstante geschwindigkeitsänderung pro > zeiteinheit, oder? Ja richtig. Ist zwar unüblich das zu betrachten, aber formal hast Du recht. Ob das unüblich ist, hängt allerdings sicher davon ab, in welchen Kontexten man sich bewegt. >> Darf ich fragen, warum die Beschleunigung konstant sein soll? > > sie muss nicht konstant sein, aber maximal hoch (was idR auf konstant > hinausläuft) Gut. Darf ich dann fragen warum die Beschleunigung maximal sein soll? > Dein Einwand mit dem nicht konstanten Drehmoment ist korrekt. Das > Drehmoment sinkt aber erst bei recht hohen Drehzahlen stark ab, ich > bleib aber eh im unteren bereich, meine maximale Beschleunigung > entspricht halt dem Drehmoment bei maximaldrehzahl. Aha. Verstehe.
Michael Reinelt schrieb: > Die 2+2 Takte sind mir egal, aber der gesamte Pre- und Epilog fehlt mir > (und der ist nichtmal konstant, je nachdem wieviele Register verwendet > werden, fürchte ich) Ja. Aber das abzuzählen ist überschaubar.
>Ich brauch vermutlich den dynamischen Bereich. Ein großer Vorteil von
Float ist, dass man Divisionen mit konstantem Divisor durch eine
Multiplikation mit dem Kehrwert ersetzen kann. Wenn man im
integer-Bereich dividieren muss, schmilzt der Geschwindigkeitsvorteil
ziemlich dahin...
Kann man mit fixed point alles auch.
Michael Reinelt schrieb: > Kannst/Darfst du mir Source zukommen lassen? Habe ich im Rahmen meines "Laser-Exposer-Projektes" aus Spass mal gemacht, weil mir die Rückfahrt des Schlittens zu lange gedauert hat. Ist also in eine etwas größere Anwendung eingebunden ... und wahrscheinlich auch nicht optimal. Schau Dir erstmal mein "Basis-Excel-Sheet" dazu an - falls dann immer noch Interesse besteht (da musste ich schon einiges rumfrickeln ...) kann ich Dir die Includes (ohne die Projekt-spezifischen Teile herauszunehmen) gerne per PN zusenden.
Kein Troll schrieb: >>Ich brauch vermutlich den dynamischen Bereich. Ein großer Vorteil > von > Float ist, dass man Divisionen mit konstantem Divisor durch eine > Multiplikation mit dem Kehrwert ersetzen kann. Wenn man im > integer-Bereich dividieren muss, schmilzt der Geschwindigkeitsvorteil > ziemlich dahin... > > Kann man mit fixed point alles auch. Ja, wenn man einen festen Dynamikbereich hat, den ich nicht habe.
Fliesskommarechnung pauschal zu verteufeln bringt nicht weiter. Sie hat ihre Berechtigung. Festkommarechnung kann sie nicht immer ersetzen und kann einen erheblichen Umstellungsaufwand bedeuten, nicht zuletzt in Form von Vorarbeit. Nur muss man sich eben darüber im Klaren sein, dass AVR dafür eine etwas langsame Plattform ist. Da gibt es (pro Stück) günstige Alternativen mit viel höherer Leistung.
:
Bearbeitet durch User
Dein Timer und seine OCRx Register arbeiten eh nur mit Integer bzw. rationalen Verhältnissen. Somit kannst du gleich mit Integer-Approximation rechnen, statt mit Float.
@ Michael Reinelt (fisa) >Glaubensfrage ist das keine, ich arbeite halt eher "old school", linux, >emacs und ein Makefile sind meine Freunde :-) Und ich hab einen >Microsoft-freien Haushalt. Naja. >Oszi wäre vorhanden, Logikanalysator nicht. Dann NIMM IHN! Mein Gott! > Ist mir aber zu ungenau, zu >umständlich, greift tatsächlich in den Code ein (ich muss ja schließlich >einen Pin hoch-. und runterziehen). Was für eine ZUMUTUNG! > Vor allem ist es damit schwierig, >Maximalwerte zu ermitteln (und die float-Berechnungen zeigen durchaus >unterschiedliche laufzeiten) Die musst du so oder so geschickt ermittlen, egal ob im Simulator oder mit der Realmessung. >Zur Klarstellung: ich rede von Laufzeiten von 600-800 Zyklen, also nix >mörder-kompliziertes... trotzdem kann das eng werden, wenn der Timer >alle 1000 Takte zuschlägt. Dein uC läuft nur auf 1MHz? Takt hochstellen? >Mittlerweile bin ich eh etwas schlauer: "Software-Interrupts" lautet das >zauberwort, Wer keine Probleme hat, macht sich welche.
Bitflüsterer schrieb: > Michael Reinelt schrieb: >> Bitflüsterer schrieb: >>> Das ist durchaus eine lineare Rampe. Die Geschwindigkeit steigt linear >>> an. :-) >> >> Aber die Zeit nicht (in deinem Fall) > > Huch?! Die Zeit ist per Axiom linear. Wahrscheinlich ein > Missverständnis. Was meinst Du? Vielleicht ist es ein Mißverständnis: Wenn du in der Timer-ISR die den Step-Impuls für den Schrittmotor-Controller erzeugt, jedesmal den Timer-Wert konstant erniedrigst, so hast du zwar auf den ersten Blick einen linearen Anstieg der Geschwindigkeit. Eigentlich steigt aber sogar die Geschwindigkeit über die Schirttanzahl betrachtet nciht linear. Dazu kommt, dass die Zeit die für jeden Schritt benötigt wird, wird ja immer kleiner. Daraus resultiert keine konstante Geschwindigkeitsänderung pro Zeit. Beispiel: Annahme: 16 MHz CPU-Takt, Timer1 läuft mit Prescaler 16 und erzeugt beim Overflow den Step-Impuls (Effektive Timer-Clock 1 MHz) Wir beginnen mit einer Geschwindigkeit von 100 Schritten/sec, und wollen auf 1000 Schritte/sec beschleunigen Wir beginnen bei einem Timer-Wert von 10.000 => Geschwindigkeit 100 Steps/sec Nun beschleunigen wir, indem wir den Zähler konstant um 100 dekrementieren Nächster Timer-Wert: 9.900 => Geschwindigkeit 101 Schritte pro Sekunde => delta von 1 Schritt/sec Inzwischen sind 9.9 msec vergangen a = delta v durch delta t = 1 / 0.099 =? 101 Schritte/sec^2 gegen Ende hin sind wir bei 1.100 => Geschwindigkeit 909 Schritte/sec letzter Schritt: 1.000 => Geschwindigkeit 1000 Schritte/sec Geschwindigkeitsänderung: 91 Schritte/sec Zeit für den letzten Schritt: 1 msec Beschleunigung: 91/0.001 = 91.000 Schritte/sec^2 Sieht für mich nicht sonderlich linear aus... >> konstante Beschleunigung heisst konstante Geschwindigkeitsänderung pro >> Zeiteinheit, oder? > > Ja richtig. Ist zwar unüblich das zu betrachten, aber formal hast Du > recht. Entweder ich habe meinen gesamten Physik-Unterricht vergessen (oder versoffen), aber ich denke ich habe nicht nur formal recht ;-) > Gut. Darf ich dann fragen warum die Beschleunigung maximal sein soll? Weil ich die neue Solldrehzahl so schnell wie möglich erreichen will? Ist das so unüblich???
:
Bearbeitet durch User
Peter Dannegger schrieb: > Der Timer läuft doch mit. Einfach am Ende den Timer auslesen und in eine > Variable speichern, wenn er größer als der vorherige Wert war. Danke, Peter! Deine Antwort hatte ich in den ganzen Grundsatzdiskussionen hier glatt übersehen... Du triffst wie üblich den Punkt: Damit erreiche ich mit minimalem Aufwand ein maximal genaues Ergebnis, und fange damit auch etwaige "Ausreißer" nach oben hin.
Michael Reinelt schrieb: > Bitflüsterer schrieb: >> Michael Reinelt schrieb: >>> Bitflüsterer schrieb: >>>> Das ist durchaus eine lineare Rampe. Die Geschwindigkeit steigt linear >>>> an. :-) >>> >>> Aber die Zeit nicht (in deinem Fall) >> >> Huch?! Die Zeit ist per Axiom linear. Wahrscheinlich ein >> Missverständnis. Was meinst Du? > > Vielleicht ist es ein Mißverständnis: Wenn du in der Timer-ISR die den > Step-Impuls für den Schrittmotor-Controller erzeugt, jedesmal den > Timer-Wert konstant erniedrigst... Daraus resultiert keine konstante > Geschwindigkeitsänderung pro Zeit. Ja richtig. Mein Fehler. >> Gut. Darf ich dann fragen warum die Beschleunigung maximal sein soll? > Weil ich die neue Solldrehzahl so schnell wie möglich erreichen will? > Ist das so unüblich??? Durchaus nicht. Danke für die Information.
Lasse einen Timer schnell frei laufen und lies in der (fast leeren) Hauptschleife ständig den Wert. Wenn die Differenz zweier Werte über einem Schwellwert ist, hat der Interrupt zugeschlagen - und du kennst die Zeit in der Auflösung des Timers.
tester schrieb: > ich bin neugierig... nenne mir bitte ein beispiel damit ich die logik > dahinter verstehe Wenn man es beherrscht, schreibt man die komplette Anwendung als Sammlung von ISRs. Die Hauptschleife sieht dann (auf das Wesentliche vereinfacht) so aus: main: sleep rjmp main Und dieses Konstrukt ist bei weitem nicht exotisch, sondern Standard bei allen modernen MT-OS, bloß dieses main dort meist IdleTask oder so ähnlich heißt. Alles andere wird als Reaktion auf einen Interrupt abgearbeitet, sogar sämtliche Anwendungstasks sind allesamt letztlich nichts anderes als unterbrechbare Abschnitte einer Timer-ISR. Erkennst du jetzt den Sinn?
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.