Developing a workable RF communications protocol is apt to be a tricky but educational exercise. A few additional points to consider beyond what's been said:
- On some radio hardware, it takes a lot of power to listen for a signal. With many if not most small radios, listening for a second is going to take more energy than transmitting for a millisecond; on some radios, listening for a millisecond may take more energy than transmitting for a millisecond. If current consumption is not an issue, listening continuously is a lot simpler than listening intermittently; if current consumption is an issue, however, it may be necessary to listen intermittently. Probably not a good idea until you've managed to get something going with a continuous-listen protocol.
- Listen-before-transmit may be "polite", but it's nowhere near as useful with RF as with e.g. an Ethernet cable. Ethernet signalling is designed so that not only is it likely that a device which listens before transmitting will usually avoid a collision, but it's also designed so that a device whose transmission collides with that of another device is virtually guaranteed to notice. RF transmission offers no such promise. It's entirely possible that when P wants to transmit to Q, some other device X which is closer to Q than to P will be transmitting loud enough to prevent Q from hearing P's transmission, but not loud enough for P to notice. The only way P will know that Q might not have received his transmission is by the fact that P won't hear a response from Q.
- It's important to beware the consensus problem--much moreso with RF than with wire signalling. If a P sends to Q, it's possible that Q will hear P's transmission and send an acknowledgment, but P will for various reasons not hear that acknowledgment. It's thus necessary to be very careful to distinguish retransmissions from "new" transmissions.
The consensus problem can be especially vexing if one is trying to save energy by powering down receivers when they're not needed. Suppose two P and Q are supposed to communicate once every 10 seconds, so they power up and P sends Q a packet. Q receives the packet, sends his acknowledgment, and--knowing that P won't be sending anything for almost ten seconds, powers down. If P doesn't get Q's acknowledgment, he'll retransmit; since Q is asleep, however, he won't hear P's retransmission. From Q's perspective, that wouldn't matter (he's already received his data), but it means no matter how many times P retries, he'll have no way of knowing Q got his packet (at least not until the next rendezvous in about ten seconds).
- It's entirely possible to have a situation in which node Q will be able to receive transmissions from P, but P will not be able to receive transmissions from Q. It may not be possible to usefully communicate in such scenarios, but one should at least endeavor to avoid doing anything obnoxious (like having P endlessly retry a transmission hundreds of retries per second)
As said, a workable RF communications protocol is apt to be a tricky exercise. Still, I'd expect you'll probably learn a lot from the experience.
EDIT: This answer has been modified to reflect the comment by the question asker and points out that he is quite right in his diagnosis of the problem, which isn't terribly useful information. The only useful piece of information in the section is the fact that there is no receive invert bit... But perhaps it will help future people diagnose their own UART problems
So let's take a look
a maps to O which means 01100001 maps to 01001111
b maps to ' which means 01100010 maps to 00100111
Let's assume that there's an implicit 1 before each of those and an implicit 0 after (start and stop bits). The RX module receives a continuous low signal, then the stop bit is sent as a high, which will be eaten as an idle signal, then the initial 0 will be consumed as a stop bit. Then the remaining bits will be inverted,
so 'a' == 1 10000110 0 initially (we send least significant bit first)
1 (implicit start bit) and starting 1 are both consumed as idle bits
then the first 0 is treated as a start bit
so received == 00001100 inverted (the extra zeros are the stop bit and idle bits after transmission has ended)
11110011 and reverse it (it was sent LSB first)
11001111 is what the inverted input would look like
01001111 is what's actually received which is super close!
if what you actually sent was "abc" all in a row, then the start bit of the b would make what was received 01001111 which matches exactly
'b' == 1 01000110 0 ==> 10001100 inverted and reversed gives
11001110 is what should have "logically" happened
00100111 actual
So that doesn't quite match, but if we assume that the "abc" is what happened again, we get
01001110 which is close enough (not sure where the shift came from)
Looks like you nailed the diagnosis, unfortunately there is no similar "invert signal" configuration bit in the receiver on the PIC. Though it's not hard to put an inverter on the receive path, which is incidentally what I would recommend doing!
As Olin noted, standard rs-232 signals are from +3V to +15V for a logical '1' and -3V to -15V for a logical '0'. The PIC is designed to operated at "TTL" levels, which means "transistor-transistor logic". The idea is that the PIC is designed to talk to other things which are physically close (i.e. on the same board) and thus the extra transmission distance and noise rejection provided by the full rs-232 levels are not needed for "standard" operation. It's not practical to be able to completely internally generate the positive/negative voltages needed for rs-232 operation completely internally on the PIC, so "normal" rs-232 communication was never really an option.
Since TTL levels are not the standard but instead a derivative of the standard (same protocol for timing, start and stop bits, parity, but different voltages), you don't buy a consumer "rs-232 adapter" for your computer unless it adheres to the standard. They do make TTL-level rs-232 adapters and they're very popular on hobbyist websites! Check out Adafruit's cable or the Sparkfun FTDI breakout. I find that in general, if it goes to a DB9 connector, it's probably a rs-232 level adapter.
Best Answer
The FS1000A is a 433MHz OOK (On Off Keying) transmitter. It produces a continuous 433MHz carrier wave when the digital input signal is high (keyed 'ON'), and no carrier when the input is low (keyed 'OFF'). OOK is a form of Amplitude Modulation suitable for transmitting digital signals.
This transmission could be received with a simple tuned circuit and diode detector (ie. a 'crystal set') to recreate the original digital signal, but only at close range because RF signal strength drops off rapidly with distance (and the FS1000A only puts out a few milliwatts, so the range would be extremely short!).
Most users want more than a few cm of range, so the XY-MK-5V uses a simple but very effective superregenerative circuit, which has an inherent AGC (Automatic Gain Control) action that amplifies even extremely weak RF signals. However it has two problems:-
when the RF signal is keyed OFF the receiver 'winds up the gain' trying to detect the nonexistent signal between the carrier wave pulses. If the carrier is OFF for too long then noise pulses will start to appear between the ON periods. When no signal is being transmitted the receiver's output is just a mess of noise.
The output of a superregenerative detector is AC, so the 0-5V DC digital signal becomes an audio signal whose average DC voltage varies depending on the ratio of high to low pulse times. The XY-MK-5V has a data slicer which attempts to regenerate the digital signal, but it only works properly when the high/low ratio is not too far away from 50%.
Your servo pulse signal is high for 1~2ms and low for 18~19ms, an ON/OFF ratio of only 5~11%. This is probably too low for the data slicer to work reliably, and the long OFF time may be enough to cause noise as the receiver 'winds up the gain'. The end result is that your digital signal is not received cleanly.
To solve these problems you need to 'encode' the servo pulse into a digital signal whose average ON/OFF ratio is not too far way from 50% (to keep the data slicer happy) and with short times between pulses (to keep the receiver's AGC happy). Then at the receiving end you need to 'decode' it back to a 1~2ms servo pulse.
One simple way to do it might be to produce a 50% PWM signal whose period varies from 1 to 2ms. At the receiver you could use another PIC which measures the period and uses it to control its own servo pulse generator. (the reason for using period rather than pulse width is to avoid timing errors due to unequal pulse rise and fall times).
A more complicated protocol might send digital data via Manchester coding or some other rf friendly encoding scheme, with a corresponding decoder at the receiver. Digital data usually needs synchronization bits to identify where the data packets start and end, and more bits (parity/checksum/CRC) to detect and possibly correct errors. This can make the coding of digital data protocols quite complex.
A UART is designed to send and receive asynchronous serial data over wires. The data format is not normally RF friendly because the signal can spend long periods of time being high or low with no attempt to maintain a 50% average. This can be fixed by carefully selecting which data patterns to transmit, or by further encoding the output. However unless you need to transmit and receive a lot of digital data it might be easier to just 'bit-bang' your own protocol.
UARTS have a very basic error detection system which uses a 'parity' bit to check that the number of '1's in a byte is even or odd, and they can detect 'framing' errors caused by missing start and stop bits. However this is often not enough to trap all errors caused by RF noise.