Hallo zusammen,
ich wollte mir einen Digitalen Drehzahlmesser mit einer LCD-Anzeige fürs
Auto bauen. Es sollte eine Drehzahl von ca. 1000 – 7000 U/min gemessen
werden können. Das entspricht einer Frequenz von 16,6 Hz - 116,6 Hz.
Um die Drehzahl zu erfassen wollte ich mittels Polling die Low-Zeit
zählen. Da ich mich mit der Programmiersprache C recht gut auskenne
sollte das eigentlich kein Problem sein.
Ich habe auch schon ein Programm geschrieben mit dem ich eigentlich die
Low-Zeit einer Rechteck-Spannung in ms messe und die auf das LC-Display
ausgeben kann. Zum testen habe ich einen Frequenz-Generator an den
Atmega16 angeschlossen, der mir eine 5V Rechteck-Spannung generiert.
Jetzt zu meinem Problem. Egal welche Frequenz ich auf den Eingang gebe
zeigt mir das Display irgendwelchen Murks an. Die Zahlen auf dem
LC-Display schwanken unregelmäßig von ca. 550 – 1050. Eigentlich sollte
auf dem LC-Display bei einer Frequenz von 1Hz ja 500 zu lesen sein, da
ich ja nur das Low-Signal Messe. Berechne derzeit noch nicht die U/min,
sondern lasse die Zeit des Low-Signal anzeigen.
Bei 10 Hz zeigt mir das Display 60-105 an.
Bei 100Hz zeigt mir das Display 7-13 an.
Nutze derzeit noch die 1MHz des internen Quarzes.
Woran kann das liegen?
Ist die Lösung eigentlich für eine Frequenz von 16,6 Hz - 116,6 Hz
geeignet?
Der interne RC-Generator (intere Quarze gibts so nicht) ist nicht sehr
genau, kann man aber kalibrieren. Drehzahlmessungen brauchen aber eine
recht genaue Zeitbasis. Per Polling wird se nicht ordentlich
Funktionieren da ja der Zeitpunkt des Messbegins und Endes nicht exakt
zur Flanke des Signals kommen, daher die schwankendem Messwerte. Besser
mit dem Inputcapture des Timers oder Interruptgesteuerter Abfrage
arbeiten.
Daniel wrote:
> Auto bauen. Es sollte eine Drehzahl von ca. 1000 – 7000 U/min gemessen> werden können. Das entspricht einer Frequenz von 16,6 Hz - 116,6 Hz.
Das ist rechnerisch richtig.
Physikalisch kann je nach Messprinzip in deinem Auto eine andere
Frequenz an deinem Drehzahlsensor anliegen. Wenn du nicht direkt dir
Kurbelwellenumdrehungen misst, sondern die Zündimpulse, kommt es u.a.
auf Zylinderzahl und Motorprinzip (Viertakt/Zweitakt) an.
Ich messe mit einem Initiator die Umdrehungen an der Riemenscheibe, die
direkt auf der Kurbelwelle sitzt. Das erschien mir am sinnvollsten.
Zündimpulse hat mein Diesel nicht. Des weiteren währe mir das zu
Riskant, da ich mir nicht sicher bin, wie der Atmega und die Beschaltung
auf die elektromagnetischen Einflüsse durch die Induktion an den
Zündspulen / Zündkerze reagiert.
Hab ich das richtig verstanden: Du misst die Zeit, in der der Sensor ein
low-Pegel ausgibt?
Üblicher ist Vorgehensweise, bei der Impulse gezählt werden. D.h. dass
du enweder über Polling überprüfst, ob ein Pegelwechsel (z.B. von low
nach high) stattgefunden hat und addierst die Wechsel. Das ganze machst
du über eine gewisse Zeit (Timer) und errechnest dir daraus die
Frequenz. Eine weitere Möglichkeit wäre einen Timer nicht per Quarztakt,
sondern mit einem extern angeschlossenen Takt (deinem Sensor) hochzählen
zu lassen. Danach wieder die Frequenz mit der verstrichenen Zeit
berechnen.
Der Nachteil: Du brauchst mehrere Umdrehungen für die Frquenzberechnung.
Das wird dir fürs Auto wohl zu langsam sein.
Ansonsten: Bleib bei deiner Methode und arbeite mit einem externen
Interrupt.
-> von low nach high -> Timer start, beim nächsten low nach high ->
Timer stop. Im Timer hast du dann deine Zeit.
Wenn du nur die Low-Zeit misst, weißt du die Frequenz ja nicht. Die
High-Zeit spielt da auch mit rein.
> Der interne RC-Generator (intere Quarze gibts so nicht)> ist nicht sehr genau, kann man aber kalibrieren.
Das betrifft eher die absolute Genauigkeit und die
Temperaturabhängigkeit. Im Kurzzeitbereich (Minuten) kann die Frequenz
als konstant angesehen werden. D.h. evtl. wird ein falscher Wert
angezeigt, aber der ist dann konstant.
> Eigentlich sollte auf dem LC-Display bei einer Frequenz von 1Hz> ja 500 zu lesen sein, da ich ja nur das Low-Signal Messe.
Wie sieht denn dein Signal aus?
Hast du wirklich ein Tastverhältnis von 50%?
Üblicherweise wird die Frequenz eines Signals von z.B. der steigenden
Flanke zur nächsten steigenden Flanke gemessen.
Bei meinem Frequenzgenerator habe ich eine Tastverhältnis von 50%, also
bei 1 Hz 500ms high dann 500ms low. Ich wollte so erstmal Testweise die
Low-Zeit messen, da ich später in der Realität bei 1 Hz ca 25ms ein
High-Signal habe und dann 975ms ein Low-Signal.
Ob ich jetzt die gesamte Periode oder nur das Low-Signal messe, geht es
mir erstmal ja gar nicht. Ich Frage mich, warum die Werte auf dem
Display so stark von den errechneten abweichen. Mit einigen % Abweichung
habe ich ja gerechnet und währen ja auch verkraftbar aber teilweise über
50% ist schon etwas seltsam, wie ich finde. Ich sehe da auch kein System
hinter. Der Zahlenwirwar gleicht eher Zufallszahlen die ausgegeben
werden.
Habe ich in dem Quelltext, den ich oben gepostet habe irgendwo doch
einen Fehler drin? Wüsste zumindest nicht wo.
Währe euch sehr verbunden da mal einen Blick rein zu werfen.
Wahrscheinlich braucht die Ausgabe auf dem Display recht lange, locker
einige zig Millisekunden. Die erste Abfrageschleife kannst Du auch aus
der Endlosschleife rausziehen.
Am besten wäre wirklich eine Interrupt-gesteuerte Auswertung. Dann
könntest im Interrupt die Zeit abspeichern und in der Hauptschleife neu
gemessene Werte ausgeben.
Gruß,
Roland
Der Code sieht eigentlich ok aus. Kreativ, aber lebensfähig.
> Bei 10 Hz zeigt mir das Display 60-105 an.> Bei 100Hz zeigt mir das Display 7-13 an.
Schon recht eigenartig, du kommst nicht mal annähernd in den Bereich,
der zu erwarten wäre... 10 Hz -> 50ms low, 50ms high. Die Verwaltung
der Schleife braucht auch noch Zeit, so dass ausschliesslich Werte unter
50 herauskommen müssten.
Wie sieht denn jetzt dein Signal aus:
Signalgenerator mit 0V/5V Rechteck und 50% Tastverhältnis?
Das hast du mit einem Oszi gemessen?
Oder glaubst du das nur?
Versuch doch mal den umgekehrten Weg:
Gib ein Signal an einen uC-Pin aus, und miss nach, ob das jittert.
Also nur z.B.
1
// angenommen am Pin D0 hängt eine LED
2
main{
3
DDRD=1;
4
while(1){
5
PORTD=1;
6
_delay_ms(1000);
7
PORTD=0;
8
_delay_ms(1000);
9
}
10
}
Das kannst du schon alleine mit dem Auge und einer Uhr kontrollieren.
Mit kleineren Verzögerungszeiten ist ein Oszi besser.