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.