Searching \ for '[PIC] RF Tx/Rx modules with PIC (reposted with tag' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/ios.htm?key=rf
Search entire site for: 'RF Tx/Rx modules with PIC (reposted with tag'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] RF Tx/Rx modules with PIC (reposted with tag'
2007\05\12@162828 by Chris

flavicon
face

Has anyone used the following modules, or anything similar, with a PIC?

http://www.maplin.co.uk/module.aspx?ModuleNo=22965&doy=12m5

I want to build a device which measures the time between pulses on my
electricity meter, and send the result to a battery powered
logger/display unit and/or PC, and i'm hoping they will work.

My meter is one of these:

http://www.btinternet.com/~jon00/images/meter.gif

(1000 flashes per KWh)
--
Chris


2007\05\12@183212 by Jinx

face picon face
> Has anyone used the following modules, or anything similar, with a PIC?
>
> http://www.maplin.co.uk/module.aspx?ModuleNo=22965&doy=12m5

Yes. I use the Keymark equivalent, Manchester encoded data between
PICs, 200m line-of-sight with simple 1/4 wave aerials

I was intending to write it up shortly as a PIClist page, but I can give you
details now if you want

2007\05\12@211210 by Chris

flavicon
face
In message <01cc01c794e5$605b8260$0100a8c0@ivp2000>, Jinx
<spam_OUTjoecolquittTakeThisOuTspamclear.net.nz> writes
>> Has anyone used the following modules, or anything similar, with a PIC?
>>
>> http://www.maplin.co.uk/module.aspx?ModuleNo=22965&doy=12m5
>
>Yes. I use the Keymark equivalent, Manchester encoded data between
>PICs, 200m line-of-sight with simple 1/4 wave aerials
>
>I was intending to write it up shortly as a PIClist page, but I can give you
>details now if you want

That would be lovely, thanks!
--
Chris


2007\05\12@224838 by Jinx

face picon face
part 1 11432 bytes content-type:text/plain; (decoded 7bit)


> That would be lovely, thanks!

Okey-doke. Any questions, please ask

As I said, I want to write this up properly, so for now I'll keep it to
an understandable minimum

The attached diagram will help explain. Note that I do not recall
what ID is represented in that diagram, and that bits of a byte are
on screen as MSB on the left and LSB on the right. Each original
data bit is converted to a bit pair by the Manchester

The first thing with these receivers is that with no signal present they
turn up the AGC, looking for any 433MHz, resulting in random noise
from the output. The second thing is that the output needs to be
stabilised with a DC-balanced preamble (equal-ish number of '0' and
'1') before you can get meaningful data out. IOW, the output needs to
settle down for a few ms at least, and a pre-amble will do that

My application uses two 12F675s clocked with 4MHz internal. The
receiver PIC needs to match its timing to the transmitter, which uses
(approx) 1ms bit length. Two bytes of data are sent = 32 bits of
Manchester

So, from left to right - (my application in particular)

The PIC waits with a timer running that has a rollover of about 4ms.
Noise is generally shorter than this (occassionally it isn't but I'll get to
that). The timer is reset anytime there's a transition before rollover, so
PIC only moves on to data detection if the timer rolls over

;==================
t1off    macro
        bcf     t1con,tmr1on
        endm

t1on     macro
        bsf     t1con,tmr1on
        endm

#define  rx_data  gpio,2         ;output from receiver
#define  echo     gpio,4         ;echo received data
#define  marker   gpio,5         ;indicator
#define  t1over   pir1,tmr1if
;==================

        clrf    tmr1l           ;reset Timer1
        movlw   0xf1            ;4ms (approx) to rollover
        movwf   tmr1h
        bcf     t1over          ;clear rollover flag
        t1on                    ;start Timer1

reload1  clrf    tmr1l
        movlw   0xf1
        movwf   tmr1h
        bcf     t1over          ;clear rollover flag

test1    btfss   rx_data         ;skip if pin still high
        goto    reload1         ;pin went low before rollover
        btfss   t1over          ;rollover
        goto    test1           ;pin still high, re-test

Once it's detected a long '1' the PIC assumes a pre-amble and
looks for the transitions. When it gets to the 55 it measures 4
bits. That timing is used as the basis for the 1-bit data sampling

        t1on                    ;start timing
        bsf     marker

;time 4 bits

        btfsc   rx_data
        goto    $-1             ;'0'
        btfss   rx_data
        goto    $-1             ;'1'
        btfsc   rx_data
        goto    $-1             ;'0'
        btfss   rx_data
        goto    $-1             ;'1', start of bit5

        t1off                   ;stop timing
        bcf     marker

;calculate during data = 1 time

        movfw   tmr1l
        movwf   temp0

        movfw   tmr1h
        movwf   temp1

        movlw   d40             ;a little compensation for
        subwf   temp0           ;reload delays
        skpc
        decf    temp1

        clrc                    ;/4 = 1 bit time
        rrf     temp1
        rrf     temp0
        clrc
        rrf     temp1
        rrf     temp0

        movfw   temp0           ;1 bit time in reload
        movwf   reload_lo
        movfw   temp1
        movwf   reload_hi

        comf    reload_lo       ;negate for count up
        comf    reload_hi
        incfsz  reload_lo
        goto    $+2
        incf    reload_hi

        clrc                    ;/2 = 1/2 bit time
        rrf     temp1
        rrf     temp0

        comf    temp0           ;negate
        comf    temp1
        incfsz  temp0
        goto    $+2
        incf    temp1

        movfw   temp0           ;1/2 bit time in timer
        movwf   tmr1l
        movfw   temp1
        movwf   tmr1h

Part of the pre-amble detection is rejection of a long (>4ms) '1'
followed by noise that doesn't conform to the pre-amble format.
In one situation I wondered why the receiver was appearing to be
triggered by a transmitter that wasn't powered up. The answer
turned out to be simple (and my fault). It's possible for a long '1'
to be followed by a quiet period. The PIC was sampling that quiet
period and producing an ID of h00. What ID was the receiver
looking for ? Yup, h00. So I toughened up the detection routine

God bless logic analysers

The pre-amble is terminated by a 1111 -> 0 transition. At this point
the PIC waits for 1/2-bit, then starts sampling

After 32 bits have been received, the bits are compiled back to
two data bytes and compared with the ID of the transmitter (they
operate in ID-matched pairs)

;================================================
;        Get data bits
;================================================

;rx_byte+0 is start of 4-byte array for received bits

        movlw   .31             ;pick up and shift 31 bits
        movwf   cnt0

next_bit bsf     in_bit          ;assume bit = 1
        btfss   rx_data
        bcf     in_bit          ;else bit = 0

        movfw   rx_byte+3       ;echo received bit on gpio
        andlw   b'10000000'
        bnz     echo1           ;in_bit = 1
echo0    bcf     echo
        goto    rotate
echo1    bsf     echo

rotate   clrc
        rrf     rx_byte+3
        rrf     rx_byte+2
        rrf     rx_byte+1
        rrf     rx_byte+0

        bsf     marker
        bcf     t1over
        btfss   t1over
        goto    $-1             ;delay until middle of next bit
        bcf     marker

        t1off
        movfw   reload_lo
        movwf   tmr1l
        movfw   reload_hi
        movwf   tmr1h
        t1on

        decfsz  cnt0
        goto    next_bit

last_bit bsf     in_bit          ;get last bit, no shift
        btfss   rx_data
        bcf     in_bit

;================================================

;decode 4 bytes of Manchester

        t1off
        bsf     marker

        movlw   rx_byte+0
        movwf   fsr

        movfw   indf            ;combine rx_byte+0
        movwf   temp0
        incf    fsr
        movfw   indf            ;and rx_byte+1
        movwf   temp1
        call    combine
        movfw   temp2
        movwf   in_byte1        ;into 1 byte

        incf    fsr
        movfw   indf            ;combine rx_byte+2
        movwf   temp0
        incf    fsr
        movfw   indf            ;and rx_byte+3
        movwf   temp1
        call    combine
        movfw   temp2
        movwf   in_byte2        ;into 1 byte

        movlw   byte1           ;compare received with ID
        xorwf   in_byte1,w
        bnz     no_match
        movlw   byte2
        xorwf   in_byte2
        bnz     no_match

match - routine here for IDs equal (accepts more data etc)

no_match - routine here for IDs different (resets back to waiting)

;================================================
;        convert 2 bytes Manchester to 1 byte data
;================================================

combine  rrf     temp0,w
        andlw   b'00000001'
        btfsc   temp0,3
        iorlw   b'00000010'
        btfsc   temp0,5
        iorlw   b'00000100'
        btfsc   temp0,7
        iorlw   b'00001000'
        movwf   temp2
        swapf   temp2

        rrf     temp1,w
        andlw   b'00000001'
        btfsc   temp1,3
        iorlw   b'00000010'
        btfsc   temp1,5
        iorlw   b'00000100'
        btfsc   temp1,7
        iorlw   b'00001000'
        addwf   temp2
        swapf   temp2

        return

;==================
; Transmitter output
;==================

;16-bit ID sent from transmitter

byte1    set      "I"            ;LSB
byte2    set      "D"            ;MSB

;                          M                    L
;eg 'A' 0x41 converted to 01 10 01 01 01 01 01 10
;                          0  1  0  0  0  0  0  1
;
;                     p/a  L                    M
;and sent LSB first  1111 01 10 10 10 10 10 01 10
;                          1  0  0  0  0  0  1  0
;================================================

;Convert bytes to Manchester

convert1 movlw   byte1
        movwf   temp

        movlw   b'01010101'   ;assume all bits are 0
        movwf   man1_lo
        movwf   man1_hi

        movlw   b'00000011'   ;setup invert mask
        btfsc   temp,0        ;test bit 0
        xorwf   man1_lo       ;invert code if 1
        btfsc   temp,4        ;test bit 4
        xorwf   man1_hi       ;invert code if 1

        movlw   b'00001100'   ;same as above, repeated 3 times
        btfsc   temp,1
        xorwf   man1_lo
        btfsc   temp,5
        xorwf   man1_hi

        movlw   b'00110000'
        btfsc   temp,2
        xorwf   man1_lo
        btfsc   temp,6
        xorwf   man1_hi

        movlw   b'11000000'
        btfsc   temp,3
        xorwf   man1_lo
        btfsc   temp,7
        xorwf   man1_hi

convert2 movlw   byte2
        movwf   temp

        movlw   b'01010101'   ;assume all bits are 0
        movwf   man2_lo
        movwf   man2_hi

        movlw   b'00000011'   ;setup invert mask
        btfsc   temp,0        ;test bit 0
        xorwf   man2_lo       ;invert code if 1
        btfsc   temp,4        ;test bit 4
        xorwf   man2_hi       ;invert code if 1

        movlw   b'00001100'   ;same as above, repeated 3 times
        btfsc   temp,1
        xorwf   man2_lo
        btfsc   temp,5
        xorwf   man2_hi

        movlw   b'00110000'
        btfsc   temp,2
        xorwf   man2_lo
        btfsc   temp,6
        xorwf   man2_hi

        movlw   b'11000000'
        btfsc   temp,3
        xorwf   man2_lo
        btfsc   temp,7
        xorwf   man2_hi

;Send pre-amble to stabilise receiver and time-align decoding PIC
;
;Pre-amble is 0f 0f 55 f0 0
;Each whole byte sent LSb first
;-> bits received in order f0 f0 55 0f 0
;                              1111>0 ^ marks end of pre-amble bytes

preamble movlw   0x0f
        movwf   temp0
        call    snd_byte

        movlw   0x0f
        movwf   temp0
        call    snd_byte

        movlw   0x55
        movwf   temp0
        call    snd_byte

        movlw   0xf0
        movwf   temp0
        call    snd_byte

;send '0' bit to signal end of pre-amble
;marks end of '1111' bits of f0

        bcf     tx_data         ;0
        call    ms1

; routine to send Manchester

send     movlw   .16             ;send first 16 bits
        movwf   cnt0

;Each bit loop takes 1ms @ 4MHz

tx_loop  bcf     tx_data         ;assume 0 bit
        btfss   out_bit         ;test for actual value
        goto    data_tx         ;bit is 0
        bsf     tx_data         ;bit is 1
data_tx  call    ms1             ;hold for 1ms

        rrf     man1_hi
        rrf     man1_lo

        decfsz  cnt0
        goto    tx_loop

        movfw   man2_lo          ;next 16 bits
        movwf   man1_lo
        movfw   man2_hi
        movwf   man1_hi

        decfsz  cnt1
        goto    send

        movfw   gpio
        movwf   temp0
        bcf     temp0,1
        bcf     temp0,4
        movfw   temp0
        movwf   gpio
        nop
        nop
        bcf     led


part 2 2660 bytes content-type:image/gif; (decode)


part 3 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2007\05\12@235218 by John Dammeyer

flavicon
face
Hi Jinx,


> Okey-doke. Any questions, please ask
>
> As I said, I want to write this up properly, so for now I'll
> keep it to
> an understandable minimum

Than you for sharing that.  Very generous.  

In keeping with that spirit here's an approach I used for imitation
anti-personal land mines. (Called WORMs for Wireless Operated Replica
Mines).  The mines using the 12F675 are buried up to 25cm deep in wet
soil.  The 433Mhz units at that depth have a range of about 20m.  In
order to broadcast the ID of the mine when it was tripped by demining
equipment it had to provide a message ID within 4mS.  After that the
target is usually turned into rubble.  The software sends out 200
messages and then stops to prevent jamming the next mine.  For testing
these mines are buried at various depths.

The code is written in C and is available from the Defence Research
Establishment Suffield (DRES).  I believe it's public now since the
tender to manufacture these included the source code written in
Bytecraft C.

Bits are 50uS long and transferred in a while (1) loop.

if (TIMR0 == Capture) {
 Capture = TMR0+TIME_PERIOD;
 iDATA_ASK = ~DATA_MSB; // Send bit: Low is Recessive (RF OFF), High is
Dominant (RF ON).
 GPIO = GPIO_Image;
 // Next Bit
 DataByte <<= 1;
 ...
}

/*
DESCRIPTION:
   On button press, sends out preamble stream,  then ID Byte
       and then compliment of ID Byte.

       Bit stuffing is used because a message can't have more than
       4 bits of a particular polarity.  

       The preamble breaks this rule by sending 5 bits Dominant,
       5 bits Recessive

       After the 5 bits recessive a Dominant Start bit starts the data
       byte.

       The bit counter represents the total number of bits of a
message,
       not a byte.  The message is preformatted by external software.
       The end of the message is always terminated with a recessive 6
bits
       to prevent misinterpreting starts and ends of messages.
       i.e.  A node won't start receiving until it sees 6 bits of
       bus silence.

       However,  with the rfPIC hardware the receiver doesn't have a
Squelch
       ability which means that even with no signal,  the noise floor
creates
       an almost continuous dominant state.  So to condition the
receiver a
       slightly different process was chosen.

       The first message transmitted contains an extra preamble of 16
bits
       consisting of 9 alternating 1's and 0's and then a recessive or
       transmitter off time of 7 bits representing a new interframe
gap.

       This conditions the data slicer to properly see the 5 bit on/off

       preamble which signifies a new message.

       Once this first preamble is done, the rest of the block of
messages
       no longer needs the extra two bytes as the data slicer in the
receiver
       is now conditioned.
       
       For example without the initial conditioning preamble:

       Sending 0x55 which doesn't need bit stuffing looks like this:
       000001111100101010110101010111111
          |-0x07  |-0xCA  |-0xB5  |-0x5F  |-0xFF
   17 overhead bits plus 16 data bits = 33 bits * 50uS per bit = 1.65mS
       
       while sending 0xFF, which needs stuffing looks like this:
       0000011111011110111100001000010111111
          |-0x07  |-0xDE  |-0xF0  |-0x85  |-0xFF
       |         |    |    |   |    | |----|- Interframe Space(6)
     |         |    |    |   |    |- Stuff bit(1)

       |         |    |    |   |- Stuff Bit(1)        
       |         |    |    |- Stuff Bit(1)
     |         |    |- Stuff Bit(1)
     |         |- Start Bit(1)  
     |--------|- Preamble for Data Slicer conditioning(10)

   21 overhead bits plus 16 data bits.
       at 20kbps ==> 50uS/bit * 37 bits == 1.85mS

   Add in worst case Transmitter start up time of 1.2mS
       and worst case message transmission time is:
       
       1.2mS + 1.85mS == 3.05mS
       
*/  

Automation Artisans Inc.
http://www.autoartisans.com
Ph. 1 250 544 4950


{Quote hidden}

2007\05\13@013615 by Jinx

face picon face
> Than you for sharing that.  Very generous

What goes around comes around

> In keeping with that spirit here's an approach I used for imitation
> anti-personal land mines

Cheers for another approach


2007\05\13@105345 by Scott Dattalo

face
flavicon
face
On Sun, 2007-05-13 at 14:47 +1200, Jinx wrote:

<snip>

Thanks for sharing...

> My application uses two 12F675s clocked with 4MHz internal. The
> receiver PIC needs to match its timing to the transmitter, which uses
> (approx) 1ms bit length. Two bytes of data are sent = 32 bits of
> Manchester

For my (similar) application, a fixed bit rate is unacceptable. While I
can't share the code, I can say that it's fairly straight forward for the
receiver to dynamically adjust to the transmitter's bit rate. There's a
trade off between interference/noise rejection and the dynamic range of
the bit rates. For my set up, I accommodate a ratio of 4:1.

Another improvement you may wish to consider is decoding the Manchester
stream while the data is being received. This accomplishes two things.
First, it allows you to recognize more quickly when the incoming stream is
corrupted. Second, it allows you to respond more quickly to the next data
stream.

> God bless logic analysers

And simulators...

Once you remove the big kinks, a simulator will allow you to explore all
of those corner cases.

Scott

2007\05\13@193239 by Jinx

face picon face
part 1 1329 bytes content-type:text/plain; (decoded 7bit)

> Another improvement you may wish to consider is decoding the
> Manchester stream while the data is being received

That would be quite possible to do that, given the longish bit time of
1ms. All in favour of concurrent events where possible. Probably
wouldn't change this one, but I'm working on a bi-directional application
that can, for example, request a re-send if data is munted

> > God bless logic analysers
>
> And simulators...
>
> Once you remove the big kinks, a simulator will allow you to explore
> all of those corner cases.

Very true, although it really needed a logic analyser in this case to
capture what happened in h/w before the PIC reacted (attached). It
did show, most clearly and in a revelatory manner, that the s/w was
too lax by letting noise slip though as data. It ruled out immediately,
even at first glance, many other possible causes

Chris, the attached is an actual analyser output showing just what sort
of noise comes out of the rx module. The sampling indicators are 1ms
apart, it gives you some idea of the randomness. I tried a simple RC
filter when I first used these modules, but the nature of the noise makes
that impractical. I don't think any general purpose filter would work
very well, you'd be better to do it in s/w


part 2 1697 bytes content-type:image/gif; (decode)


part 3 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2007\05\13@222536 by Dennis Crawley

picon face
On Sunday, May 13, 2007 8:31 PM [GMT-3=CET],
Jinx  wrote:

> > > Another improvement you may wish to consider is decoding the
> > > Manchester stream while the data is being received
> >
> > That would be quite possible to do that, given the longish bit time of
> > 1ms. All in favour of concurrent events where possible. Probably
> > wouldn't change this one, but I'm working on a bi-directional
application
> > that can, for example, request a re-send if data is munted
> >

Talking about balanced transmission, Alfredo Squieri "alfredo AT
metronic.com.ar", from PiclistLatina, has suggested to split the byte. Both
Upper an Lower nibble are the upper nibble of the new two bytes. The lower
nibble is 1010 for both new bytes. eg desired byte: 11000011  the new two
bytes: 11001010 00111010

This is an improvement from sending the word without encoding, but is much
simpler than manchester, i think.

Anyway, I'm still thinking on Scott proposal. How can the receiver change
the period of a bit dinamically?. (Zen) I'd better re-study Nyquist, Shanon,
SNR, etc!

Regards,
Dennis.

ps: 500mt with a 10 elements Yagui with reflector for 419MHz. wenshing
modules.




2007\05\13@235141 by Jinx

face picon face
> Upper an Lower nibble are the upper nibble of the new two bytes.
> The lower nibble is 1010 for both new bytes. eg desired byte:
> 11000011, the new two bytes: 11001010 00111010

I'll try that when I get a moment

2007\05\14@044952 by Alan B. Pearce

face picon face
>> In keeping with that spirit here's an approach I used for
>> imitation anti-personal land mines
>
>Cheers for another approach

I am real impressed with the exciting things people get up to ...

2007\05\14@130544 by Scott Dattalo

face
flavicon
face
Dennis Crawley wrote:

> Anyway, I'm still thinking on Scott proposal. How can the receiver change
> the period of a bit dinamically?. (Zen) I'd better re-study Nyquist, Shanon,
> SNR, etc!
>  

Hi Dennis,

The receiver doesn't change the period of the bit, instead it adapts to
whatever period the transmitter produces. Instead of sampling at a
constant rate (like in Jinx's algorithm), I measure when the edges
occur. This practically necessitates continuous Manchester decoding.

Scott

2007\05\15@064301 by Dennis Crawley

picon face
On Monday, May 14, 2007 2:05 PM [GMT-3=CET],
Scott Dattalo  wrote:

> Dennis Crawley wrote:
>
> > Anyway, I'm still thinking on Scott proposal. How can the receiver
change
> > the period of a bit dinamically?. (Zen) I'd better re-study Nyquist,
Shanon,
{Quote hidden}

got it.

Thanks Scott


2007\05\15@133710 by Rolf

face picon face
Chris wrote:
> In message <01cc01c794e5$605b8260$0100a8c0@ivp2000>, Jinx
> <.....joecolquittKILLspamspam.....clear.net.nz> writes
>  
>>> Has anyone used the following modules, or anything similar, with a PIC?
>>>
>>> www.maplin.co.uk/module.aspx?ModuleNo=22965&doy=12m5
>>>      
>> Yes. I use the Keymark equivalent, Manchester encoded data between
>> PICs, 200m line-of-sight with simple 1/4 wave aerials
>>
>> I was intending to write it up shortly as a PIClist page, but I can give you
>> details now if you want
>>    
>
> That would be lovely, thanks!
>  
Well, I have been working on a TX/RX process as well, using the Linx
TXM-418-LR and RXM-418-LR pair. I have tried a number of different
protocols, and I eliminated Manchester as being too complicated, slow,
and inconvenient.... I know thet I may get scorned for this, but, I
think there is a better way when dealing with the modules.... ;-) There
may even be a name for what I am doing, but I am uncertain.

Like Jinx's modules, you need to have regular toggling of the radio
carrier in order for the RX to keep a fix on the signal, and not drop in
to a noisy quagmire. The Linx modules are spec's for a bit rate of
between 100 and 10,000 bps. Anything slower than 100bps will have noise,
and more than 10,000 will fall outside the RF rise/fall times. So, you
need to keep the RF signal toggling otherwise the RX will loose sync.
For this reason I initially started with Manchester encoding. It seemed
ideal.... ;-)

Like others have mentioned, there is a problem syncing the TX's and RX's
bit rate. Specifically, with a sampling process that the manchester
encoding requires, you need to first measure the TX's period, and then
sample (preferably multiple times) the signal as it arrives. I see that
jinx only samples once per bit.

Anyway, I have a CCP module on the PIC I am using on the RX side. Using
it on capture mode I was able to significantly reduce the code
requirements, and the reliability was much improved. The PIC12F675 that
Jinx is using does not have a CCP module, so this would not be available....

On the other hand, I am using a PIC18F4620, and coding in C18, so I do
have the CCP module, and writing it in C is easier for me... ;-) The
transmitter is controlled by a PIC10F206, so I do at least have some
assembler in there ;-)

Anyways, I tried manchester encoding, I tried simple UART stuff, and I
tried numerous home-brew things I could think of. Additionally, in the
early stages of this process I had some hardware problems with my setup,
and this caused reliability issues. I am sure that I could have got
things working reliably using any of the protocols I tried, but, the
final result is much cleaner than any others I tried.

The basic concept is that for every bit of data the TX PIC will toggle
the TX Module high for some period, and then low for another period.
Each of these periods will be longer than the minimum time of 100us (the
maximum bit rate is 10,000bps, or 1 bit per 100us). I could have pushed
it to 100us bits, but, for somesafety factors, and because of the slow
clock on the receiver, I doubled it to 200us.
In addition, the period for the transmission is always fixed (in my
case, 500us). So, to send a '1' bit, I transmit 'high' for 300us, and
low for 200us. For a '0' bit, I transmit high for 200us, and low for 300us.

