Forum: Mikrocontroller und Digitale Elektronik 1/Zeit in Assembler?


von Knut (Gast)


Lesenswert?

Hallo

Ich möchte einen Drehzahlmesser bauen, unter Verwendung des 8515. Ich 
habe bereits den 16-Bit Timer aktiviert, der die Zeit zwischen zwei 
Zündimpulsen misst. Jetzt stehe ich jedoch bei einem Problem an, wie 
wandle ich diese Zeiteinheit in eine proportionale Drehzahl um, die ich 
dann ausgeben kann. Wie Ihr sicher wisst entspricht RPM = 1/s .

MfG

Knut

von Denis (Gast)


Lesenswert?

moin, ein timer zählt im prozessortakt, und dieser hängt vom verwendeten 
quarz und einer eventuellen internen Teilung ab, also wenn der timer bis 
100 hochzählt dann 100 x Dauer eines Prozessortaktes.

das mal so als Anstoß

von Knut (Gast)


Lesenswert?

Das wusste ich auch, vielleicht habe ich mich nicht klar ausgedrückt. 
Mit Zeiteinheit meine ich Zähler*Impulsdauer.

von Denis (Gast)


Lesenswert?

hm, auch auf die Gefahr hin das ich das wieder falsch verstehe,

du hast die Zeit zwischen zwei funken also weißt du auch wie lange 2 bzw 
1 kw-Umdrehung(2takter) dauern,

so,und nun ist das doch nur noch rechnerei auf die richtige Basis sprich 
minuten, z.b. zeitdauer 2 sekunde, das mancht bei 4 takter eine 
umdrehung je 1 s, mal 60 und dann hast du 60 Upm.

und diese berechnung müsste man dann in bestimmten zeitabständen 
wiederholen, aber was vieleicht noch besser ist, bezüglich konflikte mit 
rechenzeit oder sowas, einfach die zeit für ein paar mehr zündimpulse 
zählen und dann erst berechnen.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Wenn genug Speicher übrig ist und keine hohe Auflösung benötigt wird, 
dann würde ich die Umwandlung Zeit -> Frequenz einfach mit einer Tabelle 
(Lookup-Table) machen.

von Mark Hämmerling (Gast)


Lesenswert?

Salut,

@Knut: Nun, eigentlich ist "RPM" bereits eine Einheit und steht (die der 
Name schon sagt) für 2pi/60s.

Das heißt, Kreisfrequenz [omega]=2pi/s einfach mal als [f]=1Hz 
formuliert:

f = CLK / T ; CLK ^= präskalierter Timertakt; T ^= gemessene Zeit für 1 
Umdrehung

also per Minute:

f_RPM = (60 * CLK) / T ; (60 * CLK) = const.

Also bräuchtest Du nur noch eine Division.

"Bräuchtest" deswegen, weil Deinem Verfahren leider ein Designfehler 
innewohnt. Schonmal überlegt, was passiert, wenn die Motorwelle 
stillsteht? Für eine Frequenzmessung solltest Du deshalb eine feste 
Torzeit verwenden. Das heißt: Drehzahlausgang des Motors an T0 oder T1 
legen und den jeweiligen Timer als Event-Counter verwenden. Dann kannst 
Du per Zeitschleife (oder mittels freiem Timer) die Torzeit lang warten 
und anschließend den proportionalen(!) Wert auslesen. Alles, was dann 
noch fehlt ist eine Multiplikation. Wenn Du die Torzeit clever wählst 
(exakte Länge evtl. per Timer Match messen), genügt es vielleicht, den 
Timer-Wert etwas herum zu shiften. :)

Hoffe, das hilft. Viel Spaß beim Basteln!

Mark H. -- http://markh.de/avr/

von ant (Gast)


Lesenswert?

Mit einem externen Interrupt (z.B. int0) die Impulse zählen, parallel 
einen Timer eine konstante Zeit laufen lassen und nach Ablauf Zähler 
auslesen und löschen.

Gruß, Jürgen

von ant (Gast)


Lesenswert?

Ach ja - Entprellen nicht vergessen, falls die Impulse von einem 
Reed-Kontakt kommen.

