Sinus mit DDS erstellt - geht nicht über 400 hz

Gast #2284475
Lesenswert?

Hallo Leute,

folgendes Problem: ich habe einen Sinus mit DDS erstellt und je nach 
Veränderung des IR1-Wertes ändert sich die Frequenz.

Leider ist bei 400 HZ Schluss - Wenn ich den IR1 noch kleiner setze, 
ändert sich der Sinus nicht mehr, habe es mit einem Oszilloskop 
nachgemessen.


Hat jemand eine Idee, woran das liegt?

Gruß, Martin
Gast #2284508
Lesenswert?

Hi

>Leider ist bei 400 HZ Schluss - Wenn ich den IR1 noch kleiner setze,
>ändert sich der Sinus nicht mehr, habe es mit einem Oszilloskop
>nachgemessen.

Dann hast du etwas falsch gemacht.

MfG Spess
Gast #2284536
Lesenswert?

Hier ist mein Quelltextauszug:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#include "D:\lcd.h"
5

6
const uint8_t sinustabelle[256] = //HexaWerte = 8 Bit; Anzahl der Tabellenwerte:256
7
{
8
0x80,0x83,0x86,0x89,0x8C,0x8F,0x92,0x95,
9
0x98,0x9C,0x9F,0xA2,0xA5,0xA8,0xAB,0xAE,
10
0xB0,0xB3,0xB6,0xB9,0xBC,0xBF,0xC1,0xC4,
11
0xC7,0xC9,0xCC,0xCE,0xD1,0xD3,0xD5,0xD8,
12
0xDA,0xDC,0xDE,0xE0,0xE2,0xE4,0xE6,0xE8,
13
0xEA,0xEC,0xED,0xEF,0xF0,0xF2,0xF3,0xF5,
14
0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFC,
15
0xFD,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
16
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,
17
0xFD,0xFC,0xFC,0xFB,0xFA,0xF9,0xF8,0xF7,
18
0xF6,0xF5,0xF3,0xF2,0xF0,0xEF,0xED,0xEC,
19
0xEA,0xE8,0xE6,0xE4,0xE2,0xE0,0xDE,0xDC,
20
0xDA,0xD8,0xD5,0xD3,0xD1,0xCE,0xCC,0xC9,
21
0xC7,0xC4,0xC1,0xBF,0xBC,0xB9,0xB6,0xB3,
22
0xB0,0xAE,0xAB,0xA8,0xA5,0xA2,0x9F,0x9C,
23
0x98,0x95,0x92,0x8F,0x8C,0x89,0x86,0x83,
24
0x80,0x7C,0x79,0x76,0x73,0x70,0x6D,0x6A,
25
0x67,0x63,0x60,0x5D,0x5A,0x57,0x54,0x51,
26
0x4F,0x4C,0x49,0x46,0x43,0x40,0x3E,0x3B,
27
0x38,0x36,0x33,0x31,0x2E,0x2C,0x2A,0x27,
28
0x25,0x23,0x21,0x1F,0x1D,0x1B,0x19,0x17,
29
0x15,0x13,0x12,0x10,0x0F,0x0D,0x0C,0x0A,
30
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,
31
0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
32
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
33
0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
34
0x09,0x0A,0x0C,0x0D,0x0F,0x10,0x12,0x13,
35
0x15,0x17,0x19,0x1B,0x1D,0x1F,0x21,0x23,
36
0x25,0x27,0x2A,0x2C,0x2E,0x31,0x33,0x36,
37
0x38,0x3B,0x3E,0x40,0x43,0x46,0x49,0x4C,
38
0x4F,0x51,0x54,0x57,0x5A,0x5D,0x60,0x63,
39
0x67,0x6A,0x6D,0x70,0x73,0x76,0x79,0x7C,
40
};
41

42
void initialisierung()
43
{
44
ICR1=0x3E8; //1000 als Hexazahl (Bis wohin gezählt wird); Je kleiner, desto höher die Frequenz
45

46

47
TCCR1A=(1<<WGM11);
48
TCCR1B=(1<<WGM13) | (1<<WGM12) | (1<<CS10) ; 
49
//WGM  : Fast PWM mit ICR1-Wert; Fast PWM: Zähler geht auf Null, sobald ICR1 erreicht wird.
50
TIMSK=(1<<TICIE1); // Interrupt wird ausgelöst, wenn ICR1 erreicht wird; Löst Timer_CAPT_vect aus.
51

52
}
53

