Comunicación PIC - Arduino usando NRF24L01

Muy buenas a todos, soy nuevo en el foro. Tengo un problema de programación que no logro resolver y estaría necesitando ayuda; la idea es intercomunicar un PIC16F887 con un Arduino MEGA usando el transceptor NRF24L01, básicamente la idea principal es tener varios esclavos con los pics, y que el arduino mega sea el maestro, pero de momento lo único que estoy buscando es lograr una comunicación de la forma que sea (Que el PIC envíe datos, o que el arduino envíe datos, o que los dos sean transmisores y receptores). De igual forma debajo compartiré el progreso de mi programación. En un futuro subiré colaboraciones de proyectos hechos, ya había trabajado con transceptores, específicamente el XBEE, para hacer un robot con el 16F887, pero quiero probar el NRF, es mucho más barato y tiene un rango de alcance muy elevado.
Esta es la programación del PIC16F887
C:
#include<16F887.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

void int_ext_isr(void)              // 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.
   }
}
Y esta la programación del arduino MEGA
C++:
#include <SPI.h>

#include <nRF24L01.h>

#include <RF24.h>


//Declaremos los pines CE y el CSN para NRF24L01

#define CE_PIN 7

#define CSN_PIN 8


byte direccion[6] = {8};  // Dirección elegida en el PIC (0x08)

RF24 radio(CE_PIN, CSN_PIN);  // Creael objeto radio (NRF24L01)

char datos[10];   // Buffer para los datos recibidos


void setup(){

  radio.begin();   //inicializamos el NRF24L01

//---------------------------------------------------------------------------------------

    // Posibles ajustes de ptencia.

    // RF24_PA_MIN = -18dBm, RF24_PA_LOW = -12dBm, RF24_PA_HIGH = -6dBm, RF24_PA_MAX = 0dBm

//---------------------------------------------------------------------------------------

  radio.setPALevel(RF24_PA_MAX); // Potencia máxima (irrelevante en modo escucha)

  Serial.begin(9600);

  radio.setChannel(64); // canal escogido en el pic (0x40)

  radio.openReadingPipe(1, direccion);  // Modo escucha siempre llamar antes que radio.startListening()

  radio.startListening();   // Modo escucha activo

}


void loop() {

  if ( radio.available())   // Datos disponibles?

{ 

     radio.read(datos,sizeof(unsigned long));  // Leer los datos

     Serial.println(datos);     // Mostrar los datos en el puerto serial

}

delay(1000);

}
 
Depura el código con una conexión directa uart-uart y luego pones enmedio lo que sea.


Suele ser más eficiente primero hacer pc-pic y pc Arduino y después quitar el pc de.enmedio.

Ahora.mismo no va y no sabes por qué
 
Depura el código con una conexión directa uart-uart y luego pones enmedio lo que sea.


Suele ser más eficiente primero hacer pc-pic y pc Arduino y después quitar el pc de.enmedio.

Ahora.mismo no va y no sabes por qué
Hola, gracias por responder, la comunicación que se usa en el NRF24L01 es SPI, no logro entender lo que podría hacer conectando el PIC a la PC usando la comunicación uart, disculpa mi ignorancia en el tema
 
Última edición:
Para arduino hay una libreria para nRF24L01 que crea una red entre varios tranceptores.
Quizas podrias buscarla y adaptarla para PIC (dependiendo del lenguaje que uses). No logre encontrarla
 
Muy buenas! Logré encontrar una solución y voy a compartirla. Encontré una librería genérica para el arduino y para el PIC. Lo que hace el ejemplo es mandar un valor del 0 al 255 desde el PIC hacia el Arduino. El trabajo que encontré se lo debo a "Luis Castellanos", realmente no sé si se encuentra en el foro, pero vale mucho la pena mencionar.
Programa para el ARDUINO MEGA
Código:
#define IRQ_pin                         6 
#define CE_pin                          7
#define SS_pin                          8
#define MOSI_pin                        51
#define MISO_pin                        50
#define SCK_pin                         52

