(SOLVED) AtMega32a + Nrf24L01+ Nrf is so poorly documented need help.

Go To Last Post
27 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have read the datasheet of Nrf well not as whole but important parts, like register maps payloads addresses etc. I have no problem with the atmega and SPI communication. The problem is Nrf is so poorly documented it has not even given any example timing table about how to send a code or receive it. All i could find was on internet thx to this guys post http://gizmosnack.blogspot.com.t...

 

http://gizmosnack.blogspot.com.tr/2013/04/tutorial-nrf24l01-and-avr.html

 

I followed this guide first i tried his code but atmel studio gave me errors about type conversions. I understand his code but it just did not work so i wanted to write my own. Mine is nearly same as his code but only with 1 byte payload. I want to send a byte with transmitter and the receiver will receive it and increment PORTD with +1 that is it. If i can achive this simple task rest will come up with no problems. I can read registers with no problem at all NRFs are connected right. It has been 2 days and i am in need of help... 

 

here is my nrf setup code i only change CONFIG register to 0x1F and 0x1E for transmitting/receiving 

 

 /*
 * my nrf setup tx.c
 *
 * Created: 1/6/2018 5:41:48 AM
 * Author : rbkyo
 */
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "nrf.h"

void Init_SPI()
{
	DDRB|=_BV(3);  //chip enable
	DDRB|=_BV(4);  //ss pin c?k?s
	DDRB|=_BV(5);  //mosi pin cikis
	DDRB|=_BV(7);  //sck pin ç?k??
	DDRB&=~_BV(6); //miso pin giri?
	SPCR|=(1<<SPE)|(1<<MSTR)|(1<SPR0);  //enable spi as master
	SPCR&=~_BV(SPI2X)&~_BV(SPR1); //set clock rate but not too important
	PORTB|=_BV(4); // SS high to start with
	PORTB&=~_BV(3);

}

unsigned char spi_tranceiver (unsigned char data)
{
	// Load data into the buffer
	SPDR = data;

	//Wait until transmission complete
	while(!(SPSR & (1<<SPIF)));   // Return received data

	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
		_delay_ms(10);
		PORTB&=~_BV(4);
		spi_tranceiver(R_REGISTER+reg);
		_delay_ms(10);
		reg=spi_tranceiver(NOP);
		_delay_ms(10);
		PORTB|=_BV(4);
		return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_ms(10);
	PORTB&=~_BV(4);
	_delay_ms(10);
	spi_tranceiver(W_REGISTER+reg);
	_delay_ms(10);
	spi_tranceiver(data);
	_delay_ms(10);
	PORTB|=_BV(4);
}

void Init_nrf(void)
{
	_delay_ms(100);

	Write_byte(EN_AA,0x01); //Enable auto acknowledgement Transmiter gets automatic response For data pipe 0

	Write_byte(EN_RXADDR,0x01); //enable data pipe 0

    Write_byte(SETUP_AW,0x03);  //adress width is 5 byte

	Write_byte(RF_CH, 0x01);  //2.401GHz

	Write_byte(RF_SETUP,0x07);  // 1Mbps 00gain

		_delay_ms(10);
		PORTB&=~_BV(4);
		_delay_ms(10);
		spi_tranceiver(W_REGISTER+RX_ADDR_P0); //setup p0 pipe adress for receiveing
		_delay_ms(10);
		spi_tranceiver(0x01);
		_delay_ms(10);
		spi_tranceiver(0x02);
		_delay_ms(10);
		spi_tranceiver(0x03);
		_delay_ms(10);
		spi_tranceiver(0x04);
		_delay_ms(10);
		spi_tranceiver(0x05);
		_delay_ms(10);
		PORTB|=_BV(4);

			_delay_ms(10);
			PORTB&=~_BV(4);
			_delay_ms(10);
			spi_tranceiver(W_REGISTER+TX_ADDR);  //transmitter adress
			_delay_ms(10);
			spi_tranceiver(0x01);
			_delay_ms(10);
			spi_tranceiver(0x02);
			_delay_ms(10);
			spi_tranceiver(0x03);
			_delay_ms(10);
			spi_tranceiver(0x04);
			_delay_ms(10);
			spi_tranceiver(0x05);
			_delay_ms(10);
			PORTB|=_BV(4);

	Write_byte(RX_PW_P0,0x01); //only 1 byte for transceiving

	Write_byte(SETUP_RETR,0x2F); //750us delay with 15 retries

	Write_byte(CONFIG,0x1E); //boot up nrf as transmitter MAX_RETR interrupt disabled

	_delay_ms(100);

}

void Flush_tx(void)
{
		_delay_ms(10);
		PORTB&=~_BV(4);
		_delay_ms(10);
		spi_tranceiver(FLUSH_TX);
		_delay_ms(10);
		PORTB|=_BV(4);
		_delay_ms(10);
}

void Flush_rx(void)
{
			_delay_ms(10);
			PORTB&=~_BV(4);
			_delay_ms(10);
			spi_tranceiver(FLUSH_RX);
			_delay_ms(10);
			PORTB|=_BV(4);
			_delay_ms(10);
}

void transmit_data(unsigned char tdata)
{
	Flush_tx();
	Write_byte(W_TX_PAYLOAD,tdata);
	_delay_ms(10);
	PORTB|=_BV(3);
	_delay_ms(20);
	PORTB&=~_BV(3);
	_delay_ms(10);
}

