J'écris un exemple sur la transmission de données via le son entre deux ordinateurs. Quelques exigences:
La distance est très proche, c'est-à-dire que les 2 ordinateurs sont fondamentalement adjacents l'un à l'autre
Très peu de bruit (je ne pense pas que mon professeur allumerait une chanson rock comme source de bruit)
L'erreur est acceptable: par exemple, si j'envoie "Communication radio", si l'autre ordinateur reçoit "RadiQ communEcation", ça va aussi.
Si possible: pas d'en-tête, indicateur, somme de contrôle, .... car je veux juste un exemple très basique démontrant les bases de la transmission de données par le son. Pas besoin d'être chic.
J'ai essayé d'utiliser la modulation de fréquence audio selon ce lien:
Lab 5 APRS (Automatic Package Reporting System)
et obtenu quelques résultats: Ma page Github
Mais ce n'est pas assez. Je ne sais pas comment faire la récupération d'horloge, la synchronisation, ... (le lien a une boucle à verrouillage de phase comme mécanisme de récupération de synchronisation, mais ce n'était apparemment pas suffisant).
Je pense donc que je devrais trouver une approche plus simple. Trouvé un lien ici:
Données audio et retour. Modulation / démodulation avec code source
mais l'OP n'a pas mis en œuvre la méthode suggérée dans la réponse, donc je crains que cela ne soit très complexe. De plus, je ne comprends pas clairement la méthode de décodage suggérée dans la réponse:
Le décodeur est un peu plus compliqué mais voici un aperçu:
Optionnellement, filtre passe-bande du signal échantillonné autour de 11 kHz. Cela améliorera les performances dans un environnement bruyant. Les filtres FIR sont assez simples et il existe quelques applets de conception en ligne qui généreront le filtre pour vous.
Seuil le signal. Chaque valeur au-dessus de 1/2 amplitude maximale est 1 chaque valeur au-dessous est 0. Cela suppose que vous avez échantillonné la totalité du signal. Si c'est en temps réel, vous choisissez un seuil fixe ou effectuez une sorte de contrôle automatique du gain où vous suivez le niveau de signal maximum sur une certaine période.
Recherchez le début du point ou du tiret. Vous voulez probablement voir au moins un certain nombre de 1 dans votre période de points pour considérer les échantillons comme un point. Continuez ensuite à scanner pour voir s'il s'agit d'un tiret. Ne vous attendez pas à un signal parfait - vous verrez quelques 0 au milieu de vos 1 et quelques 1 au milieu de vos 0. S'il y a peu de bruit, différencier les périodes "marche" des périodes "arrêt" devrait être assez facile.
Inversez ensuite le processus ci-dessus. Si vous voyez un tiret, poussez 1 bit vers votre tampon, si un point pousse un zéro.
Je ne comprends pas combien de 1 avant de le classer comme un point, ... Il y a donc beaucoup de choses que je ne comprends pas en ce moment. Veuillez me suggérer une méthode simple pour transmettre des données par le son afin que je puisse comprendre le processus. Merci beaucoup :)
MISE À JOUR:
J'ai créé du code Matlab qui semble être (quelque peu) opérationnel. Je module d'abord le signal en utilisant la modulation par décalage d'amplitude (fréquence d'échantillonnage 48000 Hz, F_on = 5000 Hz, débit binaire = 10 bits / s), puis je l'ajoute avec un en-tête et une séquence de fin (bien sûr, modulez-les également). L'en-tête et la séquence de fin ont été choisis sur une base ad hoc (ouais c'était un hack):
header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1];
end_seq = [1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1];
Je les transmets ensuite par le son et je les enregistre avec mon smartphone. Ensuite, j'envoie l'audio enregistré à mon ordinateur, utilise un autre morceau de code pour lire l'audio. Ensuite, je corrèle le signal reçu (pas encore démodulé) avec l'en-tête modulé et la séquence de fin pour connaître le début et la fin. Après cela, je ne prends que le signal pertinent (du début à la fin, comme on le trouve dans la partie corrélation). Ensuite, je démodule et échantillonne pour trouver les données numériques. Voici 3 fichiers audio:
"DigitalCommunication_ask": Le lien ici envoie le texte "Communication numérique". Relativement sans bruit, bien que vous puissiez entendre un bruit de fond au début et à la fin. Cependant, le résultat n'a montré que "Digital Commincatio"
"HelloWorld_ask": Le lien ici envoie le texte "Hello world". Sans bruit comme "DigitalCommunication_ask". Cependant le résultat pour celui-ci était correct
"HelloWorld_noise_ask": Le lien ici envoie le texte "Hello world". Cependant il y a du bruit que j'ai fait (je viens de dire quelques trucs aléatoires "A, B, C, D, E, ...." pendant la transmission). Malheureusement celui-ci a échoué
Voici le code de l'expéditeur (sender.m):
clear
fs = 48000;
F_on = 5000;
bit_rate = 10;
% header = [0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ];
% header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 ];
header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1 ];
% end_seq = [0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0];
end_seq = [1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1];
num_of_samples_per_bit = round(fs / bit_rate);
modulated_header = ask_modulate(header, fs, F_on, bit_rate);
modulated_end_seq = ask_modulate(end_seq, fs, F_on, bit_rate);
% input_str = 'Ah';
input_str = 'Hello world';
ascii_list = double(input_str); % https://www.mathworks.com/matlabcentral/answers/298215-how-to-get-ascii-value-of-characters-stored-in-an-array
bit_stream = [];
for i = 1:numel(ascii_list)
bit = de2bi(ascii_list(i), 8, 'left-msb');
bit_stream = [bit_stream bit];
end
bit_stream = [header bit_stream end_seq];
num_of_bits = numel(bit_stream);
bandlimited_and_modulated_signal = ask_modulate(bit_stream, fs, F_on, bit_rate);
sound(bandlimited_and_modulated_signal, fs);
Pour le récepteur (receiver.m):
clear
fs = 48000;
F_on = 5000;
bit_rate = 10;
% header = [0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ];
% header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 ];
header = [0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1];
% end_seq = [1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 1 1 0 0 1 ];
% end_seq = [0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0];
end_seq = [1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 1];
modulated_header = ask_modulate(header, fs, F_on, bit_rate);
modulated_end_seq = ask_modulate(end_seq, fs, F_on, bit_rate);
% recObj = audiorecorder(fs,8,1);
% time_to_record = 10; % In seconds
% recordblocking(recObj, time_to_record);
% received_signal = getaudiodata(recObj);
% [received_signal, fs] = audioread('SounddataTruong_Ask.m4a');
% [received_signal, fs] = audioread('HelloWorld_noise_ask.m4a');
% [received_signal, fs] = audioread('HelloWorld_ask.m4a');
[received_signal, fs] = audioread('DigitalCommunication_ask.m4a');
ereceived_signal = received_signal(:)';
num_of_samples_per_bit = round(fs / bit_rate);
modulated_header = ask_modulate(header, fs, F_on, bit_rate);
modulated_end_seq = ask_modulate(end_seq, fs, F_on, bit_rate);
y= xcorr(modulated_header, received_signal); % do cross correlation
[m,ind]=max(y); % location of largest correlation
headstart=length(received_signal)-ind+1;
z = xcorr(modulated_end_seq, received_signal);
[m,ind]=max(z); % location of largest correlation
end_index=length(received_signal)-ind+1;
relevant_signal = received_signal(headstart + num_of_samples_per_bit * numel(header) : end_index - 1);
% relevant_signal = received_signal(headstart + num_of_samples_per_bit * numel(header): end);
demodulated_signal = ask_demodulate(relevant_signal, fs, F_on, bit_rate);
sampled_points_in_demodulated_signal = demodulated_signal(round(num_of_samples_per_bit / 2) : num_of_samples_per_bit :end);
digital_output = (sampled_points_in_demodulated_signal > (max(sampled_points_in_demodulated_signal(:)) / 2));
% digital_output = (sampled_points_in_demodulated_signal > 0.05);
% Convert to characters
total_num_of_bits = numel(digital_output);
total_num_of_characters = total_num_of_bits / 8;
first_idx = 0;
last_idx = 0;
output_str = '';
for i = 1:total_num_of_characters
first_idx = last_idx + 1;
last_idx = first_idx + 7;
binary_repr = digital_output(first_idx:last_idx);
ascii_value = bi2de(binary_repr(:)', 'left-msb');
character = char(ascii_value);
output_str = [output_str character];
end
output_str
Code de modulation ASK (ask_modulate):
function [bandlimited_and_modulated_signal] = ask_modulate(bit_stream, fs, F_on, bit_rate)
% Amplitude shift keying: Modulation
% Dang Manh Truong ([email protected])
num_of_bits = numel(bit_stream);
num_of_samples_per_bit = round(fs / bit_rate);
alpha = 0;
d_alpha = 2 * pi * F_on / fs;
A = 3;
analog_signal = [];
for i = 1 : num_of_bits
bit = bit_stream(i);
switch bit
case 1
for j = 1 : num_of_samples_per_bit
analog_signal = [analog_signal A * cos(alpha)];
alpha = alpha + d_alpha;
end
case 0
for j = 1 : num_of_samples_per_bit
analog_signal = [analog_signal 0];
alpha = alpha + d_alpha;
end
end
end
filter_order = 15;
LP_filter = fir1(filter_order, (2*6000)/fs, 'low');
bandlimited_analog_signal = conv(analog_signal, LP_filter,'same');
% plot(abs(fft(bandlimited_analog_signal)))
% plot(bandlimited_analog_signal)
bandlimited_and_modulated_signal = bandlimited_analog_signal;
end
Démodulation ASK (ask_demodulate.m) (Fondamentalement, ce n'est que la détection d'enveloppe, pour laquelle j'ai utilisé la transformée de Hilbert)
function [demodulated_signal] = ask_demodulate(received_signal, fs, F_on, bit_rate)
% Amplitude shift keying: Demodulation
% Dang Manh Truong ([email protected])
demodulated_signal = abs(hilbert(received_signal));
end
Veuillez me dire pourquoi cela ne fonctionne pas? Merci beaucoup
la source
Réponses:
Comme vous l'avez compris, la partie difficile des communications numériques est la synchronisation des porteuses, des symboles et des trames, ainsi que l'estimation / l'égalisation des canaux.
La mauvaise nouvelle est que vous ne pouvez pas contourner ces problèmes. La bonne nouvelle est que leur mise en œuvre n'est pas si difficile, tant que vous vous limitez au BPSK à bande étroite. Je sais, parce que je l'ai fait moi-même, tout comme mes étudiants (de premier cycle) (voir http://ieeexplore.ieee.org/document/5739249/ )
Une suggestion simple pour contourner le problème de la synchronisation des porteuses consiste à utiliser AM DSB-LC pour convertir le signal en bande de base. Ensuite, vous pouvez utiliser un détecteur d'enveloppe sans synchronisation de porteuse et de phase. Cela vous coûtera en efficacité énergétique, mais ce n'est pas une priorité dans votre cas.
Une autre suggestion simple est de faire un "traitement par lots" au lieu d'un "traitement en temps réel"; ce que cela signifie, stocker tout le signal reçu et le traiter ensuite. C'est beaucoup plus facile à mettre en œuvre que le traitement en continu ou en temps réel.
Ma suggestion plus substantielle est de lire ce livre: Johnson, Sethares et Klein, "Software receiver design", Cambridge. Il explique en termes très clairs chaque pièce du récepteur et contient de nombreux exemples de code Matlab. Il y a un livre similaire de Steven Tretter, sur l'implémentation d'un système de communication sur un DSP (je ne me souviens pas du titre exact en ce moment).
Bonne chance; et veuillez poser de nouvelles questions plus spécifiques si vous en avez.
la source
Au final, j'ai utilisé le DTMF (Dual Tone Multi Frequency signaling). Le DTMF d'origine a 16 signaux chacun utilisant une combinaison de 2 fréquences. Mais ici, je n'ai utilisé que "1" (697 Hz et 1209 Hz) et "0" (941Hz et 1336 Hz)
Un aperçu du fonctionnement du code:
Le côté récepteur utilise d'abord 2 filtres passe-bande ridiculement élevés et ridiculement ordonnés pour extraire les composantes de fréquence "0" et "1", respectivement:
filter_order = 1000;
Après cela, nous trouverons le début et la fin de chaque signal "1" et "0". Le code provient de https://github.com/codyaray/dtmf-signaling . Fondamentalement, il trouve la période de silence qui est d'au moins 10 ms et toute période de tonalité supérieure à 100 ms):
(De haut en bas: signal zéro, signal après le déplacement de la moyenne du filtre, différence de signal après suppression de ceux en dessous du seuil, signal après seuillage)
Ensuite, nous assemblons les bits et les reconvertissons en texte :)
Démo vidéo: https://www.youtube.com/watch?v=vwQVmNnWa4s , où j'envoie le texte "Xin chao" entre mon ordinateur portable et le PC de mon frère :)
P / S: À l'origine, je l'ai fait parce que mon professeur de communication numérique a dit que celui qui le ferait obtiendrait un A sans avoir à passer l'examen final, mais je n'ai pu le faire qu'après l'examen. Voici donc tous mes efforts :(
P / S2: j'ai un C + :(
la source
Si vous voulez une bibliothèque open source avec une très bonne synchronisation, je recommande https://github.com/jgaeddert/liquid-dsp qui utilise msequences pour s'aligner, puis fait l'égalisation et démodule la charge utile. J'ai créé un modem audio qui fonctionne sur le dessus et il fonctionne assez bien, donc si rien d'autre, les méthodes de Liquid devraient être utiles
la source