Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Reduce range of a RFM70 2.4GHz transceiver

Status
Not open for further replies.

Futterama

Member
Hi forum,

I have purchased some RFM70 modules: **broken link removed**

I want to built a lap counter system for RC cars, and since these modules are very cheap, I thought they might be usable.

But according to the link above, the modules have a range of 70-80m in "open area". I would need the modules to have a range of around 10 meters. I don't know if I can reduce the range just by adjusting the output power (it has programmable output power -40dBm to 5dBm) or maybe I need to modify the antenna if possible?

Another thing that concerns me, is that most RC radios also operate in the 2.4GHz band. As far as I have understood, the RC radios will detect which channels are available when turning the radio on. If my lap counter only have a range of 10m, the RC radio might not detect that the channel is in use by my lap counter, and the radio might transmit on that channel and then the lap counter probably wont work.

Comments and ideas are very welcome. Thanks.
 
I have just read some stuff about RC radios and they use DSSS or FHSS modulation and my modules use FSK/GFSK modulation, so I guess this means that the RC radios wont have direct influence on my modules unless they totally jam the signal because the radio transmitter is way more powerful than the lap counter transmitter...
 
Last edited:
Presumably the quoted 70-80m range (which may well be an optimistic figure anyway) is with max output power? If so, then the range can certainly be reduced by reducing the power. You have the units; why not just try them? IMHO conflict of radio channels is likely if your purchased radios don't have a channel-detect feature.
 
Hi Alec,

I will try them soon when I get the time (I have like a million other projects too) but I just thought I would ask here before I use a lot of time getting the thing to work, if someone here can already tell me that it is not going to work.
 
In answer to your email question the 5-byte data stored in RX_ADDR_P0 is 0xE7E7E7E7E7 is the pipe-0 receiver address stored in Bank-0 Register-0x0A. It is the same as the TX_ADDR in register 0x10. If you want to check your SPI comms you can read the 5-bytes at 0x0A and 0x10 to double check the data in the DS. Pipe-1 has 0xC2C2C2C2C2 but I am not sure how to setup the TX_ADDR for pipe-1 or whether you have to change register 0x10 to suit. I am sticking to the defaults for now until I find out that it all works :)

I finally got register 0x17 (FIFO_STATUS) bit-4 to change state after loading the W_TX_PAYLOAD with 5-bytes of data but it didn't send the data and after a few cycles the bit-4 changed back again :(
 
Hi Graham,

I received your email regarding the RX_ADDR_P0 this morning. And my reply also bounced back.

You can try an alternate address, I'll send it to you by PM.
 
Hi Graham,

Is there an error in the code supplied from Hope RF or in the datasheet?

In Bank1, we need to write 4 bytes with predefined values to address 0x04. In the datasheet it says 0xD99E860B, but in the code it is 0xF99E860B (F9 and not D9 as in the datasheet).

What to do?

I tried to contact Hope RF yesterday through their website, no response yet.
 
Last edited:
RFM70 - Bank-1

I think that the email I sent you from Bai Guang of Hope RF said "leave as is", but I am not sure of this any more, does he mean "don't mess with values" or don't initialise? Why did Hope RF not pre-program these registers as per bank-0?

If you check register 0x0E the contents is already 0xFF FF FE F7 CF 20 81 04 08 20 41 (remember this is read out backwards in your SPI loop).

Another source I found also gives the same, i.e. 0xF9:

const unsigned long Bank1_Reg0_13[]={
0xE2014B40, // 0x00
0x00004BC0, // 0x01
0x028CFCD0, // 0x02
0x41390099, // 0x03
0x0B869EF9, // 0x04
0xA67F0624, // 0x05
0x00000000, // 0x06
0x00000000, // 0x07
0x00000000, // 0x08
0x00000000, // 0x09
0x00000000, // 0x0A
0x00000000, // 0x0B
0x00127300, // 0x0C
0x36B48000, // 0x0D
};

I also did not get an answer from a Hope RF website enquiry :(
 
Bank1 is very tricky, some of the registers are read forward, others backwards.

Bai Guang writes: "BANK-1 register is setting the parameter of Analog part in the module. If not setting,the register is default value.That is OK" - seems like it is OK to leave them default?

In the code supplied by Hope RF, the value in the const array is "0x0B869Ef9", the last byte f9 is D9 in the datasheet. All other bytes in the code are written in uppercase, and this is written in lowercase, it seems like a quick correction in the code, maybe they forgot to change it in the datasheet?

My computer crashed yesterday and decided to write all nulls in my .c file, i recovered some of the code from the .lst file but all last nights work is gone *DAMN*, I need to do backup every hour :)
 
Ok, I have more information to back up my theory regarding Bank1 register 0x04.

In the code downloaded from the website, you have a comment to Bank1_Reg0_13[]:

const unsigned long Bank1_Reg0_13[]={ //latest config txt

The RFM70_init.c file has a modified date of 5. August 2010.
The other source files have a date of 15. July 2010.
The RFM70.pdf file has a created date in document properties of 19. July 2010.

So the source files was written a few days before the datasheet. Two weeks later, the source file RFM70_init.c is changed, the change might just be the update of the Bank1_Reg0_13 array and then the comment was added (//latest config txt).

So I think they forgot to change the value in the datasheet.
 
Last edited:
Bank-1 is indeed a a ******* as, as you say, you can ONLY write to it :(. I am not even sure whether you can read the device ID, only the ramp.

I cannot get the TX routine to work. What routines are you using? The "Hope" variety (good name for the I think) or your own code?
 
Hi Graham,

I tried, and you can read the RAMP (0x0E) register, 0x07 (RBANK) register and 0x08 (Chip ID) register in Bank1.

I actually just managed to send a byte from one RFM70 to the other! I took some Hope RF code as inspiration and wrote my own code in CCS for it.

I just use Pipe 0 only, and uses the Reset value addresses for the TX and RX.

Init RFM70 for TX:

void Init_RFM70()
{
int8 Temp;

SwitchToBank(0); // Not needed, Bank should be 0 after reset

SPI_Write_Reg(CONFIG, 0b00001110); // Enable CRC - 2 bytes CRC - POWER UP - PTX
SPI_Write_Reg(EN_AA, 0b00000000); // Disable Auto Acknowledge
SPI_Write_Reg(EN_RXADDR, 0b00000001); // Enable data pipe 0
SPI_Write_Reg(SETUP_AW, 0b00000011); // 5 bytes address
SPI_Write_Reg(SETUP_RETR, 0b00000000); // Re-Transmit disabled
SPI_Write_Reg(RF_CH, 23); // Set the frequency channel to 23

Temp = SPI_Read_Reg(RF_SETUP); // Read existing values in register
Temp = Temp & 0b11110111; // Air Data Rate 1Mbps
SPI_Write_Reg(RF_SETUP, Temp); // Write value to register

SPI_Write_Cmd(ACTIVATE, 0x73); // Activate registers: R_RX_PL_WID - W_ACK_PAYLOAD - W_TX_PAYLOAD_NOACK

SwitchToBank(1);

// Write predefined value 0x404B01E2 to register 0x00
CSN = 0; // Start SPI communication
SPI_RW(0x00|W_REGISTER); // Select register 0x00 and indicate a write operation
SPI_RW(0x40); // Write 1 byte
SPI_RW(0x4B); // Write 1 byte
SPI_RW(0x01); // Write 1 byte
SPI_RW(0xE2); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0xC04B0000 to register 0x01
CSN = 0; // Start SPI communication
SPI_RW(0x01|W_REGISTER); // Select register 0x01 and indicate a write operation
SPI_RW(0xC0); // Write 1 byte
SPI_RW(0x4B); // Write 1 byte
SPI_RW(0x00); // Write 1 byte
SPI_RW(0x00); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0xD0FC8C02 to register 0x02
CSN = 0; // Start SPI communication
SPI_RW(0x02|W_REGISTER); // Select register 0x02 and indicate a write operation
SPI_RW(0xD0); // Write 1 byte
SPI_RW(0xFC); // Write 1 byte
SPI_RW(0x8C); // Write 1 byte
SPI_RW(0x02); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0x99003941 to register 0x03
CSN = 0; // Start SPI communication
SPI_RW(0x03|W_REGISTER); // Select register 0x03 and indicate a write operation
SPI_RW(0x99); // Write 1 byte
SPI_RW(0x00); // Write 1 byte
SPI_RW(0x39); // Write 1 byte
SPI_RW(0x41); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0xD99E860B to register 0x04
CSN = 0; // Start SPI communication
SPI_RW(0x04|W_REGISTER); // Select register 0x04 and indicate a write operation
SPI_RW(0xF9); // Write 1 byte
SPI_RW(0x9E); // Write 1 byte
SPI_RW(0x86); // Write 1 byte
SPI_RW(0x0B); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0x24067FA6 to register 0x05
CSN = 0; // Start SPI communication
SPI_RW(0x05|W_REGISTER); // Select register 0x05 and indicate a write operation
SPI_RW(0x24); // Write 1 byte
SPI_RW(0x06); // Write 1 byte
SPI_RW(0x7F); // Write 1 byte
SPI_RW(0xA6); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0x00731200 to register 0x0C (in reversed order!)
CSN = 0; // Start SPI communication
SPI_RW(0x0C|W_REGISTER); // Select register 0x0C and indicate a write operation
SPI_RW(0x00); // Write 1 byte
SPI_RW(0x12); // Write 1 byte
SPI_RW(0x73); // Write 1 byte
SPI_RW(0x00); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

// Write predefined value 0x0080B436 to register 0x0D (in reversed order!)
CSN = 0; // Start SPI communication
SPI_RW(0x0D|W_REGISTER); // Select register 0x0D and indicate a write operation
SPI_RW(0x36); // Write 1 byte
SPI_RW(0xB4); // Write 1 byte
SPI_RW(0x80); // Write 1 byte
SPI_RW(0x00); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)

/* Data is already written to RFM70
// Write predefined value 0x404B01E2 to register 0x00 (in reversed order!)
CSN = 0; // Start SPI communication
SPI_RW(0x0E|W_REGISTER); // Select register 0x0E and indicate a write operation
SPI_RW(0x41); // Write 1 byte
SPI_RW(0x20); // Write 1 byte
SPI_RW(0x08); // Write 1 byte
SPI_RW(0x04); // Write 1 byte
SPI_RW(0x81); // Write 1 byte
SPI_RW(0x20); // Write 1 byte
SPI_RW(0xCF); // Write 1 byte
SPI_RW(0xF7); // Write 1 byte
SPI_RW(0xFE); // Write 1 byte
SPI_RW(0xFF); // Write 1 byte
SPI_RW(0xFF); // Write 1 byte
CSN = 1; // Set CSN high (end SPI communication)
*/
}

Transmit data:

// Put payload in the TX FIFO
CSN = 0; // Start SPI communication
SPI_RW(W_TX_PAYLOAD); // Write command
SPI_RW(0x31); // Write some random data to the FIFO for transmission
CSN = 1; // Set CSN high (end SPI communication)

// High pulse om CE to transmit packet
CE = 1;
delay_ms(1); // More than 10µs
CE = 0;

After the CE pulse, the RFM70 will transmit the data and set bit TX_DS, and also set the IRQ pin low if MASK_TX_DS = 0.

Functions used:

/**************************************************/
// Took this function from the Hope code
int8 SPI_RW(int8 value)
{
int8 bit_ctr;
for(bit_ctr=0; bit_ctr<8; bit_ctr++) // output 8-bit
{
if(value & 0x80)
{
MOSI=1;
}
else
{
MOSI=0;
}
value = (value << 1); // shift next bit into MSB..
SCK = 1; // Set SCK high..
value |= MISO; // capture current MISO bit
SCK = 0; // ..then set SCK low again
}
return(value); // return read UINT8
}


/**************************************************/
// Write a command + data
void SPI_Write_Cmd(int8 command, int8 value)
{
CSN = 0; // Start SPI communication
SPI_RW(command); // Write command
SPI_RW(value); // Write command data
CSN = 1; // Set CSN high (end SPI communication)
}


/**************************************************/
// Write 1 byte to a register
void SPI_Write_Reg(int8 reg, int8 value)
{
CSN = 0; // Start SPI communication
SPI_RW(reg|0x20); // Select register to write to and indicate a write operation
SPI_RW(value); // Write value to register
CSN = 1; // Set CSN high (end SPI communication)
}


/**************************************************/
// Read a register
int8 SPI_Read_Reg(int8 reg)
{
int8 value;
CSN = 0; // Start SPI communication
SPI_RW(reg); // Select register to read from
value = SPI_RW(0); // Read register value
CSN = 1; // Set CSN high (end SPI communication)
return(value); // Return register value
}


/**************************************************/
// Switch to a bank, inspired by the Hope code
void SwitchToBank(int1 bank)
{
int8 BankStatus;

BankStatus = SPI_Read_Status(); // Read STATUS register
BankStatus = BankStatus & RBANK; // Extract the RBANK bit

// Check if the RBANK bit is indicating a different bank than the wanted
if(((bank == 0) && (BankStatus != 0)) || ((bank == 1) && (BankStatus == 0)))
{
SPI_Write_Cmd(ACTIVATE, 0x53); // Toggle the register bank
}
}


/**************************************************/
// The SwitchToBank() function uses another version of the read from register function
// We don't need to select a register to read from, to get data from the STATUS register (it is shifted out during the first byte write)
int8 SPI_Read_Status()
{
int8 value;
CSN = 0; // Start SPI communication
value = SPI_RW(NOP); // Read STATUS register
CSN = 1; // End SPI communication
return(value); // Return register value
}
 
Last edited:
Well done indeed. Did you use the payload length or did you just load a single byte ? The default payload length I think is 5-bytes.
 
In the init procedure in the receiver, I have another line of code:

SPI_Write_Reg(RX_PW_P0, 1); // 1 byte in RX payload in data pipe 0

The payload length is only applicable in the receiver as the transmitter will transmit whatever you put in the TX FIFO as far as I can see from the datasheet.

And I use static payload length here at first, I might move to dynamic as my project will need to send mostly 4 bytes, but once in a while I need to send up to 250 bytes.
 
Last edited:
Oh, in my init code, I first read the RF_SETUP register, change the bits and then writes it back. I do this because some of the bits are reserved, and to make sure I don't change them, I have to do it this way. Who knows, maybe they change away from the reset values at some point, so I'll better be safe. I'll do this with all registers containing reserved bits.
 
I have problems using the W_TX_PAYLOAD_NOACK command.

I did set the EN_DYN_ACK bit in the FEATURE register, but RFM70 don't send anything with this command.
 
DOH! You cannot write to the FEATURE register before you have run run the ACTIVATE command with 0x73. I don't see this mentioned anywhere in the datasheet :-(
 
FEATURE regsiter

How the heck did you figure that one out as I cannot write to it either !!!

I don't know whether it is my coding or what but it seems that when you read from a register in Bank-0 you read the STATUS first and then the register but this doesn't happen with all registers! (refer 6.3.2 at the bottom of page-13). FIFO_STATUS for instance only seems to spit out only itself.....

Perhaps you should add this to the Martin/Graham document "RFM70 for Dummies" or "Getting the RFM70 to Work" and send a copy to Hope RF :)
 
Oh, in my init code, I first read the RF_SETUP register, change the bits and then writes it back. I do this because some of the bits are reserved, and to make sure I don't change them, I have to do it this way. Who knows, maybe they change away from the reset values at some point, so I'll better be safe. I'll do this with all registers containing reserved bits.

Why did you change this register to channel 0x23 ?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top