nRF24L01 using PIC18F2550 with Brennen lib

I had no time to work on the module before, so I’m just getting back to it, and it seems that I am talking to the module without any problem (once I have implemented the SPI_CSN byte that I didn’t before), here is the code added :

	nrf24l01_flush_tx();
	nrf24l01_flush_rx();
	nrf24l01_get_all_registers(buffer);
   for(count = 0; count < 36; count++)
       printf("%x: %x\r\n", count, buffer[count]); 
//ADDED---------------------------------------------------------
#define SPI_CSN      LATBbits.LATB6      // CSN output pin, PORTB pin 6
	   SPI_CSN = 0;         //CSN low
	status = spi1_send_read_byte(0x30);
	spi1_send_read_byte(0x11);
	spi1_send_read_byte(0x22);
	spi1_send_read_byte(0x33);
	spi1_send_read_byte(0x44);
	spi1_send_read_byte(0x55);
	   SPI_CSN = 1;               // CSN high

	printf("WRITING...\n\r");
   nrf24l01_get_all_registers(buffer);
	for(count = 0; count < 36; count++)
       printf("%x: %x\r\n", count, buffer[count]);

and here is the output:

Init OK0: a

1: 0

2: 3

3: 3

4: 3

5: 2

6: f

7: e

8: 0

9: 0

a: e7

b: e7

c: e7

d: e7

e: e7

f: c2

10: c2

11: c2

12: c2

13: c2

14: c3

15: c4

16: c5

17: c6

18: e7

19: e7

1a: e7

1b: e7

1c: e7

1d: 1

1e: 0

1f: 0

20: 0

21: 0

22: 0

23: 11

WRITING…

0: a

1: 0

2: 3

3: 3

4: 3

5: 2

6: f

7: e

8: 0

9: 0

a: e7

b: e7

c: e7

d: e7

e: e7

f: c2

10: c2

11: c2

12: c2

13: c2

14: c3

15: c4

16: c5

17: c6

18: 11

19: 22

1a: 33

1b: 44

1c: 55

1d: 1

1e: 0

1f: 0

20: 0

21: 0

22: 0

23: 11

we see clearly that I have written :

18: 11

19: 22

1a: 33

1b: 44

1c: 55

Now I’ll have a look at the slave… I don’t know why it doesn’t receive anything. May the bunch of wires around be a problem you think ? (even if my 2 modules are almost stuck to one another ?)

Thank you very much for your help

Here is the code of my slave, the initialization part is exactly the same as the master module, the only thing that changes is in the “nrf24l01_initialize_debug(true, 1, false);” that init the module to RX. The initialization IO part is exactly the same for master and slave…

My LED 0 blinks at startup, this means the initialization went all right. but then it seems never to get any interruption and gets stuck to " while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active())); "

Here is the code. I can’t see what’s wrong…

#include <p18F2620.H>
//#include <string.h>
#include <spi.h> 
#include "delays.h" 
#include "nrf24l01.h" 


#pragma config OSC = HS//
//#pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
//#pragma config IESO = OFF //Oscillator Switchover mode disabled
#pragma config PWRT = ON //Power-up Timer Enable
//#pragma config BOREN = OFF //Brown-out Reset disabled in hardware and software 
//#pragma config BORV = 0 //Brown Out Reset Voltage: Maximum setting
#pragma config WDT = OFF //
//#pragma config WDTPS = 1 //Watchdog Timer Postscale Select 1:1
//#pragma config CCP2MX = PORTC //CCP2 input/output is multiplexed with RC1 
//#pragma config PBADEN = OFF // PORTB<4:0> pins are configured as digital I/O on Reset 
//#pragma config LPT1OSC = OFF //Timer1 configured for higher power operation
#pragma config MCLRE = ON //(ON)MCLR pin enabled; RE3 input pin disabled
#pragma config STVREN = ON //Stack full/underflow will not cause Reset 
#pragma config LVP = OFF //Single-Supply ICSP disabled 

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

void ToggleLED(int id); //toggle the current state of the on-board LED

//main routine
void main(void) 
{ 
   unsigned char data; //register to hold letter received and sent 
    
   Initialize(); //initialize PLL, IO, SPI, set up nRF24L01 as RX 

   //main program loop 
   while(1) 
   { 
      //wait until a packet has been received 
      while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active())); 
	ToggleLED(1);
      nrf24l01_read_rx_payload(&data, 1); //read the packet into data 
      nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01 

      DelayUS(130); //wait for the other 24L01 to come from standby to RX 
       
      nrf24l01_set_as_tx(); //change the device to a TX to send back from the other 24L01 
      nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF 
       
      //wait until the packet has been sent 
      while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active())); 

      nrf24l01_irq_clear_all(); //clear interrupts again 
      nrf24l01_set_as_rx(true); //resume normal operation as an RX  
   } 
} 

//initialize routine
void Initialize(void) 
{ 
   InitializeIO(); //set up IO (directions and functions)
   OpenSPI(SPI_FOSC_16, MODE_00, SMPMID); //open SPI1 
   nrf24l01_initialize_debug(true, 1, false); //initialize the 24L01 to the debug configuration as RX, 1 data byte, and auto-ack disabled
	DelayUS(200);
	ToggleLED(0);
} 

//initialize IO pins
void InitializeIO(void)
{
	ADCON1 = 0x0F; //disable AD converter functionality on PORTA
	CMCON = 0x07; //disable comparators on PORTA

	TRISAbits.TRISA0 = 0; //make PORTA.0 an output to control LED
	PORTAbits.RA0 = 1; //turn on LED0
	TRISAbits.TRISA1 = 0; //make PORTA.1 an output to control LED
	PORTAbits.RA1 = 1; //turn on LED1

	TRISBbits.TRISB7 = 1; //make sure that PORTB.7 INPUT since it is IRQ pin
	TRISBbits.TRISB6 = 0; //make sure that PORTB.6 OUTPUT since it is CSN pin
	TRISBbits.TRISB5 = 0; //make sure that PORTB.5 OUTPUT since it is CE pin
	PORTBbits.RB6 = 1; //set CSN bit

	TRISCbits.TRISC3 = 0; //make sure that PORTC.3 OUTPUT since it is SCK pin
	TRISCbits.TRISC4 = 1; //make sure that PORTC.4 INPUT since it is SDI pin
	TRISCbits.TRISC5 = 0; //make sure that PORTC.5 OUTPUT since it is SDO pin

	TRISCbits.TRISC6 = 0; //make sure that PORTC.6 OUTPUT since it is TX pin UART
	TRISCbits.TRISC7 = 1; //make sure that PORTC.7 INPUT since it is RX pin UART

	//TRISC = 0x91; //make CSN, CE, SCK, MOSI (SDO), and TX outputs
}	  

//toggles on-board LED
void ToggleLED(int id) 
{ 
	if (id==1)
   	PORTAbits.RA1 = ~PORTAbits.RA1;
	else 
	PORTAbits.RA0 = ~PORTAbits.RA0;
}

Do you have an LED on the TX side that blinks when you get the TX_DS interrupt? If the TX doesn’t give a TX_DS interrupt, then the RX is certainly not going to assert an RX_DS interrupt.

Hi Brennen, thank’s for your answer, on the TX side, I have an UART message that tells me it is sent :

	nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF	
			//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()));
			if (nrf24l01_irq_tx_ds_active()){ //see if it was sent or not and tell me..
				printf("\n Sent");
			} else {
				printf("\n Something's wrong");
			}

It tells me “Sent”

No more idea about my trouble ? I’ve check my connections carefully and both modules are wired the same way…

You have never answered about the trouble I could have because of the wires around the RF module… Do you think this could cause the receiver not to receive anything ?

Thank you

Have you checked the IRQ pin at the RX to see if it is asserted (GND) after the TX sends a packet? I highly doubt that wires will cause you to not get a packet if the boards are close to one another.

Thank you for your suggestion, I have just check with a multimeter (I don’t have any oscilloscope) and the IRQ pin is never low, it keeps being at 3.1v…

edit:

Wait, I just check with the TX IRQ pin that should be low when it has transmitted, and the pin only goes from 3.2V to 3.1 for a second, and then back to 3.2V…

If the RX IRQ pin never goes low, then it’s not getting the packet. You should also verify that the CE pin is logic high for the RX constantly, or else the radio won’t be turned on.

For the TX, it is expected that the IRQ will only drop momentarily. That is because your code clears the interrupt almost as soon as it is asserted.

Thank you for your help.

I have noticed a change to RX IRQ when I send a packet. Just like TX IRQ, it seems to be floating (around 3.2V) and then when I send a packet it stops floating around 3V… for a second, and then goes floating again… Something happens obviously…

TX CE is low (close to 0) and goes high when it has sent, and then goes low again (as expected).

RX CE pin is 3.2V (logic high I assume) and seems to be floating as well, but just like IRQ, something happens (it stops floating) when I send a character…

My pin declaration seems to be all right though…

EDIT: :shifty: ok now RX IRQ pin is kept low (close to 0V…)

To test if you are reading the RX IRQ pin correctly, then in place of this code

   while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active())); 
   ToggleLED(1);

substitute this code

   while(!(nrf24l01_irq_pin_active());
   ToggleLED(1);

   printf("IRQ is ");
   
   if(nrf24l01_irq_rx_dr_active())
      printf("RX_DR\n");
   else if(nrf24l01_irq_tx_ds_active())
      printf("TX_DS\n");
   else if(nrf24l01_irq_max_rt_active())
      printf("MAX_RT\n");
   else
      printf("unknown\n");

This will print out the IRQ type when IRQ is asserted, assuming you have everything set up properly.

NOTE: I did not compile this code, so it may contain syntax errors.

Well I do not have any UART on the slave as I only have one RS232 adaptor and I need it to be able to send a character. However I was able to get an oscilloscope and I have clearly seen that RX IRQ isn’t going low, as well as TX IRQ… there’s something wring with that. I’ll test your code on the TX to make sure that the IRQ isn’t working properly.

Thank’s a lot for your help again

I made sure my IRQ works when I am sending… and it works…

			data = ReadUSART(); //get data from UART
			printf("\n merci");
			nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF	
while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));
			if (nrf24l01_irq_pin_active()){
				printf("\n IRQ pin active");
			}
			if (nrf24l01_irq_tx_ds_active()){ //see if it was sent or not and tell me..
				printf("\n TX_DS active");
			} else
			if	(nrf24l01_irq_max_rt_active()){
				printf("\n Max RT active");
			} else {
				printf("Something's wrong");
			}

output:

wait

wait<--------- here I type in a character on my keyboard

merci

IRQ pin active

TX_DS active

count:0

count:1000

count:2000

count:3000

count:4000

count:5000

count:6000

count:7000

count:8000

count:9000

count:10000

count:11000

count:12000

count:13000

count:14000

count:15000

count:16000

count:17000

count:18000

count:19000data: ?

wait

wait

I’ll modify my program for the TX to send continuously and have a look at the RX side to try to understand what’s wrong with IRQ

You need to remove the else before

if (nrf24l01_irq_tx_ds_active()){ //see if it was sent or not and tell me..

Otherwise, you’ll never see what type of IRQ you’re getting, because the first if will always be true there.

I realized this afterwards, I have edited my previous post, the TX_DS is active.

However, when I type in one character it works, well it sends something, and goes waiting for another character, but then if I type in a character (for the second time) it gets stuck (obviously on while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active())); )

EDIT: This was a bug, it doesn’t get stuck anymore…

So it sounds like you’ve proven the TX is working as expected, so the problem almost certainly lies in the RX (unless there’s some kind of register settings problem that I can’t see).

I’ll check the RX side now. What kind of register problem are you thinking about. I can’t think of any because I’m not dealing with them directly.

Thank’s a lot for your help, it’s really pleasant not to feel alone !

I don’t know of any register issues specifically…just not ruling it out as a possibility. And you’re welcome. :ugeek:

One of my major problem could have come to the fact that “#include <stdio.h>” was missing in RX code…

Here is where I am (this is close to the end !)

I’ve modified the TX code to keep sending and receiving, this module doesn’t have any UART, just the LED blinking as I’m sure it works well.

I sends a ‘a’, get into RX mode, waits a while for something to receive, and loops even if it didn’t receive anything.

The RX module has UART, it tells me if the init went all right, tells me it’s waiting for a packet to receive, then tells me what it has received. It goes then in TX mode to send the ‘a’, it tells me the IRQ state and loops.

Here is the main while loop of RX module :

   while(1) 
   { 
	CheckErrorsUSART();
	printf("\n wait");
    //wait until a packet has been received 
	while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active())); 
	ToggleLED(1);
	nrf24l01_read_rx_payload(&data, 1); //read the packet into data 
	nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01 
	printf("\ndata received: %c",data);
	DelayUS(130); //wait for the other 24L01 to come from standby to RX 
       
	nrf24l01_set_as_tx(); //change the device to a TX to send back from the other 24L01 
	nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF 
    printf("\n\rsending...");   
	//wait until the packet has been sent 
	while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active())); 
			if (nrf24l01_irq_pin_active()){
				printf("\n IRQ pin active");
			}
			if (nrf24l01_irq_tx_ds_active()){ //see if it was sent or not and tell me..
				printf("\n TX_DS active");
			} 
			if	(nrf24l01_irq_max_rt_active()){
				printf("\n Max RT active");
			} 
	nrf24l01_irq_clear_all(); //clear interrupts again 
	nrf24l01_set_as_rx(true); //resume normal operation as an RX  
   }

and the output :

  Init OK
          wait
              data received: a
sending...
           IRQ pin active
                          TX_DS active
                                       wait
                                            Init OK
                                                    wait<--- gets stuck here

So it receives the ‘a’ properly, sends properly the data back, but gets stuck on the second iteration…

edit: :o Wait I just realized it resets after sending… it shouldn’t !

:dance: Don’t know why… but it now works the way it should

Thank you very much for your help !!

Glad to hear it!