Forum: Mikrocontroller und Digitale Elektronik Frequenz erzeugen


von Leif (Gast)


Lesenswert?

Ich stehe irgendwie auf dem Schlauch. Ich will mit einem ATmega168 bei 
16 MHz (von mir aus auch ein anderer Quarz) eine Frequenz an einem I/O 
Pin erzeugen. Diese soll variabel von 0 bis ca. 140.000 Hz in Ein-Herz 
Schritten veränderbar sein. Da ich mehrere Frequenzen gleichzeitig 
benötige, dachte ich an eine Lösung mit einem Zähler für die Impulse und 
Timer. Aber irgendwie habe ich ein Brett vor dem Kopf, wie ich das in 
GCC umsetzen kann. Timer sind eigentlich kein Problem. Kann mir wer 
einen Denkanstoß geben?

von Gerrit (Gast)


Lesenswert?

Das Zauberwort lautet DDS:

https://de.wikipedia.org/wiki/Direct_Digital_Synthesis


An deiner Stelle würde ich überlegen, für 5€ bei der Bucht ein 
AD9850-Modul zu kaufen und mit dem Controller anzusteuern.

So kommst du locker bis 20 oder 30MHz in 0,1Hz-Schritten.

von yo man (Gast)


Lesenswert?


von Leif (Gast)


Lesenswert?

Ah, ihr seit schnell. Aber ich brauche keinen D/A Wandler. Ich will ein 
reines TTL Rechtecksignal generieren. Oder habe ich da jetzt was zu 
schnell überflogen?

von npn (Gast)


Lesenswert?

Leif schrieb:
> Ah, ihr seit schnell. Aber ich brauche keinen D/A Wandler. Ich
> will ein
> reines TTL Rechtecksignal generieren. Oder habe ich da jetzt was zu
> schnell überflogen?

Stimmt, du brauchst keinen D/A-Wandler. Der ist schon im IC drin :-)
Der AD9833 macht Sinus, Rechteck und Dreieck von Haus aus. Er kann eine 
Frequenz von 0..12,5MHz bei einer Auflösung von 0,1Hz erzeugen. Das ist 
alles schon in diesem einen IC.

von Hanns (Gast)


Lesenswert?

Für ein Rechteck würde ich es so machen, dass ich das Tastverhältnis 
leicht variieren würde.
Soll heißen, wenn man von kleinen zu großen Frequenzen geht:
Von Schritt zu Schritt immer die Onzeit verkürzen, dann die Offzeit. 
Dann wieder die Onzeit verkürzen und dann die Offzeit.
Dadurch erhält man grob gesagt die maximal mögliche Auflösung. Das 
Tastverhältnis bleibt bei annähernd 50%, damit hält man die nicht 
50%-rechteckgerechten Oberwellenanteile klein.

Es gibt bestimmt auch eine Formel, um die optimalen On-und-Offlängen für 
eine gegebene Frequenz zu erhalten.

von Gerrit (Gast)


Lesenswert?

Leif schrieb:
> Ah, ihr seit schnell. Aber ich brauche keinen D/A Wandler. Ich will ein
> reines TTL Rechtecksignal generieren. Oder habe ich da jetzt was zu
> schnell überflogen?

Der AD9850 hat den AD-Wandler schon eingebaut und er hat neben dem Sinus 
auch einen Rechteckausgang.


npn schrieb:
> Stimmt, du brauchst keinen D/A-Wandler. Der ist schon im IC drin :-)
> Der AD9833 macht Sinus, Rechteck und Dreieck von Haus aus. Er kann eine
> Frequenz von 0..12,5MHz bei einer Auflösung von 0,1Hz erzeugen.

Wenn 12,5MHz gut darstellbar sind und Dir reichen, ist das sicher eine 
gute Wahl.

von npn (Gast)


Lesenswert?

