That's good enough for me!

Saturday, January 29, 2011

Arduino and RFM22


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 http://www.sparkfun.com/products/10153 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 pinsArduino pinsNotes
GNDGND
VCC3.3v
SDOdigital 12in SPI terms, SDO is also called MISO - no voltage divider needed since 3.3v is high enough for the arduino to read HIGH
SDIdigital 11in SPI terms, SDI is also called MOSI
SCKdigital 13
NSELany other digital pin, I used 9 for one, and 10 for the other
NIRQany IRQ pin, I used digital 3
SDNGNDthis 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 can be found on github. Simply create a folder called RFM22 in your arduino libraries folder with the files in the repo, and try the following code:

#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() {
  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);
}


Hopefully in the near future I'll putting this together, along with a second assembly so two devices can be demonstrated to talk over the air. And hopefully I won't let this blog sit ignore for another two years again...

EDIT: Made a copying error in the sample code which prevented it from compiling or making sense - it should work now...

6 comments:

Jaskirat said...

I don't understand how do you have wire the TWO rfm22? I understand for one, but the other? What sdo I have to connect? The sdo of the first rfm22, or of the second? Otherwise both? Ecc...
Can you explain more clearly?

Ben said...
This comment has been removed by the author.
Ben said...
This comment has been removed by the author.
Ben said...

Great and thanks but you've lost a line from the code you posted. Add:
int i;
as line 3, ie directly after the includes.
Ben

Unknown said...

Hey I'm working on a project with RFM 22b. I've downloaded the Arduino Library, but I can't figure out how to make it work, syntax wise. Could you please email me for help? bzlister@gmail.com

OT said...

Hi
Any new update about your setting of two devices?

Thx and good job for the library.