我几乎完成了我的开源 DCF77 解码器项目。当我注意到标准 (Arduino) DCF77 库在噪声信号上表现非常差时,这一切就开始了。特别是当天线靠近计算机或洗衣机正在运行时,我永远无法从解码器中获取时间。
我的第一个方法是向输入信号添加(数字)指数滤波器+触发器。
虽然这大大改善了情况,但仍然不是很好。然后我开始阅读一些关于数字信号处理的标准书籍,尤其是Claude Elwood Shannon的原著。我的结论是,正确的方法是根本不“解码”信号,因为它(除了闰秒)是完全先验已知的。相反,将接收到的数据与本地合成信号相匹配并确定正确的相位会更合适。这反过来又会将有效带宽降低几个数量级,从而显着降低噪声。
相位检测意味着需要快速卷积。高效卷积的标准方法当然是快速傅里叶变换。不过我正在为 Arduino / Atmega 328 实现。因此我只有 2k RAM。因此,我没有采用直接的 FFT 方法,而是开始堆叠匹配的锁相环滤波器。我在这里记录了不同的项目阶段:
- 第一次尝试:指数过滤器 http://blog.blinkenlight.net/experiments/dcf77/binary-clock/
- 更好方法的开始:信号锁相/秒滴答 http://blog.blinkenlight.net/experiments/dcf77/phase-detection/
- 锁相至分钟 http://blog.blinkenlight.net/experiments/dcf77/second-decoder/
- 解码分钟和小时数据 http://blog.blinkenlight.net/experiments/dcf77/decoding-time-data//
- 解码整个信号 http://blog.blinkenlight.net/experiments/dcf77/decoding-everything/
- 添加本地时钟来处理信号丢失 http://blog.blinkenlight.net/experiments/dcf77/local-clock/
- 使用本地合成信号在信号丢失后更快地重新获取锁定 http://blog.blinkenlight.net/experiments/dcf77/the-clock/
我在互联网上进行了广泛的搜索,没有发现类似的方法。我仍然想知道是否有类似(也许更好)的实现。或者是否存在这种信号重建的研究。
我不是在寻找:设计优化代码以接近香农极限。我也不是在寻找有关 DCF77 上叠加的 PRNG 代码的信息。我也不需要有关“匹配过滤器”的提示,因为我当前的实现是匹配过滤器的近似值。关于维特比解码器或网格方法的具体提示不是我要寻找的 - 除非它们解决了严格的 CPU 和 RAM 限制的问题。
我正在寻找什么:是否有其他非平凡算法的描述/实现,用于解码信号,如 DCF77,CPU 和 RAM 有限在有明显噪音的情况下?也许在前互联网时代的一些书籍或论文中?
您是否考虑过使用芯片匹配滤波器来执行卷积?
http://en.wikipedia.org/wiki/Matched_filter http://en.wikipedia.org/wiki/Matched_filter
它们几乎很容易实现,因为每个码片/位周期都可以实现为 n 加减延迟线(使用循环缓冲器)
对于未知序列(但频率已知)的方波(也可以工作,但对于其他波形不太理想),可以实现如下简单的方法:
// 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;
);
正如您所看到的,从资源角度来看,这是相对微不足道的。如果您需要特定的波形,您可以将它们级联在一起以提供更长的相关性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)