NRF24l01+, EEPROM and shared SPI = brick module ?

  • Hello Everyone,

    i'm currently working on building a new module using an RFID module + NRF24L01+ using mysensors.

    for my RFID module, i'm using the EEPROM to store card ID and mysensors to communicate to my jeedom who came home etc.
    both devices work with SPI that i manage to share (did I ?).
    in the EEPROM i store some data from 0 to 20 (5cards) using the EEPROM library (read/write)

    my code is based on this example with addition of mysensors and some minor correction and simplification (i will share it later if that could help)

    and i got a weird behavior:

    • when i plugged the device the first time, everything work fine but the master card as been forgotten, so i got to store it again in the eeprom (write 5 byte from 0) but otherwise enverything work fine on mysensors side or rfid

    • when i unplggued and plugged again a second time, same behavior (that's when i started to feel something was off πŸ˜… )

    • and when i do it again... this time, the mysensors library refuse to start (init fail in loop ...).

    to make sure i didnt brick my code (cause i change some minor thing between each plugged), i changed the nrf module, and it start to work again but same exact behavior : 3 power on/off and no more mysensors init ...

    with this behavior, i started some research on internet and find out that mysensors is also using the eeprom to store some information ... first fail ! i then tried to wipe the eeprom with a simple write 0 everywhere. but it didnt work .. my nrf modules are still brick ...

    i found into config.h this information:

     * @def MY_SPECIAL_DEBUG
     * @brief Define MY_SPECIAL_DEBUG to enable support for I_DEBUG messages.
     * I_DEBUG messages are sent from the controller to the node, which responds with the requested
     * data. The request can be one of the following:
     * - 'R': routing info (only repeaters): received msg XXYY (as stream), where XX is the node and YY
     *   the routing node
     * - 'V': CPU voltage
     * - 'F': CPU frequency
     * - 'M': free memory
     * - 'E': clear MySensors EEPROM area and reboot (i.e. "factory" reset)
    //#define MY_SPECIAL_DEBUG

    if i want to make sure to clear the eeprom for mysensors, i should put #define MY_SPECIAL_DEBUG 'E' and/or 'M' onto my node ? i dont understand the "I_DEBUG messages are sent from the controller to the node, which responds with the requested" ?
    i dont think it will fix my issue, but it worse the try.

    to correct my code i will try to use :
    Saving state
    You can save a state (in local EEPROM) which is good for actuators to "remember" state between power cycles. You have 256 bytes to play with. Note that there is a limitation on the number of writes the EEPROM can handle (~100 000 cycles).

    void saveState(uint8_t pos, uint8_t value);
    pos - The position to store value in (0-255)
    value - Value to store in position

    Retrieving a state (from local EEPROM).
    uint8_t loadState(uint8_t pos);
    pos - The position to fetch from EEPROM (0-255)

    is it really to save custom value ? i don't understand why we talk about "state". i don't want to brick a new one ! πŸ˜–

    finally my real questions:

    • does it already happen to you this kind of behavior ? and how did you fixed it ? perhaps i'm missleading myself with eeprom. Maybe the shared SPI is the issue ?
    • is using saveState/loadstate is the correct way to use eeprom when using mysensors ?
    • is there a way to hard reset a nrf24 module ? i cant believe the nrf module is completly brick since voltage is stable and it's not 3 plug/unplgged that will brick them ...

    thanks a lot for your help and the great work on mysensors πŸ™‚

  • You seem to have directly accessed the EEPROM; as you already have found out, there is only a specific area reserved to store from sketch side and some functionality provided to do it in a "save" way. So you will have to split your information on the card ID's and use the "MySensors"-way...

    If the Node isn't working, I don't believe you bricked the nRF but the node will not boot or get correct communication info from EEPROM. So just use the MySensors (!) clear EEPROM sketch and reflash the Arduino...

    On I_DEBUG: Just set the option in the sketch; the letter is used to identify the type of request at runtime ("payload"). "E" will just erase some basic info afaik, especially NodeID and ParentnodeID.

    Hope this makes the picture more clear.

  • @rejoe2 thanks ! i didnt see there was a specific sketch for it...
    i will try this tonight. concerning the I_DEBUG, just for my understanding, if i put the define with "E", it will automatically clear some setting in the eeprom so it's less invasive than the dedicated clear sketch. did i understand it right ?

    thanks a lot, it make me crazy for 2 days, but at least i found out some new features on mysensors πŸ˜‰

  • well ...

    i just tried to use the dedicated flash eeprom sketch ... and nothing changed 😞
    i also tried to plug the nrf24l01 module to another arduino with a basic sketch... it fails init ...

    is there another way to directly hard reset the nrf24 module ? or did i really brick it ? ... i'm scared to try my main sketch again, because if it doesnt come from eeprom wrong usage, i'm screwed ! 😱 )

    does a wrong manipulation of eeprom can brick a nrf24 module ?

  • so ... i'm completly lost ... i made several test.... nothing worked... i look through the rf24 library to get more debug from the module itself ...

    i found out the function: void RF24::printDetails ( void )

    i tried it several time on my "brick" nrf24 module ... it shows everything at 0 and got stuck on a send function (obviously).
    i even tried without the module plug ... same result (everything at 0)

    i cried a little, then tried the same code on the same arduino but with a new module ...
    i got a result

    19:42:05.014 -> STATUS		 = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    19:42:05.082 -> RX_ADDR_P0-1	 = 0x4141417852 0xc2c2c2c2c2
    19:42:05.115 -> RX_ADDR_P2-5	 = 0xc3 0xc4 0xc5 0xc6
    19:42:05.182 -> TX_ADDR		 = 0x4141417852
    19:42:05.182 -> RX_PW_P0-6	 = 0x20 0x00 0x00 0x00 0x00 0x00
    19:42:05.250 -> EN_AA		 = 0x3f
    19:42:05.250 -> EN_RXADDR	 = 0x03
    19:42:05.284 -> RF_CH		 = 0x4c
    19:42:05.284 -> RF_SETUP	 = 0x27
    19:42:05.318 -> CONFIG		 = 0x0e
    19:42:05.318 -> DYNPD/FEATURE	 = 0x00 0x00
    19:42:05.353 -> Data Rate	 = 250KBPS
    19:42:05.387 -> Model		 = nRF24L01+
    19:42:05.421 -> CRC Length	 = 16 bits
    19:42:05.421 -> PA Power	 = PA_MAX

    i then tried to replug my "brick" module ... and this time ... it works ... i'm lost ! lol

    in case someone got the same issue and want to try my "fix" (can't call it a fix, but work on 2 "brick" nrf24 module for mysterious reason).

    most of the code is useless (then send & Co) but i let it to make sure it initiate a send.

    // SimpleTx - the master or the transmitter
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #define CE_PIN   9
    #define CSN_PIN 10
    const byte slaveAddress[5] = {'R','x','A','A','A'};
    RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
    char dataToSend[10] = "Message 0";
    char txNum = '0';
    unsigned long currentMillis;
    unsigned long prevMillis;
    unsigned long txIntervalMillis = 1000; // send once per second
    static FILE uartout = {0} ;
    void setup() {
        Serial.println("SimpleTx Starting");
    // fill in the UART file descriptor with pointer to writer.
       fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
       // The uart is the standard output device STDOUT.
       stdout = &uartout ;
        radio.setDataRate( RF24_250KBPS );
        radio.setRetries(3,5); // delay, count
    bool printed = false;
    void loop() {
        currentMillis = millis();
        if (currentMillis - prevMillis >= txIntervalMillis) {
            prevMillis = millis();
        if (!printed){
    void send() {
        bool rslt;
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
            // Always use sizeof() as it gives the size as the number of bytes.
            // For example if dataToSend was an int sizeof() would correctly return 2
        Serial.print("Data Sent ");
        if (rslt) {
            Serial.println("  Acknowledge received");
        else {
            Serial.println("  Tx failed");
    void updateMessage() {
            // so you can see that new data is being sent
        txNum += 1;
        if (txNum > '9') {
            txNum = '0';
        dataToSend[8] = txNum;
    // create a output function
    // This works because Serial.write, although of
    // type virtual, already exists.
    static int uart_putchar (char c, FILE *stream)
        Serial.write(c) ;
        return 0 ;

    and after i tried this mysensor code that failed before (with a working gateway) and worked after the code above... :

     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     * Created by Henrik Ekblad <>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list:
     * Documentation:
     * Support Forum:
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     * Version 1.0 - Henrik Ekblad
     * Motion Sensor example using HC-SR501
    // Enable debug prints
    #define MY_DEBUG
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    #include <MySensors.h>
    uint32_t SLEEP_TIME = 5000; // Sleep time between reports (in milliseconds)
    #define CHILD_ID 1   // Id of the sensor child
    // Initialize motion message
    MyMessage msg(CHILD_ID, V_TRIPPED);
    void setup()
    void presentation()
    	// Send the sketch version information to the gateway and Controller
    	sendSketchInfo("basic test", "1.0");
    	// Register all sensors to gw (they will be created as child devices)
    	present(CHILD_ID, S_MOTION);
    bool tripped = true;
    void loop()
    	send(msg.set(tripped?"1":"0"));  // Send tripped value to gw

    thanks again @rejoe2

    hope this will help someone, or if someone can explain to me the "magic" behind this ?

  • @oniric Which clear EEPROM sketch did you use?
    There are two of them, this is the reason I put the (!) behind the MySensors version. This one writes "FF" (meaning: we don't have an NodeID and first have to ask for that at boot time) the other one "00" (meaning: I'm Node_0, my parent is Node_0...).

  • HEllo,

    i used this one :

    ok intersting what you said, isnt it a magic number somewhere on the eeprom at boot to make sure this doesnt happen ? (if i understand correclty what you said : if i wipe my eeprom with 0x0, it might be wrong cause at boot it will think I'm Node_0, my parent is Node_0...) ?

    it seems i used the right one tho, but not at the beginning, maybe it would explain the weird behavior i had issue to understand because at first i used my own made wiper and of course i put 0x0 ! which would explain the result using the rf24 library debug printer full of 0.

    thanks again πŸ™‚

  • @oniric said in NRF24l01+, EEPROM and shared SPI = brick module ?:

    if i wipe my eeprom with 0x0, it might be wrong cause at boot it will think I'm Node_0, my parent is Node_0...) ?

    This might not be wrong, it is wrong to write zeros, causing the node acting as a GW: Node_0, no further transport over nRF-air required...)

Log in to reply

Suggested Topics

  • 3
  • 24
  • 5
  • 7
  • 6
  • 15
  • 4
  • 3