Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing SPI speed #19

offgridsystems opened this issue Mar 14, 2019 · 6 comments


Copy link

commented Mar 14, 2019

I'm finding it impossible to change the SPI speed, which NRFlite programs the default to be 8Mhz .
The nRF24L01+ data sheet calls out a maximum SPI SCK speed of 4M-10Mhz depending on loading on the clock pin. With as little as 10pf loading, the max. clock speed is down to 5Mhz. I would recommend a 4Mhz default, and the user can go up or down from there.
Second, when I edit the NRFLite.h file:
const static uint32_t NRF_SPICLOCK = 8000000; // Speed to use for SPI communication with the transceiver.
I don't see any clock change. Is there somewhere else the clock speed is also being set? If I am not finding it!

Edit 24 minutes later. I did find that the SPI clock speed is also set in SPI.h, so maybe that is overriding the NRFLite.h, which is being included after SPI.h? Hmmmm. Also included code, which is being run on Teensy 3.2.

dparson55 edit: fixed the code block formatting so I could read it. 3 back ticks were needed for the multi-line code blocks.


Demonstrates simple RX and TX operation.
Please read the notes in NRFLite.h for a description of all library features.

Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> No connection
VCC   -> No more than 3.6 volts
GND   -> GND


#include <SPI.h>
//#include <NRFLite.h>
#include <NRFLiteforDK.h>

const static uint8_t SUPERVISOR_RADIO_ID = 1;             // Our radio's id.
const static uint8_t BLOCK_RADIO_ID = 2; // Id of the radio we will transmit to.
const static uint8_t PIN_RADIO_CE = 9;
const static uint8_t PIN_RADIO_CSN = 10;

struct TXRadioPacket // Any packet up to 32 bytes can be sent.
    uint8_t FromRadioId;
    uint32_t OnTimeMillis;
    uint32_t FailedTxCount;
}; */
    uint32_t PS_Id;     // Pack Supervisor radio address
    uint32_t PS_command;    // command to block from supervisor

struct RXRadioPacket // Any packet up to 32 bytes can be used.
    uint32_t Block_Id;     // Block radio address
    uint32_t Block_data;    // data to supervisor 

NRFLite _radio;
TXRadioPacket _TX_radioData;
RXRadioPacket _RX_radioData;

void setup()
        Serial.println("Cannot communicate with radio");
        while (1); // Wait here forever.
    _TX_radioData.PS_Id = SUPERVISOR_RADIO_ID;

void loop()
    // broadcast trigger to blocks, which is a repeat packet containing pack supv. 4 byte ID plus a 4 byte command
    _TX_radioData.PS_command = millis(); // send the current time in milliseconds as a command

    Serial.print("Sending ");
    Serial.print(" ms");
   Serial.print(" from Pack Supervisor #:");

    // Transmit data trigger N times (1.5msec time each one)
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::NO_ACK);
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::NO_ACK);
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::NO_ACK);
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::NO_ACK);
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::NO_ACK);

    // now switch to receive mode to hear all blocks, one after the other. Incomming packet is 32 bytes long
    // takes ~ 100msecs

    // Default states for the radio pins.  When CSN is LOW the radio listens to SPI communication,
    // so we operate most of the time with CSN HIGH.
     delay(10); // now wait for  switch to RX mode, block to send data back  (can be 100msec)   
  while (_radio.hasData())      // see if block has data
    _RX_radioData.Block_Id = BLOCK_RADIO_ID;

        String msg = "Radio ";
        msg += _RX_radioData.Block_Id;
        msg += ", ";
        msg += _RX_radioData.Block_data;
        msg += " ms, ";

        Serial.print(" Total round trip msecs was = ");
        Serial.println((millis()) - _TX_radioData.PS_command);

    By default, 'send' transmits data and waits for an acknowledgement.
    You can also send without requesting an acknowledgement.
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::NO_ACK)
    _radio.send(BLOCK_RADIO_ID, &_TX_radioData, sizeof(_TX_radioData), NRFLite::REQUIRE_ACK) // THE DEFAULT

Thanks for the absolutely jaw dropping great library, nice work!!!!



This comment has been minimized.

Copy link

commented Mar 15, 2019

Well shoot, I made a change to the library recently to fix Issue 18 and maybe this caused the problem you are now seeing. Unfortunately this issue was also related to my attempt to help support the Teensy architecture so maybe I fixed it for one person's situation, but broke it for yours. I don't have one of these for testing, so adding Teensy support looks to be problematic.

For adjusting the SPI clock speed, NRF_SPICLOCK is used in and this is supposed to override any default value assigned in the Arduino SPI library and also override changes other libraries make prior to their usage of the SPI bus (which was issue 18).

Try commenting out the beginTransaction and endTransaction lines so whatever default values the Arduino SPI library is using for the Teensy are preserved. You can also try lowering the NRF_SPICLOCK to 1000000 in case 4000000 (or any other values you have tried) are unsupported on the Teensy for some reason.

// Transfer with the Arduino SPI library.
// SPI.beginTransaction(SPISettings(NRF_SPICLOCK, MSBFIRST, SPI_MODE0)); // Commented out for Teeny test.
for (uint8_t i = 0; i < length; ++i) {
    uint8_t newData = SPI.transfer(intData[i]);
    if (transferType == READ_OPERATION) { intData[i] = newData; }
//SPI.endTransaction(); // Commented out for Teensy test.

Thanks for the note about the 8MHz clock speed being too high based on the capacitive load placed on the crystal. I didn't notice the other tables in the datasheet that showed the max SPI clock being as low as 4MHz, e.g. table 27. I will get this fixed but will wait to hear back from you about the additional SPI troubleshooting.


This comment has been minimized.

Copy link

commented Mar 15, 2019

Unrelated question concerning the code: was there a reason why you didn't use acknowledgement data packets, was it not working or just easier for you to manually switch the radio from being a transmitter and receiver?


This comment has been minimized.

Copy link

commented Mar 15, 2019

Thanks for taking the time to look at the problem. I can take a look at problem on my end this weekend and get back to you by Monday latest.
On the ack packets, I'm not a fan, they seem to add a lot of time. My app needs hundreds of nodes (battery blocks) and there is no time for acks, nor do they seem to be very reliable. My application uses a master to send a sync packet, and then all the nodes respond in sequence. Since it all happens so fast, there is time to query the nodes that did not update data in the master. This is much more reliable than the ack packets, in my testing.


This comment has been minimized.

Copy link

commented Mar 15, 2019

I'll dig into the datasheet of whatever microncontroller the Teensy uses this weekend as well. Maybe manually controlling one of its registers to set its SPI speed is something else that can be tried.

Great info about your ack packet situation as well. Your bad experience with the automatic ack data packets makes perfect sense when so many nodes are involved. Internally the nRF24L01 switches between TX and RX operation each time a REQUIRE_ACK send is performed, and even though it does this much quicker than doing it via the library, having to switch hundreds of times would cause all sorts of packet loss. The radio will retry each send 16 times as well, each time having to switch between TX and RX operation. So it is no wonder why the ack data packets did not work for your situation, what you did to manually control the TX and RX mode is perfect, great work!


This comment has been minimized.

Copy link

commented Mar 18, 2019

Unfortunately the datasheet for the Teensy is a little beyond me, so I'll just need to depend on the Arduino library honoring the setting NRFLite provides. I hope the 2 things I mentioned will work, let me know by 3/20 if you can.


This comment has been minimized.

Copy link

commented Mar 25, 2019

Closing, not able to reproduce and no response from @offgridsystems.

@dparson55 dparson55 closed this Mar 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
2 participants
You can’t perform that action at this time.