Декодер DCF77 по сравнению с шумовым сигналом
Я почти завершил проект декодера DCF77 с открытым исходным кодом. Все началось, когда я заметил, что стандартные (Arduino) библиотеки DCF77 работают очень плохо на шумных сигналах. Особенно я никогда не мог получить время из декодеров, когда антенна была близка к компьютеру или когда моя стиральная машина работала.
Мой первый подход состоял в том, чтобы добавить (цифровой) экспоненциальный фильтр + триггер к входящему сигналу.
Хотя это значительно улучшило ситуацию, все равно это было не очень хорошо. Затем я начал читать некоторые стандартные книги по цифровой обработке сигналов и особенно оригинальные работы Клода Элвуда Шеннона. Мой вывод заключался в том, что правильным подходом было бы не "декодировать" сигнал вообще, потому что он (за исключением секунд прыжка) полностью известен априори. Вместо этого было бы более подходящим сопоставить полученные данные с локально синтезированным сигналом и просто определить правильную фазу. Это, в свою очередь, уменьшит эффективную пропускную способность на несколько порядков и, следовательно, значительно снизит шум.
Определение фазы подразумевает необходимость быстрой свертки. Стандартным подходом для эффективной свертки является, конечно, быстрое преобразование Фурье. Однако я реализую для Arduino/Atmega 328. Таким образом, у меня есть только 2k RAM. Поэтому вместо простого подхода с FFT я начал складывать согласованные фильтры с фазовой автоподстройкой. Я зарегистрировал различные этапы проекта здесь:
Я довольно широко искал интернет и не нашел подобного подхода. Тем не менее мне интересно, есть ли аналогичные (и, возможно, лучшие) реализации. Или, если существуют исследования по реконструкции такого рода сигналов.
Я не ищу: проектирование оптимизированных кодов для приближения к пределу Шеннона. Я также не ищу информацию о наложенном PRNG-коде DCF77. Мне также не нужны намеки на "сопоставленные фильтры", так как моя текущая реализация является приближением согласованного фильтра. Конкретные намеки на подходы Viterbi Decoders или Trellis - это не то, что я ищу, - если они не затронут проблему жестких ограничений ЦП и ОЗУ.
Что я ищу: есть ли какие-либо описания/реализации других нетривиальных алгоритмов для декодирования сигналов типа DCF77 с ограниченным ЦП и ОЗУ при наличии значительного шума? Может быть, в некоторых книгах или в газетах из эпохи интернета?
Ответы
Ответ 1
Ссылка на сопоставленные фильтры Олли Б. не то, о чем я просил. Я уже рассказывал об этом раньше в своем блоге.
Однако к настоящему времени я получил очень хороший совет по частной почте. Существует документ " Анализ производительности и
Receiver Architectures of DCF77 Radio-Controlled Clock " от Daniel Engeler. Это тот материал, который я ищу.
С дальнейшими поисками, начиная с бумаги Engeler, я нашел следующие немецкие патенты DE3733966A1 - Anordnung zum Empfang stark gestoerter Signal des Senders dcf-77 и DE4219417C2 - Schmalbandempfänger für Datensignale.
Ответ 2
Считаете ли вы использование фильтра с фильтром для выполнения свертки?
http://en.wikipedia.org/wiki/Matched_filter
Они почти тривиально просты в реализации, так как каждый период чипа/бит может быть реализован как строка с вычитанием n add (используйте круговой буфер)
Простая для прямоугольной волны (также будет работать, но менее оптимальной с другими формами сигналов) неизвестной последовательности (но известной частоты) может быть реализована примерно так:
// Filter class
template <int samples_per_bit>
class matchedFilter(
public:
// constructor
matchedFilter() : acc(0) {};
// destructor
~matchedFilter() {};
int filterInput(int next_sample){
int temp;
temp = sample_buffer.insert(nextSample);
temp -= next_sample;
temp -= result_buffer.insert(temp);
return temp;
};
private:
int acc;
CircularBuffer<samples_per_bit> sample_buffer;
CircularBuffer<samples_per_bit> result_buffer;
);
// Circular buffer
template <int length>
class CircularBuffer(
public:
// constructor
CircularBuffer() : element(0) {
buffer.fill(0);
};
// destructor
~CircularBuffer(){};
int insert(int new_element){
int temp;
temp = array[element_pos];
array[element_pos] = new_element;
element_pos += 1;
if (element_pos == length){
element_pos = 0;
};
return temp;
}
private:
std::array<int, length> buffer;
int element_pos;
);
Как вы видите, ресурс мудрый, это относительно тривиально. Это конкретная форма сигнала, после которой вы можете каскадировать их вместе, чтобы дать более длительную корреляцию.