Forum: Mikrocontroller und Digitale Elektronik Drehzahlmessung (Hallsensor)


von Mc A. (mc_avr)


Angehängte Dateien:

Lesenswert?

Guten Tag,

ich beschäftige mich zur Zeit mit der Drehzahlerfassung eines kleinen 
Gleichstrommotors. Ich habe eben meine ersten Versuche gemacht und habe 
auch Ergebnisse und möchte meine Vorgehensweise hier mal erläutern um 
eventuelle Fehler deutlich zu machen und Ratschläge von euch zu hören.


Der Versuchsaufbau:
Als Tachogenerator dient ein Hallsensor vom Typ TLE4905, welcher immer 
beim Erfassen des Magnetfeldes den Signal-Ausgang Q auf Low schaltet. 
Der Signal-Ausgang ist mit dem ICP1 (PB0) vom Atmega8 verbunden. Der 
Atmega8 ist über die Serielle Schnittstelle mit dem PC verbunden um die 
Daten am PC darzustellen. Der Atmega8 wird mit einem externen Takt von 
11.05920Mhz betrieben. Die Versorgungsspannung für den Atmega8 und dem 
Hallsensor beträgt c.a. 5.27V.

Vorgehensweise der Drehzahlerfassung:
Der ICP1 vom Atmega8 ist so eingestellt, dass dieser auf fallende 
Flanken reagiert. Der Frequenz-Vorteiler ist 1024 und somit ergibt sich 
eine Taktfrequenz der Zähler: Fz=11059200/1024=10800 bzw. eine 
Taktperiode von: Tz=1/10800=92,5926µs. Sobald der Magnet am Hallsensor 
vorbei läuft (erste fallende Flanke) fängt der Timer TCNT1 mit dem 
Initialwert 0 an zu zählen und hört bei der zweiten fallenden Flanke auf 
und der Zählwert ICR1 wird in die Variable "zaehlstand" zwischen 
gespeichert. Bei der dritten fallenden Flanke wird der Zählwert über 
UART zum PC geschickt und die Variable "calc" wird auf 0 gesetzt, damit 
wieder eine Drehzahlerfassung statt finden kann.


Vor dem Versuchsaufbau habe ich versucht die Drehzahl des Motors mit 
Hilfe meines Multimeters zu ermitteln, da dieser einen Frequenzmesser 
und eine RPM Anzeige hat. Also habe
ich einfach den Ausgang Q des Hallsensors mit dem Multimeter verbunden 
und habe bei vollem Anschlag des Stelltrafos (c.a. 14-15V Ankerspannung 
am GSM)  eine Frequenz von 90-91Hz gemessen. Der RPM Wert ist dann 
dementsprechend nach RPM = f*60 = c.a. 5400. Nun habe ich einen 
Referenzwert.

Jetzt habe ich die Messung mit dem Atmega8 durchgeführt und habe über 
UART bei voller Ankerspannung einen Zählwert von 119-120 erhalten. Da 
die Zählperiode des Zählers 92.5926µs entspricht ergibt für die 119 
Schritte eine Gesamtzeit von: T_1Umdrehung=119*92.5926µs=11.0185ms. Der 
RPM Wert beträgt dann demnach: RPM = 60/T_1Umdrehung=60/11.0185ms=5445.
Dieser Wert weicht etwas dem Wert vom Multimeter ab.


Anmerkung: In der Interrupt Routine befindet sich deshalb eine 
Endlosschleife, da ich erstmals nur einen einzigen Wert ausgeben wollte, 
quasi wie ein "ScreenShot". Dazu wurde der Gleichstrommotor angeschaltet 
um das Tacho-Signal zu generieren und zusätzlich lief das Terminal 
(HTerm) Programm. Um jetzt einen einzigen Wert zu erhalten, wird der 
Atmega8 mit avrdude (Programmiergerät: USBASP) einfach resetted. Das ist 
natürlich nur eine provisorische Lösung.

Das Programm ist in C geschrieben und befindet sich im Anhang.

Ich bin für jeden Tipp sehr dankbar.

Mit freundlichem Gruß,
MC_AVR

von Jan B. (manax)


Lesenswert?

Hallo McAvr

Ich habe bereits auf dem Attiny2313 eine Zündung realisiert ( die misst 
ja auch die Drehzahl).
Daher kann ich dir eventuell etwas weiterhelfen.
Also dein Code ist ehrlich gesagt nicht so was ware finde ich.
Warum denn nur ein Interrupt ?
Durch das wählen deines Vorteilers bekommst du relativ ungenaue 
Ergebnisse finde ich.
Ich hab jetzt nicht nachgeschaut aber hat dein MCU keinen 16 bit Timer 
den du etwas höher laufen lassen kannst ? Ich zumindest mache das so.

Zu deiner Interrupt Routine.
So würde ich das nicht machen.
Du gehst rein in die Interrupt routine prüfst auf calc==1 Warum?
Ob der Timer läuft bekommst du doch ganz einfach über deine Register 
raus.
Danach würde ich grundsätzlich raus aus der Interruptroutine.
Du kannst deine beiden Umdrehungen auch einfach in Variable speichern ( 
ich empfehle 16-bit)  rpm.old und rpm.new
Prüfst mit einem einfachen if ob rpm.old != 0 ist und speicherst dann 
rpm.new
also sowas hier

if ( rpm.neu != 0 )
{
rpm.old = rpm.neu;
calc=1;
}
rpm.neu = TCNT1;

Jetzt einfach in der Mainschleife calc abfragen wenn es 1 ist kannste 
verschicken. Sachen über Uart würde ich nie aus einer Interruptschleife 
heraus schicken.

while schleife in main


if ( calc == 1)
{
calc=0;
hier deine Uarts
hier setzt du beide rpm variable zurück
}

Bei Hallgebern kenne ich das übrigens so das sie an einer Lücke in 
irgendeinem Rad vorbeilaufen und nicht an einem Magneten.


mfg Jan

p.s. wenn du noch Probleme hast schick mir einfach ne PM
Ich hab jetzt einfach mal geschrieben was mir so eingefallen ist weil du 
gar nicht gesagt hast wo dein Problem überhaupt liegt ;)

von MC_AVR (Gast)


Lesenswert?

Moinsen Jan !

Danke für die Tipps. Ich werde meinen Code nochmals überarbeiten und 
werde mich ggf. nochmal melden.

Es kam mir sogar selbst etwas komisch vor, dass ich aus der Interrupt 
Routine mit UART was sende ;-). Ich wollte einfach mal erste 
Versuchsergebnisse...


MfG,

MC_AVR

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.