Hallo Zusammen Ich will eine Frequenz mit einem ATtiny85 messen. Der Messeingang ist PB4. Das INT0 Interrupt soll dann einen Timer starten, und so die Frequenz ermitteln. Nun funktioniert nicht einmal das INT0, das interrupt wird dauernd ausgelöst, sollte aber nur, wen sich PB4 ändert. Hier ein kleines Testprogramm in Bascom: $regfile = "attiny85.dat" $crystal = 8000000 Open "comb.2:1200,8,n,1" For Output As #1 Print #1 , "Start" Enable Interrupts Enable Int0 On Int0 Frequenz_messung Config Portb.4 = Input Gimsk = &B01100000 Pcmsk = &B00010000 Mcucr = &B00000001 Do 'Hauptprogramm Print #1 , "warte..." Waitms 1000 Loop End Frequenz_messung: Gifr = &B01100000 Print #1 , "INT0" Return
Im Interrupt eine Ausgabe auf die Seriell zu machen dauert zu lang, bei 1200 Baud/s dauert dein "Int0" ca 4,2ms! Inzwischen ist sícher die nächste Änderung am Int0 passiert. Wie willst du da Signale schneller als vielleicht 100 Hz messen? Besser macht man das so mit einem AVR: Der AVR zählt eine bestimmte Zeit lang (Torzeit) die Änderungen auf dem Eingangspin, elegant lässt sich das z.B. mit dem Timerclockeingang (weiß grad nicht ob der tiny85 einen hat) erledigen. Nach der Torzeit kannst du den Frequenzwert an den PC übertragen und die nächste Messung starten.
Floh schrieb: > Besser macht man das so mit einem AVR: Der Tiny85 ist ein AVR. > Der AVR zählt eine bestimmte Zeit lang (Torzeit) Wenn schon, dann bitte eine reziproke Messung. Da reicht schon ein ATtiny2313.
M. N. schrieb: > Floh schrieb: >> Besser macht man das so mit einem AVR: > > Der Tiny85 ist ein AVR. > >> Der AVR zählt eine bestimmte Zeit lang (Torzeit) > > Wenn schon, dann bitte eine reziproke Messung. Da reicht schon ein > ATtiny2313. ....ich verneige mich vor dir !
M. N. schrieb: > Wenn schon, dann bitte eine reziproke Messung. Da reicht schon ein > ATtiny2313. 2,5x so groß ist 2,5x so gut oder ist wie ist das "Da reicht schon ein ATtiny2313" zu verstehen?
Das Interrupt sollte mit dem Befehl "Pcmsk = &B00010000" eigentlich nur auf PCINT4 ausgelöst werden. Und nicht am Standartpin PCINT0, oder sehe ich das falsch ? Die andere Möglichkeit, anzahl Pulse zählen wäre auch eine Variante. Ich will eine Frequenz zwischen 1Hz und 3KHz messen. Wie mache ich das am besten ? Wie gesagt, der AVR sollte ein tiny85 sein (aus Platz gründen), und der Messeingang darf nicht auf PB0 und PB2 liegen, da ich den I2C Bus ebenfalls brauche.
Der Tiny2313 ist für eine Frequenzmessung als reziprokzähler deutlich besser geeignet - der Tiny85 hat leider keine ICP Funktion, aber immerhin mehr Speicher. Mit dem Tiny85 hat man 2 Möglichkeiten: 1) klassich mit fester Torzeit und zählen der Perioden des Signals 2) als Reziprokzähler mit Interrupt als ICP Ersatz in Software Bei nur 8 Bit Timern und in Software wird die Genauigkeit beim Rezirokzähler nicht so besonders gut, und abhängig vom Aufwand den man treibt. An einigen Stellen wäre ASM statt C hilfreich/nötig um trotzdem eine sehr gute Auflösung zu erreichen. Trotzdem ist das Verfahren für niedriger Frequenzen noch die bessere Wahl. Die maximale mögliche Frequenz wird bei rund 100 kHz liegen, in ASM auch etwas mehr. Das klassische Verfahren ist einfacher, und für höhere Frequenzen geeignet, und in einem kleinen Bereich (so ab 50 kHz) ggf. auch genauer. Bei niedriger Frequenz fehlt einfach die Auflösung, oder die Torzeit müsste lang werden. Welcher weg passt hängt von der Frequenz, der benötigten Auflösung und Geschwindigkeit der Messung ab.
Das Projekt wird eine Drehzahlsensor für einen Datenlogger, um die Propellerdrehzahl im Modellbau zu messen. Mit 2 Pulsen pro Umdrehung (Zweiblattpropeller), und einer Torzeit von 0.5s, ergibt dies eine Auflösung von 60rpm, das wäre gerade noch akzeptabel. Besser wäre eine Messzeit von 0.1s und einer Auflösung von 10rpm. Bei sehr kleiner Drehzahl (100rpm), ist das natürlich nicht möglich, da wäre eine Messzeit von 1s allemal in Ordnung.
Michael L. schrieb: > Ich will eine Frequenz zwischen 1Hz und 3KHz messen. das ist ja nun keine Raketentechnik, ich würde einen Timer laufen lassen und per Interrupt die Flanken zählen und wenn 1 Sekunde um ist und die nächste Flanke kommt den Zählerstand nehmen, durch die Zahl der Perioden teilen und so eine Periode berechnen
So habe ich mir das auch überlegt... Nur wie Anfangs beschrieben, funktioniert die Interrupt Geschichte, der die Flanke auslösen soll, mit dem Pin PB4 nicht. Irgendwie wird trotz der Maskierung von INT0 auf PCINT4, der PCINT0 Pin ausgewertet. Und dort ist momentan zu Testzwecken die Serielle Schnittstelle, und später wird dort der I2C Bus sein.
Michael L. schrieb: > Irgendwie wird trotz der Maskierung von INT0 auf PCINT4, Was ist denn das für ein Unsinn ? Da kann nichts ummaskiert werden. Außerdem triggerst Du mit dem Soft-UART den INT0. Wie wär's mit ein paar Grundlagen ?
Das mit dem UART und INT0 habe ich auch gemerkt. Im Datenblatt auf Seite 54, im Register PCMSK – Pin Change Mask Register, sollte man das INT0 auf einen anderen PIN legen, oder habe ich da was falsch verstanden ?
Beim Propeller werden es eher keine 3 kHz, und wohl auch nicht runter bis 1 Hz gehen. Die Logische Wahl wäre da schon die Messung über eine Zeitmessung zwischen 2 gleichen Flanken, z.B. mit int0. Die Genauigkeit wird ggf. durch langsamere andere Interrupts gestört, aber die Anforderungen sind auch nicht so extem. Bei der Software UART muss man aber ggf. schon aufpassen, das die nicht zu lange Pausen verursacht. Zur Erweiterung der Auflösung der 8 Bit Timer gibt es 2 Möglichkeiten: Zählen der Überläufe in Software, oder man nutzt 2 Timer mit unterschiedlichem Vorteiler, etwa so das der eine Timer die 8 unteren Bits liefert, und der andere 7 zusätzliche - ohne 1 Bit als Überlapp ginge es ggf. mit einem sehr genauen Timing in ASM. Mit 15 oder 16 Bit Auflösung für die Zeit sollte man auskommen, denn die Genauigkeit ist ohnehin durch die nicht immer konstante Antwortzeit für den Interrupt begrenzt. Falls einem wieder Erwarten die Auflösung bei den höheren Frequenzen nicht reicht, ließe sich auch die Zeit für mehr als eine Periode messen.
Michael L. schrieb: > Wo zu dient den das PCMSK – Pin Change Mask Register ? Für eine ganze Reihe PCINT-Pins, meist ein ganzer Port, gibt's jeweils nur einen Interruptvektor, der dann eben entsprechend heißt, hier PCINT0. Jeder in PCMSK gesetzte Pin kann dann eben diesen Vektor triggern. Rauszubringen welcher es war, ist dann Dein Job. Der Vektor INT0 und PCINT0 sind aber zwei voneinander getrennte Sachen. Verwirrend mag sein, dass die Pinchange-Pins auch mit PCINTx bezeichnet werden, ähnlich dem Namen des eigentlichen Interruptvektors.
Michael L. schrieb: > Pin Change Mask > Register, sollte man das INT0 auf einen anderen PIN legen, oder habe ich > da was falsch verstanden ? pin change Interrupt heißt nicht dass da ein Pin gewechselt wird, sondern das ein Pegelwechsel an einem Pin einen Interrupt auslöst
Ja genau, wir sind uns einig, die Messung mit einem Interrupt zwischen zwei flanken wäre die richtige. Nun genau da ist mein Problem, das INT0 ist auf PB2, und dort ist zu Testzwecken der UART, später brauche ich den HW I2C der auf PB0 und PB2 liegt. Die Schnittstellen lösen aber immer das INT0 aus. Nun wollte ich das INT0 auf PB4 umleiten, aber irgendwie geht das mit dem PCMSK Register nicht.
So könnte es gehen, oder ? Enable Interrupts Enable Int0 On Int0 Frequenz_messung Config Portb.4 = Input Gimsk = &B01100000 Pcmsk = &B00010000 'PCINT4 Maskieren Mcucr = &B00000001 Do 'Hauptprogramm Loop End Frequenz_messung: if Gifr.5 = 1 then 'Prüfen ob PCINT4 das Interrupt ausgelöst hat Gifr = &B01100000 'PCINT4 reset Print #1 , "OK" end if Return
Michael L. schrieb: > So könnte es gehen, oder ? Nein. Vergleich die Interruptvektoren, bzw. was ich schrieb.
BerndB schrieb: > 2,5x so groß ist 2,5x so gut oder ist wie ist das "Da reicht schon ein > ATtiny2313" zu verstehen? Tut mir Leid, ich habe in Eile nur knapp formuliert. Auf den ATtiny2313 habe ich verwiesen, weil dieser zum einen einen 16-Bit Timer mit input-capture Funktion und zum anderen auch ein USART auf dem Chip hat. Da braucht man nicht viel zu tricksen, um eine gute Lösung zu bekommen. Als kleinere Lösung könnte man auch einen ATtiny461/861 nehmen. Der Beitrag, auf den ich ganz oben verwiesen habe, beschreibt ja auch schon eine reziproke Messung mit dem ATtiny45/85. Dass nur 4 Stellen angezeigt werden, liegt an der Grundschaltung mit 7-Segment LCD und daran, dass unbedingt 'float' vermieden werden sollte und die Berechnungen als uint32_t stattfinden. Beim ATtiny85 kann man getrost 'float' rechnen. Das Programm passt locker ins FLASH. Wie man das Ganze in BASIC formuliert, weiß ich allerdings nicht.
@MWS habs verstanden, so funktioniert nun die Interruptsache mit PCINT4: Enable Interrupts 'Interrupts einschalten Enable Pcint0 On Pcint0 Frequenz_messung Gimsk = &B00100000 Pcmsk = &B00010000 Do 'Hauptprogramm Print #1 , Drehzahl Drehzahl = 0 Waitms 500 Loop End Frequenz_messung: Incr Drehzahl Return
Nun habe ich noch ein anderes Problem. Die HW mit dem Fototransistor ist scheisse ! Wenn ich mit der Hand den Fototransistor auf- und abdecke, funktionierts einigermassen. Aber die Drehzahl eines Propellers damit messen, geht nicht ! Ich habe den 10k Widerstand von 0-100k verändert, und zwei Transistoren probiert, ohne erfolg.
Du tust Dir selber einen Gefallen, wenn Du das:
1 | Gimsk = &B00100000 |
2 | Pcmsk = &B00010000 |
so schreibst:
1 | Gimsk = Bits(PCIE) |
2 | Pcmsk = Bits(PCINT4) |
Michael L. schrieb: > Nun habe ich noch ein anderes Problem. Die HW mit dem Fototransistor ist > scheisse ! Bei veränderlicher Umgebungshelligkeit braucht Du irgendeine Regelung, um den Arbeitspunkt des Fototransistors jeweils darauf einzustellen. In Wirklichkeit hast Du keine Helligkeitsschwankungen Tag/Nacht.
Vielen Dank für die Info. Die Schaltung kenne ich. Habe den Datenlogger von d.meissner ebenfalls schon aufgebaut, mit dem Logger von d.meissner mit PIC funktionierts auch einwandfrei. nur wenn ich die Schaltung ohne PIC laufen lasse, und die Freuqenz mit dem Multimeter messen will, kommt nichts raus ?!?
Michael L. schrieb: > nur wenn ich die Schaltung ohne PIC laufen lasse, und die Freuqenz mit > dem Multimeter messen will, kommt nichts raus ?!? Die Schaltung dürfte Nadelimpulse erzeugen, mit denen ein MM überfordert sein könnte, ein µC jedoch durchaus klarkommt.
Also dann probier ich die Schaltung von Sprut an einem AVR aus. Spurt verwendet da 5V, ich habe aber nur 3.3V, sollte ich die Widerstände ändern, oder funktioniert das trotzdem ?
Michael L. schrieb: > Spurt verwendet da 5V, ich habe aber nur 3.3V, sollte ich die > Widerstände ändern, oder funktioniert das trotzdem ? Könnt' genauso mit 3,3V gehen, Widerstände würde ich so lassen.
Super !! Habe nun die Schaltung wie im Anhang aufgebaut, und die HW funktioniert einwandfrei !! Jetzt noch was anderes: Der PCINT4 erkennt ja nur wenn sich der Pegel ändert, und nicht ob eine steigende Flanke ansteht. Wenn sich das Propellerblatt am Fototransistor vorbei bewegt, wird das Interrupt zweimal aufgerufen. Ich will bis 80000rpm messen können, könnte dies zu Problemen führen, wenn der high Pegel nur sehr kurz ist ?
Die steigende Flanke erkennt man beim PCINT daran, dass der Pin beim Eintritt in die ISR High ist. Vorausgesetzt natürlich, der Puls dauert lang genug von Auslösung bis Pinabfrage. Ausgelöst wird die ISR natürlich trotzdem immer zweimal, nur verlässt man sie bei Low-Pegel sofort wieder. Michael L. schrieb: > wenn der high Pegel nur sehr kurz ist ? Auch das dürfte keine Schwierigkeit sein. Wie viele Takte ein Impuls mindestens dauern muss, um erkannt zu werden, ist im Datenblatt zu finden.
So habe an der SW weiter gearbeitet, das Resultat ist aber noch nicht in Ordnung. Wenn ich den Fototransistor zu einer Leuchtstofflampe mit 50Hz halte, ergibt dies ein Werte von ca. 77, Jedoch schwankt der Wert ziemlich stark (+/-10). Nun die Frage ob ich so auf dem richtigen Weg bin ? Oder gibt es SW-Technisch bessere Lösungen ? evtl ASM ? Config Timer1 = Timer , Prescale = 256 Enable Interrupts Enable Timer1 Enable Pcint0 On Pcint0 Frequenz_messung On Ovf1 Timer1ueberlauf Gimsk = &B00100000 Pcmsk = &B00010000 Do 'Hauptprogramm Print #1 , Drehzahl Waitms 500 Loop End Timer1ueberlauf: Incr Timer_ovf If Timer_ovf = 255 Then Drehzahl = 0 End If Return Frequenz_messung: Incr Pulse If Pulse = 1 Then Timer_ovf = 0 Timer1 = 0 Enable Timer1 End If If Pulse = 8 Then Disable Timer1 Drehzahl = Timer_ovf Shift Timer_ovf , Left , 8 Drehzahl = Drehzahl + Timer1 Pulse = 0 Timer_ovf = 0 Enable Timer1 End If Return
Hi, Michael L. schrieb: > Shift Timer_ovf , Left , 8 > Drehzahl = Drehzahl + Timer1 > Pulse = 0 > Timer_ovf = 0 Wozu ist die erste Zeile gut, wenn in der 4.Zeile Timer_ovf auf 0 gesetzt wird und dazwischen nix mit Timer_ovf gemacht wird?
Oh ja das sollte so heissen: Drehzahl = Timer_ovf Shift Drehzahl, Left , 8 Drehzahl = Drehzahl + Timer1 Pulse = 0 Timer_ovf = 0 Da ich nur einen 8bit timer habe, habe ich diesen per SW auf 16bit erweitert. Timer_ovf sind anzahl Überläufe von timer1.
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.