#define R_REGISTER_cmd                0x00
#define W_REGISTER_cmd                0x20
#define R_RX_PL_WID_cmd               0x60
#define R_RX_PAYLOAD_cmd              0x61
#define W_TX_PAYLOAD_cmd              0xA0  
#define W_ACK_PAYLOAD_cmd             0xA8
#define W_TX_PAYLOAD_NO_ACK_cmd       0xB0
#define FLUSH_TX_cmd                  0xE1
#define FLUSH_RX_cmd                  0xE2
#define REUSE_TX_PL_cmd	              0xE3
#define NOP_cmd                       0xFF

#define CONFIG_reg   		      0x00
#define EN_AA_reg                     0x01
#define EN_RXADDR_reg                 0x02
#define SETUP_AW_reg		      0x03
#define SETUP_RETR_reg                0x04                             
#define RF_CH_reg		      0x05                 
#define RF_SETUP_reg                  0x06
#define STATUS_reg                    0x07
#define OBSERVE_TX_reg                0x08
#define RPD_reg                       0x09
#define RX_ADDR_P0_reg                0x0A
#define RX_ADDR_P1_reg                0x0B
#define RX_ADDR_P2_reg                0x0C
#define RX_ADDR_P3_reg                0x0D
#define RX_ADDR_P4_reg                0x0E
#define RX_ADDR_P5_reg                0x0F
#define TX_ADDR_reg                   0x10
#define RX_PW_P0_reg                  0x11
#define RX_PW_P1_reg                  0x12
#define RX_PW_P2_reg                  0x13               
#define RX_PW_P3_reg                  0x14
#define RX_PW_P4_reg                  0x15
#define RX_PW_P5_reg                  0x16
#define FIFO_STATUS_reg               0x17
#define DYNPD_reg                     0x1C
#define FEATURE_reg                   0x1D


unsigned char x, uchartemperatura, uchartemperatura1 = 0;
int t, h;


unsigned char nRF24L01_read()
{
  unsigned char s = 0;
  unsigned char msg = 0;
  
  for(s = 0; s < 8; s++)
  {
      msg <<= 1;
      digitalWrite(SCK_pin, HIGH); 
      if(digitalRead(MISO_pin) != 0)
      {
        msg |= 1;
      }
      digitalWrite(SCK_pin, LOW); 
  }
  
  return msg; 
}


void nRF24L01_write(unsigned char d)
{
  unsigned char s = 0;
  
  for(s = 0; s < 8; s++)
  {
    if((d & 0x80) != 0)
    {
      digitalWrite(MOSI_pin, HIGH);
    } 
    else
    {
      digitalWrite(MOSI_pin, LOW);
    }
    d <<= 1;
    digitalWrite(SCK_pin, HIGH); 
    digitalWrite(SCK_pin, LOW); 
  }
}


void register_write(unsigned char reg, unsigned char value)
{
  digitalWrite(SS_pin, LOW);
  nRF24L01_write((reg | W_REGISTER_cmd));
  nRF24L01_write(value);
  digitalWrite(SS_pin, HIGH);
}


void write_command(unsigned char cmd)
{
  digitalWrite(SS_pin, LOW);
  nRF24L01_write(cmd);
  digitalWrite(SS_pin, HIGH);
}


unsigned char register_read(unsigned char reg)
{
  unsigned char value = 0;
  
  digitalWrite(SS_pin, LOW);
  nRF24L01_write((reg | R_REGISTER_cmd));
  value = nRF24L01_read();
  digitalWrite(SS_pin, HIGH);
  
  return value;
}


void set_TX_RX_address(unsigned char *addr, unsigned char bytes, unsigned char reg)
{
  unsigned char n = 0;
  
  digitalWrite(SS_pin, LOW);
  nRF24L01_write((reg | W_REGISTER_cmd));
  for(n = 0; n < bytes; n++)
  {
    nRF24L01_write(addr[n]);
  }
  digitalWrite(SS_pin, HIGH);
}


void flush_TX_RX()
{
  register_write(STATUS_reg, 0x70);
  write_command(FLUSH_TX_cmd);
  write_command(FLUSH_RX_cmd);
}


void send_data(unsigned char bytes, unsigned char *value)
{
  unsigned char s = 0;
  
  flush_TX_RX();
  register_write(CONFIG_reg, 0x3A);
  
  digitalWrite(SS_pin, LOW);
  nRF24L01_write(W_TX_PAYLOAD_cmd);
  for(s = 0; s < bytes; s++)
  {
    nRF24L01_write(value[s]);
  }
  digitalWrite(SS_pin, HIGH);

  digitalWrite(CE_pin, HIGH);
  delayMicroseconds(60);
  digitalWrite(CE_pin, LOW);
  
  register_write(CONFIG_reg, 0x38);
}

void receive_data(unsigned char bytes, unsigned char *value)
{
  unsigned char s = 0;
  
  digitalWrite(SS_pin, LOW);
  nRF24L01_write(R_RX_PAYLOAD_cmd);
  for (s = 0; s < bytes; s++)
  {
    value[s] = nRF24L01_read();
  }
  digitalWrite(SS_pin, HIGH);
}


void nrF24L01_TXinit()
{
  unsigned char address[5] = {0x99, 0x99, 0x99, 0x99, 0x99};
  
  digitalWrite(CE_pin, LOW);
  
  register_write(SETUP_RETR_reg, 0x00);
  register_write(SETUP_AW_reg, 0x03);
  register_write(RF_SETUP_reg, 0x0E);
  register_write(RF_CH_reg, 0x09);  
  register_write(EN_AA_reg, 0x00);
  register_write(CONFIG_reg, 0x38);
  set_TX_RX_address(address, 5, TX_ADDR_reg);
  set_TX_RX_address(address, 5, RX_ADDR_P0_reg);
  flush_TX_RX();
  
  digitalWrite(CE_pin, HIGH);
}

void nrF24L01_RXinit()
{
  unsigned char address[5] = {0x99, 0x99, 0x99, 0x99, 0x99};
  
  digitalWrite(CE_pin, LOW);
  
  register_write(CONFIG_reg, 0x38);
  register_write(SETUP_RETR_reg, 0x00);
  register_write(SETUP_AW_reg, 0x03);
  register_write(RF_SETUP_reg, 0x0E);
  register_write(RF_CH_reg, 0x09);  
  register_write(EN_AA_reg, 0x00);
  register_write(RX_PW_P0_reg, 0x01);
  register_write(CONFIG_reg, 0x3B);
  set_TX_RX_address(address, 5, TX_ADDR_reg);
  set_TX_RX_address(address, 5, RX_ADDR_P0_reg);
  flush_TX_RX();
  
  digitalWrite(CE_pin, HIGH);
}

unsigned char get_Status_Reg()
{
  return register_read(STATUS_reg);
}



void setup()
{
  unsigned char val = 0;
  
  pinMode(IRQ_pin, INPUT_PULLUP);
  pinMode(MISO_pin, INPUT);
  pinMode(CE_pin, OUTPUT);
  pinMode(SS_pin, OUTPUT);
  pinMode(SCK_pin, OUTPUT);
  pinMode(MOSI_pin, OUTPUT);

  digitalWrite(CE_pin, LOW);
  digitalWrite(SS_pin, LOW);
  digitalWrite(SCK_pin, LOW);
  digitalWrite(MOSI_pin, LOW);
  
  Serial.begin(9600);
  Serial.flush();
  
  nrF24L01_RXinit();
  
  delay(900);
  
  val = register_read(SETUP_RETR_reg);
  Serial.print("SETUP_RETR: 0x");
  Serial.println(val, HEX);
  
  val = register_read(SETUP_AW_reg);
  Serial.print("SETUP_AW: 0x");
  Serial.println(val, HEX);
  
  val = register_read(RF_SETUP_reg);
  Serial.print("RF_SETUP: 0x");
  Serial.println(val, HEX);
  
  val = register_read(RF_CH_reg);
  Serial.print("RF_CH: 0x");
  Serial.println(val, HEX);
  
  val = register_read(EN_AA_reg);
  Serial.print("EN_AA: 0x");
  Serial.println(val, HEX);
  
  val = register_read(CONFIG_reg);
  Serial.print("CONFIG: 0x");
  Serial.println(val, HEX);
}


void loop()
{
  if(get_Status_Reg() == 0x40)
  {
    receive_data(1, &x);
    Serial.println(x);
    
    if (x == 5){ //Evaluando el valor de X
      flush_TX_RX(); 
      nrF24L01_TXinit(); //Cuando el tranceptor pasa de TX a RX colocar el dedo en el cristal del tranceptor para atterizar bien la tierra y que el modulo envie mensaje
      delay(3000);
      x = 0;
      while(1){
          send_data(1, &x);
          x++;
          Serial.println(x);
        }   
      }
    
    
    
  }
  
   
}
Programa para PIC16F887

Código:
sbit RF_IRQ_TRIS at TRISB0_bit;
sbit RF_CS_TRIS at TRISC1_bit;
sbit RF_CE_TRIS at TRISC2_bit;
sbit SCK_TRIS at TRISC3_bit;
sbit SDI_TRIS at TRISC4_bit;
sbit SDO_TRIS at TRISC5_bit;

sbit IRQ_pin at RB0_bit;
sbit SS_pin at RC1_bit;
sbit CE_pin at RC2_bit;
sbit SCK_pin at RC3_bit;
sbit MOSI_pin at RC5_bit; //SDO Escritura Salida
sbit MISO_pin at RC4_bit; //SDI Lectura Entrada

sbit Led at RC1_bit;

#define R_REGISTER_cmd                0x00
#define W_REGISTER_cmd                0x20
#define R_RX_PL_WID_cmd               0x60
#define R_RX_PAYLOAD_cmd              0x61
#define W_TX_PAYLOAD_cmd              0xA0
#define W_ACK_PAYLOAD_cmd             0xA8
#define W_TX_PAYLOAD_NO_ACK_cmd       0xB0
#define FLUSH_TX_cmd                  0xE1
#define FLUSH_RX_cmd                  0xE2
#define REUSE_TX_PL_cmd                      0xE3
#define NOP_cmd                       0xFF

#define CONFIG_reg                         0x00
#define EN_AA_reg                     0x01
#define EN_RXADDR_reg                 0x02
#define SETUP_AW_reg                      0x03
#define SETUP_RETR_reg                0x04
#define RF_CH_reg                      0x05
#define RF_SETUP_reg                  0x06
#define STATUS_reg                    0x07
#define OBSERVE_TX_reg                0x08
#define RPD_reg                       0x09
#define RX_ADDR_P0_reg                0x0A
#define RX_ADDR_P1_reg                0x0B
#define RX_ADDR_P2_reg                0x0C
#define RX_ADDR_P3_reg                0x0D
#define RX_ADDR_P4_reg                0x0E
#define RX_ADDR_P5_reg                0x0F
#define TX_ADDR_reg                   0x10
#define RX_PW_P0_reg                  0x11
#define RX_PW_P1_reg                  0x12
#define RX_PW_P2_reg                  0x13
#define RX_PW_P3_reg                  0x14
#define RX_PW_P4_reg                  0x15
#define RX_PW_P5_reg                  0x16
#define FIFO_STATUS_reg               0x17
#define DYNPD_reg                     0x1C
#define FEATURE_reg                   0x1D


unsigned char x = 0;


unsigned char nRF24L01_read()
{
  unsigned char s = 0;
  unsigned char msg = 0;

  for(s = 0; s < 8; s++)
  {
      msg <<= 1;
      SCK_pin = 1;
      delay_us(8);
      if(MISO_pin != 0)
      {
        msg |= 1;
      }
      SCK_pin = 0;
      delay_us(8);
  }

  return msg;
}


void nRF24L01_write(unsigned char d)
{
  unsigned char s = 0;

  for(s = 0; s < 8; s++)
  {
    if((d & 0x80) != 0)
    {
      MOSI_pin = 1;
    }
    else
    {
      MOSI_pin = 0;
    }
    d <<= 1;
    SCK_pin = 1;
    delay_us(8);
    SCK_pin = 0;
    delay_us(8);
  }
}


void register_write(unsigned char reg, unsigned char value)
{
  SS_pin = 0;
  nRF24L01_write((reg | W_REGISTER_cmd));
  nRF24L01_write(value);
  SS_pin = 1;
  delay_us(8);
}


void write_command(unsigned char cmd)
{
  SS_pin = 0;
  nRF24L01_write(cmd);
  SS_pin = 1;
  delay_us(8);
}


unsigned char register_read(unsigned char reg)
{
  unsigned char value = 0;

  SS_pin = 0;
  nRF24L01_write((reg | R_REGISTER_cmd));
  value = nRF24L01_read();
  SS_pin = 1;
  delay_us(8);

  return value;
}


void set_TX_RX_address(unsigned char *addr, unsigned char bytes, unsigned char reg)
{
  unsigned char n = 0;

  SS_pin = 0;
  nRF24L01_write((reg | W_REGISTER_cmd));
  for(n = 0; n < bytes; n++)
  {
    nRF24L01_write(addr[n]);
  }
  SS_pin = 1;
  delay_us(8);
}


void flush_TX_RX()
{
  register_write(STATUS_reg, 0x70);
  write_command(FLUSH_TX_cmd);
  write_command(FLUSH_RX_cmd);
}


void send_data(unsigned char bytes, unsigned char *value)
{
  unsigned char s = 0;

  flush_TX_RX();
  register_write(CONFIG_reg, 0x3A);

  SS_pin = 0;
  nRF24L01_write(W_TX_PAYLOAD_cmd);
  for(s = 0; s < bytes; s++)
  {
    nRF24L01_write(value[s]);
  }
  SS_pin = 1;
  delay_us(8);

  CE_pin = 1;
  delay_us(60);
  CE_pin = 0;

  register_write(CONFIG_reg, 0x38); //En modo RX se quita
}

void receive_data(unsigned char bytes, unsigned char *value)
{
  unsigned char s = 0;

  SS_pin = 0;
  nRF24L01_write(R_RX_PAYLOAD_cmd);
  for (s = 0; s < bytes; s++)
  {
    value[s] = nRF24L01_read();
  }
  SS_pin = 1;
  delay_us(8);
}


void nrF24L01_init_TX()
{
  unsigned char address[5] = {0x99, 0x99, 0x99, 0x99, 0x99};

  CE_pin = 0;

  register_write(SETUP_RETR_reg, 0x00);
  register_write(SETUP_AW_reg, 0x03);
  register_write(RF_SETUP_reg, 0x0E);
  register_write(RF_CH_reg, 0x09);
  register_write(EN_AA_reg, 0x00);
  register_write(CONFIG_reg, 0x38);
  set_TX_RX_address(address, 5, TX_ADDR_reg);
  set_TX_RX_address(address, 5, RX_ADDR_P0_reg);
  flush_TX_RX();

  CE_pin = 1;
}

void nrF24L01_init_RX()
{
  unsigned char address[5] = {0x99, 0x99, 0x99, 0x99, 0x99};

  CE_pin = 0;

  register_write(CONFIG_reg, 0x38);
  register_write(SETUP_RETR_reg, 0x00);
  register_write(SETUP_AW_reg, 0x03);
  register_write(RF_SETUP_reg, 0x0E);
  register_write(RF_CH_reg, 0x09);
  register_write(EN_AA_reg, 0x00);
  register_write(RX_PW_P0_reg, 0x01);
  register_write(CONFIG_reg, 0x3B);
  set_TX_RX_address(address, 5, TX_ADDR_reg);
  set_TX_RX_address(address, 5, RX_ADDR_P0_reg);
  flush_TX_RX();

  CE_pin = 1;
}

unsigned char get_Status_Reg()
{
  return register_read(STATUS_reg);
}


  unsigned char val = 0;

void main(){

delay_ms(1000);
//Enntradas con 1 y salidas 0
 TRISA     =  0x00;
 TRISB     =  0x00;
 TRISC     =  0x00;
 ADCON1 = 0x0F;
 PORTB = 0X00;
 PORTC = 0x00;

 RF_IRQ_TRIS = 1;
 RF_CS_TRIS = 0;
 RF_CE_TRIS = 0;
 SCK_TRIS = 0;
 SDI_TRIS = 1;  //MISO
 SDO_TRIS = 0;  //MOSI

 CE_pin = 0;
 SS_pin = 0;
 SCK_pin = 0;
 MOSI_pin = 0;

 delay_ms(1000);

 nrF24L01_init_TX();

 delay_ms(900);


 while(1){
  send_data(1, &x);
  porta = x;
  x++;
  delay_ms(1000);
  Led = 1;
  if (x == 6){
   flush_TX_RX();
   nrF24L01_init_RX();
   delay_ms(900);
   porta = 0;
   x = 0;
   while(1){
    if(get_Status_Reg() == 0x40)
    {
      receive_data(1, &x);
      porta = x;
    }
   }
  }
 }
}
En los dos, los parámetros de los pines a usarse pueden configurarse, y básicamente podremos lograr comunicar CUALQUIER PIC con arduino modificando ciertos parámetros en el comienzo del código.
 

Temas similares


Arriba