Gerrit schrieb:
> Wenn 12,5MHz gut darstellbar sind und Dir reichen, ist das sicher eine
> gute Wahl.

Die werden ihm reichen :-)
Leif schrieb:
> Diese soll variabel von 0 bis ca. 140.000 Hz in Ein-Herz
> Schritten veränderbar sein.

von gvs (Gast)


Lesenswert?

Mit der Maximalfrequenz am T-Pin rein und am OC-Pin raus. Sind dann zwar 
nur 16 Bit (eigentlich brauchst ja mindestens 17) aber besser als nix.

von Leif (Gast)


Lesenswert?

Wo ist mein Denkfehler? Das folgende erzeugt kein Signal. Sollte doch 
aber oder?
1
#include <stdint.h>
2
#include <avr/interrupt.h>
3
#include <avr/io.h>
4
5
#define OUT1DDR DDRB  
6
#define OUT1PORT PORTB
7
#define OUT1PIN PB1
8
volatile uint16_t z=0;
9
10
ISR (TIMER1_COMPA_vect)
11
{
12
13
  z++;
14
  if (z >= 10)
15
  {
16
    OUT1PORT ^= (1 << OUT1PIN);
17
    z = 0;
18
  }
19
20
}
21
22
23
int main (void)
24
{
25
  OUT1PORT &= ~(1 << OUT1PIN);    // Aus
26
  OUT1DDR |= (1 << OUT1PIN);      // Richtung: Ausgang
27
28
  TIMSK1 |= (1 << OCIE1A);  // Output Compare A Match Interrupt Enable
29
  OCR1A = 9;
30
  TCCR1B |= (1 << CS11);    // // Prescaler: 1/8
31
  TCCR1B |= (1 << WGM12);  // CTC
32
  sei();
33
34
35
  while (1);
36
37
  return 0;
38
}

Wenn ich schreibe:
1
ISR (TIMER1_COMPA_vect)
2
{
3
    OUT1PORT ^= (1 << OUT1PIN);
4
}
dann kommen immerhin 100kHz raus. Wobei ab und zu eine Flanke außerhalb 
der Reihe tanzt. Mit dem Zähler oben sollte doch dann 1/10 Takr raus 
kommen. ???

von npn (Gast)


Lesenswert?

gvs schrieb:
> Mit der Maximalfrequenz am T-Pin rein und am OC-Pin raus. Sind
> dann zwar
> nur 16 Bit (eigentlich brauchst ja mindestens 17) aber besser als nix.

Der AD9833 hat aber keinen T- und OC-Pin. Und der AD9850 auch nicht. 
(???)

von gvs (Gast)


Lesenswert?

npn schrieb:
> Der AD9833 hat aber keinen T- und OC-Pin. Und der AD9850 auch nicht.
> (???)

Leif schrieb:
> Ich will mit einem ATmega168

Ohne Studium des Datenblatts behaupte ich er hätte sie.

von npn (Gast)


Lesenswert?

gvs schrieb:
> Ohne Studium des Datenblatts behaupte ich er hätte sie.

Ich auch :-)
Sorry, den Mega168 hatte ich glatt übersehen, weil die ganze Zeit von 
DDS die Rede war.

von gvs (Gast)


Lesenswert?

Leif schrieb:
> Mit dem Zähler oben sollte doch dann 1/10 Takr raus
> kommen. ???

Mit Prescaler 1/80 oder ?

von Leif (Gast)


Lesenswert?

Na ich dachte, wenn der Timer alle 0,00001s auslöst und ich darin 10 
"Takte" zähle, dann produziere ich 10kHz.
Muß doch irgendwie ganz simpel sein, so ein Signalgenerator mit 
"geringer" Frequenz ohne extra Hardware zu lösen. Aber wie gesagt: Brett 
vorm Kopf.

von Dieter F. (Gast)


Lesenswert?

Leif schrieb:
> dann kommen immerhin 100kHz raus

