need a low-latency wireless solution

I am new to wireless, with a moderate comprehension of theory and operation, but no hands on experience.

My desired application is to synchronize the operation of two separate devices, and transmit a little data between them. They will both be sampling some input at a fixed frequency (at least 1KHz, ideally), and I want to make sure they do so at the same time (preferably within 100us of each other), and exchange the data with each other (maybe 8 bit packets). Now the raw data rate isn’t a problem since most decent modules can do that, but the latency is the issue, since I doubt anything is under 100us, especially when accounting for failed transmissions and acknowledgment and such. If the latency was predictable within 100us, I could deal with it being long by simply correcting for the sample time, but I don’t know if such consistency is reasonable. I’ve been looking at the different products from sparkfun, mainly the Xbees and nRF2401 modules, but I get the feeling they won’t work for what I want. On the other hand I imagine something like the RF link pair would have much lower latency since it’s OOK, but then I would only be able the operate one pair of the devices (they will always be in pairs).

So I guess I want something that uses a spread spectrum modulation technique but also doesn’t require long latency. It this a feasible request? Or are there tricks to work around the latency problems?

Thanks,

Mike

Suggestion: each node takes its data samples and time-tags them and stores them in a data buffer/cache. The the data is sent wirelessly in non-real time for analysis.

Otherwise, at the 100uSec level of precision, this gets complex.

yes, but when the devices exchange data, the time data associated with each sample will still be referenced to the time frame of the device that sampled it, not the device that receives it wirelessly. If the clock frequency is even a tiny bit different between the two devices, then after just few minutes they will drift apart. I need a way to periodically synchronize them. Am I even making sense?

-Mike

After consulting some people I’ve come up with the following idea. For each pair of “slave” devices I will have a third “master” with its own RF module (I’m going with the nrf24l01 at this point). Every 500us, the master will alternate between sending transmissions to the slaves (so each slave will receive one every 1ms, 500us out of phase of each other). Each slave will have a sort of PLL function where every time it receives a transmission, it will record the time since its last transmission (should be 1ms) and it will factor that value into a recursively filtered average. That average will be the “output” of my software PLL, so the slave’s sample rate will be that average. Thusly, even if a transmission is missed it won’t affect the syncing, unless several are missed in a short time. The PLL outputs of each slave will be offset from each other by 500us, but since that is consistent and precise, I can just have each slave compensate for it.

Does this make sense?

So I have another question, this time specifically about the nrf24L01. There are apparently two ways to address different modules; the frequency channel and the address. I’m assuming that for my application, I will want each set of three devices running on it’s own frequency (assuming I don’t want to use more sets than channels available). And then just pick some random set of addresses for the devices. Is this correct? I’m pretty sure I wouldn’t several sets of these things running on the same frequency.

Also, is it true that having longer address lengths tends to result in better transmissions? I’ve also heard that certain address registers (especially stuff starting in 101010 like the preamble) are harder to recognize than others).

edit: oh, and one last thing. I wanted to make it so that on startup the master does a scanning routine to see which RF channels are already being used. I would just set it as a RX, wait a bit, then read the CD (carrier detect) bit, and if it was clear then I’d use that channel, otherwise try another and repeat. But the documentation doesn’t say much about the CD bit except that it is set high when a carrier is detected for 128us. Does is clear itself automatically when the carrier is gone, or do you have to clear it manually via a write operation?

-Mike

mtwieg:
So I have another question, this time specifically about the nrf24L01. There are apparently two ways to address different modules; the frequency channel and the address. I’m assuming that for my application, I will want each set of three devices running on it’s own frequency (assuming I don’t want to use more sets than channels available). And then just pick some random set of addresses for the devices. Is this correct? I’m pretty sure I wouldn’t several sets of these things running on the same frequency.

If you're running them all on different frequencies, you could use the same addresses for each group (since they won't be able to interfere with one another). Keep in mind that you have to have a 2 MHz frequency separation when running at 2 Mbps (this is 2 LSBs in the RF_CH register). Ideally, you would choose addresses that have as few repeating bits as possible.

You could also set the devices up as subnets on the same frequency. The only trade-off there is that you could only have one of the devices talking at any one time.

mtwieg:
Also, is it true that having longer address lengths tends to result in better transmissions? I’ve also heard that certain address registers (especially stuff starting in 101010 like the preamble) are harder to recognize than others).

The advantage you get with longer address lengths isn't necessarily better transmissions (likely worse, since there's more data to be sent per packet), but instead less noise packets at the RX. And alternating bits are generally the best way to go for addresses.

mtwieg:
edit: oh, and one last thing. I wanted to make it so that on startup the master does a scanning routine to see which RF channels are already being used. I would just set it as a RX, wait a bit, then read the CD (carrier detect) bit, and if it was clear then I’d use that channel, otherwise try another and repeat. But the documentation doesn’t say much about the CD bit except that it is set high when a carrier is detected for 128us. Does is clear itself automatically when the carrier is gone, or do you have to clear it manually via a write operation?

As far as I know, the CD bit will clear itself once it loses the RF signal.

The advantage you get with longer address lengths isn’t necessarily better transmissions (likely worse, since there’s more data to be sent per packet), but instead less noise packets at the RX.

If there aren’t any other devices operating on its frequency channel, then is there any significant chance of noise packets?

brennen:
Ideally, you would choose addresses that have as few repeating bits as possible.

And alternating bits are generally the best way to go for addresses.

wait, what?

mtwieg:
As far as I know, the CD bit will clear itself once it loses the RF signal.

That’s what I’d assume.

also, are interrupt bits in the status register automatically cleared when it’s read, or do you need to write to status to clear them?

-Mike

An RTC will solve the time problem. You could use a watch crystal on the MCU, if you choose a suitable chip. It could be updated periodically via the radio link.

Leon

mtwieg:

The advantage you get with longer address lengths isn’t necessarily better transmissions (likely worse, since there’s more data to be sent per packet), but instead less noise packets at the RX.

If there aren’t any other devices operating on its frequency channel, then is there any significant chance of noise packets?

You never know if there's going to be a microwave or WiFi where you are (unless you're out in the woods or something like that).

mtwieg:

brennen:
Ideally, you would choose addresses that have as few repeating bits as possible.

And alternating bits are generally the best way to go for addresses.

wait, what?

By repeating bits I meant sequences like b'11111111' or b'00000000'. What I was trying to convey was that alternating bit sequences like b'01010101' are the best for addresses.

mtwieg:
also, are interrupt bits in the status register automatically cleared when it’s read, or do you need to write to status to clear them?

You have to manually clear interrupts in the status register.

brennen:
You never know if there’s going to be a microwave or WiFi where you are (unless you’re out in the woods or something like that).

I suppose that's true.

brennen:
By repeating bits I meant sequences like b’11111111’ or b’00000000’. What I was trying to convey was that alternating bit sequences like b’01010101’ are the best for addresses.

Okay I get what you mean by avoiding lots of repeating bits, but wouldn't strings of alternating bits also be bad, since it could be seen as a continuation of the preamble? The datasheet mentions this:

Addresses where the level shifts only one time (that is, 000FFFFFFF) can often be detected in

noise and can give a false detection, which may give a raised Packet-Error-Rate. Addresses

as a continuation of the preamble (hi-low toggling) raises the Packet-Error-Rate.

So it seems the best solution is somewhere in the middle. As long as the toggling bits aren’t in the first byte of the address, it should be okay, I guess.

You have to manually clear interrupts in the status register.

Yeah, just found that in the datasheet after asking. Makes sense.

-Mike

leon_heller:
An RTC will solve the time problem. You could use a watch crystal on the MCU, if you choose a suitable chip. It could be updated periodically via the radio link.

Leon

No matter how tight the clock frequencies are between the two devices, drift will occur, so I need some sort of master/slave orientation where all the devices need to sync periodically to the master. Having less drift in the clocks just means I have to update less frequently (like with 60ppm crystals the devices would drift apart by 100us in as little as 1.667 seconds, where as 10ppm crystals would be in sync for up to 10 seconds). And having a third device as a master ensures that neither of the slave devices are biased in any way.

Right now I’m writing the code for the initialization routine of the master device. When the devices are turned on the slaves will physically dock with the master so they can exchange addresses, channels, and get their sync initially. After the master recognized a good sync, it will indicate it somehow and then the devices can be separated for use. I’m programming in AVR assembly and it looks like just that routine will be around 2Kb of code. I might need a bigger memory version of my AVR…

Okay, so I got three nrf24l01 modules in about a week ago and I’m slowly getting them working. Getting a simple two way data stream with enhanced shockburst was pretty easy, but it seems that when transmitting a packed I can’t do any write operations until I get either the TX_DS or MAX_DS interrupts without it screwing up the payload. I want to switch TX addresses in between each transmission, so this makes things go pretty slow. I assumed the address registers were buffered so that when you started a transmit by pulsing CE, it would store the present registers, but it seems that if you modify them before the TX is finished it screws things up. Is this correct?

To compensate for this slowness, I’ll probably need to push the spi speed a bit. Can anyone verify how fast it’ll reliably work? The datasheet says 8Mbs, but I have a suspicion that this IC has unusually high input capacitance, so I doubt I can get it that high.

Other than that, I’m pretty happy with them so far. The latency is very consistent (like within a microsecond or two), so I’m sure I’ll be able to sync the slave devices very well.

However, one of the modules was dead. I built up some test circuits with two of them to practice getting them working, but today when I switched in the third one into the same working circuit, it didn’t function and the circuit drew way more current than it’s supposed to. Testing revealed its MOSI and SCK pins were shorted together, making it completely unusable :x . Hadn’t been used at all since then. I wrote an email inquiring about if I could get a replacement, but I have no idea if they’ll do it.

Until I have three working modules again, I really can’t develop this much more :frowning: