|
|
View previous topic :: View next topic |
Author |
Message |
dan king
Joined: 22 Sep 2003 Posts: 119
|
rfm22 transceiver module - disable usb interrupts ?? |
Posted: Thu Mar 04, 2010 4:12 pm |
|
|
Hi Folks,
Has anyone used and been able to get code to work with the RFM22 rf modules? I have been fighting this module for a few days now. I can set and readback the configuration registers using a SW SPI interface. The code I'm using is based on the example from http://www.hoperf.com for transmit and receive.
I have the receive side polling the nIRQ pin and when active, the code polls the receive FIFO for the received data. The test sends 17 bytes as a payload and for some reason every time I receive a valid packet, as indicated by the chip, I only get 17 copies of the last byte loaded into the TX FIFO. There are so many registers to set that I really don't understand it all yet and was hoping that someone might have already run through this and could shed some light.
I can post the final working code for others if I ever get it working.
Thanks,
Dan
Last edited by dan king on Fri Mar 12, 2010 12:57 pm; edited 1 time in total |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Fri Mar 05, 2010 2:22 am |
|
|
Dan,
I haven't used the RFM12 or 22 modules yet, but hope (sic) to in the future.
A few months ago, I did some googling, and there's loads of stuff on google.
try RFM12.
have a look at
http://blog.strobotics.com.au/2008/01/08/rfm12-tutorial-part1/
I haven't studied the modules in great detail, but they seem to use the silabs chips.
http://www.silabs.com
Please post code if you get it up and running.
I will happily zip all the stuff I have if you pm me with your email address.
Mike |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Fri Mar 05, 2010 7:33 am |
|
|
Hi Mike,
I reviewed the silabs docs since the rfm22 uses the si4431 transceiver chip but they really don't have much in the way of an app note with register settings, at least that I could find.
I've also been to the tutorial link but it's incomplete, doesn't go past section 2.
The amount of detail on google for the rfm22 is pretty sparse, the rfm12 has more but I'm pretty sure they are different enough to not be applicable.
I haven't made much progress with my code at getting past the fifo containing 17 copies of the last byte tx'd. I wish I could read back what was loaded into the tx fifo to check the integrity of the data but a read to the fifo pulls data from the rx fifo. I'm really at an impass now because I can't determine what is actually being transmitted.
I'll pm my email address, thanks for anything you might have.
Rgds,
Dan |
|
|
xberger
Joined: 11 Mar 2010 Posts: 2
|
|
Posted: Thu Mar 11, 2010 6:21 am |
|
|
Hello Dan,
RFM22 (+20dBm) module is based on Si4432 chip from Silicon Labs.
But demo code of HopeRF should work for both.
I used the transmit and receive demo code on MSP430.
It's work fine. I receive the same payload than I transmit.
But since I used it, HopeRF modified their demo code.
see the news from HopeRF : http://www.hoperf.com/news/32.htm
I didn't test this new code.
As define in the code, the payload should be :
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x38
0x39
0x3a
0x3b
0x3c
0x3d
0x3e
0x3f
0x78
In your case, you receive 17 copies of the last byte tx'd.
That's mean, 17 times 0x78 ?
Best regards |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Thu Mar 11, 2010 7:25 am |
|
|
I'm getting better results than when I posted before. I am sometimes receiving the complete payload but something with my setup is flakey. I get varying levels of success and I can't determine what is causing the inconsistency. I added code to check for TX timeouts where the fifo gets loaded and then the code waits for nIRQ incdicating a successful TX. This sometimes gets lost and when I re-init the registers the issue isn't resolved. If I reset the entire system is sometimes recovers.
As far as the RX side, I do occasionally get valid packets received showing the 17 bytes but I also seem to get an odd extra reception at the end and my code reads the rx fifo 17 times and prints the result to show the same value. I'm not sure where that is coming from but I'm assuming that 17 bytes are being sent for the mystery data because I believe the nIRQ doesn't change state until a full packet(17 bytes) is received, is that correct based on the register settings in the demo code?
I wish I could read the tx fifo after I load it but the datasheet indicates that when I read the fifo I'm actually getting what is in the rx fifo. UGH.
Anyhow, i'll stop my rambling and keep trying. When I have something that is stable and repeatable I'll post for others to reference.
OH - BTW the datasheet schematic doesn't show the connection for the SDN pin, a big time gotcha since if that pin isn't tied to GND the transceiver does nothing. The example code does show that and saved me
Rgds,
Dan |
|
|
xberger
Joined: 11 Mar 2010 Posts: 2
|
|
Posted: Fri Mar 12, 2010 5:07 am |
|
|
Hello Dan,
In the case of HopeRF's configuration, nIRQ goes low only if a valid packet in received.
It's sure because there is a CRC in the packet (encrc = '1' in Register 30h : Data Access Control.
On the receiver side, if you read the RX FIFO after nIRQ goes low you must read the right payload.
HopeRF add a 8-bit checksum in the payload but it's not necessary.
Best regards |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Fri Mar 12, 2010 7:15 am |
|
|
Yah, I know about the CRC. That's why I would like to see what is in the TX FIFO because when I finally do get a correct TX, it's always followed by another packet that is the same value for all 17 bytes. Very confusing because I'm only sending the example packet.
I am also have serious stability issues. Both my send and receive platforms are going into strange modes that require toggling the SDN pin to recover. Resending the init register values doesn't restore it because I believe the onboard micro has latched or something. Reading register 0x00 should always return the same device type but starts sending random data when read in the "unknown" mode.
After I toggle SDN the registers return expected value. I am looking into the power supply further but I don't expect to find any surprises there since I have decoupling caps everywhere and some stiff electrolytics on both sides of the 3.3 V regulator.
Anyhow, thanks for the input. I'll report more back later.
Dan |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Fri Mar 12, 2010 10:03 am |
|
|
Ok, I think I've found part of the problem with my setup. I have been using PIC18F2455 USB parts and run the CDC configuration to allow terminal access to each part. It appears that the USB influence, whether rf or in pic code, is to blame. I modified my code to allow a pushbutton to initiate TX as well as through usb terminal commands and what I found is that the TX works almost 100% of the time when the transmit side runs off of batteries. When connected to usb neither the pushbutton or the terminal command for TX works even close to reasonable. The RX side works just fine when connected to USB though so I'm not sure if the usb code is causing problems or if it's rf related but I tend to think the usb code is the problem since the rf transceiver gets latched fairly often.
My main code is shown below to demostrate what I have set up.
Code: | while(1){
usb_task();
if (!button){
testled = !testled;
to_tx_mode();
delay_ms(100);
}
if (usb_cdc_kbhit()) { //if incoming USB commands, service them
c=usb_cdc_getc();
switch (c){
case 'h': usb_cdc_putc("TX help usb link\n\r");
usb_cdc_putc("t to transmit packet\n\r");
usb_cdc_putc("i to init the transceiver\n\r");
usb_cdc_putc("r to read back a register\n\r");
break;
case 'g': usb_cdc_putc("input an 8 bit number\n\r");
temp = get_usb_num();
printf(usb_cdc_putc,"\r\ntest %u\r\n",temp);
break;
case 'i': usb_cdc_putc("initializing\n\r");
shutdown = 1;
delay_ms(100);
shutdown = 0;
delay_ms(1000);
rf22_init_parameter();
idle;
usb_cdc_putc("done\n\r");
break;
case 't': testled = !testled;
to_tx_mode();
delay_ms(100);
usb_cdc_putc("sent\n\r");
break;
case 'r': usb_cdc_putc("input an 8 bit hex address to read\n\r");
nib_h = get_usb_nibble();
nib_h = nib_h <<4;
nib_l = get_usb_nibble();
nib_h = nib_h|nib_l;
temp=spi_read_rfm(nib_h);
printf(usb_cdc_putc,"\r\naddress 0x%x= %x\r\n",nib_h,temp);
break;
case 'w': usb_cdc_putc("input an 8 bit hex address to write to\n\r");
nib_h = get_usb_nibble();
nib_h = nib_h <<4;
nib_l = get_usb_nibble();
nib_h = nib_h|nib_l;
printf(usb_cdc_putc,"\r\ninput an 8 bit hex value to write to address 0x%x\n\r",nib_h);
val_h = get_usb_nibble();
val_h = val_h <<4;
val_l = get_usb_nibble();
val_h = val_h|val_l;
spi_write_rfm(nib_h,val_h);
usb_cdc_putc("\r\nwritten\n\r");
break;
default: ;
}
}
} //close while 1
} //close mai
|
is there a way to disable usb interrupts during certain routines?
btw - compiler version CCS PCH C Compiler, Version 4.074
Thanks,
Dan |
|
|
danr
Joined: 14 Sep 2010 Posts: 4
|
RFM22B Multiple copies of last byte |
Posted: Tue Sep 14, 2010 6:18 am |
|
|
Hi Dan,
I have just produced some code using an RFM22 module and a PIC16f687 to control it. Everything is fine except the use of the FIFO and what happens to the payoad - it sounds exactly like your original post where whatever the last byte shifted into the FIFO at the TX end is gets read out at the receiver end the same number of times as the packet payload length.
How did you finally solve this problem - I have no USB interractions to consider, it is pure SPI from the PIC.
Many thanks. |
|
|
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Tue Sep 14, 2010 10:00 am |
|
|
Sorry to say, that was as far as I got since I didn't have a project in mind I only wanted to get started with the modules.
I found that if I initiated a TX with a pushbutton instead of through terminal access(via USB) the module would work pretty well. I figured that once I had a project that I could narrow down the other issues.
I know that doesn't help but good luck. |
|
|
danr
Joined: 14 Sep 2010 Posts: 4
|
RFM22B Multiple copies of last byte |
Posted: Wed Sep 15, 2010 4:33 am |
|
|
Looks resolved now - the RFM22b datasheet from Hope doesn't say (or I didn't notice) that the clear RX/TX FIFO is a double write - set '1' and then set '0'. It appears in an application note from SI. Once implimented the modules perform as expected. |
|
|
dap20
Joined: 11 Aug 2011 Posts: 5
|
Re: RFM22B Multiple copies of last byte |
Posted: Thu Aug 11, 2011 5:01 pm |
|
|
Hi, I have tried to make work the rfm22b, but with no positive results, please could you show me your source code. |
|
|
danr
Joined: 14 Sep 2010 Posts: 4
|
|
Posted: Sun Aug 14, 2011 2:44 am |
|
|
I initalise the module like this:
Code: |
void init_radio(char pause)
{
char freq_reg_76;
char freq_reg_77;
switch (master_station) //first decide the frequency based on master station number - 6 stations allowed for here
{
case 1: //433.1MHz
freq_reg_76 = 0x4d;
freq_reg_77 = 0x80;
break;
case 2: //433.4MHz
freq_reg_76 = 0x55;
freq_reg_77 = 0x00;
break;
case 3: //433.7MHz
freq_reg_76 = 0x5c;
freq_reg_77 = 0x80;
break;
case 4: //434.1MHz
freq_reg_76 = 0x66;
freq_reg_77 = 0x80;
break;
case 5: //434.4MHz
freq_reg_76 = 0x6e;
freq_reg_77 = 0x00;
break;
case 6: //434.7MHz
freq_reg_76 = 0x75;
freq_reg_77 = 0x80;
break;
}
if(pause)
{
rf_sdn = 1; //shut down the RF module
delay_ms(50);
rf_sdn = 0; //start up the RF module
delay_ms(50);
}
send_rf_spi(interrupt_enable_reg_1, 0x00);//5 00 //interrupt enable reg1 - none used at the moment
send_rf_spi(interrupt_enable_reg_2, 0x00);//6 03 //interrupt enable reg2 - none used at the moment
get_rf_spi(interrupt_status_1); //read out interrupt register 1
get_rf_spi(interrupt_status_2); //read out interrupt register 2
send_rf_spi(operating_and_func_control_1, idle_standby);//7 01 //start out in standby mode
send_rf_spi(operating_and_func_control_2, 0b00000001);//8 00
send_rf_spi(operating_and_func_control_2, 0b00000000);//8 00
send_rf_spi(operating_and_func_control_2, 0b00000010);//8 00
send_rf_spi(operating_and_func_control_2, 0b00000000);//8 00
send_rf_spi(if_filter_bandwidth, 0x15);//1C
send_rf_spi(afc_loop_gearshift_override, 0x40);//1D
send_rf_spi(afc_timing_control, 0x0A);//1E 0A
send_rf_spi(clock_recovery_gearshift_override, 0x00);//1F 03 should be 00
send_rf_spi(clock_recovery_oversampling_ratio, 0xC8);//20
send_rf_spi(clock_recovery_offset_2, 0x00);//21
send_rf_spi(clock_recovery_offset_1, 0x51);//22
send_rf_spi(clock_recovery_offset_0, 0xEC);//23
send_rf_spi(clock_recovery_timing_loop_gain_1, 0x10);//24 should be 10
send_rf_spi(clock_recovery_timing_loop_gain_0, 0xA6);//25
send_rf_spi(afc_limiter, 0x29);//2A
send_rf_spi(data_access_control, 0x8D);//30 8D //TX and RX packet handling on, CRC whole packet, CRC-16 polynomial
send_rf_spi(header_control_1, 0x0C);//32 0C
send_rf_spi(header_control_2, 0x22);//33 22
send_rf_spi(preamble_length, 0x20);//34 //use 4 bytes (8 nibbles) of transmitted preamble
send_rf_spi(preamble_detection_control, 0x52);//35 22 //use 4 nibbles <7:3> for preamble detection threshold
send_rf_spi(sync_word_3, 0x2D);//36 2D //only using 2 sync words so leaving 1 and 0 unconfigured
send_rf_spi(sync_word_2, 0xD4);//37 D4
send_rf_spi(sync_word_1, 0x00);//38 00
send_rf_spi(sync_word_0, 0x00);//39 00
send_rf_spi(transmit_header_3, master_station);//3A 00 //this is the address put into the packet header for tx
send_rf_spi(transmit_header_2, 0x02);//3B 00
send_rf_spi(transmit_header_1, 0x03);//3C 00
send_rf_spi(transmit_header_0, 0x04);//3D 00
send_rf_spi(transmit_packet_length, payload_length);//3E 00 //payload length in bytes
send_rf_spi(check_header_3, node);//3F 00 //this is the 'local' address the packet header is checked against
send_rf_spi(check_header_2, 0x02);//40 00
send_rf_spi(check_header_1, 0x03);//41 00
send_rf_spi(check_header_0, 0x04);//42 00
send_rf_spi(header_enable_3, 0xFF);//43 FF
send_rf_spi(header_enable_2, 0xFF);//44 FF
send_rf_spi(header_enable_1, 0xFF);//45 FF
send_rf_spi(header_enable_0, 0xFF);//46 FF
send_rf_spi(reserved_0x58, 0x80);//58 -
send_rf_spi(agc_override_1, 0x60);//69 20 60 //reserved, 0, agcen, lnagain, 0, 0, 0, 0
char cur_reg_setting = get_rf_spi(tx_power); //get the existing register value
cur_reg_setting &= 0b11111000; //mask out the existing power setting, leave the other bits unchanged
cur_reg_setting += initial_power;//_14dbm; //add in the initial tx power setting
send_rf_spi(tx_power, cur_reg_setting);//6D 18 //put the new power setting back into the module
send_rf_spi(tx_data_rate_1, 0x28);//6E was 0x05 //data rate set for 5kbps
send_rf_spi(tx_data_rate_0, 0xF6);//6F was 0x1F //data rate set for 5kbps
send_rf_spi(modulation_mode_control_1, 0x2E);//70 //txdtrtscale = 0 <5>, en PH, ?, en maninv, enmanch, no whitening
send_rf_spi(modulation_mode_control_2, 0x23);//71
send_rf_spi(freq_deviation, 0x20);//72 //this is 20kHz deviation
send_rf_spi(freq_band_select, 0x53);//75 75
send_rf_spi(nominal_carrier_freq_1, freq_reg_76);//76 BB
send_rf_spi(nominal_carrier_freq_0, freq_reg_77);//77 80
}
|
I switch to rx mode like this:
Code: |
void rf_to_rx()
{
tx_ant = 0; //disconnect the tx antenna
rx_ant = 1; //connect the rx antenna
send_rf_spi(interrupt_enable_reg_1, 0x02); //enable the valid packet interrupt
send_rf_spi(interrupt_enable_reg_2, 0x00); //no other interrupts needed
get_rf_spi(interrupt_status_1); //read out interrupt register 1
get_rf_spi(interrupt_status_2); //read out interrupt register 2
send_rf_spi(operating_and_func_control_2, 0b00000010); //clear the RX FIFO
send_rf_spi(operating_and_func_control_2, 0b00000000); //clearing is a double write
delay_100us(1); //pause in idle before RX
send_rf_spi(operating_and_func_control_1, rx_state); //switch to the rx state
return;
}
|
and I switch to the tx state like this:
Code: |
void rf_to_tx(char* data, char length)
{
delay_100us(3);
send_rf_spi(operating_and_func_control_2, 0b00000001); //clear the TX FIFO
send_rf_spi(operating_and_func_control_2, 0b00000000); //clearing is a double write function
send_rf_spi(transmit_packet_length, length); //update the packet length register
burst_write_rf_spi(fifo, data, length); //burst write the payload to the TX FIFO
send_rf_spi(interrupt_enable_reg_1, 0x04); //enable the packet sent interrupt
send_rf_spi(interrupt_enable_reg_2, 0x00); //no other interrupts needed
get_rf_spi(interrupt_status_1); //read out interrupt register 1
get_rf_spi(interrupt_status_2); //read out interrupt register 2
send_rf_spi(operating_and_func_control_1, tx_state); //switch to the tx state
char time_out_on_tx = 50; //time out in ms
set_bit(intcon, GIE);
packet_status = 0; //clear the status of incoming/outgoing packets
while((packet_status == 0) && (time_out_on_tx > 0)) //wait here until the packet sent interrupt comes in
{
delay_ms(1);
time_out_on_tx--;
if(time_out_on_tx == 0) //if there seems to be a problem with confirmation of TX then re-init the radio
{
init_radio(); //re - init the RF board
}
}
clear_bit(intcon, GIE); //disallow interrupts
get_rf_spi(interrupt_status_1);
get_rf_spi(interrupt_status_2);
return;
}
|
This has some timeout stuff in there that could be omitted if you're not too worried about making sure it tx'd OK.
SPI send to the module looks like this:
Code: |
char send_rf_spi(char address, char data)
{
//address bit 7 is R/W - read is 0 write is 1
char int_state = intcon;
clear_bit (intcon, GIE);
config_spi(spi_rfm);
address.7 = 1;
delay_us(1);
rf_cs = 0; //rf chip select is active low - assert here
delay_us(1); //min delay required is 400nS
clear_bit(sspcon, WCOL); //ensure the collision detect flag s reset before we start
sspbuf = address; //first clock out the register address to write to
while (!(sspstat & 1<<BF)); //wait to be finished
sspbuf = data; //next clock data from the master
while (!(sspstat & 1<<BF)); //wait to be finished
delay_us(1); //min delay required is 400nS
rf_cs = 1; //release the chip select
intcon = int_state;
return 1; //success
}
|
Get from RF module looks like this:
Code: |
char get_rf_spi(char address)
{
//address bit 7 is R/W - read is 0 write is 1
char int_state = intcon;
clear_bit (intcon, GIE);
config_spi(spi_rfm);
delay_us(1);
rf_cs = 0; //rf chip select is active low - assert here
delay_us(1); //min delay required is 400nS
address.7 = 0;
clear_bit(sspcon, WCOL); //ensure the collision detect flag s reset before we start
sspbuf = address; //first clock out the register address to read from
while (!(sspstat & 1<<BF)); //wait to be finished
sspbuf = 0; //next clock dummy data from the master to read slave
while (!(sspstat & 1<<BF)); //wait to be finished
delay_us(1); //min delay required is 400nS
rf_cs = 1; //release the chip select
intcon = int_state;
return sspbuf; //this will now contain the data clocked out of the slave
}
|
And finally, burst write:
Code: |
void burst_write_rf_spi(char address, char length)
{
char int_state = intcon;
clear_bit (intcon, GIE);
config_spi(spi_rfm);
address.7 = 1;
delay_us(1);
rf_cs = 0; //rf chip select is active low - assert here
delay_us(1); //min delay required is 400nS
clear_bit(sspcon, WCOL); //ensure the collision detect flag is reset before we start
sspbuf = address; //first clock out the register address to write to
while (!(sspstat & 1<<BF)); //wait to be finished
for (char i=0; i<length; i++)
{
sspbuf = tx_data[i]; //next clock data from the master
while (!(sspstat & 1<<BF)); //wait to be finished
}
delay_us(1); //min delay required is 400nS
rf_cs = 1;
intcon = int_state;
} |
|
|
|
danr
Joined: 14 Sep 2010 Posts: 4
|
|
Posted: Sun Aug 14, 2011 8:32 am |
|
|
The comments are not up to date, so don't pay to much attention to them! |
|
|
crocu
Joined: 02 Nov 2009 Posts: 5
|
|
Posted: Sat Sep 29, 2012 5:19 pm |
|
|
Hello danr,
Would you please share you entire code with *.c and *.h files ?
I'm trying to use your code with a PIC 18F2620 but RFM22 registers defines are stated in your code and it is difficult to see how your code works.
I will appreciate if you could post the all project archive here, it will help me a lot.
Many thanks, |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|