|
|
View previous topic :: View next topic |
Author |
Message |
tiagojampietro
Joined: 15 Mar 2012 Posts: 3
|
Driver use example 2: Transmitting data(Using 3 level FIFO |
Posted: Thu May 24, 2012 8:08 am |
|
|
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
|
|
Posted: Thu May 24, 2012 10:33 am |
|
|
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
|
|
Posted: Sun Jun 03, 2012 3:57 pm |
|
|
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. |
|
|
Eduardo__
Joined: 23 Nov 2011 Posts: 197 Location: Brazil
|
|
Posted: Sun Jun 03, 2012 6:08 pm |
|
|
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
|
|
Posted: Sun Jun 03, 2012 7:18 pm |
|
|
Ah, great!
I'll try this. 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
|
|
Posted: Mon Jun 04, 2012 2:50 pm |
|
|
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
|
|
Posted: Mon Jun 04, 2012 3:02 pm |
|
|
nice!
thank you o/. i'll try this tonight.
best regards! _________________ Leonardo Silva |
|
|
Leonardo-Silva
Joined: 03 Jun 2012 Posts: 4
|
|
Posted: Wed Jun 13, 2012 12:43 pm |
|
|
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
|
answer |
Posted: Wed Jun 13, 2012 1:37 pm |
|
|
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
|
Another tip |
Posted: Wed Jun 13, 2012 1:41 pm |
|
|
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
|
|
Posted: Wed Jun 13, 2012 8:50 pm |
|
|
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
|
|
Posted: Wed Jun 13, 2012 9:16 pm |
|
|
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
|
spi_xfer() problem |
Posted: Thu Jun 14, 2012 2:36 am |
|
|
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+ ).
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
|
|
Posted: Thu Jun 14, 2012 8:13 am |
|
|
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.
_________________ Eduardo Guilherme Brandt |
|
|
Eduardo__
Joined: 23 Nov 2011 Posts: 197 Location: Brazil
|
|
Posted: Thu Jun 14, 2012 8:16 am |
|
|
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 |
|
|
|
|
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
|