This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Testing connection between atmega32 and nRF24L01 isn't working

I am trying to interface an atmega32 with an nRF24L01. I am trying to communicate between two nRF's. But before proceeding to that, I set out to test the SPI connection between the atmega and nRF.

/*
 * nRF Transmitter.c
 *
 * Created: 27-Jul-18 7:40:11 PM
 * Author : DELL
 */ 

#define F_CPU 1e6
#include <avr/io.h>
#include <util/delay.h>
#include "nRF24L01.h"

#define MOSI PB5
#define SCK PB7
#define CSN PB4 /* CSN == SS */
#define CE PD7 /* Chip Enable */

#define READ 0
#define WRITE 1

/* SPI - to communicate between Master MCU and Slave nRF */

void initSPI(){
	/* Set MOSI , SCK , CSN and CE as output */
	DDRB |= (1 < MOSI) | (1 << SCK) | (1 << CSN);
	DDRD |= (1 << CE);

	/* SPI Control Register */
	/* Enable SPI and set the MCU as master */
	/* SPI clock rate = f_osc / 4 ; SPR0 = 0 and SPR1 = 0 */
	SPCR |= (1 << SPE) | (1 << MSTR);

	/* CSN or SS is active low, as we'll not send anything to nRF yet, we're making it high */
	PORTB |= (1 << CSN);
	/* Making CE low, nothing to transmit or receive yet */
	PORTD &= ~(1 << CE);
}

/* SPI Transmit & Receive Module */
/* Communication between MCU and nRF */

unsigned char SPITransceiver(unsigned char data){
	SPDR = data; // load data in SPDR to start transmission
	while(!(SPSR & (1 << SPIF))); // Transmit data until the SPIF flag is set
	return SPDR; // return the received data
}

/* Read the status of a register */

uint8_t getRegister(uint8_t reg){
	_delay_us(10);
	PORTB &= ~(1 << CSN); // making CSN or SS low, nRF starts to listen for command, MCU will send command to slave nRF
	_delay_us(10);
	SPITransceiver(R_REGISTER + reg); // send a command to nRF to read a register (reg)
	_delay_us(10);
	reg = SPITransceiver(NOP); // send dummy byte to nRF and save the contents of the register "reg"
	_delay_us(10);
	PORTB |= (1 << CSN); // make CSN or SS high to stop communicating with nRF
	return reg;
}

uint8_t* WriteToNrf(uint8_t readOrWrite,uint8_t reg,uint8_t* valArr,uint8_t arrSize){
	if(readOrWrite == WRITE){
		reg = W_REGISTER + reg;
	}

	static uint8_t ret[32]; // array to be returned

	_delay_us(10);
	PORTB &= ~(1 << CSN);
	_delay_us(10);
	SPITransceiver(reg); // send command to nRF whether to read or write
	_delay_us(10);

	for(int i = 0 ; i < arrSize ; i++){
		if(readOrWrite == READ && reg != W_TX_PAYLOAD){
			ret[i] = SPITransceiver(NOP);
		} else{
			SPITransceiver(valArr[i]);
		}
		_delay_us(10);
	}

	PORTB |= (1 << CSN);

	return ret;
}

void nrf24L01_init(void)
{
	_delay_ms(100);	//allow radio to reach power down if shut down
	
	uint8_t val[5];	//en array av integers som skickar värden till WriteToNrf-funktionen

	//EN_AA - (auto-acknowledgements) - Transmittern får svar av recivern att packetet kommit fram, grymt!!! (behöver endast vara enablad på Transmittern!)
	//Kräver att Transmittern även har satt SAMMA RF_Adress på sin mottagarkanal nedan ex: RX_ADDR_P0 = TX_ADDR
	val[0]=0x01;	//ger första integern i arrayen "val" ett värde: 0x01=EN_AA på pipe P0.
	WriteToNrf(W, EN_AA, val, 1);	//W=ska skriva/ändra nåt i nrfen, EN_AA=vilket register ska ändras, val=en array med 1 till 32 värden  som ska skrivas till registret, 1=antal värden som ska läsas ur "val" arrayen.
	
	//SETUP_RETR (the setup for "EN_AA")
	val[0]=0x2F;	//0b0010 00011 "2" sets it up to 750uS delay between every retry (at least 500us at 250kbps and if payload >5bytes in 1Mbps, and if payload >15byte in 2Mbps) "F" is number of retries (1-15, now 15)
	WriteToNrf(W, SETUP_RETR, val, 1);
	
	//Väljer vilken/vilka datapipes (0-5) som ska vara igång.
	val[0]=0x01;
	WriteToNrf(W, EN_RXADDR, val, 1); //enable data pipe 0

	//RF_Adress width setup (hur många byte ska RF_Adressen bestå av? 1-5 bytes) (5bytes säkrare då det finns störningar men långsammare dataöverföring) 5addr-32data-5addr-32data....
	val[0]=0x03;
	WriteToNrf(W, SETUP_AW, val, 1); //0b0000 00011 motsvarar 5byte RF_Adress

	//RF channel setup - väljer frekvens 2,400-2,527GHz 1MHz/steg
	val[0]=0x01;
	WriteToNrf(W, RF_CH, val, 1); //RF channel registry 0b0000 0001 = 2,401GHz (samma på TX å RX)

	//RF setup	- väljer effekt och överföringshastighet
	val[0]=0x07;
	WriteToNrf(W, RF_SETUP, val, 1); //00000111 bit 3="0" ger lägre överföringshastighet 1Mbps=Längre räckvidd, bit 2-1 ger effektläge hög (-0dB) ("11"=(-18dB) ger lägre effekt =strömsnålare men lägre range)

	//RX RF_Adress setup 5 byte - väljer RF_Adressen på Recivern (Måste ges samma RF_Adress om Transmittern har EN_AA påslaget!!!)
	int i;
	for(i=0; i<5; i++)
	{
		val[i]=0x12;	//RF channel registry 0b10101011 x 5 - skriver samma RF_Adress 5ggr för att få en lätt och säker RF_Adress (samma på transmitterns chip!!!)
	}
	WriteToNrf(W, RX_ADDR_P0, val, 5); //0b0010 1010 write registry - eftersom vi valde pipe 0 i "EN_RXADDR" ovan, ger vi RF_Adressen till denna pipe. (kan ge olika RF_Adresser till olika pipes och därmed lyssna på olika transmittrar)
	
	//TX RF_Adress setup 5 byte -  väljer RF_Adressen på Transmittern (kan kommenteras bort på en "ren" Reciver)
	//int i; //återanvänder föregående i...
	for(i=0; i<5; i++)
	{
		val[i]=0x12;	//RF channel registry 0b10111100 x 5 - skriver samma RF_Adress 5ggr för att få en lätt och säker RF_Adress (samma på Reciverns chip och på RX-RF_Adressen ovan om EN_AA enablats!!!)
	}
	WriteToNrf(W, TX_ADDR, val, 5);

	// payload width setup - Hur många byte ska skickas per sändning? 1-32byte
	val[0]=3;		//"0b0000 0001"=1 byte per 5byte RF_Adress  (kan välja upp till "0b00100000"=32byte/5byte RF_Adress) (definierat högst uppe i global variabel!)
	WriteToNrf(W, RX_PW_P0, val, 1);
	
	//CONFIG reg setup - Nu är allt inställt, boota upp nrf'en och gör den antingen Transmitter lr Reciver
	val[0]=0x1E;  //0b0000 1110 config registry	bit "1":1=power up,  bit "0":0=transmitter (bit "0":1=Reciver) (bit "4":1=>mask_Max_RT,dvs IRQ-vektorn reagerar inte om sändningen misslyckades.
	WriteToNrf(W, CONFIG, val, 1);

	//device need 1.5ms to reach standby mode
	_delay_ms(100);

	//sei();
}


int main(void)
{
	initSPI();
	nrf24L01_init();
	DDRA = 0xFF;
	/*
	uint8_t valArr[5];
	valArr[0] = 0x03; // PWR_UP = 1 and PRIM_RX = 1
	WriteToNRF(WRITE,CONFIG,valArr,1);
	uint8_t conf = getRegister(CONFIG);
	*/
    while (1)
    {
		if(getRegister(EN_AA) == 0x01){
			PORTA = 0x01;
			_delay_ms(1000);
			PORTA = 0x00;
			_delay_ms(1000);	
		}
    }
}

 

This is the nRF24L01.h header file:

/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17

/* Bit Mnemonics */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0
#define AW          0
#define ARD         4
#define ARC         0
#define PLL_LOCK    4
#define RF_DR       3
#define RF_PWR      1
#define LNA_HCURR   0
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1
#define TX_FULL     0
#define PLOS_CNT    4
#define ARC_CNT     0
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0

/* Instruction Mnemonics */
#define R_REGISTER    0x00
#define W_REGISTER    0x20
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define NOP           0xFF
#define W			  1
#define R			  0
#define RECEIVER	  0x1F
#define TRANSMITTER   0x1E

This is a picture of my connection. I've used the upper atmega32 and an nRF24L01 and USBASP V2.0 from LC Technology. I'm using atmel studio 7 to write the code and extreme burner AVR to burn the code. I'm using a PAKKO 6F22 9V Heavy duty battery as the power source. I have used two potentiometers to divide the voltage. Atmega32 is given around ~4.8V and nRF around ~3.2 V. But with this current configuration, power fluctuates a lot. I'm using LED on PORTA to test my code. But sometimes the LED lights up and sometimes it doesn't. (PORTA = 0x04 don't get executed) I've checked the connection thoroughly, but can't figure out why it is behaving like this. And if it does light up, it is not giving the correct output, i.e the value I've written to the registers is not reflected on the LED. (If condition in while loop is not executed) Can you guys give me some suggestions to work out the power issue and to get the intended output on LEDs?

Note : Code is taken mainly from Gizmosnack's tutorial. 

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

I'm using 

Parents Reply Children
No Data
Related