54
ISR(TIMER1_CAPT_vect) //Timer-Interrupt-Routine, wird ausgelöst, wenn ICR1 erreicht wird.
55
{
56
  static uint8_t sinus_zaehler=0; //Gibt an, welche Position im Sinus ausgegeben wird.
57

58
  PORTC &=~(0x0F); //C0 - C3 werden auf 0 gesetzt.
59
  PORTC |= (sinustabelle[sinus_zaehler])&(0x0F); //Wert sinus_zaehler in sinustabelle mit der Maske 0x0F und-verknüpft,
60
                           //damit nur die Werte C0-C3 verwendet werden.
61

62
  PORTB &=~(0x3C); //B2 - B5 werden auf 0 gesetzt.
63
  PORTB |= (sinustabelle[sinus_zaehler]>>2)&(0x3C);//Wert sinus_zaehler in sinustabelle wird um zwei Stellen nach rechts verschoben, 
64
                           //und anschließend mit der Maske 0x3C und-verknüpft,
65
                               //damit nur die Werte B2-B5 verwendet werden.
66

67
  sinus_zaehler++; //Inkrementierung der Sinus-Position
68
}
69

70

71
int main(void)
72

73
{
74
char run=1;
75

76
DDRC= (1<<PINC0) | (1<<PINC1) | (1<<PINC2) | (1<<PINC3);
77
DDRB= (1<<PINB2) | (1<<PINB3) | (1<<PINB4) | (1<<PINB5);
78
DDRD= (1<<PIND3);
79

80
PORTD |= (1<<PIND3); // Stromversorgung für Operationsverstärker
81

82
initialisierung(); //Aufruf der Funktion "initialisierung"
83

84

85

86
sei(); // Globale Interrupts aktivieren
87

88
while(run) // Endlosschleife
89
{
90
}
91

92
}


Den Sinus erzeuge ich mit je 4 Pins von Port B % C.
Gast #2284559
Lesenswert?

Ich habe dieses Problem auch. Bei mir war allerdings schon bei ~110Hz 
Schluss. Ich hatte damals ~ 190 Werte in meiner Tabelle. Ich habe um 
höhere Frequenzen zu erreichen einfach weniger Werte genommen. Wenn man 
mal überlegt, liegt die Interrptfrequenz bei 100 Werten mal 200Hz schon 
bei 20kHz(!). Das is ne Menge. Ich habe einen Mega128 @ 16MHz verwendet.
Heute würde ich einen XMega vorziehen, der dürfte dank DMA schneller 
sein.

Es liegt also daran, dass der AVR zu langsam ist, bzw. du nicht mehr 
Werte in dieser Zeit ausgeben kannst. Ist also ein Problem mit der 
Rechenleistung!

Sollte ich mit meiner Vermutung falsch liegen, wäre ich auch an einer 
Lösung interessiert.




Gruß
Knut
Gast #2284581
Lesenswert?

Also  ich versteh  den Code zwar  nicht ohne stundenlanges Nachdenken, 
aber ich rate mal dass Du die Tabelle  Wert  für Wert ausliest  mit 
unterschiedlichen Geschwindigkeiten.

Das sagt   mir dass Du  noch  nie vom Abtasttheorem gehört hast.
Du kannst in der Tabelle Werte überspringen, das gibt  dann immer noch 
einen Sinus.  Nach  oben Schluss ist dann wenn Du  pro Sinusperiode  nur 
noch 2 Stützpunkte  hast.

Andererseits:  was Du da machst  ist  zwar  ein digital erzeugter Sinus, 
aber nicht DDS.

DDS  nimmt  einen  schnellen Sinus, haut den auf nen schnellen DAC, 
dann wird das ganze  noch etwas tiefpassgefiltert, und fertig.

Eine  PWM  im  Signalpfad  zu haben  (als Ersatz  für einen schnellen 
DAC)  bremst  alles um den Faktor  100 runter.  Macht irgendwie  keinen 
Sinn.

