Forum: Mikrocontroller und Digitale Elektronik Frequenz erzeugen


von Michael L. (nightflyer88)


Lesenswert?

Hallo Zusammen

Ich habe mir ein Programm geschrieben, das eine Frequenz von 10Hz bis 
ca. 32khz erzeugen soll. Im folgendem Testprogramm ist eine Variable 
"takt??", die die Frequenz definiert. Jetzt habe ich aber das Problem, 
dass die Frequenz im Verhältnis zur Variable im Quadrat zunimmt.

Beispiel:
Variable - Frequenz
32000 - 10hz
16000 - 20hz
8000 - 40hz
4000 - 80 hz
...
10 - 32khz

Ich möchte aber das die ganze Sache Linear ist:
32000 - 10hz
16000 - 16khz
10 - 32khz


Hier der Code:

do
  takt?? = 32000
  gosub wait_takt
  out (&h378),&b00000010    'Out hight
  gosub wait_takt
  out (&h378),&b00000000     'Out low
loop

wait_takt:
  ! push ax
  ! push cx

  ! mov cx, takt??
  wait1:             '1. Verzögerungsschlaufe
  ! dec cx
    ! mov ax, 300    'Kalibrierwert
    wait2:           '2. Verzögerungsschlaufe
    ! dec ax
    ! cmp ax, 0
    ! jg wait2
  ! cmp cx, 0
  ! jg wait1

  ! pop cx
  ! pop ax
return


Es sind zwei Verzögerungsschlaufen ineinander verschachtelt, wobei die 
zweite als Kalibrierschlaufe dient, diese hat auch immer die gleiche 
Dauer.

Hat jemand eine schlaue Idee, wie ich das ganze irgendwie Linear 
hinbekommen ? Aufbau der Verzögerungsschlaufe ?

von Axel S. (a-za-z0-9)


Lesenswert?

Timer insbesondere FAQ: Timer

von Bernie (Gast)


Lesenswert?

Nach welcher Rechenregel sollen denn die Zuordnungen
32000 - 10hz
16000 - 16khz
   10 - 32khz     funktionieren?

Was soll sich denn aus der Vorgabe 16001 ergeben?
Und was soll sich aus der Vorgabe 11 ergeben?

Wenn du das klar und eindeutig erklären kannst, findet
sich ein Weg (auch wenn es nicht mit jedem µC machbar
sein wird) dies zu programmieren.

von ./. (Gast)


Lesenswert?

Hol Dir einen 16F150x PIC. Der hat einen schicken NCO.
(NCO := Numerically Controlled Oscillator)
Quasi ein DDS für Rechteck- und Pulssignale.

Einfach den Wert in ein Registerpaar schreiben. Fertig.

Wenn man will, kann man die Ausgabe des NCO noch mit den
integrierten CLC (Configurable Logic Cell) verwursten.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael L. schrieb:
> Jetzt habe ich aber das Problem, dass die Frequenz im Verhältnis zur
> Variable im Quadrat zunimmt.
Diese Funktion verläuft wie 1/x und nennt sich Kehrwert...


Michael L. schrieb:
> Ich möchte aber das die ganze Sache Linear ist:
> 32000 - 10hz
> 16000 - 16khz
> 10 - 32khz
Ähm, das wäre eine Art "umgekehrt proportional", aber irgendwie 
vermischst da beliebig einen Integerwert mit einer Frequenz. Ich hätte 
an deiner Stelle wenistens gefordert, dass der Verlauf so ist:
32000 - 32kHz //
16000 - 16kHz //
10    - 10Hz

> Ich möchte aber das die ganze Sache Linear ist:
Das wird mit diesem einfachen Ansatz nicht gehen. Vor allem die Dynamik 
über mehr als 3 Zehnerpotenzen (10Hz - 32kHz) ist recht sportlich. Der 
Tipp mit dem NCO geht in die richtige Richtung, aber leider haben das 
die wenigsten uC eingebaut.

Eine Frage hätte ich noch: reichen dir Zehnerschritte (also 10Hz, 20Hz, 
30Hz, ...) oder willst du da sogar noch Einerschritte?

von Rolf Magnus (Gast)


Lesenswert?

Michael L. schrieb:
> Jetzt habe ich aber das Problem,
> dass die Frequenz im Verhältnis zur Variable im Quadrat zunimmt.
>
> Beispiel:
> Variable - Frequenz
> 32000 - 10hz
> 16000 - 20hz
> 8000 - 40hz
> 4000 - 80 hz
> ...
> 10 - 32khz

Was ist daran quadratisch? Der Zusammenhang scheint wie folgt zu sein:

320.000 / Variable = Frequenz

> Ich möchte aber das die ganze Sache Linear ist:
> 32000 - 10hz
> 16000 - 16khz
> 10 - 32khz

Das geht nicht linear. Durch diese drei Punkte läßt sich keine Gerade 
legen. Für die ersten beiden Punkte wäre die lineare Funktion folgende:

Frequenz = 31990 - Variable * (15990/16000)

Damit kommt für einen Wert von 10 aber eine Frequenz von ca. 31,98 kHz 
raus.


Übrigens:

Michael L. schrieb:
> Verzögerungsschlaufen
> Kalibrierschlaufe
> Verzögerungsschlaufe

Die Dinger heißen nicht Schlaufen, sondern Schleifen.

von Christian B. (luckyfu)


Lesenswert?

nun, das Problem ist, man stellt den Timer ein, dieser zählt Takte, 
misst also die Zeit. Und da die Zeit der Kehrwert der Frequenz ist wird 
das nie linear werden.

Ich hab sowas auch schonmal programmiert (bzw. bin noch dabei 0,2-20Hz). 
Ich hab dazu eine Tabelle vorher berechnet und als Array abgespeichert. 
Dieses enthält die Reloadwerte der Timer sowie die Menge der Überläufe 
bei kleineren Frequenzen.

Ich muss es aber noch optimieren. Im Originalaufbau hatte ich den 
inneren Frequenzgenerator verwendet (weil ich eine bestehende Platine 
nutzte) aber damit wird das zu ungenau und nicht reproduzierbar. Ich hab 
keine Lust bei jedem aufgebauten Gerät Manuell die Werte 
nachzujustieren... Wenn die finale Hardware fertig ist mach ich da 
weiter.

Es gibt genug Timerrechner im Netz, welche dir die Rechnerei abnehmen. 
oder du schreibst dir schnell was in Excel.

von Michael L. (nightflyer88)


Lesenswert?

Vielen Dank erstmal für eure tipps !!

Die Variable ist der Zeitwert, also Anzahl der Schleifen Wiederholungen. 
Wenn die Variable auf 10 ist, so wird nur ganz kurz zwischen High und 
Low gewartet. Soweit sollte das jedem verständlich sein.... Beim 
genannten Wert 10, habe ich eine Frequenz von etwa 32khz, würde ich den 
Wert auf 5 setzten, so habe ich eine Frequenz von 64khz, aber soviel 
brauche ich nicht.

Letztlich spielt es mir keine Rolle, ob die Variable von 0 - 32000, oder 
32000 - 10 die entsprechende Frequenz ausgibt. Es muss einfach linear 
sein.
Ich brauche eine Frequenz von min 10hz bis ca. 30 - 32 khz. Am besten 
mit einer Auflösung von etwa 5hz. Wie gesagt, muss die maximal Frequenz 
nicht genau 32khz sein, 30khz reichen auch.

Noch etwas: Das ganze läuft nicht auf einem uC, sondern auf einem ganz 
normal PC mit DOS, die Frequenz wird am LPT ausgegeben. Jedoch zum 
programmieren ist es genau gleich wie bei einem uC.

Das ganze wird eine Schrittmotorensteuerung, die Frequenz gibt dann die 
Drehzahl des Motors vor, deshalb brauche ich eine "linear regelbare 
Frequenz".

Die Kalibrierschleife dient dazu, damit die Drehzahl genau kalibriert 
werden kann.

Wenn jemand einen Lösungsvorschlag oder einen Tipp hat, wie man das 
bewerkstelligen könnte, währe ich ihm dankbar.

von Bernie (Gast)


Lesenswert?

Was ist denn "ganz kurz" für eine Zeiteinheit?
Kann man die zwischen 29,999 und 30,000 kHz
vernachlässigen?

Oweh, Wünsche hat er, aber Denken mag der TO nicht.

Tschüs.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Bernie schrieb:
> Kann man die zwischen 29,999 und 30,000 kHz vernachlässigen?
Ja, denn Michael L. schrieb:
>> mit einer Auflösung von etwa 5hz.
D.h. 29,999 und 30,000 kHz sind gleich. Aber 29,995 und 30,000 kHz sind 
unterschiedlich...

> aber Denken mag der TO nicht.
Nicht zu weit aus dem Fenster lehnen...  ;-)

Michael L. schrieb:
> Beim genannten Wert 10, habe ich eine Frequenz von etwa 32khz, würde ich
> den Wert auf 5 setzten, so habe ich eine Frequenz von 64khz, aber soviel
> brauche ich nicht.
Ja klar. Aber damit hast du vom Wert 10 nach 11 auch keinen 5Hz Schritt, 
sondern gut 3kHz. Für die von dir gewünschte feinere Auflösung müsstest 
du also etwa 600 mal schneller sein.
So wie ich das Ganze ansehe schaffst du aber bestenfalls (nach Weglassen 
der 300er-Schleife und der Push-Pop Orgie) eine Beschleunigung um den 
Faktor 150-200. Deine Schritte würden also dort im 32kHz Bereich 
mindestens 20Hz groß werden.

Um die 5Hz-Granularität bei 30kHz jitterfrei zu bekommen bräuchtest du 
einen (Hardware-)Zähler, der mit mindestens 200MHz läuft.

> Noch etwas: Das ganze läuft nicht auf einem uC, sondern auf einem ganz
> normal PC mit DOS, die Frequenz wird am LPT ausgegeben. Jedoch zum
> programmieren ist es genau gleich wie bei einem uC.
Oh, scheiss Salamitaktik. Die Antwort lautet: Vergiss es. Denn allein 
der Jitter, den dir irgendwelche Interrupts auf diesem Gerät machen, 
wird dein Konzept zerlegen.
Aber: wenn du schon einen Rechenboliden hast, dann sollte doch die 
Berechnung des Kehrwerts nach der oben geposteten Formel nicht allzu 
schwer sein...

@ Michael:
Das 'H' in Hertz schreibt man weltweit GROSS!

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Du solltest ernsthaft darüber nachdenken, den 8253 Timer des PC zu 
benutzen. Gut, Channel 0 ist schon auf den Ticker eingestellt mit 18,2 
Hz, Channel 1 besorgt mit ca. 66kHz den DRAM Refresh, aber Channel 2 
versorgt den PC Speaker und das ist der, mit dem du bestens rumspielen 
könntest.
Alles andere ist zu sehr abhängig vom CPU Takt und auch wg. der oben 
erwähnten Interrupts einfach nicht brauchbar.

http://computer-programming-forum.com/40-scheme/fa1ab14f38fe7211.htm
http://computer-programming-forum.com/46-asm/cbb489b2413bf90c.htm

von Michael L. (nightflyer88)


Lesenswert?

Also alle störenden Interrupts habe ich ausgeschaltet. "OUT (&H21), 
252". Einige sind jedoch noch aktiv, wie beispielsweise die Systemuhr, 
aber die stören nicht, respektive, die Systemuhr brauche ich noch für 
andere Aufgaben.

Mit der Schleifen-taktik, habe ich die Frequenz gemessen, und diese ist 
konstant. Für meine Anwendung einwandfrei.

Mit dem 8253 Timer habe ich mich bereits auch schon herumgeschlagen, 
aber irgendwie klappts nicht so richtig... Wenn es funktionieren würde, 
währe das eine feine Sache, unabhängig vom CPU takt.

Ich habe, wie Matthias beschrieben hat, den Kanal 2 des Speakers 
verwendet. Jedoch weis ich nicht, wie ich den Timer konfigurieren muss, 
damit ein Interrupt ausgelöst wird, wenn dieser bei 0 ankommt. Somit 
könnte ich in einer ISR den Ausgang auf high oder low schalten. Oder 
gibts eine andere Möglichkeit ?

Konfiguration des Timers:

OUT (&H61), INP(&H61) OR 1  'Lautsprecher und damit Zähler 2 aktivieren
OUT (&H43), 176             '8253 Zähler 2 auf Modus 0 setzen

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.