Smart Packet Radio - Department of Electrical and Computer

advertisement
Jordan Guest 20747896
Supervised by Ahmet Sekercioglu
Table of Contents
1 - Introduction ....................................................................................................................................... 3
2 - Development...................................................................................................................................... 3
2.1 – Hardware .................................................................................................................................... 3
2.1.1 - Atmel AT90USB1286 Microcontroller .................................................................................. 3
2.1.2 - Hope RFM22B Wireless Transceiver .................................................................................... 3
2.1.3 - DS18B20 Temperature Sensor ............................................................................................. 3
2.2 – Software ..................................................................................................................................... 3
2.2.1 – LUFA..................................................................................................................................... 3
2.2.2 – Initialisation ......................................................................................................................... 4
2.2.3 – Sending ................................................................................................................................ 5
2.2.4 – Receiving ............................................................................................................................. 7
2.2.5 – Miscellaneous ..................................................................................................................... 9
3 - User Guide........................................................................................................................................ 10
3.1 – Linux ......................................................................................................................................... 10
3.1.1 - Programming the Microcontroller ..................................................................................... 10
3.1.3 - Using the Smart Packet Radio ............................................................................................ 11
3.2 – Windows .................................................................................................................................. 12
3.2.1 - Programming the Microcontroller ..................................................................................... 12
3.2.3 - Using the Smart Packet Radio ............................................................................................ 13
3.3 – Altering the RFM22B Settings .................................................................................................. 13
Interrupts ...................................................................................................................................... 14
Operating Function and Control.................................................................................................... 14
Packet Format ............................................................................................................................... 14
Transmitting and Receiving Settings ............................................................................................. 14
4 – Applications ..................................................................................................................................... 15
4.1 - A Learning Tool.......................................................................................................................... 15
4.2 - Beaconless Routing Protocols ................................................................................................... 15
3.2 - Beacon-Less Routing (BLR)[1] ............................................................................................... 15
3.3 - Implicit Geographic Forwarding (IGF)[2]............................................................................... 17
3.4 - BLR and IGF Combination (Based on BOSS protocol)[3] ....................................................... 18
5 – Conclusion ....................................................................................................................................... 18
6 – Appendices ...................................................................................................................................... 20
Appendix A ........................................................................................................................................ 20
Appendix B ........................................................................................................................................ 20
Appendix C ........................................................................................................................................ 21
Appendix D ........................................................................................................................................ 22
Works Cited ........................................................................................................................................... 52
1 - Introduction
The Smart Packet Radio has been developed for design and testing of wireless routing algorithms.
The layout of the board had been completed previously and this document describes the
development of the board from a freshly soldered printed circuit board, to a wireless device. Each
main component is described a long with its function. The firmware used is also detailed, to give the
user an idea of how the device operates without having to trawl through the code and scrutinise the
comments.
As the device is to be used by future students a user guide has been included in the report, which
details how to use the board step by step and is divided into 2 sections, one for the Windows
operating system and one for the Linux operating system.
As the initial purpose of this board was to provide an environment to test beaconless routing
protocols, research was conducted to find some example protocols which can be implemented in the
future. A section detailing three of these protocols is also included.
A conclusion detailing the testing results and also problems encountered is at the end, followed by
photos of the board, the PCB layout and the firmware which are included in the appendices for
further reference.
2 - Development
2.1 – Hardware
This section contains a short description of each major piece of hardware that facilitates the
operation of the Smart Packet Radio.
2.1.1 - Atmel AT90USB1286 Microcontroller
The Atmel Microcontroller serves many purposes. Firstly it allows communication between the user
and the RFM22B transceiver module. It is responsible for the passing of commands and information
to and from the module. This is achieved using the SPI interface available on the chip. It is also used
to format and decode packets that have been sent and received at a very basic level, requiring a
destination address and packet length in order to transmit data in its current mode of operation.
Once programmed, the microcontroller acts as an interface through which information can be
wirelessly sent and received. Utilising the LUFA library, the microcontroller is recognised by the host
as a communications port which makes it easily accessible across multiple platforms. As the device is
so easily configurable, the way in which this information is sent including the format, transmission
rate, carrier frequency etcetera, is completely up to the user. Using the current firmware, information
can be sent byte by byte (as long as it’s in the required packet format). Alternatively the packet
handling in the firmware can be removed entirely and the user can have this operation taken care of
by implementing the desired transmission algorithm at a higher level. This can be achieved by using a
script and accessing the device for the sole purpose of sending and receiving information.
Both port A and D are connected to external headers which can be used as general inputs and
outputs depending on what the desired operation is. Port B is used for the SPI interface and also for
LEDs which can be used to indicate whether the device is sending or receiving and also a health light
to ensure the microcontroller is functioning as expecting.
2.1.2 - Hope RFM22B Wireless Transceiver
The Hope transceiver module is what provides the Smart Packet Radio with its wireless capabilities.
The microcontroller communicates with it using a SPI interface. The mode of operation used in the
firmware provided is called FIFO mode. It operates by receiving the data intended for wireless
transmission to be sent from the microcontroller and storing it in a FIFO buffer located on the
transceiver module. Once the full packet has been stored in the buffer and the transceiver has been
notified of the packet length, the microcontroller puts the transceiver into transmit mode. Once in
transmit mode, the transceiver uses its internal packet handler to format the packet (the firmware
formats it as shown in Figure 1) using the data in the FIFO as the payload.
Figure - Packet Format
The preamble length is configurable though in testing it was found that with a preamble of less than
2 bytes, the device would regularly receive a valid preamble erroneously. In FIFO mode the
transceiver must have a sync word of at least one byte in length, so in testing the minimum was used.
The destination address can either be specified to a board or can be set to 0xFF which means the
broadcast is read by all devices. The source address of a board is coded in the firmware and can be
easily altered.
2.1.3 - DS18B20 Temperature Sensor
The temperature sensor is used to detect the temperature of the Smart Packet Radio’s immediate
environment. This is accomplished using a ‘one-wire’ protocol for requesting and reading data from
the chip. In the firmware, the temperature is read and the information sent to the host in a string
format. This only occurs when a jumper is placed across PA6 (Pin 6 on Port A) and ground.
After testing, it was determined that the device reads the temperature accurately, though as the
transceiver and microcontroller both heat up during operation, the temperature read was higher
than room temperature.
2.2 – Software
This section contains a description of the code written.
2.2.1 – LUFA
The LUFA library is what allows the host to communicate with the Smart Packet Radio via USB. The
USB to Serial demo project was used as a base to form the firmware. The purpose of this project was
to allow communications between the USB input and a serial output. The serial component of the
code was deleted as only the USB communication was required. The main functions used are:
void CDC_Device_SendByte (&VirtualSerial_CDC_Interface, const uint8_t Data)
This function sends a single byte of data to the host via USB.
void CDC_Device_ReceiveByte (&VirtualSerial_CDC_Interface, const uint8_t
Data)
This function receives a single byte of data from the host via USB.
Although these are the only functions actively used in the firmware, the remainder of the LUFA
project takes care of fundamental USB tasks and events required to make communication possible.
2.2.2 – Initialisation
When the firmware is executed, a function called SetupHardware() is called. As the name suggests,
this function initialises the hardware and makes it ready for use. There are three initialisation
functions that are called. The first is USB_Init() which is located in the LUFA library and is required to
allow the USB to function properly. The next two functions are AVR_Init() and RFM22_Init() which
initialise the microcontroller and transceiver module respectively.
AT90USB1286
SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_RISING |
SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
The SPI_Init function initialises parameters specific to the SPI required to send information and
commands to the transceiver module. The speed is set to 4MHz (the CPU speed divided by 2). The
order of information is the MSB first which is standard for SPI. The SPI clock leads on the rising edge,
and the data is sampled on the leading edge of the clock. The microcontroller is the SPI master and is
initialised as such.
DDRB |= 0xF1;
PORTB |= 0x80;
//Enable SS as an output
//Pull SS high
Sets the SPI chip select pin as an output and initialises it high as chip select is active low. This will be
used when conducting SPI reads and writes.
DDRE = 0x00;
PORTE = 0x40;
//Enable pull-up on PE6 to be used for interrupt
Sets PE6 as an input and pulls it up. This pin is connected to the interrupt pin on the transceiver
module and will be used to notify the microcontroller of certain events.
DDRC = 0x77;
//RGB LED output pins LED1(PC4-R, PC5-G, PC6-B) LED2(PC0 B) Used for USB Status
PORTC = 0x71;
//Output High
DDRE |= 0x03;
PORTE |= 0x03;
//RGB LED output pins LED2(PE0 - R, PE1 - G)
//Output high
Sets Port C and E (not include PE6) as outputs and pulls them up. These pins are used for the RGB
LEDs on the board and are active low. These LEDs have no dedicated purpose and have been used to
indicate the USB connection status as well as when an unrecognised interrupt has occurred.
DDRA = 0x00; //Port A used for input
PORTA = 0x40;
Sets Port A to be used as inputs and pulls PA6 up. Although this port can be used as an input or
output, in this case it’s set up as in input to allow the user to read the temperature when the pulled
up pin is connected to ground.
RFM22B
The function initialising the transceiver module consists of a series of SPI writes to various registers
of the module which determine how it will operate. Each register is mentioned in the code whether
it was used in the firmware or not, to allow for the user to have a general understanding of what the
registers do without having to refer to the relevant paperwork. The most important part of this
function is right at the start.
_delay_ms(50);
write(0x07, 0x81);
_delay_ms(50);
//Reset register values on RFM22B
There is a delay inserted which gives time for the transceiver module to ‘wake up’ before any
information is written. Then a command is sent to clear all of the register before any of the settings
are changed. This ensured that every desired register write is executed properly.
Although the settings on the transceiver module are fully customisable, the firmware uses the
following settings:
Function / Description
Default
Firmware
Transmission Rate
40 kbps
200 kbps
Transmission Frequency
995 MHz
434 MHz
Peak Frequency Deviation
20 KHz
26 KHz
Transmission Power
-1 dBm
2 dBm
Preamble Length
4 Bytes
2 Bytes
Modulation Type
Unmodulated carrier
Frequency Shift Keying
Mode
Direct Mode
FIFO Mode
Automatic Packet Handling
Enabled
Enabled
Before the main loop of the program is entered, the rx_mode function is called to ensure that the
default state of the device is awaiting a packet. The rx_mode function is detailed in the ‘Receiving’
section.
2.2.3 – Sending
To send a packet using the firmware provided, the first step is sending the Smart Packet Radio the
packet desired to be sent in the following format:
Figure - Packet format for microcontroller
The packet is stored in a buffer on the microcontroller and once the full packet has been received the
tx_mode function is called:
void tx_mode(void)
{
write(0x07, 0x01);
cbi(PORTC, RXANT);
sbi(PORTC, TXANT);
write(0x08, 0x03);
write(0x08, 0x00);
//To ready mode
//Clears RXANT
//Sets TXANT
// FIFO reset
// Clear FIFO
}
This function sets the antenna to be used for transmission and clears the FIFO on the transceiver.
This is done to ensure that the correct data is sent. Once this has been done, the transmit function is
called:
void transmit(unsigned char *tx_packet)
{
write(0x3A, tx_packet[0]);
write(0x3E, (tx_packet[2]+3));
for (int i=0; i<(tx_packet[2]+3); i++)
{
write(0x7F, tx_packet[i]);
//Send payload to the FIFO
}
write(0x05, 0x04);
// Enable packet sent interrupt
write(0x06, 0x00);
tx_mode_enabled = true; //Flag used to identify source of interrupt
write(0x07, 0x09);
// Start TX
}
The transmit function takes the buffer of characters sent from the host as an input. It writes the
destination address to be used as Header Byte 3 which will be checked when other radios receive the
packet and also sets the packet length. The packet is then written to the transceiver modules FIFO.
An interrupt is enabled on the transceiver which is used to notify the microcontroller when the
packet has been completely sent and a flag is set which prevents another packet from being read on
the USB input before the current pack is sent. Another flag is set and checked in the ISR to determine
what the interrupt was for. The microcontroller then sends the command for the transceiver to begin
transmission.
Once the transmission is complete, an interrupt is sent to the microcontroller. When this happens,
the ISR sets a flag high and reads the interrupt status registers located on the transceiver. The actual
response to the interrupt takes place in the main loop of code. The interrupt status registers and
relevant flags are checked and once it is determined that the interrupt was due to a valid packet
being sent the following events occur:

The transceiver is taken out of transmission mode and placed into ready mode

The TX LED is turned on and a timer is started which will turn it off after an arbitrary amount
of time.

The relevant transmission flags are cleared.

The rx_mode function is called, placing the transceiver into a state awaiting a packet.
2.2.4 – Receiving
Unless the Smart Packet Radio is sending a packet, the firmware ensures that it is in a state waiting to
receive a packet from another device. There are two functions which facilitate the reception of a
packet, the first being rx_mode:
void rx_mode(void)
{
write(0x07, 0x01);
//To ready mode
cbi(PORTC, TXANT);
sbi(PORTC, RXANT);
//Clears TXANT
//Sets RXANT
write(0x07, 0x01);
//To ready mode
write(0x08, 0x03);
write(0x08, 0x00);
//Clears FIFO
//Resets FIFO
write(0x05, 0x02);
//Enables packet received interrupt
write(0x06, 0x00);
rx_mode_enabled = true; //Flag used to identify source of interrupt
write(0x07, 0x05);
//Places RFM22B in RX mode
}
Firstly, the above function sets the antenna to be used for receiving and resets the FIFO on the
transceiver module. It then enables an interrupt that will notify the microcontroller when a valid
packet has been received and also sets a flag which will help the ISR identify which interrupt has
caused the interrupt service routine to be initiated. The microcontroller then sends the command
that places the transceiver into receive mode.
When the device receives a valid packet, and interrupt is triggered and the interrupt service routine
is initiated which sets the IRQ flag and reads the interrupt status registers. Once the microcontroller
determines that the interrupt was triggered due to a valid packet being received, the following
events occur:

The transceiver is taken out of receive mode.

The RX LED is turned on and a timer is started which will turn it off after an arbitrary amount
of time.

The receive function is called.

The received packet is sent to the host byte by byte via USB.

The rx_mode function is called and the device waits for another valid packet.
The following code is the receive function:
int receive(unsigned char *rx_buffer)
{
unsigned char i;
int receive_packet_length = read(0x4B);
for(i=0; i<receive_packet_length; i++)
{
rx_buffer[i] = read(0x7F);
}
return receive_packet_length;
}
The receive function first reads the packet length from the transceiver module and then proceeds to
read the received packet from the FIFO on board the module and returns the length of the packet
received.
2.2.5 – Miscellaneous
Apart from the interrupt generated by the transceiver module, there are three timer overflow
interrupts which are used. Two of them are used to operate the RX and TX LEDs. The LEDs are
switched on right before the timer is started. When the timer overflows an interrupt occurs, and the
interrupts service routine switches the respective LED off. The third interrupt is used for two
purposes. Firstly it toggles a blue LED intermittently as long as the firmware is running. This is used to
ensure that the microcontroller is still running. If PA7 is pulled to ground and the interrupt is
serviced, the temperature is read and sent to the host via USB in a string format.
The function idle_mode is not implemented in the firmware though was used for testing and
debugging. Although the function isn’t called, it has been left as it may be necessary for future
projects using the board. As the name suggests, the function places the transceiver module in an idle
state where it won’t send or receive any information.
The function read_all_registers isn’t used in the firmware either but is another tool which can be
used in future projects. The function simply sends the register number followed by the contents of
that register to the host via USB. It can be used to ensure the registers are set as required.
3 - User Guide
3.1 – Linux
Most of the development of the Smart Packet Radio was performed using the Windows operating
system. This was mainly due to the software available, as AVR Studio was preferable when
programming the microcontroller and since the software used has a GUI which is generally easier to
use. Once the microcontroller was setup as desired however, Linux provides a much easier method
for communicating with the device.
3.1.1 - Programming the Microcontroller
Installation of required software:
1. GCC-AVR is required to compile the code, this can be obtained by opening the terminal and
typing:
sudo apt-get install gcc-avr
2. A program called dfu-programmer is required to flash the code in .hex format onto the
microcontroller. This can be installed by opening the terminal and typing:
sudo apt-get install dfu-programmer
Compiling the code:
1. Extract the SPR Project to a directory of your choice.
2. Use your favourite text editor to edit the project as desired.
3. If any new files have been added, be sure to update the makefile included in the project.
4. Navigate to the projects directory in terminal and make the project.
Programming the microcontroller
After making the project, the .hex file should have been generated and saved to the project directory.
Now it needs to be flashed to the microcontroller, which is accomplished using dfu-programmer and
following the steps provided:
1. Hold the reset button on the Smart Packet Radio. Whilst the reset button is held down, hold
the HWB button simultaneously. Let go of the reset button, followed by the HWB. This places
the microcontroller into DFU mode and allows it to be programmed via USB.
NOTE: No fuses on the microcontroller can be changed via USB.
2. Once in DFU mode, open the terminal and type:
sudo dfu-programmer at90usb1286 erase
3. As long as the previous operation was performed successfully,
the microcontroller can now be programmed by typing:
sudo dfu-programmer at90usb1286 flash SPR.hex
4. After this has been done the device needs to be reset. This can be accomplished by pressing
the reset button or by using the dfu-programmer by typing:
sudo dfu-programmer at90usb1286 reset
3.1.3 - Using the Smart Packet Radio
After the device has been programmed and reset the operating system should recognise it as a
communications port. In order to find what port it has been assigned to, open the terminal and type:
ls /dev/ttyACM*
The following should show on the screen:
Figure - Ports listed in terminal
In the example above the port is located at “/dev/ttyACM0”. Depending on what is connected to the
computer, more than one port may be displayed. Simple testing is required to determine which one
the Smart Packet Radio is connected to. Once the port is determined it can simply be written to using
the appropriate packet format and the data will be sent. It should also receive data but will only
display it on the screen when the serial read command is used.
Example Python Script
As Python was the language intended to be used with the boards, an example script for transmitting
and a separate script for receiving have been written. In order to use the script, it is required that the
‘serial’ header file is downloaded. This can be acquired by typing:
sudo apt-get install python-serial
Once it has been downloaded, the sample code for transmission is as follows:
Note: The port must be edited depending on which port the device is connected.
#!/usr/bin/env python
import serial
import sys
import time
device=serial.Serial('/dev/ttyACM'+sys.argv[1],115200)
for i in range(500):
device.write(chr(0xff)+chr(0xaa)+chr(0x07)+'1234567')
print 'Sending packet %d'%i
The port determined in the previous step is used as an input argument when running the code. The
above code sends the 500 packets which are 10 bytes long, and returns the total time taken to send
the packets. Note that the format used is ‘Destination address’, ‘Don’t care’ (as the source address is
inserted by the firmware), ‘Payload length’, followed by the payload which is 7 bytes in length.
The sample code for receiving is as follows:
#!/usr/bin/env python
import serial
import sys
import time
device=serial.Serial('/dev/ttyACM'+sys.argv[1],115200)
device.read(20)
start=time.time()
device.read(1020)
print time.time()-start
The above code reads 1000 bytes and prints the time taken to receive the data. This was useful for
determining the practical transmission rate of the device.
This is how the Smart Packet Radio is used. Obviously the Python script can be expanded on greatly
to include packet handling and can be used to implement any desired routing algorithm
3.2 – Windows
Windows was chiefly used when developing the device. This was due to the fact that the testing
software and hardware used was more easily compatible with Windows. As expressed in the final
section though, communication with the Smart Packet Radio as a communications port is limited.
3.2.1 - Programming the Microcontroller
Installation of required software
AVR Studio is used to write and compile the code that will be flashed onto the microcontroller. It is
recommended that AVR Studio 4 is used. This can be downloaded for free though is included with
the project.
Win AVR is also required to compile the code. This can be downloaded for free.
Flip is the program that is used to flash the compiled .hex file onto the microcontroller. This can also
be downloaded for free and is included with the project.
Programming the microcontroller
After the software is downloaded and installed, the desired code can be flashed onto the device by
following these steps:
1. Open project in AVR Studio.
2. Edit the project as desired.
3. If any new files have been added, be sure to update the makefile included in the project.
4. Select “Build -> Rebuild All”.
5. The SPR.hex file should be generated and saved in the project directory.
Now that the code has been compiled successfully, it can be flashed onto the microcontroller using
Flip. After the program is open:
1. Hold the reset button on the Smart Packet Radio. Whilst the reset button is held down, hold
the HWB button simultaneously. Let go of the reset button, followed by the HWB. This places
the microcontroller into DFU mode and allows it to be programmed via USB.
NOTE: No fuses on the microcontroller can be changed via USB.
2. From the toolbar “Device -> Select” and choose AT90USB1286 from the list.
3. Select the “Load hex file” button and navigate to the .hex file generated previously.
Figure - Flip Toolbar
4. Select the “Open communications medium” button and click USB. Then click “Open”. If this
doesn’t work reset the device and repeat from step 1.
5. Click “Run” in the bottom left hand corner and once the device is programmed click “Start
Application” in the bottom right.
The software should now be loaded on to the device.
3.2.3 - Using the Smart Packet Radio
When the device is programmed and connected, Windows 7 should recognise the Smart Packet
Radio as a communications port and subsequently install the required drivers.
The program used in testing to access the communications port was “Terminal by Brady”. This can
also be downloaded for free. One of the limitations using the Smart Packet Radio with Windows is
that a script can’t be written which handles reading and writing to the communications port. As such
the only intelligence on the user end is writing the packet that wishes to be sent, and choosing a rate
of transmitting those packets (to a maximum of 100 times a second). The programs interface is as
follows:
Figure - Toolbar of Terminal Program
After the device has been programmed and reset, select “ReScan” and it should show up in the
dropdown menu to the right as one of the COM ports. The baud rate can also be chosen. The data
bits must be set to 8, with no parity and 1 stop bits. There’s also no handshaking. The other
important selection is whether you want the data to be displayed in HEX or ASCII.
Once the desired settings have been chosen, select “Connect” from the top left hand corner. If the
output is selected to be displayed in hex, any information received from another device should
automatically show up on the screen. If the temperature sensor is enabled, ASCII display should be
selected as the temperature will be printed approximately twice a second.
To send information, select “Set Macros” located at the bottom. The following screen will be
presented:
Figure - Macro Settings Menu (Terminal Program)
The information to be sent should be entered in HEX using the format $AA for a HEX value of 0xAA.
It’s important to note that spaces shouldn’t be placed between bytes, and that if using the firmware
the appropriate packet format is used (i.e. Destination address, don’t care, payload length, payload).
If the checkbox at the end of the macro is checked, that macro will be sent to the relevant port every
1000 ms. This number can be changed to a minimum of 10 ms.
3.3 – Altering the RFM22B Settings
Altering the settings used to transmit data on the transceiver module can easily be changed by
altering the contents of the registers using simple SPI writes. In the firmware code, these have been
listed in sequential order with a brief description of their function. Although specific details of their
implementation can be found in the attached information, a general overview of the registers mainly
utilised in the firmware is given below.
Not all registers and settings are used in the firmware. The main ones used are:
Interrupts
Register
Function
0x03 & 0x04
Interrupt status registers. Information in these registers can be used to determine
what the reason for a triggered interrupt was. They must also be read in order to
reset the signal on the interrupt pin.
Note: If an event occurs, the interrupt status bit will be asserted whether the
interrupt enable bit is set or not. Though the interrupt enable bit must be set for an
interrupt to physically occur.
0x05 & 0x06
Interrupt enable registers. By setting the bits in these registers, the microcontroller
will be notified when the relevant event occurs via a signal on the interrupt pin. The
only two interrupts used in the firmware are valid packet sent and valid packet
received interrupts.
Operating Function and Control
Register
Function
0x07 & 0x08
Used to control the operation of the transceiver module. In the firmware, these
registers are used to initialise the transceiver to a ready state and also to place it
into send and receive modes. They are also used to clear the send and receive FIFOs
to ensure that the correct data is read from the module.
Packet Format
Register
Function
0x30
Data access control. Is used to enable the used of the packet handler on board the
transceiver module for both sending and receiving. Also used to implement a CRC
on the packet sent. The mentioned features are all taken advantage of in the
firmware.
0x32 & 0x33
Header control. Used to set the desired length of both the sync word and header.
Also enables the use of a broadcast byte, which means if the header is set to a hex
value of 0xFF the receive header check is disregarded. This feature is implemented
in the firmware.
0x34
Used to set the preamble length. Through testing, it was determined that 2 bytes
length resulted in few erroneous valid preambles being detected though this can
obviously be alter depending on the application desired.
0x36 – 0x39
Sync word 3-0. These registers are used to set the sync word which consists of 4
bytes of data. When using the automatic packet handler offered by the transceiver
module, the sync word must be at least 1 byte in length. In the firmware only 1 byte
is used and it’s set to the default value.
0x3A – 0x3D
Transmit header 3-0. These registers are used to set the value of the header bytes
used. In the firmware, only 1 header byte is used and the destination address is
written to the relevant register in the transmit function.
0x3E
Packet length. The length of the payload is written to this register and notifies the
transceiver of how many bytes it needs to send. In the firmware, this is written
inside the transmit function.
0x3F – 0x42
Check header 3-0. The head bytes received are checked against the values held
inside these registers. In the firmware, the source address of the board is written to
check header byte 3 at start up.
Transmitting and Receiving Settings
Register
Function
0x1C – 0x25
FSK settings. These registers are used when utilizing frequency shift keying which is
implemented in the firmware.
0x6E – 0x70
Data rate settings. Used to set the transmission rate of the transceiver, is set to the
maximum of 200 kbps in the firmware.
0x75 – 0x77
RX/TX carrier frequency settings. Used to determine the carrier frequency used. Is
set to 434 MHz in the firmware.
0x71 & 0x72
Frequency deviation settings. In the firmware this is set to 26 MHz.
Note: When changing these settings, the suggested method is to open the spreadsheet “Si443xRegister-Settings” and put in the desired settings. The spreadsheet should update the relevant
register information and this can be used to program the transceiver.
4 – Applications
4.1 - A Learning Tool
The Smart Packet Radio is intended to replace the current packet radios being used in the wireless
communication labs. The Smart Packet Radio can be used to introduce students to
telecommunications, and can be used as a tool to learn and implement simple protocols to observe
how they work in practice. At a more advanced level, the device can be used as a platform to develop
and test various routing protocols. Due to its configurability, a wider variety of avenues can be
explored. These features include frequency hopping, varying transmission frequencies, different
types of modulation (or no modulation); different transmission rates and a direct mode which
bypasses the packet handler on board the transceiver (which may be desirable for certain
applications)
4.2 - Beaconless Routing Protocols
The Smart Packet Radio was initially developed to provide an opportunity to research beaconless
routing protocols. In the design specification for this project, three different beaconless routing
protocols were researched for implementation in a wireless network of Smart Packet Radios. This
section will detail each protocol, as they may still serve as a base for development in the future.
3.2 - Beacon-Less Routing (BLR)[1]
Process
1. The full data packet is sent by the initial sender.
2. Any nodes that provide progress towards the destination consider themselves appropriate as
a next hop and begin a countdown timer.
3. When the countdown is complete, the data is resent either to the next hop or destination.
4. Any node that overhears the packet being resent cancels their own timer whilst the sender
interprets this as an acknowledgement and assumes the first hop has received the packet
successfully.
If the initial sender doesn’t overhear the data packet being forwarded within the time Tmax, it will
attempt to send the packet another 5 times before discarding the data packet.
Advantages
There has been a study regarding packet length and how it affects the reliability of transmission. It
has been shown that smaller packets are more likely to be delivered than larger ones[3]. Because this
algorithm sends the full data packet straight away, this means it will choose a next hop with a stable
connection every time.
The BLR protocol uses the full data packet as its initial broadcast and also uses subsequent broadcasts
of the data packet as passive acknowledgements. This reduces the amount of control packets
required and this is a highly desirable characteristic as one of the major goals of research in this area
is to minimize the amount messages required to transfer information, both to save power and reduce
the chances of collisions.
Disadvantages
Although the use of subsequent broadcasts of the data packet as a passive acknowledgement may be
advantages in some respects, it also results in multiple neighbours forwarding the message. This
occurs when both nodes are within range of the initial sender, but not within range of each other.
The following diagram illustrates this scenario:
Although the sender has detected 2 potential next hops,
because A can’t overhear B forwarding the packet and vice
versa, a duplicate message will be produced.
3.3 - Implicit Geographic Forwarding (IGF)[2]
Process
1. A Request to Send (RTS) message is sent by initial sender.
2. Any nodes that provide progress towards the destination begin a countdown timer.
3. The timer is calculated using the same equation described previously.
4. When the countdown is complete, a Clear to Send (CTS) message is broadcast.
5. Any potential hops that overhear this CTS will cancel their own timers.
6. The node that provides the most progress should respond with a CTS frame first, when this is
received by the initial sender the data packet is sent to that particular node.
7. After the full data packet is received and acknowledgement is sent back to the initial sender.
8. The selected node then begins the process again.
If the initial sender does not receive a CTS in response to its first RTS message by time Tmax, it will
broadcast another 5 RTS frames before discarding the data packet.
After a next hop is selected via the RTS to CTS handshake and the full data packet is sent, if an
acknowledgement isn’t received by time , the node will attempt to send the data packet up to a
maximum of 3 times until it will retransmit a RTS frame, ignoring any CTS messages sent by the initial
next hop selected.
Advantages
The use of RTS and CTS control messages means that the initial sender will unicast the data packet to
the first hop. As the next hop is decided by the sender there is virtually no chance of multiple
forwarders being selected.
Disadvantages
Using control messages in the algorithm means that the number of messages sent per transfer is
increased. This is undesirable as the purpose of beacon less routing is to minimise the total number
of messages being sent to provide a more efficient communications protocol.
Generally the RTS and CTS packets being sent are relatively small. This means that although control
messages can be exchanged between the initial forwarder and a potential next hop, when the full
data packet is transmitted there’s a chance that it may not be able to traverse the link. This will result
in redundant messages being sent as well as a delay in the transfer as the initial sender will have to
begin the process all over again, selecting a different node as the first hop.
3.4 - BLR and IGF Combination (Based on BOSS protocol)[3]
Process
1. An initial packet is sent. This contains the full data message, the position of the initial sender
and the position of the destination.
2. Any node that provides progress towards the destination stores the message.
3. A timer is then started, with the time being calculated as with the previous protocols.
4. A response message containing the nodes position is broadcasted.
5. Any neighbours that overhear the broadcast cancel their own timer and delete the stored
packet.
6. When the initial sender receives the response, it broadcasts a selection frame notifying
neighbouring nodes of which will be selected to forward the message.
7. Any nodes that overhear the selection message and haven’t already cancelled their timers
will do so.
8. The selected node then forwards an initial packet as mentioned in step 1, beginning the
process again.
During the forwarding process, when the selected node forwards an initial packet the initial sender
will over hear this and interpret it as an acknowledgement. As with BLR, this reduces the number of
control messages required. The only drawback is when the packet reaches the destination. As the
destination doesn’t forward the message, the node that passed it on will assume the packet wasn’t
received. Therefore an acknowledgement needs to be sent when the message arrives at the
destination.
Advantages
This protocol aims to combine the advantages of the previously mentioned protocols. By including
the full data message in the first packet being sent, this will prevent the initial sender from choosing
a next hop that may have an unstable connection. This results in less retransmissions and a lower
end to end delay.
As with the IGF protocol, this protocol relies on control messages sent between nodes. This ensures
that the forwarding of the packet is done by a single node and prevents multiple packets arriving at
the destination.
Disadvantages
In theory this protocol should outperform both of the previously mentioned protocols; though by
combining their strengths it will also inherit minor comparative weaknesses.
Although it will produce fewer duplicates than the BLR protocol, it requires more control messages to
do so. And although it will utilise more stable links than the IGF protocol, it must also send larger
messages when transferring data from source to destination.
Algorithm
Problem
IGF
BLR
BOSS
Unreachability
High
Low
Low
Unreliability
Med
Med
Low
Duplicates
Low
High
Low
Contention
Med
Med
Low
5 – Conclusion
In conclusion, the Smart Packet Radio has been developed and tested, and is in basic working order.
It is set to transmit at the maximum data rate allowable for the modulation being used which is 200
kbps. The maximum transmission distance was found to be 300m, though for its intended purpose
this distance is not required.
Disregarding the internal settings for transmission power, the size of the antenna had a great impact
on the reliable transmission distance. Using an antenna with a length of ƛ/4 gave the greatest results,
though because multiple hops would be required over the length of the communications labs, the
antenna size was reduced to around half of that. Coupled with minimum transmission power this
reduced the reliable transmission distance to about 10 metres.
The internal packet handler is also used successfully, implementing a preamble, sync byte, header
byte and CRC. These features result in a great reliability of transmission though these features may
wish to be disabled in future applications.
The user guide written in this report was also a core component of this project. As the Smart Packet
Radio is intended to be used for future project of various natures, it’s essential that whoever uses
them has a quick and easy method of implementing the device whether on the Windows operating
system, or Linux.
Although most of the final tests were successful, an error was encountered when attempting to write
packets continuously to one board using the Python code mentioned earlier. The tests were
successful up to about 4000 packets. For an unknown reason if an amount greater than this was
selected, after a few seconds the radio would start transmitting at around one packet a second. As
most of the testing was performed using the terminal program in Windows this problem wasn’t
encountered until the end of the project and there wasn’t enough time to look into it thoroughly. It
may have something to do with the asymmetrical nature of the speed at which data is being read in
to the device compared to how quickly it is sent. As the ability to send this amount of packets one
after the other may not be necessary in the future, it can be investigated at a later time if this feature
is desired.
The direct mode offered by the transceiver which bypasses the internal packet handler was also
attempted. Unfortunately it was difficult to get working and the idea was scrapped as the FIFO mode
offered by the module seemed like a more reliable route. If the user wishes all of the packet handling
to be done at a higher level and the device to have no intelligence (i.e. only used to send and receive
information) direct mode may be desirable. The hardware is set up allows this mode to be possible
though more testing is needed to develop it properly.
The firmware has been attached as an appendix if further analysis is required though for practical
application the whole project is required for the board to operate, as parameters set by the LUFA
code is not included in the main c file.
6 – Appendices
Appendix A
Appendix B
Appendix C
Appendix D
/*
LUFA Library
Copyright (C) Dean Camera, 2011.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2011
Dean Camera (dean [at] fourwalledcubicle [dt] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Main source file for the USBtoSerial project. This file contains the
main tasks of
* the project and is responsible for the initial application hardware
configuration.
*/
#include
#include
#include
#include
#include
#include
<avr/io.h>
<avr/interrupt.h>
<stdio.h>
<stdbool.h>
<util/delay.h>
"ds18b20.h"
//===============================//
//Set bit and clear bit functions//
//===============================//
#define sbi(var, mask) ((var) |= (uint8_t)(1 << mask))
function
#define cbi(var, mask) ((var) &= (uint8_t)~(1 << mask))
function
//Set bit
//Clear bit
//=================//
//RFM22 Pin Defines//
//=================//
#define CS 0
//PB0 - Chip select pin for RFM22B
#define TXANT 1 //PC1 - Sets the antenna to be used for transmission
#define RXANT 2 //PC2 - Sets the antenna to be used for receiving
//==========//
//Prototypes//
//==========//
void AVR_Init(void);
//Initialises pins on the
microcontroller
void RFM22_Init(void);
//Initialises RFM22B transceiver
char read(uint8_t);
//SPI read function
void write(uint8_t, char);
//SPI write function
void tx_mode(void);
//Readies RFM22B for transmission
void transmit(unsigned char*);
//Writes data to FIFO on RFM22B and
sends transmit command
void rx_mode(void);
//Readies RFM22 for receiving
int receive(unsigned char*); //Reads received data from RFM22B
void idle_mode(void);
//Places RFM22B in an idle state
void read_all_registers(void);
//Reads all the registers on the RFM22B
//================//
//Global Variables//
//================//
volatile bool IRQTriggered;
IRQ has occured
uint8_t intrs = 0;
bool tx_mode_enabled;
board has just sent a packet
bool rx_mode_enabled;
board is waiting to receive a packet
unsigned char source_address = 0x0B;
char temperature_buffer[12];
unsigned char int1;
unsigned char int2;
//Flag indicating when an
//Flag used to show the
//Flag used to show the
//Source address of board
//================================================//
#include "USBtoSerial.h"
/** LUFA CDC Class driver interface configuration and state information.
This structure is
* passed to all CDC Class driver functions, so that multiple instances of
the same class
* within a device can be differentiated from one another.
*/
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
{
.Config =
{
.ControlInterfaceNumber
= 0,
.DataINEndpointNumber
.DataINEndpointSize
.DataINEndpointDoubleBank
= CDC_TX_EPNUM,
= CDC_TXRX_EPSIZE,
= false,
.DataOUTEndpointNumber
.DataOUTEndpointSize
.DataOUTEndpointDoubleBank
= CDC_RX_EPNUM,
= CDC_TXRX_EPSIZE,
= false,
.NotificationEndpointNumber
.NotificationEndpointSize
= CDC_NOTIFICATION_EPNUM,
= CDC_NOTIFICATION_EPSIZE,
.NotificationEndpointDoubleBank = false,
},
};
/** Main program entry point. This routine contains the overall program
flow, including initial
* setup of all components and the main program loop.
*/
int main(void)
{
// Local variables
unsigned char tx_buffer[255];
unsigned char rx_buffer[255];
int tx_count = 0;
int receive_packet_length;
store the length of the packet that's been received
bool transmitting = false;
//Variable used to
IRQTriggered = false;
SetupHardware();
sei();
rx_mode();
for (;;)
{
//ISR
if (IRQTriggered)
{
//Packet sent interrupt
if((int1 & (1 << 2)) && tx_mode_enabled)
{
write(0x07, 0x01);
//Set to ready mode
PORTB ^= (1 << 6);
//Toggle
TX LED
TCCR1B = 0x02;
tx_mode_enabled = false;
//Disable
tx_mode flag
rx_mode();
transmitting = false;
//Sets chip back to rx_mode
}
//Valid packet received interrupt
else if(int1 & (1 << 1) && rx_mode_enabled)
{
write(0x07, 0x01);
//Set to ready mode
PORTB ^= (1 << 5); //Toggle RX LED
TCCR3B = 0x02;
receive_packet_length = receive(rx_buffer);
//Reads received packet and places bits in rx_buffer
for(int i = 0; i < (receive_packet_length);
i++)
{
//Prints contents of rx_buffer to comms
port
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, rx_buffer[i]);
}
rx_mode();
//Sets chip back to
rx_mode
}
//Unexpected interrupt
else
{
PORTE ^= (1 << 0); //Causes RGB LED to go red
representing an unrecognised interrupt
}
// Reset flag
IRQTriggered = false;
}
if(!transmitting)
{
int16_t ReceivedByte =
CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
if (!(ReceivedByte < 0))
{
switch(tx_count)
{
//write(0x07, 0x01);
//Puts RFM22 into ready
mode
//First byte of the packet contains the destination
address
case 0:
tx_buffer[tx_count] = ReceivedByte;
tx_count += 1;
break;
//Second byte of the packet will contain the source
address provided by the board
case 1:
tx_buffer[tx_count] = source_address;
tx_count += 1;
break;
//Third byte of the packet contains the length of
the payload
case 2:
tx_buffer[tx_count] = ReceivedByte;
CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
tx_buffer[tx_count]);
tx_count += 1;
break;
//The rest of the data contained is the payload and
will be read into the tx_buffer
default:
if (tx_count < (tx_buffer[2]+2))
{
tx_buffer[tx_count] = ReceivedByte;
tx_count += 1;
}
//When the last byte of the payload is read in, the
transceiver is put into transmit mode
//and the packet is then transmitted
else
{
tx_buffer[tx_count] = ReceivedByte;
tx_count = 0;
transmitting = true;
tx_mode();
transmit(tx_buffer);
}
break;
}
}
}
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
}
}
/** Configures the board hardware and chip peripherals for the
functionality. */
void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
/* Hardware Initialization */
USB_Init();
AVR_Init();
RFM22_Init();
}
/** Event handler for the library USB Connection event. */
void EVENT_USB_Device_Connect(void)
{
cbi(PORTC, 6); //Set RGB LED1 Blue - USB Enumerating
}
/** Event handler for the library USB Disconnection event. */
void EVENT_USB_Device_Disconnect(void)
{
cbi(PORTC, 4); //Set RGB LED1 Red - USB Disconnected
}
/** Event handler for the library USB Configuration Changed event. */
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &=
CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
if (ConfigSuccess)
{
sbi(PORTC, 6);
cbi(PORTC, 5); //Set RGB LED1 Green - USB Ready
}
else
{
cbi(PORTC, 4);
//Set RGB LED1 Red - USB Error
}
}
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
}
/** Event handler for the CDC Class driver Line Encoding Changed event.
*
* \param[in] CDCInterfaceInfo Pointer to the CDC class interface
configuration structure being referenced
*/
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const
CDCInterfaceInfo)
{
}
void AVR_Init(void)
{
//Initialises SPI for communication with RFM22B module
SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST |
SPI_SCK_LEAD_RISING |
SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
//
DDRB |= 0xF1;
PORTB |= 0x80;
PORTB |= 0x10;
//Enable SS as an output
//Pull SS high
//Shut down RFM22
DDRE = 0x00;
PORTE = 0x40;
//Enable pull-up on PE6 to be used for intererr
DDRC = 0x77;
//RGB LED output pins LED1(PC4-R, PC5-G, PC6-B)
LED2(PC0 - B) Used for USB Status
PORTC = 0x71;
//Output High
DDRA = 0x00; //Port A used for input
PORTA = 0x40;
DDRE |= 0x03;
PORTE |= 0x03;
//RGB LED output pins LED2(PE0 - R, PE1 - G)
//Output high
// External Interrupt(s) initialization
// INT6 Mode: Falling Edge
//Sets pin PE6 to receive neg edge interrupt from RFM22B module
EICRA=0x00;
EICRB=0x20;
EIMSK=0x40;
EIFR=0x40;
//Enable
TCCR0B =
TCCR1B =
TCCR3B =
timers and timer overflow interrupts
0x04;
0x00;
0x00;
TIMSK0 |= _BV(TOIE0);
TIMSK1 = 0x01;
TIMSK3 = 0x01;
TCNT0 = 0;
}
// Initialize the RFM22 for transmitting
void RFM22_Init(void)
{
/*
//=======================//
//Register initialisation//
//=======================//
Address Read/Write - Function
*/
_delay_ms(50);
write(0x07, 0x81); //Reset register values on RFM22B
_delay_ms(50);
//0x00 R - Device type
//0x01 R - Device version
//0x02 R - Device status
//0x03 R - Interrupt status 1
//0x04 R - Interrupt status 2
//0x05 R/W - Interrupt Enable 1
write(0x05, 0x00);
//Disable all interrupts
//0x06 R/W - Interrupt Enable 2
write(0x06, 0x00);
// Disable all interrupts
//0x07 R/W - Operating function and control 2
write(0x07, 0x01);
// Set READY mode
//0x08 R/W - Operating function and control 2
//0x09 R/W - Crystal oscillator load capacitance
write(0x09, 0x7F);
// Cap = 12.5pF
//0x0A R/W - Microcontroller output clock
write(0x0A, 0x05);
// Clk output is 2MHz
//0x0B R/W - GPIO_0 configuration
write(0x0B, 0xF4);
// GPIO0 is for RX data output
//0x0C R/W - GPIO_1 configuration
write(0x0C, 0xEF);
// GPIO1 is TX/RX data CLK output
//0x0D R/W - GPIO_2 configuration
write(0x0D, 0x00);
//0x0E R/W - I/O port configuration
write(0x0E, 0x00);
//0x0F R/W - ADC configuration
write(0x0F, 0x70);
//0x10 R/W - ADC sensor amplifier offset
write(0x10, 0x00);
//0x11 R - ADC value
//0x12 R/W - Temperature sensor control
write(0x12, 0x00);
//0x13 R/W - Temperature offset value
write(0x13, 0x00);
//0x14 R/W - Wake-up timer period 1
//0x15 R/W - Wake-up timer period 2
//0x16 R/W - Wake-up timer period 3
//0x17 R - Wake-up timer value 1
//0x18 R - Wake-up timer value 2
//0x19 R/W - Low-duty cycle mode duration
//0x1A R/W - Low battery detector threshold
//0x1B R - Battery voltage level
//0x1C R/W - IF filter bandwidth
write(0x1C, 0x88);
//200kbps
//
write(0x1C, 0x83);
//150kbps
//
write(0x1C, 0x9A);
//100kbps
//0x1D R/W - AFC loop gearshift override
write(0x1D, 0x3C);
//200kbps & 150kbps & 100kbps
//0x1E R/W - AFC timing control
write(0x1E, 0x02);
//200kbps & 150kbps & 100kbps
//0x1F R/W - Clock recovery gearshift override
write(0x1F, 0x03);
//200kbps & 150kbps & 100kbps
//0x20 R/W - Clock recovery oversampling ratio
write(0x20, 0x3C);
//200kbps
//
write(0x20, 0x50);
//150kbps
//
write(0x20, 0x3C);
//100kbps
//0x21 R/W Clock recovery offset 2
write(0x21, 0x02);
//200kbps
//
write(0x21, 0x01);
//150kbps
//
write(0x21, 0x02);
//100kbps
//0x22 R/W - Clock recovery offset 1
write(0x22, 0x22);
//200kbps
//
write(0x22, 0x99);
//150kbps
//
write(0x22, 0x22);
//100kbps
//0x23 R/W - Clock recovery offset 0
write(0x23, 0x22);
//200kbps
//
write(0x23, 0x9A);
//150kbps
//
write(0x23, 0x22);
//100kbps
//0x24 R/W - Clock recovery timing loop gain 1
write(0x24, 0x07);
//200kbps & 150 kbps & 100kbps
//0x25 R/W - Clock recovery timing loop gain 0
write(0x25, 0xFF);
//200kbps & 150 kbps & 100kbps
//0x26 R - Received signal strength indicator
//0x27 R/W - RSSI threshold for clear channel indicator
//0x28 R - Antenna dicersity register 1
//0x29 R - Antenna dicersity register 2
//0x2A R/W - AFC limiter
write(0x2A, 0xFF);
//200kbps & 150 kbps & 100kbps
//0x2B R - AFC correction read
//0x2C R/W - OOK counter value 1
write(0x2C, 0x00);
//0x2D R/W - OOK counter value 2
write(0x2D, 0x00);
//0x2E R/W Slicer peak hold
write(0x2E, 0x00);
//0x2F - RESERVED
//0x30 R/W - Data access control
write(0x30, 0x8C);
//0x31 R - EzMAC Status
//0x32 R/W - Header control 1
write(0x32, 0x88);
//Check header byte 3 and enable broadcast
byte (0xFF)
//0x33 R/W - Header control 2
write(0x33, 0x10);
//Sets length of header to 1 byte
//0x34 R/W - Preamble length
write(0x34, 4);
// 4 nibble = 2 byte preamble
//0x35 R/W - Preamble detection control
write(0x35, 0x20);
//0x36 R/W - Sync word 3
write(0x36, 0x2D);
//0x37 R/W - Sync word 2
//0x38 R/W - Sync word 1
//0x39 R/W - Sync word 0
//0x3A R/W - Transmit header 3
//Transmit header set dynamically in
transmit function
//0x3B R/W - Transmit header 2
//0x3C R/W - Transmit header 1
//0x3D R/W - Transmit header 0
//0x3E R/W - Packet length
//Packet length is set dynamically in
transmit function
//0x3F R/W - Check header 3
write(0x3F, source_address);
//0x40 R/W - Check header 2
//0x41 R/W - Check header 1
//0x42 R/W - Check header 0
//0x43 R/W - Header enable 3
write(0x43, 0xFF);
//Check all bits
//0x44 R/W - Header enable 2
//0x45 R/W - Header enable 1
//0x46 R/W - Header enable 0
//0x47 R - Received header 3
//0x48 R - Received header 2
//0x49 R - Received header 1
//0x4A R - Received header 0
//0x4B R - Received packet length
//0x4C to 0x4E - RESERVED
//0x4F R/W - ADC8 control
//0x50 to 0x5F - RESERVED
//0x58 R/W - Changed whsen setting tx data rate
write(0x58, 0xED);
//200kbps
//
write(0x58, 0xC0);
//150kbps & 100kbps
//0x60 R/W - Channel filter coefficient address
//0x61 - RESERVED
//0x62 R/W - Crystal oscillator / Control test
//0x63 to 0x68 - RESERVED
//0x69 R/W - AGC Override 1
write(0x69, 0x60);
//200kbps & 150kbps & 100kbps
//0x6A to 0x6C - RESERVED
//0x6D R/W - TX power
write(0x6D, 0x01);
// TX power to max
//0x6E R/W - TX data rate 1
write(0x6E, 0x33); //200kbps
//
write(0x6E, 0x26);
//150kbps
//
write(0x6E, 0x19);
//100kbps
//0x6F R/W - TX data rate 0
write(0x6F, 0x33); //200kbps
//
write(0x6F, 0x66);
//150kbps
//
write(0x6F, 0x9A);
//100kbps
//0x70 R/W - Modulcation mode control 1
write(0x70, 0x0C);
// No manchester code, no data
whiting
//0x71 R/W - Modulcation mode control 2
//write(0x71, 0x02);
//Direct mode FSK
write(0x71, 0x22);
// FSK, fd[8]=0, no invert for TX/RX
data, FIFO mode
//0x72 R/W - Frequency deviation
write(0x72, 0x50); //200kbps
// Frequency deviation
setting to 45K=72*625
//0x73 R/W - Frequency offset 1
write(0x73, 0x00);
// No frequency offset
//0x74 R/W - Frequency offset 2
write(0x74, 0x00);
// No frequency offset
//0x75 R/W - Frequency band select
write(0x75, 0x53);
// frequency set to 434MHz
//0x76 R/W - Nominal carrier frequency 1
write(0x76, 0x64);
// frequency set to 434MHz
//0x77 R/W - Nominal carrier frequency 0
write(0x77, 0x00);
// frequency set to 434Mhz
//0x78 - RESERVED
//0x79 R/W - Frequency hopping channel select
write(0x79, 0x00);
// no frequency hopping
//0x7A R/W - Frequency hopping step size
write(0x7A, 0x00);
// no frequency hopping
//0x7B - RESERVED
//0x7C R/W - TX FIFO control 1
//0x7D R/W - TX FIFO control 2
//0x7E R/W - RX FIFO control
//0x7F R/W - FIFO access
cbi(PORTC, TXANT);
cbi(PORTC, RXANT);
//Clears TXANT
//Clears RXANT
}
//=============================================================//
//Function that reads all of the registers in the RFM22B module//
//=============================================================//
void read_all_registers(void)
{
unsigned char value;
unsigned char i;
for(i = 0; i<0x80; i++)
{
value = read(i);
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, i);
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, value);
}
PORTE ^= (1 << 0);
}
//=================================================================//
//Function that readies the RFM22B module for wireless transmission//
//=================================================================//
void tx_mode(void)
{
write(0x07, 0x01);
//To ready mode
cbi(PORTC, RXANT);
//Clears RXANT
sbi(PORTC, TXANT);
//Sets TXANT
write(0x08, 0x03);
write(0x08, 0x00);
// FIFO reset
// Clear FIFO
}
//=============================================//
//Function to Transmit Packet via RFM22B Module//
//=============================================//
void transmit(unsigned char *tx_packet)
{
write(0x3A, tx_packet[0]);
write(0x3E, (tx_packet[2]+3));
for (int i=0; i<(tx_packet[2]+3); i++)
{
//
CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
tx_packet[i]);
write(0x7F, tx_packet[i]);
//Send payload to the FIFO
}
write(0x05, 0x04);
// Enable packet sent interrupt
write(0x06, 0x00);
tx_mode_enabled = true; //Sets tx_mode flag
write(0x07, 0x09);
// Start TX
}
//=============================================================//
//Puts RFM22B into an Idle state, neither sending nor receiving//
//=============================================================//
void idle_mode(void)
{
write(0x07, 0x01);
//To ready mode
write(0x08, 0x03);
write(0x08, 0x00);
//Clears FIFO
//Reset FIFO
cbi(PORTC, TXANT);
cbi(PORTC, RXANT);
//Clears TXANT
//Clears RXANT
}
//===============================================//
//Function to place RFM22B module to receive mode//
//===============================================//
void rx_mode(void)
{
write(0x07, 0x01);
//To ready mode
cbi(PORTC, TXANT);
sbi(PORTC, RXANT);
//Clears TXANT
//Sets RXANT
write(0x07, 0x01);
//To ready mode
write(0x08, 0x03);
write(0x08, 0x00);
//Clears FIFO
//Resets FIFO
write(0x05, 0x02);
//Enables packet received interrupt
write(0x06, 0x00);
rx_mode_enabled = true;
write(0x07, 0x05);
//Places RFM22B in RX mode
}
//=================================================//
//Function reads data from RX FIFO on RFM22B module//
//=================================================//
int receive(unsigned char *rx_buffer)
{
unsigned char i;
int receive_packet_length = read(0x4B);
for(i=0; i<receive_packet_length; i++)
{
rx_buffer[i] = read(0x7F);
}
return receive_packet_length;
}
//==============================================//
//Reads from specified register on RFM22B module//
//==============================================//
char read(uint8_t address)
{
address &= 0x7F;
//Sets MSB to 0 for read
cbi(PORTB, CS);
//Selects RFM22B module
SPI_SendByte (address);
//Sends address to read from
char rx = SPI_ReceiveByte(); //Reads char
sbi(PORTB, CS);
//Deselects module
return rx;
}
//=================================================//
//Writes specified data to address on RFM22B module//
//=================================================//
void write(uint8_t address, char data)
{
address |= 0x80;
//Sets MSB to 1 for write
cbi(PORTB, CS);
SPI_SendByte (address);
SPI_SendByte (data);
sbi(PORTB, CS);
//Selects RFM22B module
//Sends address to write to
//Writes data to selected address
//Deselects module
}
//======================================================//
//Raises flag when interrupt received from RFM22B module//
//======================================================//
ISR(INT6_vect)
{
IRQTriggered = true;
// Read interrupt status registers
int1 = read(0x03);
int2 = read(0x04);
}
//=============================================//
//Timer overflow interrupts used to control LEDs//
//=============================================//
ISR(TIMER0_OVF_vect)
{
//Timer1 overflow used to toggle the MCU health LED
intrs++;
if (intrs >= 30)
{
PORTB ^= (1 << 7);
//
read_all_registers();
if(bit_is_clear(PINA, PA6)) {
therm_read_temperature(temperature_buffer);
for(int i = 0; i < 10; i++)
{
//Prints contents of temperature_buffer to comms
port
CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
temperature_buffer[i]);
}
}
intrs = 0;
}
}
ISR(TIMER1_OVF_vect)
{
//Timer 1 overflow used to toggle TX LED
PORTB ^= (1 << 6);
TCCR1B = 0x00;
}
ISR(TIMER3_OVF_vect)
{
//Timer 3 overflow used to toggle RX LED
PORTB ^= (1 << 5);
TCCR3B = 0x00;
}
Works Cited
Marc Heissenb•uttel, T. B. BLR: Beacon-Less Routing Algorithm for Mobile Ad-Hoc Networks.
University of Bern, Switzerland: Institute of Computer Science and Applied Mathematics.
Z.M. Hanapi, M. I. (2009). Dynamic Window Secured Implicit Geographic. World Academy of Science,
Engineering and Technology.
Juan A. Sanchez, R. M.-P. BOSS: Beacon-less On Demand Strategy for Geographic Routing inWireless.
Fac. Informatica, Univ. of Murcia: Dept. of Information and Communications Engineering.
Atmel. (2008). USBAT9082/162 Datasheet.
HopeRF Electronic. RFM22 ISM Transceiver Module Datasheet.
Download