-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 17

Thema: Frequenzmessen

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    16.09.2008
    Ort
    Hamburg
    Beiträge
    49

    Frequenzmessen

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hi, ich weiß diese Thema wurde schon sehr oft durchgekaut, aber je mehr Beiträge und Tutorials ich lese desto mehr blick ich nicht mehr durch...
    Daher hoffe ich das ihr mir weiter Helfen könnt, ohne gleich ein würg-Reflex zu bekommen, wenn ihr den Titel lest.

    So nun zu meinen Anliegen.
    Ich möchte gerne eine Frequenz (Rechteck) zwischen 1Hz und ca 1khz messen. Als Controller hab ich den Atmega16 mir ausgesucht.
    Im Grunde soll das Programm so Funktionieren, das ab Frequenz X LED1 leuchtet, ab Frequenz Y LED2 usw. bis LED8 erreicht ist.

    Als erstes habe ich versucht eine LED zu Toggeln wenn der Counter überläuft (siehe Code) jedoch funktioniert das schon nicht...

    Code:
    'Frequenzmessen
    
    '---------------------------------
    'Deklaration
    '---------------------------------
    
    $regfile = "m16DEF.DAT"
    $crystal = 16000000
    
    
    '---------------------------------
    'Initialiserung:
    '---------------------------------
    
    Config Porta = Input
    Config Portb = Output
    Config Portc = Output
    
    Config Portd = Input
    Portd.6 = 1
    
     Dim Frequenz As Word                                       'Frequenz als Word festelegen
    
     Config Timer1 = Counter , Edge = Falling , Capture Edge = Falling , Noise Cancel = 1 , Prescale = 1       'Timer als Counter Festlegen
    
     Enable Int0                                                'Interrupt Aktivieren
     Enable Timer1                                              'Timer einschalten
    
     Enable Interrupts                                          ' Interrupts aktiv
     On Timer1 On_timer1
    
    
    '---------------------------------
    'Hauptprogramm:
    '---------------------------------
      Portb.7 = 1                                               'Kontroll LED
    
    
     Do
    
     Loop
    
     '---------------------------------
    'Interrupt
    '---------------------------------
     On_timer1:
     Toggle Portb.0
     Return
    
     End
    Und keine Angst ich möchte von keinem alles Vorgekaut haben, nur ein paar Tipps und Ideen auf die ich alleine nicht komme.

    Vielen Dank für eure Hilfe

    Mfg Tryan

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.554
    Dumm, dass Du nach Bascom fragst. Ich mache das so, dass ich das Signal (muss für einen Controller einen TTL-Pegel haben) auf den externen Interrupt lege, beispielsweise auf steigende Flanke triggern, und dann die Zeit bis zur nächsten steigenden Flanke messe. Alles Andere ist danach ja einfach . Beim M16 liegt der extInt0 glaub ich auf Pin16=PD2. Andere externe Interrupts sind dafür sicher auch geeignet - sieh mal im Datenblatt nach.

    Vielleicht hilft Dir das.
    Ciao sagt der JoeamBerg

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    16.09.2008
    Ort
    Hamburg
    Beiträge
    49
    @ oberallgeier
    Danke für die schnelle Hilfe-Stellung!
    Ich hab mich für Bascom entschieden, weil wir in der Schule eine kleine Einführung in das Programm hatten,
    sodass ich ein wenig Vorkenntnis habe (Drücke Taster1 = Leuchte LED1, naja ein wenig mehr ist es schon )

    Ich wollte zum Messen Portd.6 nehmen das ist der "ICP-Pin"
    Mit ihm sollte es am einfachsten gehen. Das mit dem Flanke zu Flanke messen ist eine sehr gut Idee.
    Also müsste ich Messen wieviele "Takte" zwischen Flanke1 und Flanke2 abgelaufen sind. Ist das so richtig?

    Mfg Tryan

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Takte zwischden den Flanken zu messen sollte bei den niedriegen Frequenzen das Beste sein. Bei nur 1 kHz Frequenz hat man reichlich Zeit, auch in Basic. Ich weiss nicht ob Bascom für die ICP Funktion eine extra Unterstützung hat, vermutlich nicht, aber es geht auch ohne. Ein Beispiel in C ist im Wiki-Bereich unter timer:
    http://www.roboternetz.de/wissen/index.php/Timer/Counter_(Avr)#Input_Capture

    Wenn man etwas sucht, vielleicht findet sich ja auch ein ICP Beispiel in Basic. Die Umsetzung von C nach Basic sollte ziehmlich 1:1 möglich sein. Allerdings sind Interrupts auch nicht gerade das einfachste und etwas compilerspezifisch.

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.554
    Hi Tryan, hallo Besserwessi,

    Tryan, meine Bemerkung mit "Dumm ... BASCOM" ... war natürlich von mir dumm ausgedrückt. Ich meinte damit blos, dass ich von Bascom nix verstehe. Ich hoffe nur, dass Du nichts anderes rausgehört hast.

    Die Frequenz von 1 Hz zu zählen mit den Takten des ICP kommt mir schwierig vor:
    Zitat Zitat von RN-Wissen
    Input Capture
    ... Die typische Anwendung ist die Messung von kurze Zeiten ...
    und weiter
    Zitat Zitat von RN-Wissen
    Input Capture
    ... Etwas komplizierter wird es wenn die 16 Bit Auflösung nicht mehr ausreicht ... wesentliche Schwierigkeit ... Fall ... berücksichtigen, dass ein Überlauf Interrupt und der ICP Interrrupt fast gleichzeitig ausgelöst werden ...
    Und dieses Nicht-Ausreichen bei etwas längeren Zeiten hatte mich abgeschreckt. Schliesslich zählst Du z.B. bei einem 4MHz-Quarz und einer Frequenz von 1 Hz bis 4 Millionen hoch . . . . . . Ich arbeite bevorzugt mit einem mega168 bei 20 MHz. Daher hatte ich mir für meine Zeitmessungen (in C) einen Timer geschrieben, der einen 50 µs-Interrupt auslöst und in der ISR eine Variable hochzählt. Die zeigt bei 20 000 eben genau eine Sekunde und kann bis über 60 000 gehen, da ich eine 16bit-unsigned-integer verwende. Ich kann also Zeiten bis über drei Sekunden ohne Überlaufprobleme messen. Diese Auflösung würde bei Deiner Einteilung der drei Größenordnungen 1 ... 1000 Hz doch reichen. Ich lese bei mir beim externen Interrupt die aktuelle Zeit aus. Du könntest so z.B. in der ISR des externen Interrupts die Variable in einen Wert für das Nicht-Interrupt-Modul sichern, danach die Zählvariable auf Null setzen und damit eine neue Zeitmessung starten. Im "Nicht-Interrupt-Modul" - also main oder einem Unterprogramm - wird dann der gesicherte Wert in eine Frequenz umgerechnet und die LED geschaltet. Sieh das bitte aber nur als Vorschlag, ich bin wirklich nicht firm im Frequenzmessen. (Anmerkung: der informative und praktische RN-Wissen-Abschnitt stammt ja von Besserwessi - ich habs nur gelesen ).
    Ciao sagt der JoeamBerg

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    16.09.2008
    Ort
    Hamburg
    Beiträge
    49
    @ oberallgeier
    Nein ist alles klar, hab mir schon so etwas gedacht

    Meine Ursprünglich Idee war es so zu arbeiten wie es hier beschrieben ist:
    http://avrhelp.mcselec.com/config_timer1.htm

    Also wenn die erste Flanke (von 0V auf 5V) aus dem ICP - PORTD.6 ankommt startet der Timer1/Counter1.
    Wenn die zweite Flanke (von 0V auf 5V) auf dem ICP - PORTD.6 ankommt stoppt der Timer1/Counter1.
    Somit würden ich jeden zweiten Takt messen.

    Der Zahlenwert der zwischen Flanke1 und Flanke2 aufgezählt wurde, wird gespeichert und so umgerechnet, sodass ich die Frequenz bekomme.

    D.H. je höher die Frequenz wird desto kleiner der Zahlenwert zwischen Flanke1 und Flanke2.

    Ist meine Idee im Grunde so in Ordnung? Oder ist da ein Denkfehler?

    Mfg Tryan

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    @tryan: Die Idee den Timer beim Interrupts zu starten ist durchausmöglich. Bei den eher kleinen Frequenzen geht das auch noch ganz gut, denn die mögliche Verzögerung beim Auslösen des Interrupts ist meistens unter 1 µs. Für höhere Frequenzen oder maximale Auflösung ist es aber besser das Starten auch über ICP zu machen. Sonst kann man den ICP Pin natürlich auch wie einen externen Interrupt nutzen.

    @oberallgeier: Die ICP Funktion ist zwar Hauptsächlich für kurze Zeiten wichtig, geht aber natürlich auch für längere Zeiten. Wenn man die hohe Auflösung nicht braucht kann man ja den Prescaler nehmen. Dann ist die Periodenmessung mit ICP wirklich sehr einfach. Wenn man erst mal weiss wie es geht, ist auch die Erweiterung der Auflösung auf 32 Bit kein Problem, dann sind selbst bei 20 MHz Timer-Takt Zeiten bis etwa 200s möglich.

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    16.09.2008
    Ort
    Hamburg
    Beiträge
    49
    Nabend, ich glaube ich bin ein wenig voran gekommen. Ich bin Soweit das ich die Pulse von der Frequenz anzeigen lassen kann.
    Das Programm sieht jetzt soweit aus:
    Code:
    'Frequenzmessen
    
    '---------------------------------
    'Deklaration
    '---------------------------------
    
    $regfile = "m16DEF.DAT"
    $crystal = 16000000
    
    
    '---------------------------------
    'Initialiserung:
    '---------------------------------
    
    Config Porta = Input
    Config Portb = Input
    Config Portc = Output
    Config Portd = Output
    
    
    Dim Pulse As Byte
    
    Enable Timer0                                     'Timer0 An
    Config Timer0 = Counter , Edge = Rising           'Config von Timer0
    
    On Ovf0 Tim0_isr                                  'Interrupt bei Overflow AN
    
    Enable Interrupts                                 'Interrupts An
    
    Tcnt0 = 0                                         'TCNT0 auf Null gesetzt
    
    '---------------------------------
    'Hauptprogramm:
    '---------------------------------
    Do
    Portd = Tcnt0                                     'Ausgabe von TCNT0 an PortD
    
    Loop
    
    '---------------------------------
    'Interrupt
    '---------------------------------
    Tim0_isr:
    Pulse = Tcnt0
    Timer0 = 0                                        'Timer0 wird zurückgesetzt
    Return
     End
    Das Problem an dem ich jetzt hänge ist das ich die Pulse nur ein Zeit X messen darf und dann müsste eigentlich ich mit einer kleinen Rechnung wissen was für eine Frequenz anliegt.

    Habt ihr ein Tipp für mich?

    lg TRyan

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.01.2007
    Ort
    Göttingen
    Beiträge
    705
    Also - Du möchtest als niedrigste Frequenz 1Hz messen. Die "Zählzeit" (oder auch Torzeit genannt) sollte deshalb nicht kleiner sein als 1 Sekunde. Längere Torzeiten liefern zwar eine höhere Auflösung, machen die Messung aber auch träger.

    1 Sekunde hätte den Charme, dass Du den Wert nicht mehr umrechnen musst: Die Zahl der Impulse ist gleich der Frequenz. Wenn Du bis 1kHz messen möchtest müsstest Du allerdings berücksichtigen, dass Timer0 nur bis 256 zählen kann. Also müsstest Du eine Überlauf-ISR einrichten, in der zu einer (Word!)-Variablen bei jedem Überlauf 256 addiert wird - oder aber auf den 16bit-Timer1 wechseln.

    Die Sekunde müsstest Du mit einem anderen Timer realisieren: Bei 16MHz und einem Prescaler von 1024 hättest Du eine Taktfrequenz von 15625Hz, d.h. der Timer zählt in 1 Sek um 15625 weiter. Wenn Du Timer1 mit (65535 - 15625), d.h. 49910 vorlädst, läuft er immer nach genau 1 Sekunde über. In der ISR müsstest Du dann den aktuellen Wert vom Frequenz-Zähl-Timer0 zu Deinem Word addieren, Timer0 auf 0 setzen, Timer1 auf 49910, den Wert von Word an eine andere Variable übergeben und Word für die nächste Zählung auf 0 setzen.

    Klar? (Bestimmt führen noch ein paar andere Wege nach Rom - aber diesen würde ich benutzen...)

    P.S.: Mit "Enable TimerX" aktiviertst Du übrigens nicht den Timer (das geschieht mit Start TimerX), sondern seinen Überlauf-Interrupt!

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    16.09.2008
    Ort
    Hamburg
    Beiträge
    49
    Hi, ich möchte gerne eine kleine Erfolgsmeldung verkünden
    Der Frequenzmesser funktioniert!
    Danke Sauerbruch du hast mir den entscheidenden Tipp gegeben.
    So sieht mein Programm aus:
    Code:
    'Frequenzmessen
    
    '---------------------------------
    'Deklaration
    '---------------------------------
    
    $regfile = "m16DEF.DAT"
    $crystal = 16000000
    
    
    '---------------------------------
    'Initialiserung:
    '---------------------------------
    
    Config Porta = Input
    Config Portb = Input
    Config Portc = Output
    Config Portd = Output
    
    
    Dim Pulselo As Word
    Dim Freq As Integer
    Dim Freq10 As Integer
    
    Enable Timer0                                     'Timer0 An
    Config Timer0 = Counter , Edge = Rising           'Config von Timer0
    Enable Timer1
    Config Timer1 = Timer , Prescale = 256
    
    
    On Ovf1 Tim1_isr                                  'Interrupt bei Timer0 Overflow AN
    On Ovf0 Tim0_isr                                  'Interrupt bei Timer0 Overflow AN
    
    Enable Interrupts                                 'Interrupts An
    
    Tcnt0 = 0                                         'TCNT0 auf Null gesetzt
    Timer1 = 59284                                    'Timer1 auf 59284 setzten
    
    Config Portd = Output
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
    Config Lcd = 20 * 4
    
    Initlcd
    Cls
    Cursor Off
    '---------------------------------
    'Hauptprogramm:
    '---------------------------------
    Do
    Portc = Freq
    Locate 1 , 1
    Lcd "Freq:"
    Locate 1 , 7
    Lcd Freq10
    Locate 1 , 11
    Lcd "Hz"
    Waitms 500
    Cls
    Loop
    
    '---------------------------------
    'InterruptTimer01
    '---------------------------------
    Tim0_isr:
    Pulselo = 255
    Return
    
    '---------------------------------
    'Interrupt Timer1
    '---------------------------------
    Tim1_isr:
    Stop Timer0
    Freq = Tcnt0 + Pulselo
    Freq10 = Freq * 10
    Timer1 = 59284
    Tcnt0 = 0
    Pulselo = 0
    Start Timer0
    Return
    
    
    
    
     End
    Leider kann ich die Frequenz nur in 10-Schritten darstellen.
    Als Auflösung haben ich 100 ms gefällt. Sonst kann ich nicht bis zu 1KHz messen.
    Vielen Danke nochmal an alle die mir geholfen haben

    Lg Tryan

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •