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?
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.
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?
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.
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.
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.
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.
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
volatileuint16_tz=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
intmain(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
return0;
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. ???
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.
(???)
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.
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.
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.
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).
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.
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.
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.
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.
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