Bitrate with RF modules

I am using 433 MHz module to send data with a custom protocol I created. Everytime I start sending data I first send a 3000 us HIGH pulse, send the data with 1000 us HIGH pulse (bit 0) or 2000 us HIGH pulse (bit 1) and 4000 us HIGH pulse to finish the data sent.

I generally send 32 bits. In the worst case, if all bits are 1 it would take 3000 + 32*2000 + 4000 = 71000 us to send all the data. It means that in one second I can send this 32 bits data about 14 times (1000000/71000). It means that in one second I can send 32*14 bits = 448 bits.

So, can I say my "bitrate" is 448 bps? Is it right, or the definition of bitrate says something else that I didnt get?

gilperon: So, can I say my "bitrate" is 448 bps? Is it right, or the definition of bitrate says something else that I didnt get?

I'd say that you can send information coded in HIGH-bits as well as in LOW-bits. If you ignore the LOW-bits for coding information, I don't think that this will lower the nominal bit rates.

So if I should calculate your sending bit rate per second, I'd ignore the start bit and stop bit and calculate like that: 0-bit HIGH time: 1000 us 0-bit LOW time: 1000 us 1-bit HIGH time: 2000 us 1-bit LOW time: 1000 us Total: 4 bits in 5000 us = 4 bits / 0.005 s = 800 bps.

gilperon: I am using 433 MHz module to send data with a custom protocol I created. Everytime I start sending data I first send a 3000 us HIGH pulse, send the data with 1000 us HIGH pulse (bit 0) or 2000 us HIGH pulse (bit 1) and 4000 us HIGH pulse to finish the data sent.

I think, that even using the cheap ASK/OOK RF modules you can use shorter bit times and you will not need a finishing bit. Receiving is finished after the 32nd bit is received.

Instead the "regenerative receiver" will need some "training bits" to adapt to the signal at the beginning of the transmission.

So a full sending ASK/OOK protocol would perhaps look like, using - 0 bit HIGH time 300 - 1 bit HIGH time 600 - bit LOW time 450 - start bit time 5000

10x training bits: 300 us HIGH, 300 us LOW 1x very long start bit: 5000 us HIGH 1x bit LOW time 450 32x bit times (HIGH/LOW 300/450 or 600/450) finished

Total time= 10*(300+300)+5000+450+32*(450+450) in average = 40250 us. = ca. 40 milliseconds Worst case= 10*(300+300)+5000+450+32*(600+450) = 45050 us = ca. 45 milliseconds

If you want to send (for safety reasons) the protocol 3, 4 or 5 times, no additional training bits are needed, you just would follow with the next long start bit and then send the 32 data bits again.

Don't forget sending some 'training bits' at the beginning of each transmission, so that the receiver can adapt to the receiving signal level, this is important for cheap "regenerative RF receivers"!

gilperon: I have never heard the term "training" but I know it's always used. But I have no idea why is it used? RCSwitch send 31000 ms of "training pulses" and after that it divides the elapsd time by 31. Why?

OOK receivers have automatic gain control (AGC) to adjust receiver sensitivity to the strength of the incoming signal. When there is no signal, they generally crank up the gain until you see a stream of noise from the receiver. The AGC operates over a period of a few milliseconds, so when the receiver starts to detect a signal, it will take 1,000us or a bit more for the AGC to adjust the gain to the proper level for the incoming signal. To allow the AGC to adjust quickly and accurately, the first part of the transmitter message should be approx 50% duty cycle, and since some of it will be lost, it has to be a throw-away -- ie: not carry essential data. This lead-in part that is designed for the AGC to "train" on is the training sequence.

gilperon: 2) I have never heard the term "training" but I know it's always used. But I have no idea why is it used? RCSwitch send 31000 ms of "training pulses" and after that it divides the elapsd time by 31. Why?

As 'gardner' says, the initial training pulses at the start of the transmission are for the receiver to adapt gain control and sensisitity to the RF signal for best receiving conditions. If you send a second or third copy of data immediately after the first one, no additional training pulses before the second or third transmission are needed, because the signal itself keeps the gain control in the correct range. So if you would repeat the data three times, the sending logic would be: Initial training bits - long start bit - data bits - long start bit - data bits - long start bit - data bits Thre receiver would not try to receive traings bits, the receiver just waits for the long start bit, then starts receiving and counting data bits.

gilperon: 3) The end pulse (4000 us) I need to send cause sometimes noise can act as a 0 or 1 and it can corrupt the data. Despite this, I do something very similar to what you say: I receive the bits and when I get the 4000 us I check if I got exactly 32 bits, if not, the data is corrupted and discarded.

