Unable to initialize NRF24L01+ when using an ATmega328P-PU



  • Hello! Hope you're all having a good day.

    I'm trying to use a NRF24L01+ module on a "bare" ATmega328P-PU, but I fail to initialize the radio, no matter what I do.

    The ATmega328P is basically a "virgin" from a reputable distributor.

    I placed it on a breadboard, added 0.1µF ceramic caps to both power pin pairs and a 10kΩ resistor between pin 1 and VCC, to pull reset high.

    The NRF24L01+ has its own electrolytic cap right next to it.

    The whole circuit is powered with 3.3V.

    Programming is done via PlatformIO in VS Studio Code on a Mac and using a USBasp. MySensors library is v2.3.1

    Here's a quick Fritzing drawing of the setup:

    0_1552860502738_breadboard.png

    This is the sketch I use:

    #include <Arduino.h>
    
    #define MY_DEBUG
    #define MY_BAUD_RATE 19200
    
    #define MY_RADIO_RF24
    #define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    #define CHILD_ID 5
    #define LED_PIN 8
    
    #define SKETCH_NAME "Test Sensor"
    #define SKETCH_MAJOR_VER "1"
    #define SKETCH_MINOR_VER "0"
    
    #include <MySensors.h>
    
    MyMessage msg(CHILD_ID, V_TRIPPED);
    
    void setup()
    {
      pinMode(LED_PIN, OUTPUT);
    }
    
    void presentation()
    {
      sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER);
      present(CHILD_ID, S_DOOR);
    }
    
    void loop()
    {
      digitalWrite(LED_PIN, HIGH);
      send(msg.set(HIGH));
      wait(1000);
      digitalWrite(LED_PIN, LOW);
      send(msg.set(LOW));
      wait(1000);
    }
    
    

    After building and uploading it via pio run -t program, the debug log consists of an endless loop of failed radio inits:

    (Also, the LED on pin 8 does not blink. I guess that's because the program never leaves the setup() if the radio cannot be initialized.)

     __  __       ____
    |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
            |___/                      2.3.1
    
    208 MCO:BGN:INIT NODE,CP=RNNNA---,REL=255,VER=2.3.1
    331 TSM:INIT
    344 TSF:WUR:MS=0
    366 !TSM:INIT:TSP FAIL
    391 TSM:FAIL:CNT=1
    411 TSM:FAIL:DIS
    430 TSF:TDI:TSL
    10448 TSM:FAIL:RE-INIT
    10471 TSM:INIT
    10493 !TSM:INIT:TSP FAIL
    10520 TSM:FAIL:CNT=2
    10541 TSM:FAIL:DIS
    10561 TSF:TDI:TSL
    20584 TSM:FAIL:RE-INIT
    20606 TSM:INIT
    20629 !TSM:INIT:TSP FAIL
    20656 TSM:FAIL:CNT=3
    20676 TSM:FAIL:DIS
    20697 TSF:TDI:TSL
    ...
    

    Things I have tried to solve this:

    • Checked the connection of all the wires
      • Checked if there is continuity between every connection, from pin to pin
      • Measured voltage on all VCC and GND pins
      • Swapped out every wire
      • I even swapped out the breadboard
    • I swapped out the radio module with two others (all without "blobs"), one of which I took straight out of a project (not using MySensors) that was known working and running minutes prior to this (and still does)
    • I tried using various different power sources
      • The USBasp itself
      • A small "breadboard PSU" via USB
      • A wall wart with adjustable output, set to 3.3V
      • All of which were able to provide sufficient power for various other projects featuring the NRF24L01+ previously
    • Used a whole bunch of different electrolytic capacitors between 4.7 and 220µF for the radio
    • Changed the low fuse byte of the ATmega328p from 0x62 to 0xE2, which sets the CKDIV8 bit to be unprogrammed, so that the MCU runs on 8MHz instead of 1MHz
    • Used various baud rates from 9600 to 115200 (19200 works best for me)
    • Uploaded a minimal sketch that drives all the SPI pins (9-13) high / low and measured if they all output stable 3.3V / 0V, which they did
    • Explicitly defined CE and CS pins as 9 and 10 in the sketch

    And probably a whole bunch of other things, too. But nothing helped to successfully init the radio. It doesn't seem to be a connection issue, nor a power issue.

    What is interessting though:

    • If I use the exact same hardware setup but use a different library to communicate over the radio (TMRh20 RF24 lib) instead of MySensors, I can send messages to a second radio just fine.
    • If I use the exact same sketch and setup, but on a Arduino Duemillanove, Nano or Pro Mini instead of the bare ATmega328P, the radio initializes right away.

    Every part on its own seems to be working perfectly fine. Only when the ATmega328P and the MySensors library come together, it fails.

    Any idea what's happening here?



  • Small Update:

    I uploaded the sketch from above onto a ATmega328P-AU that's on a custom PCB along with a NRF24L01+ SMD module. There's a 100µF electrolytic cap on the board, as well as a 0.1µF MLCC right in front of the radio's power pins.

     __  __       ____
    |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
            |___/                      2.3.1
    
    208 MCO:BGN:INIT NODE,CP=RNNNA---,REL=255,VER=2.3.1
    331 TSM:INIT
    344 TSF:WUR:MS=0
    366 !TSM:INIT:TSP FAIL
    391 TSM:FAIL:CNT=1
    411 TSM:FAIL:DIS
    430 TSF:TDI:TSL
    10448 TSM:FAIL:RE-INIT
    10471 TSM:INIT
    10493 !TSM:INIT:TSP FAIL
    10520 TSM:FAIL:CNT=2
    10541 TSM:FAIL:DIS
    10561 TSF:TDI:TSL
    10584 TSM:FAIL:RE-INIT
    20606 TSM:INIT
    20629 !TSM:INIT:TSP FAIL
    20656 TSM:FAIL:CNT=3
    20676 TSM:FAIL:DIS
    20697 TSF:TDI:TSL
    30742 TSM:INIT
    30765 !TSM:INIT:TSP FAIL
    30791 TSM:FAIL:CNT=4
    30812 TSM:FAIL:DIS
    30832 TSF:TDI:TSL
    30855 TSM:FAIL:RE-INIT
    40878 TSM:INIT
    40900 !TSM:INIT:TSP FAIL
    40927 TSM:FAIL:CNT=5
    40947 TSM:FAIL:DIS
    40968 TSF:TDI:TSL
    ...
    

    Same issue as with the ATmega328P-PU and the "regular" NRF24L01+ module. MySensors is unable to initialize the radio.

    I've double-checked all connections between the radio and the MCU. They're all properly connected. Just for my own sanity, I also uploaded a different sketch that uses the TMRh20 RF24 library for wireless communication and was able to transmit messages to a second device.

    So what is so different between a Arduino board and a bare ATmega, that MySensors fails to initialize the radio?


  • Hardware Contributor

    @bearwithbeard - very well debuged, a very strange issue it seems.

    I would still make sure the fuses are correct and upload a bootloader that you know works, like the one sensebender is using. (You can download that in the board manager in Arduino IDE).
    Is this something you have tried? I read you changed the low fuse...



  • Hey @sundberg84, thanks for your reply!

    I thought about uploading a bootloader, as this seems to be the only difference between an Arduino and a bare ATmega in this case. On the other hand, the sketch is loading properly on both ATmegas, or otherwise I wouldn't be able to read the serial output at all, right?
    I think I'm going to try uploading a bootloader anyway this or tomorrow evening, when I have a little bit more time for it.

    And yes, I changed to low fuse. Specifically, just one bit of it, to disable CKDIV8. I wanted to make sure that the MCU isn't communication too slow at 1MHz to properly init the radio, since MySensors seems to clock SPI at 2MHz per default. Maybe I should try adjusting MY_RF24_SPI_SPEED, too.

    In any case, the fuse bytes are fine:

    avrdude: Device signature = 0x1e950f (probably m328p)
    
    avrdude: safemode: Fuses OK (E:FF, H:D9, L:E2)
    

    That's the default setting except CKDIV8 set to 1:

    0x62: 0 1 1 0 0 0 1 0
    0xE2: 1 1 1 0 0 0 1 0
    

  • Hardware Contributor

    @bearwithbeard - fuses looks good.
    This works for me... except I have a bootloader. Sorry nothing else I can suggest.



  • Interesting! I increased the SPI bus speed via MY_RF24_SPI_SPEED from 2 to 10 MHz, like the TMRh20 RF24 library does, and suddenly the radio gets initialized. Even 4 MHz is high enough. Why? No clue. The default 2 MHz seems to be fine for most, if not all of you, I suppose.

    16 MCO:BGN:INIT NODE,CP=RNNNA---,REL=255,VER=2.3.1
    26 TSM:INIT
    27 TSF:WUR:MS=0
    33 TSM:INIT:TSP OK
    35 TSM:INIT:STATID=5
    37 TSF:SID:OK,ID=5
    39 TSM:FPAR
    43 TSF:MSG:SEND,5-5-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    95 TSF:MSG:READ,0-0-5,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    

    Now I'm able to communicate with the gateway, both on the 328P-PU and the 328P-AU. It doesn't matter if CKDIV8 is set or not (1 vs 8 MHz internal clock).

    Maybe my NRF24L01+ modules are weird ones, although they look normal. But since all those that I tested are from two different sellers and out of three different orders, I doubt they are all off.

    Anyway, I don't really unterstand why that change helped. All that matters for me right now is that it's working. 🙂


  • Admin

    @bearwithbeard What board settings did you choose for compilation?



  • @tekka nanoatmega328 currently. I've used 328p8m earlier - and still do in other projects - but with it I struggled to get the serial connection to not print gibberish (most likely just didn't set the right baud rate in the serial monitor).

    [env:nanoatmega328]
    platform = atmelavr
    board = nanoatmega328
    framework = arduino
    upload_protocol = usbasp
    upload_flags =
        -Pusb
        -b$UPLOAD_SPEED
    upload_speed = 19200
    

  • Admin

    @bearwithbeard Your bare at328p runs at 8Mhz [intRC] but you compile with 16Mhz settings (according to platformio nanoatmega328 boards). You may resolve your issue with e.g. pro8MHzatmega328 settings (3V3, 8Mhz). Ideal baudrate 38400 or 57600.



  • Oh shhhhoot.

    So by switching from 328p8m to nanoatmega328p in order to fix some issues, I actually made it worse, because the latter sets F_CPU to 16000000L.

    What an unbelievable oversight on my part. That explains why I had to monitor the serial output at 1/16th of the baud rate.

    Overwriting the frequency in the config file with board_build.f_cpu = 8000000L did the trick. No need to adjust the SPI bus speed anymore. Baud rate set to 57600, monitoring at 7200 (1/8th, CKDIV8 enabled). All good!

    Thanks for pointing that out, @tekka! I feel embarrassed, that I didn't notice that myself.


    Small update -- after some more testing, setting board_build.f_cpu = 1000000L and #define MY_BAUD_RATE 9600 seems to be even better with CKDIV8 enabled. 1ms is actually 1ms and communication between nodes is way more responsive.

    Powering the sensor node on, initializing, finding parent, presentation, etc,.. is now done withing 6 seconds instead of roughly 30 seconds.


 

322
Online

8.9k
Users

9.7k
Topics

101.2k
Posts