SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By Sheng
#34655
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
By brennen
#34663
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.
By Sheng
#34668
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?
By brennen
#34677
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.
By teekay_tk
#34731
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
Code: Select all
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
Code: Select all
#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
		}
}


}
By teekay_tk
#34732
OK
I think I fouind the fault a bit

in the tutorial 1 code the program is starting with the
Code: Select all
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
Code: Select all
/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.
By brennen
#34735
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.
By Sheng
#34775
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):
Code: Select all
#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

}
By brennen
#34780
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.
By teekay_tk
#34867
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
By Sheng
#34885
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?
By brennen
#34888
teekay_tk wrote: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.
By teekay_tk
#34894
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
By Sheng
#34966
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!