Experiment – Connecting up and testing the RF12 / TRX433S modules

///Experiment – Connecting up and testing the RF12 / TRX433S modules

Experiment – Connecting up and testing the RF12 / TRX433S modules

Experiment Aim

The aim here is to Setup two wireless modules and use the RF12_Demo application provided with the JeeLabs library to drive the modules. Special attention will be paid to the robustness of the signal at range.

A secondary aim is to gain an understanding into how the library is driving the modules and begin to think about how I will implement them.

Predicted Outcome

The specifications on the module say that they can reach a maximum distance of 300m. It must be assumed this will be in ideal conditions with no obstacles or interference  and hence direct line of sight. This will also assume correct antenna use. A prediction of around 20-30m would be impressive considering testing is being carried out in the Undergraduate Engineering labs which are densely filled with electronic equipment.

Setup

After reading through the documentation provided with the library the following setup was chosen:

Circuit

The following diagram illustrates the circuit to be used and how it will be connected on the breadboard:

Test circuit Setup for the Alpha transceiver module. (RF12)

This was worked out by looking at the header files of the library:

// ATmega328, etc.
#define RFM_IRQ     2
#define SS_PORT     PORTB
#define SPI_SS      5
#define SPI_MOSI    11
#define SPI_MISO    12
#define SPI_SCK     13

These were referenced with the pin out diagram of the transceiver module:

Pin-out for ALPHA RF module

Pin-out for ALPHA RF module (From Data Sheet)

Code – “RF12demo” (Relevant excerpts)

A look into what the demo code is doing to better understand what is going on. The microcontroller (MCU) was flashed with the demo program. A serial console was then opened on the computer it was connected to and a serial connection established.

Setup code:

This is the code which will be run before entering the main loop. I have used comments to better explain what it does.

void setup() {
      //Initialize a serial connection with the
      //computer at 27600 baud
      Serial.begin(57600);
      //A simple print via serial connection
      Serial.print("\n
[RF12demo.6]"); //First check EEPROM memory for stored configuration, //if nothing is found it will default to the else statement if (rf12_config()) { config.nodeId = eeprom_read_byte(RF12_EEPROM_ADDR); config.group = eeprom_read_byte(RF12_EEPROM_ADDR + 1); } // The default settings if no previously stored //configuration is found in EEPROM else { config.nodeId = 0x41; // node A1 @ 433 MHz config.group = 0xD4; saveConfig(); } //This will run the show help function which //prints text containing commands to the screen showHelp(); }

Before continuing a look at the commands this demo program allows. This is the code that the “showHelp” function prints to the serial connection, useful commands have been commented:

char helpText1[] PROGMEM =
    "\n"
    "Available commands:" "\n"
    // This will allow setting of ID in EEPROM -----------------
    "   i     - set node ID (standard node ids are 1..26)"
    "           (or enter an uppercase 'A'..'Z' to set id)"
    // ------------------------------------------------------
    "   b     - set MHz band (4 = 433, 8 = 868, 9 = 915)"
    "   g     - set network group (RFM12 only allows 212, 0 = any)"
    "   c     - set collect mode (advanced, normally 0)"
    // ------Our main method of testing will be using this-----
    "   t     - broadcast max-size test packet, with ack"
    "  ..., a - send data packet to node , with ack"
    // ------------------------------------------------------
    "  ..., s - send data packet to node , no ack"
    "   l     - turn activity LED on PB1 on or off"
    "   q     - set quiet mode (1 = don't report bad packets)"
;

Main Loop

Now the initialization of the device is complete it will fall into its main loop where it will wait for instructions via serial or received packets via the wireless module. Some relevant code excerpts have been explained below: The first condition we have will check whether there is any information on the serial buffer. If there is it will read the data into the function handleInput().

    if (Serial.available())
        handleInput(Serial.read());

Inside “handleInput” is a simple set of switch case statements. I have included below the switch case statements for the highlighted commands above:

If ‘i’ is send to the board via serial the following code is executed:

case 'i': // set node id
        config.nodeId = (config.nodeId & 0xE0) + (value & 0x1F);
        saveConfig();
        break;

So simply put when ‘i’ is selected the variable “nodeId” in class config is filled. The config is then saved. If ‘t’ is selected the following is run:

case 't': // broadcast a maximum size test packet, request an ack
        cmd = 'a';
        sendLen = RF12_MAXDATA;
        dest = 0;
        for (byte i = 0; i < RF12_MAXDATA; ++i)
             testbuf[i] = i;
        break;

The task here is to broadcast a test packet of the maximum size available and request an acknowledgement. If this is broken down:

  • Firstly broadcast means we want to send it to all nodes. This is done by setting its destination address to 0. This can be seen on line 4 of the code above.
  • Maximum size of a packet is defined in the header file by RF12_MAXDATA. We will set “sendLen” to this value. To create some data to send we load the array with numbers using a for loop from 0 to RF12_MAXDATA.
  • Lastly an ack must be requested. This is done by setting the “cmd” variable to ‘a’.

It will soon become clear how setting these variable will, after breaking from this switch case, influence the behaviour of the radio module. Here we see the ‘a’ and the ‘s’ keys run the same piece of code. The only difference is that the selected choice is moved into the global variable “cmd”.

            case 'a': // send packet to node ID N, request an ack
            case 's': // send packet to node ID N, no ack
                cmd = c;
                sendLen = top;
                dest = value;
                memcpy(testbuf, stack, top);
                break;

So the above commands, ‘t’, ‘a’ and ‘s’ set up some variables but do not actually transmit anything. The transmission part is done outside of the switch case. This was done, most likely to reduce the repetition of code within the program. Below is the code which actually performs the transmission using calls to library provided functions: Before taking a look at this code its makes for easier visual conception to see take a look at the structure of a packet:

    if (cmd && rf12_canSend()) {
        Serial.print(" -> ");
        Serial.print((int) sendLen);
        Serial.println(" b");
        byte header = cmd == 'a' ? RF12_HDR_ACK : 0;
        if (dest)
            header |= RF12_HDR_DST | dest;
        rf12_sendStart(header, testbuf, sendLen);
        cmd = 0;
    }

So to begin we have if (cmd && rf12_canSend()). Here is a condition which stops a send going ahead without a command first being set AND the module returning true to “rf12_canSend” stating its readiness. The module cannot transmit and receive at the same time.

At this point it became important to understand the structure of the packet to be sent. The diagram below shows the packet layout:

Command to build packet:

void rf12_sendStart(byte header, const void* data, byte length);
  • Header: Destination, if ack is required or if it is an ack
  • Length: Length of data in bytes (up to 66 bytes)
  • Data: A pointer to the data to be sent

Above we saw the data to be transmitted being placed into a variable names “testbuf” and the length of “testbuf” placed into “sendLen”. Now a look into how the application is building the correct packets for transmission:

After printing some characters to the serial port the header of the packet to be sent is built factoring in whether to request an acknowledgement or not. The line

“byte header = cmd == ‘a’ ? RF12_HDR_ACK : 0 ;”

is a simple “if” statement. It could also be written:

if( cmd == 'a')               //If cmd is equal to 'a'
     header = RF12_HDR_ACK;   //Header is set equal to the pre-defined-
else                          //-value RF12_HDR_ACK
     header = 0;              //If not header is set to Zero

Next we bring together all the variables we have just set and pass them to “rf12_sendstart” for transmission:

rf12_sendStart(header, testbuf, sendLen);

Experiment and Results

The experiment was simple. Set-up one of the Boards described above on a desk attached to a bench power supply. Power the other from a laptop and walk around whilst hitting the ‘t’ command. This will transmit a packet and then display acknowledgements, if any, received.

This was carried out in the undergraduate laboratories at the University of Surrey. These labs are packed densely with electronic instruments and devices.

A diagram of the set-up:

The results were very impressive. The link was solid for over 25 meters in nearly all directions. This was through walls and even worked into the building opposite. All in all the results indicate there should be little issue with range and transmission ability.

Table of results:

Direction 1 Direction 2
Distance (m) packets  Lost / 10 Line of Sight Packets Lost / 10 Line of Sight
0 0 yes 0 yes
2 0 yes 0 yes
4 0 yes 0 yes
6 1 yes 0 yes
8 0 yes 0 yes
10 0 yes 0 yes
12 0 yes 0 no
14 0 yes 0 no
16 0 yes 0 no
18 0 yes 0 no
20 0 yes 0 no
22 0 yes 0 no
24 0 no 0 no
26 0 no 6 no
28 0 no 5 no
30 0 no 10 no
32 8 no 8 no
34 10 no 10 no
36 10 no 10 no
38 10 no 10 no
40 10 no 10 no

?A graph of the values:

A screen shot of the test taking place (click to zoom):

Credits once again to http://jeelabs.org/. An immensely helpful and well written library.

By |2016-11-05T11:17:47+00:00November 14th, 2010|Lightive Project|3 Comments

About the Author:

A PhD in Electronic Engineering. A love for photography (www.islou.co.uk). An interest in tinkering, electronics and design. (www.louisc.co.uk).

3 Comments

  1. Tony Burns April 19, 2012 at 6:08 am - Reply

    Hi,
    I’m about to prototype observatory dome shutter controls for Auckland Astronomical Society and Stardome Observatory Auckland New Zealand.
    We’re expecting to use Alpha-TRX433S RF Transceiver modules to link data to/from the rotating dome.
    It would be very helpful to me to be able to see the diagrams in this web page but I am unable to access any ..
    Are you able to help me with this?
    thanx
    Tony Burns
    Auckland
    NZ

    • louis October 23, 2013 at 11:26 pm - Reply

      Sorry for the lack of reply Tony, I do hope you got this working!

      Images have been restored on the off chance its on the back burner.

      Cheers,

      Louis

  2. uki June 5, 2013 at 11:08 am - Reply

    hi,

    First two images are broken, please can you reupload them, it’s very hard to debug this library. Also can you write a simple example how to send one data packet to from one node to another just to test devices. br

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.