This gives an effective bit rate of 1 data bit per 500us, or 2000bps.

The RF modules have another small complexity, the time for the RX output
to go high after the TX input goes high (high lag time) is different to
the time for the RX output to go low after the TX input goes low.
Basically, a 200us high time on the TX input will not be a 200us high
time at the RX output. I found that logic trying to rely on this was
doomed to failure. On the other hand, the high lag time is very
consistent between bits, so, the period for one of my data bits is very
very constant (I found it to be within 1 'tick' of my system clock, and
that is most likely due to the fact that the RX is not sync'd with the PIC).

So, the protocol I have implemented ended up being very simple. The
transmitter sends 8 sync bits (8 is overkill, I could have used 2 I
think). These sync bits are, as far as the TX is concerned, exactly
250us high, and 250us low. These bits serve the two-fold purpose of
bringing the RX out of is noisy slumber, as well as supplying the
receiving PIC with a few constant sync bits. The PIC expects to receive
sync bits, and it identifies the first sync bit as having an approximate
250us high time, and a period of approx 500us. It identifies the second
sync bit as having a nearly identical high time and pariod as the first
sync bit. In my current version of the code, it also expects a third and
fourth sync bit.

After receiving some consecutive sync bits, the RX Pic expects two start
bits. These are '0' and '1' respectively. The '0' bit is expected to
have a high time of about 200us, and the same period as the sync bits.
The '1' bit is expected to have a high time of about 300us, and the same
period as the sync bits.

From this point, the code expects to get the data bits. These must have
the same period as all previous bits (the sync bits), and must also have
close to identical high times as either the '1'start bit, or the '0'
start bit.

It sort of looks like....

     _       ________       ___     ___     ___ ... __      ____    
____    __      .....
    | |     |        |     |   |   |   |   |   |...|  |    |    |  |    
|  |  |    |.....
_____| |_____|        |_____|   |___|   |___|   |...|  |____|    |__|    
|__|  |____|.....
....noise................   .........sync bits......  0start 1start  
1data   0data

Currently I am only receiving 8 data bits, and I coded it all in a
switch statement..... it is not necessarily pretty..., but it works
well. The concept could scale up pretty much endlessly in trms of data
bits in the transmission, and because the code re-synchronizes with the
transmitter's bit rate at the start of each bit, it will never need to
be resynchronized... well, you know what I mean... a 1% error on a bit
stream using manchester encoding where the signal is sampled twice per
period (like jinx's system), will loose sync within 50 bits or so...

I am using a 6.5536Mhx CX, giving a PIC clock speed of 1.6384MHz, and
this is only slightly faster than the transmitter's 1MHz. Additionally,
this gives me only 327 Tcy per 200us transmission.

So, the high time varies, but the period is constant. Sort of like
PWM..... which is why I use the CCP module to receive the transmission.

In order to avoid lag times for ISR servicing, I have written the code
in the high priority ISR, and there are no other High priority interrupts.

Anyway, I don't think my system is perfect, and it most likely has been
done before (but I can't find a reference/name for it), still, I am
throwing it out there for two reasons .... firstly, it works and is on
topic. Secondly, it would be nice to get some Constructive (and perhaps
not so constructive) criticism.

Rolf

Here's the C code:

#include <p18cxxx.h>

/*
This is set up using the CCP2 module...

The goal is as follows...:
0.  Identify multiple (at least 4) 250us pulses (with 500us period).
(the TX will send 8 bits).
1.  Wait for 2 start bits (zero, then one) about 200us of 500us, and
300us of 500us respectively.
   use the start bit times for identifying later bits of data...
4.  Zero bits must be very close to first start bit time.
5.  One bits must be very close to second start bit time.
6.  The rising edges must all be consistent periods
7.  We expect a parity bit at the end. This is odd parity...
   it will ensure an odd number of ones in the transmission.
8.  There will be two stop bits, which, for the moment I will ignore.

All in all, we want to account for as many as 30 edges:
- 8 edges for 4 sync bits.
- 4 edges for 2 start bits.
- 16 edges for 8 data bits
- 2 edges for parity bit.

for debug purposes we will record the relevant details of each edge in
the bittimes[] array.

The TMR3 module is used with two purposes. Firstly it is the time base
of the CCP module.
Secondly, if 2 TMR3 interrups happen while waiting for an edge it means
at least 1/25th of a
second has elapsed, which is longer than our bits will ever be. it also
ensures that our math is
OK (we do simple additions/subtractions on unsigned ints.
 
*/

#define RXPWR LATAbits.LATA4
#define RXPWRDDR DDRAbits.RA4
#define TMRCON T3CON
#define TMRINIT 0x41
#define TMRIF PIR2bits.TMR3IF
#define TMRIE PIE2bits.TMR3IE

#define DATADDR DDRCbits.RC2
#define DATA PORTCbits.CCP1
#define CCPCON CCP1CON
#define CCPR CCPR1
#define CCPFALLING (unsigned char)0x04
#define CCPRISING (unsigned char)0x05
#define CCPCOMPARE (unsigned char)0x0b
#define CCPIE PIE1bits.CCP1IE
#define CCPIF PIR1bits.CCP1IF
#define CCPIP IPR1bits.CCP1IP

#pragma udata txrx_chunky
unsigned int bittimes[32];

#pragma idata access txrx_iaccess
volatile near unsigned char rxdata = 0;
volatile near          char rxflag = 0;
#pragma idata

#pragma udata access txrx_uaccess
volatile near union
{
 struct
 {
   unsigned S_DONE:1;
   unsigned E_NOISE:1;
   unsigned E_SYNC:1;
   unsigned E_PERIOD:1;
   unsigned E_STARTZ:1;
   unsigned E_STARTO:1;
   unsigned E_DATA:1;
   unsigned E_TMRLOOP:1;
   unsigned E_PARITY:1;
 };
 unsigned char Byte;
} rxStatus;

#pragma code
void rxInit(void) {
   RXPWRDDR = 0;   // Turn off the RX power.
   RXPWR = 0;      // Turn off the RX power.
   CCPIP = 1;      // Set CCP interrupt to high priority!
}

unsigned char rxData(void) {
   return rxdata;
}

unsigned char rxIsActive (void) {
   return CCPIE;
}

void rxEnable(void) {
   RXPWR = 1;      // turn on

   TMRCON = TMRINIT; // enable 16bit T3 Reads/writes, and start timer.
                     // we never stop timer until end of decode.
                     // Set timer 3 as clock for CCP
                   
   TMRIF = 0;
   TMRIE = 1;
 
   rxflag = -1; // this will cause a 'reset' logic to happen inside the
CCP ISR.
   CCPIF = 1;
   CCPIE = 1; // cause a CCP trigger - a reset
}

void rxDisable(void) {
   TMRIE = 0;
   CCPIE = 0;

   RXPWR = 0;      // turn of

   TMRCON = 0x00;
   TMRIF = 0;
   CCPIF = 0;
 
}


#pragma interrupt rxCCPInt
void rxCCPInt (void) {
   static near char rxi;
   static near char bi;
   static near char synccnt;
   static near char parity;
   static near unsigned int hitime;
   static near unsigned int lotime;
   static near unsigned int synctime;
   static near unsigned int period;
   static near unsigned int bittime;
   static near unsigned int zerotimel;
   static near unsigned int zerotimeh;
   static near unsigned int onetimel;
   static near unsigned int onetimeh;
 
   if (rxi & 0x01) {
       // we are an odd rxi ... which means we have just got the end of
a high pulse...
       // which means we are measuring the low time.... the time when
the data line went low.
       lotime = CCPR;
       // we expect the next edge to be rising.
       CCPCON = CCPRISING;
   } else {
       hitime = CCPR;
       CCPCON = CCPFALLING; // we expect end of bit at a falling edge
   }
   if (bi >= 32) {
       bi = 0;
   }
 
   CCPIF = 0; //clear interrupt flag
 
   if (rxflag < 0) {
       // we had a timer rollover during a bit transmission..... a bad
thing...
       // this requires a reset....
       // this will also happen when the module is initialized (forced
interrupt...).
       rxi = 0;
       CCPCON = CCPRISING; // we expect end of bit at a rising edge...
       CCPIF = 0;
       rxStatus.E_TMRLOOP = 1;
       rxflag = 0;
       return; // exit from the ISR
   }
 
   rxflag = 0; // reset any timer loops now....

   // test rxi AND INCREMENT IT!!!!
   switch (rxi++) {
   case 0: // start 1st - high
       // we just got a rising edge... perhaps a start bit.
       // bittimes[0] = 0;
       break;
   case 1: // start 2nd - Low
       synctime = lotime - hitime;
       bittimes[bi++] = synctime;
       if (synctime < (unsigned)(350) || synctime > (unsigned)(600)) {
           // bit 1 time is too far out of expectations.
           // this was probably just some noise....
           // go back to case 0:
           rxi = 0;
           rxStatus.E_NOISE = 1;
       } else {
           // for later reference, we calculate the brackets for the
zero and one bits....
           // it has to be longer than 1/4 period....
           zerotimel = synctime >> 1;
           // and a 1 bit has to be less than 3/4 period
           onetimeh = synctime + zerotimel;
       }
       break;
   case 2: // start 3rd - High
       // got end of low period... end of first sync. Start of second sync.
       period = hitime - lotime + synctime;
       bittimes[bi++] = period;
       if (period < (unsigned)(790) || period > (unsigned)(850)) {
           // The period is not close to 500us
           // this is not the intended start bit...
           // we need to pretend we have just been case 0:, and next is
case 1:
           rxi = 1;
           rxStatus.E_NOISE = 1;
       } else {
           // it looks like we may just have finnished our first sync bit.
           synccnt = 1;
       }
       break;
   case 3: // end of high part of second sync bit.
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       if (bittime < (unsigned)(synctime - 20) || bittime >
(unsigned)(synctime + 20)) {
           // we are not a good sync bit.....
           // pretend we are at the end of some noise spike, and we are
ready for the first sync bit...
           rxi = 0;
           rxStatus.E_SYNC = 1;
       }
       break;
   case 5: // end of high part of third sync bit.
   case 7: // end of high part of fourth sync bit.
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       if (bittime < (unsigned)(synctime - 20) || bittime >
(unsigned)(synctime + 20)) {
           // we are not a good sync bit.....
           // pretend we are at the end of some noise spike, and we are
ready for the first sync bit...
           rxi = 0;
           rxStatus.E_SYNC = 1;
       }
       break;
   case 4: // end of low part of second sync bit
   case 6: // end of low part of third sync bit
   case 8: // end of low part of fourth sync bit
   case 10: // end of low part of 1st start bit.
   case 12: // end of low part of 2nd start bit.
   case 14: // end of low part of 1st data bit
   case 16: // end of low part of 2nd data bit.
   case 18: // end of low part of 3rd data bit.
   case 20: // end of low part of 4th data bit.
   case 22: // end of low part of 5th data bit.
   case 24: // end of low part of 6th data bit.
   case 26: // end of low part of 7th data bit.
   case 28: // end of low part of 8th data bit.
   case 30: // end of low part of parity bit.
       bittime = hitime - lotime + bittime;
       bittimes[bi++] = bittime;
       if (bittime < (unsigned)(period - 20) || bittime >
(unsigned)(period + 20)) {
           // we have the wrong period .... oops.
           // since the period is fairly precise... we go back to the
beginning....
           // but, this could be the start of a new sync bit....
           rxi = 1;
           rxStatus.E_PERIOD = 1;
       } else {
           synccnt++;
       }
       break;
   case 9: // end of high part of potentially first start bit - which
will be a zero (short pulse).
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       if (bittime > (unsigned)(synctime + 20)) {
           // we are not a good sync bit..... nor a start bit....
           // pretend we are at the end of some noise spike, and we are
ready for the first sync bit...
           rxi = 0;
           rxStatus.E_SYNC = 1;
       } else {
           // we are a potential sync bit.... or the zero start bit so
far... lets wait for the period to come through....
           if (bittime > (unsigned)(synctime - 20)) {
               // we just another sync bit.....
               // pretend we are at stage 8
               rxi = 8;
           } else if (bittime > zerotimel) {
               // we have a valid start bit....
               zerotimel = bittime - 20;
               zerotimeh = bittime + 20;
           } else {
               // we have an invalid start bit.... go back to the
drawing board.
               rxi = 0;
               rxStatus.E_STARTZ = 1;
           }
       }
       break;
   case 11: // end of high part of second start bit - a one (long pulse)
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       // we are fully expecting this to be a one....
       if (bittime < (unsigned)(synctime + 20) || bittime > onetimeh) {
           // we are not a good one start bit....
           // this is fatal, start all over at the beginning....
           TMRIE = 0;
           rxi = 0;
           rxStatus.E_STARTO = 1;
       } else {
           onetimel = bittime - 20;
           onetimeh = bittime + 20;
           parity = 0;
           rxdata = 0;
       }
       break;
   case 13: // end of high part of data bit 1
   case 15: // end of high part of data bit 2
   case 17: // end of high part of data bit 3
   case 19: // end of high part of data bit 4
   case 21: // end of high part of data bit 5
   case 23: // end of high part of data bit 6
   case 25: // end of high part of data bit 7
   case 27: // end of high part of data bit 8
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       rxdata <<= 1;
       if (bittime > zerotimel && bittime < zerotimeh) {
           // we are a zero
       } else if (bittime > onetimel && bittime < onetimeh) {
           // we are a 1
           rxdata ++;
           parity++;
       } else {
           // we are some crap... start over.
           rxi = 0;
           rxStatus.E_DATA = 1;
       }
       break;
   case 29: // end of high part of parity bit
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       if (bittime > zerotimel && bittime < zerotimeh) {
           // we are a zero - parity count should be odd so that the
parity bit keeps it odd...
           if (parity & 0x01) {
               // the count is odd... a good thing.
           } else {
               // but we got even... so, parity calc was broken.
               // start over.....
               rxi = 0;
               rxStatus.E_PARITY = 1;
           }
       } else if (bittime > onetimel && bittime < onetimeh) {
           // we are a one ... so, parity count should be even... while
the parity bit makes it odd.
           if (parity & 0x01) {
               // but we got odd... so, parity calc was broken.
               // start over.....
               rxi = 0;
               rxStatus.E_PARITY = 1;
           } else {
               // parity matches....
           }
       } else {
           // we are some crap... start over.
           rxi = 0;
           rxStatus.E_PARITY = 1;
       }
       break;
   case 31:
       // this is the start of the stop bit.. if that makes sense....
       // we will just use this to short-change the process...
       bittime = lotime - hitime;
       bittimes[bi++] = bittime;
       rxStatus.S_DONE = 1;
       CCPIE = 0; // disable the interrupt ... we are done...
       break;
   default:
       // This is an unexpected occurrence.....
       rxStatus.Byte = 0xff;
       rxflag = -1; // cause a 'reset' to the logic...
       break;
   }
}

// This calls the interrupt function when interrupted.
#pragma code high_vector=0x08
void interrupt_high (void) {
 /*
  * Inline assembly that will jump to the ISR.
  */
 _asm GOTO rxCCPInt _endasm
}
#pragma code


void rxTmrInt (void) {
       // thi method must be called from the low priority interrupt.
       // the timer has looped once, and is about to again....
       // this is an error condition.
       // reset the CCP to wait for a start bit...
       // whatever we have been waiting for has taken too long.
       if (rxflag) {
           rxflag = -1;
           CCPIF = 1; // trigger an interrupt in the module....
       } else {
           rxflag = 1;
       }
}




2007\05\15@191127 by Gerhard Fiedler

picon face
Rolf wrote:

> The basic concept is that for every bit of data the TX PIC will toggle
> the TX Module high for some period, and then low for another period.
> Each of these periods will be longer than the minimum time of 100us (the
> maximum bit rate is 10,000bps, or 1 bit per 100us). I could have pushed
> it to 100us bits, but, for somesafety factors, and because of the slow
> clock on the receiver, I doubled it to 200us. In addition, the period
> for the transmission is always fixed (in my case, 500us). So, to send a
> '1' bit, I transmit 'high' for 300us, and low for 200us. For a '0' bit,
> I transmit high for 200us, and low for 300us.

This is very similar to Microchip's KEELOQ PWM protocol. Your preamble is a
bit different, and I don't think they take different delays for hi>lo and
lo>hi transitions into account like you do. (They use duty cycles of 1/3
and 2/3 and three samples per bit for decoding: one in the part that should
always be hi, one in the variable part, and one in the part that should
always be lo.) But in essence, it's the same thing. I'm also currently
researching what protocol to use over a radio link, and just today thought
that I'd found it with this PWM scheme.

The simpleness to synchronize to the bit rate is really convincing, as is
the fact that you have a good noise retention at the bit level by very
simple checks before even looking at the data.

It is probably not as effective bandwidth-wise as Manchester, and it is not
a balanced protocol (the average value depends on the data transmitted).
But it seems a very good compromise, and easy to implement.

It seems you weren't aware of the KEELOQ PWM protocol. If not yet done,
have a look at Microchip's data sheets; they probably give you an idea or
two.

Thanks for sharing,
Gerhard

2007\05\15@200144 by Jinx

face picon face
> be resynchronized... well, you know what I mean... a 1% error on
> a bit stream using manchester encoding where the signal is sampled
> twice per period (like jinx's system), will loose sync within 50 bits
> or so...

That's very true. The downside of not periodically detecting edges
is that synch will be lost. For the application I described I've sent
data streams of 100 bytes as a test (actual application is 6 bytes)
without loss, but the simple "time and sample" method is not what
should be used

That said, I've analysed many receptions in all weather conditions
and temperatures (which affects the PIC's clocks) and with various
transmission blockages (wet house in the way etc) and yet to have
a failure at 70m, using just a single sample point

As I mentioned, an upcoming half-duplex project will need a better
protocol, so I'll be toughening it with some of the suggestions

2007\05\15@210737 by Marcel Duchamp

picon face
Gerhard Fiedler wrote:

> (They use duty cycles of 1/3 and 2/3)


I used this approach a while back on a hobby project and it worked quite
well for my needs. Extremely simple to encode and decode.

For receiving, I used interrupts driven by edge detection from the RF rcvr.

Once triggered, I counted one-banana, two-bananas until half a bit time
transpired.  Then I sampled the incoming line.  Shifting this in
produced a byte.

Is it the correct byte?  I used framing as follows: synchronize with
0xAA, 0x55, byte count, data, checksum.

The 0xAA and 0x55 did duty to get the RF rcvr to play nice.  Plus noise
had a hard time to keep up and look like that along with the byte count
and checksum.

I was sending control data to a lighting controller; if a frame or 3 got
lost, no big deal.  The data was sent continuously until the operator
approved of the result. Think: operator with control watching the lights
for correct operation.

Noise, especially when the TX was off, meant a steady stream of
interrupts.  I dealt with this in the easiest way: a separate PIC to
demodulate the RX line.  Only good data got sent to the main controller
via serial data lines.

2007\05\15@233148 by Scott Dattalo

face
flavicon
face
On Tue, 2007-05-15 at 20:11 -0300, Gerhard Fiedler wrote:

> This is very similar to Microchip's KEELOQ PWM protocol. Your preamble is a
> bit different, and I don't think they take different delays for hi>lo and
> lo>hi transitions into account like you do. (They use duty cycles of 1/3
> and 2/3 and three samples per bit for decoding: one in the part that should
> always be hi, one in the variable part, and one in the part that should
> always be lo.) But in essence, it's the same thing. I'm also currently
> researching what protocol to use over a radio link, and just today thought
> that I'd found it with this PWM scheme.

When designing an RF link based on PWM, be sure to compare it against
Manchester encoding for the following cases:

  -- varying pulse timing
  -- multiple transmitters
  -- distance between transmitter and receiver

If PWM works for you then use it. However, there are many reasons people
have been using Manchester encoding for decades!

The RF system I work on was originally implemented (by another engineer)
to use the Keeloq PWM style encoding. However, my client had problems
whenever there were multiple transmitters. Specifically, interference
between transmitters would frequently cause bits to get missed. The common
manifestation was a shift-by-one error in the data. Now, I'm sure this
particular error could have been fixed (e.g. by adding better error
detection). But there were other system "issues" (like having a separate
dedicate processor to decode the RF stream), that required a redesign.

You may wonder how Manchester encoding may be more robust against multiple
transmitters or how it can allow the distance between the transmitter and
receiver be increased. Well first, a Manchester encoded data stream has
state information. For example, if you look at a Manchester stream there
are narrow pulses and wide pulses. Only certain combinations of these
pulses are allowed. So if interference damages a particular pulse then
there's a significant probability that the Manchester state decoder will
encounter an illegal state. Second, the narrow pulses in a Manchester
encoded stream are wider than the narrow pulses in a PWM encoded stream
(assuming the two streams have the same bit time). This means that the
frequency spectrum of the data stream has a greater proportion of its
energy in the lower harmonics. This further means that the RF transmitter
hardware has more time to transmit the narrow pulses. And finally, this
means that the narrow Manchester pulses have a greater probability
reaching there receiver than the narrow PWM pulses as the distance between
the receiver and transmitter increases.


> The simpleness to synchronize to the bit rate is really convincing, as is
> the fact that you have a good noise retention at the bit level by very
> simple checks before even looking at the data.

I think the Manchester encoding is only more complicated if you don't
understand it. The synchronization and decoding of Manchester and PWM are
comparable in code size. My Manchester receiver takes about 100
instructions to receive a 32 bit stream, although any given path through
the receiver takes fewer than 50 cycles.

Scott

2007\05\15@235538 by John Dammeyer

flavicon
face
Hi Scott,

> The RF system I work on was originally implemented (by
> another engineer)
> to use the Keeloq PWM style encoding. However, my client had problems
> whenever there were multiple transmitters. Specifically, interference
> between transmitters would frequently cause bits to get
> missed. The common
> manifestation was a shift-by-one error in the data. Now, I'm sure this
> particular error could have been fixed (e.g. by adding better error
> detection). But there were other system "issues" (like having
> a separate
> dedicate processor to decode the RF stream), that required a redesign.

Multiple transmitters and collisions are a pain.  

Way back when I designed the CANRF modules the only transceiver that was
workable was the RFM TR1000.  Working in OOK mode, it had a
transmit/receive turnaround time that let me do bitwise arbitration at
20kbps.  Dominant or RF on has priority over Recessive or RF off so as
long as the receiver was ready to listen in the next bit period it would
arbitrate and allow the highest priority transmitter to win the bus (RF
medium).  Then the message with bit stuffing and a CRC followed.  I used
the Microchip MCP2510 and then later the MCP2515 CAN devices using SPI
to fill the CAN registers.

And yes, if the threshold was set too low the CAN RX input was
constantly bombarded with RF noise.

CAN would also handle retries if the message was corrupted or not
received.

If I were to do it again, there are definitely things I'd change in the
CAN protocol to make it better.   Also, since there was no transmitted
preamble to condition the receive data slicers, I'd send a dummy message
with a 0 payload and then follow that with the real message.  The dummy
had the highest priority so it was always transmitted first out of the
lowest tx buffer.

John Dammeyer


{Quote hidden}

> --

2007\05\16@092616 by Gerhard Fiedler

picon face
Scott Dattalo wrote:

>> This is very similar to Microchip's KEELOQ PWM protocol. Your preamble
>> is a bit different, and I don't think they take different delays for
>> hi>lo and lo>hi transitions into account like you do. (They use duty
>> cycles of 1/3 and 2/3 and three samples per bit for decoding: one in
>> the part that should always be hi, one in the variable part, and one in
>> the part that should always be lo.) But in essence, it's the same
>> thing. I'm also currently researching what protocol to use over a radio
>> link, and just today thought that I'd found it with this PWM scheme.
>
> When designing an RF link based on PWM, be sure to compare it against
> Manchester encoding for the following cases:
>
>    -- varying pulse timing
>    -- multiple transmitters
>    -- distance between transmitter and receiver
>
> If PWM works for you then use it. However, there are many reasons people
> have been using Manchester encoding for decades!

I'm sure there are :)

One is that Manchester guarantees an average; with PWM, it may be anything
between the two limits (all 0, all 1). Another is, as you say, that PWM
requires more bandwidth, which may affect maximum distance. I didn't think
the latter was very noticeable, but maybe it is.


> You may wonder how Manchester encoding may be more robust against
> multiple transmitters or how it can allow the distance between the
> transmitter and receiver be increased. Well first, a Manchester encoded
> data stream has state information. For example, if you look at a
> Manchester stream there are narrow pulses and wide pulses. Only certain
> combinations of these pulses are allowed. So if interference damages a
> particular pulse then there's a significant probability that the
> Manchester state decoder will encounter an illegal state.

Same for PWM. If you sample 3 times per bit, the first sample must be 1,
the second is the bit state, the third must be 0. Anything that's not 1x0
is noise.

The difference is, again, that for this you need 3 samples per bit, with
Manchester you need (at least) 2 for something similar. But the noise
rejection of PWM doesn't seem to be worse.

> Second, the narrow pulses in a Manchester encoded stream are wider than
> the narrow pulses in a PWM encoded stream (assuming the two streams have
> the same bit time). This means that the frequency spectrum of the data
> stream has a greater proportion of its energy in the lower harmonics.
> This further means that the RF transmitter hardware has more time to
> transmit the narrow pulses. And finally, this means that the narrow
> Manchester pulses have a greater probability reaching there receiver
> than the narrow PWM pulses as the distance between the receiver and
> transmitter increases.

To me, it seems that this is the main difference.


>> The simpleness to synchronize to the bit rate is really convincing, as
>> is the fact that you have a good noise retention at the bit level by
>> very simple checks before even looking at the data.
>
> I think the Manchester encoding is only more complicated if you don't
> understand it.

This may well be true :)

> The synchronization and decoding of Manchester and PWM are comparable in
> code size. My Manchester receiver takes about 100 instructions to
> receive a 32 bit stream, although any given path through the receiver
> takes fewer than 50 cycles.

Thanks for insisting... I'll definitely have a closer look at Manchester
decoding. I just liked the simpleness (in terms of firmware implementation)
of a guaranteed rising edge at the beginning of each bit time.


OTOH... Why would Microchip use this as basis for their KEELOQ products if
decoding Manchester is as easy as decoding PWM and results in better
performance?

Gerhard

2007\05\16@112759 by Bob Blick

face picon face

>
> OTOH... Why would Microchip use this as basis for
> their KEELOQ products if
> decoding Manchester is as easy as decoding PWM and
> results in better
> performance?
>

Maybe because they didn't have someone of Scott's
caliber working on that project? Judging by their app
notes and libraries, there's an assortment of skill
levels at Microchip.

Cheerful regards,

Bob

2007\05\16@134153 by Scott Dattalo
face
flavicon
face
Gerhard Fiedler wrote:
> Scott Dattalo wrote:
>  
>> You may wonder how Manchester encoding may be more robust against
>> multiple transmitters or how it can allow the distance between the
>> transmitter and receiver be increased. Well first, a Manchester encoded
>> data stream has state information. For example, if you look at a
>> Manchester stream there are narrow pulses and wide pulses. Only certain
>> combinations of these pulses are allowed. So if interference damages a
>> particular pulse then there's a significant probability that the
>> Manchester state decoder will encounter an illegal state.
>>    
>
> Same for PWM. If you sample 3 times per bit, the first sample must be 1,
> the second is the bit state, the third must be 0. Anything that's not 1x0
> is noise.
>  

Gerhard,

You're confusing pulse width validation with pulse stream state. For
example, it's possible for interference to perturb a skinny pulse into a
fat pulse or vice versa in both Manchester encoded data streams and PWM
encoded streams. In a PWM encoded stream, you can only detect this error
via your error code -- and to the degree it's robust enough to catch
these types of errors, then there's no problem. However, in Manchester
coding there is state information in the data stream itself. Regardless
of the message, there are certain combinations of skinny and wide pulses
that are illegal. For example, a skinny pulse must either be preceded or
followed by another skinny pulse. So if you see a wide pulse on either
side of a skinny one, then that's an error.

However to be fair here, interference very seldom perturbs a single
pulse. Pulse width validation is adequate protection against
interference. A more likely scenario is one in which there's variability
among the transmitters. For example, 1/3 of a bit time may differ from
one transmitter to another (due to things like the transmitter's
hardware or it's distance from the receiver). This requires a less
stringent check on the pulse validation which in turn makes the system
more susceptible to interference.

> OTOH... Why would Microchip use this as basis for their KEELOQ products if
> decoding Manchester is as easy as decoding PWM and results in better
> performance?
>  

I'm not sure for their reasons for choosing a PWM encoding scheme over a
Manchester encoding. But KEELOQ is a whole lot more than just the
physical layer.

Scott

2007\05\17@083510 by Gerhard Fiedler

picon face
Scott Dattalo wrote:

{Quote hidden}

I'm not sure I'm confusing things :)  I know that there is state
information in the Manchester stream, in that only certain states are
permitted. But that's also true for the PWM stream.

Take the simplest case of two samples per bit for Manchester and 3 samples
per bit for PWM. Manchester allows only combinations 10 and 01, everything
else is considered invalid. Average noise has a 50% probability of
generating a valid bit. PWM allows only combinations 1x0, everything else
is considered invalid. Average noise has a 25% probability of generating a
valid bit.

This doesn't say much about robustness against various forms of distortion,
but it shows the inherent state information in both encodings that allows
rejection of invalid states at the bit level. Certain combinations are
legal, others are not legal -- this is the same in both encodings.


>> OTOH... Why would Microchip use this as basis for their KEELOQ products if
>> decoding Manchester is as easy as decoding PWM and results in better
>> performance?
>
> I'm not sure for their reasons for choosing a PWM encoding scheme over a
> Manchester encoding. But KEELOQ is a whole lot more than just the
> physical layer.

Of course, however AFAICS the rest of the system could remain pretty much
the same if it was implemented with Manchester instead of PWM.

Gerhard

2007\05\17@104202 by Scott Dattalo

face
flavicon
face
part 1 806 bytes content-type:text/plain; charset="iso-8859-1" (unknown type 8bit not decoded)

On Thu, 2007-05-17 at 09:33 -0300, Gerhard Fiedler wrote:

> I'm not sure I'm confusing things :)  I know that there is state
> information in the Manchester stream, in that only certain states are
> permitted. But that's also true for the PWM stream.

Maybe an illustration will make things clearer. In the attached figure,
the 5-bit pulse stream of 11000 is encoded with PWM and Manchester. Single
bit errors in PWM still produce a valid PWM data stream. However, single
bit errors in Manchester produce illegal Manchester streams. All the pulse
in the erroneous Manchester streams are the correct width. However, if
state information is not retained from the previous pulses then it's not
possible to recognize the erroneous encoding.

Scott

part 2 11734 bytes content-type:image/png; name="pwmVSman.png" (decode)


part 3 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2007\05\17@125800 by Gerhard Fiedler

picon face
Scott Dattalo wrote:

>> I'm not sure I'm confusing things :)  I know that there is state
>> information in the Manchester stream, in that only certain states are
>> permitted. But that's also true for the PWM stream.
>
> Maybe an illustration will make things clearer. In the attached figure,
> the 5-bit pulse stream of 11000 is encoded with PWM and Manchester. Single
> bit errors in PWM still produce a valid PWM data stream.

Ok, I'm gonna try to put apples to apples and oranges to oranges :)

> However, single bit errors in Manchester produce illegal Manchester
> streams. All the pulse in the erroneous Manchester streams are the
> correct width.

Correct width, yes -- but not single sample errors. 4th line has two wrong
samples (the PWM has only one wrong sample), 5th line is a sync error that
can't (easily) happen with PWM.


If the issue is that the hi>lo transition has a delay that varies from bit
to bit (as you seem to assume in the 2nd line), you may have a point -- or
not, because none of the Manchester examples uses the same type of
distortion. OTOH, if that is not something that changes from bit to bit,
it's probably not so difficult to "calibrate" the receiver for a single
transmission by a suitable preamble.

It seems to me we need to first discuss what kind of distortion we want to
look at (and possibly why, for my education), and then see how these
distortions affect the different encodings, in rejection of non-signals,
recovery of distorted information and interpreting information wrongly.

Gerhard

2007\05\17@134327 by Scott Dattalo

face
flavicon
face
Gerhard Fiedler wrote:
> Correct width, yes -- but not single sample errors. 4th line has two wrong
> samples (the PWM has only one wrong sample), 5th line is a sync error that
> can't (easily) happen with PWM.
>  
Let me try just one more time (3rd time's a charm?).:

Manchester encoding has state information PWM encoding does not.

Take a continuous stream of either encoding and try to start decoding it
any point. With PWM the bit boundaries are very explicit. With
Manchester, any edge is potentially a bit boundary. With PWM you can
trivially read off the 0's and 1's. With Manchester you'll get 0's and
1's only if you started at the proper bit boundary. Manchester bit
boundaries are only ascertainable based on past bits, i.e. state
information. I'm not sure how this is refutable?

In my opinion (and experience), the Manchester state information
provides another degree of robustness over other encoding schemes.

Scott

2007\05\17@213704 by Gerhard Fiedler

picon face
Scott Dattalo wrote:

> Manchester encoding has state information PWM encoding does not.
>
> Take a continuous stream of either encoding and try to start decoding it
> any point. With PWM the bit boundaries are very explicit.

Yes, but only if you start decoding (sampling) at the right point. The fact
that this "right point" is easier to find with PWM doesn't mean it's not a
"state information" -- it's just one that's a whole lot easier to find.

> With Manchester, any edge is potentially a bit boundary. With PWM you can
> trivially read off the 0's and 1's. With Manchester you'll get 0's and
> 1's only if you started at the proper bit boundary.

Sounds to me as if this, by itself, could mean that PWM is more robust.

> Manchester bit boundaries are only ascertainable based on past bits, i.e.
> state information. I'm not sure how this is refutable?

I never said that decoding a Manchester stream doesn't need state
information carried from one bit to the next, so the question whether this
is refutable is a bit moot -- no one's trying to refute it :)  It's you
who's claiming that PWM doesn't. If I understand you correctly, the state
information you're after are the bit start and end points. With Manchester,
you need past bits to find it, with PWM, each bit carries this state
information. But depending on the decoding algorithm, for example when
using preambles to determine the bit timing or the correct comparator
threshold, there's also state information that goes over more than a single
bit. So what is it that PWM doesn't have (not "requires", but "have")?

I also think that there's a difference between "carries state information"
and "requires state information to decode". No single Manchester-encoded
bit carries any state information. You receive a hi-lo sequence or a lo-hi
sequence, and that's your bit (if you know the bit start and end times) --
there's no information about past bits included. The information about past
bits is necessary to find the bit boundaries, but it's not included.

> In my opinion (and experience), the Manchester state information
> provides another degree of robustness over other encoding schemes.

That may well be, as I've already written. To me it seems likely that the
lower bandwidth requirements are an important part of this.

Gerhard

More... (looser matching)
- Last day of these posts
- In 2007 , 2008 only
- Today
- New search...