CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

nRF24L01+ full driver by Eduardo Guilherme Brandt
Goto page Previous  1, 2, 3, ... 18, 19, 20  Next
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
tiagojampietro



Joined: 15 Mar 2012
Posts: 3

View user's profile Send private message

Driver use example 2: Transmitting data(Using 3 level FIFO
PostPosted: Thu May 24, 2012 8:08 am     Reply with quote

Have some questions:

- In this example you send a string, but the receiver example you use a int array. How you compare this to make a function?? For example: send a "Led on!" and receive and activate led.

I'm using this radio to control a robot soccer, and I need to send a series of commands to be interpreted by the robot.

Thanks for help.
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

PostPosted: Thu May 24, 2012 10:33 am     Reply with quote

It´s simply. It´s not C++. So it not have complex type checking.

So when you send a string, you´re sending an array of bytes(with a null caracter at the end, null caracter is a zero), which length is the length of the string. A writer/Debugger from CCS or Microchip(Mosaico Sells ICD2br in Brazil) will help you understanding that, using breakpoints and watch window.

An array can contain any kind of data. It can be string, numbers, audio, video, anything. So an array of bytes is simply a buffer!!!


I suggest you using command streams for control your robot, with fixed size.

For example: Comand_byte+data_1_byte+data2_byte+data3_byte. It´s a fixed size command stream.

So, your robot will know that the first byte is the command(e.g. speed control), the second byte would be the value(e.g. 100 meaning 100%) and the last two bytes could be discarded as "speed_control" command would not use them. But another commands could making use of last two bytes.

There´re infinite possibilities...

best wishes!

ps: Please, share with us a video of your robot working when you finish it(if you can).
_________________
Eduardo Guilherme Brandt
Leonardo-Silva



Joined: 03 Jun 2012
Posts: 4

View user's profile Send private message

PostPosted: Sun Jun 03, 2012 3:57 pm     Reply with quote

hi Eduardo,
I'm using the nRF24l01 to control the acceleration and the break of my robot. the pic I have here is the 16f877a. I've read your code and you're using dma for sending multiples bytes... but the 877a doesn't have dma. I started learning about pic 3 months ago and I have this problem. it would be possible to your code work without it? I just have to transmit 2 bytes and 1 bit, and I was thinking in sending one information per sending, like:
Code:
spi_write(val1);
spi_write(val2);
spi_write(bitbreak);

this way I guess I wouldn't need to use dma. How can I do it?

Thank you. Very Happy
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

PostPosted: Sun Jun 03, 2012 6:08 pm     Reply with quote

Sure, you can use without DMA. Just not enable DMA when setuping your nRF24 driver.

But you´re doing the wrong way. You must use driver commands to communnicate with the nRF24 chip.
See example code
Code:
RF24_driver_use_example_TXdata_simple()



Example:
Code:
    RF24_initPorts();
    RF24_default_config();
     
    RF24_TX_SET();       //Transmitter on   

    while(true) {        //Enter transmit mode infinitely
       //Sending number 1(1 byte).  See RF24_TX_putbuffer contruction inside driver
       RF24_TX_putbuffer(false,1, 1); //Transmit 1byte data(number) to actual address(default_config address)

       //Do this to check each data transfer
       while(RF24_IRQ_state()==false);        //Waits for any interrupt.  Same as "while(!RF24_IRQ_state());"     
       RF24_STATUS_clr_IRQs(IRQ_ALL);   
.. and so on...


You can use command number "1" to turn on something and 0 to turn off something.
At the receiver side, when you receive an "1", you should turn on the motor, and if you receive an "0", turn off.


You can implement any command or protocol as you want to.

Good luck!
_________________
Eduardo Guilherme Brandt
Leonardo-Silva



Joined: 03 Jun 2012
Posts: 4

View user's profile Send private message

PostPosted: Sun Jun 03, 2012 7:18 pm     Reply with quote

Ah, great!
I'll try this. Very Happy I had this doubt because the functions you used to configure the transceiver's commands uses dma. Like here:
Code:

int RF24_comm_out(int comm, char *dataout, int dataSZ) {       //Send command and send output string(dataSZ=number of bytes to output)(dataout=pointer to data for sending)
   #ifndef RF24_USE_DMA    int i;   #endif
   int rv;                          //rv=return value(SPI read value)
   RF24_select();       
   RF24_xfer(comm);                 //RF24 Write address/command(see RF24_addr addresses list tabble in .h file)
   
   #ifdef RF24_USE_DMA
      DMA_write(dataSZ, dataout);   //Simple DMA Write and start transfer
      DMA_start();                  //Start DMA transfer
      while(DMA_is_busy());         //DMA is working
   #else                            //Programed IO mode(Normal mode)
      for(i=0;i<dataSZ;i++) {
         RF24_xfer(*(dataout+i));
      } 
   #endif
   //rv = RF24_xfer();    //just catch last spi_xfer received byte)
   //rv = spi_read2();    //It´s necessary due to spi_xfer read bug
   RF24_unselect();   
   return rv;             //Return last read value
}

Then, if I used dma in my code, this function would use the part:
Code:

#ifdef RF24_USE_DMA
      DMA_write(dataSZ, dataout);   //Simple DMA Write and start transfer
      DMA_start();                  //Start DMA transfer
      while(DMA_is_busy());         //DMA is working
   #else                            //Programed IO mode(Normal mode)
      for(i=0;i<dataSZ;i++) {
         RF24_xfer(*(dataout+i));
      } 
   #endif

and if I didn't, it just would go to the end:
Code:

 //rv = RF24_xfer();    //just catch last spi_xfer received byte)
 //rv = spi_read2();    //It´s necessary due to spi_xfer read bug
   RF24_unselect();   
   return rv;             //Return last read value

Is it correct?

Thank you o/
_________________
Leonardo Silva
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

PostPosted: Mon Jun 04, 2012 2:50 pm     Reply with quote

Yes, you´re correct.

So, if you do not want to use DMA, just NOT define RF24_USE_DMA.

Best regards
_________________
Eduardo Guilherme Brandt
Leonardo-Silva



Joined: 03 Jun 2012
Posts: 4

View user's profile Send private message

PostPosted: Mon Jun 04, 2012 3:02 pm     Reply with quote

nice!

thank you o/. i'll try this tonight.

best regards! Very Happy
_________________
Leonardo Silva
Leonardo-Silva



Joined: 03 Jun 2012
Posts: 4

View user's profile Send private message

PostPosted: Wed Jun 13, 2012 12:43 pm     Reply with quote

Hi, Eduardo.
I have tried what you said, but it didn't worked. It should be my code, can you help me again here?
My controller's code:
Code:
#include <16F877A.h>

#DEVICE *=16    ICD=TRUE  PASS_STRINGS=IN_RAM     //I need PASS_STRINGS=IN_RAM
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay (clock = 4000000)

//Setting Spi
#USE SPI(MASTER,DI=pin_c4,DO=pin_c5,CLK=pin_c3, BAUD=1000000, MODE=0, BITS=8, MSB_FIRST, STREAM=STREAM_SPI) //this will set SPI in 4MHz(maximum for 16MHz Xtal. #Use SPI is a little buggy)


//********** DEFINE PORT NAMES
//CEL_PROBE AN0,RP0;INDICACAO_LED RA1,RP1;I2C_SCL RC3,RP14;I2C_SDA RC4,RP15;_IRQ_rf RC5,RP16;SPI_MISO RC6,RP17;SPI_MOSI RC7,RP18;SPI_CLK RB0,RP3;CS_rf RB1,RP4;CE_rf RB2,RP5;
#define  SPI_MISO       PIN_C4   //RC2,RP13; SPI(Usar por hardware)
#define  SPI_MOSI       PIN_C5   //RC7,RP18; SPI(Usar por hardware)
#define  SPI_CLK        PIN_C3   //RB0,RP3;  SPI(Usar por hardware)
#define  INDICACAO_LED  PIN_A1   //RA1,RP1;  just a test LED output

//Driver nRF24L01P.C
#define  RF24_IRQ       PIN_B0   //RC5,RP16; interrupcao nRF24L01
#define  RF24_CS        PIN_B5   //RB1,RP4;  chipselect nRF24L01+
#define  RF24_CE        PIN_C2   //RB2,RP5;  chipEnable nRF24L01+
#define  RF24_PERFORMANCE_MODE   //performance mode ON
//#define  RF24_USE_DMA            //nRF24 uses SPI DMA for multiple byte transfers(I´m using Hardware DMA)
#define  RF24_SPI       STREAM_SPI//Redirects SPI2 port to RS24_SPI stream


//*******************************
//*         Set Tris            *
#define   RF_IRQ_TRIS   TRISB,0
#define   RF_CS_TRIS    TRISB,5
#define   RF_CE_TRIS    TRISC,2
#define   SCK_TRIS      TRISC,3
#define   SDI_TRIS      TRISC,4
#define   SDO_TRIS      TRISC,5
//*         VARIABLES           *
//*******************************
#BYTE TRISA     =  0x85
#BYTE TRISB     =  0x86
#BYTE TRISC     =  0x87
//*******************************

//INCLUDES_2   -  Drivers
#include <nRF24L01P.C>           //Driver nRF24L01+   Single Chip 2.4GHz Transceiver Driver

void main() {    //Example of using this driver
   
   //setup_spi(spi_master| spi_l_to_h| spi_clk_div_4);
   
   
   set_tris_a(0x00);
   bit_clear(SCK_TRIS);
   bit_set(SDI_TRIS);
   bit_clear(SDO_TRIS);
   bit_clear(RF_CS_TRIS);
   bit_set(RF_IRQ_TRIS);
   bit_clear(RF_CE_TRIS);
   
   RF24_initPorts();
   
   RF24_default_config();
   
   RF24_TX_SET();       //Transmitter on   

   while(true) {        //Enter transmit mode infinitely
   
      output_high(pin_a1);
      delay_ms(1000);
      output_low(pin_a1);
      //Sending number 1(1 byte).  See RF24_TX_putbuffer contruction inside driver
       RF24_TX_putbuffer(false,1, 1); //Transmit 1byte data(number) to actual address(default_config address)

       //Do this to check each data transfer
       while(RF24_IRQ_state()==false);        //Waits for any interrupt.  Same as "while(!RF24_IRQ_state());"     
       RF24_STATUS_clr_IRQs(IRQ_ALL);   
   }
}


And my car's code:
Code:
#include <16F877A.h>

#DEVICE *=16    ICD=TRUE  PASS_STRINGS=IN_RAM     //I need PASS_STRINGS=IN_RAM
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay (clock = 4000000)

//Setting Spi
#USE SPI(MASTER,DI=pin_c4,DO=pin_c5,CLK=pin_c3, BAUD=1000000, MODE=0, BITS=8, MSB_FIRST, STREAM=STREAM_SPI) //this will set SPI in 4MHz(maximum for 16MHz Xtal. #Use SPI is a little buggy)


//********** DEFINE PORT NAMES
//CEL_PROBE AN0,RP0;INDICACAO_LED RA1,RP1;I2C_SCL RC3,RP14;I2C_SDA RC4,RP15;_IRQ_rf RC5,RP16;SPI_MISO RC6,RP17;SPI_MOSI RC7,RP18;SPI_CLK RB0,RP3;CS_rf RB1,RP4;CE_rf RB2,RP5;
#define  SPI_MISO       PIN_C4   //RC2,RP13; SPI(Usar por hardware)
#define  SPI_MOSI       PIN_C5   //RC7,RP18; SPI(Usar por hardware)
#define  SPI_CLK        PIN_C3   //RB0,RP3;  SPI(Usar por hardware)
#define  INDICACAO_LED  PIN_A1   //RA1,RP1;  just a test LED output

//Driver nRF24L01P.C
#define  RF24_IRQ       PIN_B0   //RC5,RP16; interrupcao nRF24L01
#define  RF24_CS        PIN_B5   //RB1,RP4;  chipselect nRF24L01+
#define  RF24_CE        PIN_C2   //RB2,RP5;  chipEnable nRF24L01+
#define  RF24_PERFORMANCE_MODE   //performance mode ON
//#define  RF24_USE_DMA            //nRF24 uses SPI DMA for multiple byte transfers(I´m using Hardware DMA)
#define  RF24_SPI       STREAM_SPI//Redirects SPI2 port to RS24_SPI stream

//*******************************
//*         Set Tris            *
#define   RF_IRQ_TRIS   TRISB,0
#define   RF_CS_TRIS    TRISB,5
#define   RF_CE_TRIS    TRISC,2
#define   SCK_TRIS      TRISC,3
#define   SDI_TRIS      TRISC,4
#define   SDO_TRIS      TRISC,5
//*         VARIABLES           *
//*******************************
#BYTE TRISA     =  0x85
#BYTE TRISB     =  0x86
#BYTE TRISC     =  0x87
//*******************************


//INCLUDES_2   -  Drivers
#include <nRF24L01P.C>           //Driver nRF24L01+   Single Chip 2.4GHz Transceiver Driver

#BYTE PORTA=0x05

void main() {    //Example of using this driver
   int RXbuffer1[32];
   int RXdatasize, RXpipe;
   //int TXbuffer[40], TXdatasize;        //not necessary
   //int stat=0,fstat=0,retrys,lost,ret;  //
   //int i=false;
   
   set_tris_a(0x00);
   bit_clear(SCK_TRIS);
   bit_set(SDI_TRIS);
   bit_clear(SDO_TRIS);
   bit_clear(RF_CS_TRIS);
   bit_set(RF_IRQ_TRIS);
   bit_clear(RF_CE_TRIS);
   
   
   RF24_initPorts();
   RF24_default_config();
   
   //RF24_check_config();    //check configuration 

   RF24_RX_SET();       //Receiver on
   
   while(true) {
     
      output_high(pin_a1);
      delay_ms(1000);
      output_low(pin_a1);
     
      while ( RF24_RX_getbuffer(&RXpipe, &RXdatasize, RXbuffer1)!=true );    //Wait till receive data(1 to 32 bytes) into buffer(from default_config address of pipe0)
      PORTA=RXbuffer1;
      delay_cycles(1);
   }
   

}


I haven't set the tris registers, so i've tried setting them, but... it's still not working. >< do you know what i did wrong?

thanks in advance
_________________
Leonardo Silva
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

answer
PostPosted: Wed Jun 13, 2012 1:37 pm     Reply with quote

Please, do not change tris by yourself. Leave it for the driver itself.
When programming in C, output() and input() functions do it automatically. You only disable this

with the directive "#USE FAST_IO (port)". Look for it on CCS help.



The first thing that you should do is check whether SPI communication is working.
The best way to do these tests is using a Debugger. Do you´ve a debugger?


I did a mistake using RF24_TX_putbuffer function( don´t know if it works as I taught you). The 3rd parameter must be a pointer. It can be the array TX_buffer[]. Arrays are almost like pointers.



Another thing:

You can´t say that "PORTA=RXbuffer1;"
The correct thing is:
Code:

//Transmitter side
/*
    1 and 0 are the command value. in your transmit example, you sent only the command 1

repeatdly.
    it´s better to read some input and send a 1 when it´s 1 and a 0 when it´s zero.
  /*
while(true) {
  if (input(PIN_B3)==true)  TXbuffer[0]=1;       //Check input and put a 1 in position 0 of buffer TXbuffer
  else TXbuffer[0]=0;                                  //Check input and put a 0 in position 0 o fbuffer TXbuffer
  RF24_TX_putbuffer(false,1, TXbuffer);          //Transmit data(just 1 byte) at position 0 of TXbuffer
}

//**********************************************
//receiver side
    you can define that 1 means "Turn motor on" and 0 means "Turn motor off"(you can define any value from 0 to 255, because it is a byte data), for example.
  */
  If (RXbuffer1[0]==1) output_high(PIN_B0);    //1 is the received command value.
  If (RXbuffer1[0]==0) output_low(PIN_B0);     //0 is the received command value.

 
  //delay_ms(1000);    //It´s not necessary to wait so long(1000ms=1second).


=====================
As you´re a newbie in uC and CCS C, I recomend you buy a debugger/ programmer like that CCS sells.
Here in Brazil you´re able to buy ICD2br from Mosaic.

Best wishes
_________________
Eduardo Guilherme Brandt
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

Another tip
PostPosted: Wed Jun 13, 2012 1:41 pm     Reply with quote

You should learn driver commands before use it.

e.g.

Look at command "RF24_TX_putbuffer" inside driver.

Code:
/************************************************************************************
 * Transmit data(1 to 32 bytes) to actual address:
 *
 * Parameters:
 *
 * datasize  : number of bytes in TX pointer_buffer(1 to 32) for transmiting
 * burst     : This function disable packet acknowledge receiving. It makes the link less reliable, but tree times faster.
 *                 true: No returning acknowledge(triplicates datarate in 2Mbps). You can reach max. transfer speed(200KByte/s).   
 *                 false: Without burst, the max speed is 70KByte/s(It´s good when in low power, long range or noise is present).
 * buffer    : buffer where data for transmiting is
 * returns   : Returns true(1) if data put into buffer. Other if not(error)
 *
 */
 int RF24_TX_putbuffer(short int burst, int datasize, char *buffer) {//Transmit data(1 to 32 bytes) to actual address



Good luck!
_________________
Eduardo Guilherme Brandt
Bruno12



Joined: 13 Jun 2012
Posts: 1
Location: Brazil

View user's profile Send private message

PostPosted: Wed Jun 13, 2012 8:50 pm     Reply with quote

Hi Eduardo,

I'm trying to send 1 byte between two PIC16f877.
I use this library and there isn't communication.

For transmiting data I use both the example 3 and your last post. For receiving data I use only the code in your last post.

Using an osciloscope, I've observed in the transmitter that the PIC is communicating with the nrf and the same thing happens in the receiver, but the strange is that the nrf's is not returning data to PIC.
I did the same things that you indicated to Leonardo-Silva, but any progress.
Do you know what may be happening?

Thanks

Bruno
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

PostPosted: Wed Jun 13, 2012 9:16 pm     Reply with quote

Did you a put a break after "RF24_TX_putbuffer(false,1, TXbuffer);"?
What happens?

ANother thing:

After initialization(but before transmitting and receiving data) I suggest you use command "RF24_check_config()"

Inside this function, you can put a break in each "delay_ms(10);" and check bbuf value.

The values must be the same programmed with "RF24_default_config()".
Go inside "RF24_default_config()" and see default values.


Because of that, debugger should be very important in these cases.


Good luck
_________________
Eduardo Guilherme Brandt
kenvinh



Joined: 13 Jun 2012
Posts: 12

View user's profile Send private message

spi_xfer() problem
PostPosted: Thu Jun 14, 2012 2:36 am     Reply with quote

Hi Eduardo, I'm very interested with your code about nRF24L01.
I've read through your code and implement it with my PIC16F876A as the receiver and nRF24L01 on CCS PICC 4.106 with 20MHz crystal (my area still don't have nRF24L01+ Sad ).
As for testing, I want to send a adc signal from another board to display on rs232.
But now, I get stuck right from the beginning with spi_xfer()
Because my PIC doesn't support #pin_select directive, so here's my code:

Code:


#include "SPI nRF24L01 transmitter.h"
#use SPI(FORCE_HW, baud=1000000, BITS=8, stream=RF24_SPI)
#use rs232(baud=9600,parity=N, xmit=PIN_C6,rcv=PIN_C7, bits=8)

#define SPI_CLK   PIN_C3
#define SPI_MISO  PIN_C4
#define SPI_MOSI  PIN_C5
#define RF24_CS   PIN_C0
#define RF24_CE   PIN_C1
#define RF24_IRQ  PIN_C2
#define RF24_SPI_DISABLE_WARNING

#include "nRF24L01.c"


And here's my manual debugging code: (terminal display until Init OK, and I also use leds for monitoring signal on SPI bus. The led on MISO pin blinking at the stop point)

Code:

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   //setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   int RXbuffer1[32];
   RF24_initPorts();
   printf("\n\rInit OK \n\r");
   delay_ms(1000);
   
   RF24_disable();
   int rv;
   RF24_select();
   rv = spi_xfer(RF24_SPI,0b00100000); //I receive value from here because "... the STATUS register is shifted serially out on the MISO pin"
   rv = spi_read();
   spi_xfer(RF24_SPI,0b00101110);
   RF24_unselect();
   printf("Default configuration OK \n\r");
   delay_ms(1000);
   while(true)
   {
      printf("demodemo \n\r");
      delay_ms(500);
   }
}


What I need to do now to make the spi_xfer() function work? I've tried changing to #USE SPI(SPI2, MASTER, BAUD=1000000, MODE=0, BITS=8, MSB_FIRST, STREAM=RF24_SPI), but it's still stuck there.
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 8:13 am     Reply with quote

The 1st thing, I suggest you use software SPI and disable every line like "rv = spi_read2(); " inside driver. This like is because a bug in hardware SPI, something that I could not understand.

Another thing, I suggest you use driver commands for controlling nRF24L01+.

See post "how to do" and use driver example functions. read that functions.

Best whishes.
Smile
_________________
Eduardo Guilherme Brandt
Eduardo__



Joined: 23 Nov 2011
Posts: 197
Location: Brazil

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 8:16 am     Reply with quote

another thing, you cannot simply use printf with this driver.

You should use "RF24_TX_putbuffer()" and "RF24_RX_getbuffer()" functions for that.

buffer is only 32bytes. Please, get reading a little of nRf24 datasheet and driver for understanding better.

good luck
_________________
Eduardo Guilherme Brandt
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, ... 18, 19, 20  Next
Page 2 of 20

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group