www.mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP PSK 31 Modlulation im Mikrocontroller


Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kennt jemand das PSK31 Verfahren zu Datenübertragung über einen 
Analogkanal?

http://de.wikipedia.org/wiki/PSK31

Ich frage mich, ob man dieses Prinzip in einem Atmega8 oder ähnlichem 
implemetieren könnte.
Nach einiger Überlegung bin ich der Meinung, dass es geht, wenn man 
Tricks wie Abtastratenreduktion usw. anwendet.

Mir ist noch unklar, wie die Zeichenkodierung funktioniert.
Irgendwie muss man sich auf die Phase synchronisieren um zu erkennen, ob 
eine 1 oder eine 0 übertragen wird. Daher meine Vermutung: die 
Information kann eigenlich nur im Phasenwechsel kodiert sein.

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es schon, ein ATmega als PSK31-Decoder und Encoder mit einem 
inzwischen nicht mehr lieferbarem Display von Pollin:

http://www.aatis.de/content/aatis-bei-der-ham-radio-2008
"...Am gleichen Stand werden Workshops zum Aufbau eines einfachen und 
preisgünstigen PSK31-Controllers angeboten, so dass Sende- und 
Empfangsbetrieb ohne Einsatz eines PCs oder Notebooks durchgeführt 
werden kann. Der Transceiver muss dabei eine Abstimmung von 10Hz 
ermöglichen. Es wird nur eine PC-Tastatur mit deutschem Zeichensatz 
benötigt. Jeweils bis zu zwölf Interessenten können täglich um 9.30 Uhr 
und um 13.30 Uhr unter Anleitung diese Schaltung aufbauen."

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klingt interessant. Schade, dass es nicht mehr Informationen gibt: Ist 
ein externer AD-Wandler eingebaut? Ist die Schaltung wirklich 
mimimalistisch, also nur Atmega und Display?
Vor allen Dingen: wie ist die Signalverarbeitung umgesetzt? Ist 
tatsächlich ein I/Q Mischer implementiert?

Noch eine andere Frage: kann man mit einem Weltempfänger auf irgendeinem 
Band solche Signale empfangen?

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So sieht die Schaltung und das Blockdiagramm aus. Es gibt einen Artikel 
dazu im Praxisheft 18.

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anscheinend kann ich nicht nachträglich eine zweite Datei anhängen, hier 
das Blockdiagramm aus dem Artikel.

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PSK31 ist im Internet ausführlichst bis ins letzte Detail dokumentiert.
Einfach nach "PSK31" googeln und lesen. :-)

Kostenlose PSK31-Software auf dem PC installieren, SSB-Weltempfänger mit
der Soundkarte verbinden, PSK31-Frequenz einstellen. Fertsch! :-)

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Christoph,

vielen Dank für die Unterlagen. Beim Durchsehen des Schalplans meine ich 
Optimierungsmöglichkeiten zu erkennen:

Den R2R DAC könnte man durch eine einfach PWM mit RC-Tiefpass ersetzen. 
Das würde Bauteile spaaren. Ausserdem könnte man den nachfolgenden 
Verstärker weglassen und statt dessen eine AGC im Eingangszweig 
implementieren.

Auf der Softwareseite ist mir noch nicht ganz klar, warum da eine FFT 
implementiert ist. Um die Phase zu bestimmen, ist die nicht notwendig, 
oder?

marc

Autor: Bernd Wiebus (berndwiebus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo marc.

> Den R2R DAC könnte man durch eine einfach PWM mit RC-Tiefpass ersetzen.
> Das würde Bauteile spaaren.

Vorsicht! PSK31 soll auch schmalbandig sein. Wenn Du irgendwelche 
Artefakte, Nichtlinearitäten oder gar Reste vom Takt auf dem Signal 
hast, funktioniert Deine Übertragung möglicherweise noch, aber Du störst 
andere mit dem breitbandigen Störnebel, und letztlich wird Deine 
Leistungsbilanz auch mies. In Bezug auf Linearität des Audiozuges ist 
PSK31 relativ anspruchsvoll.


Also an dem Punkte GUT FILTERN!


> Auf der Softwareseite ist mir noch nicht ganz klar, warum da eine FFT
> implementiert ist. Um die Phase zu bestimmen, ist die nicht notwendig,
> oder?

Es gibt PSK 31 Phasenumtastung mit 180 Grad, aber eben auch mehrfach mit 
90 Grad.
Ersteres ist langsamer, aber störfester, zweites empfindlicher aber 
schneller, weil du eine höhere Anzahl von Zuständen überträgst bei 
gleichem Takt.
Es gibt auch noch Varianten mit schnellerem oder langsamerem Takt.
Ausserdem willst Du eventuelle Frequenzabweichungen noch ausgleichen 
können.....
FET könnte Dir dafür die Parameter liefern.

Die Problematik solcher Stand allone Lösungen ist meist die 
Abstimmanzeige....oder Du brauchst eine NF-AFC. Die wird aber 
möglicherweise von benachbarten  Stationen (insbesondere wenn sie 
breitbandig sind) schon beinflusst.


Mit freundlichem Gruß: Bernd Wiebus alias dl1eic

http://www.dl0dg.de

Selbsterkenntnis ist der erste Schritt zur Depression.
Jeder echte Wettbewerb ist ruinös. Darum beruht jede funktionierende 
Wirtschaft auf Schiebung.

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Den R2R DAC könnte man durch eine einfach PWM mit RC-Tiefpass ersetzen.
>> Das würde Bauteile spaaren.

>Vorsicht! PSK31 soll auch schmalbandig sein. Wenn Du irgendwelche
>Artefakte, Nichtlinearitäten oder gar Reste vom Takt auf dem Signal

In einem Beispiel für ein PSK31 Signal habe ich eine Signalfrequenz von 
1600Hz gesehen. Wenn man eine PWM Frequenz von 32Khz nimmt und einen 
doppelten RC Tiefpass nachschaltet dürfte der Noise flor deutlich 
kleiner 46dB sein. Ich würde vermuten, dass das sogar eine besseres 
Ergebnis als beim R2R DAC mit seinen toleranzbehafteten Widerständen 
ist.

Autor: Bernd Wiebus (berndwiebus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo marc.

> In einem Beispiel für ein PSK31 Signal habe ich eine Signalfrequenz von
> 1600Hz gesehen. Wenn man eine PWM Frequenz von 32Khz nimmt und einen
> doppelten RC Tiefpass nachschaltet dürfte der Noise flor deutlich
> kleiner 46dB sein. Ich würde vermuten, dass das sogar eine besseres
> Ergebnis als beim R2R DAC mit seinen toleranzbehafteten Widerständen
> ist.

Das ist Richtig. Du must halt nur darauf achten. PSK31 ist eben nicht in 
dem Sinne "digital", als das Du meinst, Du hättest auf unterster Ebene 
nur mit "High/Low" zu tun.

Mit freundlichem Gruß: Bernd Wiebus alias dl1eic

http://www.dl0dg.de

Selbsterkenntnis ist der erste Schritt zur Depression.
Jeder echte Wettbewerb ist ruinös. Darum beruht jede funktionierende
Wirtschaft auf Schiebung.

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Um die Schwächen und Stärken des Verfahrens besser zu verstehen, möchte 
ich das ganze simulieren.
Für die Simulation benutze ich Octave ( die freie Version von Matlab ).

Ich habe die Modulation des Sendesignals modelliert. Die 
Modulationsfrequenz und Baudrate kann mit den Variblen verändert werden.

Als nächstes ist das Kanalmodell an der Reihe. Dort weiß ich noch nicht, 
wie es realistischerweise aussehen sollte. Ich werde wohl mit einem 
einfachen Rauschoffset beginnen.
% modulation frequency [Hz ]
fmod=1000;
% sample frequency of the system [Hz]
fs=20000;
% bit rate ( Baud [1/s])
baud=31;

%bits to be transmitted
bits=[0 1 0 1];

bittime=1/baud;
sendtime=length(bits)*bittime;

% samples n
n=1:sendtime*fs;

phases=[];
onebitsamples=bittime*fs;

% phase 180 degree
phase180=fs/fmod/2;

% generate phase vektor
for bitcount=1:length(bits)
  for kk=1:onebitsamples
        phases=[phases bits(bitcount)*phase180];
  endfor
endfor

%plot(phases);

envelope=abs(sin(pi*baud/fs*n));
signal=sin(2*pi*fmod/fs*(n+phases));
modulatedSignal=envelope.*signal;

plot(modulatedSignal);
grid on

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier mein erster Versuch für den Demodulator:

Das Empfangssignal wird mit der Modulationsfrequenz gemischt
signalMixed=modulatedSignal.*exp(i*2*pi*fmod/fs*n); 
und danach mittels eines einfache RC-Tiefpassmodels gefiltert.
Der einpolige Filter wird deshalb verwedet, weil er sich auf einem 
Atmega8 mit einer Addion und einem Schiebebefehl realisieren lässt und 
damit sehr wenig Rechenzeit verbraucht.
Im Diagramm sieht man den Realteil und den Imaginärteil des 
ungefilterten und gefilterten Signals.
Wie man sieht, findet sich die Modulationsinformation im Imaginärteil 
des Signals wieder ( durch die Berechnung sind die Vektoren 
synchronisiert, das ist in Wirklichkeit nicht gegeben ).
Allerdings sind die Ripple auf den gefilterten Signalen noch ziemlich 
groß, deshalb bin ich mir nicht sicher, ob nicht deutlich bessere Filter 
notwendig sind.
Hat jemand eine Idee für einen recheneffizienten Tiefpass?


Folgende Einstellungen wurden verwendet
% modulation frequency [Hz ]
fmod=1000;
% sample frequency of the system [Hz]
fs=20000;
% bit rate ( Baud [1/s])
baud=250;

%bits to be transmitted
bits=[0 1 1 0 1];


Kode für Mischer und Tiefpassfilter
%############# demodulation ###################################

signalMixed=modulatedSignal.*exp(i*2*pi*fmod/fs*n);

%corner frequency of lowpass
fg=200;
%simple RC-lowpass
a=2*pi*fg/fs;
B=a;
A=[1 a-1];
% filter signal with IIR-Filter ( RC-low pass modell )
signalFiltered=filter(B,A,signalMixed);

subplot(2,1,1)
plot(real(signalMixed));
hold on
plot(real(signalFiltered),'g');
hold on
subplot(2,1,2)
plot(imag(signalMixed));
hold on
plot(imag(signalFiltered),'g');
hold on
grid on


Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Um das Signal noch besser zu Filtern, habe ich einen Moving Average 
Filter und den RC-Tiefpass kombiniert. Die Länge des Moving Average 
Filters entspricht genau der halben Modulationsfrequenz, dadurch wird 
das heruntergemischte Modulationssignal ideal unteredrückt, da sich 
genau an der Stelle der Modulationsfrequenz die Nullstelle des Moving 
Average Filters befindet. Das Ergebnis ist super, wie in den Diagrammen 
zu sehen :-)

Zur Rückgewinnung des Signals habe ich einfach die Phase aus dem I und Q 
Anteil berechnet und siehe da: Die Phase zeigt sich als sehr stabil.
% phase plotten ( rote Farbe )
plot(angle(signalFiltered),'r');

Um zu testen, wie gut das Verfahren funktioniert, habe ich dem 
Nutzsignal ein weises Rauschen mit der selben Amplitude überlagert ( 
2tes Bild ). Die Phase zeigt sich trotz der Störungen weiterhin ziemlich 
stabil.
modulatedSignal=modulatedSignal+(rand(1,length(modulatedSignal))-0.5);

Jetzt muss ich überlegen, wie ich aus dem roten Signal die Bits wieder 
zurückgewinnen kann. Wenn man sich das rote Signal ansieht, scheint das 
kein Problem zu sein. Man sieht ja deutlich, wenn die rote Linie ( Phase 
) oben oder unten ist. Aber einen Algorithmus dazu zu entwerfen, der 
dies Unterscheidung trifft, scheint mir nicht so einfach.

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein reales Signal (aus dem Internet ) durch den "octave 
Demodulator" geschickt.

Seltsamerweise liegt die Modulationsfrequenz wohl bei ca.954Hz. 
Zumindest habe ich die Mischfrequenz so gewählt. Allerdings sieht man, 
dass die Frequenz nicht haargenau stimmt, weil im unteren Diagramm die 
Phase ( rot ) langsam nach unten davon läuft. Warum die Funker in diesem 
Fall eine so ungerade Modulationsfrequenz gewählt haben, ist mir ein 
Rätsel.

Für diesen Fall müsste man wohl noch einen "Tracker" einbauen, der das 
langsame Weglaufen der Phase korrigiert.

Auf jeden Fall kann man im roten Phasendiagramm super die BITs erkennen.


Programmkopf zum laden des Signals
% psk31 signal von: http://www.pci-card.com/PSK31_BPSK.wav

[Y,FS,BITS]=wavread("PSK31_BPSK.wav");

modulatedSignal=Y(2000:6000)';

% modulation frequency [Hz ]
fm=954;
% sample frequency of the system [Hz]
fs=FS;
% bit rate ( Baud [1/s])
baud=31;

bittime=1/baud;
onebitsamples=bittime*fs;

n=1:length(modulatedSignal);


Autor: p_31 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: p_31 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Gerrit Buhe (gbuhe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marc,

die Trägerfrequenz und selbst die Symbolrate des PSK31-Signales wird 
immer "krumm" sein, da die Taktbasis der beteiligten Rechner - ob 
Mikrocontroller oder PC - immer leicht unterschiedlich ist.
Zum Ausgleich ist eine Trägerfrequenz- und Symboltaktrückgewinnung in 
der Signalverarbeitung vorzunehmen. Auf den Folien 106 und 107 folgender 
Präsentation findest Du etwas Information dazu:

http://www.unidsp56.de/data/DigitaleDatenuebertrag...

Im Falle dieser einfachen BPSK und angesichts der gwünschten niedrigen 
Komplexität, kann die Symboltaktrückgwinnung deutlich vereinfacht 
werden, indem die Symbolmitte bei der betragsmäßig größten Amplitude 
angenommen wird (genügend Überabtastung vorrausgesetzt). Selbst bei der 
QPSK erhöht man damit schon die BER (Bit Error Rate), weil die größten 
Amplituden nicht zum Symbolabtastzeitpunkt auftreten, sondern durch das 
"Überschwingen", bedingt durch die Pulsformung zur 
Bandbreitenreduzierung. Bei der BPSK hat sich die einfache Variante aber 
durchaus bewährt.

Die Simulation mit Octave (oder Alternativen) ist absolut der beste Weg, 
so ein PSK31-Modem zu entwickeln. Ich würde als Datensequenz eine PRBS 
(Pseudo Random Bit Sequence) einsetzen, z.B. eine PRBS9 (9 Bit 
Schieberegister). So kannst Du später den empfangenen Bitstrom in ein 
identisches Schieberegister einspeisen und die BER feststellen. Diese 
ist die wichtigste Metrik zur Beurteilung von in die Signalverarbeitung 
eingebrachten Verbesserungen oder Vereinfachungen. So kannst Du dann 
beurteilen, wie viel dB Signalrauschabstand für eine gegebene BER mehr 
nötig sind, wenn z.B. die Frequenzrückgewinnung sehr einfach anstatt 
komplex implementiert wird, usw.

Weiterhin viel Erfolg und viele Grüße!

Gerrit, DL9GFA

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gerrit,

vielen Dank für Deine Antwort und Deine auführlichen Folien ( sieht nach 
viel Arbeit aus). Die Folien finde ich ganz gut weil sie das Thema 
Signalverarbeitung ziemlich umfangreich behandeln.

>Im Falle dieser einfachen BPSK und angesichts der gwünschten niedrigen
>Komplexität, kann die Symboltaktrückgwinnung deutlich vereinfacht
>werden, indem die Symbolmitte bei der betragsmäßig größten Amplitude
>angenommen wird (genügend Überabtastung vorrausgesetzt)

Daran habe ich auch schon gedacht, aber ich bin noch im Zweifel: Ich 
nehme an dass in einem Funkkanal auch ordentlich Amplitudenschwankungen 
vorhanden sein können. Ich bin mir auch nicht ganz sicher, ob bei PSK31 
zwischen 2 gleichen Symbolen die Amplitude auf 0 geregelt wird ( der 
Einfachheit habler habe ich es in der Senderoutine so gemacht ).

Gerade vorher kam mir die Idee, dass ein "matched Filter" vor dem 
Mischer ja ideal sein müsste um Störungen zu unterdrdrüken. Mit meine 
Simulationsroutinen konnte ich ein Rauchen mit 10 facher Stärke auf das 
Nutzsignal legen und die Phase war immer noch einigermaßen gut 
detektierbar. Das Interessante: Bei der Ausgabe des Signals auf die 
Soundkarte ist bei Rauschfaktor 10 das eigentlich Signal schon gar nicht 
mehr hörbar.

Gruß,
marc

Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das man das PSK-modulierte Signal nicht mehr hören kann, ist normal. 
Kannste bei Phil Karn dich schlau machen.

Du ersparst dir viel Kopfschmerzen, wenn du dein Signal mit einem 
Komparator jeglicher Amplitude befreist und DPSK verwendest.

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Kannste bei Phil Karn dich schlau machen.
Meinst Du hier?
http://www.ka9q.net/dsp.html

Autor: Gerrit Buhe (gbuhe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marc,

bei der Symbolsynchronisation anhand der maximalen Amplitude betrachtet 
man vorzugsweise nur ein kleines zeitliches Fenster um den genauen 
Erwartungswert des Symbolabtastzeitpunktes herum. Wenn das 
Amplitudenmaximum systematisch immer etwas später kommt, erhöht man den 
Periodenzähler, der das nächste Abtastfenster vorhersagt. Wenn das 
Maximum früher kommt, erniedrigt man den Zähler. Der Zähler schwankt 
schlußendlich +/-1 um den idealen Abtastwert herum. Das ist der 
sogenanne "early/late"-Ansatz. Er ist auch auf Mikrocontrollern leicht 
implementiert und die Performance ist auch sehr gut. Ggf. hilft eine AGC 
mit langsamer Zeitkonstante (>>Tsymbol=32ms), die Amplitudenwerte in 
einem geeigneten Fenster zu halten.


> Ich bin mir auch nicht ganz sicher, ob bei PSK31
> zwischen 2 gleichen Symbolen die Amplitude auf 0 geregelt wird ( der
> Einfachheit habler habe ich es in der Senderoutine so gemacht ).

Nein, wenn eine '1' gesendet wird, verändert sich die Phase nicht und 
die Amplitude geht nicht in Richtung Null. Eine größere Anzahl von '1' 
in direkter Folge wird durch die Kodierung allerdings vermieden. Viele 
Nullen können ohne weiteres auftreten (z.B. wenn kein Zeichen gesendet 
wird), aber das führt zu lauter 180°-Änderungen, die hervorragend zur 
Synchronisation taugen.


> Gerade vorher kam mir die Idee, dass ein "matched Filter" vor dem
> Mischer ja ideal sein müsste um Störungen zu unterdrdrüken.

Ja, das Matched Filter ist das optimale Filter hinsichtlich 
Signal-Rausch-Abstand.

> Simulationsroutinen konnte ich ein Rauchen mit 10 facher Stärke auf das
> Nutzsignal legen und die Phase war immer noch einigermaßen gut
> detektierbar. Das Interessante: Bei der Ausgabe des Signals auf die
> Soundkarte ist bei Rauschfaktor 10 das eigentlich Signal schon gar nicht
> mehr hörbar.

Immer wenn die Gesamtrauschleistung in der abgehörten Bandbreite höher 
ist als die Nutzsignalleistung des PSK31-Signales, kann man letzteres 
nicht heraushören. Dank des schmalen Bandpaß- bzw. Tiefpaß-Filters 
(Matched Filter), das auf die PSK31-Bandbreite optimiert ist, wird die 
Rauschbandbreite in der Signalverarbeitung deutlich reduziert und das 
SNR des Nutzsignales wächst so weit, daß eine Auswertung möglich wird. 
Bei Bandbreitenverhältnissen von 2.4kHz (SSB-Filter des Empfängers) zu 
60Hz (Auswertebandbreite des PSK31-Signals) hat man z.B. einen Gewinn an 
Rauschunterdrückung von 16dB (10*log10(2400/60)).

Viele Grüße!

Gerrit, DL9GFA

Autor: Gerrit Buhe (gbuhe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marc,

mir ist aufgefallen, daß Du oben mit genau 31 Symbolen pro Sekunde 
rechnest. Die Symbolrate bei PSK31 ist aber 31.25 Symbole pro Sekunde, 
also genau 32ms pro Symbol.
Wenn Du Dich also wunderst, warum Deine Symboltaktrückgewinnung immer 
hinterher rennt, liegt es vielleicht daran ;o).

Gute Nacht!

Gerrit, DL9GFA

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nanu, Thread eingeschlafen?

Gibt es schon Neuigkeiten bzgl. des Demodulators? Bin sehr interessiert.

Autor: DG8NCY (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo? Gehts hier nicht weiter?? Das wäre sehr sehr schade!!!
Leider kommt man ja bei AATIS schlecht an Bausätze ran, das hier hat 
nach einer hoffnungsvollen Alternative ausgesehen...

Autor: p_31 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
NUE-PSK, open source

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier gibt es eine interessante Realisierung des BPSK31 Verfahrens:

http://www.analogzoo.com/2014/12/amplitude-demodul...

Scheinbar wird bei der 0 auch die Amplitude reduziert:

http://upload.wikimedia.org/wikipedia/commons/7/78...

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wie es aussieht, habe ich die ganze Zeit die Modulation nicht richtig 
verstanden: Die Mitte des Null-Symbols ist genau da, wo die Amplitude 0 
ist. An diesem Punkt macht die Phase dann den Sprung um 180°.

Der Vollständigkeit halber hier noch den Link auf das GitHub-Repo für 
BPSK31.

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was er da im Analogzoo macht ist aber keine BPSK Dekodierung. Er nutz 
halt die Tatsache aus das die Amplitude abgesenkt wird im Zeitpunkt des 
Umschaltens. Kann man machen. Dabei hat man aber eine hoehere 
Stoerempfindlichkeit zu erwarten. Richtige BPSK dekoder werten die Phase 
des Signal aus und sind deshalb stabiler. Der normale Weg ist aber das 
in Software zu machen. Da reicht ein kleiner ARM Controller fuer aus.

Autor: Gerrit Buhe (gbuhe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marc,

nein, die minimale Amplitude hat das Signal genau zwischen den 
Symbolen und ausschließlich(!) wenn eine 0 gesendet wurde.
Du mußt Dir das Augendiagramm mit der Phase auf der Ordinate 
("Y-Achse") ansehen (B_P_SK!). Im optimalen Abtastzeitpunkt liegt bei 
gutem SNR auch die maximale Amplitude vor, egal ob es einen 
Phasenwechsel gab oder nicht. Wenn eine 1 gesendet wurde, bleibt die 
Amplitude aber unverändert hoch und verrät nicht den optimalen 
Abtastzeitpunkt.

Natürlich kann man den Effekt ausnutzen, wie im Beispiel, und nur anhand 
des AM-Anteils das Signal demodulieren, aber dafür wird ein deutlich 
höheres SNR benötigt, als es bei der herkömmlichen Phasendemodulation 
nötig ist. Für eine möglichst stabile Verbindung bei geringer Feldstärke 
ist das Verfahren nicht geeignet.

Viele Grüße!

Gerrit, DL9GFA

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gerit,

lustig, dass Du auch nach 4 Jahren des Thread-Stillstands gleich 
antwortest ;-)
Mir ist das Thema gerade wieder ins Auge gesprungen, weil es in Hackaday 
war.

>nein, die minimale Amplitude hat das Signal genau zwischen den
>Symbolen und ausschließlich(!) wenn eine 0 gesendet wurde.

Das Wikipedia-Bild zeigt es anders:

http://upload.wikimedia.org/wikipedia/commons/7/78...

Vielleicht ist es ja falsch.

>Du mußt Dir das Augendiagramm mit der Phase auf der Ordinate
>("Y-Achse") ansehen (B_P_SK!).

Hast Du gerade einen Link?

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Der Vollständigkeit halber hier noch den Link auf das GitHub-Repo für
>BPSK31.

Link vergessen:
https://github.com/zenmetsu/radioModem

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>nein, die minimale Amplitude hat das Signal genau zwischen den
>Symbolen und ausschließlich(!) wenn eine 0 gesendet wurde.

Zur Sicherheit habe ich mal den ersten Teil des Audiosignals aus der 
Wikipedia mit Audacity visuallisiert.
( http://en.wikipedia.org/wiki/File:PSK31_sample.ogg )

Zuer Synchromisation beginnt das Signal wohl mit lauter Nullen ( 
Phasenwechsel ). Danach kommen vereinzelt die Einzen. Bei den Einsen 
bricht das Signal auch leicht ein, was nach der schematischen Wikipedia 
Zeichung nicht sein müsste.

Autor: Gerrit Buhe (gbuhe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marc,

wenn Du nach 'Augendiagramm BPSK' suchst, findest Du etliche Bilder. 
Leider steht immer Amplitude und nicht Phase auf der Ordinate, obwohl es 
sich um die Phase handelt. Leider ist damit die Amplitudeninformation 
nicht dargestellt. Besser läßt sich so ein digital moduliertes Signal im 
Zeigerdiagramm ansehen und diskutieren, da hier Phase und Amplitude 
gleichzeitig gezeigt werden. Man könnte als zweites Diagramm auch die 
Amplituden abschnittsweise (Symboldauer) übereinander legen und damit 
deren zeitlichen Verlauf parallel zur Phase verdeutlichen.

Warum gibt es eigentlich einen Amplitudenanteil, wenn die Information 
doch in der Phase steckt? Nun, man kann die Amplitude auch konstant 
halten, aber dann ist der "Weg zwischen den Symbolen im 
Konstellationsdiagramm" bei der BPSK um den Faktor pi/2 länger. Da die 
Geschwindikeit der Phasenänderung die Bandbreite beeinflußt, würde diese 
bei gleicher Symbolrate höher werden, oder aber die Symbolrate wäre für 
die gleiche Bandbreite zu reduzieren. Um beides zu vermeiden, wird der 
direkte, also kürzeste Weg durch den Ursprung des 
Konstellationsdiagrammes gewählt, was den Amplitudenanteil einbringt, 
mit der Amplitude Null direkt zwischen den Phasenwechseln.

Etwas Überblick über diese Themen findest Du in einem alten Vortrag von 
mir an dieser Stelle (ab Folie 70):

http://unidsp56.de/data/DigitaleDatenuebertragung0...

Viele Grüße!

Gerrit, DL9GFA

: Bearbeitet durch User
Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antwort, deine Folien sind sehr ausführlich und ganz 
informativ.

Von Michael Keller gibt es ein Signalflussbild zu einem PSK31 Empfänger:
http://dl6iak.etonlein.de/pics/pskstructure.gif
Vielleicht werde ich versuchen, die Auswertung so ähnlich in Octave zu 
machen.

Gestern habe ich endeckt, dass ich mit meinem Weltempfänger Radio 
"Sangean ATS909" tatsächlich PSK31 empfangen kann. Ich habe die 
Empfangsfrequenz auf 14.070 MHz ( USB ) eingestellt  und das Radio via 
Soundkarte an den PC angeschlossen. Dann habe ich "fldigi" in der 
"virtualbox" auf meinem Linux System installiert. ( 
http://www.w1hkj.com/Fldigi.html )

Jetzt am Neujahrstag kann ich tatsächlich einige PSK32 Konversationen 
mitlesen. Zugegebnermaßen verstehe ich nicht alle Kürzel der 
Amateurfunker aber macht nichts, ich finde es interessant, dass ich die 
Signale aus so großer Entfernung trotz meiner schlechten Antenne und des 
großen "Noise-Floors" empfangen kann. Hier ein Beispiel:
          How copy? QÖtog, DL3DJ de 9A7JDF pse kn 
   9A7JDF de DL3DJ
   Many thank
 sWSr aid enfon
my QcP wKO ee-ooee e GW5PH GW5PH pse kn 
 .
This is the first time we've worked
fb signal 599 599  
Name EDMOND 
QTH Longueville JN04CL Atlantic Coast
QSL by Eqsl,  (preffered) (AG) NO Bureau 
? 
TU IU4AVQ de F1DFF pse
-KN-
r
FYm    h 2893. cable digicat power 40 watios
  Antenna  : Hy-Gann 
 spletewlno ee V inverter 10/80
  Operator : 66 years, licenced 1983
 My QSL is OK via only bureau, or direct, information, www.qrz.com
 how copy? Michael BTU M6EFO M6EFO de E


Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
marc schrieb:
>>nein, die minimale Amplitude hat das Signal genau zwischen den
>>Symbolen und ausschließlich(!) wenn eine 0 gesendet wurde.
>
> Zur Sicherheit habe ich mal den ersten Teil des Audiosignals aus der
> Wikipedia mit Audacity visuallisiert.
> ( http://en.wikipedia.org/wiki/File:PSK31_sample.ogg )

Diese Ogg-Datei hat ziemlich verschmierte Phasenlagen so wie mir das 
nach ein paar ersten Versuchen erscheint (dieser Thread hier hat mich 
angesteckt, jetzt will ichs auch wissen), besser wäre es vielleicht 
erstmal ein wirklich sauberes Signal zu verwenden, ich weiß nicht ob das 
was der extrem komprimierende Vorbis-codec da veranstaltet hat 
realistisch ist um einen gestörten Übertragungsweg zu simulieren.

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
marc schrieb:
> Von Michael Keller gibt es ein Signalflussbild zu einem PSK31 Empfänger:
> http://dl6iak.etonlein.de/pics/pskstructure.gif
> Vielleicht werde ich versuchen, die Auswertung so ähnlich in Octave zu
> machen.

Vielleicht wäre es einfacher auf die Trägerrückgewinnung komplett zu 
verzichten (spart nen Arkustangens auf schwachbrüstigen 
Microcontrollern) und stattdessen einfach das um eine Symbollänge 
verzögerte Empfangssignal selbst als Referenz zu nehmen, die Modulation 
ist ja Differential-PSK, also ginge das, das wäre dann in etwa so wie 
hier auf Seite 4: http://det.bi.ehu.es/~jtpjatae/pdf/p31g3plx.pdf

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Diese Ogg-Datei hat ziemlich verschmierte Phasenlagen so wie mir das
>nach ein paar ersten Versuchen erscheint (dieser Thread hier hat mich
>angesteckt, jetzt will ichs auch wissen), besser wäre es vielleicht
>erstmal ein wirklich sauberes Signal zu verwenden,

Hallo Bernd,
es freut mich, dass Du Dich auch dafür begeistern kannst. Ich habe eben 
mal eine Wav-Datei mit dem Programm "fldigi" erstellt. Gesendet wird 
immer

test test test ....

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal folgendes gemacht, ziemlich hemdsärmelig aber zumindest 
tut es das was ich davon erwarte:


Ausgegangen wird davon daß ein Audiosignal von exakt 1kHz vorliegt, es 
muss also schon geeignet genau dorthin heruntergemischt sein durch 
entsprechend feinfühligen Abgleich des Transceivers plusminus ein paar 
wenige Hertz.

Ich habe einen Timer laufen mit 4kHz, der stößt den ADC an, ich sample 
also mit exakt der 4-fachen Frequenz. Im ADC-Interrupt dann wird die 
folgende Funktion aufgerufen, 4000 mal in der Sekunde:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    int32_t value = HAL_ADC_GetValue(hadc);
    int32_t old = buffer[buffer_ptr];
    buffer[buffer_ptr] = value;
    if (++buffer_ptr == BUF_SIZE) {
        buffer_ptr = 0;
    }

    if (phase == 0) {
        I -= old;
        I += value;
    } else if (phase == 1) {
        Q -= old;
        Q += value;
    } else if (phase == 2) {
        I += old;
        I -= value;
    } else {
        Q += old;
        Q -= value;
        have_sample = true;
    }
    phase = (phase + 1) & 3;

}

buffer kann genau 4*32 Samples aufnehmen, ich summiere also immer über 
die letzten 32 Perioden jeweils I und Q, das hat schon eine ziemliche 
Filterwirkung und es sind dennoch keine Multiplikationen notwendig. Ich 
habe da also einen Direktmischer gebaut, wenn die Frequenz exakt 1/4 der 
Abtastrate wäre blieben I und Q konstant, wenn sie leicht daneben liegt 
dann dreht sich der Vektor (I,Q) langsam. Wenn die Phase um 180° springt 
dann springt dieser Vektor ebenfalls um 180°.

in der main habe ich nun folgendes:
int main(void) {
    init_board();

    for (uint16_t i=0; i<BUF_SIZE; i++) {
        buffer[i] = 0;
    }

    while (1) {
        if (have_sample) {
            have_sample = false;

            int32_t previous_I = delay_I[delay_ptr];
            int32_t previous_Q = delay_Q[delay_ptr];
            delay_I[delay_ptr] = I;
            delay_Q[delay_ptr] = Q;
            delay_ptr = (delay_ptr + 1) & 31;

            // scalar product with delayed sample
            int32_t prod = I * previous_I + Q * previous_Q;

            uart_send_16(prod >> 16);
        }
    }
}

delay_I und delay_Q sind beide genau 32 Elemente lang und verzögern 
somit genau 32ms. Ich berechne das Skalarprodukt aus (I,Q) mit dem von 
vor 32ms und das Ergebnis ist negativ wenn die Phase sich geändert hat 
oder positiv wenn die Phase gleich geblieben ist. Dass sich der vektor 
(I,Q) langsam dreht weil die Frequenz weggedriftet ist hat keinen 
Einfluss darauf dass man dennoch einen deutlichen Phasensprung erkennen 
kann.

Zu Debuggingzwecken sende ich dann das Produkt via UART an den PC und 
plotte es, siehe Bild.

Der analoge Aufbau sieht so aus daß ich eine wav Datei am PC abspiele 
über die angeschlossenen Brüllwürfel als Schall ausgebe, dann mit einem 
kleinen Electretmikrofon wieder aufnehme, zwei npn-Transistoren in 
Emitterschaltung zum Verstärken und dann direkt in den ADC-Eingang eines 
am USB-Port angeschlossenen stm32nucleo-boards. Mein Mikrofonverstärker 
ist nicht gerade optimal und er fängt einigen Schmutz aus dem 
Schaltnetzteil auf, das hab ich in 5 Minuten schnell zusammengestöpselt 
auf dem Steckbrett.

Anbei die wav Datei (im Internet gefunden) und ein Screenshot vom Plot 
der Ausgabe von uart_send_16(prod >> 16);

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So. Mal eben schnell zusammengehackt das timing für das Samplen der 
bits. Wenn ich davon ausgehe dass mein Takt keine Abweichungen von 
mehreren Prozent hat dann hab ich mit einem Zähler der bei 32 überläuft 
schon den richtigen takt, ich muss nur die Phase einrasten lassen auf 
den negativen Peaks.

Die blauen spikes sind der Zeitpunkt wo time==symbol_sample_time, man 
sieht schön wie symbol_sample_time zu Beginn langsam verschoben wird bis 
die Phase eingerastet ist.
int main(void) {
    init_board();

    for (uint16_t i=0; i<BUF_SIZE; i++) {
        buffer[i] = 0;
    }

    //uint32_t period_0 = TIM2->ARR;

    int32_t neg_peak_value;
    uint8_t neg_peak_time;
    uint8_t symbol_sample_time = 16;
    uint8_t time = 0;

    int16_t x = 0;

    while (1) {
        if (have_sample) {
            have_sample = false;

            int32_t previous_I = delay_I[delay_ptr];
            int32_t previous_Q = delay_Q[delay_ptr];
            delay_I[delay_ptr] = I;
            delay_Q[delay_ptr] = Q;
            delay_ptr = (delay_ptr + 1) & 31;

            // scalar product with delayed sample
            int32_t prod = I * previous_I + Q * previous_Q;
            
            if (time == symbol_sample_time) {
                x = 10000;
            } else {
                x = 0;
            }

            uart_send_16(prod >> 10);
            uart_send_16(x);
            
            // find the exact time of the negative peak
            if (prod < 0 && prod < neg_peak_value) {
                neg_peak_value = prod;
                neg_peak_time = time;
            }
            
            // the symbol sampling clock is accurate (because we
            // have a crystal oscillator) but we must correct its 
            // phase so that it coincides with the negative peaks.
            // We do this adjustment 16 ms after each negative peak.
            if ((time - neg_peak_time == 16) || (time + 32 - neg_peak_time == 16)) {
                int8_t diff = neg_peak_time - symbol_sample_time;
                if ((diff > 0 && diff <= 16) || (diff <= -16)) {
                    symbol_sample_time = (symbol_sample_time + 1) & 31;
                }
                if ((diff < 0 && diff > -16) || (diff > 16)) {
                    symbol_sample_time = (symbol_sample_time - 1) & 31;
                }
                neg_peak_value = 0;
                neg_peak_time = 255; //
            }

            time = (time + 1) & 31;
        }
    }
}

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Du warst etwas schneller.
( Aber ich musste zwischendurch das Abendessen kochen ;-) )

Ich habe Dein Wav-File genommen und mit Octave verarbeitet.
Die Phase wird mit der "angle" Funktion getracked. Sie wird mit einem 
Schrittregler auf pi/2 geregelt.

Die Filter hatte ich auch schon als Moving-Average ausgeführt. 
Ursprünglich habe ich die Filterlänge genau auf die Symbollänge 
eingestellt. Das war aber falsch. Die halbe Symbollänge scheint mir das 
Optimum für die Filter zu sein.

[Y,FS,BITS]=wavread("bpsk31.wav");
psk31_signal=Y(1:20000)';

% modulation frequency [Hz ]
%fcarrier=954;
fcarrier=1000;
% sample frequency of the system [Hz]
fs=FS;
% bit rate ( Baud [1/s])
baud=31.25;

bittime=1/baud;
symbol_length=bittime*fs;

%***************************************************
% demodulator and phase controller
%***************************************************
filter_length=round(symbol_length/2);

% moving averiger filter coeeficients
Bma=ones(1,filter_length)/filter_length;

filtermemory=zeros(1,filter_length-1); 

fcorrection=0;

controlFactor=0.0004;

for n=1:length(psk31_signal),
  fcarrier_corrected=fcarrier+fcorrection;

  signalMixed(n)=psk31_signal(n)*exp(i*2*pi*fcarrier_corrected/fs*n);

  [signalFiltered(n) filtermemory]=filter(Bma,1,signalMixed(n),filtermemory);
  
  alpha=angle(signalFiltered(n));
  if(alpha>0)  
    x=alpha-pi/2;
    fcorrection=fcorrection-sign(x)*controlFactor;    
  else
    x=alpha+pi/2;
    fcorrection=fcorrection-sign(x)*controlFactor;
  end
  fcorr(n)=fcorrection;
end

Bdelay=zeros(1,filter_length);
Bdelay(round(filter_length/2))=1;
psk31_signal_shifted_and_scaled=filter(Bdelay,1,psk31_signal)/max(psk31_signal);

plot(psk31_signal_shifted_and_scaled);
hold on
plot(angle(signalFiltered),'r','LineWidth',2);
plot(fcorr,'y','LineWidth',2);

% plot phase sollwert helper lines
plot(ones(1,length(psk31_signal))*pi/2);
plot(ones(1,length(psk31_signal))*-pi/2);

title('blue: psk31 signal    red: detected phase    yellow: carrier frequency correction');




Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
anbei noch ein bild mit den gesampleten bits

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>anbei noch ein bild mit den gesampleten bits

Sieht gut aus :-)

Hier gibt es die Code-Tabelle in C, falls Du den Decoder bist zum 
Textempfang weiterprogrammieren willst und keine Lust hast, die Code 
selber einzutippen:

https://github.com/zenmetsu/radioModem/blob/master/psk31.cpp

Ich schätze, dass die Rechenleistung eines Atmega8 für den Dekoder 
ausreichen würde ....

Hast Du einen Weltempfänger, mit dem Du das ganze real ausprobieren 
willst?
Man braucht einen, bei dem man das "obere Seitenband" selektieren kann.

> Der analoge Aufbau sieht so aus daß ich eine wav Datei am PC abspiele
> über die angeschlossenen Brüllwürfel als Schall ausgebe, dann mit einem
> kleinen Electretmikrofon wieder aufnehme, zwei npn-Transistoren in
> Emitterschaltung zum Verstärken und dann direkt in den ADC-Eingang eines
> am USB-Port angeschlossenen stm32nucleo-boards.

Ich hatte versucht, eine mit ""fldigi" erstellte Datei auf dem Tablet 
abzuspielen und mit dem PC zu empfangen, aber es kam fast nur Müll an. 
Die Sendefrequenz lag bei 2.5kHz und war vielleicht zu hoch.

Autor: Marek N. (bruderm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

als idealer Empfänger würde sich doch der Web-SDR eignen, oder?
http://websdr.ewi.utwente.nl:8901/

Beste Grüße, Marek

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
marc schrieb:
> Ich schätze, dass die Rechenleistung eines Atmega8 für den Dekoder
> ausreichen würde ....

Das müsste gehen, das ist auch meine Absicht. Der einzige Grund warum 
ich das  momentan auf dem stm32 laufen habe ist der daß ich den (als 
totaler ARM-Neuling und ehemals eigentlich eher bei AVR zuhause) gerade 
endlich soweit hatte dass ich Timer und ADC benutzen konnte und somit 
quasi schon genau das dafür benötigte Grundgerüst stehen hatte.

Mir schwebt da aber was für nen kleinen AVR vor, womöglich sogar ein 
ATTiny, das werd ich demnächst mal versuchsweise aufbauen. Das ist auch 
der Grund warum ich versucht habe möglichst ohne komplizierte 
Rechenoperationen auszukommen, so wie es jetzt ist hab ich nur noch zwei 
Integer-Multiplikationen pro Millisekunde, und die bring ich bestimmt 
auch noch von 32bit auf 16bit runter.

Gestern hatte ich mal versuchsweise eine tanlock-Loop so ähnlich wie bei 
Dir implementiert um meine Abtastrate auf die Trägerfreguenz 
einzurasten, das hat auch gar nicht mal so übel funktioniert aber als 
ich die Skizze mit der simplifizierten inkohärenten Demodulation gesehen 
habe hab ichs wieder rausgeworfen und muss jetzt nicht mehr über 
Winkelfunktionen auf schwachbrüstigen Mikrocontrollern nachgrübeln ;-)

Autor: Bernd Wiebus (berndwiebus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marek.

Marek N. schrieb:

> als idealer Empfänger würde sich doch der Web-SDR eignen, oder?
> http://websdr.ewi.utwente.nl:8901/

Das geht in der Tat. Weil sich meine Audiokarte streubte, intern etwas, 
was am Ausgang auftaucht im Eingang zu benutzen, habe ich eine 
Sprechkarnitur ausgegraben und das Mikrofon so an den Kopfhörer gebogen, 
dass ich das was ich über den Web-SDR im Kopfhörer höre, über das 
Mikrophon für fldigi zurückspeise. ;O)

Das geht natürlich nur bei Duplex fähigen Audiokarten.

Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Mir schwebt da aber was für nen kleinen AVR vor, womöglich sogar ein
>ATTiny, das werd ich demnächst mal versuchsweise aufbauen. Das ist auch
>der Grund warum ich versucht habe möglichst ohne komplizierte
>Rechenoperationen auszukommen, so wie es jetzt ist hab ich nur noch zwei
>Integer-Multiplikationen pro Millisekunde, und die bring ich bestimmt
>auch noch von 32bit auf 16bit runter.

Mit einem Attiny könnte es auch gehen, aber der hat ja keinen 
HW-Multiplizierer, was wieder ordentlich Rechenzeit kostet.
Meiner Meinung nach ist es gut, nicht zu sehr zu sparen, damit man nicht 
zuviel Rauschen ins System induziert. Eine hohe Dynamik durch große 
Wortbreiten ist da sicherlich nützlich. Ebenfalls sollte es helfen, den 
ADC mit der vollen Auflösung zu betreiben. Bei den AVRs also mit 10 Bit.

Wenn ich mir die echten Signale aus dem Weltempfänger anschaue, ist es 
schon erstaunlich, aus wie wenig Signal "fldigi" noch etwas herausholen 
kann. Aber wer weis, vielleicht lässt sich auch die Empfangsleistung von 
"fldigi" noch verbessern.

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht reicht es für die Phasenregelung aus, einfach den Q-Part auf 
0 zu regeln.

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Nachdem ich ein wenig mit der Carrier-Frequenz herum gespielt habe, 
scheint es doch so zu sein, dass der Regler zum schwingen neigt.
Deshalb habe ich statt der Frequenz einen Phasenregler gebaut. Der ist 
ziemlich stabil und die Phase steht nach kurzer Zeit wie eine "Eins".
Das setzt allerdings einen ziemlich guten Übereinstimmung des 
Sendercarriers mit der Empfangsmodulationsfrequenz voraus.

[Y,FS,BITS]=wavread("bpsk31.wav");
psk31_signal=Y(1:20000)';

% modulation frequency [Hz ]

fcarrier=1000;
% introduce some carrier mismatch for robustness test
carrier_error_percent=0;
fcarrier=fcarrier*(1+carrier_error_percent/100);

% sample frequency of the system [Hz]
fs=FS;
% bit rate ( Baud [1/s])
baud=31.25;

bittime=1/baud;
symbol_length=bittime*fs;

%***************************************************
% demodulator and phase controller
%***************************************************
filter_length=round(symbol_length/2);

% moving averiger filter coeeficients
Bma=ones(1,filter_length)/filter_length;

filtermemory=zeros(1,filter_length-1); 

phase_correction=0;

controlFactor=0.0004;

for n=1:length(psk31_signal),

  signalMixed(n)=psk31_signal(n)*exp(i*2*pi*fcarrier/fs*n)*exp(i*phase_correction);

  % moving average filter
  [signalFiltered(n) filtermemory]=filter(Bma,1,signalMixed(n),filtermemory);
  
  alpha=angle(signalFiltered(n));

  if(alpha>0)  
    x=alpha-pi/2;
    phase_correction=phase_correction-sign(x)*controlFactor;    
  else
    x=alpha+pi/2;
    phase_correction=phase_correction-sign(x)*controlFactor;
  end

  % fcorr just to visuallize the phase adatpion
  fcorr(n)=phase_correction;
end

Bdelay=zeros(1,filter_length);
Bdelay(round(filter_length/2))=1;
psk31_signal_shifted_and_scaled=filter(Bdelay,1,psk31_signal)/max(psk31_signal);

hold off
plot(psk31_signal_shifted_and_scaled);
hold on
plot(angle(signalFiltered),'r','LineWidth',2);
plot(fcorr,'y','LineWidth',2);

% plot phase sollwert helper lines
plot(ones(1,length(psk31_signal))*pi/2);
plot(ones(1,length(psk31_signal))*-pi/2);

title('blue: psk31 signal    red: detected phase    yellow: phase correction');




Autor: Gerrit Buhe (gbuhe)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marc und Bernd,

ich bin sehr begeistert von Euern Aktivitäten.

Eine bewährte Vorgehensweise ist tatsächlich die numerische Simulation 
auf dem PC (Matlab/Scilab/Octave), um komfortabel an alle Signale im 
Zeit- und Frequenzbereich heran zukommen und die Gesamtaufgabe richtig 
zu verstehen/durchdringen. Hier sollte zu Beginn ruhig noch alles mit 
der hohen numerischen Auflösung und z.B. den "eingebauten" 
trigonometrischen Funktionen berechnet werden.
Die Bewertung der entwickleten Signalverarbeitung kann dann anhand von 
Bitfehlerraten (BER) über Signal-zu-Rausch-Verhältnissen (SNR) erfolgen. 
Ziel ist es natürlich, so nah wie möglich an die theoretische BER-Kurve 
zu kommen, die man aber nie ganz erreichen kann (z.B. wird man keine 
unendlich langen RRC-Filter einsetzen).
Wenn das Ergebnis gut ist, können nun die einzelnen Funktionsblöcke 
durch implementierungfreundlichere Algorithmen ersetzt werden. Nun kann 
man anhand der BER-Kurven die Implementierungsverluste abschätzen die in 
dB SNR angegeben werden. Benötigt man z.B. 3dB mehr SNR für eine 
gegebene BER (BER-Kurve 3dB verschoben), dann sind diese 3dB genau der 
Implementierungsverlust. Auf diese Weise können die verschiedenen 
Vereinfachungen genau bewertet werden. Es gibt dabei oft Überraschungen, 
wenn z.B. ein viel einfacherer Algorithmus eine bessere Performance 
offenbart als manch ein komplizierter.
Im vorletzten Schritt kann man sogar die Quantisierung der Abtastwerte 
in allen Funktionsblöcken nachstellen und damit auf eine Bit-genaue 
Implementierung zur Mikrocontroller/DSP-Lösung kommen.
Der letzte Schritt ist natürlich die Implementierung auf der 
Ziel-Hardware. Da man das Verhalten der Algorithmen nun schon sehr gut 
kennt, fallen einem Abweichungen beim Debuggen sehr schnell auf und 
diese sind dann genauso schnell behoben. Sind Veränderungen in der 
Implementierung nötig, sollten sie zuerst auch in die Simulation 
aufgenommen werden, um die Auswirkungen (Verluste) beurteilen zu können.
Es ist ebenfalls möglich und gute Praxis, Abtastwerte aus der 
Implementierung in die Simulation zu übertragen und genauso Daten aus 
der Simulation in die Hardware für die Verifikation verschiedener 
Abschnitte oder der ganzen Verarbeitungskette zu laden (via 
Debug-Puffer).

Soviel zur "best practise" zum Thema. Vielleicht findet Ihr die eine 
oder andere Anregung darin. Viele Wege führen nach Rom! ;o)

Weiterhin viel Erfolg!

Gerrit, DL9GFA

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Eine bewährte Vorgehensweise ist tatsächlich die numerische Simulation
>auf dem PC (Matlab/Scilab/Octave), um komfortabel an alle Signale im
>Zeit- und Frequenzbereich heran zukommen und die Gesamtaufgabe richtig
>zu verstehen/durchdringen. Hier sollte zu Beginn ruhig noch alles mit
>der hohen numerischen Auflösung und z.B. den "eingebauten"
>trigonometrischen Funktionen berechnet werden.

Das sehe ich ganz genau so und mache es auch schon länger. Da jetzt 
gerade Jahreswechsel ist habe ich etwas Zeit und es macht Spaß, sich mal 
mit praktischer Signalverarbeitung zu befassen. Ausserdem kann ich ja 
auch noch was lernen.

Ich finde es beeindruckend, das Bernd so minimalistisch gute Ergebnisse 
erzielen kann. Bin mal gespannt, wie weit er kommt.
Ich weis noch nicht wie viel Zeit ich für dieses Projekt habe, da es 
aber schon 5 Jahre her ist ( wie man aus dem Start-Posting sieht) kann 
ich ja zur Not auch in 5 Jahren damit weitermachen. Dann sind die AVRs 
wahrscheinlich ganz obsolet und die Rechenpower der ARMs ermöglicht 100 
Kanäle gleicheitig.

Hier ein Rauschmodell. Ich hoffe, ich habe die Signalamplitude aus der 
SNR richtig berechnet. Die Phasenerkennung scheint auch bei -15dB noch 
gut zu funktionieren, das Singal kann man akustisch im Rauschen nicht 
mehr hören.
% indroduce Noise for robustness test
SNR=-15 % DB

signalPower=sum(psk31_signal_raw.*psk31_signal_raw)/length(psk31_signal_raw);
noiseAmplitude=sqrt(signalPower)/power(10,SNR/20)
noise=(rand(1,length(psk31_signal_raw))*2-1)*noiseAmplitude;

psk31_signal=psk31_signal_raw+noise;


Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier das gefilterte Signal hinter dem Moving-Average-Filter.
Wie man sieht, wird der Realteil bei korrekter Phase zu Null. Damit 
sollte es ausreichen, den Realteil zur Regelung zu verwernden.

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Es scheint tatsächlich zu funktionieren. Man braucht keine 
zeitaufwendige Winkelberechnung. Die getrennte Betrachtung der I- und Q- 
Anteile reicht aus. Damit entallen auch die Multiplikationen zur 
Betragsbildung von Bernd.

Die rote Kurve im Bild zeigt den Realteil des gefilterten Signals.

....

phase_correction=0;

controlFactor=0.0004;

for n=1:length(psk31_signal),

  signalMixed(n)=psk31_signal(n)*exp(i*2*pi*fcarrier/fs*n)*exp(i*phase_correction);

  % moving average filter
  [signalFiltered(n) filtermemory]=filter(Bma,1,signalMixed(n),filtermemory);
  
  qpart=real(signalFiltered(n));
  ipart=imag(signalFiltered(n));

  if qpart>0,
    phase_correction=phase_correction+sign(ipart)*controlFactor;
  else
    phase_correction=phase_correction-sign(ipart)*controlFactor;
  end

  % fcorr just to visuallize the phase adatpion
  fcorr(n)=phase_correction;
end

...


Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
marc schrieb:
> Es scheint tatsächlich zu funktionieren. Man braucht keine
> zeitaufwendige Winkelberechnung. Die getrennte Betrachtung der I- und Q-
> Anteile reicht aus. Damit entallen auch die Multiplikationen zur
> Betragsbildung von Bernd.

Aber wie verhält es sich dann wenn die Amplitude schwankt? Ich habe 
versuchsweise mal eine PLL mit
           int32_t phase_error = Q * (I > 0 ? 1 : -1);

implementiert und dann mit P-Filter (als auch testweise mal mit 
PI-Filter) zur Nachregelung der Mischfrequenz implementiert, es geht im 
Prinzip ganz gut, jedoch hängt dann die Stabilität ganz erheblich von 
der Amplitude des Signals ab: ist sie zu niedrig fängt er die Frequenz 
nicht vernünftig, ist sie zu hoch gibt es heftige Regelschwingungen. 
Also komm ich um mindestens eine Multiplikation zwecks Pegelregelung 
doch nicht herum.

sodann hab ich es zum direkten Vergleich noch mal mit

            int16_t a = atan2(Q, I) * 180 / PI;
            int16_t phase_error = a;
            if (phase_error > 90) {
                phase_error -= 180;
            }
            if (phase_error < -90) {
                phase_error += 180;
            }
Und das war außerordentlich stabil! Auch der Fangbereich war viel weiter 
und es war wirklich sehr gutmütig zu dimensionieren und weitaus 
stabiler. Jedoch bringt mich das wieder zurück zum Problem der 
Arkustangens-Berechnung.

Leider hat sich gezeigt daß ich mit meiner gestrigen Implementierung 
ohne PLL nicht mehr als etwa +-3Hz abweichen darf, bei +-7Hz hat das 
verzögerte Signal das ich als Referenz verwende bereits eine Drehung von 
90° und bei +-15Hz bereits 180°. Das bedeutet ich kann das Web-SDR nicht 
gut als Empfänger verwenden, dort kann ich nur in 30Hz-Schritten 
abstimmen :-(

Ich werde jetzt aber erstmal noch den letzten Schritt gehen und 
ausgehend von meinem Stand von gestern Abend mal die Decodierung der 
Daten implementieren, so daß es überhaupt mal ein paar Lebenszeichen von 
sich gibt.

@Gerrit: Es leuchtet mir ein daß eine systematische Vorgehensweise wie 
Du sie empfiehlst wahrscheinlich der bessere Weg ist, jedoch muss ich 
mir da zunächst noch etwas mehr Theorie und Praxis im Umgang mit 
Werkzeugen wie Octave zulegen und auch in die Mathematik der 
Signalverarbeitung tiefer einsteigen. Vielleicht nehm ich das zum Anlass 
mal bei Gelegenheit das was ich hier so pi-mal-Daumen implementiert habe 
in Octave nachzustellen um tiefere Erkenntnisse über das Verhalten und 
die Eigenschaften meines "Quick & Dirty"-Demodulators zu gewinnen ;-)

: Bearbeitet durch User
Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Aber wie verhält es sich dann wenn die Amplitude schwankt? Ich habe
>versuchsweise mal eine PLL mit

Getestet habe ich es nur mit -15dB SNR. Die Rausamplitude ist damit 
knapp 6 Mal stärker als die Signalamplidude und man kann das Signal 
nicht mehr erkennen.
Ich könnte mir vorstellen, dass ein Amplitudenschwankung gar nicht so 
viel ausmacht, weil ich ja nur auf großer/kleiner Null regle:

  qpart=real(signalFiltered(n));
  ipart=imag(signalFiltered(n));

  if qpart>0,
    phase_correction=phase_correction+sign(ipart)*controlFactor;
  else
    phase_correction=phase_correction-sign(ipart)*controlFactor;
  end


Beitrag #3948384 wurde von einem Moderator gelöscht.
Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Nochmal ...
Hier das Richtige.
( Falls ein Moderator mitliest: bitte den letzen Post löschen ).

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@marc:
I ist normalerweise doch der Realteil!

psk31 basiert auf BPSK. Das macht dann auch Sinn, dass es geht, weil bei 
180º ist eh nur der Realteil wichtig. Also dein 'q'.

Eventuell kann Gerrit was sagen dazu, weil ich bin da auch nicht so fit.

Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>I ist normalerweise doch der Realteil!

Tja, ich befürchte Du hast Recht. Ich habe mir immer I wie "imaginär" 
gemerkt.

Aber:

 I für In-phase component und Q für Quadrature Component
( aus http://de.wikipedia.org/wiki/Quadraturamplitudenmodulation )

Da muss ich wohl alles umbenennen ....

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, hab dann mal das Decodieren implementiert:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "stm32f4xx_hal.h"
#include "stm32f401xe.h"
#include <stm32f4xx_hal_rcc.h>
#include <itoa.h>
#include <board.h>
#include <math.h>

#define PI              3.14159265358979323846

#define BUF_PERIODS     32
#define BUF_SIZE        4 * BUF_PERIODS

uint16_t PSK_TO_PSK_IDX[128] = {
    0b1,
    0b11,
    0b101,
    0b111,
    0b1011,
    0b1101,
    0b1111,
    0b10101,
    0b10111,
    0b11011,
    0b11101,
    0b11111,
    0b101011,
    0b101101,
    0b101111,
    0b110101,
    0b110111,
    0b111011,
    0b111101,
    0b111111,
    0b1010101,
    0b1010111,
    0b1011011,
    0b1011101,
    0b1011111,
    0b1101011,
    0b1101101,
    0b1101111,
    0b1110101,
    0b1110111,
    0b1111011,
    0b1111101,
    0b1111111,
    0b10101011,
    0b10101101,
    0b10101111,
    0b10110101,
    0b10110111,
    0b10111011,
    0b10111101,
    0b10111111,
    0b11010101,
    0b11010111,
    0b11011011,
    0b11011101,
    0b11011111,
    0b11101011,
    0b11101101,
    0b11101111,
    0b11110101,
    0b11110111,
    0b11111011,
    0b11111101,
    0b11111111,
    0b101010101,
    0b101010111,
    0b101011011,
    0b101011101,
    0b101011111,
    0b101101011,
    0b101101101,
    0b101101111,
    0b101110101,
    0b101110111,
    0b101111011,
    0b101111101,
    0b101111111,
    0b110101011,
    0b110101101,
    0b110101111,
    0b110110101,
    0b110110111,
    0b110111011,
    0b110111101,
    0b110111111,
    0b111010101,
    0b111010111,
    0b111011011,
    0b111011101,
    0b111011111,
    0b111101011,
    0b111101101,
    0b111101111,
    0b111110101,
    0b111110111,
    0b111111011,
    0b111111101,
    0b111111111,
    0b1010101011,
    0b1010101101,
    0b1010101111,
    0b1010110101,
    0b1010110111,
    0b1010111011,
    0b1010111101,
    0b1010111111,
    0b1011010101,
    0b1011010111,
    0b1011011011,
    0b1011011101,
    0b1011011111,
    0b1011101011,
    0b1011101101,
    0b1011101111,
    0b1011110101,
    0b1011110111,
    0b1011111011,
    0b1011111101,
    0b1011111111,
    0b1101010101,
    0b1101010111,
    0b1101011011,
    0b1101011101,
    0b1101011111,
    0b1101101011,
    0b1101101101,
    0b1101101111,
    0b1101110101,
    0b1101110111,
    0b1101111011,
    0b1101111101,
    0b1101111111,
    0b1110101011,
    0b1110101101,
    0b1110101111,
    0b1110110101,
    0b1110110111,
    0b1110111011
};

uint16_t PSK_IDX_TO_ASCII[128] = {
    0x20, // SP
    0x65, // 'e'
    0x74, // 't'
    0x6f, // 'o'
    0x61, // 'a'
    0x69, // 'i'
    0x6e, // 'n'
    0x72, // 'r'
    0x73, // 's'
    0x6c, // 'l'
    0x0a, // LF
    0x0d, // CR
    0x68, // 'h'
    0x64, // 'd'
    0x63, // 'c'
    0x2d, // '-'
    0x75, //HD_low_u,
    0x6d, //HD_low_m,
    0x66, //HD_low_f,
    0x70, //HD_low_p,
    0x3d, //HD_equals,
    0x2e, //HD_period,
    0x67, //HD_low_g,
    0x79, //HD_low_y,
    0x62, //HD_low_b,
    0x77, //HD_low_w,
    0x54, //HD_cap_T,
    0x53, //HD_cap_S,
    0x2c, //HD_comma,
    0x45, //HD_cap_E,
    0x76, //HD_low_v,
    0x41, //HD_cap_A,
    0x49, //HD_cap_I,
    0x4f, //HD_cap_O,
    0x43, //HD_cap_C,
    0x52, //HD_cap_R,
    0x44, //HD_cap_D,
    0x30, //HD_zero,
    0x4d, //HD_cap_M,
    0x31, //HD_one,
    0x6b, //HD_low_k,
    0x50, //HD_cap_P,
    0x4c, //HD_cap_L,
    0x46, //HD_cap_F,
    0x4e, //HD_cap_N,
    0x78, //HD_low_x,
    0x42, //HD_cap_B,
    0x32, //HD_two,
    0x09, // HT Tab
    0x3a, //HD_colon,
    0x29, //HD_rightparenthesis,
    0x28, //HD_leftparenthesis,
    0x47, //HD_cap_G,
    0x33, //HD_three,
    0x48, //HD_cap_H,
    0x55, //HD_cap_U,
    0x35, //HD_five,
    0x57, //HD_cap_W,
    0x22, //HD_doublequote,
    0x36, //HD_six,
    0x5f, //HD_underscore,
    0x2a, //HD_multiply,
    0x58, //HD_cap_X,
    0x34, //HD_four,
    0x59, //HD_cap_Y,
    0x4b, //HD_cap_K,
    0x27, //HD_apostrophe,
    0x38, //HD_eight,
    0x37, //HD_seven,
    0x2f, //HD_divide, ///
    0x56, //HD_cap_V,
    0x39, //HD_nine,
    0x7c, // '|'
    0x3b, //HD_semicolon,
    0x71, //HD_low_q,
    0x7a, //HD_low_z,
    0x3e, //HD_greaterthan,
    0x24, //HD_dollar,
    0x51, //HD_cap_Q,
    0x2b, //HD_add,
    0x6a, //HD_low_j,
    0x3c, //HD_lessthan,
    0x5c, // '\'
    0x23, //HD_pound,
    0x5b, //HD_leftbracket,
    0x5d, //HD_rightbracket,
    0x4A, //HD_cap_J,
    0x21, //HD_exclamation,
    0x00, // NUL
    0x5A, //HD_cap_Z, 1010101101
    0x3f, //HD_question,
    0x7d, //HD_rightcurlybracket,
    0x7b, //HD_leftcurlybracket,
    0x26, //HD_and,
    0x40, //HD_at,
    0x5e, //HD_power,
    0x25, //HD_percent,
    0x7e, // '~'
    0x01, // SOH
    0x0c, // FF
    0x60, // '`'
    0x04, // EOT
    0x02, // STX
    0x06, // ACK
    0x11, // DC1
    0x10, // DLE
    0x1e, // RS
    0x07, // BEL
    0x08, // BS
    0x1b, // ESC
    0x17, // ETB
    0x14, // DC4
    0x1c, // FS
    0x05, // ENQ
    0x15, // NAK
    0x16, // SYN
    0x0b, // VT
    0x0e, // SO
    0x03, // ETX
    0x18, // CAN
    0x19, // EM
    0x1f, // US
    0x0f, // SI
    0x12, // DC2
    0x13, // DC3
    0x7f, // DEL
    0x1a, // SUB
    0x1d, // GS
};

int32_t buffer[BUF_SIZE];
uint16_t buffer_ptr = 0;
int32_t I = 0;
int32_t Q = 0;
uint8_t phase = 0;

uint16_t cnt = 100;
volatile bool have_sample = false;

int32_t smooth = 0;

int32_t delay_I[32];
int32_t delay_Q[32];
uint8_t delay_ptr = 0;

void process_word(uint16_t word) {
    for (uint8_t i=0; i<128; i++) {
        if (word == PSK_TO_PSK_IDX[i]) {
            char c = PSK_IDX_TO_ASCII[i];
            uart_send_8(c);
        }
    }
}

void decode_bit(bool bit) {
    static bool started = false;
    static uint16_t word = 0;
    if (bit) {
        started = true;
        word = (word << 1) | 1;
    } else {
        if (started) {
            word <<= 1;
            if ((word & 3) == 0) {
                word >>= 2;
                process_word(word);
                word = 0;
                started = false;
            }
        }
    }
}

int main(void) {
    init_board();

    for (uint16_t i=0; i<BUF_SIZE; i++) {
        buffer[i] = 0;
    }

    uint32_t period_0 = TIM2->ARR;
    int16_t period_tune_p = 0;
    int32_t period_tune_i = 0;

    int32_t neg_peak_value;
    uint8_t neg_peak_time;
    uint8_t symbol_sample_time = 16;
    uint8_t time = 0;

    int32_t phase_error_slow;
    int32_t phase_error_d;

    int16_t x = 0;
    int16_t t = 0;

    while (1) {
        if (have_sample) {
            have_sample = false;

            // PLL
            int16_t a = atan2(Q, I) * 180 / PI;
            int16_t phase_error = a;
            if (phase_error > 90) {
                phase_error -= 180;
            }
            if (phase_error < -90) {
                phase_error += 180;
            }
            phase_error_slow = (phase_error_slow * 15 + phase_error) / 16;
            phase_error_d = phase_error - phase_error_slow;

            period_tune_p = phase_error * 4;

            TIM2->ARR = period_0 + period_tune_p;


            int32_t previous_I = delay_I[delay_ptr];
            int32_t previous_Q = delay_Q[delay_ptr];
            delay_I[delay_ptr] = I;
            delay_Q[delay_ptr] = Q;
            delay_ptr = (delay_ptr + 1) & 31;

            // scalar product with delayed sample
            int32_t prod = I * previous_I + Q * previous_Q;

            if (time == symbol_sample_time) {
                t = -200;
                if (prod > 0) {
                    x = 100;
                    decode_bit(true);
                } else {
                    x = 0;
                    decode_bit(false);
                }
            } else {
                t = -100;
            }


            //uart_send_16(prod >> 10);
            //uart_send_16(x);
            //uart_send_16(t);

            if (prod < 0 && prod < neg_peak_value) {
                neg_peak_value = prod;
                neg_peak_time = time;
            }

            // the symbol sampling clock is accurate (because we
            // have a crystal oscillator) but we must correct its
            // phase so that it coincides with the negative peaks.
            // We do this adjustment 16 ms after each negative peak.
            if ((time - neg_peak_time == 16) || (time + 32 - neg_peak_time == 16)) {
                int8_t diff = neg_peak_time - symbol_sample_time;
                if ((diff > 0 && diff <= 16) || (diff <= -16)) {
                    symbol_sample_time = (symbol_sample_time + 1) & 31;
                }
                if ((diff < 0 && diff > -16) || (diff > 16)) {
                    symbol_sample_time = (symbol_sample_time - 1) & 31;
                }
                neg_peak_value = 0;
                neg_peak_time = 255; //
            }

            if (I + Q > 3000) {
                HAL_GPIO_WritePin(PORT(LED_GREEN), PIN(LED_GREEN), 1);
            } else {
                HAL_GPIO_WritePin(PORT(LED_GREEN), PIN(LED_GREEN), 0);
            }

            time = (time + 1) & 31;
        }
    }
}


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
    int32_t value = HAL_ADC_GetValue(hadc);
    int32_t old = buffer[buffer_ptr];
    buffer[buffer_ptr] = value;
    if (++buffer_ptr == BUF_SIZE) {
        buffer_ptr = 0;
    }

    if (phase == 0) {
        I -= old;
        I += value;
    } else if (phase == 1) {
        Q -= old;
        Q += value;
    } else if (phase == 2) {
        I += old;
        I -= value;
    } else {
        Q += old;
        Q -= value;
        have_sample = true;
    }
    phase = (phase + 1) & 3;

    if (phase & 1) {
        HAL_GPIO_TogglePin(PORT(D12), PIN(D12));
    }

}


Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, das sieht ja sehr gut aus. Woher hast die Empfangsdaten?

Ich habe mal Web-SDR ausprobiert, aber es gibt immer Unterbrechungen und 
bei 14070 MHz gar kein Empfangssignal.

Was mir bei Deinem "Direktmischer" auffällt: bei 4kHz ADC-Frequenz wird 
jeder der beiden IQ-Kanäle nur mit 2kHt abgetastet. Ist das richtig?

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
marc schrieb:
> Hey, das sieht ja sehr gut aus. Woher hast die Empfangsdaten?

Ich hab hab einfach das Mikrofon (+ zweistufiger Verstärker + 
STM32-Evaluation-Board) vor die PC-Lautsprecher gehalten (bis die Frau 
sich über das nervige Gefiepe beschwert hat) während ich im Web-SDR 
versucht habe so abzustimmen dass ich einen der Träger genau auf 1kHz 
bekomme (das ist gar nicht so leicht denn man kann dort nur in 
30Hz-Schritten abstimmen und das ist viel zu grob für meinen engen 
Filter und ich muss die Frequenz auf +-3Hz genau treffen, da muss ich 
mir noch was besseres überlegen)

>
> Ich habe mal Web-SDR ausprobiert, aber es gibt immer Unterbrechungen und
> bei 14070 MHz gar kein Empfangssignal.

Ja, gestern hats den ganzen Abend lang übel gestottert, das hat 
angefangen genau in dem Moment als ich fertig war und es ausprobieren 
wollte, das ist nicht immer so, normalerweise geht das besser.

> Was mir bei Deinem "Direktmischer" auffällt: bei 4kHz ADC-Frequenz wird
> jeder der beiden IQ-Kanäle nur mit 2kHt abgetastet. Ist das richtig?

Ja, das ist der Trick dabei, so muss ich nicht multiplizieren, die 
Koeffizienten sind abwechselnd 1 und -1. Was ich da eigentlich mache ist 
eine DFT über 32 Perioden für nur eine einzige Frequenz mit einem 
gleitenden Rechteckfenster. Oder ein anderer Weg es zu sehen ist ich 
korreliere (falte? mische?) das Signal mit einem Sinus (und einem 
Cosinus) von genau der selben Frequenz und raus kommen zwei Zahlen (die 
konstant wären wenn ich die Frequenz eines unmodulierten Trägers genau 
treffen würde), das Basisbandsignal kommt da direkt raus.

Das wirkt auch wie ein Filter und bei plusminus 15Hz ist die erste 
Nullstelle. Diese Anordnung ist mir eingefallen als mal jemand irgendwo 
im Forum erwähnte er habe in grauer Vorzeit mal ein Modem gebaut bei dem 
er durch geschickt gewählte Abtastfrequenz nur Koeffizienten in der Art 
von -1, 0, 1, 0 in seinen Filtern brauchte und es habe wunderbar 
funktioniert.

Ich weiß nicht ob diese Art von Anordnung (Filter und Mischer in einem) 
einen speziellen Namen hat, es hat zwei um 90° verschobene FIR-Filter 
mit Koeffizienten 1,-1,1,-1,... und es mischt das 1kHz Empfangssignal 
mit 1kHz Sinus und 1kHz Cosinus und heraus kommt direkt das Basisband. 
Es ist also gleichzeitig auch ein Direktmischer.

Mir ist übrigens aufgefallen daß man damit auch Unterabtastung machen 
kann wenn man bestimmte ganzzahlige Verhältnisse von Sample- und 
Abtastfrequenz trifft, zum Beispiel f_signal/f_sample = 3/4 (und noch 
andere, z.B. 5/4), das sind dann Spiegelfrequenzen von f_signal und 
f_abtast/2, mein Demodulator funktioniert also auch wenn ich ihm 3kHz 
oder 5kHz (und noch viele weitere) an den Eingang füttere. Die erste 
liegt bei 3kHz.

Wenn jemand weiß ob diese spezielle Filter-Mischer-Anordnung einen 
speziellen Namen hat, bitte her damit.

: Bearbeitet durch User
Autor: marc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich hab hab einfach das Mikrofon (+ zweistufiger Verstärker +
>STM32-Evaluation-Board) vor die PC-Lautsprecher gehalten (bis die Frau
>sich über das nervige Gefiepe beschwert hat)

Haha, so ging es mir auch. Ich konnte das Signal leider immer nur kurz 
abspielen, weil es immer Einspruch gab.

>Ja, das ist der Trick dabei, so muss ich nicht multiplizieren, die
>Koeffizienten sind abwechselnd 1 und -1. Was ich da eigentlich mache ist
>eine DFT über 32 Perioden für nur eine einzige Frequenz mit einem
>gleitenden Rechteckfenster.

Ah, das habe ich übersehen: Es ist einfach Sinus und Cosinus an 4 
Punkten abgetastet. Deshalb ergibt sich eine Sinus und Cosinus Frequenz 
von 1kHz bei 4kHz Abtastrate.

>Oder ein anderer Weg es zu sehen ist ich
>korreliere (falte? mische?)

Es ist ein Mischer:
http://de.wikipedia.org/wiki/Mischer_%28Elektronik%29

Das reelle Empfangssingal wird mit der komplexen Frequenz gemischt d.h. 
multipliziert. Dadurch verschiebt sich das gesuchte Signal auf die 
Frequenz 0 und kann mit dem Tiefpass von den störenden Frequenzen 
getrennt werden.

In Matlab/Octave kann man das in einer Zeile schreiben ( das i ist der 
komplexe Wert ):
signalMixed(n)=psk31_signal(n)*exp(i*2*pi*fcarrier/fs*n);

Dein Verfahren ist ziemlich effizient, hat aber eine bestimmten 
Nachteil. Besser wäre es, das Signal mit 32 kHz statt mit 4 kHz 
abzutasten, weil sich dann die Störfrequenzen auf ein breiteres Spektrum 
verteilen. Alle Frequenzanteile über 2kHz, die Dein Anti-Aliasing Filter 
nicht unterdrückt, tauchen als Spiegelfrequenzen und Störung auf.

Autor: chris_ (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier ein Text to Signal Converter für PSK31 Signale in Octave.
Das Ganze ist ein wenig langsam, aber die Signale werden korrekt 
erzeugt.

Autor: marc (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Zum Vergleich habe ich eine Signal mit fs=20kHz und fs=4kHz erzeugt, um 
zu sehen, ob bei 4kHz die Störungen mehr zuschlagen.

Von links nach rechts:

fs=20khz ohne Störung, dann SNR=-15db, dann fs=4kHz mit SNR=-15dB

so richtig viel schlechter scheint das 4kHz Signal nicht zu sein. Liegt 
das vielleicht an meiner Methode? Wahrscheinlich müsste ich das Rauschen 
um den Faktor 5 erhöhen, weil es ja erst dann der Faltung des Rauschens 
in den 4kHz Bereich entspricht.

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
marc schrieb:
> Es ist ein Mischer:
> http://de.wikipedia.org/wiki/Mischer_%28Elektronik%29
>
> Das reelle Empfangssingal wird mit der komplexen Frequenz gemischt d.h.
> multipliziert. Dadurch verschiebt sich das gesuchte Signal auf die
> Frequenz 0 und kann mit dem Tiefpass von den störenden Frequenzen
> getrennt werden.
>
> In Matlab/Octave kann man das in einer Zeile schreiben ( das i ist der
> komplexe Wert ):
> signalMixed(n)=psk31_signal(n)*exp(i*2*pi*fcarrier/fs*n);

Das was ich da gebaut habe ist aber auch gleichzeitig ein Filter. Es 
werden immer 32 Perioden aufsummiert. Laut Octave müsste der 
Frequenzgang so aussehen wie im ersten Bild.
b = repmat([1,0,-1,0],1,32)
freqz(b, 1, 8192, 0, 4000)

Und das was ich messe ist in den zwei anderen Bildern (x-Achse bitte 
ignorieren, das ist die Zeit in Millisekunden, ich hab währenddessen am 
Frequenzgenerator langsam manuell von unten nach oben durchgestimmt, die 
Minima und Maxima liegen aber auf den richtigen Frequenzen, das hab ich 
überprüft), einmal linear, einmal logarithmisch in dB, das Ergebnis 
entspricht also meiner Theorie.

Zum Mischer wird es erst dadurch daß ich nur bei jedem vierten Sample 
den Wert nehme.

Und das ist so weil ich durch die Art und Weise wie ich das 
implementiert habe gar nicht anders kann als nur jedes 4. Sample zu 
nehmen: Anstatt das Signal Sample für Sample durch den Filter 
durchzuschieben und jedesmal neu alle 128 Produkte zu berechnen und 
aufzusummieren addiere ich einfach 4 neu "berechnete" dazu und 
subtrahiere die 4 ältesten, ich schieb es also immer gleich in 4-er 
Schritten durch. Und das wiederum geht aber nur weil alle meine 
Filterkoeffizienten sich alle 4 Samples exakt wiederholen.

: Bearbeitet durch User
Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Zum Mischer wird es erst dadurch daß ich nur bei jedem vierten Sample
>den Wert nehme.

Nicht ganz.

Deine Nullen und Einsen sind exact die Abtastwerte eines Sinus und 
Cosinus wie sie für einen IQ-Mischer benötigt werden:
octave:1> n=0:3;
octave:2> f=1000;
octave:3> fs=4000;
octave:4> sin(2*pi*f/fs*n)
ans =

   0.00000   1.00000   0.00000  -1.00000

octave:5> cos(2*pi*f/fs*n)
ans =

   1.0000   0.00000  -1.0000  0.00000


Du betrachtest die Signal über 32 Stützstellen
octave:6> n=0:31;
octave:7> sin(2*pi*f/fs*n)
ans =

 Columns 1 through 12:

   0.00000   1.00000   0.00000  -1.00000  -0.00000   1.00000   0.00000  -1.00000  -0.00000   1.00000   0.00000  -1.00000

 Columns 13 through 24:

  -0.00000   1.00000   0.00000  -1.00000  -0.00000   1.00000   0.00000  -1.00000  -0.00000   1.00000   0.00000  -1.00000

 Columns 25 through 32:

  -0.00000   1.00000  -0.00000  -1.00000  -0.00000   1.00000   0.00000  -1.00000


Da es sich nur um Einsen und Nullen handelt, kann man die Multiplikation 
vereinfachen, weil

y=x*1 genau y=x entspricht.

bzw.

y=x*-1 genau y=-x

Durch die Summation mit dem Moving Average Filter ergibt sich hargenau 
das Ergebnis einer 32 Punkte DFT an der Stelle 1kHz.

Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein oben dargestellter Frequenzgang des Filters entspricht der 
Fensterfunktion der DFT
http://de.wikipedia.org/wiki/Fensterfunktion#media...

und wird schmaler, wenn Du die Filterlänge des MA erhöhst also z.B. 64 
statt 32 Abtastwerte nimmst. Allerdings geht dann der Vorteil der 
wegfallenden Multiplikationen verloren, da dann die Abtastrate erhöht 
werden muss und 8 statt 4 Stützstellen für Sinus und Cosinus benötigt 
werden.

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
chris_, Du hast Recht :-)

Ich hab mich nur etwas undeutlich ausgedrückt. Irgendwo weiter oben hab 
ich ja auch schon angedeutet daß man das was mein Mischer macht 
eigentlich auch genausogut als DFT bezeichnen könnte. Vom Verständnis 
her ist mir schon klar was da passiert, ich kanns mir auch schön 
veranschaulichen.

Die Frage war nur ob dieser Hack (nur Einsen und Nullen, neue addieren 
und alte subtrahieren um letztlich pro Sample nur noch zwei Additionen 
zu haben anstatt n Multiplikationen und n Additionen) oder wenigstens 
ganz generell die Idee eine DFT (oder diesen Spezialfall der DFT) als 
kombinierten Filter und Mischer zu verwenden einen besonderen Namen hat 
nachdem ich googlen kann um zu sehen was andere damit schon schönes 
gebaut haben.

: Bearbeitet durch User
Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm. Spezieller Name? Ich kenne das nur unter dem Oberbegriff Sampler. 
Wenn man Stützstellen wegläßt, führt das aber zu einem schlechteren S/N. 
Bzw. bei einer Phasennachregelung zu früheren Regelschwingungen und der 
zunehmenden Tendenz, daß die Chose noch früher aussetzt, also die Phase 
verliert... und dann irgendwann irgendwo irgendwie wieder einrastet...


marc schrieb:
>>Ich hab hab einfach das Mikrofon (+ zweistufiger Verstärker +
>>STM32-Evaluation-Board) vor die PC-Lautsprecher gehalten (bis die Frau
>>sich über das nervige Gefiepe beschwert hat)
>
> Haha, so ging es mir auch. Ich konnte das Signal leider immer nur kurz
> abspielen, weil es immer Einspruch gab.
>

Das muß irgendwas mit frau ansich zu tun haben. Ich kann hier auch von 
mehreren solchen Modellen berichten, die eine geradezu abartige 
Abneigung gegen elektronisches Audio haben. Ich dagegen kann mich an 
solchen Dingen und Motorgeräuschen regelrecht berauschen. Gibt doch nix 
schöneres, als blinkende LEDs, bei denen man weiß warum sie gerade 
blinken, oder?!!


Aber mal was anderes:
Ich mache solche Signalberechnungen immer in LTspice. Leider ist es 
grottelahm, wenn man da einige Bits komplett durch einen Demodulator 
durchackern läßt.
Funzt sowas in Octave usw. besser? Es sind ja immer vielleicht 100 Bits, 
die von einem Träger kommen. Das Ganze dann mehrfach leicht frequenz- 
und phasenversetzt, damit man Bitfehlerraten abschätzen kann.
Also wie lange braucht Octave auf welchem Rechner für welche 
Systembeschreibung?

: Bearbeitet durch User
Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich kenne das nur unter dem Oberbegriff Sampler.
> Wenn man Stützstellen wegläßt, führt das aber zu einem schlechteren S/N.

Für die Implementierung von Bernd trifft das aber nicht zu. zwar ist 
jede zweiter Sample beim sinus NUll

octave:4> sin(2*pi*f/fs*n)
ans =

   0.00000   1.00000   0.00000  -1.00000


Dafür ist der betrag des cosinus an der gleichen Stell Eins, so dass 
keine Information des Eingangssignals verloren geht.
octave:5> cos(2*pi*f/fs*n)
ans =

   1.0000   0.00000  -1.0000  0.00000

Es ist kein "trickreiches" Verfahren wie z.B. die DDS, bei der man 
gewisse Verluste an Genauigkeit in Kauf nimmt, um mit geringem 
Rechenaufwand ein Sinus-Signal zu erzeugen.
Das obige Verfahren ist in dem Sinne "trickreich", dass man das 
Verhältnis von Wunschfrequenz zu Abtastfrequenz so wählt, dass die 
Rechnung besonders einfach wird. Verluste an Genauigkeit gibt es 
gegenüber einem anderen Rechenverfahren nicht, es ist mathematisch 
exakt.

Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich mache solche Signalberechnungen immer in LTspice. Leider ist es
>grottelahm,
>...
>Also wie lange braucht Octave auf welchem Rechner für welche
>Systembeschreibung?

Das hängt von der Art der Programmierung ab.
Bei Matlab/Octave sind alle Variablen Vektoren bzw. Matrizen.

Man kann einen Sinus z.B. so berechnen lassen:


for n=1:1000000,
  x(n)=sin(2*pi*1/10*n);
end

dann ist die Berechnung des Sinus relativ langsam, da er Index für Index 
berechnet wird und Octave per "Malloc" für X in jedem Schritt neuen 
Speicher allocieren muss.

Folgende Berechnungsart ist viel schneller:

n=1:1000000;
x=sin(2*pi*1/10*n)

da octave jetzt die interne Vektormultiplikation benutzen kann und auch 
die Speichergröße vor der Berechnung klar ist.

Das obige Octave-Script

http://www.mikrocontroller.net/attachment/242758/O...

ist relativ langsam und braucht für die Umwandlung des Textes in das 
Signal auf meinem Rechner 5-10 Sekunden. Allerdings ist das Signal auch 
mehrere 100kB groß und ich habe viel mit Indexberechnungen gearbeitet. 
Bezüglich der Rechenzeit ist da noch einiges an Optimierungspotential.

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
wird besser (siehe Bild). Ich glaub an der Art und Weise wie der 
Symboltakt synchronisiert wird kann man noch was drehen, so hab ichs 
jetzt und das Ergebnis ist viel besser als beim ersten Mal:

            // scalar product with delayed sample
            int32_t prod = I * previous_I + Q * previous_Q;

            if (time == symbol_sample_time) {
                if (prod > 0) {
                    decode_bit(true);
                } else {
                    decode_bit(false);
                }
            }



            /*
             * Our symbol sampling clock frequency will be accurate enough
             * to hit the right symbol sample time 9 consecutive times in a
             * row (because we have a crystal oscillator) but we must correct
             * its phase occasionally. We make a slight correction on every
             * negative peak (negative peak means there was a phase change)
             */

            // record the exact time of the negative peak
            if (prod < neg_peak_value) {
                neg_peak_value = prod;
                neg_peak_time = time;
            }

            // We do this adjustment after the end of a negative peak.
            if (prod >= 0 && neg_peak_value < 0) {
                int8_t diff = neg_peak_time - symbol_sample_time;
                if ((diff > 0 && diff <= 16) || (diff <= -16)) {
                    symbol_sample_time = (symbol_sample_time + 1) & 31;
                }
                if ((diff < 0 && diff > -16) || (diff > 16)) {
                    symbol_sample_time = (symbol_sample_time - 1) & 31;
                }
                neg_peak_value = 0;
            }

Die beiden Stationen aus dem Screenshot kamen übrigens beide zwischen S7 
und S9 (schwankend) rein (laut web-SDR-Anzeige). Ich hab das Signal 
immer noch über den Umweg Lautsprecher+Mikrofon laufen.

Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke! Da kann ich ja Octave mit deinen Beispielen einfach mal 
ausprobieren. Offensichtlich kann man mit etwas Mathematikverständnis in 
Octave einfach tiefer und weiter Eingriff nehmen in die Art wie die 
Daten verwaltet werden, als in SPICE möglich ist. Speziell LTspice 
fehlen für sowas einfach ein paar wichtige Funktionen: u.a. Zähler, 
echte Digitalfunktionen im Sinne von Einzelbits, Start und Stop -Flags 
für automatische Aufzeichnung usw. Vielleicht lohnt es sich, speziell 
für solche Sachen nicht mehr LTspice zu benutzen und sich dafür in 
Octave einzuarbeiten.

Wäre es möglich vorerst die Diskussion auf die reine PSK-Demodulation zu 
beschränken? Also ohne den Varicode-Symboldekoder! Dann könnte man die 
Erkenntnisse auch im weiteren Sinne jenseits von speziell PSK31 
gebrauchen.

Kannst du mal das Ergebnis von "Das obige Octave-Script..." als 
Wave-Datei posten?
Hat schonmal jemand untersucht, inwieweit MP3, OGG etc. das Signal 
durchlassen?

Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
chris_ schrieb:
>> Ich kenne das nur unter dem Oberbegriff Sampler.
>> Wenn man Stützstellen wegläßt, führt das aber zu einem schlechteren S/N.
>
> Für die Implementierung von Bernd trifft das aber nicht zu. zwar ist
> jede zweiter Sample beim sinus NUll
> ...
> Dafür ist der betrag des cosinus an der gleichen Stell Eins, so dass
> keine Information des Eingangssignals verloren geht.
>
> ...
>
> Es ist kein "trickreiches" Verfahren wie z.B. die DDS, bei der man
> gewisse Verluste an Genauigkeit in Kauf nimmt, um mit geringem
> Rechenaufwand ein Sinus-Signal zu erzeugen.
> Das obige Verfahren ist in dem Sinne "trickreich", dass man das
> Verhältnis von Wunschfrequenz zu Abtastfrequenz so wählt, dass die
> Rechnung besonders einfach wird. Verluste an Genauigkeit gibt es
> gegenüber einem anderen Rechenverfahren nicht, es ist mathematisch
> exakt.

Das bezieht sich doch auf die Phasenlage des lokalen Oszillators im 
Empfänger in Bezug auf die Phasenlage des empfangenen Signals. Wenn nun 
der Oszillator genau äh 90° (??) verschoben ist, so sind sin und cos 
jeweils bei 45° und damit numerisch auf 0,7..
Leistungsmäßig auf 0.5 ! Die Detektionswahrscheinlichkeit wäre dann 
genau 50%. sin und cos werden korreliert, damit sinkt der S/N an dieser 
exakten Stelle um 3dB.
Je nach lokaler Phasenlage (z.B. im Präambel-Suchzeitbereich, wo der 
Empfängeroszillator einrasten [könnte]), 'wabert' also das S/N abwärts 
bis 3dB von Optimum 0dB (Wenn man den theoretischen Detektionsverlust 
von DBPSK hier schon abgezogen hat vom Realwert).

Oder denke ich falsch? Ich hoffe ich habe mich halbwegs verständlich 
gemacht.

Man muß bei solchen Betrachtungen auch immer abwägen zwischen möglichst 
nahe am theoretisch möglichen für eine spezielle Modulationstechnik und 
der Frage wie lange der Demodulator zum Einrasten brauch speziell bei 
Burst-Betrieb (also wenn zeitlich schnell aufeinander diverse 
unterschiedliche Sender zu verkraften sind). Auf einem 'Bussystem' wird 
man eher auf eine kurze Synchronisationszeit Wert legen, um Zeitverluste 
mit Datenmüll zu minimieren. Also die Durchlaß-Sättigungsgrenze des 
Mediums möglichst hoch halten.


Um nochmal auf oben zurückzukommen: Wenn man nun mehr Samples berechnet 
pro komplette Bitzeit, dann werden diese genannten 3dB kleiner. Das wäre 
der Fall von Multiplikation mit 0, -1, +1.
Bei Analogmodulation gibt es natürlich keine Schwankungen der 
Empfangsamplitude auf dem Einheitskreis. Der Radius ist dann immer =1. 
Um das anzunähern, brauch man nur einige wenige Bits 
Amplitudenauflösung. Erkauft sich aber im Umkehrschluß eine zunehmende 
Amplitudenstörungsempfindlichkeit, die ein Komparator (der nur -1 und +1 
liefern kann) nicht hat.
In einem kleinen bestimmten Bereich, gibt es sogar einen 
Detektionsgewinn wenn man einen Komparator benutzt und nicht eine 
volllineare Multiplikation hinlegt.

: Bearbeitet durch User
Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abdul K. schrieb:
> verschoben ist, so sind sin und cos
> jeweils bei 45° und damit numerisch auf 0,7..
> Leistungsmäßig auf 0.5 !

No, Leistungsmäßig zusammen immer noch auf 1:
>> sin(pi/4)^2 + cos(pi/4)^2
ans =  1
>> sin(0)^2 + cos(0)^2
ans =  1
>> sin(42)^2 + cos(42)^2
ans =  1

Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht so recht, was ich dazu sagen soll! Bei meinen 
Simulationen haben eigentlich alle stark digital arbeitenden 
Demodulatoren Probleme, wenn die Phasenlage nicht passend ist. Also 
brauch man eine Loop, die die Phase 1. erkennt und 2. nachregelt. Und 
das dann bitte ohne Schwingen - was es extrem kompliziert, denn entweder 
hängt es irgendwann leicht daneben oder fängt an sich zum Oszillator zu 
entwickeln...

Und jede Regelung verzögert die Erkennung eines Datenpakets extrem! Was 
die Präambel automatisch verlängert und damit die Sättigungsgrenze des 
Übertragungskanals verschlechtert.
Phasengeregelte Demodulatoren brauchen typisch 30 bis 100 Bits zum 
Einrasten. Demodulatoren, die komplett asynchron demodulieren können, 
schaffen das in der Zeit von 2 Bits.


Bist du denn mit meinen sonstigen Bemerkungen zufrieden und hast nichts 
einzuwenden?

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abdul K. schrieb:
> Bei meinen
> Simulationen haben eigentlich alle stark digital arbeitenden
> Demodulatoren Probleme, wenn die Phasenlage nicht passend ist.

Passend zu was? Mein Demodulator vergleicht die Phase mit der Phase von 
einer Symbollänge zuvor. Deshalb spielt die absolute Phasenlage 
überhaupt keine Rolle, einzig die Abweichung der Mischerfrequenz vom 
Träger sollte erheblich kleiner als die Symbolrate sein, so dass es sich 
nicht allzuweit weitergedreht hat zwischen 2 Symbolen.


> Bist du denn mit meinen sonstigen Bemerkungen zufrieden und hast nichts
einzuwenden?

Mir ist noch nicht ganz klar wo der eigentliche Kritikpunkt liegen soll, 
mir ist nicht klar warum Du plötzlich weniger Signal und mehr Rauschen 
hast wenn das Signal um 45° phasenverschoben abgetastet wird, eventuell 
liegt das an der Art wie Dein Demodulator arbeitet, wirfst Du Q weg und 
betrachtest nur I? Meine Demodulator berücksichtigt I und Q 
gleichermaßen, der Betrag dieses Vektors ist bei jeder Phasenlage 
gleich.

Simuliert hab ichs noch nicht (zumindest nicht außerhalb meines Kopfes), 
dazu fehlt mir die Kenntnis von Octave, ich habs stattdessen einfach 
kurzerhand implementiert und ausprobiert, aber vielleicht kannst Du es 
ja mal schnell simulieren und mit Deinen anderen Simulationen 
vergleichen.

Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd schrieb:
> Abdul K. schrieb:
>> Bei meinen
>> Simulationen haben eigentlich alle stark digital arbeitenden
>> Demodulatoren Probleme, wenn die Phasenlage nicht passend ist.
>
> Passend zu was?

Passend zum Symboltakt der Bits die reinkommen, logischerweise.


> Mein Demodulator vergleicht die Phase mit der Phase von
> einer Symbollänge zuvor. Deshalb spielt die absolute Phasenlage
> überhaupt keine Rolle, einzig die Abweichung der Mischerfrequenz vom
> Träger sollte erheblich kleiner als die Symbolrate sein, so dass es sich
> nicht allzuweit weitergedreht hat zwischen 2 Symbolen.
>

Jo, daß ist der Ansatz der DIFFERENTIEAL-BPSK.
Aber hast du deinen Demodulator auch mal länger laufen lassen. 
Irgendwann (eigentlich leicht berechenbar wann) ergibt sich keinerlei 
Amplitude mehr hinter diesem, danach gehts dann wieder aufwärts. Eine 
Schwebung eben.

Eine Korrektur ist also unumgänglich, wenn du einen Demodulator benutzt 
der synchron laufen muß. Darin unterscheidet sich BPSK und DBPSK 
überhaupt nicht.


>
>> Bist du denn mit meinen sonstigen Bemerkungen zufrieden und hast nichts
> einzuwenden?
>
> Mir ist noch nicht ganz klar wo der eigentliche Kritikpunkt liegen soll,

Kritik ist das falsche Wort. Sagen wir mal Einwendungen oder Nachfragen. 
Ich habe gar nichts gegen den Thread!


> mir ist nicht klar warum Du plötzlich weniger Signal und mehr Rauschen
> hast wenn das Signal um 45° phasenverschoben abgetastet wird, eventuell
> liegt das an der Art wie Dein Demodulator arbeitet, wirfst Du Q weg und
> betrachtest nur I? Meine Demodulator berücksichtigt I und Q
> gleichermaßen, der Betrag dieses Vektors ist bei jeder Phasenlage
> gleich.
>

Muß ich mir nochmal ansehen, wenn ich durch Octave besser durchsteige. 
Ich bin gerade bedient von Pfadangaben die keine Leerzeichen haben 
dürfen und c:\octave\ vorgegeben. Aber sonst sieht es gut aus.


> Simuliert hab ichs noch nicht (zumindest nicht außerhalb meines Kopfes),
> dazu fehlt mir die Kenntnis von Octave, ich habs stattdessen einfach
> kurzerhand implementiert und ausprobiert, aber vielleicht kannst Du es
> ja mal schnell simulieren und mit Deinen anderen Simulationen
> vergleichen.

Leider ist schnell nichhh. Deswegen will ich ja Octave in meine 
Werkzeugkiste aufnehmen, wenns besser paßt.


Eigentlich versuche ich nur besser zu verstehen, was einen guten 
Demodulator von einem schlechten unterscheidet. Manches bekomme ich 
intellektuell sauber hin, an anderen Stellen scheitere ich kläglich.
z.B. ist diese irre Frequenzempfindlichkeit (also delta Frequenz 
Sender-Empfänger) bei BPSK mir nicht ganz erklärlich. Das behindert 
diese Modulationsart im praktischen Einsatz massiv. Und wie könnte man 
das deutlich erleichtern? Gibt z.B. den Ansatz, die BPSK nach DBPSK eine 
Stufe weiter zu treiben in dem Sinne von DDBPSK. Das verschlechert zwar 
das S/N, aber relaxt auch die Frequenzempfindlichkeit. Gibt da Papers zu 
im Sat-Bereich. Über D^3(BSPK) fand ich noch nichts. Verstehen tue ich 
es auch nicht richtig.
Wenn man es mathematisch nicht nachts im Bett zerlegen kann, muß man 
tagsüber simulieren ;-)

Also vorran!

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich habs jetzt mal auf dem ATMega328 implementiert. Diese Variante 
benötigt keine einzige(!) Multiplikation, dafür aber satte 400 Byte RAM:

https://gist.github.com/prof7bit/ea9b272c80182eeaccba

Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>So, ich habs jetzt mal auf dem ATMega328 implementiert.

Sehr schön. Das ist ja der gleiche Prozessor wie auf einem Arduino Uno.
Falls sich die Interrupts nicht mit der Arduino-Lib beißen würden, 
könnte man es direkt darauf laufen lassen. Dann wäre es für eine große 
Community verfügbar.

Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Abdul K. schrieb:
>> verschoben ist, so sind sin und cos
>> jeweils bei 45° und damit numerisch auf 0,7..
>> Leistungsmäßig auf 0.5 !

Bernd schrieb:
>No, Leistungsmäßig zusammen immer noch auf 1:

>>> sin(pi/4)^2 + cos(pi/4)^2
>ans =  1
>>> sin(0)^2 + cos(0)^2
>ans =  1
>> sin(42)^2 + cos(42)^2
>ans =  1

Hier die Darstellung in Octave.

Wir erzeugen ein komplexes signal:
octave> fs=4000;
octave> f=1000;
octave> n=0:3
n =

   0   1   2   3

sig =

 Columns 1 through 3:

   1.00000 + 0.00000i   0.00000 + 1.00000i  -1.00000 + 0.00000i

 Column 4:

  -0.00000 - 1.00000i


Der Betrag des Signals ist an jeder Stelle 1:
octave> abs(sig)
ans =

   1   1   1   1

Und das selbe Signal um pi/4 phasenverschoben:
octave:20> sig=exp(i*(2*pi*f/fs*n+pi/4))
sig =

 Columns 1 through 3:

   0.70711 + 0.70711i  -0.70711 + 0.70711i  -0.70711 - 0.70711i

 Column 4:

   0.70711 - 0.70711i

Der Betrag des Signals ist wieder an jeder Stelle 1:

octave> abs(sig)
ans =

   1   1   1   1



Die Koeffizienten sind jetzt alle 1/wurzel(2). Die Multiplikation kann 
jetzt nicht mehr eingespart werden. Aber das verschobene Signal bringt 
auch keinen Gewinn an Genauigkeit, deshalb ist Bernd's Methode ohne 
Multiplikation auch völliig ausreichend.

Abdul K. schrieb
>Kannst du mal das Ergebnis von "Das obige Octave-Script..." als
>Wave-Datei posten?
Wenn Du Octave installiert hast, kannst Du obiges Script einfach laufen 
lassen. Die letzte Zeile ist für das Abspeichern des WAV-Files, die habe 
ich auskommentiert.

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
chris_ schrieb:
> Sehr schön. Das ist ja der gleiche Prozessor wie auf einem Arduino Uno.
> Falls sich die Interrupts nicht mit der Arduino-Lib beißen würden,

Von der Arduino-lib hab ich keine Ahnung, benutze ich auch nicht, 
allerdings läuft das in der Tat momentan auf der Hardware eines 
Arduino-Uno-Klons, siehe Bild :-)

(Ich hab die Schaltung mal von Steckbrett auf Drahtigel umgebaut, das 
war zu wackelig)

Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Bernd,

eine lustige Drahtigelkonstruktion hast Du da. Manchmal löte ich auch 
Drahtigel, aber ich verwende mittlerweile ganz gerne Erdnuss- oder 
Cashewkerndosen von Aldi als Grundlage. Ich drehe die Dosen mit dem 
Deckelboden nach oben und löte dann die Schaltung oben drauf. Meistens 
klebe ich noch mit doppelseitigem Klebeband kleine Kufpferplatinenstücke 
darauf. Das Ganze steht dann sehr stabil auf dem Tisch.

>Von der Arduino-lib hab ich keine Ahnung,

Bei der Arduino Lib sehe ich den Vorteil, dass man den Code einfach in 
die IDE kopieren kann und dann "downloaden". Bei reinem Code muss man 
erst eine Umgebung aufsetzen.

Autor: Floppy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
> chris_ schrieb:
>> Sehr schön. Das ist ja der gleiche Prozessor wie auf einem Arduino Uno.
>> Falls sich die Interrupts nicht mit der Arduino-Lib beißen würden,
>
> Von der Arduino-lib hab ich keine Ahnung, benutze ich auch nicht,
> allerdings läuft das in der Tat momentan auf der Hardware eines
> Arduino-Uno-Klons, siehe Bild :-)
>
> (Ich hab die Schaltung mal von Steckbrett auf Drahtigel umgebaut, das
> war zu wackelig)

Hallo Bernd,

kannst Du mal die Schaltung skizzieren? Habe auch einen Arduino, würde 
aber gerne mal eine eigene Schaltung aufbauen! An welchem Port hast du 
das Signal angeklemmt?

Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
chris_ schrieb:
>>Abdul K. schrieb:
>>> verschoben ist, so sind sin und cos
>>> jeweils bei 45° und damit numerisch auf 0,7..
>>> Leistungsmäßig auf 0.5 !
>
> Bernd schrieb:
>>No, Leistungsmäßig zusammen immer noch auf 1:
>
>>>> sin(pi/4)^2 + cos(pi/4)^2
>>ans =  1
>>>> sin(0)^2 + cos(0)^2
>>ans =  1
>>> sin(42)^2 + cos(42)^2
>>ans =  1
>
> Hier die Darstellung in Octave.
>
> Wir erzeugen ein komplexes signal:
>

Danke für deine Ausführung! Lassen wir das erstmal beiseite. Ich kann 
darauf nicht wirklich sinnvoll eingehen.


> Abdul K. schrieb
>>Kannst du mal das Ergebnis von "Das obige Octave-Script..." als
>>Wave-Datei posten?
> Wenn Du Octave installiert hast, kannst Du obiges Script einfach laufen
> lassen. Die letzte Zeile ist für das Abspeichern des WAV-Files, die habe
> ich auskommentiert.

Jo, habs installiert. Die Version der Spanier UPM R8.2 mit GUI.


Wäre es möglich, die Source oder die fertigen wave-Files von dem 
S/N-Versuch oben zu bekommen?
(Beitrag "Re: PSK 31 Modlulation im Mikrocontroller")
Würde gerne mal das wave auf meinen Demodulator in LTspice loslassen.
Vielleicht ist das irgendwo nun schon gepostet, ich finds aber nicht. 
Der Thread ist schon wieder zu lang geworden.

Also so ne Fehlerrate von 2 Bit falsch in 10 Bit insgesamt fände ich 
interessant zu vergleichen. Klar ist das unrealistisch, besser wäre 
sowas wie 1 Fehler in 100 oder gar 1000 Bits, nur sind dann die 
Simulationszeiten zumindest in LTspice sowas von irrsinnig lang, daß es 
keinen Sinn mehr macht. 1000 Bits bedeutet mehrere Stunden und 
vielleicht 3GByte Daten.
Ich weiß, daß diese Angabe quasi rückwärts ist, denn normalerweise 
definiert man das S/N und erhält dann die Bitfehlerrate, und nicht 
umgekehrt.

Müßte man noch ne sinnvolle Bandbreite fürs Breitbandrauschen sich 
ausdenken. 2,5KHz für einen SSB-Empfänger? Also das wären dann geschätzt 
3,5KHz bis 5KHz Rauschbandbreite für ne weiche Filterkurve des 
Empfängers.

Autor: Bernd K. (prof7bit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hab mir heute überlegt was wäre wenn ich einen extrem scharfen 
IIR-Bandpass zur Gewinnung des Symboltaktes verwende anstelle einer PLL.
int16_t filter_bandpass_32Hz(int16_t val) {
    static int32_t back1 = 0;
    static int32_t back2 = 0;
    int32_t acc = (int32_t)val << 7;
    acc += 32080 * back1;
    acc -= 16325 * back2;
    back2 = back1;
    back1 = acc >> 14;

    return acc >> 16;
}

Zwei von denen hab ich mal testweise hintereinandergeschaltet, Ergebnis 
siehe Bild. Allerdings ist das ziemlich knifflig den richtig 
einzustellen, und ich hab wieder einige Multiplikationen drin. Aber das 
Ergebnis scheint mir um einiges besser! Ich kann jetzt so viel Rauschen 
drüber legen daß ich das Signal nur noch mit sehr viel gutem Willen 
raushören kann, jedoch wird es immer noch fehlerfrei dekodiert. Mit der 
vorherigen Version wars deutlich anfälliger.

Autor: Abdul K. (ehydra) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal Bilder von der Phasenabhängigkeit, die ich oben erwähnte.
Oben mit wenig Rauschen im Signal, unten mit viel. In beiden Sims wird 
die Phase innerhalb 360° alle 20° durchgerechnet. Man sieht schön, wie 
bei meinem Demodulator das S/N von der aktuell verwendeten Phasenlage 
abhängt.

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abdul K. schrieb:
> In beiden Sims wird
> die Phase innerhalb 360° alle 20° durchgerechnet. Man sieht schön, wie
> bei meinem Demodulator das S/N von der aktuell verwendeten Phasenlage
> abhängt.

Wo sieht man die Phasenlage? Und die Phase von was relativ zu was 
(weiter oben gings Dir zunächst um die Phasenlage des Trägers (beim 
Samplen und im Mischer), später dann meintest Du plötzlich die 
Phasenlage des Symboltaktes, also welche Phasenlage nun)? Was sieht man 
da überhaupt in den Bildern? Es ist zwar alles schön bunt aber was ist 
was? Es ist nicht gerade selbsterklärend.

Autor: Abdul K. (ehydra) Benutzerseite
Datum:
Angehängte Dateien:
  • preview image for 23.jpg
    23.jpg
    114 KB, 146 Downloads

Bewertung
0 lesenswert
nicht lesenswert
Naja, hast recht. 1. ist es zu wenig Auflösung und 2. weiß ich nicht 
mehr genau was ich tat. Ist schon ein paar Monate her, wo ich das 
Diagramm erzeugte.


Also hab ich die letzte Version nochmal komplett durchrechnen lassen und 
angehängt:

Zeile 1 ist das bandpaßgefilterte Eingangssignal noch mit Träger. Die 
Phasensprünge kann man gut sehen.

Zeile 2 ist das Signal nach dem Demodulator. Die verschiedenen Farben 
sind jeweils ein 20° Step der Phasenlage aus den 360°. Die Phase wird 
nicht nachgeregelt!

Zeile 3 ist das per Komparator digitalisierte Signal von Zeile 2. Hier 
kann man schön die Flankenverschiebung sehen. Wenn die Flanke zu weit 
wegwandert, gibts ein Fehlerbit.

Ansich entspricht die Schaltung dem vorherig geposteten Bild. Ist hier 
nur mit wenig Rauschen am Eingang durchgerechnet.

Nein, die Schaltung werde ich nicht veröffentlichen (Ich halte sie für 
neuartig). Ich würde sie nur gerne leistungsmäßig vergleichen mit euren 
Ideen.

: Bearbeitet durch User
Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abdul K. schrieb:
> Zeile 1 ist das bandpaßgefilterte Eingangssignal noch mit Träger. Die
> Phasensprünge kann man gut sehen.

Warum ist die Amplitude nicht konstant während der Zeit während der 
"1"-Bits gesendet werden? Während einer Folge zusammenhängender 1-Bits 
soll doch weder die Phase wechseln noch die Amplitude, während dieser 
Zeit sollte da ein unmodulierter Träger stehen.

Ein Schwanken zwischen 100% und 140% könnt ich mir noch erklären wenn Du 
(so wie ich in meinem Code [der zweiten Version, nicht der ersten]) die 
Amplitude nicht über sqrt(I² + Q²) ausrechnest sondern nach 
Manhattan-Metrik abs(I)+abs(Q) und sich die Phasenlage derweil aufgrund 
leicht daneben liegender Frequenz langsam weiterdreht, aber was sollen 
die kompletten Einbrüche bei jedem zweiten Mal?

Und dann ist natürlich schwer zu sagen was dann passiert (und warum) 
wenn Du nicht offenlegst wie Du das Signal dann weiter verarbeitest, wie 
Du von Zeile 1 nach Zeile 2 kommst (oder wie Zeile 1 überhaupt zustande 
kommt, denn das sieht nicht wie ein rohes PSK31-Signal aus, das ist 
schon auf irgendeine Weise irgendwie verändert, ich kann mir aber grad 
beim besten Willen nicht vorstellen wie).

: Bearbeitet durch User
Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mich einfach mal auf das RDS gestürzt und daher ist es nicht 
einfach nur DBPSK.
Bei RDS wird das Baseband DBPSK-Signal nochmals biphase auf den Träger 
moduliert. Deswegen ist auf der eigentlichen Trägerfrequenz keine Linie.

Vorne weg ist ein analoger Bandpaß halbwegs passender Bandbreite. Daher 
ist die Amplitude niemals konstant.


Die Schaltung macht alles auf einmal:
1. Undersampler
2. phasenunabängiger Korrelator (Der Punkt ist etwas eingeschränkt)
3. Biphase-Demodulation
4. Differentialdemodulation

Alles mit ein paar wenigen Gattern und Flip-Flops. Was noch fehlt ist 
die Bittaktregeneration. Da habe ich noch keine super Idee für. Man 
könnte sich mit einem schnöden Taktteiler behelfen, der einfach an 
Flanken auf den halben Wert gesetzt wird. Dann erreicht man aber nicht 
das allerbeste S/N. Sollte aber ganz gut laufen, wenn das analoge 
Vorfilter leistungsfähig ist.


Naja, wie gesagt ich möchte es nur zu eurem Ansatz leistungsmäßig 
vergleichen. Befürchte nur, daß ich da noch kräftig umbauen muß um 
vergleichen zu können. Und da liegt das eigentliche Problem: Ich 
verstehe die eigene gefundene Schaltungsstruktur nicht komplett! Klar, 
das ist nicht euer Problem und ohne die Schaltung offenzulegen und zu 
erklären, sowieso kein Thema. Aber eure Gedanken helfen mir, Lösungen 
für mich zu finden.


Das Thema Bandpaß würde mich auch davon abgesehen weiter interessieren. 
Es hat mir mal jemand gesagt, ein RRCF könne man nicht als Bandpaß 
realisieren. Also was nimmt man dann? Ein Bessel, aber wie ergeben sich 
die Parameter??

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abdul K. schrieb:
> Das Thema Bandpaß würde mich auch davon abgesehen weiter interessieren.
> Es hat mir mal jemand gesagt, ein RRCF könne man nicht als Bandpaß
> realisieren.

da ist bei mir auch kein RRC im Spiel, mein experimenteller Ansatz war 
sehr simpel und pragmatisch (geradezu hemdsärmelig wie ich ja ganz zu 
Beginn meiner Postings warnte). Nachdem bei mir aus dem Demodulator 
etwas rausfällt was wohl am ehesten Deiner Zeile 2 entspricht habe ich 
einfach mittels gängiger Tools (z.B. hier: 
http://www.micromodeler.com/dsp/ ) einen möglichst schmalen IIR Bandpass 
hoher Güte zusammengeklickt der bei einer Samplingrate von 1kHz (das ist 
die Frequenz in der meine while() loop neue Samples entgegennimmt) eine 
Resonanzfrequenz von genau 31.25Hz hat. Also fs/32. Dort hinein habe ich 
das demodulierte Signal (das blaue Signal) geschickt, das enthält 
Anteile des Symboltaktes und heraus aus dem Filter kommt das gelbe 
Signal. Der Filter ist so haarscharf bemessen dass er beinahe (aber 
gerade eben noch nicht) von selbst oszilliert und wenn eine Weile lang 
nur 1-Bits kommen (also keine Anteile des Symboltaktes auf dem blauen 
Signal sind) schwingt er dennoch dutzende von Perioden lang weiter mit 
31.25Hz und exakt der passenden Phasenlage so daß es reicht neun 
einser-Bits (die längst-mögliche einser-Sequenz) zu überbrücken ohne daß 
er aus der Phase läuft. Das gelbe Signal hab ich dann also mal testweise 
als Symboltakt verwendet und es hat wunderbar funktioniert.

Das geht bei mir aber nur deswegen so einfach weil ich quarzstabile 
Samplerate habe und demnach mein digitaler Filter ebenso genau ist, 
deshalb läuft er nicht weg und hat seine Resonanz immer genau bei 1/32 
fs. Ich weiß nicht ob das bei Deiner diskret (und teils analog?) 
aufgebauten Anordnung so einfach einzubauen wäre, bei mir warens halt 
nur mal eben ein dutzend Zeilen Code.

: Bearbeitet durch User
Autor: Abdul K. (ehydra) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und du hast eine unmodulierte Spektrallinie auf deiner Filtermitte? Eine 
PLL kann ohne Linie nicht rasten, eine Costas-Loop dagegen ja.

Wenn man real BPSK benutzt, hat man immer Nichtlinearitäten in der 
Übertragung, die automatisch zumindest eine schwache Linie erzeugen und 
damit ein Einrasten ermöglichen.
Frag mich nicht, wie schwach die Linie sein darf. Hab ich noch keine 
Idee von.
Ich hab das mal näher untersucht und festgestellt, daß das 
Remodulator-Konzept immer daran scheitert. Keine ausreichende Linie, 
keine Demodulation.

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube da liegt ein Missverständnis vor. Oben erwähnten Filter 
verwende ich für den Symboltakt, für dessen Rekonstruktion nach 
bereits erfolgter Demodulation, nicht für den Träger.

Für den Träger benutze ich lediglich eine zeitverzögerte Version seiner 
selbst als Referenz, dieser Teil läuft vollkommen frei, nicht kohärent, 
da muss gar nichts einrasten. Das ist doch gerade der Trick dabei.

: Bearbeitet durch User
Autor: Abdul K. (ehydra) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ah. Immer dieses Aneinandervorbeireden. Schon erstaunlich wie weit du 
mit a bisserl Software kommst.


Ein direkter Vergleich ist, wie gesagt, meines Erachtens unmöglich. Ich 
habe kein zweistufiges Konzept. Der Träger wird direkt im Demodulator 
mit verwurstet. Das Ganze entstand über Monate aus diversen 
Überlegungen, Patentrecherche, Sims usw. Manches überlegt geändert, und 
abundzu würfele ich auch mal gezielt wenn ich keine bessere Idee habe. 
Wer macht das nicht ;-)
So, nachdem das fast ein Jahr rumlag, weil ich erschöpft war an dieser 
Sache, werde ich das Neuordnen und systematisch weitertesten.


Was die Ähnlichkeiten angeht:
Man kann die Biphasemodulation bei RDS auch als eine Verdopplung der 
Bitrate ansehen, wenn man sich darüber klar ist das die beiden Teilbits 
jeweils miteinander 'korrespondieren' (sage ich mal so).
Dann bleibt aber noch das feste Verhältnis von 24 zwischen 
Trägerfrequenz und Datentakt. Der Faktor ist wohl bei PSK31 ein anderer.

Die Symbol-Synchronisation läuft doch bei PSK31 ähnlich einem UART:
1. UART: Startbit(0)-Datenbits-Stopbit(1)
2. PSK31: Startbit(0)-variable Datenbitlänge (aber nie 
'00'-auftreten)-Stopbit(0)
Ich denke man kann es so sehen, wenn man die Übereinstimmungen betonen 
will.

Also z.B. retriggerbarer Monoflop, der von den Flangen getriggert wird, 
für den Takt.


Wer will kann ja mal versuchen RDS zu demodulieren. Im Thread von 
Bernhard sind dazu mehr Infos.

Hier poste ich noch die wave-Datei, die ich auch in der Sim benutze. Die 
wurde von einem Spezialprogramm für die Synthese von RDS-Datenströmen 
erzeugt und ist für Soundkarten mit 192KHz Samplerate Mono gedacht. Das 
reicht für einen Träger bei 57KHz durchaus aus.
Mehr will ich den Thread auch nicht kapern.

Autor: chris_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Floppy schrieb:
>Hallo Bernd,
>kannst Du mal die Schaltung skizzieren? Habe auch einen Arduino, würde
>aber gerne mal eine eigene Schaltung aufbauen!

Das dürfte ein zweistufiger Transistormikrofonverstärker sein:
http://www.elexs.de/ev4.gif

von http://www.elexs.de/kap5_2.htm

>An welchem Port hast du das Signal angeklemmt?

Ich würde sagen, wenn Du das Bild anschaust, siehst Du, dass das Signal 
an Analog 0 angeklemmt ist.

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
chris_ schrieb:
> Das dürfte ein zweistufiger Transistormikrofonverstärker sein:
> http://www.elexs.de/ev4.gif

Genau das ist die Schaltung. Die Widerstände sind etwas anders, ich habe 
zwei unterschiedliche Transistoren die noch übrig waren in der 
Bastelkiste genommen und habe dann die Widerstände solange geändert bis 
ich ziemlich genau 2.5V am Kollektor hatte.

Zusätzlich hab ich noch ein C (paar hundert Picofarad) zwischen 
Kollektor und Basis des ersten Transistors weil er dazu neigte zu 
schwingen und übergebührlich HF aufgeschnappt hat, das war damit gut zu 
unterdrücken.

Vom Kollektor des zweiten gehe ich direkt auf den ADC, denn da habe ich 
ja bereits einen Gleichspannungsanteil von ungefähr 2.5V, das passt 
genau.

Die Schaltung ist eigentlich vollkommen egal, es gäbe zig andere 
Varianten, Hauptsache man bekommt das NF-Signal so verstärkt dass es mit 
einem brauchbaren Pegel (einige Volt Spitze-Spitze und ein DC-Anteil von 
2.5V) am ADC ankommt.

Eine Verbesserung wäre es analoge Tiefpässe mit einzubauen die alles 
oberhalb von 1kHz gut unterdrücken (oder gar Bandpässe die nur 1kHz 
durchlassen).

Autor: DH1AKF K. (wolfgang_kiefer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Bernd,

Bernd K. schrieb:
> Eine Verbesserung wäre es analoge Tiefpässe mit einzubauen die alles
> oberhalb von 1kHz gut unterdrücken (oder gar Bandpässe die nur 1kHz
> durchlassen).

... heute habe ich auf einem PSoC5 Dein Programm vom 2.1.2015, 
zusätzlich mit einem  65 Hz breiten 1000 Hz- Filter zum Laufen gebracht. 
Allerdings ohne die AFC. Man kann sehr schön über Twente mitlesen. Es 
fehlt noch eine Möglichkeit, um z.B. über eine FFT das Spektrum 
anzuzeigen und die Frequenz exakt einstellen zu können. Aber das wird 
auch noch.

Nochmals vielen Dank für Deine Beiträge!

Wolfgang

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.