Найдите последовательность двоичных данных в сигнале

Вот моя цель:

Я пытаюсь найти способ поиска по сигналу данных и найти (индексировать) места, где находится известная повторяющаяся последовательность двоичных данных. Затем, поскольку известны код расширения и демодуляция, извлеките соответствующий чип данных и прочитайте его. В настоящее время я считаю, что xcorr справится с задачей.

Вот моя проблема:

Кажется, я не могу интерпретировать свой результат от xcorr или xcorr2, чтобы дать мне то, что я ищу. У меня либо проблема с перекрестными ссылками от местоположения вектора моей функции xcorr к моему вектору времени, либо проблема с правильной идентификацией моей последовательности данных с помощью xcorr, либо и то, и другое. Могут существовать и другие возможности.

Где я нахожусь/Что у меня есть:

Я создал случайный сигнал BPSK, который состоит из интересующей последовательности данных и мусорных данных за повторяющийся период. Я попытался обработать его с помощью xcorr, и здесь я застрял.

Вот мой код:

%% Clear Variables

clc;
clear all, close all;

%% Create random data

nbits = 2^10;
ngarbage = 3*nbits;
data = randi([0,1],1,nbits);
garbage = randi([0,1],1,ngarbage);
stream = horzcat(data,garbage); 

%% Convert from Unipolar to Bipolar Encoding

stream_b = 2*stream - 1;

%% Define Parameters

%%% Variable Parameters
nsamples = 20*nbits;
nseq = 5 %# Iterate stream nseq times
T = 10; %# Number of periods
Ts = 1; %# Symbol Duration
Es = Ts/2; %# Energy per Symbol
fc = 1e9; %# Carrier frequency

%%% Dependent Parameters
A = sqrt(2*Es/Ts); %# Amplitude of Carrier
omega = 2*pi*fc %# Frequency in radians
t = linspace(0,T,nsamples) %# Discrete time from 0 to T periods with nsamples samples
nspb = nsamples/length(stream) %# Number of samples per bit

%% Creating the BPSK Modulation
%# First we have to stretch the stream to fit the time vector. We can quickly do this using _
%# simple matrix manipulation.

% Replicate each bit nspb/nseq times
repStream_b = repmat(stream_b',1,nspb/nseq);

% Tranpose and replicate nseq times to be able to fill to t
modSig_proto = repmat(repStream_b',1,nseq);

% Tranpose column by column, then rearrange into a row vector
modSig = modSig_proto(:)';

%% The Carrier Wave

carrier = A*cos(omega*t);

%% Modulated Signal

sig = modSig.*carrier;

Использование XCORR

Я использую xcorr2(), чтобы устранить эффект заполнения нулями xcorr на неравных векторах. Смотрите комментарии ниже для уточнения.

corr = abs(xcorr2(data,sig); %# pull the absolute correlation between data and sig
[val,ind] = sort(corr(:),'descend') %# sort the correlation data and assign values and indices
ind_max = ind(1:nseq); %# pull the nseq highest valued indices and send to ind_max

Теперь я думаю, что это должно выявить пять самых высоких корреляций между данными и сигналом. Они должны соответствовать конечному биту данных в потоке для каждой итерации потока, потому что я думаю, что именно здесь данные будут наиболее сильно коррелировать с сигналом, но это не так. Иногда максимумы не отличаются даже на одну длину потока. Так что я тут запутался.

Вопрос

В трехчастном вопросе:

  1. Я пропустил определенный шаг? Как мне использовать xcorr в этом случае, чтобы найти, где данные и сигнал наиболее сильно коррелируют?

  2. Весь мой метод неверен? Разве я не должен искать максимальные корреляции?

  3. Или я должен атаковать эту проблему с другой стороны, то есть не использовать xcorr и, возможно, использовать фильтр или другую функцию?


person endowdly    schedule 23.04.2013    source источник
comment
вау... довольно длинный и многословный вопрос... как вы думаете, можно было бы сократить вопрос до пары строк, сосредоточив внимание только на реальной проблеме, с которой вы столкнулись?   -  person fpe    schedule 24.04.2013
comment
@fpe Прошу прощения за включение опции -v ... Ну, я не хотел ничего упускать. Обычно кажется, что когда вопросы резюмируются, задается много дополнительных вопросов. Подводя итог этому вопросу: как использовать xcorr для поиска потока данных data в модулированном сигнале sig?   -  person endowdly    schedule 24.04.2013
comment
Вы все еще не показали, как вы вычисляете xcorr ;) Пожалуйста, добавьте это   -  person Dan    schedule 24.04.2013
comment
@ Дэн, я думал, что сделал. Я использовал код во втором блоке кода: corr = abs(xcorr2(data,sig); затем я использовал простую сортировку, чтобы получить максимальное количество корреляций. Это то, что вы имеете в виду? Я только что отредактировал свой вопрос, чтобы лучше выделить блок xcorr.   -  person endowdly    schedule 24.04.2013
comment
о, ты хочешь сказать, что int16(xcorr2) == int16(xcorr(xcorr ~= 0) на самом деле int16(xcorr2(data,sig)) == int16(xcorr(xcorr(data, sig) ~= 0)?? Потому что, как у вас есть в вашем вопросе, похоже, что вы используете xcorr как переменную, а не функцию.   -  person Dan    schedule 24.04.2013
comment
если вы называете переменную, затем применяете эти функции, они одинаковы (в этом случае). Итак, если corr = xcorr(x,y) и corr2 = xcorr2(x,y), то int16(corr2) == int16(corr(corr ~= 0);. Я просто пытался показать, почему я выбираю функцию xcorr2, а не xcorr. Прошу прощения, если это было запутанно, я отредактирую вопрос, чтобы прояснить это.   -  person endowdly    schedule 24.04.2013


Ответы (3)


Ваш общий метод великолепен и имеет большой смысл. Проблема, с которой вы столкнулись, заключается в том, что вы получаете реальную корреляцию с вашими данными о мусоре. Я заметил, что вы сместили весь свой поток так, чтобы он был отцентрирован от нуля, но не сделали того же с данными. Если вы центрируете данные по нулю, ваши пики корреляции будут лучше определены (по крайней мере, это сработало, когда я пробовал).

data = 2*data -1;

Кроме того, я не рекомендую использовать простую сортировку для поиска пиков. Если у вас широкий пик, что особенно возможно при шумном сигнале, у вас могут быть две высокие точки рядом друг с другом. Найдите единственный максимум, а затем обнулите эту точку и несколько соседних точек. Затем просто повторите сколько угодно раз. В качестве альтернативы, если вы знаете, как долго длится ваша эпоха, выполняйте корреляцию только с данными за одну эпоху и повторяйте сигнал по мере его поступления.

person David K    schedule 24.04.2013
comment
Пытаясь решить эту проблему самостоятельно, я определенно двигался к предложенному вами решению. Я сделал нулевое центрирование данных, и это действительно помогает. Однако, как вы заметили, существует много шума из-за корреляции между данными и мусором. Итак, я начинаю работать над идеей итерации эпохи. Пока -- разбейте sig на массив (назовем его epochArray) с длинами length(sig)/nseq и nseq строк. Затем итеративно разделите массив на строки, чтобы epoch1 = epochArray(1,:), epoch2 = epochArray(2,:) и так далее, а также сопоставляя данные с каждой строкой epochArray. О праве? - person endowdly; 25.04.2013
comment
@endowdly: звучит правильно! Чтобы упростить вещи и облегчить расширение в будущем, я рекомендую просто зациклить сигнал и иметь переменную «эпоха», которая обновляет каждый цикл. Это предотвращает наличие слишком большого количества отдельных переменных эпохи и большого массива epochArray. - person David K; 25.04.2013
comment
Хорошая идея! Я проработаю это и посмотрю, что получится. примечание: я смог визуально идентифицировать корреляции, которые я ищу, добавив границы эпохи к моему графику xcorr2; вы можете легко увидеть всплеск в ~ nbits в каждую эпоху. Для 2 ^ 4 и менее нбит корреляция именно такая, какой вы ожидаете (например, при t = 32). Кажется, моя основная идея идеально подходит для низких чисел nbit. Итак, давайте посмотрим, как заставить его работать на более высокие суммы! - person endowdly; 25.04.2013
comment
Я также обнаружил, что полезно растянуть сигнал данных, чтобы он соответствовал длине одной итерации. Не знаю, почему я проглядел это. Когда я, наконец, выясню, как вытащить корреляции, я опубликую, работает это или нет. В настоящее время я пытаюсь сделать максимальное среднее значение фрагмента корреляций на основе вашего совета по максимальному обнулению точек. - person endowdly; 26.04.2013

С помощью @David K ​​и @Patrick Mineault мне удается отследить, где я ошибся. Сначала @Patrick Mineault предложил перевернуть сигналы. Лучший способ увидеть, что вы ожидаете от результата, — это сдвинуть маленький вектор вдоль большего искомого вектора. Так

corr = xcorr2(sig,data);

Потом мне нравится обрезать там конец, потому что он просто лишний. Я сделал это с помощью созданной мной функции обрезки, которая просто берет сигнал, который вы перемещаете, и обрезает его нерелевантные части с конца результата xcorr.

trim = @(x,s2) x(1:end - (length(s2) - 1));
trim(corr,data);

Затем, как предлагает @David K, вам нужно, чтобы поток данных, который вы ищете, был закодирован так же, как искомый сигнал. Итак, в этом случае

data = 2*data-1;

Во-вторых, если у вас есть данные только с исходной длиной в битах, а не с растянутой итерированной длиной, их можно найти в сигнале, но они будут ОЧЕНЬ зашумлены. Чтобы уменьшить шум, просто растяните данные, чтобы они соответствовали растянутой длине повторяющегося сигнала. Так

rdata = repmat(data',1,nspb/nseq);
rdata = repmat(rdata',1,nseq);
data = rdata(:)';

Теперь, наконец, у нас должны быть кристально чистые корреляции для этого случая. И вытащить максимумы, которые должны соответствовать тем корреляциям, которые я написал

[sortedValues sortIndex] = sort(corr(:),'descend');
c = 0 ;
for r = 1 : length(sortedValues)
    if sortedValues(r,:) == max(corr)
        c = c + 1;
        maxIndex(1,c) = sortIndex(r,:);
    else break % If you don't do this, you get loop lock
    end
 end 

Теперь c должно стать nseq для этого случая, и у вас должно быть 5 индексов времени, где должны быть исправления! Вы можете легко вытащить биты с помощью другого цикла и c или length(maxIndex). Я также превратил это в более «реальный» игрушечный сценарий, где есть поток данных, допплер, затухание и временной вектор в секундах вместо выборок.

Спасибо за помощь!

person endowdly    schedule 02.05.2013

Попробуйте перевернуть сигнал, т.е.:

corr = abs(xcorr2(data,sig(end:-1:1));

Это лучше?

person Patrick Mineault    schedule 23.04.2013
comment
После проверки... разве это не идентично corr = abs(xcorr2(data,fliplr(sig))); ? Я не упоминал об этом раньше, но я попробовал fliplr как для данных, так и для подписи по отдельности. Не похоже, чтобы улучшить сортировку или поиск максимальных значений. - person endowdly; 24.04.2013
comment
Однако это помогает упорядочить данные, чтобы их можно было лучше визуально идентифицировать. Смотрите мои комментарии к ответу Дэвида К. - person endowdly; 25.04.2013
comment
на самом деле лучший способ увидеть это, когда векторы скользят так, как вы ожидаете (маленькие вдоль больших) do corr = abs(xcorr2(sig,data)); - person endowdly; 02.05.2013