Modul nRF24L01+ je lacný bezdrôtový modul pracujúci na frekvencii 2,4 GHz. Jeho dosah je približne 50 až 200 stôp (15 - 61 m). Dosah závisí hlavne od nastaveného výkonu, rýchlosti prenosu údajov a rušenia okolitými sieťami WiFi. Dá sa použiť na ovládanie zariadení a monitorovanie stavu senzorov v dosahu. Modul je dostupný v dvoch základných prevedeniach: so zabudovanou anténou na plošnom spoji a s externou anténou.


Verzia s externou anténou.
Konfigurácia vývodov modulu je uvedená na nasledujúcom obrázku a ich význam je uvedený v tabuľke.

Pin | Názov | Funkcia | Popis |
---|---|---|---|
1 | GND | Napájanie | Zem (0V) |
2 | VCC | Napájanie | +1,9V – +3,6V |
3 | CE | Digitálny vstup | Chip Enable (aktivuje RX alebo TX mód) |
4 | CSN | Digitálny vstup | SPI Chip Select |
5 | SCK | Digitálny vstup | SPI Clock |
6 | MOSI | Digitálny vstup | SPI Slave Data Input |
7 | MISO | Digitálny výstup | SPI Slave Data Output |
8 | IRQ | Digitálny výstup | Maskable interrupt pin. Activ low. |
Prepojenie s AVR (ATmega328P)
nRF24L01+ | ATmega328P (názov) | ATmega 328P (pin) |
---|---|---|
GND | GND | |
VCC | VCC (3,3V) | |
CE | Ľubovoľný I/O pin nakonfigurovaný ako výstup | PB6 |
CSN | SS | PB2 |
SCK | SCK | PB5 |
MOSI | MOSI | PB3 |
MISO | MISO | PB4 |
IRQ | Ľubovoľný I/O pin nakonfigurovaný ako výstup | PB7 |
Programovanie AVR
Názvy registrov nRF24L01+ a jednotlivých bitov sú v hlavičkovom súbore nRF24L01.h. Namapovanie registrov umožňuje prehľadný prístup a nastavovanie jednotlivých registrov. Napríklad na prístup ku konfiguračnému registru použijeme názov STATUS namiesto 0x07.
Komunikácia cez SPI
Vzájomná komunikácia medzi bezdrôtovým modulom a AVR prebieha prostredníctvom rozhrania SPI. Definícia jednotlivých pinov a funkcií pre rozhranie SPI vyzerá nasledovne:
#define MOSI PORTB3
#define MISO PORTB4
#define SCK PORTB5
#define SS PORTB2
#define SPI_PORT PORTB
#define SS_enable() PORTB &= ~(1 << SS)
#define SS_disable() PORTB |= (1 << SS)
Funkcia SS_enable() slúži na výber čipu pre komunikáciu cez rozhranie SPI. SS_enable() nastavuje výstup SS (PB2) na log.0, pretože výstup je invertovaný. Inicializácia SPI rozhrania pre ATmega328P vyzerá nasledovne:
void SPI_Init(){
// Set MOSI, SCK, SS as Output
DDRB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
// set MISO as Input
DDRB&=~(1<<MISO);
SPI_PORT|= (1<<SS) | (1<<MISO);
SPCR=(1 << SPE) | (1 << MSTR); //SPE - enable SPI, MSTR - MASTER mode
SPCR &= ~(1<< DORD);
//prenos zacina od MSB first
//nastavenie rychlosti prenosu SCLK pri Fosc=8 MHz -> 1 MHz (SPI2X=1)/500 kHz (SPI2X=0)
SPCR |= (1 << SPR0); //predelicka Fosc/8 - treba zapnut bit SPI2X v SPSR na double speed
SPSR |= (1<< SPI2X); //dvojansobna rychlost
SS_disable(); //aby nebol vybraty cip hned po inicializacii
}
Na zaslanie jedného bajtu cez SPI slúži funkcia:
void SPI_MasterTransmit(unsigned char cData){
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while (!( SPSR & (1<< SPIF)));
}
Na zaslanie jedného bajtu cez SPI so synchrónnym načítaním odpovede (bajtu) použijeme modifikovanú funkciu:
unsigned char SPI_MasterTransmitSync(unsigned char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))
;
return SPDR; //SPI return value
}
Na načítanie bajtu cez SPI môžeme použiť predchádzajúcu funkciu (odoslaním ľubovoľného bajtu) alebo nasledujúcu funkciu:
unsigned char SPI_MasterReceive(void)
{
SPDR = 0xff; //Start transmission of byte
while(!(SPSR & (1<<SPIF))); //wait for transmission complete
return SPDR; //SPI return value
}
Konfigurácia registra nRF24L01+
Ako už bolo uvedené, komunikácia prebieha prostredníctvom rozhrania SPI. Registre v nRF24L01+ sú väčšinou jednobajtové, niektoré sú však viacbajtové. Rozhodol som sa opísať niektoré zaujímavé funkcie z knižnice funkcií, ktoré sú v nrf24.c. Knižnica s funkciami, ktoré slúžia na prácu s nRF24L01+ je modifikáciou knižnice od kehribar, ktorú najdete tu a návodu od klalle, ktorý nájdete tu. Na zápis jedného bajtu do registra použijeme funkciu:
/* Clocks only one byte into the given nrf24 register */
void nrf24_configRegister(uint8_t reg, uint8_t value)
{
_delay_us(10);
SS_enable(); //start SPI communication
_delay_us(10);
SPI_MasterTransmit(W_REGISTER | (REGISTER_MASK & reg));
_delay_us(10);
SPI_MasterTransmit(value);
_delay_us(10);
SS_disable(); //end SPI communication
}
Vstupná hodnota reg je názov registra, ktorý chceme nastaviť a value je hodnota, ktorá sa má nastaviť. Napríklad na nastavenie kanála (register RF_CH) na hodnotu 0x60 použijeme zápis: nrf24_configRegister(RF_CH, 0x60). Na zápis viacerých bajtov do jedného registra sa používa funkcia: void nrf24_writeRegister(uint8_t reg, uint8_t * value, uint8_t len). Význam jednotlivých vstupných premenných je podobný ako pri funkcii nrf24_readRegister, ktorá je uvedená nižšie.
Pre načítanie obsahu registra z nRF24L01+ (jedného alebo viacerých bajtov) použijeme nasledovnú funkciu:
/* Read single register from nrf24 */
void nrf24_readRegister(uint8_t reg, uint8_t* value, uint8_t len)
{
_delay_us(10);
SS_enable();
_delay_us(10);
SPI_MasterTransmit(R_REGISTER | (REGISTER_MASK & reg));
_delay_us(10);
nrf24_transferSync(value, value, len);
_delay_us(10);
SS_disable();
}
Kde reg je názov registra, value je hodnota alebo pole hodnôt (bajtov) načítaných z registra a len je počet bajtov na čítanie. Funkcia nrf24_transferSync slúži na načítanie viacerých bajtov s počtom len. Napríklad na načítanie obsahu konfiguračného registra použijeme zápis:
uint8_t hodnota_conf;
nrf24_readRegister(CONFIG, &hodnota_conf, 1); //load content of CONFIG register to hodnota_conf
Inicializácia nRF24L01+
Inicializácia spočíva v nastavení parametrov, ktoré sú potrebné pre komunikáciu medzi modulmi. Oba moduly musia mať nastavené rovnaké parametre: použitý kanál, adresu, dĺžka packetu (payload), počet dátových "potrubí" (datapipes), ... Nasledujúca funkcia slúži na konfiguráciu modulu:
/* conpicture the module */
void nrf24_config(uint8_t channel, uint8_t pay_length)
{
/* Use static payload length ... */
payload_len = pay_length;
// Set RF channel - choose frequency 2,400-2,527GHz step=1MHz
nrf24_configRegister(RF_CH, channel);
// Set length of incoming payload
nrf24_configRegister(RX_PW_P0, payload_len); // payload_len per package
nrf24_configRegister(RX_PW_P1, 0x00); // Pipe not used
nrf24_configRegister(RX_PW_P2, 0x00); // Pipe not used
nrf24_configRegister(RX_PW_P3, 0x00); // Pipe not used
nrf24_configRegister(RX_PW_P4, 0x00); // Pipe not used
nrf24_configRegister(RX_PW_P5, 0x00); // Pipe not used
// Set speed 250kbs, TX gain: 0dbm
uint8_t rf_setup = 0x00;
rf_setup |= (1<<RF_DR_LOW) | ((0x03)<<RF_PWR);
rf_setup &= ~(1<<RF_DR_HIGH);
nrf24_configRegister(RF_SETUP, rf_setup);
// CRC enable, 2 byte CRC length
nrf24_configRegister(CONFIG, nrf24_CONFIG);
// Enable Auto Acknowledgment
uint8_t en_aa = 0x00;
en_aa |= ((1<<ENAA_P0)); //enable pipe 0
nrf24_configRegister(EN_AA, en_aa);
//RX/TX Address field width
nrf24_configRegister(SETUP_AW, 0x03); // width of 5 bytes
// Enable RX addresses
uint8_t en_rxaddr=0x00;
en_rxaddr |= ((1<<ERX_P0));
nrf24_configRegister(EN_RXADDR, en_rxaddr);
// Auto retransmit delay: 1250 us (ARD=0100) and Up to 15 retransmit trials (ARC=1111)
nrf24_configRegister(SETUP_RETR,(0x04<<ARD)|(0x0F<<ARC));
// Dynamic length configurations: No dynamic length
//nrf24_configRegister(DYNPD,0x00);
// Dynamic length configurations: Dynamic length for all datapipes
nrf24_configRegister(DYNPD, (1<<DPL_P0) | (1<<DPL_P1) | (1<<DPL_P2) | (1<<DPL_P3) | (1<<DPL_P4) | (1<<DPL_P5));
// Enable Dynamic Payload Length and Enables Payload with ACK
nrf24_configRegister(FEATURE, (1<<EN_DPL) | (1<<EN_ACK_PAY));
_delay_ms(100);
// Start listening
nrf24_powerUpRx();
}
Predchádzajúca funkcia nastaví modulu tieto parametere:
- rýchlosť prenosu 250 kbs
- TX gain 0 dbm
- zapnutie CRC (2 bajty) - Cyclic Redundancy Test
- zapnutie potvrdenia - Acknowledgment (ACK) packet
- automatické preposlanie po zlyhaní po 1250 us;počet opakovaní max. 15
- použitie datapipe P0 (ostatné sa nepoužívajú)
Frekvencia kanála a dĺžka packetu sa nastavuje pomocou vstupných premenných funkcie. Napríklad nastavenie frekvencie 2,401 GHz (RF_CH = 0x01) a dĺžky packetu 5 bajtov vykonáme nasledovne: nrf24_config(0x01, 5). Je vhodné nastaviť frekvenciu aspoň na hodnotu 2,508 GHz (RF_CH = 108), aby sme predošli rušeniu okolitými sieťami WiFi.
Bezprostredne po inicializácii modulu je potrebné nastaviť adresu vysielača (TX) a adresu prijímača (RX). Adresa môže mať dĺžku 3, 4 alebo 5 bajtov. Dĺžka adresy sa nastavuje pomocou registra SETUP_AW. Prednastavená je dĺžka 5 bajtov. Adresy prijímača a vysielača nastavíme pomocou funkcie:
/* Set the TX and RX address */
void nrf24_tx_address(uint8_t* adr)
{
/* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
nrf24_writeRegister(RX_ADDR_P0, adr, nrf24_ADDR_LEN);
nrf24_writeRegister(TX_ADDR, adr, nrf24_ADDR_LEN);
}
V prípade, že sa používa Auto ACK, tak musia mať vysielač a prijímač rovnakú adresu. Napríklad, ak chceme nastaviť adresu {0xC2,0xC2,0xC2,0xC2,0xC2} použijeme funkciu nasledovne:
uint8_t address[5] = {0xC2,0xC2,0xC2,0xC2,0xC2};
/* Set the device addresses */
nrf24_tx_address(address);
Po nastavení všetkých potrebných registrov je modul pripravený na odosielanie a prijímanie údajov. Režim prijímača alebo vysielača sa nastavuje pomocou bitu PRIM_RX v registri CONFIG. Ak je nastavený bit PRIM_RX modul je prijímač, v opačnom prípade je vysielač. Pred prijímaním alebo odosielaním údajov je potrebné modul prepnúť z režimu Stand by do normálneho režimu nastavením bitu PWR_UP v registri CONFIG. Odosielanie alebo prímanie údajov prebieha po privedení log.1 na vstup modulu označený ako CE. Nasledujúca funkcia slúži na odosielanie údajov:
// Sends a data package to the default address. Be sure to send the correct
// amount of bytes as conpictured as payload on the receiver.
void nrf24_send(uint8_t* value)
{
/* Go to Standby first */
CE_disable(); // CE low
/* Set to transmitter mode , Power up if needed */
nrf24_powerUpTx();
/* Do we really need to flush TX fifo each time ? */
#if 1
/* Pull down chip select */
SS_enable();
/* Write cmd to flush transmit FIFO */
SPI_MasterTransmit(FLUSH_TX);
/* Pull up chip select */
SS_disable();
#endif
/* Pull down chip select */
SS_enable();
/* Write cmd to write payload */
SPI_MasterTransmit( W_TX_PAYLOAD );
/* Write payload */
nrf24_transmitSync(value, payload_len);
/* Pull up chip select */
SS_disable();
/* Start the transmission */
_delay_ms(10);
CE_enable(); //CE high - transmit the data in payload
_delay_us(20); //delay at least 10 us!
CE_disable(); //CE low - stop transmitting
_delay_ms(10);
}
Vstupný parameter value je pole hodnôt s dĺžkou (payload length) nastavenou v nrf24_config(). Odosielanie hodnôt vyzerá nasledovne:
/* Fill the data buffer */
data_array[0] = 0x01;
data_array[1] = 0x02;
data_array[2] = 0x03;
data_array[3] = 0x04;
data_array[4] = 0x05;
// Send the data
nrf24_send(data_array);
// Wait for transmission to end
while(nrf24_isSending());
// Make analysis on last tranmission attempt
temp = nrf24_lastMessageStatus();
Funkcia nrf24_isSending() zabezpečí zdržanie programu pokiaľ nedošlo k odoslaniu packetu. Funkcia nrf24_lastMessageStatus() informuje o úspešnosti prenosu. Keď je návratová hodnota rovná hodnote 1, tak prijímač nezachytil zaslané údaje a došlo k chybe prenosu. Ak je návratová hodnota rovná 0, tak prijímač úspešne prijal zaslané dáta.
Súbory na stiahnutie
Zaujímavé odkazy
RF24L01 2.4GHz Radio/Wireless Transceivers How-To
Tutorial - nRF24L01 and AVR
Arduino Using NRF24L01 Rf Module