nrf24L01 timing issues and semi full duplex code

Hi Guys! I’m designing software to have a stable and lossless rs232 connection over an rf24l01 (one on each side). My code seems to be working, but sometimes the nrf’s seem to stop listening to each other… And now I’ve written a handshaking code, to find an empty channel and here too it sometimes works perfectly and sometimes it just keeps searching indefinitely…

I have the feeling I’m doing something wrong with timing the sends and receives. I do incorporate the 130us delay and have even added some extra time on the tx side, to be sure the rx is ready.

Any ideas on timing the switch from tx to rx on both sides better?

Here is a snippet of my send and recieve functions for the handshaking:

bool sendAck (bool ok, unsigned int maxSendingTime, bool setAsTX)
{
	unsigned char okData[28] = { '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1' };
	unsigned char falseData[28] = { '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2' };

	nrf24l01_clear_flush(); //clear interrupts and flush
	if (setAsTX)
	{
		nrf24l01_set_as_tx(); //change the device to an TX
		DelayUS(130); //wait for other receiver to come from standby to RX 
	}

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

	WriteTimer0(0); // reset timer
	while( !(nrf24l01_irq_pin_active() && (nrf24l01_irq_tx_ds_active() || nrf24l01_irq_max_rt_active()) ) && ReadTimer0() < maxSendingTime );
	ToggleLED1();

	if (nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active())
	{
		DelayUS(300); // allow time to recieve ACK and settle as TX again
		ToggleLED4();
		nrf24l01_clear_flush();
		return true; // transmit succeeded and was recieved
	}
	else
	{
		ToggleLED2();
		nrf24l01_clear_flush();
		return false; // unsuccessful transmit
	}
}

unsigned int recieveAck (unsigned int maxListeningTime, bool setAsRX)
{
	unsigned char okData[28] = { '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1' };
	unsigned char falseData[28] = { '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2' };
	unsigned char recievedData[28]  = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };

	nrf24l01_clear_flush(); //clear interrupts and flush
	if (setAsRX)
	{
		nrf24l01_set_as_rx(true); //change the device to an RX
		DelayUS(200); //wait for receiver to come from standby to RX
	}	
	WriteTimer0(0); // reset timer

	while ( !(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()) && ReadTimer0() < maxListeningTime) // wait for packet
	ToggleLED1();
	if (nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()) // if recieved
	{
		DelayUS(300); // allow time to send ACK and settle as RX again
		nrf24l01_read_rx_payload(&recievedData, 28); // read into char
		if (okData[0] == recievedData[0] && okData[1] == recievedData[1]) // compare data
		{
			ToggleLED4();
			nrf24l01_clear_flush();
			return 1; // revieced an OK
		}
		if (falseData[0] == recievedData[0] && falseData[1] == recievedData[1])
		{
			//ToggleLED3();
			nrf24l01_clear_flush();
			return 0; // recieved a Not OK
		}
	}
	ToggleLED2();
	nrf24l01_clear_flush();
	return 2; // Did not recieve anything
}

I’ve made some ‘progress’. Ive narrowed it down and have one nrf sending and the other receiving continuously. When the nrf receives the packet it puts an ‘O’ on the UART. When not receiving it puts a ’ ’ (space) there. The output looks like follows: ```
OOOO OOOO OOOO

The space between the O's are exactly the same size every time. So somehow the receiver is receiving a lot of nothings. A strange thing is that there is a timer on the receiver, so it waits almost 20ms before printing the ' '. but when the O's come in, the spaces between them take way less time... I do not see how that can happen... When there is no transmitter you can see them being written on the screen, when receiving the O's you cannot...

Also sometimes the receiver puts out crap when is has received something other than one of my packets. Which is very weird.... I don't know how that can happen. SPI problems?? Echoes?

So these following functions run on the 2 nrf's. They are configured right (I checked the status registers). All default values, exept transmitting power (-12db), pipes (only pipe 0 active, with AA) and ARD delay (500us).

Anybody have any ideas???

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 (!ok)
{
	nrf24l01_write_tx_payload(falseData, 28, true); // Send a NOT OK
}
else
{
	nrf24l01_write_tx_payload(okData, 28, true); // Send an OK
}

WriteTimer0(0); // reset timer
while( !(nrf24l01_irq_pin_active() && (nrf24l01_irq_tx_ds_active() || nrf24l01_irq_max_rt_active()) ) && ReadTimer0() < maxSendingTime ); // max 1.4ms

if (nrf24l01_irq_tx_ds_active())
{
	DelayUS(130); // avoid timing issues??
	return true; // transmit succeeded and was recieved
}
else
{
	DelayUS(130); // avoid timing issues??
	return false; // unsuccessful transmit
}

}

unsigned int recieveAck (unsigned int maxListeningTime, bool setAsRX)
{
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’ };
unsigned char recievedData[28] = { ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’, ‘x’ };
int i;

nrf24l01_clear_flush(); //clear interrupts and flush
WriteTimer0(0); // reset timer

while ( !(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()) && ReadTimer0() < maxListeningTime) // wait for packet, 18ms
if (nrf24l01_irq_rx_dr_active()) // if recieved
{
	nrf24l01_irq_clear_all(); //clear interrupts
	nrf24l01_read_rx_payload(&recievedData, 28); // read into char
	DelayUS(630); // allow time to send ACK and settle as RX again (= ARD time + 130us to be on the safe side)
	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++) // Something recieved which is not a OK or NOT OK, so put it on the uart to see what's going on.
	{
		UARTIntPutChar(recievedData[i]);
	}
	PORTAbits.RA0 = 0;
	return 3;
}
UARTIntPutChar(' ');
return 2; // Did not recieve anything

}

One other question. I couldn’t find anywhere in the datasheet how long it takes to change a channel.

At the moment I use a 300 us delay after changing it. Any comments on that?