Meine Empfehlung:  Bau  Dir einen  2. Ordnung   digitalen Delta Sigma 
Modulator,  füttere ihn mit einem 8bit Sinus, der Delta Sigma macht 
daraus  4bit,  und mit den 4bit gehst Du auf einen externen  R2R DAC 
plus  Tiefpassfilter. Der DAC  arbeitet dann mit 2MHz, und DU kommst 
locker mit Deinem Sinus  auf  100-200kHz.


Noch Fragen?
Gast #2284590
Lesenswert?

Martin1 schrieb:
> DDS  nimmt  einen  schnellen Sinus
Was unterscheidet denn einen schnellen Sinus von einem langsamen 
Sinus???
Doch eigentlich nur die Periodendauer. Die ist abhängig, wie schnell die 
Werte ausgelesen werden.

> Eine  PWM  im  Signalpfad  zu haben  (als Ersatz  für einen schnellen
> DAC)  bremst  alles um den Faktor  100 runter.
Kannst du das näher Erleutern?


Gruß
Knut
#2284601
Lesenswert?

@Martin

DDS geht so:
Du definierst einen Phasenakkumulator mit z. B. 16bit.
Du setzt die Interruptrate mittels Timer auf z. B. 65536Hz.
Es ginge natürlich auch jede andere Frequenz, aber damit
bekommst du so schön 1Hz Auflösung. Die oberen 8bit deines
Akkumulators nimmst du zum Adressieren der Sinustabelle.

Auflösung:
65536Hz/65536 = 1Hz
Die 65536 ist deine Akkumulatorgröße.

Wenn du jetzt 10Hz haben willst, dann addierst du jedesmal 10 zum 
Akkumulator.

freq=10
phase=0


ISR:
phase = phase+freq
Mit den oberen 8 bits vom Accu addressierst du deine Sinustabelle.
ISR Ende


Wenn du 100Hz haben willst, dann einfach
freq=100



Am Ausgang der DDS brauchst du in Hardware ein Filter höheren Grades.
Gast #2284633
Lesenswert?

@Knut

Ein langsamer Sinus  ist einer  dessen sämtliche Oberwellen durch das 
nachgeschaltete  Tiefpassfilter rutschen.

Bei einem  4bit R2R DAC generierten Sinus sollte man  die Oberwellen 
wohl  besser wegfiltern,  das klappt schlecht wenn der Sinus  zu 
niederfrequent ist.
#2286614
Lesenswert?

Martin1 schrieb:
> Ein langsamer Sinus  ist einer  dessen sämtliche Oberwellen durch das
> nachgeschaltete  Tiefpassfilter rutschen.

Ein Sinus hat keine Oberwellen. Du mußt nur alles oberhalb fs/2 
wegfiltern.

Die Störungen, die Du aufgrund fehlender Spannungsauflösung hast, sind 
keine Oberwellen. Wenn Du die beseitigen möchtest, solltest Du über ein 
16-Bit-System nachdenken.

Mit einem ATmega168 schafft man im übrigen bis zu 500kHz Signalfrequenz 
bei 8 Bit Auflösung.

Ach ja: Du solltest unbedingt dafür sorgen, das alle Bits gleichzeitig 
am DA-Wandler ankommen.


Gruß

Jobst
#2290044
Lesenswert?

peter schrieb:
> Ja meine Ich ja einen DA - Wandler.
> Anstatt das Widerstandsnetzwerk zu benutzen, kann doch bestimmt
> DA-Wandler ICs benutzen oder ?

Hallo Peter,

Das ist eine Frage des Typs des DA-Wandlers;
Die Auflöung ist wohl weniger bedeutend als die Geschwindigkeit,
wenn es ein Funktionsgenerator werden soll.

Geschwindikeit:
Insbesondere die, in welcher die Digital-Daten an den Wandler kommen.

Ein 8 Bit R2R-DAC dierekt am µc ist einfach und sehr schnell 
anzusteuern:
Ein Byte 1:1 an den Port und der neue Analogwert pendelt sich sogleich 
ein.

Mit SPI oder TWI (I2C) musst Du ersteinmal serielle Kommunokation
vorbereiten und ablaufen lassen,
ehe die Daten zu analog umgesetzt werden.
TWI ist im übrigen meist noch langsamer als SPI.

Wenn Du allerdings nur NF-Audio erzeugen möchtest,
so kann ich mir vorstellen,
dass Du sogar mit einem TWI-Typ noch zu einem Ergebniss kommst.