Normally you would send an additional checksum with the data bits. So 32 bits may be 24 bits payload and 8 bit checksum. Or maybe 28 bits payload and 4 bits checksum. Depending on your safety requirements to detect missing or toggled bits during receiving. At least that is how the protocol of cheap wireless temperature sensors work: They send 4 or 8 bits of checksum after sending the payload bits.

Generally the training sequence will be 4 or so iterations of 500us on, 500us off. ~4ms in total.

gilperon: Just one thought: after you all telling me what to do, I did this: before send the message I sent 10,000 us of HIGH pulse and after that the message itself. I got a MUCH BETTER range! BUT if I send a 10,000 us o LOW pulse and after that the message itself my range is very poor. Why is that?

Your sender is simple OOK: on-off-keying

That means: data pin HIGH ==> sender is ON data pin LOW ==> sender is OFF

So HIGH means "is sending" and LOW means "off".

gilperon: One other thing: @jurs gave me the nice idea of sending that now only in HIGH but also in LOW, so I could send pulses duration of 3000, 1000, 2000 and 4000 us during HIGH and LOW making my code much better. But there is a problem: I got much smaller range. Sending the pulses only in HIGH gave me a much better range. Why?

I don't know for sure. Maybe caused by the receiving logic. Maybe caused by the very long pulse time of 3000 us. If sending 3000 us as LOW (meaning "send nothing"), this might lead to gain adjustment at the receiver and he will receive garbage then.

I'd cut down the pulse times to send pulses in the range of 300...600 us HIGH/LOW.

3ms will screw up the AGC.

When I use those cheapo RF modules, I use these:

define txOneLength 550; //length of a 1

define txZeroLength 300; //length of a 0

define txLowTime 420; //length of the gap between bits

This second set did not work with all bit patterns. A run of zeros would cause it to fail because the dutycycle was too low:

define txOneLength 550; //length of a 1

define txZeroLength 210;

define txLowTime 350;

gilperon: Any idea?

Well, my first suggestion would be to look into using the radiohead or virtualwire libraries to manage these radios.

http://www.airspayce.com/mikem/arduino/RadioHead/ http://www.airspayce.com/mikem/arduino/VirtualWire/

These libraries handle everything.

If you want to design your own air protocol, or interface with an existing wireless doodad that uses 433MHz, then read up on some of the reverse-engineering threads. Here's an example.

http://bertrik.sikken.nl/433mhz/

There are also numerous threads in this forum regarding the topic.

DrAzzy: 3ms will screw up the AGC.

When I use those cheapo RF modules, I use these:

#define txOneLength=550; //length of a 1
#define txZeroLength=300; //length of a 0
#define txLowTime=420; //length of the gap between bits

Really? That must make for some interesting compilation errors. ;)

gilperon: @AWOL removing = will be fine.

No, it won't ;)

gilperon: virtualwire sucks

That's a pretty broad statement. What about it is not right for you? It has forward error correction, error checking and a pretty general interface. Its reasonably lightweight. I've used it several times with good results. My personal complaint about it is that it uses a lot of RAM and can't easily be split into transmit-only and receive-only because both the transmit and receive stuff is all referenced in the ISR so it gets sucked in at link time no matter what. I had to hack it a bit to get around those issues.

gilperon: Thank you so much!

@DrAzzy why do you use a gap between bits? Why dont you send the pulses all in sequence? I send all pulses in sequence and works fine. Any reason for that?

I will consider reducing the time of the pulses as you said, maybe it will improve my reception. I just didnt use small pulses cause I see lots of noise in the receiver with pulse lenght from 50 to 400 us. I rarely see a pulse lenght over 400 us, that's why I chose 1000 and 2000 to transmit my bits so it would be very rare to have some noise messing with my bits.

@jurs after some testing I discovered that LOW does not mean the transmitter is off, cause when the transmitter is really off (disconnected) I see lots of noise in the receiver, but when I leave the transmitter connected but at LOW I see very few noise. I think that LOW is just like HIGH but it has a different level of voltage.

@gardner I tried decreasing the training pulse to 4 pulses of 500 us in LOW and 500 us in HIGH and I got a small range. Any idea?

a) Because I didn't think of it? That would solve the problem of whitening the bitstream, and would I think make some of my code smaller too. b) Hm when you get the noise, is that with the transmitter totally disconnected, or just the data pin disconnected? c) I'd use a longer training pulse. I do 30 reps at 200us, but that may be overkill.

AWOL: Really? That must make for some interesting compilation errors. ;)

Sorry - I had #defines in one place, for one version, and variable declarations in another place, and somehow managed that with copy/paste and trying to reformat them to look the same.