void reset(void)
{
	_delay_ms(10);
	PORTB&=~_BV(4);
	_delay_ms(10);
	spi_tranceiver(STATUS);
	_delay_ms(10);
	spi_tranceiver(0x70);   //reset all IRQ after every succesfull transmit and receive
	_delay_ms(10);
	PORTB|=_BV(4);
}

int main(void)
{
    DDRD=0xff;
	PORTD=0x00;
	Init_SPI();
	Init_nrf();
    unsigned char data=40;

    while (1)
    {
        transmit_data(data);
		_delay_ms(500);
		reset();

    }
}

and here is my receive part setting up nrf is same with tx Except for CONFIG reg

 

int main(void)
{
    DDRD=0xff;
	PORTD=0x00;
	Init_SPI();
	Init_nrf();
	unsigned char data;

    while (1)
    {
		  receive_payload();
          spi_tranceiver(R_RX_PAYLOAD);
		  _delay_ms(10);
		  data=spi_tranceiver(NOP);
		  if(data==40)
		  {
			  PORTD=PORTD+1;
		  }
		  _delay_ms(10);
		  reset();
    }
}

I am not asking for any code from you. If any one have gone through this i need some good examples of setting NRF. I have worked with 433MHz transmitter/receiver pairs they worked fine because they are just plain transmitters with no registries. 

 

Last Edited: Tue. Nov 26, 2019 - 06:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what does your

receive_payload();

do?

 

Either way, here's how you receive stuff:

set the CE pin

Wait for the  IRQ pin to go low
read the status register to determine if the rx_dr bit is set and if so which pipe's payload is currently in the fifo
read the rx_pl_wid register to determine how long the received payload is
read as many bytes as there are in the fifo

clear the rx_dr bit in the status register
 

on the sending side, you should check which flags go high one you set CE. If it isn't TX_DS, you're doing it wrong.
And it helps a lot to not use the auto ack feature in the beginning. Just write your payload to W_TX_PAYLOAD_NO_ACK

 

If you can't get it to work with these hints, I might find the time tomorrow to write an example code for my library. Without it, it would be hard to understand how to use it

 

Edit: oh and you should either correctly set the payload length in RX_PW_Px registers or activate dynamic payload length.

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

Last Edited: Sun. Jan 7, 2018 - 06:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It sets CE high for certain time then i check the RX_payload

From my understanding data_width is set before hand and not have to be checked while checking Rx_payload and Tx payload is always 32 byte witdh and transmits whatever there is in it. Example i wrote 1 byte and transmit, it transmits 1 byte if i write 2 byte and transmit, it transmits 2 byte only etc.

I first listen for data then stop listening and get 1 data byte from rx_payload then reset all the flags then loop goes on . Tx side transmit every 500ms.

And i found a mistake of mine in reset i forgot to write W_REGISTER for STATUS for reseting IRQ.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As you said i disabled autoack by setting EN_AA 0x00 IRQ pin never goes low. I have 500ms delay before resetting it so it is not a quick blink. Apparently as i have guessed, probably i am doing something wrong while setting nrf or transmitting payload. I will not do anything with receiver until i see this IRQ pin goes low as you said.

I need step by step instructions :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have a specific reason for jusing nRF24L01+ ?

Long time ago I bought some (and got them to work) but I really did not like them. Weeks of headackes to get them to work.

Nordic makes you jump trhough some convoluted loops.

The whole "6 pipe" model in those nRF's is just garbage and it would have been much easier and straight forward if they ofloaded that to the programmer.

On the other hand, there is no collison avoidance, which would have been really usefull.

There are also Chines clones which are not completely function compatible.

 

Have you looked at some libraries for Arduino / github / platformio?

 

I also bought some RFM69 boards, but haven't used them yet.

They seem to have a much more logical mix of complexity / simplicity / ease of use / functionality.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yorem_kastor wrote:
From my understanding data_width is set before hand and not have to be checked while checking Rx_payload and Tx payload is always 32 byte witdh and transmits whatever there is in it. Example i wrote 1 byte and transmit, it transmits 1 byte if i write 2 byte and transmit, it transmits 2 byte only etc.

There are two modes:

The Version of the chip wit a "+" at the end supports dynamic payload. In this mode, it just sends as many bytes as there are in the payload register. The MCU at the receving side needs to know how many bytes it has to read from the NRF chip, so there is a register for retrieving that number (RX_PL_WID). This mode is not active by default. It has to be activated by setting a total of three bits: EN_DPL in the FEATURE register, DPL_Px in DYNPD and ENAA_Px in ENAA.

In the default mode, you have to set the number of bytes in the RX_PW_Px registers in both the receiver and the transmitter.

yorem_kastor wrote:
i disabled autoack by setting EN_AA 0x00

That's not what I meant. To send a payload without requesting the acknowledgement, you need to write it using W_TX_PAYLOAD_NO_ACK SPI command. EN_AA has not the desired effect. It is used to enable the acknowledgment on the receiver side. You should leave it enable to use the Enhanced Shockburst mode of the NRF chip.

 

I recommend this configuration:

CONFIG     = CONFIG_PWR_UP|CONFIG_EN_CRC|CRCO
SETUP_RETR = SETUP_RETR_ARD_4000_us|10
RF_SETUP   = RF_SETUP_RF_DR_LOW|RF_SETUP_RF_PWR_0dBM
EN_AA      = EN_AA_ENAA_P0
DYNPD      = DYNPD_DPL_P0
EN_RXADDR  = ERX_P0
FEATURE    = FEATURE_EN_DPL|FEATURE_EN_ACK_PAY|FEATURE_EN_DYN_ACK

Sorry for the weird notation, I adapted it from my own library code. But you get the idea. Of course, you need to set the PRIM_RX bit the CONFIG register on the receiving side. And you may want to change the channel, too. Until everything works, you better leave the addresses alone. The default ones are chosen carefully by the maker of the chip.

And one other very important point: You almost certainly have Chinese clones of the NRF chip. These have subtle error: They discard repeated payloads in the receiving mode. So you need to send something else every time or your receiver will only capture the first transmission!

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No specific reason i picked what is available on market. I tried few code libraries but none worked. I do not know if mine is a Chinese replica or not it is a module so probably Chinese replica. If you know any better chips on 2.4 GHz range which is easier to setup and use with less pins could you tell me?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When interrupt occurs on IRQ pin does it stay low or is it a fast off/on blink. I am trying to see if i manage to send something to air at least using Tx side only.

...and with your reply here is what i will do. I only want to send 1 byte so i set RX_PW_Px to 0x01 leave FEAUTRE registers untouched make necessary setup to nrf which i already posted in code before.Flush tx, write my data using W_TX_PAYLOAD_NO_ACK set ce high for 10 ms then low and see if IRQ pin goes low?
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i enabled EN_DYN_ACK command

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I managed to transmit data at last. IRQ pin goes low and high with 500ms delays. I will return to you when i tidy things up with my whole working code, your recommendations helped me a lot thx :). 

I found few more mistakes like trying to write to TX buffer with reg+write command i fixed that too. I also enabled all interrupt just for the sake of seeing IRQ pin goes low. thx again one more step taken to make this thing work

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yorem_kastor wrote:
If you know any better chips on 2.4 GHz range which is easier to setup and use with less pins could you tell me?

 

I have been using these with great success:

 

https://www.digi.com/products/xb...

 

And these:

 

https://www.digi.com/products/xb...

 

 

They are a little pricey, but they connect to your USART and work right out of the box.  You use the programming software and a Grove board you can get from Sparkfun to tweak the modules the way you want.

teh Sparkfun Grove Board:

https://www.sparkfun.com/product...

 

JIm

 

Even Better deal:

https://www.mouser.com/productde...

 

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Mon. Jan 8, 2018 - 03:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made transmitter transmit with EN_AA for data pipe 0 disabled send and receive interrupts enabled max_retry interrupt disabled. When i transmit data for every 500ms it transmits and IRQ pin led blinks.

I made receiver work it blinks when it received some data. When i unplug the transmitter receiver stops receiving so i m sure it is receiving data from transmitter.

But here is the problem leds on receiver never increments. I send a value of 40 from transmitter and when receiver picks this value it should increment portd by 1 but it does not. Here are my fixed up tidied up codes for transmitter and receiver 

 

TX

 /*
 * my nrf setup tx.c
 *
 * Created: 1/6/2018 5:41:48 AM
 * Author : rbkyo
 */ 
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "nrf.h"

void Init_SPI()
{
	DDRB|=_BV(3);  //chip enable
	DDRB|=_BV(4);  //ss pin c?k?s
	DDRB|=_BV(5);  //mosi pin cikis
	DDRB|=_BV(7);  //sck pin ç?k??
	DDRB&=~_BV(6); //miso pin giri?
	SPCR|=(1<<SPE)|(1<<MSTR)|(1<SPR0);  //enable spi as master
	SPCR&=~_BV(SPI2X)&~_BV(SPR1); //set clock rate but not too important
	PORTB|=_BV(4); // SS high to start with
	PORTB&=~_BV(3);
	
}

unsigned char spi_tranceiver (unsigned char data)
{
	// Load data into the buffer
	SPDR = data;
	
	//Wait until transmission complete
	while(!(SPSR & (1<<SPIF)));   // Return received data

	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
		_delay_ms(10);
		PORTB&=~_BV(4);
		spi_tranceiver(R_REGISTER+reg);
		_delay_ms(10);
		reg=spi_tranceiver(NOP);
		_delay_ms(10);
		PORTB|=_BV(4);
		return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_ms(10);
	PORTB&=~_BV(4);
	_delay_ms(10);
	spi_tranceiver(W_REGISTER+reg);
	_delay_ms(10);
	spi_tranceiver(data);
	_delay_ms(10);
	PORTB|=_BV(4);
}

void Init_nrf(void)
{
	_delay_ms(100);
	
	Write_byte(EN_AA,0x01); //Enable auto acknowledgement Transmiter gets automatic response For data pipe 0
	
	Write_byte(EN_RXADDR,0x01); //enable data pipe 0

    Write_byte(SETUP_AW,0x03);  //adress width is 5 byte
	
	Write_byte(RF_CH, 0x09);  //2.409GHz
	
	Write_byte(RF_SETUP,0x07);  // 1Mbps 00gain
	
	Write_byte(FEATURE,0b00000001);  //enable W_TX_PAYLOAD_NOACK command
	
		_delay_ms(10);
		PORTB&=~_BV(4);
		_delay_ms(10);
		spi_tranceiver(W_REGISTER+RX_ADDR_P0); //setup p0 pipe adress for receiveing
		_delay_ms(10);
		spi_tranceiver(0x01);
		_delay_ms(10);
		spi_tranceiver(0x02);
		_delay_ms(10);
		spi_tranceiver(0x03);
		_delay_ms(10);
		spi_tranceiver(0x04);
		_delay_ms(10);
		spi_tranceiver(0x05);
		_delay_ms(10);
		PORTB|=_BV(4);
		
			_delay_ms(10);
			PORTB&=~_BV(4);
			_delay_ms(10);
			spi_tranceiver(W_REGISTER+TX_ADDR);  //transmitter adress 
			_delay_ms(10);
			spi_tranceiver(0x01);
			_delay_ms(10);
			spi_tranceiver(0x02);
			_delay_ms(10);
			spi_tranceiver(0x03);
			_delay_ms(10);
			spi_tranceiver(0x04);
			_delay_ms(10);
			spi_tranceiver(0x05);
			_delay_ms(10);
			PORTB|=_BV(4);
		
	Write_byte(RX_PW_P0,0x01); //only 1 byte for transceiving
	
	Write_byte(SETUP_RETR,0x2F); //750us delay with 15 retries
	
	Write_byte(CONFIG,0x1E); //boot up nrf as transmitter MAX_RETR interrupt disabled
	
	_delay_ms(100);
				
}

void Flush_tx(void)
{
		_delay_ms(10);
		PORTB&=~_BV(4);
		_delay_ms(10);
		spi_tranceiver(FLUSH_TX);
		_delay_ms(10);
		PORTB|=_BV(4);
		_delay_ms(10);
}

void Flush_rx(void)
{
			_delay_ms(10);
			PORTB&=~_BV(4);
			_delay_ms(10);
			spi_tranceiver(FLUSH_RX);
			_delay_ms(10);
			PORTB|=_BV(4);
			_delay_ms(10);
}

void transmit_data(unsigned char tdata)
{
	Flush_tx();
    PORTB&=~_BV(4);
	_delay_ms(10);
	spi_tranceiver(W_TX_PAYLOAD);
	_delay_ms(10);
	spi_tranceiver(tdata);
	_delay_ms(10);
	PORTB|=_BV(4);
	_delay_ms(10);
	PORTB|=_BV(3);
	_delay_us(20);
	PORTB&=~_BV(3);
	_delay_ms(10);
}

void reset(void)
{
	_delay_ms(10);
    Write_byte(STATUS,0x70);   //reset all IRQ after every succesfull transmit and receive
	_delay_ms(10);
}

int main(void)
{
    DDRD=0xff;
	PORTD=0x00;
	Init_SPI();
	Init_nrf();
    unsigned char my_data=40;
	
    while (1) 
    {
        	
        transmit_data(my_data);
		_delay_ms(500);
		reset();
		
    }
}

RX

 /*
 * my nrf setup tx.c
 *
 * Created: 1/6/2018 5:41:48 AM
 * Author : rbkyo
 */ 
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "nrf.h"

void Init_SPI()
{
	DDRB|=_BV(3);  //chip enable
	DDRB|=_BV(4);  //ss pin c?k?s
	DDRB|=_BV(5);  //mosi pin cikis
	DDRB|=_BV(7);  //sck pin ç?k??
	DDRB&=~_BV(6); //miso pin giri?
	SPCR|=(1<<SPE)|(1<<MSTR)|(1<SPR0);  //enable spi as master
	SPCR&=~_BV(SPI2X)&~_BV(SPR1); //set clock rate but not too important
	PORTB|=_BV(4); // SS high to start with
	PORTB&=~_BV(3);
	
}

unsigned char spi_tranceiver (unsigned char data)
{
	// Load data into the buffer
	SPDR = data;
	
	//Wait until transmission complete
	while(!(SPSR & (1<<SPIF)));   // Return received data

	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
		_delay_ms(10);
		PORTB&=~_BV(4);
		spi_tranceiver(R_REGISTER+reg);
		_delay_ms(10);
		reg=spi_tranceiver(NOP);
		_delay_ms(10);
		PORTB|=_BV(4);
		return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_ms(10);
	PORTB&=~_BV(4);
	_delay_ms(10);
	spi_tranceiver(W_REGISTER+reg);
	_delay_ms(10);
	spi_tranceiver(data);
	_delay_ms(10);
	PORTB|=_BV(4);
}

void Init_nrf(void)
{
	_delay_ms(100);
	
	Write_byte(EN_AA,0x01); //Enable auto acknowledgement Transmiter gets automatic response For data pipe 0
	
	Write_byte(EN_RXADDR,0x01); //enable data pipe 0

    Write_byte(SETUP_AW,0x03);  //adress width is 5 byte
	
	Write_byte(RF_CH, 0x09);  //2.409GHz
	
	Write_byte(RF_SETUP,0x07);  // 1Mbps 00gain
	
	Write_byte(FEATURE,0b00000001);
	
		_delay_ms(10);
		PORTB&=~_BV(4);
		_delay_ms(10);
		spi_tranceiver(W_REGISTER+RX_ADDR_P0); //setup p0 pipe adress for receiveing
		_delay_ms(10);
		spi_tranceiver(0x01);
		_delay_ms(10);
		spi_tranceiver(0x02);
		_delay_ms(10);
		spi_tranceiver(0x03);
		_delay_ms(10);
		spi_tranceiver(0x04);
		_delay_ms(10);
		spi_tranceiver(0x05);
		_delay_ms(10);
		PORTB|=_BV(4);
		
			_delay_ms(10);
			PORTB&=~_BV(4);
			_delay_ms(10);
			spi_tranceiver(W_REGISTER+TX_ADDR);  //transmitter adress 
			_delay_ms(10);
			spi_tranceiver(0x01);
			_delay_ms(10);
			spi_tranceiver(0x02);
			_delay_ms(10);
			spi_tranceiver(0x03);
			_delay_ms(10);
			spi_tranceiver(0x04);
			_delay_ms(10);
			spi_tranceiver(0x05);
			_delay_ms(10);
			PORTB|=_BV(4);
		
	Write_byte(RX_PW_P0,0x01); //only 1 byte for transceiving
	
	Write_byte(SETUP_RETR,0x2F); //750us delay with 15 retries
	
	Write_byte(CONFIG,0x1F); //boot up nrf as receiver MAX_RETR interrupt disabled
	
	_delay_ms(100);
				
}

void Flush_tx(void)
{
		_delay_ms(10);
		PORTB&=~_BV(4);
		_delay_ms(10);
		spi_tranceiver(FLUSH_TX);
		_delay_ms(10);
		PORTB|=_BV(4);
		_delay_ms(10);
}

void Flush_rx(void)
{
			_delay_ms(10);
			PORTB&=~_BV(4);
			_delay_ms(10);
			spi_tranceiver(FLUSH_RX);
			_delay_ms(10);
			PORTB|=_BV(4);
			_delay_ms(10);
}

void transmit_data(unsigned char tdata)
{
	Flush_tx();
    PORTB&=~_BV(4);
	_delay_ms(10);
	spi_tranceiver(W_TX_PAYLOAD);
	_delay_ms(10);
	spi_tranceiver(tdata);
	PORTB|=_BV(4);
	_delay_ms(10);
	PORTB|=_BV(3);
	_delay_us(50);
	PORTB&=~_BV(3);
	_delay_ms(10);
}

void reset(void)
{
	_delay_ms(10);
    Write_byte(STATUS,0x70);   //reset all IRQ after every succesfull transmit and receive
	_delay_ms(10);
}

int main(void)
{
    DDRD=0xff;
	PORTD=0x00;
	Init_SPI();
	Init_nrf();
    unsigned char my_data=40;
	
    while (1) 
    {
        	PORTB|=_BV(3);        //start listening for data
			_delay_ms(1000);
			PORTB&=~_BV(3);       //stop listening 
            PORTD=Read_Byte(R_RX_PAYLOAD);  			
			Flush_rx();
			reset();

		
    }
}

 

When i disable EN_AA does it matter what i write to SETUP_RETR for both rx and tx?

 

Edit:

 

I enabled EN_AA for both 0x01, and they work fine with auto acknowledge when i keep receiver mcu on reset state transmitter IRQ stops blinking. I also tried to give received value to PORTD and it is just 0x01 (int 1)all the time not 40 the value i want to see.

 

LAST EDIT 

I slapped myself in face the whole problem was reading the RX register with wrong command RX_PW_P0 changed that to R_RX_PAYLOAD and now i received the correct data took me 2 hours :O.

I also edited codes in this post and it is working now. It sends 1 byte static payload with EN_AA enabled for data pipe 0 MAX_retr=disabled receive_int=enabled transmit_int=enabled and rest of the settings are commented on init_nrf. From now on i ll try different approaches for this chip as the datasheet is so poorly documented. I ll try different setups to fully understand and grasp what datasheet has not given us. I am willing to help anyone who is new to this chip. I am not setting the topic as solved i might have more questions later on.

Thx anyone who participated in this topic.

 

Last Edited: Mon. Jan 8, 2018 - 09:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We once had an idea to use those modules for our SMART GRID project to transmit power usage of appliances to main grid but we could not make it to that point. Reason i chose these are because they are cheap and readily available elsewhere. Listed modules are present here but they are nearly x20 times more expensive then nrf24l01+. I live in a country(Turkey) where most products are Chinese replica or do not even exist in local stores, ordering them from internet is just plain pain for few products. Waiting time plus TURKEYs SPECIAL TAXES ON EVERYTHING makes components 2x the price they are available on internet. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a stock of the nRF24L01+ modules that I have wanted to use, but never had the time to fight with them.  From reading threads like this, reinforces why too.

 

Community member "TORBY" has done some work with these modules.  He might be able to help out....Wonder where he is these days as a matter of fact.

 

Jim

 

Heres something from Torby's website:

http://www.barefootelectronics.c...

 

 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Mon. Jan 8, 2018 - 03:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wonder where he is these days as a matter of fact.

Off buying a pair of warm shoes or huggboots.......

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I use the NRF 24L01+ modules for half a year now without trouble (once I got the basics working using the datasheet). I remember it took me a couple of days before I got it working because I had the Payload Length not setup correctly.

My code (for PSOC5lp) is attached, sorry I cannot provide you with the complete code. For debugging it is very usefull to have a routine such as printf_NrfSettings. 

 

Patrick

 

Attachment(s): 

Last Edited: Mon. Jan 8, 2018 - 08:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:

Wonder where he is these days as a matter of fact.

Off buying a pair of warm shoes or huggboots.......

 

Nope. Still barefoot. Having trouble concentrating on things and need to get a web site built for a guy. Playing with a drone : https://www.youtube.com/watch?v=... (Was a Christmas present) You can't see in the video, but I was barefoot as expected.

 

Went to Illinois to see family and friends at Christmas. Wanted to get to know my daughter-in-law better and see Allister. Found out more than I wanted to know about daughter-in-law who forbade anyone from Caleb's family seeing Allister. Pray for Caleb and Allister.

 

Nordics are easy to work. Just grab any simple code and graft in your own SPI routines. Find my code and explanation at http://barefootelectronics.com . One thing to remember: Almost all of them are counterfeit. The counterfeits work well as long as you remember that the auto acking feature has a bug and if you transmit the same packet over and over, the receiver will think it's a retransmition of the same packet where the ack got missed and discard it. I just add a counter byte to the packet to make sure this doesn't happen. One thing I haven't figured out is how to put payload in the ack packet.

 

Forget the 6 node network thingy. It's not worth the hassle. To make a network, just assign each node a unique address. Let the nodes mainly listen to their assigned addresses. To send a message to another node, switch to that node's address, send the packet and switch back to assigned address as soon as you get the ack. For simple two point communication, it's even easier, just set both to the same address and they'll happily send each other packets.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby wrote:
One thing I haven't figured out is how to put payload in the ack packet

 

Just write the payload in the receiving module using the W_ACK_PAYLOAD command. Of course, auto ack must be enabled and you must send a normal payload for this to work. If the receiver gets a no-ack payload, it holds the ack pyload until a normal payload is received and acknowledged. The no-ack payload is received normally.

 

If anyone wants it, I could give you a little project I made but never completely finished. It's a GUI for the NRF modules that uses a UART connection and an AVR as bridge. Most things work but not everything. All registers can be written and read and payloads can be sent and received. I could rewrite the MCU code so that it works on an Arduino. The GUI is written in C++ using the Qt framework, so it runs on Windows and Linux(it must be recompiled of course). On Mac it should run too, but I never tested that.

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I took the liberty of attaching my Project.

 

If you want to get it to work, here's how:

The NrfCommanderForNano ZIP contains the complete Atmel Studio project including the hex. It runs on an Arduino Nano(Uno probably too) with the NRF connected as follows:

A0: CE

A1:CSN

A2:SCK

A3:MOSI

A4:MISO

A5:IRQ

Note that the NRF module must be connected to the 3.3V output, not 5V!

 

The other ZIP contains the Qt project. It does not contain an executable, you have to download the Qt Creator and compile it yourself. This is for security and compatibility reasons. Qt is free for non-commercial use under the LGPL v3 license.
You can download it here: https://download.qt.io/official_...

 

The GUI should be more or less self explanatory. The default port settings are correct for the attached hex file.

The screenshot shows two instances of the program with two modules connected. The log shows that a message was sent from the right module and received and acknowledged from the left one.

Attachment(s): 

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh and just so it's said: This code comes with no warranty whatsoever. It is not fit for any purpose. It is not finished and written very badly. I'm sorry for any inconvenience.

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made mine work but when i go far away it still reads the same value from RX_fifo even when i flush it or stop transmitter transmitting.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yorem_kastor wrote:
I made mine work but when i go far away it still reads the same value from RX_fifo even when i flush it or stop transmitter transmitting.

Why dont you use the STATUS register to see IF there is data in the fifo ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have got everything in working state now i am able to send 1 byte every packet using static mode. I reconfigured timing tables and fixed some more things. My mistakes from last one were using atmel studio libraries that i did not know what is happening in background (Examples Setting PORTD=PORTD+1 causing to increment portd even if i do not receive anything, using If_bit_clear(PORTB,x) causing 2 times click to send data instead of 1), i used wrong timings at some lines, example to this using 10us after transmitting a packet and quickly reseting nrf. with retry on fail it takes longer then 10us sometimes to transmit a packet therefor IRQ pin stays in wrong state or chip stops working. Anyway here is the last state of code. 

 

TX

 /*
 * my nrf setup tx.c
 *
 * Created: 1/6/2018 5:41:48 AM
 * Author : rbkyo
 */ 
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "nrf.h"

void Init_SPI()
{
	DDRB|=_BV(3);  //chip enable
	DDRB|=_BV(4);  //ss pin c?k?s
	DDRB|=_BV(5);  //mosi pin cikis
	DDRB|=_BV(7);  //sck pin ç?k??
	DDRB&=~_BV(6); //miso pin giri?
	SPCR|=(1<<SPE)|(1<<MSTR)|(1<SPR0);  //enable spi as master
	SPCR&=~_BV(SPI2X)&~_BV(SPR1); //set clock rate but not too important
	PORTB|=_BV(4); // SS high to start with
	PORTB&=~_BV(3);
	
}

unsigned char spi_tranceiver (unsigned char data)
{
	// Load data into the buffer
	SPDR = data;
	
	//Wait until transmission complete
	while(!(SPSR & (1<<SPIF)));   // Return received data

	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
		_delay_us(10);
		PORTB&=~_BV(4);
		spi_tranceiver(R_REGISTER+reg);
		_delay_us(10);
		reg=spi_tranceiver(NOP);
		_delay_us(10);
		PORTB|=_BV(4);
		return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_us(10);
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(W_REGISTER+reg);
	_delay_us(10);
	spi_tranceiver(data);
	_delay_us(10);
	PORTB|=_BV(4);
}

void Init_nrf(void)
{
	_delay_ms(100);
	
	Write_byte(EN_AA,0x01); //Enable auto acknowledgement Transmiter gets automatic response For data pipe 0
	
	Write_byte(EN_RXADDR,0x01); //enable data pipe 0

    Write_byte(SETUP_AW,0x03);  //adress width is 5 byte
	
	Write_byte(RF_CH, 0x09);  //2.409GHz
	
	Write_byte(RF_SETUP,0x07);  // 1Mbps 00gain
	
	Write_byte(FEATURE,0b00000001);  //enable W_TX_PAYLOAD_NOACK command
	
		_delay_us(10);
		PORTB&=~_BV(4);
		_delay_us(10);
		spi_tranceiver(W_REGISTER+RX_ADDR_P0); //setup p0 pipe adress for receiveing
		_delay_us(10);
		spi_tranceiver(0x01);
		_delay_us(10);
		spi_tranceiver(0x02);
		_delay_us(10);
		spi_tranceiver(0x03);
		_delay_us(10);
		spi_tranceiver(0x04);
		_delay_us(10);
		spi_tranceiver(0x05);
		_delay_us(10);
		PORTB|=_BV(4);
		
			_delay_us(10);
			PORTB&=~_BV(4);
			_delay_us(10);
			spi_tranceiver(W_REGISTER+TX_ADDR);  //transmitter adress 
			_delay_us(10);
			spi_tranceiver(0x01);
			_delay_us(10);
			spi_tranceiver(0x02);
			_delay_us(10);
			spi_tranceiver(0x03);
			_delay_us(10);
			spi_tranceiver(0x04);
			_delay_us(10);
			spi_tranceiver(0x05);
			_delay_us(10);
			PORTB|=_BV(4);
		
	Write_byte(RX_PW_P0,0x01); //only 1 byte for transceiving
	
	Write_byte(SETUP_RETR,0x2F); //750us delay with 15 retries
	
	Write_byte(CONFIG,0x1E); //boot up nrf as transmitter MAX_RETR interrupt disabled
	
	_delay_ms(100);
				
}

void Flush_tx(void)
{
		_delay_us(10);
		PORTB&=~_BV(4);
		_delay_us(10);
		spi_tranceiver(FLUSH_TX);
		_delay_us(10);
		PORTB|=_BV(4);
		_delay_us(10);
}

void Flush_rx(void)
{
			_delay_us(10);
			PORTB&=~_BV(4);
			_delay_us(10);
			spi_tranceiver(FLUSH_RX);
			_delay_us(10);
			PORTB|=_BV(4);
			_delay_us(10);
}

void transmit_data(unsigned char tdata)
{
	Flush_tx();
    PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(W_TX_PAYLOAD);
	_delay_us(10);
	spi_tranceiver(tdata);
	_delay_us(10);
	PORTB|=_BV(4);
	_delay_ms(10); //need 10ms before sending
	PORTB|=_BV(3);
	_delay_us(20);  //at least 10us not longer then 2ms
	PORTB&=~_BV(3);
	_delay_ms(10); //we need this delay before reseting because retry on fail time might take longer that 10us so 10ms is optional and the best 
}

void reset(void)
{
	_delay_us(10);
    Write_byte(STATUS,0x70);   //reset all IRQ after every succesfull transmit and receive
	_delay_us(10);
}

int main(void)
{
    DDRD=0xff;
	PORTD=0x00;
	DDRB&=~_BV(0);   //  input
	DDRB&=~_BV(1);   //  input
	Init_SPI();
	Init_nrf();
    unsigned char my_data;
	
    while (1) 
    {
        	if(bit_is_clear(PINB,0))
			{
				_delay_ms(100);  //voltage spide blocking time also to block accidental double sending
				my_data=40;
				transmit_data(my_data);
				reset();
			}
			if(bit_is_clear(PINB,1))
			{
				_delay_ms(100);   //voltage spike blocking time also to block acciedental double sending
				my_data=50;
				transmit_data(my_data);
				reset();
			}
			
    }
}

RX

 /*
 * my nrf setup tx.c
 *
 * Created: 1/6/2018 5:41:48 AM
 * Author : rbkyo
 */ 
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "nrf.h"

void Init_SPI()
{
	DDRB|=_BV(3);  //chip enable
	DDRB|=_BV(4);  //ss pin c?k?s
	DDRB|=_BV(5);  //mosi pin cikis
	DDRB|=_BV(7);  //sck pin ç?k??
	DDRB&=~_BV(6); //miso pin giri?
	SPCR|=(1<<SPE)|(1<<MSTR)|(1<SPR0);  //enable spi as master
	SPCR&=~_BV(SPI2X)&~_BV(SPR1); //set clock rate but not too important
	PORTB|=_BV(4); // SS high to start with
	PORTB&=~_BV(3);
	
}

unsigned char spi_tranceiver (unsigned char data)
{
	// Load data into the buffer
	SPDR = data;
	
	//Wait until transmission complete
	while(!(SPSR & (1<<SPIF)));   // Return received data

	return(SPDR);
}

unsigned char Read_Byte(unsigned char reg)
{
	_delay_us(10);
	PORTB&=~_BV(4);
	spi_tranceiver(R_REGISTER+reg);
	_delay_us(10);
	reg=spi_tranceiver(NOP);
	_delay_us(10);
	PORTB|=_BV(4);
	return reg;
}

void Write_byte(unsigned char reg, unsigned char data)
{
	_delay_us(10);
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(W_REGISTER+reg);
	_delay_us(10);
	spi_tranceiver(data);
	_delay_us(10);
	PORTB|=_BV(4);
}

void Init_nrf(void)
{
	_delay_ms(100);
	
	Write_byte(EN_AA,0x01); //Enable auto acknowledgement Transmiter gets automatic response For data pipe 0
	
	Write_byte(EN_RXADDR,0x01); //enable data pipe 0

	Write_byte(SETUP_AW,0x03);  //adress width is 5 byte
	
	Write_byte(RF_CH, 0x09);  //2.409GHz
	
	Write_byte(RF_SETUP,0x07);  // 1Mbps 00gain
	
	Write_byte(FEATURE,0b00000001);  //enable W_TX_PAYLOAD_NOACK command
	
	_delay_us(10);
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(W_REGISTER+RX_ADDR_P0); //setup p0 pipe adress for receiveing
	_delay_us(10);
	spi_tranceiver(0x01);
	_delay_us(10);
	spi_tranceiver(0x02);
	_delay_us(10);
	spi_tranceiver(0x03);
	_delay_us(10);
	spi_tranceiver(0x04);
	_delay_us(10);
	spi_tranceiver(0x05);
	_delay_us(10);
	PORTB|=_BV(4);
	
	_delay_us(10);
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(W_REGISTER+TX_ADDR);  //transmitter adress
	_delay_us(10);
	spi_tranceiver(0x01);
	_delay_us(10);
	spi_tranceiver(0x02);
	_delay_us(10);
	spi_tranceiver(0x03);
	_delay_us(10);
	spi_tranceiver(0x04);
	_delay_us(10);
	spi_tranceiver(0x05);
	_delay_us(10);
	PORTB|=_BV(4);
	
	Write_byte(RX_PW_P0,0x01); //only 1 byte for transceiving
	
	Write_byte(SETUP_RETR,0x2F); //750us delay with 15 retries
	
	Write_byte(CONFIG,0x1F); //boot up nrf as receiver MAX_RETR interrupt disabled
	
	_delay_ms(100);
	
}

void Flush_tx(void)
{
	_delay_us(10);
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(FLUSH_TX);
	_delay_us(10);
	PORTB|=_BV(4);
	_delay_us(10);
}

void Flush_rx(void)
{
	_delay_us(10);
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(FLUSH_RX);
	_delay_us(10);
	PORTB|=_BV(4);
	_delay_us(10);
}

void transmit_data(unsigned char tdata)
{
	Flush_tx();
	PORTB&=~_BV(4);
	_delay_us(10);
	spi_tranceiver(W_TX_PAYLOAD);
	_delay_us(10);
	spi_tranceiver(tdata);
	_delay_us(10);
	PORTB|=_BV(4);
	_delay_ms(10); //needs 10ms for transmitting
	PORTB|=_BV(3);
	_delay_us(20);  //at least 10us not longer then 2ms
	PORTB&=~_BV(3);
	_delay_ms(10);   //we need this delay before reseting because retry on fail time might take longer that 10us so 10ms is optional and the best 
}

void reset(void)
{
	_delay_us(10);
	Write_byte(STATUS,0x70);   //reset all IRQ after every succesfull transmit and receive
	_delay_us(10);
}


void Init_INT2(void)
{
	DDRB&=~_BV(2); //INT2 pin as input
	GICR|=_BV(INT2); //enable INT2
		MCUCSR&=~_BV(INT2);  //enable INT2 as falling edge triggered interrupt
		sei();   //enable global interrupts
}

ISR(INT2_vect)
{
	cli(); //disable global interrupts
	PORTB&=~_BV(3); //stop sending listening
	unsigned char my_data=Read_Byte(R_RX_PAYLOAD);
	if(my_data==40)
	{
		PORTD++;
	}
	if(my_data==50)
	{
		PORTD--;
	}
	Flush_rx(); //flush rx
	reset();  //reset IRQ
	sei();
	PORTB|=_BV(3);  //start listening again
}

int main(void)
{
    DDRD=0xff;
	PORTD=0x00;
	Init_SPI();
	Init_INT2();
	Init_nrf();
	Flush_rx();
	reset();
	PORTB|=_BV(3);  //start listening
    
	
    while (1) 
    {
        		
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you do busy waiting with the delays anyway, why not poll the IRQ line instead? This would guarantee that the delay is as short as possible but never too short. The NRF chip pulls the line low whenever something interesting happened, be that a successful or failed transmission or the reception of a packet. You can always just wait for the signal, check why it was sent and then reset the respecting flag. Because the status register is always sent to you no matter what command you send, you don't even have to waste an SPI transmission for checking the flags.

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working on a project also with the nrf and I cant get it running so this code is of much use for me. I just wanted to ask if the "nrf.h" library you're including is the one in the tutorial you mentioned? https://gizmosnack.blogspot.com/...

thanks in advance

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can you share the complete code

JANARDHAN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

See the note in your other thread: https://www.avrfreaks.net/forum/...

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Topic locked