von Knut (Gast)


Lesenswert?

Danke Mark & Jürgen, auf diese Weise habe ich es mir gar noch nicht 
überlegt, ich werde nun eine geeignete Zeit durchlaufen lassen und 
während dieser jeden Zündimpuls zählen. Somit kriege ich eine 
Proportionalzahl ohne Dividieren zu müssen -> genial!
Wenn ich 0.3s lang warte, habe ich Ideale Voraussetzungen, das wären 
1/200min damit 1/100rpm bei einem Viertakter.
So sollte ich es hinkriegen.

von Andreas H (Gast)


Lesenswert?

Hallöchen!

Da ich auch gerade dabei bin, einen Boardcomputer mit nem 8515 zu bauen, 
könnte es interessant sein, die Überlegungen auszutauschen. Wie oben 
schon festgestellt: Es gibt 2 Möglichkeiten, eine Frequenz zu messen. 
(Im Grunde genommen sind die Motordrehzahlen nix anderes.) Die eine 
Möglichkeit ist es, den Zeitabstand zwischen zwei Impulsen zu messen und 
das dann umzurechnen, die andere Möglichkeit besteht darin, die Anzahl 
der Impulse in einer festgelegten Zeit (=Torzeit) zu zählen. Beides hat 
Vor und Nachteile.

Bei meinen Überlegungen habe ich festgestellt, daß die zweite 
Möglichkeit, die Impulse während einer festen Torzeit zu messen, zwar 
recht einfach, aber auch recht ungenau ist...

Mein Motor läuft im Standgas bei etwa 800 Umdrehungen pro Minute. Das 
sind also 400 Zündungen je Zylinder. In der Sekunde sind das also 
400/60=6,666 Impulse. Wenn ich jetzt nur 0,3 Sekunden warte, dann 
bekomme ich meist nur 2, manchmal aber 3 Impulse innerhalb einer 
Torzeit. Das heißt, meine Anzeige würde zwischen 800 und 1200 RPM 
springen. Die Auflösung der Anzeige beträgt gerade mal 400 RPM!

Denn:
0,3 Sekunden Torzeit entspricht einer Frequenz von 3,33333 Hz. Pro 
Minute sind das (3,33333*60) genau 200 Abtastungen. Bei einem 4-Takter 
habe ich dann exakt 400 Umdrehungen pro Minute, da nur jede 2. Umdrehung 
gezündet wird. Somit hat Knut einen Denkfehler in seiner Rechnung, denn 
er hat bei 0,3s nicht 1/100rpm sondern 1/400rpm. (Oder liege ICH jetzt 
komplett falsch?)

Um auf die Auflösung von 100rpm zu kommen (was MIR immer noch viel zu 
ungenau ist), stelle folgende Überlegung an:

100rpm = 50 Zündungen pro Minute = 0,83333 Zündungen pro Sekunde = 1,2 
Sekunden Zeit zwischen 2 Zündungen. Die Torzeit müßte also 1,2 Sekunden 
betragen, um eine Auflösung von 100rpm zu bekommen.

Bei 800rpm habe ich in 1,2 Sekunden also genau 8 Impulse. Beträgt die 
Drehzahl des Motors allerdings z.B. 830rpm wären das 8,3 Impulse in 1,2 
Sekunden. Da ja aber logischer Weise nur ganze Impulse gezählt werden 
können, habe ich meistens 8 Impulse, durch die Phasenverschiebung 
zwischen Abtastung und Impulsen aber manchmal auch 9 Impulse. Meine 
Anzeige springt also zwischen 800 und 900rpm ständig hin und her.

*** Fazit:
Meiner Meinung nach kann bei einer so niedrigen Frequenz lediglich eine 
einzige sinnvolle Messmethode stattfinden: Messung der Zeit zwischen der 
Impulse und anschließende Umrechnung. Den Code dazu in Assembler sollte 
nicht so schwer hinzubekommen sein, zum Glück gibt es ja die 
ASM32-Routinen, die sich umbasteln lassen :-)

