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.
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?