MFG:MBP
Markus.
Gast #2290116
Lesenswert?

peter schrieb:
> Anstatt das Widerstandsnetzwerk zu benutzen, kann doch bestimmt
> DA-Wandler ICs benutzen oder ?

Wenn du hohe Frequenze erzeugen willst, verringserst du durch zusätzlich 
Zeit, die du brauchst, um die Daten zum DAC zu übertragen, deine obere 
Grenzfrequenz.

Probier mal den miniDDS von Jesper mit 8-Bit R2R DA-Wandler (bis 
200..300 kHz je nach Quarz, Zykluszeit 9 Take auf ATmega8)
http://www.myplace.nu/avr/minidds/index.htm
#2290180
Lesenswert?

Michael schrieb:
> peter schrieb:
>> Anstatt das Widerstandsnetzwerk zu benutzen, kann doch bestimmt
>> DA-Wandler ICs benutzen oder ?
>
> Wenn du hohe Frequenze erzeugen willst, verringserst du durch zusätzlich
> Zeit, die du brauchst, um die Daten zum DAC zu übertragen, deine obere
> Grenzfrequenz.
>
> Probier mal den miniDDS von Jesper mit 8-Bit R2R DA-Wandler (bis
> 200..300 kHz je nach Quarz, Zykluszeit 9 Take auf ATmega8)
> http://www.myplace.nu/avr/minidds/index.htm

Hab mit Hilfe von Jesper das folgende gebaut:
http://www.elo-web.de/f-drabek
Habe absichtlich eine höhere Zykluszeit gewählt. Warum steht im Artikel.
#2290224
Lesenswert?

Jobst M. schrieb:
> Rudi D. schrieb:
>> http://www.elo-web.de/f-drabek
>
> 'Die modernste Art von RC-Generatoren ist zweifellos die Synthese mit
> einem digitalen Signalprozessor.'
>
> ... ist dann nur kein RC-Generator mehr ...
>
>
> Rudi D. schrieb:
>> Warum steht im Artikel.
>
> Und Du erwartest nun, daß die Leute Deinen Artikel kaufen?
>
>
> Gruß
>
> Jobst

Der Artikel kostet natürlich nichts.
Er ist auch noch bei elektronik-labor.de gelistet.
Gast #2300898
Lesenswert?

mbp schrieb:
> Ein 8 Bit R2R-DAC dierekt am µc ist einfach und sehr schnell
anzusteuern:
Ein Byte 1:1 an den Port und der neue Analogwert pendelt sich sogleich
ein

Kann jemand den Typ eines solchen R2R-DAC sagen?
#2302047
Lesenswert?

spess53 schrieb:
>
> CSD hat auch reine R2R-Widerstandsnetzwerke.

Das 1k Netzwerk ist zwar billig aber nicht so gut geeignet für direkte 
Anschaltung an Ports.
Die 10k Variante kann man IMHO mit genauen Widerständen aus der 
Schatzkiste billiger herstellen. Wenn man die nicht hat, dann das 10k 
Netzwerk kaufen, denke ich. Oder Widerstände ausmessen, was ja immer 
geht.
Gast #2309136
Lesenswert?

Hallo,
ich habe mir jetzt eien DAC 0808LCN besorgt.
http://www.datasheetcatalog.org/datasheet2/8/0iff6chuycj3uriy0x2ls8p5cwfy.pdf

nur weiss ich jetzt genau wie ich den anschließen muss. Digital in 
Inputs müsste ich ja 1:1 an mein PORTA anschließen können(PA0 -> A1,PA1 
-> A2, usw.).
Nur was ist mit VCC,Vref+,Vref- und VEE ich weis, dass es schon mehrere 
Beiträge zu diesem Thema gibt. Aber eine Antwort konnte ich daraus nicht 
gewinnen.

Wäre nett wenn ihr mir nochmal weiterhelfen könntet.
Gruß Peter
Gast #2320751
Lesenswert?

habe jetzt die schaltung nach figure 9 aufgebaut. nur das ich Vs 
weglassen habe.
ich will ja ein 22khz sinussignal erzeugen, nur ausgang ausgang bekomme 
jetzt 3MHZ sinussignal. habe ich irgendwie ein Frequenzbeschleuniger 
gebaut? weiß jemand woran das liegen könnte?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren