segunda-feira, 18 de outubro de 2010

RF Links Reliable Messaging

This is something i've been working on for a couple days and finally got something worth showing. After a while using Radio Frequency Links in some projects i realized that many messages are lost and it requires you to send them over and over again until it reaches the destiny and does what it is supposed to do. I then decided to do something about it and since i know i'm going to lose a few messages in the air at least send it again in a transparent way so it doesn't bother me. In a few words this is an implementation of a protocol that guarantees that a message sent over a RF Link will get to its destiny no matter what. This implementation is based on RF Links, Arduino e Java. At the end of the explanation of the protocol there's an example of where it can be usefull, so, let's get it started.

RF Links

What you will need
Part 1 (The Protocol):
1x Arduino (any version, mine is a Duemilanove)
1x RF Link 2400bps Receiver - 315MHz
1x RF Link 2400bps Receiver - 434MHz
1x RF Link Transmitter - 315MHz
1x RF Link Transmitter - 434MHz
1x Breakout Board for FT232RL USB to Serial


Part 2 (The Application):
1x Three-Way Switch
1x 5V Relay
1x 2N2222 Transistor
1x 1N4007 Diode (1N4004 also works)
1x 1K Resistor


Part 1 (The Protocol):
This solution is based on two parts, a transmitter, connected to a PC running Java code, and a receiver, connected to the Arduino board. Important to say that this name schema can get confused once both the transmitter and the receiver can transmit and receive messages, so let's establish that the transmitter is the one connect to the PC, always, and the receiver is the one on the Arduino board.

The transmitter
To build the transmitter we're going to use the Breakout Board for FT232RL USB to Serial, the RF Link Transmitter - 315MHz and the RF Link 2400bps Receiver - 434MHz. One thing to pay attention here is that the receiver and the transmitter need to have different frequencies, otherwise the communication will not happen.
First thing to do is to wire the VCCIO pin on the breakout board to 5V and to help you on this, check this mini-tutorial on the SparkFun Forum.
Once this first step is done we need to add the transmitter/receiver pair to our transmitter (remember? transmitter means PC, receiver, Arduino). So, there's also a thread on the SparkFun forum to help you on this task.
As you may have noticed on the thread it only refers to the transmitter, to add the receiver is easy and the labels on the pins are self-explanatory. One thing that can get you confused is that the receiver has two data pins, we're going to use only one, the first one from left to right, and it goes on the RXD pin on the breakout board.
Antennas are optional, i used them.

Transmitter - Left View

Transmitter - Right View

Transmitter - Top View

The receiver
To build the receiver we just need to take a look at this post and instead of wiring to different Arduinos you will wire both the transmitter and the receiver in only one board. One more thing that need to be done is that instead of using pins 0 and 1 for the transmitter and the receiver respectively we're are going to use pins 2 and 3.

Receiver - Front View

Receiver - Back View

Receiver - Other Angle View

Code
This is the best part, so let's begin from the beginning. To get it done i started using this and this codes available here. This code already implements error catching so i just had to do a little modification to add reliable messaging and it's available for download in two parts here and here.
After that comes the Java code wich is a version of the Arduino code implemented in Java, of course, and it's also available in two parts here and here. This is a improved version of the Java code available here and it uses the RXTX library for serial communication.
In a few words what this code does is: The transmitter (Java code) keeps the id (a random number) of the last message sent and keeps sending this very same message until it gets a reply from the receiver (Arduino). The receiver, once a message is received, verifies if it has the same id of the last message it received. If the id is the same it means the transmitter didn't receive the reply and just send a reply again if it's not it handles the message and send a reply for the first time. When a reply gets to the transmitter it verifies if it's a reply for the last message sent and, if it's ok, it stops sending messages. All this is done with some error catching that was already available and you can check the console (both Arduino and Java) for the outputs.

Java code running
Part 2 (The Application)
I think an implementation like that can be used in many situations, and it can also be improved to add more capabilities. One situation where it can be used is to build a home automation system, which was already something i would like to work on. On my case i just added the capability of switching my room light wirelessly and in order to do that i added a little circuit and a relay to the Arduino part of the solution, walkthrough found here. Thing is, i wanted the wirelessly controlling to be a plus, i still wanted to be able to turn my light on and off using the switch. So, i added a three-way switch to the solution and connected it to the relay, help found here. Doing this i'm now able to turn my light on using the switch and turn it off wirelessly and vice versa or use just one to accomplish both tasks. Here are some pictures to help in the understanding:

parts needed

AC
Three-way switch connected to the 5V relay and the AC
The whole thing connected
Conclusion
So, i think that's it. Let me know if you guys used it to something else, or even if you think something can be modified or, i don't know, if you have doubts in some part that was not very well explained (easy to happen). Comments will be very appreciated. And remember to follow Arduitter on Twitter to get to know about all the news here.

14 comments:

wtf disse...

What about a formal description of the protocol? A description that can be used to implement the protocol in the language you want without looking at the current implementation. That would be useful!

Arduitter disse...

@wtf, that sounds good, i'll work on it. Thanks for the comment.

CVBruce disse...

I'm curious as to why you use a random packet id instead of a serial count. A random number generator will produce the same number twice in a row, so you risk having two sequential packets with the same id.

Anônimo disse...

I really like how you documented your protocol, but _please_ do a solid electrical installation!



If you solder bare wires to the relay, only a few movements on the cable will bend the pins around enough to break off. And use a flame-retardant, protective isolated encasing for the whole setup if it is to be placed into wooden furniture.

chrisbbehrens disse...

Have you looked at Forward Error Correction (http://en.wikipedia.org/wiki/Forward_error_correction)? This is how the problem is handled in most digital media, like CDs and portable phones.

There are two primary problems I see: there is no open source implementation of a non-trivial method (that I know of, please correct me if anybody knows of one), and this will substantially increase the processing load on BOTH sides of the transmission.

But it sure is cool. I worked on it for a startup a few years ago, trying to optimize the transmission of multi-terabyte video files across company networks...

Bunedoggle disse...

@WTF

So looking at the code, you're building a data packet that looks like this:

-----------------------------------------
| SOP byte | MAC Addr 3 bytes |
-----------------------------------------
| Seq # byte | DATA 3 bytes |
-----------------------------------------
| DATA byte | CHKSUM byte |
----------------------------

Where:
SOP = Start of packet (0xF0)
Seq # = User defined ID number
CHKSUM = (DATA[1]) ^ (DATA[0])

Is that pretty accurate Arduitter?

Arduitter disse...

@Bunedoggle, you almost got it. I'm preparing a post where i'm going to explain it. It actually is a 3 bytes (header), 1 byte (identifier), 1 byte (data) and 1 byte (checksum) packet.

Arduitter disse...

Here's the second post on the protocol.

http://arduitter.blogspot.com/2010/10/rf-links-reliable-messaging-part-2.html

Prashanth disse...

hey,
great article. Is it possible to use RF transmitter and receiver to make wireless USB ports?

Arduitter disse...

If i got your question right, yes, it is possible.

Prashanth disse...

Could you provide me with some more information on this.. am really interested in doing this(wireless USB)..Thanks.. Is there any way i can contact you via email/chat etc ?

Arduitter disse...

@Prashanth,

I think this post already provides something you can start with (components, code, schematics) but let me know if you need something else.
On the email/chat question, let's keep it here, this way we can help others.

Prashanth disse...

Sure.. i was just afraid i'd cramp up your comments section :) .. for my need i guess at the PC end i need the USB to serial converter which goes over a transmitter and then in the receiver's end i need the receiver but what do i connect to convert the serial back to USB?? can an arduino do that?
Thanks..

Arduitter disse...

@Prashanth,

Yeah, an Arduino is the way to go.

Postar um comentário