DCF77

Started by wimn.rm October 27, 2005
I need to measure incoming pulses of 100 and 200 milliseconds.
The PulseIn in not suitable for this, it's rangs is to short.
Before I start doing difficult things with the rtc I will ask if
someone has another bright idea how to do a simple pulswidth
measurement of pulses of this lenght.


I do this on one of my projects. It is very simple but the accuracy is only +/- 4 ms. sse

do
If pin = high and sse then
t=timer
s=true
end if

If pin=low and s=true then
pulsewidth=-timer-t
sse
end if
loop

Its accuracy is limited by the 2ms accuaracy of timer and it can stack in both directions to generate a +/-4 ms range. In my case that was fine.

Art
[] I need to measure incoming pulses of 100 and 200 milliseconds.


How about hooking the pulse up to an interrupt, then the interrupt
should loop while checking the pin state until it changes back.

You could benchmark the interrupt by manually triggering the
interrupt, and holding it for a fairly precise, long time and then
read out the number of loop iterations.

Do this for 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20.... seconds
then look at the loop iterations. There will be a small time
overhead of the entry into the interrupt, but not much compared to
many milliseconds.

By simple comutation, you can calculate the decimal fraction of a
second per loop. You could get more sophisticated and do a
regression to calculate the seconds per loop, but unless you have a
precise mechanism to handle the pulse duration, the regression will
not be much better than averaging many 10 second trials.

Then try it in real life and see what you get.

A logic probe, or even a DMM can tell you the frequency and duty-
cycle of the signal, if your signal is repetetive and fixed. An
oscilloscope would work too for the benchmarking.

--- In basicx@basi..., "wimn.rm" <wimn@r...> wrote:
>
> I need to measure incoming pulses of 100 and 200 milliseconds.



--- In basicx@basi..., "wimn.rm" <wimn@r...> wrote:
> I need to measure incoming pulses of 100 and 200 milliseconds.

You may be able to use WaitForInterrupt. If you're measuring a high
pulse, use bxPinRisingEdge initially. When the interrupt occurs store
the value of Register.RTCTick and do another WaitForInterrupt using
bxPinFallingEdge. When the interrupt occurs again the pulse width is
the difference between Register.RTCTick and the stored value time
1.95mS. You'll have to add code to detect when RTCTick rolls over to
zero. (Unfortunately, Register.RTCStopWatch is broken on the BX-24 -
that would be a much simpler solution.) Alternately, you could employ
Timer1 to measure the elapsed time with better resolution. See the
BasicX Timer1_Stopwatch_App_Note.pdf for detail on how to do this.


If you are decoding DCF77 (a German 77.5KHz timecode broadcast), you
don't need any precision, just a threshold to determine if the incoming
bit is a one or zero. That bit can then shift into a 60-bit string to
contain the entire minute frame of data, or code can parse the bit
stream on the fly.

I believe that all you need to do is find the start of a bit and then
determine if the bit period is >150mS. A missing bit signals bit 59 in
anticipation of :00 - or loss of data. You can, of course, time the bit
with code, but another way to decode it is to charge a capacitor during
the high bit period - either spinning in code until the bit falls, or
interrupting the machine when the bit falls. Immediately sample the
analog charge on the cap to determine the bit state, then discharge it.

Somewhere I have code for an MSF/DCF77/WWVB decoder that I wrote for
DOS. If that is helpful, I'll hunt it down. Tom



--- In basicx@basi..., "wimn.rm" <wimn@r...> wrote:
> I need to measure incoming pulses of 100 and 200 milliseconds.

On further reflection, I assume that you're trying to decode the
pulse-width-modulated DCF77 signal. In that case, you might
consider using external hardware to discriminate between the pulse
widths.

One way to do that simply is to use a one-shot that is triggered by
the incoming pulse. The pulse width of the one-shot should be set
to 150mS. Use the trailing edge of the one-shot's pulse to clock a
D flop whose data input is the original pulse signal. If the
original pulse was 100mS long the D flop will store a zero and if it
was the longer 200mS pulse it will store a 1.

The trailing edge of the one-shot's pulse could also set another
flip-flop to indicate that data is ready to be read. Your code
would then read the D flop output and then reset the "data-ready"
flip-flop.

I've put a quick sketch of such a circuit at:
http://www.kinzers.com/don/BX24/dcf77.jpg

The proposed circuit requires 3 I/O pins on the BX-24 but you could
reduce that to 2 by using the /RESET output to multiplex the DATA
RDY and DATA signals.

Don


Actually, now that I think about it, my MSF/DCF77/WWVB decoder is an
assembly language TSR, so it will be of little use. I was thinking it
was a QuickBasic app that might be useful for structure, but I doubt
the assembly code will serve any useful purpose. Tom



That is a nice "quick" sketch! Do you just know the R & C values off
the top of your head for the 1-shot (3.3M, 0.1uF)?

-Tony


Don, I'm close to the solution I think.
I now use 2 do while loops.

First waits for the raising edge. Next is starting a sleep of 120 mSec
Then a check if it's still high.
If not we have a short ( 100mSec)
If yes we have a long ( 200mSec)

Wim
[]


Works! so simple afterward. do
CB = 0

'Wait for a 1
do while (cb = 0)
CB = GetPin(DCF77) 'Get clock output
loop

call sleep(60) 'pass the 100mSec
CB = GetPin(DCF77) 'Get clock output
if (cb = 1 ) then 'still a 1 ?
bit =1 'So it's a long pulse
else
bit = 0 'It's a short pulse
end if
debug.print cstr(bit)
call sleep(100) 'to prevent in enters the
'do-while with a value of 1
loop