Buen día amigos, espero estén muy bien.
El día de hoy he decidido compartir con ustedes mi experiencia con los famosos módulos NRF24L01 de Nordic Semiconductor.

Por lo visto no hay un tema conciso y concreto sobre el uso de estos módulos en el foro, así que fundado en lo aprendido en la web y mi propia experiencia, me di a la tarea de redactar un tema sobre como dominar un poco estos bichitos
Ante todo me considero un aprendiz mas, la idea es que con base en esta información, entre todos logremos ampliar aun mas el conocimiento sobre estos grandes módulos.
Para tomar en cuenta:
No siendo mas empecemos.
El cto a usar es el siguiente:
Emisor:

Receptor:

El código en CCS para el cto emisor es el siguiente:
Y el código para el receptor es:
Expliquemos brevemente algunas sentencias del los programas así entender un poco el código.
Para el emisor:
Algunas especificaciones a resaltar del modulo son que usa modulación GFSK a 2.4 Ghz, una velocidad de datos configurable entre 1mbps y 2 mbps para el modelo "NRF24L01".
Existe una tercera velocidad de 250kbps para el modelo "NRF24L01+" y el consenso no es unánime a la hora de dar un alcance máximo de transmision, algo muy importante a tener en cuenta cuando construimos un proyecto de RF, según el dataaheet el alcance es de 100mts, sin embargo según las experiencias de muchas personas, esa distancia esta lejos del valor real, así que les diré el alcance logrado dependiendo de su configuración, y basado en mis experiencias
Bueno el alcance depende fundamentalmente de tres cosas:
Ahora les explicare como modificar la libreria para cambiar la velocidad de transmision de datos:
Para Finalizar adjunto los archivos correspondientes a este miniproyecto espero les sean de utilidad, cualquier duda, por este hilo
El día de hoy he decidido compartir con ustedes mi experiencia con los famosos módulos NRF24L01 de Nordic Semiconductor.

Por lo visto no hay un tema conciso y concreto sobre el uso de estos módulos en el foro, así que fundado en lo aprendido en la web y mi propia experiencia, me di a la tarea de redactar un tema sobre como dominar un poco estos bichitos
Ante todo me considero un aprendiz mas, la idea es que con base en esta información, entre todos logremos ampliar aun mas el conocimiento sobre estos grandes módulos.
Para tomar en cuenta:
- Los módulos NRF24L01 son transceptores ya que cada uno puede ser emisor o receptor en el momento que deseemos, esto se controla por software y resulta muy útil, ya que existe una comunicación bidireccional.
- Estos módulos NRF24L01 SOLO trabajan entre 1.9 y 3.6v según la hoja de datos, pero ellos recomiendan un voltaje de 3.3v, así que para fines prácticos usaremos esta tensión, y para evitar errores relacionados a los niveles TTL en la comunicación con el micro, inicialmente el pic que usemos que en este caso sera un 16F876A, lo alimentaremos también a 3.3v.
- Algo fundamental a la hora de alimentar los módulos, es que trabajemos inicialmente con baterías o una fuente de alimentación muy bien filtrada, idealmente una vieja fuente de PC ya que estos módulos son muy sensibles a nuestro gran dolor de cabeza las interferencias por parte del ruido de naturaleza analógica.
- La comunicación de estos módulos con el pic es por medio del puerto SPI, y como recomendación personal a la hora de montar el Cto en la protoboard, peinen muy bien los puentes, ser ordenados en eso les ahorrara tiempo a la hora de hacer verificaciones y evitaran errores de conexión que pueden terminar dañando el modulo.
- La configuración de el modulo, y su relativamente sencillo acoplamiento con el microcontrolador, se lo debemos a esta gran libreria, lib_rf2gh4_10.h propiedad de Bizintek Innova, S.L. el cual puede ser usada, modificada y distribuida bago licencia GNU, Por ultimo agradecer a Océano y a Biblioman de la web "aquí hay apuntes" ya que gracias a ellos logre avanzar con estos módulos
No siendo mas empecemos.
El cto a usar es el siguiente:
Emisor:

Receptor:

El código en CCS para el cto emisor es el siguiente:
Código:
#include <16F876A.h>
#fuses NOWDT
#fuses XT
#fuses PUT
#fuses NOPROTECT
#fuses NODEBUG
#fuses NOBROWNOUT
#fuses NOLVP
#fuses NOCPD
#fuses NOWRT
#use delay(clock=4000000)
#include "lib_rf2gh4_10.h"
#byte porta=0x05
#byte portb=0x06
#int_ext // Esta rutina está para un futuro si haces comunicaciones bidireccionales.
void int_RB0() // No tiene efecto en el programa principal, ya que sólo emite.
{ // Se encargaría de la recepción de datos.
int8 ret1;
ret1 = RF_RECEIVE();
if ( (ret1 == 0) || (ret1 == 1) )
{
do
{
ret1 = RF_RECEIVE();
} while ( (ret1 == 0) || (ret1 == 1) );
}
}
void main()
{
port_b_pullups(FALSE); // Todo digital... etc.
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
int8 ret2;
RF_INT_EN(); // Habilitar interrupción RB0/INT.
RF_CONFIG_SPI(); // Configurar módulo SPI del PIC.
RF_CONFIG(0x40,0x01); // Configurar módulo RF canal y dirección de recepción. Para recibir datos tiene la dirección 0x01.
RF_ON(); // Activar el módulo RF.
delay_ms(5); // Le damos un mínimo de 2.5 milisegundos para que se ponga en marcha.
set_tris_a(0b111111); // Todo el puerto A como entradas.
while(true) // Bucle infinito.
{
RF_DATA[0]= porta; // Cargamos el dato en RF_DATA[0].
RF_DIR=0x08; // Dirección del receptor.
ret2=RF_SEND(); // Enviar datos.
if(ret2==0){
//Envio realizado y ACK recibido
}
else if(ret2==1){
//Envio realizado y ACK no recibido
}
else{
//Envio no realizado
}
}
}
Y el código para el receptor es:
Código:
#include <16F876A.h>
#FUSES NOWDT
#FUSES XT
#FUSES PUT
#FUSES NOPROTECT
#FUSES NODEBUG
#FUSES NOBROWNOUT
#FUSES NOLVP
#FUSES NOCPD
#FUSES NOWRT
#use delay(clock=4000000)
#include "lib_rf2gh4_10.h"
#byte porta=0x05 // Dirección del puerto A.
#int_ext // Interrupción del módulo RF.
void int_RB0()
{
int8 ret1;
ret1 = RF_RECEIVE();
if ( (ret1 == 0) || (ret1 == 1) ) // Tanto si hay recepción simple o múltiple, leer datos.
{
do
{
porta=RF_DATA[0]; // El puerto A contendrá el valor que le llegue del emisor, a través de RF_DATA[0].
ret1 = RF_RECEIVE(); // "ret1" nos dirá si hay recepción simple, múltiple o no hay datos para leer.
} while ( (ret1 == 0) || (ret1 == 1) ); // Mientras haya datos para leer, seguir leyendo.
}
}
void main() // Programa principal.
{
port_b_pullups(FALSE); // Todo digital... etc.
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_a(0b000000); // Todo el puerto A como salida.
porta=0; // Inicialmente lo ponemos a cero.
RF_INT_EN(); // Habilitar interrupción RB0/INT.
RF_CONFIG_SPI(); // Configurar módulos SPI del PIC.
RF_CONFIG(0x40,0x08); // Configurar módulo RF (canal y dirección).
RF_ON(); // Activar el módulo RF.
while(true); // Bucle infinito.
}
Expliquemos brevemente algunas sentencias del los programas así entender un poco el código.
Para el emisor:
- En este segmento:
Código:
RF_INT_EN(); // Habilitar interrupción RB0/INT. RF_CONFIG_SPI(); // Configurar módulo SPI del PIC.
- En este otro segmento:
Código:
RF_CONFIG(0x40,0x01); // Configurar módulo RF canal y dirección de recepción. Para recibir datos tiene la dirección 0x01. RF_ON(); // Activar el módulo RF.
Modulo 1:
canal de transmision = 10
dirección de recepción = 1
enviar dato [$#] a "2"
Modulo 2
canal de transmision = 10
dirección de recepción = 2
Dato [$#] recibido
Enviar confirmación de recepción a "1"
Modulo1
canal de transmision = 10
dirección de recepción = 1
Dato [Confirmación] recibido
- Para este segmento:
Código:
RF_DATA[0]= porta; // Cargamos el dato en RF_DATA[0]. RF_DIR=0x08; // Dirección del receptor. ret2=RF_SEND(); // Enviar datos.
RF_DIR es la función que asina la dirección de recepción en el momento del envió que mencionábamos anteriormente, es la dirección a donde se enviara el dato del array.
por ultimo la función RF_SEND() esta es la que fuerza el envió del dato, y tiene capacidad de acuse de recibo o ACK, asi que la variable ret2 se carga con 3 valores posibles:
0 si el envió fue correcto y se ha recibido el ACK
1 si el envió fue correcto pero no se recibió el ACK
2 si se produjo algún error u el envió no fue posible
Para el receptor:
- En el receptor no cambia mucho el programa, vasta con decir que la función principal es un bucle infinito el cual se ve interrumpido por la recepción de un dato, en cuyo caso entra la función de interrupción por cambio de estado en RB0, y su función mas importante destacaríamos RF_RESEIVE el cual se encarga de guardar los datos entrantes en el array RF_DATA[0], posteriormente tratamos los datos recibidos, y el valor es asignado al puerto A del micro
Algunas especificaciones a resaltar del modulo son que usa modulación GFSK a 2.4 Ghz, una velocidad de datos configurable entre 1mbps y 2 mbps para el modelo "NRF24L01".
Existe una tercera velocidad de 250kbps para el modelo "NRF24L01+" y el consenso no es unánime a la hora de dar un alcance máximo de transmision, algo muy importante a tener en cuenta cuando construimos un proyecto de RF, según el dataaheet el alcance es de 100mts, sin embargo según las experiencias de muchas personas, esa distancia esta lejos del valor real, así que les diré el alcance logrado dependiendo de su configuración, y basado en mis experiencias
Bueno el alcance depende fundamentalmente de tres cosas:
- La libertad de la señal entre los módulos, con eso me refiero a si esta en linea de visión, o con muchos obstáculos como paredes que la señal tiene que atravesar.
- La potencia de salida de la señar preconfigurada en el modulo.
- La velocidad de datos:
Experimentalmente logre a 2Mbps un alcance de unos 11 metros en linea de visión, pero si se enfrentaba a 2 paredes no pasaba de 6 metros
A 1Mbps el asunto mejoro, ahora alcanzaba unos 40 metros en linea de visión, y la señal expuesta a 5 paredes sobrevivía hasta unos 18 metros.
finalmente a una velocidad de datos de 250Kbps, el modulo a linea de visión logro unos cómodos 150 metros de alcance, algo mas que inesperado considerando el costo de estos módulos, en cuanto a los obstáculos, logro transmitir de un lado de la casa al otro, el cual son 7 paredes y logro una distancia de 25 mts antes de perder la señal
Ahora les explicare como modificar la libreria para cambiar la velocidad de transmision de datos:
- primero que todo deben pegar la libreria lib_rf2gh4_10.h que dejo adjunta, en la carpeta en donde guardaran su proyecto en CCS.
Ya estando en el programa CCS y ya habiendo escrito el código correspondiente a cualquiera de los módulos damos click derecho sobre la sentencia "#include "lib_rf2gh4_10.h"" y le damos "Open file at cursor", de inmediato nos saldrá una pestaña en donde esta todo el código correspondiente a la libreria, buscamos el registro RF_SETUP que esta en fila 231 y aparece lo siguiente:
Código://RF_SETUP //Configuración aspectos RF. //Ganancia máxima de LNA, 0dBm potencia de salida y 2Mbps de velocidad. output_low(RF_CS); spi_write(0x26); spi_write(0x27); output_high(RF_CS);
Como podemos ver es un registro que se configura con un numero binario de 8 bits, en donde los bits 5, 3 , 2, 1, y 0 son los que nos interesan.
si el bit 5 esta a "0" queda desactivado el modo de transmisión con velocidad de datos a 250kbps
si el bit 3 esta a "0" configuramos el modulo a 1Mbps
si el bit 3 esta a "1" configuramos el modulo a 2Mbps
Para dejar el modulo con una velocidad de datos de 250kbps, ha que poner el bit 5 a "1" y el bit 3 a "0"
Los bits 2 y 1 configura la potencia del modulo
si los bits 2 y 1 están a "00" configuramos el modulo a -18dDm
si los bits 2 y 1 están a "01" configuramos el modulo a -12dDm
si los bits 2 y 1 están a "10" configuramos el modulo a -6dDm
si los bits 2 y 1 están a "11" configuramos el modulo a 0dDm
Esta ultima es la de mayor potencia de salida.
Aunque el bit 0 de este registro en este modulo se desprecie, debemos tenerlo en cuenta ya que existe una version mas potente de este, mas precisamente es el modulo "nrf24l01+pa+lna" el cual cuenta con un amplificador de salida para la antena, y un pre-amplificador para la entrada de la señal.
La disposición de pines de este modulo exactamente igual al del NRF menos potente, por lo cual también puede ser usado por esta libreria sin ningún problema.
En fin Como decía, el bit 0 debemos tenerlo en cuenta ya que si decidimos usar el modulo "nrf24l01+pa+lna"
si el bit 0 esta a "0" apagamos el pre-amplificador de la antena
si el bit 0 esta a "1" encendemos el pre-amplificador de la antena
Finalmente teniendo en cuenta la tabla, los valores validos para los 3 modos de transmision del modulo son:
- Para 2Mbps y maxima potencia el byte sera 00001111 entonces la linea de la libreria sera "spi_write(0x0f);"
- Para 1Mbps y maxima potencia el byte sera 00000111 entonces la linea de la libreria sera "spi_write(0x07);"
- Para 250Kbps y maxima potencia el byte sera 00100111 entonces la linea de la libreria sera "spi_write(0x27);"
Para Finalizar adjunto los archivos correspondientes a este miniproyecto espero les sean de utilidad, cualquier duda, por este hilo