Getreu dem Motto viele Wege führen um Rom, habe ich nun verschiedene Lösungsanzätze zum Messen der Frequenzen genutzt.
Außerdem habe ich endlich das Timer-Capture-Register zum Messen der Frequenzen nutzen können.Der Fehler war der Befehl „Edge= Rising“ in der Config-Zeile, denn der darf dort wohl nicht sein.
An sich funktioniert der jetzt soweit ganz schön.
Leider nur an sich!
Tests über Prescaler (256 und 1024) und Frequenzen von 244 Hz und 61Hz haben super funktioniert.
Beim Prescaler 8 (mit und auch ohne Clear Timer, der die Zählschritte zwischen 256 und 512 umschaltet, also Frequenz verdoppelt) kriege ich leichte Abweichungen. Bei höheren Frequenzen noch extremer.
Sie sind nicht nachvollziehbar und auch nicht linear (zumindest nicht für mich )
Hier mal ein paar gemessene und reale Werte:
Real 3,92 kHz - Mess (µC) 3,99 kHz
Real 7,81 kHz – Mess 8,07kHz
Real 31,37 kHz – Mess 36,36 kHz
Real 62,5 kHz – Mess 83,333 kHz
Der Unterschied beruht wohl darauf, dass der Timerwert dann zu klein ist (Ticks verpasst?!) und demnach errechnet sich eine falsche Frequenz.
Demnach habe ich auch versucht, über einen Interrupt (Int1) , Bitwait und auch Pulsein die Frequenzen zu Messen. Alles mit ähnlich schlechtem Ergebnis in höheren Frequenzen.
Nun die Frage wieso? Hat da jemand vielleicht Erfahrungen?
Habe auch versucht einen Korrekturfaktor im Interrupt oder ähnlichem zu realisieren, was zwar an sich klappt, aber auch nicht so eindeutig. Erstens ist es schwierig einen genauen Korrekturfaktor zu bestimmen und dann geht wohl noch der Echtzeitbezug verloren, da der Faktor je nach Inhalt/Länge des Interrupts anders ist, was eigentlich nicht sein kann, da ja erst beim Verlassen des Interrupts der Timer genullt wird, bzw. jedes Mal nach dem gleichen Schritt.
Hatte auch schon mal ein ähnliches Problem als ich einen Timer für Millisekunden nutzen wollte. Von der Rechnung hat der wunderbar auf 1ms gepasst, jede Ms in den Interrupt und globalen Zähler Hochzählen. Die darauf folgenden Rechnungen (zB Wartezeit 10000 ms zum Schalten ; nein wollte eben kein „waitms“ nutzen, sondern in der Zwischenzeit weiter das Programm bearbeiten) haben jedoch gezeigt, dass der Timer auch da nicht so genau ging und von Hand nach korrigiert werden musste.
Anbei einmal mein Code zum Messen der Frequenzen (alle genutzten Möglichkeiten auskommentiert drin), vielleicht hat ja noch jemand eine Lösung, die auch bei hohen Frequenzen (1-100kHz noch funktioniert, oder alternativ eine Möglichkeit für einen passenden Korrekturfaktor)
Zudem wäre es schön irgendwie neben der Frequenz auch noch die Pulsweite (für das Verhältniss) Messen zu können, muss nicht gleichzeitig kann abwechselnd realisiert werden.
Das geht wohl auch über ein RC Glied und anschließend ADC, ist dann aber recht ungenau aufgrund der Bauteiltoleranzen (soweit habe ich das gelesen).
Ich freue mich auf weitere Anregungen.
Code:
$regfile = "m32def.dat"
$framesize = 500
$swstack = 500
$hwstack = 500
$crystal = 16000000
$baud = 9600
Config Portd.6 = Input
Config Portb.0 = Input
Config Portd.3 = Input
Config Portd.7 = Output
Config Portb.0 = Input
Dim Us As Long
Dim Mess_frequenz1 As Word , Mess_frequenz2 As Word , Mess_frequenz As Long
Dim Pwm_counter As Byte
Const Led_1_value = 200
Const Presc = 1
Dim Prisc As Word
Prisc = Presc
Config Timer2 = Timer Pwm , Pwm = On , Compare Pwm = Clear Down , Prescale = Presc , Clear Timer = 0
Compare2 = 128
'Timer Config
Config Timer1 = Timer , Capture Edge = Rising , Prescale = 8 , Noise Cancel = 1 , 'Edge = Rising
'Capture Interrupt
On Capture1 Cap_int
'Config Timer1 = Timer , Prescale = 1 'Zähler
'Config Int1 = Rising 'Int1 – geht „Change“ auch???
'On Int1 Irq1
Enable Interrupts
Enable Timer1
'Enable Timer0 'Enable Timer0
'Start Timer1
Enable Timer2
Enable Capture1
'Enable Icp1
'Enable Int1
'Main
'-------------------------------------------------------------------------------
Do
'( '1. Möglichkeit über Bitwait und Zeit nehmen
Bitwait Pind.6 , Set
Mess_frequenz1 = Timer1
Timer1 = 0
Bitwait Pind.6 , Reset
Mess_frequenz2 = Timer1
Timer1 = 0
')
'( 2. Möglichkeit über Pulsein und Wechsel
Pulsein Mess_frequenz1 , Pind , 6 , 1
Print "High: " ; Mess_frequenz1
Pulsein Mess_frequenz2 , Pind , 6 , 0
Print "Low: " ; Mess_frequenz2
')
' Mess_frequenz = Mess_frequenz1 + Mess_frequenz2 'Frequenz bestimmen
' Print "Dauer: " ; Mess_frequenz
' 3. Möglichkeit über Input-Capture-Register
Mess_frequenz = Capture1
Mess_frequenz = 16000000 / Mess_frequenz
Mess_frequenz = Mess_frequenz / 8
Print "MessFrequenz: " ; Mess_frequenz
' Waitms 50
Loop
End
'-------------------------------------------------------------------------------
'Timer1 Capture Interrupt Routine
Cap_int:
'(
Select Case Prisc
Case 1 : Timer1 = 81
Case 8 : Timer1 = 90
Case 256 : Timer1 = 0
Case 1024 : Timer1 = 0
End Select
')
Timer1 = 0
Return
'-------------------------------------------------------------------------------
Irq1:
' If Portd.3 = 1 Then
Mess_frequenz1 = Timer1
' Else
' Mess_frequenz2 = Timer1
' End If
Timer1 = 0
Return
'-------------------------------------------------------------------------------
Irq2:
Mess_frequenz = Timer1
Timer1 = 0
' Print "In"
Return
Lesezeichen