nrf24l01 IRQ problem

Hi all,

I am using PIC16F877 to interface with nrf24l01 for both transmitter and receiver. I am able to configure all nrf24l01 registers using software SPI, and also read back to verify for the registers value. However, I can’t get the IRQ after the CE pulse at the transmitter side, of course the receiver side also can’t get the IRQ unless the transmitter is working correctly.

I also ported brennen’s tutorial 1 to PIC16F877, but i am still having this problem.

nrf24l01 configured for no ack, IRQ enabled, payload of 1 byte.

Below are my registers configurations:

config = TX:0x0a RX:0x0b

en_aa = TX:0x00 RX:0x00

en_rxaddr = TX:0x00 RX:0x01

setup_aw = TX:0x03 RX:0x03

setup_retr = TX:0x00 RX:0x00

rf_ch = TX:0x02 RX:0x02

rf_setup = TX:0x07 RX:0x07

rx_addr_p0 = TX:default RX:default

rx_addr_p1 = TX:default RX:default

rx_addr_p2 = TX:default RX:default

rx_addr_p3 = TX:default RX:default

rx_addr_p4 = TX:default RX:default

rx_addr_p5 = TX:default RX:default

tx_addr = TX:default RX:default

rx_pw_p0 = TX:0x00 RX:0x01

rx_pw_p1 = TX:0x00 RX:0x00

rx_pw_p2 = TX:0x00 RX:0x00

rx_pw_p3 = TX:0x00 RX:0x00

rx_pw_p4 = TX:0x00 RX:0x00

rx_pw_p5 = TX:0x00 RX:0x00

Connection for PIC with nordic is:

RA0 = CE

RA1 = SCK

RA2 = MOSI

RA3 = MISO

RA4 = CSN

RA5 = IRQ

I am able to get the status when i write SPI data, so i think the SCK, MOSI, MISO and CSN should be correct.

Is there any registers i set wrongly?

Thanks!!

Regards,

Sheng

One thing I would suggest is to disconnect the IRQ line and measure the voltage that the 24L01 is putting out. It should be 3.3V. Then, keeping the IRQ pin disconnected, send a packet (make sure not to clear interrupts or flush the FIFO). Now measure the voltage at the IRQ pin. If it is 0V, then the 24L01 is working properly and you have set up your IRQ pin on the PIC as an output. If this doesn’t work, then we’ll have to delve a little more deeply into your problems.

Hi brennen,

Thanks for your advice! I have tested it. The IRQ pin gives me 3.3V before and after transmission. Tested with 2 nrf24l01 modules.

Besides, i tried to write 3 times 32 bytes of data into the TX FIFO, i got the TX_FULL flag. Then i did a CE pluse and the flag was cleared, however i still can’t get the IRQ.

Will it be the nrf24l01 is faulty? If yes, cannot be both units are faulty, rite?

Are you totally sure that your CONFIG register has the MASK_TX_DS bit cleared? It looked like it did in your register dump, but make totally sure. Other than that, one other possibility I can think of is that you’re maybe getting a short to your 3.3V rail. Measure the continuity from the IRQ pin the 3.3V output of the regulator that’s feeding the 24L01 (if you’re using a MiRF-v2, it’s on the board), and make sure that you’re not shorted out. Other than those two things, I’m at a bit of a loss as to what else might be your problem. I am highly doubting at this point that it’s faulty units, though, since two of them did the same thing.

strangley

I am having the same problem, on PIC18f8722 microchip explorer board, ccs compiler.

I can write to NRF and read all registers

but following tutorial 1, I cant get the

while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active())){
			}

loop to break

on checking the tx_ds is 0,

so I am a bot lost what to do now. again… i have tested this on two mirf v2 boards

here is my little bit modified code

#include <18F8722.h>
#fuses H4,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=40000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include <stdlib.h>                                //for printf

#define VCC     PIN_A1      // power to NRF24L01
#define CE      PIN_B5      // output Chip enable to nRF24L01 CE PIN_1 
#define CSN      PIN_B4      // output Chip Select to nRF24L01 CSN PIN_2 
#define SCK      PIN_B3      // serial clock output to nRF24L01 SCK PIN_3 
#define IRQ      PIN_B0      // input valid TX/RX from nRF24L01 IRQ PIN_6 

// LED indicator Pins 
#define LED0   PIN_D0 
#define LED1   PIN_D1 
#define LED2   PIN_D2 

#byte PORTA = 0xf80
#byte PORTB = 0xf81
#byte PORTC = 0xf82

#bit CSN_PIN = PORTB.4
#bit CE_PIN  = PORTB.5
#bit IRQ_PIN = PORTB.0

#include <NRF24L01.C>


void main(){
unsigned char data; //register to hold letter sent and received
unsigned int count; //counter for for loop
char test;

set_tris_b(0b00000001);
printf("\n\r Start \n\r");
output_high(VCC);
setup_spi(spi_master|SPI_L_TO_H|SPI_CLK_DIV_64);
nrf24l01_initialize_debug(false, 1, true); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled

while(1){
//printf(".");


while(kbhit())
		{
			
			putc(data);
            printf("\n\r Recieved Char \n\r");

			for (count = 1; count <255; count ++){
            nrf24l01_write_register(nrf24l01_setup_retr, &count, 1);
			nrf24l01_read_register(nrf24l01_setup_retr, &data,1);
			printf("%X ",data);
			putc('.');
			}
            printf("\n\r OUT OF READ/WRITE LOOP \n\r");
			data = getc(); //get data from UART
			nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF
            printf("\n\r TX PAYLOAD SENT \n\r");

			//wait until the packet has been sent or the maximum number of retries has been reached
			while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active())){
			}
               printf("\n\r IRQ RECIEVED \n\r");
            
			nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
			nrf24l01_set_as_rx(true); //change the device to an RX to get the character back from the other 24L01

			     printf("\n\r SET AS RX \n\r");
			//wait a while to see if we get the data back (change the loop maximum and the lower if
			//  argument (should be loop maximum - 1) to lengthen or shorten this time frame
			 printf("\n\r Going in for loop of hundred \n\r");
			for(count = 0; count < 100; count++)
			{
				//check to see if the data has been received.  if so, get the data and exit the loop.
				//  if the loop is at its last count, assume the packet has been lost and set the data
				//  to go to the UART to "?".  If neither of these is true, keep looping.
				if((nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()))
				{
					nrf24l01_read_rx_payload(&data, 1); //get the payload into data
					break;
				}
				
				//if loop is on its last iteration, assume packet has been lost.
				if(count == 99)
					data = '?';
			}
			 printf("\n\r out of for loop of undred \n\r");
			nrf24l01_irq_clear_all(); //clear interrupts again
			putc(data); //print the received data (or ? if none) to the screen
		     printf("\n\r Just put recieved dfata \n\r");
			delay_us(130); //wait for receiver to come from standby to RX
             printf("\n\r SET AS TX \n\r");
			nrf24l01_set_as_tx(); //resume normal operation as a TX
			 printf("\n\r LED TOGGLE \n\r");								
			output_toggle(LED0); //toggle the on-board LED as visual indication that the loop has completed
		}
}


}

OK

I think I fouind the fault a bit

in the tutorial 1 code the program is starting with the

nrf24l01_initialize_debug(false, 1, false); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled

but in the nrf24L01.c file it says

/initializes the 24L01 to all default values except the PWR_UP and PRIM_RX bits
//this function also disables the auto-ack feature on the chip (EN_AA register is 0)
//bool rx is true if the device should be a receiver and false if it should be
//  a transmitter.
//unsigned char payload_width is the payload width for pipe 0.  All other pipes
//  are left in their default (disabled) state.
//bool enable_auto_ack controls the auto ack feature on pipe 0.  If true, auto-ack will
//  be enabled.  If false, auto-ack is disabled.
void nrf24l01_initialize_debug(bool rx, unsigned char p0_payload_width, bool enable_auto_ack)

which means we have to seperately use the pwr_up command to start using the nrf24L01

I did this and the IRQ pin stadted working.

which means we have to seperately use the pwr_up command to start using the nrf24L01

This is an incorrect interpretation. The nrf24l01_initialize_debug() function sets the PWR_UP bit in the CONFIG register and if the argument bool rx is true, it sets the PRIM_RX bit in CONFIG. There is no need to separately have to call any other function to set up your radio if the code is working properly. This is the way the code works in the tutorials. Apparently there's something that CCS doesn't like about my code, considering to my knowledge nobody that's used C18 has had similar problems, but two people using CCS are. It could also have something to do with your PIC of choice.

You should simply call the nrf24l01_initialize_debug() function, then dump your registers to check the problem. If the PWR_UP bit in the CONFIG register is set and the PRIM_RX bit is what it should be (1 for RX and 0 for TX), then the initialize function is working as it should. Otherwise, please let me know what the actual register dump says.

Hi brennen,

The IRQ pin doesn’t short to 3.3V rail. I discovered something funny! After i transmit out a packet, all the registers reset to the default settings including the pwr_up. Seems like the nrf24l01 was rebooted?? During the transmission i measured the VDD_PA, it does give me a high pulse. I really don’t know what is happening. Below is my code (modified frm tut 1):

#include <htc.h>
__CONFIG(HS & WDTDIS & PWRTDIS);
#include <stdio.h>
#include "delays.h"
#include "nrf24l01.h"

#define	Reg_CONFIG		0x0a
#define	Reg_EN_AA		0x00
#define	Reg_EN_RXADDR	0x00
#define	Reg_SETUP_AW	0x03
#define	Reg_SETUP_RETR	0x00
#define Reg_RF_CH		0x02
#define Reg_RF_SETUP	0x07
#define Reg_ADDR_P2		0xC3
#define Reg_ADDR_P3		0xC4
#define Reg_ADDR_P4		0xC5
#define Reg_ADDR_P5		0xC6
#define Reg_RX_PW_P0	0x00
#define Reg_RX_PW_P1	0x00
#define Reg_RX_PW_P2	0x00
#define Reg_RX_PW_P3	0x00
#define Reg_RX_PW_P4	0x00
#define Reg_RX_PW_P5	0x00

void Initialize(void);
void InitializeIO(void);

unsigned char	Reg_RX_ADDR_P0[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
unsigned char	Reg_RX_ADDR_P1[5] = {0xC2, 0xC2, 0xC2, 0xC2, 0xC2};
unsigned char	Reg_TX_ADDR[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};

//main routine
void main(void)
{
	unsigned char data; //register to hold letter sent and received
	unsigned int count; //counter for for loop
	
	Initialize(); //initialize IO, set up nRF24L01 as TX


	while(1)
	{
			data = 0xff;
			nrf24l01_read_register(0x01, &data, 1);
			RB1 = 0;
			if(data == Reg_EN_AA)
				RB1 = 1;	//LED
			else
				RB1 = 0;
			data = 0xff;
			nrf24l01_read_register(0x00, &data, 1);
			if (data == Reg_CONFIG)
			{
				RB2 = 1;	//LED
				data = 0x66;
				nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF
			}else
			{
				RB2 = 0;
			}
			
			//wait until the packet has been sent or the maximum number of retries has been reached
//			while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));
			nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
			DelayUs(Delay130Us);
	}
}

//initialize routine
void Initialize(void)
{
	InitializeIO(); //set up IO (directions and functions)
//	nrf24l01_initialize_debug(false, 0x01, false); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled
	nrf24l01_initialize(Reg_CONFIG, false, Reg_EN_AA, Reg_EN_RXADDR, Reg_SETUP_AW, Reg_SETUP_RETR, Reg_RF_CH, Reg_RF_SETUP, Reg_RX_ADDR_P0, 
						 Reg_RX_ADDR_P1, Reg_ADDR_P2, Reg_ADDR_P3, Reg_ADDR_P4, Reg_ADDR_P5, Reg_TX_ADDR, Reg_RX_PW_P0, Reg_RX_PW_P1, 
						 Reg_RX_PW_P2, Reg_RX_PW_P3, Reg_RX_PW_P4, Reg_RX_PW_P5);
}

//initialize IO pins
void InitializeIO(void)
{

	PORTA = 0;
	PORTB = 0;
	ADCON1 = 0x06;	// All digital
	TRISA = 0x28;	// RA0 to RA2 and RA4 = o/p, RA3 and RA5 = i/p
	TRISB = 0x01;	// RB0 as i/p (push-button), RB1 to RB2 as o/p (LED)

	RA0 = 0; //CE
	RA1 = 0; //SCK
	RA2 = 0; //MOSI
	RA4 = 1; //CSN

}

I recall somebody that had a similar problem to you, but I forgot how they resolved it. It sounds like a hardware problem of some sort, either how things are wired or how your ports are defined with respect to input or output pin status. I would suggest disconnecting the IRQ pin and then trying to send a packet. Check the registers of the 24L01 after that (without doing any IRQ clears or FIFO flushes) and see if they have all reset. If not, then your problem is IRQ. If not, it is likely some other pin that is causing some sort of short somewhere that is resetting the 24L01.

hi brennen

first of all, i want to thank you a lot for the great job you have done with the tutorials. I have finally got the nrf24L01s communicating. I think it is problem with ccs rather than your code.

Again thanks a lot

Also Sheng, did you get it to work, what compiler are you using?

Regards

hi teekay_tk,

i am using HI-TECH C Compiler (PICC). I am still trying out, haven’t solved the problem yet. May I know how you solved your problem? Did you change compiler?

teekay_tk:
hi brennen

first of all, i want to thank you a lot for the great job you have done with the tutorials. I have finally got the nrf24L01s communicating. I think it is problem with ccs rather than your code.

Again thanks a lot

No problem man. I figured that since I wrote it, I might as well share it and help people out as much as I can.

no

i just wrote to the power_up bit once again and things started working. but my problem was that i wasnt even getting the tx_flag. Also I made pretty sure that the IRQ pin was set up as an input as CCS some times sets stuff as output for no reason at all.

i havent used hitec-c but i think it shouldn be too different. Can i suggest that you stop looking at the IRQ altogether. Just look at the three IRQ flags and you will be fine i think

Hi all,

I have solved the problem. It was due to a glitch in the power supply when transmitting. Adding a capacitor at the power line solved the problem.

Btw, brennen was right that there is no need to set the power_up bit again after calling the nrf24l01_initialize_debug() function.

Thanks, brennen & teekay_tk!