Hallo! Ich lese das Drehzahl vom Motor meines Autos über den µC ein. Das Signal ist pulsweitenmoduliert. Da es nicht genau sein muss lese ich es einfach direkt über einen Portpin ein und zähle mit, wie lange das signal high ist. Das funktioniert auch relativ gut (bis auf das, dass ab und zu auch komplett unsinnige werte eingelesen werden, aber egal). Die umgerechnete Drehzahl gib ich dann am LCD aus. Das Problem ist nun, dass die division durch 10 und wieder anschliessende multiplikation mit 10 anscheinend nicht immer funktioniert. Ich will damit nur die unsinnige Einer-Stelle des Drehzahlsignals abschneiden. Aber trotzdem zeigt die Drehzahl am LCD ab und zu noch eine einerstelle an (also irgendwas anderes als 0). eine zeit lang ist die drehzahl am lcd immer im zehnerbereich und dann hab ich auf einmal wieder 2568 rpm. Vielen Dank schonmal im Voraus mfg Wolfgang
Laß doch die ganze komplizierte Hin- und Herrechnerei sein, rechne von vornerein immer mit "drehzahl_in_10rpm" und gib nachher noch eine 0 aus. Sollte auch schneller gehen ;-) also
1 | if (Drehzahl_in_teile > 0) |
2 | {
|
3 | Drehzahl_in_10rpm = 700000 / Drehzahl_in_teile; |
4 | }
|
(mit einer 0 weniger) und danach natürlich
1 | if (Drehzahl_in_10rpm > 450) Drehzahl_in_10rpm = 450; |
2 | if (Drehzahl_in_10rpm < 50) Drehzahl_in_10rpm = 0; |
später hängst du einfach die 0 dran:
1 | strcat(Drehzahl_in_rpm_Temp, "0"); |
Bedenken mußt du nämlich, daß eine Division, auch wenn sie korrekt funktioniert, ganz schön Rechenleistung frißt, vor allem bei long.
@ atze: Ja das sind Ganzzahltypen. @ der mechatroniker: Ja das stimmt. Diese paar Berechnungen fressen mir sehr die Rechenleistung auf. Und was ist jetzt der Grund dafür, dass die Ausgabe der Drehzahl am LCD ab und zu stimmt und dann wieder nicht?
Entweder optimiert der Compiler /10 *10 weg (kann ich mir eigentlich nicht vorstellen), oder der Fehler liegt wo anders: Wie gibst du denn die Drehzahl aus? Interrupt-gesteuert? Wenn ja, dann könnte der Interrupt ja auch genau beim Abarbeiten des Drehzahl-lesens eintreffen und Dir damit deine Werte versauen. Nu so eine Idee.
Die Ausgabe erfolgt ganz normal am Schluss der Hauptschleife. Nach den ganzen Berechnungen und Einlesen der Ports, usw. Das kanns nicht sein. Dass der Compiler es weg optimiert glaub ich auch nicht, da beim Wert am Display die meiste Zeit die Einerstelle dann 0 ist. Ab und zu dann für ein paar Sekunden dann aber wieder nicht. Es ist auch kein Muster zu erkennen, dass es regelmäßig dann die Einerstelle wieder ausgibt.
1 | void Drehzahl_einlesen (void) |
2 | {
|
3 | ...
|
4 | |
5 | if (bit_is_clear(PIND, 3) && freigabe_drehzahl == 2) |
6 | {
|
7 | freigabe_drehzahl = 0; |
8 | }
|
9 | |
10 | ...
|
11 | }
|
Ist es gewollt, daß freigabe_drehzahl == 2 bleibt, wenn nach dem Verlassen der while-Schleife bit_is_clear(PIND, 3) false zurückgibt?
Ja das ist gewollt da die if in der while nur zum begrenzen der variable und somit der unteren drehzahlgrenze dient. Aber durch das hast du mich auf etwas anderes aufmerksam gemacht. Muss ich gleich mal nachschauen. Ich meld mich später wieder...
So, hab eine neue Methode ausprobiert, die das Signal genauer einliest ohne Schwankungen, aber dafür blockiere ich den µC damit. Dachte am Anfang das wär nicht so arg, aber anscheinend doch. Die Aktualisierungszeit des Drehzahlsignals ist dadurch auf ein paar Sekunden gestiegen! Hier der Code: if (bit_is_clear(PIND, 3)) { Drehzahl_in_teile = 0; while (bit_is_clear(PIND, 3)) {}; while ((bit_is_set(PIND, 3)) && (Drehzahl_in_teile < 65000)) Drehzahl_in_teile++; } Der Code an sich stimmt ja oder? Aber kann es wirklich sein, dass dieser code den µC so ausbremst?
Wie würde bei euch der Code für das Einlesen eines PWM-Signals von einem Datenpin aussehen? (ohne Timer und Interrupt, die sind schon für eine pwm-ausgabe in verwendung) Ich brauche keinen kompletten Source-Code, sondern eh nur die Stelle mit der Abfrage. Das Signal hat eine Periodendauer von ein paar ms, der Takt des µC ist 16MHz und die Abfrage sollte den µC nicht zu lange auslasten, da ich auch noch Spannungen mittels ADC einlese und die dann immer schnell am LCD angezeigt werden sollen, ohne "Ruckler". es wäre gut wenn das Signal um die 10 mal/s eingelesen wird, nicht langsamer.
Wolfgang wrote: > Aber kann es wirklich sein, dass dieser > code den µC so ausbremst? Dein Code pollt das Signal. Er wartet also solange in der Schleife, bis er einen kompletten High-Puls des Signals gesehen hat. Das 'Ausbremsen' ist also per Design: In der Zeit, in der der Eingangspegel des Signals auf High ist, passiert nichts weiter (ausser einem möglichen Interrupt) und kann auch nichts weiter passieren.
Wolfgang wrote: > Wie würde bei euch der Code für das Einlesen eines PWM-Signals von einem > Datenpin aussehen? (ohne Timer und Interrupt, die sind schon für eine > pwm-ausgabe in verwendung) Es gibt nur die beiden Möglichkeiten * entweder du pollst das Signal * oder du lässt dir einen Interrupt vom Signal erzeugen, wenn es den Pegel wechselst. Allerdings brauchst du dazu einen Timer, denn irgendwie musst du ja auch die Zeit messen.
Dass der µC durch das Pollen ausgebremst wird ist mir klar, mir ist nur nicht klar, warum die Aktualisierungsrate des LCD auf einmal alle 3 sekunden ansteigt mit diesem code hier: if (bit_is_clear(PIND, 3)) { Drehzahl_in_teile = 0; while (bit_is_clear(PIND, 3)) {}; while ((bit_is_set(PIND, 3)) && (Drehzahl_in_teile < 65000)) Drehzahl_in_teile++; } Mit dem alten Code hier hingegen funktioniert es einwandfrei, dass die Werte am LCD mehrere Male pro Sekunde aktualisiert werden, ohne dass irgend ein anderer Programmteil geändert wurde. if (bit_is_clear(PIND, 3) && freigabe_drehzahl == 0) { freigabe_drehzahl = 1; Drehzahl_in_teile = 0; } while ((bit_is_set(PIND, 3) && freigabe_drehzahl == 1)) { Drehzahl_in_teile++; if (Drehzahl_in_teile > 65000) { freigabe_drehzahl = 2; } } if (bit_is_clear(PIND, 3) && freigabe_drehzahl == 2) { freigabe_drehzahl = 0; } Will den ganz obigen neuen Code aber lieber verwenden, da er genauer ist als der untere, bezüglich wann der Beginn des High ist. Der µC läuft ja mit 16MHz und das Signal hat eine Periodendauer von maximal 50ms. Warum schaut es dann so aus, als ob der µC für mehrere Sekunden blockiert ist mit dieser Polling-Methode? Denkfehler im Code?
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.