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
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 ;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.