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