modules again. Just to recap, the problem with these is that the receiver usually employs a simple
slicer which switches the output high or low based on whether its above or below the slice point.
The slice point itself is set from the filtered mark-space ratio of the incoming signal, which of
course on a balanced signal source is exactly midway.
This is the ideal situation for maximum reliability, range and 'cleanliness' of the received signal.
They're intended to be used with symmetrical data, such as Manchester encoding.
That said, a few of us have been using these modules with straight unbalanced PPM with reasonable
results, but I finally got around to trying a 'homebrew' form of balanced-PPM, and here it is - and it
works superby on these modules. This idea may of course have been proposed before, but not that
I'm aware of, certainly I've never seen an actual implementation like this.
Its similar to conventional PPM in that the channel timing is edge to matching-edge, but instead of
having fixed-width PPM pulses (usually of 300uS or so) we share the timing such that for each
channel, the PPM line spends half the channel-time low and half the channel-time high.
Each channel is therefore symmetrical.
The sync period is also shared, half high, half low, and so the entire frame or stream of frames is
always perfectly symmetrical. The performance over cheap 433 modules is astonishing, with good
range, no noise or jitters, instant recovery from loss-of-signal and no syncronisation problems
whatsoever.
Creating symmetrical PPM is easy, for each channel value in turn, you set the PPM line, wait half
the channel value, reset the PPM line, wait half the channel value - then move on to the next channel.
Sync is simply an extra-long channel value of 4-6ms or so.
Recovering symmetrical PPM at the receiver is a little more complex, but easy enough.
The timer is configured to free-run at a half-microsecond increment.
We set up an edge-triggered interrupt (ie interrupt-on-change) linked to the PPM input pin.
We discard every alternate edge, so we're working on either just the positive-going edges (or just the
neg, doesnt matter which). We keep track of time between ISR calls. If > 4ms has passed its a sync
pause, and we zero the channel count. Otherwise we populate the current channel with the timer
value and increment onto the next element:
Code: Select all
void read_symmetrical_ppm() {
static unsigned long counter;
static byte channel;
if (PIND & B00001000) { // PPM input on D3. we use only alternate edges, doesnt matter which
counter = TCNT1;
TCNT1 = 0;
if (counter < 8000) { // if less than 4ms since last edge
ppm[channel] = (counter / 2); // cos timer has half uS increment
channel++;
}
else channel = 0; // Sync
}
}
The diagram shows a typical 4-channel frame but you can get say 7 channels into a 20ms frame.
Cheers
Phil