einfache Drehzahlmessung mit ATmega88

Gast #2336456
Lesenswert?

Anbei eine Schaltung und ein Programm für einen einfachen 
Drehzahlmesser. Das Programm wurde unter AVR-Studio 4.18 entwickelt. Zum 
Einrichten eines eigenen Projektes reicht die angehängte .c-Datei sowie 
die Einstellungen  F_CPU = 2000000 sowie CPU = ATmega88. Die 'fuses' 
werden für max. ext. Quarz gewählt und BOD auf 4,3V gesetzt.

Die Schaltung ist einfach: sie besteht aus einem ATmega88, einer 
LC-Anzeige 2x16 und wenigen passiven Bauteilen besteht.
Das Programm ist einfach: eine einzige .c-Datei, die mit den 
Grundeinstellungen des AVR-Studio übersetzt wird.

Das Programm:
Gemessen wird im Grunde die Eingangsfrequenz; angezeigt werden Drehzahl 
("D") und Zeit_pro_Umdrehung ("T") als 6-stellige Werte (gerundet). Die 
Berechnungen werden mit den 'float'-Routinen des AVR-GCC durchgeführt; 
das Programm benötigt ca. 5,4KB Programmspeicher.
Gemessen wird lückenlos - jede Sekunde ein neuer Wert bei 60 rpm - und 
angezeigt werden maximal drei Ergebnisse/s; eine LED signalisiert eine 
fertige Messung.

Zur Schaltung:
Der Prozessor ist mit der Anzeige gemäß Schaltbild verdrahtet; die 
Pinbelegung ist 'historisch' gewachsen (beruht auf einem abgemagerten 
Frequenzzähler).
Das Eingangssignal wird über den analogen Komparator dem ICP des Timer1 
zugeführt. Das hat den Vorteil, dass die Eingangsbeschaltung variabel 
ausgelegt und bei Bedarf die Eingangsempfindlichkeit auf einige 10mV 
erhöht werden kann. So lassen sich z.B. R4 und C3 als Widerstände 2M2 
bestücken und D1 gegen einen Kondensator 100nF austauschen, wenn sehr 
kleine Drehzahlen nicht erwartet werden.

An anderer Stelle befindet sich noch ein Vorschlag für eine 
Eingangsstufe, mit denen man auch unsaubere Eingangssignale für die 
Drehzahlmessung aufbereiten kann. 
Beitrag "Eingangsstufe für Frequenzzähler DC-50MHz, +5V"
Angehängte Dateien:
Gast #2339852
Lesenswert?

Hallo,
folgender codeausschnitt verstehe ich nicht ganz:
1
  for(;;) {
2
    if(mess_status==MESSEN  && mess_dauer >= MESSZEIT) {
3
      mess_status=AUSLESEN;      // Auswertung starten
4
      mess_dauer = 0;        // wieder Messzeit abwarten
5
    }
6
    if(mess_status==AUSWERTEN) {
7
      end_zeit = zeit_high*0x10000 + zeit_low;
8
      mess_zeit = end_zeit - start_zeit;        // Zeit-Differenz bilden
9
      start_zeit = end_zeit;    // neue startzeit merken
10
      mess_ereignisse = end_ereignis - start_ereignis;  // Impuls-Differenz
11
    start_ereignis = end_ereignis;// fuers naechste Intervall
12
      mess_status = MESSEN;      // wieder warten
13
      if(messwert_vorhanden) {
14
    led_cnt = LED_EIN;      // LED-Zeit vorgeben
15
    frequenz = ((float)mess_ereignisse * F_CLOCK) / mess_zeit;  // Frequenz berechnen
16
    lcd_cmd(ZEILE1+5);      // 1.Zeile, 5.Spalte
17
    zeige_x(frequenz,0);    // Drehzahl anzeigen
18
    lcd_cmd(ZEILE2+5);      // 2.Zeile, 5.Spalte
19
    zeige_x(frequenz,1);    // Zeit/Umdr. anzeigen
20
      }
21
      else messwert_vorhanden = 1;  // sperre wieder aufheben
22
  }
23
  }
24
  return(815);
25
}
26

27
    lcd_cmd(ZEILE1+5);      // 1.Zeile, 5.Spalte
28
    zeige_x(frequenz,0);    // Drehzahl anzeigen
29
    lcd_cmd(ZEILE2+5);      // 2.Zeile, 5.Spalte
30
    zeige_x(frequenz,1);    // Zeit/Umdr. anzeigen

gibst du damit nicht auf beiden Zeilen das selbe aus?

mfg
Lukas
Gast #2339946
Lesenswert?