Ich fange gleich mal mit den Überlegungen hierzu an: Ich wähle einen 
Zähler, der alle 1,2ms um eins erhöht wird. Bei 100rpm habe ich dann 
einen Zählerstand von exakt 1000. Ich brauche also nur die Formel
rpm=100000/Zählerstand
zu verwenden. fertig. Einwände? Denkfehler? Ich lasse mich gerne 
Korrigieren! :-)

Da die Berechnung im AVR ja binär erfolgt müssen nach der Berechnung die 
Zahlen nur noch zur Ausgabe umgewandelt werden

Den Code dazu (in Assembler) werde ich mir nachher mal überlegen. Sollte 
ich es gebacken kriegen, werde ich ihn hier posten. :-)

ciao,
Andi

von Knut (Gast)


Lesenswert?

Du hast recht was die Genauigkeit angeht, das würde recht ungenau werden 
mit der Torzeitvariante. Ich sehe eine Präzise Lösung auch nur mittels 
Zeitmessung. Ich sehe nicht ganz wie du die Zahl 100'000 generieren 
möchtest, dazu müsstest du ja 3 Register verwenden, ich hatte eine sehr 
ähnliche Lösung im Kopf bevor ich den ersten Beitrag hier gepostet habe. 
Evtl könnte man alle 2.4ms zählen und 50'000/Zählerstand rechnen, das 
würde jedoch der Genauigkeit schaden.

von Andreas H (Gast)


Lesenswert?

Hallo Knut!

Ich bin gerade dabei in Assembler den Code zur Umrechnung zu schreiben 
und bin fast fertig. Soviel schonmal vorweg: Du hast recht, ich benötige 
für die Zahl "100000" 3 Bytes. Nachdem ich aber noch einige Überlegungen 
gemacht habe, sind die genannten Werte nicht mehr ganz korrekt, aber die 
Größenordnung kommt schon hin. Als Dividend nehme ich jetzt 3750000, 
gezählt wird alle 32µs. Nur so wirds einigermaßen genau, auch noch in 
den oberen Drehzahlen...
( Gib mir noch ne Stunde, dann gibts mehr. Auch den ersten Code... :-)

ciao,
Andi

von Andreas H (Gast)


Angehängte Dateien:

Lesenswert?

Soooo!

Den ersten Abschnitt des Programmes hab ich jetzt fertig. Bisher 
lediglich die Berechnung. Was noch fehlt ist die Zählersteuerung und 
übriger Klimbim wie Ausgabe etc. Allerdings habe ich schon folgende 
Überlegungen gemacht:

Man nehme den Timer1 des 8515 und konfiguriere ihn so, daß er bei jedem 
256. Takt des Prozessortaktes einen hoch zählt. Der Takt des Prozessors 
muß dabei auf 8MHz liegen. Daraus resultiert dann, daß alle 32µs der 
Timer um einen erhöht wird.

In einer Schleife wird ein beliebiger Porteingang des uC überwacht. 
Sofern an diesem Eingang der Zündimpuls erkannt wird, wird der 
Zählerstand in die Register 16/17 übernommen und zurück gesetzt. Im 
Hintergrund läuft der Zähler jetzt schön wieder hoch bis zum nächsten 
Impuls. Bis dieser kommt, haben wir genug Zeit, die Berechnung zu 
starten und noch andere Dinge zu tun. (Siehe Code im Anhang). Zum Ende 
springen wir dann wieder in den Abschnitt der Zählersteuerung. -> 
Endlos...

In die Zählersteuerung kann man jetzt noch ne Art Überlauferkennung 
einbauen um zum Beispiel darauf zu reagieren, wenn die Umdreheungen 
kleiner als 100rpm sind. Das könnte man dann als "Motor steht" 
auswerten. Genauso kann man auch eine (einstellbare) Höchstdrehzahl 
festlegen und warn-LEDs ansteuern. und was einem noch alles so einfällt. 
Wie wäre es z.B. zusätzlich zur Anzeige per LCD (oder 7-Segment-LEDs) 
mit einer LED-Balken-Anzeige?

Fragen? Was falsch? Verbesserungen oder Vorschläge? Immer her damit! :-)

ciao,
Andi

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
Noch kein Account? Hier anmelden.