nrf24l01 recieving gibberish. Bad units?

Has anyone ever experienced that a nrf24l01 with no transmitter in the neighbourhood and AA+CRC enabled receives a load of crap sometimes? Mine does that and when it happens (and it happens often) it also doesn’t receive any real packets anymore from another nrf? Somehow it craps out and stops receiving real packets…

Also somehow the RX_DR irq get set, when the RX buffer is empty, as it prints out X’s (see code).

Both my nrf’s do this, so most likely it is not a defective unit, but what can it be???

Please respond if you have any clue. I’m really stuck at the moment!

	nrf24l01_clear_flush(); //clear interrupts and flush
	while ( !(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()) && ReadTimer0() < maxListeningTime) // wait for packet
	if (nrf24l01_irq_rx_dr_active()) // if recieved
	{
		if (nrf24l01_fifo_rx_empty()) // doublecheck. THIS X GETS PRINTED!! HOW????
		{
			UARTIntPutChar('X');
		}
		nrf24l01_irq_clear_all(); //clear interrupts
		nrf24l01_read_rx_payload(&recievedData, 28); // read into char
		DelayUS(500); // allow time to send ACK and settle as RX again (= ARD time)
		if (okData[0] == recievedData[0] && okData[1] == recievedData[1]) // compare data
		{
			UARTIntPutChar('O');	
			return 1; // revieced an OK
		}
		if (falseData[0] == recievedData[0] && falseData[1] == recievedData[1])
		{
			UARTIntPutChar('N');
			return 0; // recieved a Not OK
		}
		for (i = 0; i < 28; i++)
		{
			UARTIntPutChar(recievedData[i]); // THIS PUTS OUT A BUNCH OF CRAP
		}
		PORTAbits.RA0 = 0;
		return 3;
	}

It’s certainly possible that you’re getting interference from other 2.4 GHz devices, such as wireless cards, routers, mice/keyboards, etc. You may try changing the channel on your units to see if that makes the interference less. I don’t know how your device is configured, but going up to 5 address bytes and 2 byte CRC will also help with avoiding noise packets.

I’ll try changing the channel. I’m using your code and your standard settings (which is a 5 byte address, btw thanks for writing the library!!). I’ll try 2 CRC bytes aswell.

But still I find it strange that the receiver receives the packets just fine and then suddenly spits out crap and doesn’t receive anything anymore. I’ll try focusing on the transmitter side now, maybe there’s also a problem there.

I hope I get it right soon. Very frustrating to be stuck for a week on the same problem… :slight_smile:

JaapvdBosch:
But still I find it strange that the receiver receives the packets just fine and then suddenly spits out crap and doesn’t receive anything anymore.

If it just locks up, check to make sure that you clear out all the possible interrupts and the RX FIFO, too. This should bring it back to life if the problem is at the RX side. If it's at the TX side, then you have other issues to work out.

JaapvdBosch:
I’m using your code and your standard settings (which is a 5 byte address, btw thanks for writing the library!!).

No problem! I initially wrote it for myself, so I figured that in the spirit of open source that I would release it to everyone. I enjoy helping people out whenever I can with this stuff.

OK, I changed to a 2 byte CRC and removed any time delays from the TX side (according to the datasheet this should be possible). Now I receive a steady stream of data (the O’s represent a valid packet). That makes me very happy!!!

But still sometimes it craps out and stops recieving. Here’s a printout:

 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO  // STEADY STREAM OF VALID PACKETS
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 4F 4F 4F 70 78 00 00 00 00 00 00 00 00 00   OOOOOpx......... // 5 good packets and then some crap (px..................)
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
 00 60 6B 66 62 63 64 65 63 67 68 69 6A 6B 6C 6D   .`kfbcdecghijklm // second invalid packet (somehow this does get through the CRC filter...)
 03 00 00 00 00 00 00 00 00 00 00 00 00 4F 4F 4F   .............OOO // Some valid packets again
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 70 78 00 01 00 00 00 07 00 01 0F 01 03 0F 0F   Opx............. // some crap
 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 4F 4F 4F   .............OOO // valid
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 78 78 00 00 00 00 00 00 00 00 00 00 00 00 00   Oxx............. // crap
 00 00 00 00 00 00 00 00 00 00 00 00 00 78 78 00   .............xx.
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
 00 00 00 05 06 77 00 79 7A 4F 4F 4F 4F 4F 4F 4F   .....w.yzOOOOOOO // valid
 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F 4F   OOOOOOOOOOOOOOOO
 4F 4F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F   OO _ _ _ _ _ _ _ // receiver doesn't receive anyting anymore from this point on
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F    _ _ _ _ _ _ _ _
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F    _ _ _ _ _ _ _ _
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F    _ _ _ _ _ _ _ _
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F    _ _ _ _ _ _ _ _
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F    _ _ _ _ _ _ _ _

Does this make any sense to you with you experience?

So there could also be something wrong on the TX side perhaps?

The TX runs this code:

bool sendAck (bool ok, unsigned int maxSendingTime, bool setAsTX)
{
	unsigned char okData[28] = { 'o', 'k', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
	unsigned char falseData[28] = { 'n', 'o', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };

	nrf24l01_clear_flush(); //clear interrupts and flush
	if (setAsTX)
	{
		nrf24l01_rx_active_to_standby();
		DelayUS(130);
		nrf24l01_set_as_tx(); //change the device to an TX
	}

	WriteTimer0(0); // reset timer

	if (!ok)
	{
		nrf24l01_write_tx_payload(falseData, 28, true);
	}
	else
	{
		nrf24l01_write_tx_payload(okData, 28, true);
	}


	while( !(nrf24l01_irq_pin_active() && (nrf24l01_irq_tx_ds_active() || nrf24l01_irq_max_rt_active()) ) && ReadTimer0() < maxSendingTime );
	DelayUS(10); // Delay to be sure STATUS info is up to date
	if (nrf24l01_irq_tx_ds_active())
	{
		//////nrf24l01_irq_clear_all(); //clear interrupts
		//////DelayUS(130); // avoid timing issues??
		return true; // transmit succeeded and was recieved
	}
	else
	{
		//////nrf24l01_irq_clear_all(); //clear interrupts
		//////DelayUS(130); // avoid timing issues??
		return false; // unsuccessful transmit
	}
}

I added some output to the TX too. And ‘O’ means that the TX_DS went high (successful transmission) and ‘X’ that a time-out occurred or the MAX_RT went high.

I get this output:

 4F 4F 4F 4F 58 58 58 58 58 58 58 58 58 58 58 4F   OOOOXXXXXXXXXXXO // it prints continuously 4 O's and 11 X's. When I turn off the receiver the O's stop, so they do get received. Why the X's get printed I do not know.
 4F 4F 4F 58 58 58 58 58 58 58 58 58 58 58 4F 4F   OOOXXXXXXXXXXXOO
 4F 4F 58 58 58 58 58 58 58 58 58 58 58 4F 4F 4F   OOXXXXXXXXXXXOOO
 4F 58 58 58 58 58 58 58 58 58 58 58 4F 4F 4F 4F   OXXXXXXXXXXXOOOO
 58 58 58 58 58 58 58 58 58 58 58 4F 4F 4F 4F 58   XXXXXXXXXXXOOOOX
 58 58 58 58 58 58 58 58 58 58 4F 4F 4F 4F 58 58   XXXXXXXXXXOOOOXX
 58 58 58 58 58 58 58 58 58 4F 4F 4F 4F 58 58 58   XXXXXXXXXOOOOXXX
 58 58 58 58 58 58 58 58 4F 4F 4F 4F 20 5F 20 5F   XXXXXXXXOOOO _ _ // here I plugged the UART into the receiver. It is receiving nothing (als displayed by the ' _'.... I do not understand how this is possible...
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F    _ _ _ _ _ _ _ _
 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F 20 5F          _ _ _ _ _ _ _

I’m puzzled by how the transmitter can report a good delivery when the receiver does not report one…

OK, I just figured out what might be interfering with the reception. The previous post showed how the TX makes a good transmission on a regular basis and the RX did not receive it. Well, if I remove a few lines on the RX side which I added to protect the SPI functions from being interfered by the UART interrupts (see below), the RX does recieve data… (it still craps out sometimes thought, after a while or even right after power-up).

I’m puzzled by this relation of the UART interrupt and the SPI. Any ideas anyone??

By the way, it doesn’t affect the TX side if the irq’s are enables or disabled…

//low-level spi send function for library use

//the user should not call this function directly, but rather use one of the 8 SPI data instructions

unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata)

{

unsigned char status;

// disable UART interrupts I ADDED THESE 2 LINES

// PIE1bits.TXIE = 0;

// PIE1bits.RCIE = 0;

nrf24l01_clear_csn();

status = instruction;

nrf24l01_spi_send_read(&status, 1, true);

nrf24l01_spi_send_read(data, len, copydata);

nrf24l01_set_csn();

// enable UART interrupts I ADDED THESE 2 LINES

// PIE1bits.TXIE = 1;

// PIE1bits.RCIE = 1;

return status;

}

The evidence pointed to the SPI, so I abandoned the hardware SPI of the PIC and wrote my own software SPI (which I needed anyway). Now there’s no more crapping out!! Somehow the hardware SPI did not communicate well with the nrf probably…

Now to solve some timing issues and then I can go on! I’m happy!

Probably you didn’t configured correctly the SPI. I think you need to have mode 0. This is the configuration function for my code (18F4680) that works:

void SPIInit (void) {

//disable module to do initialization

SSPEN = 0;

//init registers

SSPCON1 = 0b00000001; //CKP = 0, SPI Master Mode, clock = Fosc / 16

SSPSTAT = 0b01000000; //SMP = 0, CKE = 1 → SPI Mode 0,0

//enable MSSP module

SSPEN = 1;

}

I use C18 with this line:

OpenSPI(SPI_FOSC_4, MODE_00, SMPMID); // open SPI1

Should be ok I thought…?

That should work just fine. The other thing is to make sure you’re using an SPI read function that is similar to the one that I have in the tutorials. C18’s included SPI read routines don’t work well with my library.

For others to enjoy or comment on; this is the code I use now:

/** D E F I N E S **************************************************/
#define SPI_SCK         LATBbits.LATB2       // Clock pin, PORTB pin 0
#define SPI_SO          LATBbits.LATB3       // Serial output pin, PORTB pin 1
#define SPI_SI          PORTBbits.RB4       // Serial input pin, PORTB pin 4
#define SPI_SCALE		4					// postscaling of signal


/********************************************************************
 * Function:        unsigned char spi_Send_Read(unsigned char bytein)
 *
 * Description:     This function outputs a single byte onto the
 *                  SPI bus, MSb first. And it gets the response.
 *******************************************************************/
unsigned char spi_Send_Read(unsigned char bytein)
{
    static unsigned char i;         // Loop counter
	static unsigned char j;         // Delay counter
	unsigned char byteout = 0;		// return bit

    SPI_SCK = 0;                        // Ensure SCK is low
    for (i = 0; i < 8; i++)         // Loop through each bit
    {
        if (bytein & 0x80)          // Check if next outbit is a 1
        {
            SPI_SO = 1;                 // If a 1, pull SO high
        }
        else
        {
            SPI_SO = 0;                 // If a 0, pull SO low
        }
        byteout = byteout << 1;     // Shift outbyte left for next bit
        if (SPI_SI == 1)                // Check if next inbit is a 1
        {
            byteout |= 0x01;         // If a 1, set next bit to 1
        }
        else
        {
            byteout &= 0xFE;         // If a 0, set next bit to 0
        }
        SPI_SCK = 1;                    // Bring SCK high to latch bit
        for (j = 0; j < SPI_SCALE; j++)
		{
			Nop();                      // Avoid violating Thi
		}
        SPI_SCK = 0;                    // Bring SCK low for next bit
        bytein = bytein << 1;       // Shift byte left for next bit
    }
	return byteout;
} // end of spi_Send_Read(...)

I’ve converted your C code into assembler for the 16F88:

spi_send_read:
	banksel	PORTB
	bcf		PORTB,SPI_SCK	;SCK low
	movfw	TXDATA			;get byte to output
	movlw	8				;8 bits to send
	movwf	count
sp1_1:
	rlf		TXDATA,f		;MS bit in C
	btfss	STATUS,C		;C = 0?		
	goto	spi_2			;no, jump
	bsf		PORTB,SPI_SO	;yes, output one
	goto	spi_3
spi_2:
	bcf		PORTB,SPI_SO	;output zero
spi_3:
	btfsc	PORTB,SPI_SI	;SPI_SI input low?
	goto	spi_4			;no, jump
	bcf		STATUS,C		;yes, clear carry bit
	goto	spi_5
spi_4:
	bsf		STATUS,C		;set carry bit
spi_5:
	rlf		RXDATA,f		;rotate RXDATA left
	bsf		PORTB,SPI_SCK	;SCK high to latch bit
	decfsz	count,f			;count = 0?
	goto	sp1_1			;no, loop back
	return					;yes, return

I’ve tested it quite thoroughly with a loopback test, so it should work when I plug the MiRF V2 into my board. It’ll probably need some delays adding to it.

Interestingly, it isn’t much bigger than the C version. It must have taken me a lot longer to get it working, though.

Leon

JaapvdBosch:
I use C18 with this line:

OpenSPI(SPI_FOSC_4, MODE_00, SMPMID); // open SPI1

Should be ok I thought…?

That is interesting. I was getting very odd data back from the SPI using the following:

SSPSTAT = 0x40 or 0x00

SSPCON1 = 0x02

which was consistent with what I was getting with:

SSPSTAT = 0xC0

SSPCON1 = 0x11

(used with microSD cards)

But when I used the library init function above, it fixed the problem… Very confused, but thanks!

Robert Vogt IV