Forum: FPGA, VHDL & Co. DDS mit AM Modulation


von Commtel @. (commtel)


Lesenswert?

Hallo Forum,

zur Zeit beschäftigt mich mein Spartan3 in dem ein NCO realisiert wurde.
Daran angeschlossen ein 8 Bit D/A Wandler (DAC0800) an dem ein Sinus 
Signal mit 12 Vss am Ausgang sich messen läst.

Nun meine Frage wie bekomm ich die AM Modulation hin?

Klar DAC_out <= NCO Sinus * der Wert vom z.b A/D

Das Problem ist:
Vollaussteuerung = +-6Vss <= ist OK
Halbe            = 0V bis -6V <= sollte +-3V sein
viertel          = -3 bis -6V <= sollte +-1,5V

wenn ich nun ein addierer rein mach hab ich das Prob bei 
Vollaussteuerung.

Wer kann Helfen?

c.u
Commtel

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


Lesenswert?

> Nun meine Frage wie bekomm ich die AM Modulation hin?
Eine AM-Modulation ist wie ein LCD-Display   :-o
Nämlich doppelt gemoppelt:
Amplitudenmodulation-Modulation

> Nun meine Frage wie bekomm ich die AM Modulation hin?
Du solltest die Multiplikation signed machen (weil du ja auch -6V..+6V 
hast). Offenbar machst du es bisher unsigned und sagst dann 0 = -6V.

Aber ohne Code ist das nur Raten auf Raten... ;-)

von Commtel (Gast)


Lesenswert?

Hallo Lothar,

hier der Code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.math_real.all;
--library UNISIM;
--use UNISIM.VComponents.all;

entity DDS is
    Generic ( ADC_size : natural := 8;
             DAC_size : natural := 8;
             Phase0_Akku_Size : natural := 32;
          Freq0_Reg_Size : natural := 32;
          Phase0_Reg_Size : natural := 12
             );

    Port ( ADC_in : in  STD_LOGIC_VECTOR (ADC_size -1 downto 0);
          DAC_out : out  STD_LOGIC_VECTOR (DAC_size -1 downto 0);
           Clk : in  STD_LOGIC --16Mhz = 62,5ns
       );

end DDS;

architecture Behavioral of DDS is
 signal Phase0_Akkumulator : unsigned (Phase0_Akku_Size -1 downto 0) := 
(others=> '0');
 signal Freq0_Reg : unsigned (Freq0_Reg_Size -1 downto 0) := 
x"02000000";
 signal Phase0_Reg : unsigned (Phase0_Reg_Size-1 downto 0) := (others=> 
'0');
 signal Sigma0_Phase_Freq : unsigned (Phase0_Akku_Size -1 downto 0);

 signal DAC0_temp0 : signed (7 downto 0);
 signal DAC0_temp1 : signed (15 downto 0);
 signal DAC0_temp2 : signed (15 downto 0);
 signal DAC0_Amplitude : signed (7 downto 0);

 type Rom256x8 is array (0 to 255) of signed (7 downto 0);
 signal Sinus_Rom : Rom256x8 ;


begin
 process
  begin

    for i in 0 to 255 loop
       Sinus_Rom(i) <= to_signed(integer((sin(2.0*MATH_PI*real(i)/256.0) 
+1.0)*127.5),8);
    end loop;

  wait until rising_edge(Clk);
   DAC0_Amplitude <= signed(ADC_in);

    Phase0_Akkumulator <= Phase0_Akkumulator + Freq0_Reg;
   Sigma0_Phase_Freq <= Phase0_Akkumulator + Phase0_Reg;
   DAC0_temp1 <= (DAC0_temp0 - DAC0_Amplitude);
   DAC0_temp2 <= (DAC0_temp1 * DAC0_Amplitude) ;

   end process;
 --DAC_out <= STD_LOGIC_VECTOR(Sigma0_Phase_Freq(31 downto 24));
 --DAC_out <= 
STD_LOGIC_VECTOR(Sinus_Rom(to_integer(unsigned(Sigma0_Phase_Freq(31 
downto 24)))));
  DAC0_temp0 <= signed(Sinus_Rom(to_integer(signed(Sigma0_Phase_Freq(31 
downto 24)))));

  DAC_out <= STD_LOGIC_VECTOR(DAC0_temp2(15 downto 8));

end Behavioral;

Vielen Dank für deine Antwort leider hab ich es bis jetzt noch nicht 
ganz verstanden in welcher reihenfolge das gehen soll.

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


Lesenswert?

> signed(ADC_in);
Ist das so?
Ist ADC_in=x"00" wirklich 0V am Eingang
und ADC_in=x"80" der negativste Wert
und ADC_in=x"7F" der positivste Wert?


1
       Sinus_Rom(i) <= to_signed( integer( ( sin(2.0*MATH_PI*real(i)/256.0) +1.0) *127.5) ,8);
Was machst du denn hier mit dem  +1.0 ?
Damit wird doch dein ganzer Sinus doch in den positiven Bereich 
geschoben...

> Vielen Dank für deine Antwort leider hab ich es bis jetzt noch nicht
> ganz verstanden in welcher reihenfolge das gehen soll.
Gehe doch erst mal her und gib einfach mal einen Sinus aus. Und dann 
machst du deine Amplitudenmodulation (Multiplikation) genau dort, wo der 
Sinus auf DAC_out ausgegeben wird.

von Commtel @. (commtel)


Lesenswert?

> signed(ADC_in);
> Ist das so?
> Ist ADC_in=x"00" wirklich 0V am Eingang
> und ADC_in=x"80" der negativste Wert
> und ADC_in=x"7F" der positivste Wert?

nein natürlich nicht

ich hätte gern

ADC 0V = DAC x"7F" entspricht beim DAC0800 0V
ADC 2,5V = DAC x"7F" + dem Sinus +- 3F also DAC offset 7F - 3F und 7F + 
3F
ADC 5V = DAC X"7F" + dem Sinus +- 7F also DAC offset 7F - 7F und 7F + 7F


> Gehe doch erst mal her und gib einfach mal einen Sinus aus. Und dann
> machst du deine Amplitudenmodulation (Multiplikation) genau dort, wo der
> Sinus auf DAC_out ausgegeben wird.

Lothar das geht ja auch
z.b FF kommt vom ADC und ich bekommt 00 bis FF Sinus
    7F vom ADC bekomm ich die hälfte an Sinus ist ja auch OK
    aber an den DAC wird 00 bis 7F gesendet was dem Bereich
    -6 bis 0 entspricht.
Es sollten aber +3 bis -3V sein das muß doch möglich sein ?

Mfg
Commtel

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


Lesenswert?

> nein natürlich nicht.
> ich hätte gern...
Du hast meine Frage nicht beantwortet.
Ich möchte nicht wissen, was du gerne hättest, sondern was du hast.

>>> Spartan3 in dem ein NCO realisiert wurde.
>>> Vollaussteuerung = +-6Vss <= ist OK
Also, ist doch schön, wenn das funktioniert.
Dann mußt du doch nur noch ein klitzeklein wenig verstehen was da gerade 
passiert und danach auch nur eine Klitzekleinigkeit ändern.

Was mußt du (ganz ohne AM und ADC) am DAC ausgeben, um -6V zu erhalten?
Was, um 0V zu erhalten und was, um +6V zu erhalten?
Kontrollier doch mal die Tabellen und korrigier die Werte ggfs.:
DAC-Wert  Ausgangsspannung
  0x00        -6V ?
  0x7f        -0V ?
  0x80        +0V ?
  0xff        +6V ?


> ADC 0V = DAC x"7F" entspricht beim DAC0800 0V
> ADC 2,5V = DAC x"7F" ....
> ADC 5V = ...
Wieso steht hier jetzt was von 0V und 2,5V und 5V?
Wie passt das jetzt schon wieder auf die -6V...+6V?

Und wenn wir schon am definieren sind, dann zeig doch mal die 
Wandlungsfunktion des ADCs:
Eingangsspannung     ADC-Wert
  0V                   0x00 ?
  2,5V                 0x80 ?
  5V                   0xFF ?

von Commtel @. (commtel)


Lesenswert?

> Was mußt du (ganz ohne AM und ADC) am DAC ausgeben, um -6V zu erhalten?
> Was, um 0V zu erhalten und was, um +6V zu erhalten?
> Kontrollier doch mal die Tabellen und korrigier die Werte ggfs.:
> DAC-Wert  Ausgangsspannung
>  0x00        -6V ?
>  0x7f        -0V ?
>  0x80        +0V ?
>  0xff        +6V ?

Genau so ist die Ausgabe

> ADC 0V = DAC x"7F" entspricht beim DAC0800 0V
> ADC 2,5V = DAC x"7F" ....
> ADC 5V = ...
> Wieso steht hier jetzt was von 0V und 2,5V und 5V?
> Wie passt das jetzt schon wieder auf die -6V...+6V?

> Und wenn wir schon am definieren sind, dann zeig doch mal die
> Wandlungsfunktion des ADCs:
> Eingangsspannung     ADC-Wert
>  0V                   0x00 ?
>  2,5V                 0x80 ?
>  5V                   0xFF ?

nochmals genau wobei ich die Eingänge des FPGA s jetzt als PullUP 
defeniert sind und ich die 0x80 über Schiebeschalter einstell.

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


Lesenswert?

> Genau so ist die Ausgabe
Dann ist es doch gar nicht so schwer:
1) du berechnest mit der DDS deinen DAC-Wert (der ist unsigned!!!!)
2) du ziehst den Offset 0x80 ab (jetzt ist er signed)
3) du multiplizierst den erhaltenen Wert mit dem ADC-(Dipschalter-)Wert
4) du addierst wieder den Offset von 0x80 drauf
5) du gibst den Wert an den DAC aus

von Commtel @. (commtel)


Lesenswert?

meinst du so?

 signal DAC0_temp0 : unsigned (7 downto 0);
 signal DAC0_temp1 : unsigned (7 downto 0);
 signal DAC0_temp2 : unsigned (15 downto 0);
 signal DAC0_temp3 : unsigned (15 downto 0);
 signal DAC0_Amplitude : unsigned (7 downto 0) ;

 type Rom256x8 is array (0 to 255) of signed (7 downto 0);
 signal Sinus_Rom : Rom256x8 ;


begin
 process
  begin

    for i in 0 to 255 loop
       Sinus_Rom(i) <= to_signed(integer((sin(2.0*MATH_PI*real(i)/256.0) 
+1.0) *127.5),8);
    end loop;

  wait until rising_edge(Clk);
   DAC0_Amplitude <= unsigned(ADC_in);

    Phase0_Akkumulator <= Phase0_Akkumulator + Freq0_Reg;
   Sigma0_Phase_Freq <= Phase0_Akkumulator + Phase0_Reg;

   DAC0_temp1 <= (DAC0_temp0 - x"80");
   DAC0_temp2 <= (DAC0_temp1 * DAC0_Amplitude) ;
   DAC0_temp3 <= (DAC0_temp2 + x"8000");

   end process;

  DAC0_temp0 <= 
unsigned(Sinus_Rom(to_integer(unsigned(Sigma0_Phase_Freq(31 downto 
24)))));

  DAC_out <= STD_LOGIC_VECTOR(DAC0_temp3(15 downto 8));

end Behavioral;

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


Lesenswert?

Das sieht schon ganz gut aus, ich würde allerdings noch prüfen, ob das 
Pipelining im Prozess nötig ist.
Komplett registriert (mit 4 Takten Latency):
1
 process begin
2
   wait until rising_edge(Clk);
3
   DAC0_Amplitude <= unsigned(ADC_in);
4
5
   Phase0_Akkumulator <= Phase0_Akkumulator + Freq0_Reg;
6
   Sigma0_Phase_Freq <= Phase0_Akkumulator + Phase0_Reg;
7
8
   DAC0_temp0 <= unsigned(Sinus_Rom(to_integer(unsigned(Sigma0_Phase_Freq(31 downto 24)))));
9
   DAC0_temp1 <= (DAC0_temp0 - x"80");
10
   DAC0_temp2 <= (DAC0_temp1 * DAC0_Amplitude) ;
11
   DAC0_temp3 <= (DAC0_temp2 + x"8000");
12
   DAC_out <= STD_LOGIC_VECTOR(DAC0_temp3(15 downto 8));
13
 end process;
Concurrent:
1
 process begin
2
    :
3
    wait until rising_edge(Clk);
4
    DAC0_Amplitude <= unsigned(ADC_in);
5
    Phase0_Akkumulator <= Phase0_Akkumulator + Freq0_Reg;
6
    Sigma0_Phase_Freq <= Phase0_Akkumulator + Phase0_Reg;
7
8
 end process;
9
10
 DAC0_temp0 <= unsigned(Sinus_Rom(to_integer(unsigned(Sigma0_Phase_Freq(31 downto 24)))));
11
 DAC0_temp1 <= (DAC0_temp0 - x"80");
12
 DAC0_temp2 <= (DAC0_temp1 * DAC0_Amplitude) ;
13
 DAC0_temp3 <= (DAC0_temp2 + x"8000");
14
 DAC_out <= STD_LOGIC_VECTOR(DAC0_temp3(15 downto 8));
Simulier doch einfach mal beide Varianten und schau nach, was jeweils 
passiert... ;-)

von Commtel @. (commtel)


Angehängte Dateien:

Lesenswert?

So Cam funzt endlich.

Hallo Lothar erst mal vielen Dank für deine Mühe.
Wie du siehst (hoffe Anhang kommt mit) geht es leider immer noch nicht

Das Signal fängt bei Offset 0x80 an.
Entschuldige bitte die schlechte Quali.
Hoffe du kannst was damit anfangen

von Commtel @. (commtel)


Lesenswert?

Achso beide Codes haben das gleiche Ergebnis auf dem Oszi.

Gedanklich wäre es ja perfekt gewesen das Signal um die Nullachse 
wandern zu lassen und den Offset dazuaddieren.

Ich hab mir ja auch von c't den DDS Code angesehen.
Die machen ein XOR nach der Tabellenausgabe.

Ich vermute wir sollten die "Lookup" Tabelle ändern.
Leider komm ich mit deiner Sinus_Rom(i) <= 
to_signed(integer((sin(2.0*MATH_PI*real(i)/256.0)+1.0) *127.5),8);
nicht ganz mit.

Mfg

Commtel

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


Lesenswert?

Ich hatte erwartet, dass genau dieses Signal aus deiner DDFS 
herauskommt. Denn du initialiisert ein signed-Array mit einem Offset 
(meine Frage im Beitrag "Re: DDS mit AM Modulation"). 
Lass doch mal das +1.0 raus...
1
 Sinus_Rom(i) <= to_signed( integer( sin(2.0*MATH_PI*real(i)/256.0)  *127.5) ,8);
2
                                              -1...+1                 *127

Dann hast du einen 8 Bit breiten signed Sinus. Und der braucht für die 
Ausgabe dann nur noch die Skalierung mit dem ADC-(Dipschalter-)Wert und 
anschliessend die Addition von 0x80 für die Ausgabe von 0V, wenn auch 
die DDFS 0 ausgibt.

von Commtel @. (commtel)


Angehängte Dateien:

Lesenswert?

ok hab ich

nun mit einem Nadelimpuls nach unten

von Rick Dangerus (Gast)


Lesenswert?

Commtel @msn schrieb:
> Nadelimpuls nach unten

Gib Dir doch mal im Simulator alle Werte aus. Vielleicht erfolgt an der 
Stelle des Nadelpulses ein Überlauf?

Rick

von Commtel @. (commtel)


Angehängte Dateien:

Lesenswert?

Hallo Rick Dangerus,

freu mich einen weiteren Mitstreiter in der Runde zu haben

Der Nadelimpuls ist was ich gerade feststelle unabhängig von 
DAC0_Amplitude.
Aber der Impuls ist jetzt weniger das Problem sondern das die Regelung 
immer noch nicht tut.
Amplitude fängt bei 0x7F an * Schalterstellung 0x3F

von Commtel @. (commtel)


Lesenswert?

DAC_Out(Foto)
Schalter 0xFF

von Commtel @. (commtel)


Angehängte Dateien:

Lesenswert?

m**t Foto

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


Lesenswert?

> m**t Foto
Aber noch ohne deinen aktuellen Quelltext.


BTW:
die Idee mit der Simulation ist übrigens wirklich nicht schlecht  :-o
Das kann man alles super gut simulieren, und man sieht gleich ob das 
Verfahren prinzipiell klappt.

von Rick Dangerus (Gast)


Lesenswert?

Hast Du denn eine Testbench für Deinen Code? Dann könnte man das ganz im 
heimischen Simulator mal durchspielen.

Deinen DAC kann man ja als Verhaltensmodell nachbilden. Er schreibt dann 
alle Werte in eine Datei. Und für den ADC kann man sich auch was 
geeignetes einfallen lassen. z.B. einen Rampengenerator.

Rick

von Commtel @. (commtel)


Lesenswert?

Nun nicht direkt ich hab Modelsim 6.5 das ich aus ISE 11.4 herraus 
starte.
In Modelsim bin ich noch neu daher weis ich jetzt nicht ob da eine Datei 
erzeugt wird die ihr benutzen könnt.

Ich war die ganze Zeit am Überlegen ob es nicht möglich ist
Halbwellen zu erzeugen diese mit dem Offset zu versehen dann zu 
multiplizieren und jede 2. umzuklappen.

Bleibt die Frage offen ob das mit anderen Signalformen auch möglich ist.

@ Lothar der aktuelle Code ist das was du vorgeschlagen hast.

von Commtel @. (commtel)


Lesenswert?

Achso der Peak ist jetzt weg

 Sinus_Rom(i) <= to_signed( 
integer(sin(2.0*MATH_PI*real(i)/256.0)*127.5),8);

geändert zu

  Sinus_Rom(i) <= 
to_signed(integer(sin(2.0*MATH_PI*real(i)/256.0)*127.0),8);

sorry Admin für dieses Doppelpost wie man merkt bin ich in Gedanken 
wieder beim Code.
Ich versuch es zu vermeiden in Zukunft

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


Lesenswert?

> @ Lothar der aktuelle Code ist das was du vorgeschlagen hast.
Naja, ich habe so viel vorgeschlagen...

> Achso der Peak ist jetzt weg
Aber dafür ist der Minimalwert nur -127  (möglich wäre -128)   :-o
Besser wäre  integer(sin(2.0*MATH_PI*real(i)/256.0)*127.5-0.5)

von Commtel @. (commtel)


Angehängte Dateien:

Lesenswert?

Jungs ihr dürft die Hosen runter lassen LOL

begin
 process
  begin

    for i in 0 to 255 loop
       Sinus_Rom(i) <= to_signed(integer(sin(2.0*MATH_PI*real(i)/256.0) 
*127.5 -0.5),8);
    end loop;

  wait until rising_edge(Clk);
  DAC0_Amplitude <= unsigned(ADC_in);

   Phase0_Akkumulator <= Phase0_Akkumulator + Freq0_Reg;
   Sigma0_Phase_Freq <= Phase0_Akkumulator + Phase0_Reg;

  DAC0_temp0 <= 
unsigned(Sinus_Rom(to_integer(unsigned(Sigma0_Phase_Freq(31 downto 
24)))));

   DAC0_temp2 <= (DAC0_temp1 * DAC0_Amplitude) ; -- Gain z.b vom A/D
   DAC0_temp3 <= (DAC0_temp2 + x"8000"); --Offset (0 Linie)

  if DAC0_temp0(7) = '1' then --Sinus "Gleichrichten"
   DAC0_temp1 <= not (DAC0_temp0);
  else
    DAC0_temp1 <= DAC0_temp0;
   end if;

   if DAC0_temp0(7) = '1' then --Sinus "umklappen"
   DAC0_temp4 <= not (DAC0_temp3);
  else
    DAC0_temp4 <= DAC0_temp3;
   end if;

  DAC_out <= STD_LOGIC_VECTOR(DAC0_temp4(15 downto 8));
   end process;
end Behavioral;

Es geht mit einem aber.
Kleine Peaks an den null durchgängen (0x80).
Latency??

4 Tage google mit Kopfzerbrechen

Darauf ein Bier

von Thorsten S. (thosch)


Lesenswert?

Commtel @msn schrieb:
> Ich war die ganze Zeit am Überlegen ob es nicht möglich ist
> Halbwellen zu erzeugen diese mit dem Offset zu versehen dann zu
> multiplizieren und jede 2. umzuklappen.

Natürlich ist das möglich.
Aber es geht auch mit einem Viertel des Speichers als Lookup-Table bzw. 
mit der 4-fachen Phasenauflösung bei gleichem Speicherverbrauch:

Es genügt völlig, eine Viertelwelle der Sinusfunktion zu speichern.
Die Tabelle wird dann mit den Quadranten abwechselnd vorwärts und 
rückwärts ausgelesen, und im 3. und 4. Quadranten wird zusätzlich das 
Vorzeichen des Ausgangs umgekehrt.


So erreichst Du die 4-fache Phasenauflösung mit einer 8-Bit Adresse für 
die Lookup-Table:

Sigma0_Phase_Freq[31..22] liefert insgesamt die Adresse für die 
Sinuswelle.

Sigma0_Phase_Freq[31] ist ist das Vorzeichen für den Ausgangswert, wenn 
dieses Bit 1 ist, muß der Ausgang negiert werden.

Sigma0_Phase_Freq[30] bestimmt, wie die unteren Bits die Adresse für die 
Lookup-Table liefern:

Wenn Bit30 = 0 ist, liefert Sigma0_Phase_Freq[29..22] die Adresse 
direkt.

Wenn Bit30 = 1 ist, wird (255 - Sigma0_Phase_Freq[29..22]) als Adresse 
an die Lookup-Table geliefert und damit die Ausleserichtung umkekehrt.

Jetzt muß nur noch die Tabelle mit der passenden Viertelwelle geladen 
werden: Die Sinuswerte der Tabelle müssen symmetrisch zwischen Maximum 
und Nulldurchgang liegen, also in der Phase um einen Offset von 1/2 der 
Phasenauflösung verschoben.

also:
1
for i in 0 to 255 loop
2
  Sinus_Rom(i) <= to_signed(integer(sin((0.5*MATH_PI*real(i)/256.0)+(0.5*MATH_PI/512.0))*127.0),8);
3
end loop;

Habe derartige Generatoren bereits praktisch realisiert, allerdings 
nicht in VHDL, sondern in Schematic-Entry...
Meiner läuft bei einer Abtastrate von 27MHz mit 13 Bit Phasenauflösung 
sowie 16 Bit Ausgangssignal.
Allerdings mit einem Takt von 108MHz, so daß ich aus dem einen Generator 
4 Signale erhalte: Sinus und Cosinus jeweils einmal frequenzmoduliert 
und unmoduliert.
Fittet problemlos in einem Spartan 3AN mit Speedgrade -4.

Gruß,
Thorsten

von Thorsten S. (thosch)


Lesenswert?

Lothar Miller schrieb:
> Aber dafür ist der Minimalwert nur -127  (möglich wäre -128)   :-o
> Besser wäre  integer(sin(2.0*MATH_PI*real(i)/256.0)*127.5-0.5)

Damit hast Du aber einen DC-Offset, würde ich von daher nicht empfehlen.

von Commtel @. (commtel)


Lesenswert?

Hallo Thorsten S. ,

auch du hertzlich Willkommen.Dein Generator gefällt mir. :-)

Ja dieses Prinzip mit der Viertelwelle hab ich im c't DDS Generator 
gesehen.

Ich frag mich gerade ob dieses Prinzip auch für andere Signalformen in 
Verbindung mit der Verstärkung funktioniert.

Hast du das Erfahrung z.b Sägezahn mit Rückwärtszählen wird da nix.

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


Lesenswert?

> Damit hast Du aber einen DC-Offset, würde ich von daher nicht empfehlen.
Das kommt auf den DAC an. Mit -127 bis +127 hast du auf jeden Fall 1 LSB 
verloren.

>> Ich war die ganze Zeit am Überlegen ob es nicht möglich ist
>> Halbwellen zu erzeugen diese mit dem Offset zu versehen dann zu
>> multiplizieren und jede 2. umzuklappen.
> Es genügt völlig, eine Viertelwelle der Sinusfunktion zu speichern.
Hier meine Lösung mit dem Viertel-Sinus:
http://www.lothar-miller.de/s9y/categories/31-DDFS

EDIT:
>> Ich frag mich gerade ob dieses Prinzip auch für andere Signalformen in
>> Verbindung mit der Verstärkung funktioniert.
Bei Sinus-, Dreieck- und anderen Punktsymmetrischen Wellenformen geht 
das.

von Commtel @. (commtel)


Lesenswert?

@  Lothar Miller

wär vieleicht ein weiterer Artikel für deine Seite AM Modulation.
Wie gesagt beim googeln hab ich nix dergleichen gefunden.

Ich werd jetzt mal versuchen ein weiteren Weg der AM Modulation zu 
testen.
Positive Halbwellen werden durch Multiplikation weitergegeben.
Negative werden durch Multiplikation subtrahiert.

Mfg
Commtel

von Commtel @. (commtel)


Lesenswert?

EDIT:
Mir ist gerade aufgefallen das die Peaks bei meinem Code in den 
Nulldurchgängen nicht von meinem Code kommen.
Liegt woll eher an meinem Aufbau.

von Thorsten S. (thosch)


Lesenswert?

Commtel @msn schrieb:
> Hast du das Erfahrung z.b Sägezahn mit Rückwärtszählen wird da nix.

für'n Sägezahn kannst Du das ROM weglassen. Die Adresse (die oberen Bits 
vom Phasenakku + Phasenoffset) liefern direkt einen Sägezahn. Da mußt Du 
für vorzeichenbehaftete Werte nur den Offset subtrahieren, also bei 8 
Bit Werten -0x80.


Für alle unsymmetrischen Signalformen benötigt man (mindestens) ein ROM 
mit eienr Vollwelle des Signals.

Da man für Mischer, Quadraturmodulatoren oder -Demodulatoren aber 
normalerweise nur Sinus und Cosinus benötigt ist das Sparkonzept mit dem 
Viertelwellen-ROM hier ressourcenschonend einsetzbar.

Gruß,
Thorsten

von Thorsten S. (thosch)


Lesenswert?

Commtel @msn schrieb:
> Ich werd jetzt mal versuchen ein weiteren Weg der AM Modulation zu
> testen.
> Positive Halbwellen werden durch Multiplikation weitergegeben.
> Negative werden durch Multiplikation subtrahiert.

Die Beschreibung irritiert mich jetzt etwas. Hört sich für mich nicht so 
an, als käme damit eine AM heraus...

Ein normaler Amplituden-Modulator arbeitet als Multiplizierer signed x 
unsigned. Die Modulation darf keine Trägerphasen-Umkehrung bewirken, der 
Modulationsgrad ist stets < 100%, damit ein minimaler Restträger 
erhalten bleibt.

Das Trägersignal (Sinusschwingung aus dem DDFS) kommt an den 
Signed-Input des Multilplizierers, die Modulation muß als unsigned 
vorliegen (ein normales signed-Audiosignal wäre dementsprechend mit 
einem Offset in Höhe des MSB zu versehen).

Der Offset sorgt auch dafür, daß der Träger mit halber Maximalamplitude 
am Ausgang erscheint, wenn das Modulationssignal Null ist.


Eine signed x signed Multiplikation des Modulationssignals mit dem 
Träger bewirkt eine Trägerunterdrückung. Ohne Modulationssignal gibts 
kein Ausgangssignal; bei Modulation erscheinen nur die Seitenbänder am 
Ausgang.
Wenn man jetzt noch durch einen passenden Bandpaß das obere oder untere 
Seitenband ausfiltert, hat man einen SSB-Sender.

Gruß,
Thorsten

von Commtel @. (commtel)


Lesenswert?

Hallo Thorsten

hast du was mit Funktechnik zu tun?
Wo finde ich ähnliche Projekte wie das was du beschreibst?
Eventuell als VHDL Code oder wer hat ein Link.

von Thorsten S. (thosch)


Lesenswert?

Commtel @msn schrieb:
> hast du was mit Funktechnik zu tun?
nicht direkt. Bin in früher Jugend durch Radiobasteln zur Elektronik 
gekommen...
Interesse habe ich auch noch am Amateurfunk, bin nur bislang vor allem 
aus Zeitgründen nie dazu gekommen, die Prüfung abzulegen.
Beschäftige mich beruflich u.a. mit digitaler Signalverarbeitung.

> Wo finde ich ähnliche Projekte wie das was du beschreibst?
> Eventuell als VHDL Code oder wer hat ein Link.
Damit kann ich leider nicht dienen...
Ein paar gute Hinweise zur Amplitudenmodulation, kannst Du aus dem 
entsprechenden Wikipedia-Artikel entnehmen:
http://de.wikipedia.org/wiki/Amplitudenmodulation

AM mit unterdrücktem Träger: 
http://de.wikipedia.org/wiki/Amplitudenmodulation_mit_unterdr%C3%BCcktem_Tr%C3%A4ger

SSB: http://de.wikipedia.org/wiki/Einseitenbandmodulation


Was hast Du mit Deinem Oszillator eigentlich vor?

Gruß,
Thorsten

von Commtel @. (commtel)


Lesenswert?

Es sollte später mal ein Arbiträr-Funktionsgenerator werden.
Um erst mal erfahrungen zu sammeln hab ich den DAC0800 
gewählt(Krustelkiste gefunden).
Sinusausgabe hat ja im ersten Durchlauf funktioniert FM 
(Schiebeschalter) auch.
Tja dacht ich mir AM sollt auch ganz einfach sein. ;-)
Nun gut aber so richtig zufireden bin ich mit meiner Lösung noch nicht.

Die Links sind mir bekannt und auch
http://www.mikrocontroller.net/attachment/70196/sinus.txt

> Interesse habe ich auch noch am Amateurfunk, bin nur bislang vor allem
> aus Zeitgründen nie dazu gekommen, die Prüfung abzulegen.

so geht es mir leider auch.

Was genau machst du mit deinem Funktionsgernerator?
Ist der fix fertig mit Tastatur,Endstufe in einem Gehäuse?

Schönen Sontag euch allen.

c.u
Commtel

von Thorsten S. (thosch)


Lesenswert?

Commtel @msn schrieb:
> Was genau machst du mit deinem Funktionsgernerator?
> Ist der fix fertig mit Tastatur,Endstufe in einem Gehäuse?
Nein, der dient nicht als Funktionsgenerator...
Der Oszillator ist nur ein kleiner Building-Block in einem
größeren Design, dient dort als Farbträgeroszillator in einem 
volldigitalen Videoencoder, der alle gängigen Standards ausgeben kann.

In meiner Freizeit beschäftige ich mich u.a. mit der Entwicklung eines 
leistungsfähigen Ultraschalldetektors zur Fledermausbeobachtung...

Die Ultraschallsignale werden in einem Multiplizierer mit dem 
Sinussignal aus dem Oszillator gemischt, (signed x signed) so daß am 
Ausgang nur die Summen- und Differenzfrequenz von Ultraschallsignal und 
Oszillator erscheinen.  Das Signal wird Tiefpaß-gefiltert, so daß nur 
die Differenzfrequenz übrig bleibt.
Damit lassen sich die Ultraschallsignale hörbar machen.

Gruß,
Thorsten

von Commtel @. (commtel)


Lesenswert?

Fledermausbeobachtung?
Auch nicht schlecht.

von Commtel @. (commtel)


Angehängte Dateien:

Lesenswert?

Wer noch mitliest für den hab ich noch was ähnliches gefunden.
Leider komm ich in nächster Zeit nicht mehr dazu.

Mfg
Commtel

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.