Schon mal überlegt, dass die ISR ggf. etwas lang ist ...

Probier doch mal Precaler 32 - ich wette, dann funktioniert auch die 
Zähl-Routine ... (halt mit dann 2,5 kHz).

von gvs (Gast)


Lesenswert?

Wenn der mit 100kHz laufen würde, was ich bezweifle bei Prescaler 8.

Der Delay der ISR sollte nicht wirklich ins Gewicht fallen, und sich auf 
wenige Clocks beschränken, wenn man nicht gerade uint16 nimmt um bis 10 
zu zählen.

von Dieter F. (Gast)


Lesenswert?

gvs schrieb:
> wenige Clocks beschränken

... es gibt da auch noch Prolog und Epilog zur ISR ...

von Helmut S. (helmuts)


Lesenswert?

Schon mal an den Jitter der Periodendauer und der Pulsbreite gedacht?
Nehmen wir die 140,000kHz.
Dazu braucht man 71.428571 Takte bei 10MHz Prozessorfrequenz. Egal wie 
man das macht (Software/Timer), die Periodendauer muss immer zwischen 71 
und 72 Takten umgeschaltet werden um im Mittel in 1s auf 140000 Perioden 
zu kommen. Das sind 1,4% Jitter in der Periodendauer und 2,8% Jitter in 
der Pulsbreite. Damit man in der Mitte den Pegelwechsel macht muss man 
nach 35 oder 36 Takten den Ausgang umschalten. Da kann der Prozessor 
nichts anderes mehr tun, da sonst ja sofort die Zahl der Zyklen total 
falsch(zu groß) wird.

Es gibt einen PIC der eine DDS mit 1Bit-Ausgang in Hardware eingebaut 
hat. Damit hat man zwar auch den Periodenjitter, aber der Prozessor wird 
überhaupt nicht belastet und ist somit frei für andere Aufgaben.

Mit echtem DDS (ADxxxx) hat man diese Probleme überhaupt nicht.

von Gerrit (Gast)


Lesenswert?

Oder man bekommt es hin, dass ein timer die Onzeit erzeugt, dann toggle, 
dann der zweite Timer für die Offzeit, toggle, das ganze von vorne.

dann kann man die Werte für on und off in die entsprechenden Register 
(OCR... oder so) laden, ohne dass der Prozessor belastet wird.

von suppigroppi (Gast)


Lesenswert?


von Helmut S. (helmuts)


Lesenswert?

Vielleicht solltet ihr alle mal richtig lesen. Hier der Wunsch des 
Fragestellers.

>Diese soll variabel von 0 bis ca. 140.000 Hz in Ein-Herz Schritten veränderbar 
sein.

Erzeugt mal bitte mit euren Timervorschlägen 139999Hz und 140000Hz. Die 
Quarzfrequenz sei 10MHz. Ich bin gespannt.

von Leif (Gast)


Lesenswert?

Danke.
Also doch Denk-Fehler. Fehler zu denken oder zu denken, gedacht zu 
haben. Ich werd's anders lösen.

Besinnliche Feiertage!

von DH1AKF W. (wolfgang_kiefer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo Leif,
schau doch mal diesen Thread an:
Beitrag "Mikrocontroller als I/Q- Generator (MW bis KW)"
Hier wird zwar ein PSoC3 oder 5 verwendet, aber mit dem PSoC4 (42xx), 
den es mittlerweile als Breakout- Board für wenige Euro auch in 
Deutschland gibt, sollte das Prinzip ebenso funktionieren.
Die genannten Mikrocontroller von Cypress beinhalten eine PLL zur 
Takterzeugung.
Bei der Programmierung könnte ich behilflich sein.
Das Ganze könnte dann so aussehen wie auf dem Bild. Eventuell noch ein 
zweiter Drehgeber für verschiedene Schrittweiten, Festfrequenzen usw.

Schönen Advent, Wolfgang

: Bearbeitet durch User
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.