Lukas schrieb:
> gibst du damit nicht auf beiden Zeilen das selbe aus?

Sieh Dir bitte weiter oben an:
"void zeige_x(float x,char zeige_periode)"

Bei 'zeige_x(frequenz,0)' wird die Drehzahl (ursprünglich die Frequenz) 
und anderfalls die Periodendauer angezeigt.
Das obige Foto entstand bei ca. 1,2kHz Eingangsfrequenz; einmal x*60 
skaliert und in der 2. Zeile mit 1/x.
Gast #2349664
Lesenswert?

Vielleicht ist es niemandem aufgefallen und es wird äußerst selten zu 
'unsauberer' Auswertung führen, aber nachfolgender Programmabschnitt 
sollte vor einem T1OV-Interrupt geschützt werden. 'mess_dauer' kann 
sonst falsch gelesen oder gelöscht werden.
Die Sperre für TOIE1 habe ich hier ergänzt:

TIMSK1 &= ~(1<<TOIE1);           // t1OV interrupt sperren
    if(mess_status==MESSEN  && mess_dauer >= MESSZEIT) {
      mess_status=AUSLESEN;      // Auswertung starten
      mess_dauer = 0;            // wieder Messzeit abwarten
    }
TIMSK1 |= (1<<TOIE1);            // t1OV interrupt freigeben
Gast #2386711
Lesenswert?

Als Hallsensor sollte ein TLE4905 direkt anschließbar sein. R4 ist der 
Pullup für den OC-Ausgang.

Bei einem Reedkontakt würde ich in Reihe zum Kontakt 1k legen und C3 
soweit vergrößeren, dass bei max. Schaltfolge die Signalamplitude an 
AIN0 maximal 1,5V unter- und minimal 3,5V überschreitet. Als 
experimentellen Startwert würde ich mit 10nF beginnen, was grob einer 
Eingangsfrequenz von 10kHz entsprechen würde. Das Tastverhältnis ist 
aber zu berücksichtigen.
Der 1k Widerstand schützt den Reedkontakt vor zu großen Entladeströmen.

Wenn kein Schmutz auftreten kann, kann man auch mit Reflexkopplern 
arbeiten. Ein bißchen Alufolie auf dem Drehteil erzeugt kaum Unwucht.
Gast #2389748
Lesenswert?

Das Programm zu portieren sollte kein Problem sein. ICP als Eingang ist 
auch in Ordnung.
Was den Webserver angeht: den kenne ich nicht. Dazu muß man wissen, 
welche Timer, I/O und Interrupts dort verwendet werden und ob dies mit 
der Drehzahlmessung kollidiert.

Für ein Einzelstück würde ich der Drehzahlmessung einen eigenen 
Prozessor spendieren und die Meßwerte per UART an den Webserver 
übertragen. Da stören sich die Programme nicht und man ist auf der 
sicheren Seite.
Gast #2895576
Lesenswert?

Hallo Leute.
Ich komme hier wirklich nicht weiter und nach langem Überlegen habe mich 
doch entschlossen kein Internet Forschung mehr in diesem Fall zu 
betreiben.
Vielleicht hilft mir hier jemand der "sich besser auskennt".
Ich versuche die möglichst Übersichtig mein Problem zu erklären :

Ich versuche seit tagen die Messung an ein ATmega8 und mein Display 
anzupassen und habe bis jetzt folgendes geändert:

-TMSK1 in TMSK unbenannt - da an ATmega 8- so steht bei Atmel
-lcd_routines.c mit meiner LCD Konfiguration eingebunden - die sind ok.
- im Code folgendes unbenannt:
--int_lcd in lcd_init von lcd_routnes
--lcd_f_str in lcd_string von lcd_routines.

