Page 1 of 1

NRF24L01+ won't send

PostPosted: Tue Jun 12, 2012 9:27 pm
by arhi
Can't get NRF24L01+ to send data. When I use Mirf library and 2 arduinos it works, but when I use Brenann's lib on pic it won't send... I wrote already about it on "http: / / forum.sparkfun com/viewtopic.php?f=13&t=32404&p=145931#p145930" but maybe this is a proper place to get help as I hit a brick wall and can't move forward

- pic32mx460F512L, mplabx, c32, spi1
- tried both 1M and 2M
- 0dB
- 1byte payload, 4 byte payload
- channel 1 and channel 2

Everything seems to go ok, the nrfl is accepting all register changes and then when I try to send something

Code: Select all
...
    nrf24l01_initialize_debug(true, 4, false);
    nrf24l01_set_rx_addr("clie1", 5, 0);
    nrf24l01_set_rx_pw(4,0);
    nrf24l01_set_tx_addr("serv1", 5);

    ttt = 0;
    while (1) {
        ttt++;
        nrf24l01_set_as_tx();
        nrf24l01_write_tx_payload((unsigned char *)&ttt, 4, true);
        while (!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));

//////////////////////////////
//IT NEVER ARRIVES HERE!!!!!!!!!!!
//////////////////////////////
...


every read of the status register returns 0x0E ..

I can upload logic analyzer screenshots (some already on sparkfun theme I linked), logic analyzer decoded data... can test anything if anyone have any ideas - I'm stuck - it just won't send anything (the receiver is the arduino running mirf.ping_server demo)

Re: NRF24L01+ won't send

PostPosted: Wed Jun 13, 2012 12:10 pm
by brennen
The first argument in nrf24l01_initialize_debug() is a boolean indicating if the L01 should be set up as an RX (true) or TX (false). Try flipping that value.

Re: NRF24L01+ won't send

PostPosted: Wed Jun 13, 2012 12:47 pm
by arhi
brennen wrote:The first argument in nrf24l01_initialize_debug() is a boolean indicating if the L01 should be set up as an RX (true) or TX (false). Try flipping that value.


No change :(

I changed also spi init to
Code: Select all
    OpenSPI1(
            FRAME_ENABLE_OFF |
            FRAME_SYNC_OUTPUT |
            ENABLE_SDO_PIN |
            SPI_MODE8_ON |
            SPI_SMP_OFF |
            SPI_CKE_OFF |
            SLAVE_ENABLE_OFF |
            CLK_POL_ACTIVE_HIGH |
            MASTER_ENABLE_ON |
            SEC_PRESCAL_1_1 |
            PRI_PRESCAL_16_1
            ,
            SPI_ENABLE |
            SPI_IDLE_CON |
            SPI_RX_OVFLOW_CLR |
            FRAME_POL_ACTIVE_LOW |
            FRAME_SYNC_EDGE_PRECEDE
            );


as I noticed SPI was reading data 1 bit late so I assume SPI_SMP_OFF should solve it, and it did, now when I try the simple:

Code: Select all
//DEBUG
nrf24l01_clear_csn();
status = spi_send_read_byte(0x30);
spi_send_read_byte(0x11);
spi_send_read_byte(0x22);
spi_send_read_byte(0x33);
spi_send_read_byte(0x44);
spi_send_read_byte(0x55);
nrf24l01_set_csn();

aa=0;
bb=0;
cc=0;
dd=0;
ee=0;

nrf24l01_clear_csn();
status = spi_send_read_byte(0x10);
aa = spi_send_read_byte(0);
bb = spi_send_read_byte(0);
cc = spi_send_read_byte(0);
dd = spi_send_read_byte(0);
ee = spi_send_read_byte(0);
nrf24l01_set_csn();


while(1);
//ENDDEBUG


and run it trough debugger I see proper values in aa-ee, but still I can't get anything on the ping server nor it's going pass the
while (!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));

Re: NRF24L01+ won't send

PostPosted: Wed Jun 13, 2012 2:18 pm
by brennen
You might try changing
Code: Select all
while (!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));

to
Code: Select all
while (!nrf24l01_irq_tx_ds_active());


If code does pass the new check, then you are likely masking the TX_DS interrupt in the CONFIG register. If that doesn't pass, then there are other problems to find.

Re: NRF24L01+ won't send

PostPosted: Wed Jun 13, 2012 3:19 pm
by arhi
brennen wrote:You might try changing
Code: Select all
while (!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));

to
Code: Select all
while (!nrf24l01_irq_tx_ds_active());


If code does pass the new check, then you are likely masking the TX_DS interrupt in the CONFIG register. If that doesn't pass, then there are other problems to find.


IRQ is HIGH all the time as you can see on the LA output here so I think something else is a problem... I started doubting arduino receiver as if I understand how this stuff works, if there's no receiver with proper "name" the package will not be sent - right? So it will be retrying it indefinitely.... I'll make some quick pic18 board with nrfl so I can use same library for bot send and receive, maybe it will work, anyway it will reduce number of things that can go wrong :D

Re: NRF24L01+ won't send

PostPosted: Wed Jun 13, 2012 3:21 pm
by arhi
as for the config

Code: Select all
   config = nrf24l01_CONFIG_DEFAULT_VAL | nrf24l01_CONFIG_PWR_UP;
   
   if(enable_auto_ack != false)
      en_aa = nrf24l01_EN_AA_ENAA_P0;
   else
      en_aa = nrf24l01_EN_AA_ENAA_NONE;
   
   if(rx == true)
      config = config | nrf24l01_CONFIG_PRIM_RX;


I don't see a reason for TX_DS to be masked :(

Re: NRF24L01+ won't send

PostPosted: Wed Jun 13, 2012 3:38 pm
by brennen
This is just strictly for validation purposes. Chances are this isn't the problem, but it's something that would be very easy for you to check. At the very least, it takes the IRQ pin out of the running as having an issue.

If you could print out the values of the CONFIG, STATUS, and FIFO_STATUS registers both before *AND* after you try to send that first TX packet, that would be helpful.

Re: NRF24L01+ won't send

PostPosted: Thu Jul 05, 2012 2:19 am
by arhi
I'm not sure what finally solved the problem but it might be wrong SPI parameters so I did something like this:
Code: Select all
    SpiChnOpen(NRFL_SPI_CHN, SPI_CON_MODE8 | SPI_CON_MSTEN, 30);
    if (NRFL_SPI_CHN == SPI_CHANNEL1) {
        SPI1CONbits.CKP = 0;
        SPI1CONbits.SMP = 0;
        SPI1CONbits.CKE = 1;
    } else if ((NRFL_SPI_CHN == SPI_CHANNEL1A) || (NRFL_SPI_CHN == SPI_CHANNEL3)) {
        SPI1ACONbits.CKP = 0;
        SPI1ACONbits.SMP = 0;
        SPI1ACONbits.CKE = 1;
    } else if ((NRFL_SPI_CHN == SPI_CHANNEL2A) || (NRFL_SPI_CHN == SPI_CHANNEL2)) {
        SPI2ACONbits.CKP = 0;
        SPI2ACONbits.SMP = 0;
        SPI2ACONbits.CKE = 1;
    } else if ((NRFL_SPI_CHN == SPI_CHANNEL3A) || (NRFL_SPI_CHN == SPI_CHANNEL4)) {
        SPI3ACONbits.CKP = 0;
        SPI3ACONbits.SMP = 0;
        SPI3ACONbits.CKE = 1;
    }
    SpiChnSetBitRate(NRFL_SPI_CHN, GetPeripheralClock(), 4000000);


and now it works, I did change bunch of other things too so can't say what really solved the problem but I think it was the wrong SPI settings as I had problem with some MP3 module also that was behaving weirdly (works normally but often adds some chirps into the song), it ended up being "not stable SPI" so ... whatever is proper way to setup SPI using SpiChnOpen() I gave up on finding it and set SPI#CON register manually :)

Thanks for the library btw :D

I made few changes, they are pretty much irrelevant but, since it's open source ...

as I'm using pic32, I have coretimer turned on running at 10us interval
Code: Select all
// ...
volatile unsigned int CoreDelay;
// ...
#define TOGGLES_PER_SEC             100000
#define CORE_TICK_RATE               (GetSystemClock()/2/TOGGLES_PER_SEC)
// ...
SYSTEMConfigPerformance(GetSystemClock());
while (!(OSCCON & 0x00000020));
OpenCoreTimer(CORE_TICK_RATE);
// ...
void __ISR(_CORE_TIMER_VECTOR, ipl2) CoreTimerHandler(void) {
    if (CoreDelay) --CoreDelay;
    UpdateCoreTimer(CORE_TICK_RATE);
    mCTClearIntFlag();
}


hence I replaced all occurences of delayus() in the library with delay10us() and added:

Code: Select all
void delayms(unsigned int milliseconds){
    CoreDelay = TOGGLES_PER_SEC / 1000  * milliseconds;
    while(CoreDelay);
}

void delay10us(unsigned int i) {
    CoreDelay = i;
    while (CoreDelay);
}

