I've put together a simple RFM22 library based on the sample code at sparkfun and some google-translate assisted reading at http://www.3e-club.ru/view_full.php?id=19&name=rfm22. I've used this with the now-retired RFM22 purchased from http://www.sparkfun.com/products/9581, configured to operate at 434 MHz.
The replacement model at RFM22B-S2 SMD Wireless Transceiver - 434MHz - WRL-10153 - SparkFun Electronics should work more or less the same, but I won't know for certain until I have burned through my remaining 6 radios.
The device operates at 3.3v, as opposed to the 5v that most Arduinos seem to operate at. I used the diagram from http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206874649/1 to set up SPI to talk back and forth to the device, operating from the apparently correct assumption that if it works for one SPI 3.3v to 5v system it will work for another. I haven't done anything too serious with this, but with both radios on the same board I can tell one to listen, push data into the FIFO of the second and trigger a TX, and be told by an interrupt that the first has gotten data. Soon I'll have a second avr to run with the second radio from another board, and start playing with how much data I can push back and forth, and from what range.
A few tricks I have learned from playing with this: SDN (shutdown) must be dealt with. If you leave it unconnected and 'floating', it will intermittently work and stop working, including allowing corrupt data to flow back and forth to the main board. For several weeks I did battle with a single register on all the radios I had soldered up which would subtract one from the top 4 bits I would write in... Very frustrating.
RX_ANT, TX_ANT appear to be unnecessary, making for an easier time of soldering the thing up. Same goes for the GPIO (general purpose I/O) contacts – I am sure some projects can make excellent use of them, but thus far leaving them alone has served me well.
From the datasheet, my connections:
RFM22 pins | Arduino pins | Notes |
---|---|---|
GND | GND | |
VCC | 3.3v | |
SDO | digital 12 | in SPI terms, SDO is also called MISO - no voltage divider needed since 3.3v is high enough for the arduino to read HIGH |
SDI | digital 11 | in SPI terms, SDI is also called MOSI |
SCK | digital 13 | |
NSEL | any other digital pin, I used 9 for one, and 10 for the other | |
NIRQ | any IRQ pin, I used digital 3 | |
SDN | GND | this sets the device to stay on until power has been lost |
I'd be happy to offer the code for people to play with, but all I can say at this point is that it works for me, with two radios on the same board with no antennas. The code will be available via git in the near future.
Err... Uploads dir for new forums is apparently no writable, so try my blog(C is for Colin: Arduino and RFM22) for a repost of this comment with a pic or two, and github for the code GitHub - niloc132/arduino-rfm22: A c++ library for the arduino to talk to the HopeRF RFM22 wireless radio.
Sample sketch:
#include <SPI.h>
#include <RFM22.h>
rfm22 radio1(10); // radio 1 with NSEL on pin 10
rfm22 radio2(9); // radio 2 with NSEL on pin 9
void setup() {
Serial.begin(9600);
rfm22::initSPI();
radio1.init();
radio2.init();
}
void sendByte(uint8_t data) {
// move to ready
radio2.write(0x07, 0x01);
// reset fifo
radio2.resetFIFO();
//write data (bursted, but it is only one byte) to the FIFO reg
radio2.write(0x7F, data);
//move to TX mode to send
radio2.write(0x07, 0x09);
//wait until sent...
//move to ready
}
void readyToRecieve() {
// move to ready state
radio1.write(0x07, 0x01);
// clear existing interrupts
radio1.readAndClearInterrupts();
// set up interrupt to list to
attachInterrupt(1, radio1_int, LOW);//1 is digital pin 3
radio1.setInterrupt(RFM_INT_PKVALID, RFM_INT_PKVALID);
// clear out the fifo
radio1.resetFIFO();
// move to read mode
radio1.write(0x07, 0x05);
}
char data_recieved = 1;
void radio1_int() {
data_recieved = 1;
}
void loop() {
static int i = 0;
if (data_recieved) {
// reset the flag
data_recieved = 0;
// Print the last recieved chunk (one byte)
Serial.println(radio1.read(0x7F), DEC);
// Tell the listener to be ready
readyToRecieve();
delay(50);
}
// Send the next chunk
sendByte(i++);
delay(1000);
}
EDIT: I made copying error in the code, such that the code would not compile, and if it did, every byte written to serial read '42' instead of continually incrementing. Should be fixed now.