Erkennung des Startbits bei UART mit FSK

Gast #3576352
Hallo zusammen,

ich überlege mir gerade eine Übertragungsart für serielle Daten über 
eine Audioleitung. Momentaner Stand ist, dass ich die logischen Pegel 
einer einfachen 1200 Baud UART mittels FSK moduliere und entsprechend 
beim Empfänger wieder demodulieren möchte.
Jetzt das Problem: Wie erkenne ich beim Empfänger, dass ein Startbit 
vorliegt? Die Detektion der beiden Spektralkomponenten geschieht über 2 
Goertzel-Filter. Allerdings ist mir nicht klar, über wieviele Samples N 
ich die Filter laufen lassen soll, um nichts zu "verpassen" und dennoch 
die Synchronisation bzgl. nachfolgender Bits zu gewährleisten?

Meine bisherige Idee wäre, N zunächst möglichst klein zu wählen und 
sobald das Filter eine Frequenz (=Startbit) erkennt, N auf die Anzahl 
der Samples pro Symbol bei gegebener Abtastrate zu setzen. Wäre das ein 
praktikabler Weg?

Vielleicht noch wichtig zu wissen: Die UART wird nicht auf einem µC 
implementiert, sondern in einer PC-Software.

Beste Grüße
Gast #3576375
Danke für den Tipp. Leider sind bei mir alle Frequenzen fest vorgeben:
Baudrate: 1225
Logisch 0: 4900 Hz
Logisch 1: 7350 Hz

Abtastrate: 44100, 48000 oder 96000 Hz, je nach Umgebung.

Damit fällt - zumindest nach meinem Verständnis - ein I&Q-Verfahren 
raus. Ich lasse mich da aber sehr gerne eines Besseren belehren!
(Firma: Brainit GmbH) #3576404
ich denke das sollte trotzdem gehen...

Mittenfrequenz: (4900+7350)/2 = 6125 Hz

4-fach abtasten: 24500Hz

andersrum: 48000 Hz, jedes zweite Sample verwenden: 24000 Hz, dividiert 
durch 4 = 6000 Hz, nicht weit daneben. Damit liefe halt die Phase in 
eine Richtung schneller als in die andere...
Gast #3576527
Blöderweise habe ich nicht die Wahl zwischen 44.1, 48 und 96 KHz, das 
kann sich von System zu System ändern.

Ich habe trotzdem mal deine Beispielrechnung simuliert mit MATLAB (Code 
aus deinem vorherigen Link):
1
baud = 1225;
2
fs = 44100;
3

4
% Signal für Simulation generieren
5
l = fs/baud;
6
w = 2*pi/(fs/(4900));
7
lo = sign(sin(linspace(0,w*l-1,l)));
8
w = 2*pi/(fs/(7350));
9
hi = sign(sin(linspace(0,w*l-1,l)));
10

11
signal = [lo, hi, lo, hi, hi, hi, lo];
12

13
faktor1 = 4;
14
inphase = signal(1:faktor1:length(signal));
15
quadratur = signal((1:faktor1:length(signal))+1);
16

17
% Samplingrate dezimieren
18
faktor2 = 2;
19
inphase_r = inphase(1:faktor2:length(inphase));
20
quadratur_r = quadratur(1:faktor2:length(inphase));
21

22
% Phasenverlauf berechnen
23
angles = unwrap(angle(inphase_r + 1i*quadratur_r));
24
plot(angles, '-o');

Das Ergebnis (siehe Plot) ist zumindest für 44.1 KHz so nicht zu 
gebrauchen, da werde ich wohl doch bei meinen Goertzeln bleiben.

Hättest du denn eventuell eine Idee, wie ich ein Startbit anständig mit 
Goertzel-Filtern detektieren könnte?
Angehängte Dateien:
(Firma: Brainit GmbH) #3576610
ich kenn mich leider mit matlab genau gar nicht aus, aber könnte dein 
Fehler hier liegen: im Original wird jedes 4. Sample für I verwendet 
(4*n) und jedes (4*n+1)te für Q. Du solltest aber doppelt so schnell 
abtasten, also 8*n bzw. 8*n+2 (note the "+2")

Ansonsten lass ich mal den Signalverarbeitern hier den Vortritt :-)
Gast #3576679
Hmm, einleuchtend! :-D
Dennoch sind die Ergebnisse unbrauchbar, die Abweichung von der idealen 
Abtastrate ist zu groß, die Fehler sind leider nicht ignorierbar.
Gast #3578900
Wenn du schon mit FSK arbeiten willst, dann solltest du dir merken, daß 
dein Dekodieralgorithmus lediglich das ursprüngliche Sendesignal 
wiederherstellen kann, also hi oder lo 
-->Modulator-->Transmission-->Demodulator--> hi oder lo. Mehr nicht, 
auch keine Startbiterkennung. Was dann ein anschließender 
Protokoll-Detektor draus macht, kommt dahinter und ist wirklich ein 
anderes Thema als deine FSK-Modulation.

W.S.
Gast #3581044
W.S. schrieb:
> Was dann ein anschließender
> Protokoll-Detektor draus macht, kommt dahinter und ist wirklich ein
> anderes Thema als deine FSK-Modulation.

Gut, das sehe ich natürlich ein. Dann stufe ich meine Frage mal ein 
klein wenig zurück: Welche Fenstergröße macht Sinn für eine 
Demodulation? Ich fange mit meiner Frequenzerkennung ja leider nicht 
passgenau zu Signalbeginn an.
(Firma: Brainit GmbH) #3586172
Ich hab mich jetzt nochmal etwas mit dem IQ-Demodulator gespielt. Da ich 
Mathematica weder habe noch bedienen kann, hab ich eine kleine 
Simulation in Perl programmiert.

Wenn ich da keinen groben Schnitzer eingebaut habe, spricht das Ergebnis 
für sich: das funktioniert nicht nur gut, sondern saugut!

Blau ist dein Nutzsignal, abgetastet mit 48kHz. Wechselt zwischen 4900Hz 
und 7350Hz mit einer Rate von 1225 Hz. X-Achse ist skaliert auf die 
Baudrate.

Rot ist der erkannte Phasor. Verschoben primär deshalb, weil die 
Erkennung nur alle 8 samples läuft.
Angehängte Dateien:
(Firma: Brainit GmbH) #3589078
Ist aber ein superquickhack :-)
Insbesondere die Richtungserkennung hat noch Optimierungspotential
1
#!/usr/bin/perl
2

3
use strict;
4
use warnings;
5

6
use constant PI => 4 * atan2(1, 1);
7

8
my $baud = 1225;
9
my $f0 = 4900;
10
my $f1 = 7350;
11

12
my $sample = 48000;
13

14
sub quadrant ($$) {
15
    my ($i, $q) = @_;
16
    return 1 if ($i >= 0 && $q >= 0);
17
    return 2 if ($i <= 0 && $q >= 0);
18
    return 3 if ($i <= 0 && $q <= 0);
19
    return 4;
20
}
21

22
    
23
my ($I_old, $I_new) = (0, 0);
24
my ($Q_old, $Q_new) = (0, 0);
25

26
my $dir = 0;
27

28
for (my $t = 0, my $i = 0; $t < 0.01; $t += 1.0/$sample, $i++ ) {
29

30
    my $a0 = sin (2*PI*$t*$f0);                                                                                                                                                               
31
    my $a1 = sin (2*PI*$t*$f1);                                                                                                                                                               
32
                                                                                                                                                                                              
33
    my $x = $t * $baud;                                                                                                                                                                       
34
    my $a;                                                                                                                                                                                    
35
    if (int($x) % 2 == 0) {                                                                                                                                                                   
36
        $a = $a0;                                                                                                                                                                             
37
    } else {                                                                                                                                                                                  
38
        $a = $a1;                                                                                                                                                                             
39
    }                                                                                                                                                                                         
40

41
    if ($i % 8 == 0) {
42
        $I_old = $I_new;
43
        $I_new = $a;
44
    } elsif ($i % 8 == 2) {
45
        $Q_old = $Q_new;
46
        $Q_new = $a;
47

48
        my $qu1 = quadrant ($I_old, $Q_old);
49
        my $qu2 = quadrant ($I_new, $Q_new);
50

51
        if ($qu1 == $qu2) {
52
            if ($qu1 == 1) {
53
                if ($I_new > $I_old) {
54
                    $dir = 1;
55
                } elsif ($I_new < $I_old) {
56
                    $dir = -1;
57
                } else {
58
                    $dir = 0;
59
                }
60
            } elsif ($qu1 == 2) {
61
                if ($I_new > $I_old) {
62
                    $dir = 1;
63
                } elsif ($I_new < $I_old) {
64
                    $dir = -1;
65
                } else {
66
                    $dir = 0;
67
                }
68
            } elsif ($qu1 == 3) {
69
                if ($I_new > $I_old) {
70
                    $dir = -1;
71
                } elsif ($I_new < $I_old) {
72
                    $dir = 1;
73
                } else {
74
                    $dir = 0;
75
                }
76
            } elsif ($qu1 == 4) {
77
                if ($I_new > $I_old) {
78
                    $dir = -1;
79
                } elsif ($I_new < $I_old) {
80
                    $dir = 1;
81
                } else {
82
                    $dir = 0;
83
                }
84
            } else {
85
                $dir = 0;
86
            }
87
        } elsif ($qu2-$qu1 == 1 || $qu2-$qu1 == -3) {
88
            $dir = -1;          # CCW
89
        } elsif ($qu2-$qu1 == -1 || $qu2-$qu1 == 3) {
90
            $dir = 1;           # CW
91
        } else {
92
            # Sprung über zwei Quadranten => Richtung unbestimmt
93
            $dir = 0;
94
        }
95
    }
96
    printf ("%d %.6f %.6f %.6f %d\n", $i, $t, $x, $a, $dir);
97

98
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.