void delayus(unsigned int i) {
    CoreDelay = i/10;
    while (CoreDelay);
}


LowLevel SPI stuff:

Code: Select all
unsigned char spi_send_read_byte(unsigned char b) {
    unsigned short rxData;
    SpiChnPutC(NRFL_SPI_CHN, b);
    rxData = SpiChnGetC(NRFL_SPI_CHN);
    return rxData;
}

void spiinit(){
    SpiChnOpen(NRFL_SPI_CHN, SPI_CON_MODE8 | SPI_CON_MSTEN, 30);
    if (NRFL_SPI_CHN == SPI_CHANNEL1) {
        SPI1CONbits.CKP = 0;
        SPI1CONbits.SMP = 0;
        SPI1CONbits.CKE = 1;
    } else if ((NRFL_SPI_CHN == SPI_CHANNEL1A) || (NRFL_SPI_CHN == SPI_CHANNEL3)) {
        SPI1ACONbits.CKP = 0;
        SPI1ACONbits.SMP = 0;
        SPI1ACONbits.CKE = 1;
    } else if ((NRFL_SPI_CHN == SPI_CHANNEL2A) || (NRFL_SPI_CHN == SPI_CHANNEL2)) {
        SPI2ACONbits.CKP = 0;
        SPI2ACONbits.SMP = 0;
        SPI2ACONbits.CKE = 1;
    } else if ((NRFL_SPI_CHN == SPI_CHANNEL3A) || (NRFL_SPI_CHN == SPI_CHANNEL4)) {
        SPI3ACONbits.CKP = 0;
        SPI3ACONbits.SMP = 0;
        SPI3ACONbits.CKE = 1;
    }
    SpiChnSetBitRate(NRFL_SPI_CHN, GetPeripheralClock(), 4000000);
}


I removed

bool xnrf24l01_csn_pin_active();
bool nrf24l01_ce_pin_active();

since I don't see a point for them, and changed the set/clear functions to address pins directly as I
Code: Select all
#define NRFL_SPI_CHN SPI_CHANNEL1A
#define NRFL_cePin PORTAbits.RA15
#define NRFL_ceTris TRISAbits.TRISA15
#define NRFL_csnPin PORTAbits.RA14
#define NRFL_csnTris TRISAbits.TRISA14
#define NRFL_irqPin  PORTBbits.RB10
#define NRFL_irqTris TRISBbits.TRISB10
#define NRFL_MOSI PORTFbits.RF8
#define NRFL_MOSI_Tris TRISFbits.TRISF8
#define NRFL_MISO PORTFbits.RF2
#define NRFL_MISO_Tris TRISFbits.TRISF2
#define NRFL_SCK PORTDbits.RD15
#define NRFL_SCK_Tris TRISDbits.TRISD15


So, if it helps someone with pic32, cool :) if not it would not be the first nor last useless post on the net :D

I did found some weird issue with C32, this code don't work:
Code: Select all
#define NRFL_SPI_CHN SPI_CHANNEL2A
#define SPI_CHANNEL1 1
#define SPI_CHANNEL2 2
#define SPI_CHANNEL3 3
#define SPI_CHANNEL4 4
#define SPI_CHANNEL1A SPI_CHANNEL3
#define SPI_CHANNEL2A SPI_CHANNEL2
#define SPI_CHANNEL3A SPI_CHANNEL4

#if (NRFL_SPI_CHN == SPI_CHANNEL1)
        SPI1CONbits.CKP = 0;
        SPI1CONbits.SMP = 0;
        SPI1CONbits.CKE = 1;
#elif ((NRFL_SPI_CHN == SPI_CHANNEL1A) || (NRFL_SPI_CHN == SPI_CHANNEL3))
        SPI1ACONbits.CKP = 0;
        SPI1ACONbits.SMP = 0;
        SPI1ACONbits.CKE = 1;
#elif ((NRFL_SPI_CHN == SPI_CHANNEL2A) || (NRFL_SPI_CHN == SPI_CHANNEL2))
        SPI2ACONbits.CKP = 0;
        SPI2ACONbits.SMP = 0;
        SPI2ACONbits.CKE = 1;
#elif ((NRFL_SPI_CHN == SPI_CHANNEL3A) || (NRFL_SPI_CHN == SPI_CHANNEL4))
        SPI3ACONbits.CKP = 0;
        SPI3ACONbits.SMP = 0;
        SPI3ACONbits.CKE = 1;
#endif

looks like c32 evaluates all macros as 1 so the first IF is always true no matter what the actual value of the macro is :(