# Comunicación por Radiofrecuencia entre PICs y nRF24L01



## luvhines (Ago 1, 2014)

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:*


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:*


```
#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:*


```
#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:*

```
RF_INT_EN();              // Habilitar interrupción RB0/INT.
RF_CONFIG_SPI();          // Configurar módulo SPI del PIC.
```
Como su descripción lo indica son funciones incluidas en la libreria lib_rf2gh4_10.h que  de modo simple, permiten la activación del la interrupción por cambio de estado en RB0 en el micro, y la configuración correcta del puerto SPI en este


*En este otro segmento:*

```
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.
```
Se configura el modulo, la función RF_CONFIG permite seleccionar el CANAL de comunicación y la dirección de recepción, con esto quiero decir que para que exista una comunicación entre dos o mas módulos, todos deben de estar exactamente en el mismo canal de transmision, pero la dirección es útil en el momento del recibir un dato, y este se debe ser especificado por el modulo emisor en el momento del envió, por ejemplo:

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:*

```
RF_DATA[0]= porta;     // Cargamos el dato en RF_DATA[0].
RF_DIR=0x08;           // Dirección del receptor.
ret2=RF_SEND();        // Enviar datos.
```
La función RF_DATA es un array de 8 bytes y podemos notar que solo se usara un byte para guardar el estado del puerto A del micro.
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:


```
//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);
```
La linea que nos interesa es la que dice "spi_write(0x27);" pues este numero hexadecimal es el que permite configurar los aspectos de RF del modulo: tomemos un momento para explicar el como y porque, para eso nos vamos al registro RF_SETUP del datasheet del modulo:




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


----------



## Miembro eliminado 356005 (Ago 2, 2014)

Gracias por al aporte. Es muy bueno.

Sólo diría que yo cambiaría las líneas

```
while(true);              // Bucle infinito.
```
por
	
	



```
while(true) {             // A dormir
        sleep();
        delay_cycles(2);     // (por seguridad, algo opcional) Esperamos un poco
    }
```
Para probar a ver si el consumo del PIC baja al mínimo (con el ahorro consiguiente).


----------



## luvhines (Ago 3, 2014)

Gracias joaquin efectivamente se puede hacer, el código es lo mas simplificado posible para evitar errores, ya que estos módulos a veces resultan bastante caprichosos.


----------



## el_patriarca (Sep 26, 2014)

gracias luvhines por el aporte, y que casualidad, yo también empezaba a estudiar estos módulos y no encontré mucho en el foro.

quería preguntar si alguien puede aclararme cuál es la diferencia entre estos módulos y los módulos nrf24l01+ , es que voy a hacer el pedido y no quiero quedarme con un dispositivo que no pueda usar, me sale muy caro hacer traer algo por internet.

me olvidaba: qué programa puedo usar para simular el uso de los módulos? es que en el proteus creo que no tienen el modelo del nrf24l01. gracias de antemano.


----------



## mabafi (Sep 27, 2014)

Hola luvhines mi pregunta es como puedo hacer ese mismo proyecto pero usando el 18f4550 como podras comprobar mi nivel es bastante bajo y como no tengo el 16f876 y si varios 18f4550 es por lo que necesito este cambio gracias y espero tu respuesta, un saludo.


----------



## ericksm (Sep 28, 2014)

pense que esos modulos solo tenian un alcance de 20 metros como mucho, sin la posibilidad de atravezar pared, como los modulos rf 433hz, pero ahora con la informacion planteada sera motivo para probarlos, mas aun con esa cantidad de datos de transmision, le gana por mucho a los 433mhz.


----------



## luvhines (Oct 10, 2014)

mabafi dijo:


> Hola luvhines mi pregunta es como puedo hacer ese mismo proyecto pero usando el 18f4550 como podras comprobar mi nivel es bastante bajo y como no tengo el 16f876 y si varios 18f4550 es por lo que necesito este cambio gracias y espero tu respuesta, un saludo.


Hola compa me encuentro bastante ocupado en la u pero cuando pase tanta cosa, pienso hacer un tuto para los pics de la familia 18F y tips para que adapten la librería a cualquier pic que soporte comunicación SPI, solo es cuestión de retocar algunos datos de la librería lib_rf2gh4_10.h. Saludos


----------



## jamertron (Oct 10, 2014)

el_patriarca dijo:


> gracias luvhines por el aporte, y que casualidad, yo también empezaba a estudiar estos módulos y no encontré mucho en el foro.
> 
> quería preguntar si alguien puede aclararme cuál es la diferencia entre estos módulos y los módulos nrf24l01+ , es que voy a hacer el pedido y no quiero quedarme con un dispositivo que no pueda usar, me sale muy caro hacer traer algo por internet.
> 
> me olvidaba: qué programa puedo usar para simular el uso de los módulos? es que en el proteus creo que no tienen el modelo del nrf24l01. gracias de antemano.



yo tambien quisiera saber como hiciste para simularlo.
Gran aporte a la comunidad, muchos te lo agradecemos!


----------



## luvhines (Oct 10, 2014)

el_patriarca dijo:


> gracias luvhines por el aporte, y que casualidad, yo también empezaba a estudiar estos módulos y no encontré mucho en el foro.
> 
> quería preguntar si alguien puede aclararme cuál es la diferencia entre estos módulos y los módulos nrf24l01+ , es que voy a hacer el pedido y no quiero quedarme con un dispositivo que no pueda usar, me sale muy caro hacer traer algo por internet.
> 
> me olvidaba: qué programa puedo usar para simular el uso de los módulos? es que en el proteus creo que no tienen el modelo del nrf24l01. gracias de antemano.



Hola compa este tuto es sobre los módulos NRF24l01+ creo que hay que corregir eso para evitar confusiones, y físicamente no tienen ninguna diferencia, pero si difieren en su funcionamiento, por ejemplo los módulos que usan el chip nrf24l01 no pueden configurarse a 250kbps, pero estos si, aca puedes verlo:

Datasheet nrf24L01: ve a la pagina 23 en la dirección "06" y veras el registro RF_SETUP y podras notar que solo hay 2 posibles configuraciones para 1Mbps y para 2Mbps.
https://www.sparkfun.com/datasheets/Components/nRF24L01_prelim_prod_spec_1_2.pdf

Datasheet nrf24L01+: ve a la pagina 55 en el mismo registro RF_SETUP  podrás notar que posee las 3 posibles configuraciones para, 1Mbps, 2Mbps y 250Kbps
https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf

te recomiendo que busques específicamente los NRF24L01+ y los compres por ebay, yo compre 10 unidades y en total me costo 9 dolares, no salen tan costosos.

Por ultimo amigo no existe ningún programa que pueda simular estos módulos, lo mejor que puedes hacer es traer mas de 2 por si te equivocas y te tires el modulo, después de eso probar con lo que esta en este tuto y te garantizo que si lo haces tal cual te van a funcionar =D 
De los diez que yo pedi dañe 2 por conectarlos al revés D: pero valieron la pena, ahora tengo 8 que me funcionan al pelo ;D





jamertron dijo:


> yo tambien quisiera saber como hiciste para simularlo.
> Gran aporte a la comunidad, muchos te lo agradecemos!


jajajaja no amigo no lo simule, yo solo cree el nuevo componente en proteus para poder hacer  las conexiones y crear fácilmente un PCB, pero no es simulable.


----------



## el_patriarca (Nov 20, 2014)

luvhines dijo:


> Hola compa me encuentro bastante ocupado en la u pero cuando pase tanta cosa, pienso hacer un tuto para los pics de la familia 18F y tips para que adapten la librería a cualquier pic que soporte comunicación SPI, solo es cuestión de retocar algunos datos de la librería lib_rf2gh4_10.h. Saludos



Te cuento que hice funcionar los transceptores con dos PIC18F4550, es cuestión de cambiar algunas definiciones en la librería y algunas consideraciones en los pines de acuerdo a la familia de microcontroladores. por cierto, tengo los nrf24l01+ y no he tenido problemas por el "signo más", es cuestión de velocidad de transmisión, pero funcionan con la misma librería, no afecta en nada y no hay que modificar nada para eso.


----------



## zeusjorg (Dic 14, 2014)

Hola buenas tardes a todos.

Yo estoy usando estos módulos para un proyecto para hacerme la casa domotica.
ya e echo pruebas con tres modulo a la vez.

Pero tengo la duda, que no acabo de entender cuantos canales y módulos se pueden usar a la vez.

Por lo que e entendido en la hoja de características(no se me da muy bien el ingles). 
-que tiene una banda de frecuencia 125Mhs, 
-1Mhz por canal a una velocidad de transmisión de 1Mbps.(125/1=125 canales)
-2Mhz por canal a una velocidad de transmisión de 2Mbps.(125/2=62.5 canales)

y me a parecido entender que se puede conectar 6 direcciones por canal.

haber si me podéis aclarar el tema. Si estoy en lo correcto o no.
Ya que en mi proyecto habrán bastantes módulos. y tengo que tener este tema claro.

muchas gracias a todos


----------



## luvhines (Feb 8, 2015)

zeusjorg dijo:


> Hola buenas tardes a todos.
> 
> Yo estoy usando estos módulos para un proyecto para hacerme la casa domotica.
> ya e echo pruebas con tres modulo a la vez.
> ...





hola zeusjorg, mira los módulos funcionan en la banda de 2.4 a 2.525 Ghz dejando 125Mhz para los canales de comunicación, en teoría pueden ser 125 canales para 1Mbps y 62 canales para 2Mbps pero en la practica se recomienda dejar 2 canales de "distancia" entre canales de comunicación para evitar las interferencias, por lo que en realidad quedan 31 canales disponibles para su uso. 

Para que dos módulos se comuniquen, el canal debe ser el mismo, pero cada modulo debe tener su respectiva dirección ‘broadcast". Esta dirección debe ser única para cada dispositivo en un mismo canal, y debe tener un valor entre 0.01 y 0.FE es decir 254 direcciones. Así, resumiendo, en el canal 1 tienes 254 direcciones en el canal 4 "recuerda que se espacian por 2 canales" otras 254 direcciones etc etc.. con esto te quiero decir 254 dispositivos y no 6, se pueden comunicar en un mismo canal.


----------



## arias887 (Feb 12, 2015)

Acabo de adquirir un par de estos modulos y me costaron 12k pesos (COL), algo asi como 5,5 dolales c/u....

Es factible/viable/posible redefinir/cambiar/pasar los pines que se usan  del "Puerto C" al "Puerto B" teniedo en cuenta que la libreria usa la  configuracion SPI por Hardware?

Haciendo solo lo siguente...

Cambiar esto:

```
// PORTB
#define   RF_IRQ   PIN_B0
#define   RF_CS    PIN_C1

// PORTC
#define   RF_CE    PIN_C2
#define   SCK      PIN_C3
#define   SDI      PIN_C4
#define   SDO      PIN_C5

// PORTB
#define   RF_IRQ_TRIS   TRISB,0
#define   RF_CS_TRIS    TRISB,7   // ***

// PORTC
#define   RF_CE_TRIS    TRISC,2
#define   SCK_TRIS      TRISC,3
#define   SDI_TRIS      TRISC,4
#define   SDO_TRIS      TRISC,5
```
Por esto:

```
// PORTB
#define   RF_IRQ   PIN_B0
#define   RF_CS    PIN_[B]B[/B]1
#define   RF_CE    PIN_[B]B[/B]2
#define   SCK      PIN_[B]B[/B]3
#define   SDI      PIN_[B]B[/B]4
#define   SDO      PIN_[B]B[/B]5

// PORTB
#define   RF_IRQ_TRIS   TRISB,0
#define   RF_CS_TRIS    TRISB,7   // ***
#define   RF_CE_TRIS    TRIS[B]B[/B],2
#define   SCK_TRIS      TRIS[B]B[/B],3
#define   SDI_TRIS      TRIS[B]B[/B],4
#define   SDO_TRIS      TRIS[B]B[/B],5
```
*****Porque se nombra el bit 7 del Puerto B?

Para poder usar solo un puerto "completo" del uC y no dejar dos puertos "a medio usar".

¿Seria correcto hacer esto?
¿Habria que cambiar algo mas?


----------



## luvhines (Feb 14, 2015)

arias887 dijo:


> Acabo de adquirir un par de estos modulos y me costaron 12k pesos (COL), algo asi como 5,5 dolales c/u....
> 
> Es factible/viable/posible redefinir/cambiar/pasar los pines que se usan  del "Puerto C" al "Puerto B" teniedo en cuenta que la libreria usa la  configuracion SPI por Hardware?
> 
> ...




Hola compa te respondo:



> Es factible/viable/posible redefinir/cambiar/pasar los pines que se usan  del "Puerto C" al "Puerto B" teniedo en cuenta que la libreria usa la  configuracion SPI por Hardware?



No entiendo muy bien lo que quieres decir, si bien la comunicación es por hardware se tiene que configurar desde la libreria, ten en cuenta que cada pic tiene destinado ciertos pines para la comunicación SPI, (SCK, SDI, SDO) esos pines son el 14 , 15 y 16 o RC3, RC4 y RC5 para este pic en particular, así que son intocables, no puedes simplemente cambiarlos a RB3, RB4 y RB5 puesto que esos pines no soportan la comunicación SPI ¿ya ves?

mira, para este pic estos son los pines que no debes cambiar:

El pin 21 o el famoso pin por interrupción externa RB0, y a menos que tengas otro pin para las interrupciones no debe ser cambiado. 

```
#define   RF_IRQ   PIN_B0

#define   RF_IRQ_TRIS   TRISB,0
```

Los siguientes 3 pines, el 14, 15, 16 o RC3, RC4 y RC5 son, como te mencione anteriormente, los que tiene este pic para la comunicación SPI y como no existen en el otros pines para tal tarea, tampoco podemos cambiarlos.

```
#define   SCK      PIN_C3
#define   SDI      PIN_C4
#define   SDO      PIN_C5

#define   SCK_TRIS      TRISC,3
#define   SDI_TRIS      TRISC,4
#define   SDO_TRIS      TRISC,5
```


Pero estos 2 si los puedes cambiar solo son de activación/desactivación, pero ojo, estas cambiando dos pines del micro, si los cambias no olvides cambiar también conexión en el circuito.

```
#define   RF_CS    PIN_C1
#define   RF_CE    PIN_C2

#define   RF_CS_TRIS    TRISC,1  
#define   RF_CE_TRIS    TRISC,2
```


Espero haber aclarado tu duda, ahora:


> *****Porque se nombra el bit 7 del Puerto B?


gracias por notarlo, la verdad es que retocando la libreria debí pasarlo por alto, y aunque me funciono sin problema, no es así como debe quedar, lo correcto seria:


```
#define   RF_CS    PIN_C1
#define   RF_CS_TRIS    TRISC,1
```
si es que vas a usar el RC1, y si vas a usar el RC0, RC6 ó RC7 O del RB1 al RB7 ya que te mencione anteriormente que este si lo puedes cambiar, podría quedar así:


```
#define   RF_CS    PIN_B7
#define   RF_CS_TRIS    TRISB,7
```

ó


```
#define   RF_CS    PIN_C0
#define   RF_CS_TRIS    TRISC,0
```

y asi mismo con RF_CE, yo creo que ya me entiendes


----------



## arias887 (Feb 14, 2015)

No se muccho de SPI....
Pero lo que si sé es que si configuras por Softward puedes asignar CSL/SDI/SDO a los pines que quieras...

En estos momentos estoy haciendo los cambios en un programita de prueba donde pongo el SPI en el puerto y finciona (ISIS) en unos minutos lo subo...

Mira, esto solo hace que se muetre el valor de "tabla" del Master en el PuertoC del Slave...
El SPI estan en el PuertoB de ambos micros y funciona como veras en la imagen que adjunto...

Para usar SPI con Software (sw) se usa "#USE SPI (ta,ta,...,ta)"
Para usar SPI con Hardware (hw) se usa "setup_spi (ta,ta,...,ta)"

Master [16F886]:

```
#include <Comunicacion SPI [16F886] [Master].h>
 
#byte    porta= 0x005
#byte    portb= 0x006
#byte    portc= 0x007
 
//#USE SPI (MASTER, CLK=PIN_C3, DI=PIN_C5, DO=PIN_C4, BAUD=2000, MODE=0, BITS=8, STREAM=SPI_1, force_sw)
#USE SPI (MASTER, CLK=PIN_B1, DI=PIN_B3, DO=PIN_B2, BAUD=2000, MODE=0, BITS=8, STREAM=SPI_1, force_sw)
 
int8 tabla [16]= {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int8 i;
 
void main()
{
 set_tris_b (0b00001000);
 set_tris_c (0b00100000);
 portb= 0x00;
 portc= 0x00;
 
   while(TRUE)
   {
      //TODO: User Code
      for (i=0;i<16;i++)
      {
         spi_xfer (spi_1, tabla[i]);
         delay_ms (500);
      }
   }
}
```
Slave [16F887]:

```
#include <Comunicacion SPI [16F887] [Slave].h>
 
#byte    porta= 0x005
#byte    portb= 0x006
#byte    portc= 0x007
 
//#USE SPI (SLAVE, CLK=PIN_C3, DI=PIN_C5, DO=PIN_C4, BITS=16, STREAM=SPI_1, force_sw)
#USE SPI (SLAVE, CLK=PIN_B1, DI=PIN_B3, DO=PIN_B2, BITS=8, STREAM=SPI_1, force_sw)
 
void main()
{
 set_tris_b (0b00001010);
 set_tris_c (0b00000000);
 portb= 0x00;
 portc= 0x00;
 
   while(TRUE)
   {
      //TODO: User Code
      portc= spi_xfer(spi_1);
   }
}
```
A esto es a lo que me refieria, pero sinceramente, no se como aplicar (en caso de que se pueda) esa configuracion por software a la libreria y tampoco estou seguro que se pueda hacer el cambio que dije antes....


----------



## luvhines (Feb 14, 2015)

arias887 dijo:


> No se muccho de SPI....
> Pero lo que si sé es que si configuras por Softward puedes asignar CSL/SDI/SDO a los pines que quieras...
> 
> En estos momentos estoy haciendo los cambios en un programita de prueba donde pongo el SPI en el puerto y finciona (ISIS) en unos minutos lo subo...
> ...



La verdad, poco sé sobre la emulación del puerto SPI, pero por lo que sé, no deja de ser una emulación de dicho protocolo,  así que no cuentas con la misma velocidad.
Además para que dicho protocolo funcione bien en ese modo,  tanto el master como el esclavo deben usar la misma librería,  por eso es posible entre dos PICs, ya que ambos los puedes programar del mismo modo. 

Ahora, el PIC en este caso es el master y el módulo NRF el slave, así que no creo que pueda ser posible una comunicación emulada de un solo lado, pues el tema de la sincronización es fundamental para la comunicación SPI.
Sin embargo, es algo que supongo. Habría que hacer pruebas para ver como se comporta.


----------



## arias887 (Feb 20, 2015)

Te entiendo, y hasta donde tengo entendido, la configuración por hardware permite una mayor velocidad de transferencia que por software.

En cuanto pueda (quién sabe) me dispondré a hacer las pruebas pertinentes y si es posible, una librería de uso por software para "aprovechar mejor" los recursos y pines del microcontrolador.


----------



## luvhines (Abr 18, 2015)

luvhines dijo:


> 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...




Me falto la lista de  materiales.

2 módulos Nrf24L01
2 Pic´s 16f876a
2 cristales 4mhz
4 condensadores cerámicos de 22pf
1 Dipswich de 8 pines o bien 6 pulsadores 
8 resistencias de 1 kΩ
6 resistencias de 220 kΩ
6 leds

2 conectores ribbon de este tipo:


Este ultimo lo podrían cortar para insertar los módulos NRF24L01 soldar cables he insertarlos fácilmente en el protoboard, ya que la separación entre los pines del modulo no permite insertarlos en la proto, y tampoco recomiendo para nada soldar cables directamente a los pines del modulo ya que lo podrían dañar.

Por ultimo, en el esquemático que postee yo creé el componente del nrf24L01 en proteus solo para poder ilustrar la conexión, pero no tuve en cuenta los números de los pines, así en esa imagen solo tengan en cuenta el nombre de los pines según la siguiente imagen lo pueden conectar tal cual al pic.


----------



## crismabuba (Ene 18, 2016)

> if(ret2==0){
> //Envio realizado y ACK recibido
> }
> 
> ...



buen dia amigos del foro es que tengo duda de como utilizar el modo de confirmacion de estos modulos. mi pregunta es como se hace para que el receptor conteste automaticamente que recibio el dato y sino el transmisor vuelva a enviar el dato. agradeceria su ayuda


----------



## dcsalg (Mar 11, 2016)

Hola tengo un inconveniente, compre estos modulos y la verdad no puedo hacerlos funcionar trate de utilizar el ejemplo por donde comenzaron este foro y no logro nada, estoy utilizando un pic16f887 y un pic16f818, que son los que tengo para hacerlos funcionar como ejemplo, lo que quiero es precionar un botoen en el 887 que seria el TX, y el 818 que es el RX enciende un led, no logro hacerlo. Me pueden explicar por favor ese simple ejemplo que quiero a ver si puedo hacerlo funcionar, estoy utilizando un protoboard no simulo.
Subi los dos archivos zip del TX y RX modificando la libreria del 818 porque SDI, SCK y demas son otros pines, pero no entiendo la verdad? precionar un boton y el receptor encender un led Una verguenza preguntar esto pero no me sale. Por favor si hay alguien que con un simple ejemplo asi lo cargo y lo puedo probar muchas Gracias. 

Otra cosa capaz este bien y lo que este mal son los modulos pero nose como chequearlos! Pero me inclino mas que es problema en la programacion.

Tengo dos pic16f819 por si quieren utilizar estos para explicarme tambien

es uno de los progrogramas porque lo voy variando a cada rato. la verdad no entiendo alguien tiene un programa o me ayuda hacerlo? de ultima que prenda un led de un lado y lo repita en el otro pero algo.

lo peor que me puede pasar que no me funcione los modulos pero nose? hay alguna manera de testearlo?

lo que si antes aclaro logre comunicar los dos pic mediante spi osea uno enciende el led (maestro) y el esclavo hace lo mismo. fue todo un logro jeje


----------



## colombia90 (Mar 13, 2016)

yo los hice funcionar con el pic16f876a.


----------



## dcsalg (Mar 13, 2016)

tenes un ejemplo asi con un boton solo y un led en el receptor asi lo enciendo.. me ayudas? con un pic16f819. aca no es problema del pic. ayudame y mostrame algo asi los codigos a ver si me funciona.


----------



## D@rkbytes (Mar 14, 2016)

Saludos.
Cuando yo realicé la prueba de éstos módulos, me funcionó a la primera.
No tuve complicaciones de ningún tipo con el software, con el hardware si tuve, pero lo resolví.

Recuerdo que la primera prueba fue usando Proteus para analizar la comunicación SPI con el debugger.
Noté que existían varias advertencias cuando se hacía el cambio de modo Master/Slave.
Así que en modo de depuración me dediqué a corregir la librería "lib_rf2gh4_10.h"

Esa fue una prueba y corrección en simulador, me quedaba la duda de que funcionaran físicamente.
Pero llegó el detalle con el hardware. Los módulos no son aptos para usarse en protoboard. 
Entonces realicé unos pequeños adaptadores en PCB, y hasta con máscara antisoldante. 

Posteriormente hice el diseñó para el cual tenía pensado usar los módulos.
(Un sistema de control de iluminación con LEDs para una discoteca.)
Tras armar las tarjetas, todo funcionó correctamente al primer encendido.
El sistema funcionó tal cual se requería y se había programado, sin ninguna falla. (Hasta el momento)

Ahora les comparto un proyecto, pero para encender y apagar un simple LED.
Incluye los esquemas y diseños para los PCB, así como también el footprint que usé como adaptador.
(Este footprint les servirá si desean hacer pruebas en protoboard.)

El sistema está funcionando físicamente y no deben tener problemas si realizan todo como está en los esquemas.
Usé dos PIC16F690, ya que con esos realicé mi prototipo.
(Tienen módulo SSP, oscilador interno y la cantidad de pines que yo necesitaba.)

Nota:
Recuerden que si se desea usar otro PIC, éste debe tener  módulo SSP, y no olvidar configurar los pines a usar en la librería.

Espero les sea de utilidad.


----------



## dcsalg (Mar 14, 2016)

Ahora lo voy a ver, pero otra consulta, vos diste un detalle, vos tenes los modulos para proteus para simularlo? porque la verdad ya nose.   Lindo seria saber si mis modulos funcionan hay manera de saberlo eso?. Y como dije voy a observar eso que esta en el rar , y tal cual queria eso solo sencillo encender o apagar un led mediante un boton o lo que sea pero nunca lo logre comunicar. espero entenderlo.  vos sabes mucho y la verdad nose mucho de esto con spi. 

perdon ahi vi que pusiste tambien las librerias para proteus


----------



## D@rkbytes (Mar 14, 2016)

Las librerías adjuntas del NRF24L01, no sirven para simulación.
Son para realizar el diagrama esquemático que posteriormente se usará para crear el circuito impreso.

La única forma de saber si los módulos funcionan, es realizando una prueba en físico.
El proyecto que subí funciona perfectamente y debe funcionar con cualquier PIC que tenga módulo SSP.
Nada más se necesita configurar los pines conforme al PIC que se quiera usar.


----------



## dcsalg (Mar 15, 2016)

Te comento, yo tengo los dos pic16F819 que programe uno como TX y el otro RX con sus respectivos modulos NRF24L01, (que la verdad nose si funcionan porque hice de todo) la realidad que no pasa nada solo me enciende el led como que envia el dato segun tu programa, lo que hice fue modificar unos puntos para poder utilizarlos con mis pic. 

Por favor podrias verlos porque la realidad no me funciona esta todo armado en un protoboard y prolijo nada de nada solo el led en mi pic transmisor como que envia el dato. Ahi te adjunto los archivos. Maestro ayudame por favor.

Todo fisico lo pruebo nada de simulado todo lo que te explico


----------



## luvhines (Mar 15, 2016)

hola dcsalg, te recomiendo que no te sales las configuraciones iniciales del microcontrolador son muy importantes, 

preguntas:

- Estas alimentando todo con una fuente de pc ? o baterías ? créeme que es muy importante también

- Estas alimentando todo a 3.3v? incluyendo los pics?

recomendaciones (aparte de las de arriba):

- no omitas las configuraciones iniciales del micro créeme que tuve problemas por eso

- para empezar trata de hacer lo mas simple posible tu código, cuando te funcione si retocalo todo lo que quieras, lo digo porque haces varios llamados a la funcion RF_RECEIVE() en tu receptor, te recomiendo que empezando trabajes solamente con la que esta en la interrupción, lo mismo para el emisor 

-haciendo pruebas creo que también tuve problemas cuando asignaba valores enteros al array RF_DATA[0], prueba asignando valores hexadecimales primero


----------



## dcsalg (Mar 16, 2016)

Esta tarde voy a intentar de nuevo. A ver que sucede. La alimentación de la pc , tendría que utilizar una fuente no?, lo de RF_RECEIVE voy a colocarlo en una interrupción, lo había sacado  en su momento de ahí porqué tenía miedo que no funcionara la interrupcion. Como esta adentro de un bucle, me aseguraba sólo que lo iba a leer seguro. Pero voy a probar y te cuento esta tarde y te envío lo que hice

en lo siguiente deje el codigo asi, sigue sin funcionar. Los pic si estan Barbaros funcionan. no entiendo,. La alimentacion lo hago con un TTL que estoy ulizando en la PC que lo conectas a usb y entrega 5v y 3.3V. No creo que tenga problema eso, con eso mismo alimente dos pic que se comunicaban no por este medio sino por cable y funcionaban. Pero me supero esto ya nose que hacer?

el programa del transmisor es el mismo que esta en el archivo que subi anteriormente el RAR


```
#include <16f819.h>
//#fuses   nofcmen
#use     delay(internal = 4MHz)

#include "lib_rf2gh4_10.h"

#define  led   PIN_A1

// Servicio de interrupción externa por RB0
#int_ext
void sdi_rb0()
{
   int8 ret;

   ret = RF_RECEIVE();           // "ret" contendrá el valor que le llegue del emisor
   
   if ( (ret == 0) || (ret == 1) ) // Tanto si hay recepción simple o múltiple, leer datos.
   {
      do
      {
         ret = RF_RECEIVE();     // "ret" nos dirá si hay recepción simple, múltiple o no hay datos para leer.
         
            switch (RF_DATA[0])  // Seleccionar los datos que hay en RF_DATA[0]
            {
               case 1:
                  output_high(led);
                  break;
               case 0:
                  output_low(led);
            }
      }
      while ( (ret == 0) || (ret == 1) ); // Mientras haya datos para leer, seguir leyendo.
   }  
}

void main (void)
{  int8 ret;
   output_low(led);              // Inicialmente el LED estará apagado.
   
   
   
   RF_INT_EN();                  // Habilitar interrupción por RB0.
   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)
   {
      sleep();
      delay_cycles(127);
     
       
   }
}
```


----------



## luvhines (Mar 16, 2016)

compa te comento de nuevo no te saltes las configuraciones para tu micro me refiero a esta parte : 

```
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);
```

Asi como tampoco las directivas del preprocesador. mi pregunta es si estas alimentando todo a 3.3 v tanto los pics como los NRF? y te recomiendo que la alimentación sea con una fuente de PC o con  baterías y un regulador como el Ld33v puesto que estos módulos son muy susceptibles al ruido, y pueda que los micros funcionen pero los NRF ni a palos


----------



## D@rkbytes (Mar 16, 2016)

Todas esas configuraciones son innecesarias, ya que son las que establece por defecto el compilador.
Lo puedes comprobar mirando los valores de los registros en Watch Window.


dcsalg dijo:


> Te comento, yo tengo los dos PIC16F819 que  programé uno como TX y el otro RX, con sus respectivos módulos NRF24L01  (que la verdad no sé si funcionan porque hice de todo)
> En la realidad no  pasa nada, sólo me enciende el led como que envía el dato según tu  programa.
> Lo que hice fue modificar unos puntos para poder utilizarlos  con mis pic.
> 
> ...


Te adjunto los programas y esquemas modificados para usar el PIC16F819 en ambos.
Si montas los circuitos tal y como están los esquemas, deben funcionar físicamente.

Suerte.


----------



## dcsalg (Mar 17, 2016)

D@rkbytes, lo probe como digiste ya desconfio que esten quemados es increible porque los compre hace poco esos modulos, y la verdad mo logro hacerlos funcionar. probe repito lo que me pasaste y nada. se me quedan encendidos los dos leds del transmisor por lo tanto no esta enviando nada. . por eso digo si ya con lo que me enviaste no funciono estaran quemados los modulos. Lastima porque nose si tienen un testeo para asegurarme eso. o si lo tienen?


----------



## D@rkbytes (Mar 17, 2016)

Posiblemente si se dañaron durante las varias pruebas que haz realizado.
Yo no uso arduino, pero también los puedes probar con una cosa de esas.
Desafortunadamente no tengo los PIC16F819, pero los puedo conseguir fácilmente y probar con ellos.
Sin embargo, son similares en funciones al PIC16F690 con los que yo hice mi proyecto.

Recuerda que, tanto el PIC como el módulo, deben estar alimentados con 3.3V.


----------



## dcsalg (Mar 17, 2016)

Upsss ehh yo alimente los pics con 5v y los módulos con 3.3v. 
Paso algo por eso?


----------



## D@rkbytes (Mar 17, 2016)

Pueden pasar dos cosas:


 No se establecerá la comunicación entre el microcontrolador y el NRF24L01
Se puede dañar el NRF24L01 por exceso de voltaje en sus entradas.
Por eso es importante poner atención a los esquemas.


----------



## dcsalg (Mar 18, 2016)

Compraré otros y bueno, probaré. Así q*ue* en un tiempo escribiré por aquí de nuevo a ver que me pasó.


----------



## luvhines (Mar 19, 2016)

Amigo los pines de señal del NRF24l01 son tolerantes a 5v OJO! solo los pines de señal pero su alimentación no debe ser mayor a 3.3v, puedes alimentar los pics a 5v y los NRF24l01 a 3.3v pero para evitar problemas con los niveles TTL,  debes colocar una resistencia de 1k entre +5v y el pin MISO(7) del NRF o bien debes alimentar todo a 3.3v


----------



## dcsalg (Abr 18, 2016)

entonces se quemaron o algo paso o vinieron fallados porque no me responde nada , por eso voy a comprar otros dos estoy esperando a que me lleguen los modulos aun. estan mas baratos afuera


----------



## allemore (Jun 6, 2016)

Buenas tardes luvhines,

He hecho de todo para hacer funcionar estos módulos con el pic 16f887 y 16f877a, de hecho, tengo un led de prueba para observar si encienden y creo que ni eso hacen (aunque si tiene voltaje en los pines del modulo).

No se que puedo estar haciendo mal, hasta copie y pegue tu código y no reaccionan. Me pregunto si las modificaciones que le hiciste a la librería podrían ser mi problema también?, creo que sería de ayuda si me pudieras facilitar tu librería con las modificaciones, si no es molestia.

A continuación mi código:


```
#include <16f877.h>
#fuses HS,NOWDT,XT,NOPROTECT,NODEBUG,NOBROWNOUT,NOLVP,NOCPD,NOWRT                        
#use delay(clock=4000000)
#include "lib_rf2gh4_10.h"
#byte porta=5
#byte porte=9
#define porte,0 PIN_E0

int8 ret1;
int8 ret2;
int8 i;
int8 ON;

#int_ext         
void int_externo() 
{ 
   ret1=RF_RECEIVE;
   porta=RF_DATA[0];
   
}
void main()
{  
   port_b_pullups(FALSE);        
   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);

   set_tris_a(0b000000);     
   porta=0;
   set_tris_e(0b000);
   setup_spi(SPI_SS_DISABLED);
   RF_INT_EN();
   RF_CONFIG_SPI();
   RF_CONFIG(0x40,0x01);
   RF_ON();
   ON=RF_ON;
   delay_ms(1000);
   
   if (ON==1)
  {  output_high(PIN_E0);
      while(1)
    { Delay_ms(5000);
      RF_DIR=0x08;
      for (i=0;i<8;i++)
      {
         RF_DATA[i]=1;
      }
      ret2=RF_SEND();
    }
  }
   
}
```


----------



## D@rkbytes (Jun 6, 2016)

Dentro del tema se encuentra toda la información que requieres y también la librería modificada.


D@rkbytes dijo:


> Noté que existían varias advertencias cuando se hacía el cambio de modo Master/Slave.
> Así que en modo de depuración me dediqué a corregir la librería "lib_rf2gh4_10.h"


En el único programa que expones, tienes varias cosas mal.
Dices usar dos tipos de PIC, uno de ellos, el 16F877*A*, pero declaras: *#include <16f877.h> 

**#byte porta=5
#byte porte=9
#define porte,0 PIN_E0*
La tercer declaración no es correcta para definir un pin.
En dado caso, tendría que ser así: *#bit  RE0 = porte.0
*O así: *#define* *RE0 PIN_E0

*Tienes un uso incorrecto para llamar a una función:*
ret1=RF_RECEIVE;
*Agregar los paréntesis:* ret1=RF_RECEIVE();

*Tienes configuraciones innecesarias para el microcontrolador:


```
port_b_pullups(FALSE);        
   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);
```



D@rkbytes dijo:


> Todas esas configuraciones son innecesarias, ya que son las que establece por defecto el compilador.
> Lo puedes comprobar mirando los valores de los registros en Watch Window.


Mira la información y los programas adjuntos del _post #26_


----------



## allemore (Jun 6, 2016)

Gracias, d@rkbytes, haré las que recomiendas.Estoy un poco nueva en esto 



Cuando intento igualar el retorno 3 (ret3), con el comando de encendido del modulo no me lo permite y me dice "A numeric expression must appear here", quisiera saber por qué pasa esto si en la interrupción estoy haciendo lo mismo con el comando RF_RECEIVE()


```
#include <16f877.h>
#fuses HS,NOWDT,XT,NOPROTECT,NODEBUG,NOBROWNOUT,NOLVP,NOCPD,NOWRT                        
#use delay(clock=4000000)
#include "lib_rf2gh4_10.h"
#byte porta=5
#byte porte=9
#bit RE0 = porte.0

int8 ret1;
int8 ret2;
int8 i;
int8 ret3;

#int_ext         
void int_externo() 
{ 
   ret1=RF_RECEIVE();
   porta=RF_DATA[0];
   
}
void main()
{  
   set_tris_a(0b000000);     // Todo el puerto D como salida.
   set_tris_e(0b000);
   setup_spi(SPI_SS_DISABLED);
   RF_INT_EN();
   RF_CONFIG_SPI();
   RF_CONFIG(0x40,0x01);
   RF_ON();
   ret3=RF_ON();
   delay_ms(1000);
   
   if (ret3==1)
  {  output_high(PIN_E0);
      while(1)
    { Delay_ms(5000);
      RF_DIR=0x08;
      for (i=0;i<8;i++)
      {
         RF_DATA[i]=0x01;
      }
      ret2=RF_SEND();
    }
  }
   
}
```


----------



## D@rkbytes (Jun 6, 2016)

allemore dijo:


> Cuando intento igualar el retorno 3 (ret3), con el comando de encendido del modulo no me lo permite y me dice "A numeric expression must appear here", quisiera saber por qué pasa esto si en la interrupción estoy haciendo lo mismo con el comando RF_RECEIVE()


Porque RF_ON no retorna nada, es una subrutina.
Tan sólo puedes llamarla:
RF_ON();

*void RF_ON()
{
}
*Y RF_RECEIVE() si es una función que puede retornar un valor.
*int RF_RECEIVE()
{
}

*Nota que las rutinas que pueden devolver valores, tienen al  inicio el tipo que deben retornar.
*Int* o *Int8* en PIC C de CCS = 8 Bits. (1 Byte)
*Void* = Sin retorno. (O retorno Nulo)

Cuando las rutinas no contienen nada entre los paréntesis, también se entiende como *Void.
*En éste caso; rutina sin retorno y sin parámetros.*
void mi_rutina (void)
{
}

*Rutina con retorno y con parámetros:*
int16 mi_funcion (int8 param1, int8 param2)
{
int16 x = param1 + param2;
return (x);
}
*


----------



## sadj (Nov 17, 2016)

buenas tardes luvhines, e visto todos los comentarios que se han dicho es te foro con respecto al modulo nfr NRF24L01 y su funcionamiento es muy bueno, pero tengo una pregunta es posible enviar una cadena de texto "String" o un "hola mundo ", que el maestro envíe el hola mundo y que el esclavo lo reciba y cuando lo reciba enviarlo por serial para verlo en pc.
muchas gracias podría aclarar me esa duda.


----------



## el_patriarca (Nov 18, 2016)

Puedes hacerlo enviando los caracteres uno a uno en hexadecimal. El receptor, o esclavo, lo va almacenando en la EEPROM, y cuando se haya finalizado la transmisión lo envía a la PC.


----------



## rich34 (Dic 18, 2016)

Hola.

ante todo, muchas gracias por todo lo compartido.

en los primeros posts hay algunas orientaciones sobre la distancias. Yo aún no recibí mis módulos pero ya quiero empezar a armar los PCB.

Me gustaría saber en que posición de los módulos se tiene la mejor recepción. paralelos o perpendiculares al piso? 

Gracias por los comentarios que puedan compartir.

Saluds.


----------



## luvhines (Ene 14, 2017)

rich34 dijo:


> Hola.
> 
> ante todo, muchas gracias por todo lo compartido.
> 
> ...



Hola, a mi experiencia la posición del modulo no es algo que importe realmente mi amigo.





sadj dijo:


> buenas tardes luvhines, e visto todos los comentarios que se han dicho es te foro con respecto al modulo nfr NRF24L01 y su funcionamiento es muy bueno, pero tengo una pregunta es posible enviar una cadena de texto "String" o un "hola mundo ", que el maestro envíe el hola mundo y que el esclavo lo reciba y cuando lo reciba enviarlo por serial para verlo en pc.
> muchas gracias podría aclarar me esa duda.



como dice el compañero más abajo, puedes ver que el modulo envía cada vez un paquete de 8bits que en en el emisor es el estado de un puerto, y el receptor refleja el estado de ese puerto, pero no deja de ser un simple paquete de 8bits, bien puedes usar la tabla ascii para tu propósito, en lugar del estado de un puerto envías un carácter que por naturaleza es un hexadesimal y lo recibes en el receptor.


----------



## vantware (Mar 30, 2017)

Hola a todos. Estuve probando el ejemplo expuesto aquí y no me funciona. Grabe los 2 pics sin modificarle nada y estoy alimentado mis pics con un regulador (mas o menos 4v) y los nrf con unas bases que traen regulador incluido. Cuando lo pruebo siempre obtengo que el ack no fue recibido..... ayuda D@rkbytes por favor!!!!!!!


----------



## D@rkbytes (Mar 30, 2017)

Por favor, adjunta tu proyecto completo dentro de un archivo comprimido, recuerda que no somos adivinos.
Si aún no sabes cómo subir archivos, mira por aquí: *¿Cómo subo imágenes y archivos?*


----------



## vantware (Mar 30, 2017)

D@rkbytes
Es tu ejemplo con el pic 16f690 sin cambio alguno. Lo que hace es que el transmisor me marca que no recibe ack y el receptor no hace nada. Probé las antenas con módulos usb y si funcionan. Lo único que no he probado es alimentar todo a 3.3 ya que los pics los tengo a 4v y las antenas con una base que incluyen regulador.

Mañana subo fotos, por cierto está en protoboard


----------



## D@rkbytes (Mar 31, 2017)

Ese proyecto está probado físicamente y funciona al 100%
Realiza todo tal cual y debe funcionar.
Principalmente, usa los reguladores de 3.3 V que usa el proyecto. (L78L33)


----------



## vantware (Mar 31, 2017)

D@rkbytes dijo:


> Ese proyecto está probado físicamente y funciona al 100%
> Realiza todo tal cual y debe funcionar.
> Principalmente, usa los reguladores de 3.3 V que usa el proyecto. (



Hola de nuevo, pues según yo todo esta bien cableado. lo revise como 3 veces.
adjunto una foto de como lo tengo.

Saludos y gracias por la ayuda


----------



## el_patriarca (Mar 31, 2017)

Yo tuve un problema con los conectores que estás usando: no hacían buen contacto con los módulos.

Trata de fabricar un zócalo para los módulos, de manera que puedas conectarlos directamente al protoboard sin necesidad de cables. 


Otro: trata de peinar tus cables, un poco de prolijidad te ayudará a detectar fallas.


----------



## D@rkbytes (Mar 31, 2017)

Sí. Por ese motivo diseñé los footprints para los módulos. Jamás me pasó por la mente conectarlos con cables.
También es muy importante la calidad del protoboard.
Yo he tirado varios que con el uso van presentando fallas, e incluso también he comprado algunos que desde nuevos se van directamente al bote de la basura.

El sistema que desarrollé con esos módulos sigue funcionando actualmente y no ha tenido problemas.


----------



## vantware (Mar 31, 2017)

Gracias por la ayuda. Voy a soldar las bases que compré a ver si así logró hacerlo funcionar y comentaré

De nuevo muchas gracias


----------



## rafgui12 (Sep 13, 2017)

Hola

Queria preguntar tu podrias compartir la libreria de NRF24L01 de proteus veo en las imagenes que la usas pero en el proyecto no lo vi


----------



## D@rkbytes (Sep 13, 2017)

Las librerías del nRF24L01 para proteus, no son para simular, tan sólo son para crear el esquema y el PCB.
En este post están las que yo diseñé: _post #26_


----------



## keeim (Jul 27, 2018)

Saludos a todos, utilice el código del _post #30 _,para utilizarlo con PIC*16F628A*, pero el programa no me hace la copilación, ya que, me sale un error de librería en el Transmisión y el Receptor.  
Los pines en ambos datasheet salen iguales solo cambie el *include.*


----------



## D@rkbytes (Jul 29, 2018)

keeim dijo:


> Saludos a todos. Utilicé el código del _post #30 _para utilizarlo con un PIC*16F628A*, pero el programa no me hace la compilación, ya que me sale un error en la librería del Transmisor y el Receptor.
> Los pines en ambos datasheet salen iguales solo cambie el *include.*


El PIC16F628A no tiene módulo SSP para poder usar SPI por hardware.
Por eso es que el compilador muestra el error "Undefided Identifier -- spi_write"
Usa SPI por software con: #USE SPI (_options_)


----------



## Fernando Lara (Ene 4, 2019)

Buenas tardes...

Me pueden ayudar como conseguir la librería del modulo NRF24L01 para Proteus, para poder simularlo. Muchas gracias.
Saludos


----------



## D@rkbytes (Ene 4, 2019)

Por el momento no existen, Labcenter no las ha creado y tampoco otra persona.


----------



## CARLSEVALA (Ago 7, 2020)

Hola d@rkbytes, felicitarte por tu aporte muy bueno, soy algo nuevo en esto de la radiofrecuencia por pic, hice uno con el pic 16f876a funcionan de maravilla el TX y RX, pero a medida que pasa el tiempo porque debe estar *encendido 24/7* *todo el* *año*, a veces se queda congelado o no responde,a que se deberia ese problema? . Porfavor cual es tu opinion? Y solo vuelve a funcionar si lo apago y vuelvo a encender.


----------



## DJ T3 (Ago 7, 2020)

Puede ser que se trabe el programa.
Podrias compartirlo el de ambos (tx/rx)?
Cual seria el funcionamiento?


----------



## CARLSEVALA (Ago 7, 2020)

_*Este es el código del emisor*_ 
#Include <16F876A.h>
#fuses NOWDT, XT, PUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, 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()               // Si te da error esta línea, sustituir por: *void int_ext_isr(void)*.
{                            // 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()
{  
   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.
   }
}
_*Código del receptor*_
#include <16F876A.h>
#FUSES NOWDT, XT, PUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, 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()             // Si te da error esta línea, sustituir por: *void int_ext_isr(void)*.
{
   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.
{
   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. 

}
Ambos estan compilados en ccs
Porfavor si alguien sabe el Motivo de porque podria colgarse esporadicamente


----------



## DJ T3 (Ago 8, 2020)

Personalmente no veo nada extraño.
No se si algo de fuses, o alguna configuracion que se me escape.
Podrias decir bien en qué situaciones se da el cuelgue y cual de los dos pic?
Aparte del pic y el modulo rf, tenes conectado algo mas?
Como los alimentas?

PD: Para la proxima adjunta el codigo dentro de una etiqueta, aca cómo se hace [TUTO] ¿Cómo subir archivos? (XenForo)


----------



## D@rkbytes (Ago 8, 2020)

DJ T3 dijo:


> ¿Podrias decir bien en qué situaciones se da el cuelgue y cuál de los dos PIC?


Exactamente eso es lo que hace falta saber.
Viendo los códigos lo único que puede causar dudas es el "while ( (ret1 == 0) || (ret1 == 1) ); "
O sea que eso genera un bucle infinito sin hacer otra cosa que esperar un 1 o un 0
Habrá que ver si la librería responde con otra cosa para que se pueda salir del bucle.


----------



## CARLSEVALA (Ago 8, 2020)

Muchas gracias por responder, parece ser que se cuelga el Emisor porque cuando le doy reset o lo apago y prendo vuelve a funcionar sin problemas, se cuelga de repente no se el momento preciso y las circunstancias exactas ya que debe estar encendido todo el tiempo, adjuntare el código y la libreria mas tarde espero lo vean, de nuevo muchas gracias por su tiempo


----------



## DJ T3 (Ago 8, 2020)

Si D@rk, lo primero que pense, pero me fije en la libreria (la cual adjunto sacada de *todopic*), y son diferentes banderas, osea que el 0 y el 1, son banderas que indican si hay datos, si no los hay, manda mas de "2".

Ya que ya adjunte la libreria, mejor dinos lo que te consulte mas arriba


----------



## D@rkbytes (Ago 9, 2020)

CARLSEVALA dijo:


> parece ser que se cuelga el Emisor porque cuando le doy reset o lo apago y prendo vuelve a funcionar sin problemas, se cuelga de repente no sé el momento preciso y las circunstancias exactas ya que debe estar encendido todo el tiempo


Entonces podrías dejar que el Watch-dog Timer haga su trabajo.


----------



## DJ T3 (Ago 9, 2020)

D@rkbytes dijo:


> Entonces podrías dejar que el Watch-dog Timer haga su trabajo.



Pero si mal no veo, tiene el WatchDog deshabilitado en los fuses, "NOWDT". Deberia estar activo, no?


----------



## D@rkbytes (Ago 10, 2020)

Pues sí, y resetearlo en los lugares donde se crea que no haya problemas.
Si el WDT se resetea en donde el programa se pueda colgar, no serviría de nada.


----------



## alejo278 (Ene 13, 2021)

Hola a todos.
Alguno de ustedes los a logrado andar en PBP?


----------



## resistencio (Sep 7, 2022)

Como se emularía SPI por software, para micros que no tengan estos módulos, y que precauciones hay que tener presente...???


----------



## DJ T3 (Sep 7, 2022)

Depende del software con que programes, puede ya disponer de librerias que lo hagan por tí.
En caso que no la tengas, deberás estudiar el protocolo.

Mas que precaución, yo diría que lo tengas en cuenta.
La emulación por software implica gastos de recursos, así que se te reduce la memoria de programa y RAM, y aumenta el uso de CPU, aumentando los tiempos de ejecución.
Y dependiendo de la librería, puede consumirse interrupciones, pines y timers.


----------



## resistencio (Sep 7, 2022)

Gracias DJT3...quería ensayar el programa de d@rkbytes, para ir a lo seguro (jaja...es un genio encubierto y me convertí en su "salieri") y leí por ahí que le decía a alguien que usaba el 16f628a que debía emular el protocolo...estoy usando CCS y hasta ahora sabía que se podía emular RS232, pero no me aparece nada en concreto sobre emular SPI...voy a seguir buscando o esperar que d@rkbytes se inspire con algo que quiera compartir.


----------



## switchxxi (Sep 10, 2022)

Quizás no es la forma mas optimizada para hacerlo pero:

La función en C seria así (para el Modo 0):


```
unsigned char spi_write(unsigned char byte)
{
      unsigned char i, SPI_Valor = 0;

      for (i = 0; i < 8; i++) { // 8 bit a transmitir
                                         SCK = 0;
                                         MOSI = (byte & 128) >> 7;
                                         SCK = 1;
                                         SPI_Valor = SPI_Valor << 1;
                                         SPI_Valor = SPI_Valor | MISO;
                                         byte = byte << 1;
                                      }
      MOSI = 1;
      return SPI_Valor;
}
```

Ojo que el ejemplo es para datos de 8 bits.




(Después subo al foro lo que había escrito, en mi blog, sobre el protocolo SPI).


----------