An der Schaltung hängt ein Lüfter- das Schwarze Tachokabel an PD6 ( 
(AIN0) .Ich bekomme jetzt nur D: und T: auf dem Display angezeigt. Keine 
000 keine ??? - überhaupt kein Wert,
Ich gehe davon aus dass noch was in der LCD Einbindung verändert werden 
muss.
Das Programm lässt sich fehlerfrei und Warnungsfrei kompilieren.

Kann mir da bitte jemand bei der Einbuindung von lcd_routines ein Tipp 
geben ?
Gast #2895581
Lesenswert?

>-lcd_routines.c mit meiner LCD Konfiguration eingebunden - die sind ok.
Beweise? Quellcode?

Du hast lcd_zeichen vergessen.
Wird aber alles nicht ändern.
Wenn ich den Code beim überfliegen richtig verstanden habe
erscheinen erst dann zahlen auf dem display wenn die
Messung erfolgreich war (genauer gesagt nach der 2).
Da aber D: und T: bei dir angezeit wird vermute ich mal
das entweder
- Kein Brauchbares signal ankommt
oder
- Die Ansteuerung des Timers beim M8 nicht komatibel zum m88 ist

> An der Schaltung hängt ein Lüfter- das Schwarze Tachokabel

Ich würd eher sagen Gelb....
Gast #2895705
Lesenswert?

Wenn "D: " und "T: " angezeigt werden, funktioniert die LCD-Ansteuerung.
Wenn ein Signal anliegt, muß die LED bei jeder fertigen Messung 0,1s 
aufleuchten. Falls das nicht passiert, ist das Signal nicht erkannt 
worden.

Kontrolliere bitte, ob die T1-Interrupts überhaupt arbeiten. Zunächst 
muß der OVF-Interrupt funktionieren: LED in der Routine blinken lassen.
Als Nächstes die LED in der CAPT-Routine blinken lassen.
Wenn beide Interrupts funktionieren, müßte auch die Anzeige der 
Messwerte klappen.

Noch etwas: ist SEI() wirksam, oder ist irgendwo ein CLI() vorhanden, 
was alle Interrupts wieder sperrt?

Jan schrieb:
> An der Schaltung hängt ein Lüfter- das Schwarze Tachokabel an PD6 (
> (AIN0)

Kontrolliere mit einer LED, ob hier überhaupt Impulse vorhanden sind.
Gast #3036580
Lesenswert?

m.n. schrieb:
> Vielleicht ist es niemandem aufgefallen und es wird äußerst selten zu
> 'unsauberer' Auswertung führen, aber nachfolgender Programmabschnitt
> sollte vor einem T1OV-Interrupt geschützt werden. 'mess_dauer' kann
> sonst falsch gelesen oder gelöscht werden.
> Die Sperre für TOIE1 habe ich hier ergänzt:
>
> TIMSK1 &= ~(1<<TOIE1);           // t1OV interrupt sperren
>     if(mess_status==MESSEN  && mess_dauer >= MESSZEIT) {
>       mess_status=AUSLESEN;      // Auswertung starten
>       mess_dauer = 0;            // wieder Messzeit abwarten
>     }
> TIMSK1 |= (1<<TOIE1);            // t1OV interrupt freigeben


Wenn ich das richtig verstanden habe muss es dann so wie angehängt 
aussehen.
Gruß Andreas
Angehängte Dateien:
#3274604
Lesenswert?

Hallo Leute,

da ich mal auf die Schnelle einen Drehzahlmesser brauchte, habe ich mal 
fix ein 1-seitiges Layout gemacht. Nix schönes und ohne ISP. Das LCD 
passt direkt oben drauf. Vielleicht kann es ja jemand brauchen.
Die Beleuchtung des LCD ist nicht vorgesehen, da ich es für 
Batteriebetrieb vorgesehen hatte.

Gruß

Stephan
Angehängte Dateien:
#3318601
Lesenswert?

m.n. schrieb:
> Eine neue Programmversion mit automatischen Abgleich auf ein
> 1Hz-Referenzsignal - am besten von einem GPS-Empfänger - ist fertig.
>
> Damit kann man den oben gezeigten Aufbau von Stephan Henning recht
> einfach abgleichen. Eine kurze Beschreibung dazu sowie .c-Quellcode und
> .hex-Datei sind hier zu finden.
> http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp3

theoretisch schon. Praktisch schwierig.
Ich habe die Eingangsbeschaltung nicht veröffentlicht.

Als Eingang habe ich die vom Sprut veröffentlichte genommen.
Fototranse mit OPV (Modellbaudrehzahlmesser)
Nein die ist nicht auf dem Bild zu sehen. das war was anderes,
was ich da vorn dran hatte.

Gruß

Stephan

funktioniert übrigens gut. Nur die Anzeige ist mir etwas zu hektisch
und macht zu größe Sprünge, was sich aber auf Grund des Prinzips
nicht viel ändern lassen wird. Möglich wäre eine gleitende 
Mittelwertbildung zB. Wert neu = Wert alt *3 / Wert neu. Was allerdings 
unweigerlich zu einer deutlich trägeren Anzeige führen würde, wenn sich 
Wert alt und wert neu langsam annähern.

Es ist eben nichts perfekt. So wie wir Menschen.  :-)
Gast #3323158
Lesenswert?

Stephan Henning schrieb:
> m.n. schrieb:
>> Eine neue Programmversion mit automatischen Abgleich auf ein
>> 1Hz-Referenzsignal - am besten von einem GPS-Empfänger - ist fertig.
>>
>> Damit kann man den oben gezeigten Aufbau von Stephan Henning recht
>> einfach abgleichen. Eine kurze Beschreibung dazu sowie .c-Quellcode und
>> .hex-Datei sind hier zu finden.
>> http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp3
>
> theoretisch schon. Praktisch schwierig.

Ich weiß jetzt nicht, worauf sich das "schwierig" bezieht.
Den 'Fangbereich' für den auto. Abgleich habe ich von +/-100ppm auf 
+/-1000ppm erweitert, obwohl die nun mögliche Toleranz für mich schon 
grenzwertig ist.
Unter Umständen sollte C3 bei einem GPS-Signal unbestückt sein oder R4 
verkleinert werden, falls der 1pps-Impuls nur 1µs lang ist.
#3327908
Lesenswert?

Stephan Henning schrieb:
> theoretisch schon. Praktisch schwierig.

m.n. schrieb:

> Ich weiß jetzt nicht, worauf sich das "schwierig" bezieht.

Hallo Michael,

das bezog sich lediglich auf die Eingansbeschaltung welche ich nicht 
dargestellt hatte. Das optische Eingansteil vom Sprut.
Welche für den Abgleichzweck aber völlig uninteresant ist.
Sorry, hatte einen Knoten im Hirn.

Außerdem sind ja in der BRD Datei keine Werte enthalten.
Es ging ja bei dem Post lediglich um die mögliche Nutzung des Layouts, 
da ich es ja eh machen musste.

Bleib ganz ruhig, alles gut.

Gruß

Stephan
Gast #3327998
Lesenswert?

Stephan Henning schrieb:
> Bleib ganz ruhig, alles gut.

Na ja, dass die Istfrequenz von Quarzen in manchen Fällen zu stark 
streut, ist mir schon zu Ohren gekommen. Deshalb wollte ich ein bißchen 
mehr Nachbausicherheit einbringen.

Ferner ist mir bei der Anpassung eines Frequenzzähler-Programms auf 
einen Arduino UNO R3, eine Abweicheng des 16MHz Quarzes von >500ppm 
aufgefallen. Das ist schon heftig und wohl die Folge von "Geiz ist ...".
#3328137
Lesenswert?

Michael,

ich denke Du machst Dir zu viele unnötige Sorgen. Wenn es hier deutliche 
Probleme geben würde, hättest Du schon was davon gelesen, bzw. über 
Deine eigene Homepage ein Feedback bekommen. Dein(e) Schaltung /Programm 
erhebt ja auch nicht den Status eines Präzisionsmessers.

Das wird erst interessant wenn sich der Peter Danneger melet.

Also bleib entspannt.

Ein Arduino UNO R3 kann ja wohl nicht das Maß der Dinge sein.
Ist das Ding überhaupt Echtzeifähig ?
Kann doch bei USB Interface eigentlich nicht sein, denke ich.
Ich habe keines.

Gruß

Stephan
#5300346
Lesenswert?

Hallo alle

Ich habe die Drehzahl-Schaltung gebaut (mit externem 20MHz Quarz). Ich 
verwende am Eingang einen wie im thread besprochenen Hallsensor Typ 
TLE4905. Der Prozessor erkennt die Impulse (Led), die ich mit einem 
Magneten am Sensor gebe.
Jedoch scheint die angezeigte Frequenz und damit auch die Zeit nicht zu 
stimmen. Es zeigt mit eine deutlich zu hohe Drehzahl an, wenn ich z.B. 
im Sekundentakt den Hallsensor ansteuere.
Ich vermute, dass meine Prozessor-Clock nicht stimmt. Ich habe den 
Atmega88 mit folgenden Fuses programmiert:

Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 258 CK/14 CK + 
65ms; (CKSEL0110 SUT=01)
Brown-out detection level at VCC=4.3V

ergibt:
Low: 0x56; High: 0xDC; Extended: 0xF9
Gast #5301164
Lesenswert?

Das hatte ich schon vermutet. Mit der letzten Version wäre das Problem 
nicht entstanden.

m.n. schrieb:
> Eine neue Programmversion mit automatischen Abgleich auf ein
> 1Hz-Referenzsignal - am besten von einem GPS-Empfänger - ist fertig.
>
> Damit kann man den oben gezeigten Aufbau von Stephan Henning recht
> einfach abgleichen. Eine kurze Beschreibung dazu sowie .c-Quellcode und
> .hex-Datei sind hier zu finden.
> http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp3

In der 1. Zeile von main() steht dort:
  CLKPR = 0x80; CLKPR = 0x0;
Damit wird der interne Vorteiler immer auf 1 gestellt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren