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

nRF24L01+ and PIC16F628A as RX

Hello All,

I'm trying to build a receiving unit using the nRF24L01+ and PIC16F628A. Im using an nRF24L01+ and RaspberryPi as my TX unit which i managed to get working (tested on another nRF24L01+ and RasPi, and also with Arduino Uno). I'm not very good with PIC programming and just started with Hitech C (managed the ABC projects of lighting an LED or writting to an LCD, etc.)

The following is my code on RasPi side for TX:

#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include "RF24.h"

using namespace std;

/*
Pins:
    nRF	    RasPi
    1	    25      GND
    2	    17      3v3
    3	    22      GPIO 25
    4	    24      GPIO  8
    5	    23      GPIO 11
    6	    19      GPIO 10 (MOSI)
    7	    21      GPIO  9 (MISO)

Compile:

        g++ -Wall -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -L../librf24/  -lrf24 rpi-hub.cpp -o rpi-hub

        ~/RF24/librf24-rpi/librf24/rpi-hub

Addresses:
        Use at least 32bit address and enable 16bit CRC.
        Avoid addresses that start with 0x00, 0x55, 0xAA and 0xFF.
*/

// define Own receiving addresses:
const uint64_t pipes[5] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL, 0xF0F0F0F0E4LL, 0xF0F0F0F0E5LL };

// define Remote Nodes addresses:
const uint64_t nodes[2] = { 0x7365727632LL, 0x7365727632LL };

RF24 radio("/dev/spidev0.0",8000000,25);
uint8_t counter = 0;
char receivePayload[32];

uint64_t rxAddr = 0;
int rxPin  = 0;
int rxCmd  = 0;

void setup(void) {
	radio.begin();
	radio.enableDynamicPayloads();
	radio.setAutoAck(1);
	radio.setRetries(15,15);
	radio.setDataRate(RF24_1MBPS);
	radio.setPALevel(RF24_PA_MAX);
	radio.setChannel(75);
	radio.setCRCLength(RF24_CRC_16);

	// Open 6 pipes for readings ( 5 plus pipe0, also can be used for reading )
	radio.openWritingPipe(nodes[0]);
	radio.openReadingPipe(1,pipes[0]);
	radio.openReadingPipe(2,pipes[1]);
	radio.openReadingPipe(3,pipes[2]);
	radio.openReadingPipe(4,pipes[3]);
	radio.openReadingPipe(5,pipes[4]);

	// Start Listening
	radio.startListening();

//	radio.printDetails();
//	printf("\n\rOutput below : \n\r");
	usleep(500);

}

void sendCMD(uint64_t addr, int pin, int cmd ){
    char outBuffer[32]="";
    char temp[1]="";

//    cout << "Address = " << addr << endl;

    // set node address
    radio.openWritingPipe(addr);

    radio.stopListening();

    sprintf(outBuffer, "%03d", pin);
    strcat(outBuffer,",");
    sprintf(temp, "%03d", cmd);
    strcat(outBuffer, temp);

    if (radio.write( outBuffer, strlen(outBuffer))) {
       printf("Send successful\n\r");
    }
    else {
       printf("Send failed\n\r");
    }

    radio.startListening();
    //delay(20);
}

int main(int argc, char** argv){

    std::string s(argv[1]);
    std::stringstream strm(s);
    uint64_t n;
    strm >> std::hex >> n;
//    std::cout << std::hex << n << std::endl;

    rxPin   =   atoi(argv[2]);
    rxCmd   =   atoi(argv[3]);

//    cout << "Address = " << n << endl;

	setup();

	sendCMD(n, rxPin, rxCmd);
/*
	while(1){
		sendCMD(0x7365727631LL,0,1);
        delay(5000);
		sendCMD(0x7365727631LL,1,1);
        delay(5000);
		sendCMD(0x7365727631LL,2,1);
	}
*/
	return 0;
}

I found a lot of examples for the PIC, but as my knowledge is not that great in this area, I cant manage to get it running. Here is the closest code I found to work as RX:

#include <xc.h>
#include <htc.h>
 
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_ON & LVP_OFF & CPD_OFF & CP_OFF);
#define _XTAL_FREQ      20000000
 
#define _XTAL_FREQ      20000000
 
 
 
 
#include "stdint.h"
/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C
 
/* Bit Mnemonics */
 
/* configuratio nregister */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0
 
/* enable auto acknowledgment */
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0
 
/* enable rx addresses */
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0
 
/* setup of address width */
#define AW          0 /* 2 bits */
 
/* setup of auto re-transmission */
#define ARD         4 /* 4 bits */
#define ARC         0 /* 4 bits */
 
/* RF setup register */
#define RF_DR_LOW       5
#define PLL_LOCK    4
#define RF_DR_HIGH  3
#define RF_PWR      1 /* 2 bits */
 
/* general status register */
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1 /* 3 bits */
#define TX_FULL     0
 
/* transmit observe register */
#define PLOS_CNT    4 /* 4 bits */
#define ARC_CNT     0 /* 4 bits */
 
/* fifo status */
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0
 
/* dynamic length */
#define DPL_P0      0
#define DPL_P1      1
#define DPL_P2      2
#define DPL_P3      3
#define DPL_P4      4
#define DPL_P5      5
 
/* Instruction Mnemonics */
#define R_REGISTER    0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER    0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define ACTIVATE      0x50
#define R_RX_PL_WID   0x60
#define NOP1          0xFF
 
#define nrf24_CONFIG ((1 << MASK_RX_DR)|(1<<EN_CRC)|(0<<CRCO)) //
 
// hardware spi pin defined 16F628A
#define LED_PIN      PORTAbits.RA2 // led test // pin no. 17
#define CS_Pin       PORTBbits.RB5 //          //set port as output pin no. 11
#define CE_Pin       PORTBbits.RB4         //set port as output pin no.10
#define SCK_Pin      PORTBbits.RB1        //set port as output pin no. 7
#define Mosi_Pin     PORTBbits.RB2         //set port as output pin no. 8
#define Miso_Pin     PORTBbits.RB3        //set port as input pin no. 9
#define HIGH         1
#define LOW          0
#define payload 1;
 
 
/* H/W SPI NOT REQUIRED FOR 16F628A
 
void SPI_init()
{
    SSPEN = 0;
    TRISC = 0;     //SCK
    CKE = 1;
    SSPCON = 0x01;  //CKP = 0, SCK = 1MHz
    SMP = 1;
    SSPEN = 1;
}
 
 
unsigned char SPI_transfer(unsigned char data)
{
    SSPBUF = data;       // Put command into SPI buffer
    while (!BF);         // Wait for the transfer to finish
    return SSPBUF;       // Save the read value
}
 
 
*/
 
uint8_t PTX;
 
 
 
 
 
void nrf24_ce_digitalwrite(uint8_t state)
{
if (state)
{
CE_Pin = 1;
}
else
{
CE_Pin = 0;
}
}
 
 
void nrf24_csn_digitalwrite(uint8_t state)
{
if (state)
{
CS_Pin = 1;
}
else
{
CS_Pin = 0;
}
}
 
 
void nrf24_sck_digitalwrite(uint8_t state)
{
if (state)
{
SCK_Pin = 1;
}
else
{
SCK_Pin = 0;
}
}
 
 
void nrf24_mosi_digitalwrite( uint8_t state)
{
if (state)
{
Mosi_Pin = 1;
}
else
{
Mosi_Pin = 0;
}
}
 
 
 
 
 
char SPI_transfer(char data)
{
        char i,temp=0;
        for(i=0;i<8;i++) // output 8-bit
        {
        if((data & 0x80)==0x80)
        {
                nrf24_mosi_digitalwrite(HIGH);         // output 'uchar', MSB to MOSI
        }
        else
        {
                nrf24_mosi_digitalwrite(LOW);
        }      
//==============================================================================
                data = (data << 1);            // shift next bit into MSB..
                temp<<=1;
                nrf24_sck_digitalwrite(HIGH);                // Set SCK high..
                if((Miso_Pin))temp++;         // capture current MISO bit
                nrf24_sck_digitalwrite(LOW);              // ..then set SCK low again
        }
    return(temp);                         // return read uchar
}
 
 
 
 
 
/* send and rece_pinive multiple bytes over SPI */ // checked with mirf
void nrf24_transferSync(uint8_t  *dataout,uint8_t *datain,uint8_t len)
{
    uint8_t i;
 
    for(i=0;i<len;i++){
       datain[i] = SPI_transfer(dataout[i]);
    }
}
 
 
//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len)
{
    uint8_t i;
 
    for(i=0;i<len;i++){
      SPI_transfer(dataout[i]);
    }
}
 
void nrf24_configRegister(uint8_t reg, uint8_t value)
{
    nrf24_csn_digitalwrite(LOW);
    SPI_transfer(W_REGISTER | (REGISTER_MASK & reg));
    SPI_transfer(value);
    nrf24_csn_digitalwrite(HIGH);
}
 
void nrf24_powerUpRx() // checked with mirf
{      
nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX)));  
nrf24_configRegister(RX_PW_P0,1);  
//nrf24_configRegister(RX_PW_P1,1);    
}
 
 
void nrf24_init()
{
        TRISB = 0b00001000;
        TRISA = 0b00000000;
}
 
 
uint8_t nrf24_data_ready()  
// checks if data is available for reading
{
        uint8_t status;  
        nrf24_csn_digitalwrite(LOW);                          // Pull down chip select
        status = SPI_transfer(0xff);                                    // Read status register
        nrf24_csn_digitalwrite(HIGH);                              // Pull up chip select
    return status & ( 1 << RX_DR ) ;
}
 
 
/* Reads payload bytes uint8_to data array */
uint8_t nrf24_getData(uint8_t *data1)  // check with mirf
{
        uint8_t status;
    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);
 
    /* Send cmd to read rx payload */
    SPI_transfer(R_RX_PAYLOAD);
 
    /* Read payload */
    nrf24_transferSync(data1,data1,1); //payload length 1 byte
 
    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);
 
    /* Reset status register */
    nrf24_configRegister(STATUS,(1<<RX_DR));
        return status;
 
}
 
 
 
 
void main()
{
TRISB = 0b00001000;
TRISA = 0b00000000;
CMCON = 0X07;
nrf24_init();
//__delay_us(13);
nrf24_configRegister(RF_CH,89);
//nrf24_configRegister(EN_AA,(0<<ENAA_P0)|(0<<ENAA_P1));
//nrf24_configRegister(RF_SETUP,(0<<RF_DR_LOW));
//nrf24_configRegister(RF_SETUP,(0<<RF_DR_HIGH));
 
nrf24_powerUpRx();
__delay_ms(5);
nrf24_ce_digitalwrite(HIGH);
uint8_t nrf_data[1];
uint8_t output;
uint8_t data_final = 0;
 
 
while(1)
{
{
while(nrf24_data_ready())
        {    
               
        //      LED_PIN = HIGH;
        //nrf24_configRegister(STATUS, (1<<RX_DR)); // KEEP CLEARING RX_DR AS YOU KEEP ON READING PAYLOADS....
        nrf24_ce_digitalwrite(LOW); // WHEN U HAVE RECEIVED PACKETS PULL CE LOW AND START READING R_RX_PAYLOAD
                output = nrf24_getData(nrf_data);      
        //      data_final = nrf_data[0];
        nrf24_configRegister(STATUS, (1<<RX_DR));
        }
 
 
if(nrf_data[0] == 111)
{
LED_PIN = HIGH;
}
else
{
LED_PIN = LOW;
}
while(!nrf24_data_ready()) // while nrf data not available
nrf24_ce_digitalwrite(HIGH); // START LISTENING AGAIN
__delay_us(10);
}
}
}

Is there anyway that anyone can help me out here?

I'm trying to find out how to setup the pipes addresses on RX unit (the pic) and also how to parse the payload?

Thanks

Related