Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DCF77 decoder vs. noisy signal

I have almost completed my open source DCF77 decoder project. It all started out when I noticed that the standard (Arduino) DCF77 libraries perform very poorly on noisy signals. Especially I was never able to get the time out of the decoders when the antenna was close to the computer or when my washing machine was running.

My first approach was to add a (digital) exponential filter + trigger to the incoming signal.

Although this improved the situation significantly, it was still not really good. Then I started to read some standard books on digital signal processing and especially the original works of Claude Elwood Shannon. My conclusion was that the proper approach would be to not "decode" the signal at all because it is (except for leap seconds) completely known a priori. Instead it would be more appropriate to match the received data to a locally synthesized signal and just determine the proper phase. This in turn would reduce the effective bandwidth by some orders of magnitude and thus reduce the noise significantly.

Phase detection implies the need for fast convolution. The standard approach for efficient convolution is of course the fast Fourier transform. However I am implementing for the Arduino / Atmega 328. Thus I have only 2k RAM. So instead of the straightforward approach with FFT, I started stacking matched phase locked loop filters. I documented the different project stages here:

  • First try: exponential filter
  • Start of the better apprach: phase lock to the signal / seconds ticks
  • Phase lock to the minutes
  • Decoding minute and hour data
  • Decoding the whole signal
  • Adding a local clock to deal with signal loss
  • Using local synthesized signal for faster lock reacquisition after signal loss

I searched the internet quite extensively and found no similar approach. Still I wonder if there are similar (and maybe better) implementations. Or if there exist research on this kind of signal reconstruction.

What I am not searching for: designing optimized codes for getting close to the Shannon limit. I am also not searching for information on the superimposed PRNG code on DCF77. I also do not need hints on "matched filters" as my current implementation is an approximation of a matched filter. Specific hints on Viterbi Decoders or Trellis approaches are not what I am searching for - unless they address the issue of tight CPU and RAM constraints.

What I am searching for: are there any descriptions / implementations of other non-trivial algorithms for decoding signals like DCF77, with limited CPU and RAM in the presence of significant noise? Maybe in some books or papers from the pre internet era?

like image 336
Udo Klein Avatar asked Aug 03 '13 05:08

Udo Klein


1 Answers

Have you considered using a chip matched filter to perform your convolution?

http://en.wikipedia.org/wiki/Matched_filter

They are almost trivially easy to implement, as each chip / bit period can be implemented as a n add subtract delay line ( use a circular buffer )

A simple one for a square wave (will also work, but less optimal with other waveforms) of unknown sequence (but known frequency) can be implemented something like this:

// 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;
);

As you can see, resource wise, this is relatively trivial. It there is a specific waveform you're after, you can cascade these together to give a longer correlation.

like image 177
OllieB Avatar answered Sep 21 '22 03:09

OllieB