Pico Explorer Base + NRF24L01+ - SPI Trouble

I’m working on trying to get an NRF24L01+ module working with the Pico Explorer Base. Here’s my basic wiring:

PiBase → Txr PiBase → Txr
GND → GND 3v3 → VCC
GP6 → CE GP7 → CSN
SCLK → SCK MOSI → MOSI
MISO → MISO n/c → IRQ

(n/c = not connected)

I’m getting an error: OSError: nRF24L01+ Hardware not responding

I’ve ran into several issues here, including that the drivers aren’t in the micropython repo anymore (they are there in PRs, though). However, something else I noticed was that the SPI pins on the front breakout for SCLK (GP18), MISO (GP16), and MOSI (GP19) are tied to the same SPI bus that the display seems to be using: LCD CS (GP17).

I’m using the most recent version of micropython uf2 off of your product site, but am curious if this bus is actually able to be used, period. The Pico’s SPI1 bus (8-11, 12-15) are used for the motors and buttons respectively, so those pins are not available, and if the SPI0 bus is used for the display, are those header pins not actually usable for SPI?

One more comment I should have included in the initial request: The drivers are now located here in the micropython/micropython-lib

[Just to preface this, I don’t work for Pimoroni]

The Pico’s SPI1 bus (8-11, 12-15) are used for the motors and buttons respectively, so those pins are not available, and if the SPI0 bus is used for the display, are those header pins not actually usable for SPI?

The same SPI pins can be used for driving multiple devices, there will be a Chip Select/Enable pin which is used to ensure that devices only recieve instructions intended for them and not for another device. It shouldn’t be a problem that the SPI bus is also connected to other devices, as long as you’re not trying to send data to those at the exact same time as the NRF.

I’ve got a Waveshare NRF24L01+ and the Explorer base, so I just tried setting them up in the way you described, and I’m getting the same error. I’ve hooked up a logic analyser and I can see the CSN pin dip when the board tries to talk to the NRF, but there’s no activity on the clock or MISO/MOSI lines. Assuming you and I are getting the same error for the same reason, the problem seems to lie with the clock not starting when the message is sent. I’m not sure why, honestly.

Thanks for the pointing that I’m not just fully n00b at this since you’re replicating! I feel much more sane this morning hearing that.

Hmmm… I’ve just tested it without the explorer base (basic troubleshooting I missed), and still had no joy. :( I’m wondering if there’s something wrong with the firmware itself. Specifically, I am wondering if the cs for the LCD never turns off or something goofy like that.

Next troubleshooting steps (keeping myself organized for this cause I’m stretching for options now):

  1. I’m gonna go do a full build with base micropython (and not the updated one with pimoroni’s explorer base build) and see if that starts working. I’ll be using the pinouts the driver author recommends here to try to remove any other variables.
  2. If that’s successful, I’ll roll back to the same pinouts I’m using above (which should be usable through the board). If that fails, then the driver may not handle the specific pinout setup I’m using… :)
  3. If that’s successful, then I’m gonna do a clean install of the pimoroni base firmware w/ no physical changes to the device (leaving everything plugged in) and see if that breaks the comms again. If so, there’s the problem, and I can open an issue for the firmware.
  4. If it’s working, then I’m gonna enable using the display in my code again and see if that causes the break. Again, would result in a firmware issue being opened.
  5. If step 1 fails, I’ll probably attempt to power the transceiver from a separate 3v3 power source, since I did see a comment about that this morning at this forum response.

Anyways, thanks for sanity checking my setup and understanding @Shoe! I’ll update once I run through these probably late late tonight or something if I can get my toddler to bed at a reasonable time. :D

I’m a bit confused why that person got transmit to sort of work but not recieve when using the Pico’s 3v3 pin, as surely the transmit will take a lot more power than recieve?

I think you’re right, it’s some sort of pinout issue. If the SCK isn’t ticking then the SPI transmissions won’t ever work, so there has to be some sort of pin-related reason why that isn’t happening. I’d have expected MicroPython to throw an Exception if anything failed, so maybe it thinks it is outputting a clock just fine? One of the constant issues with these boards is that everyone uses different pin teminology (physical pin vs pin function on the chip it is connected to vs just plain arbitrary designations), so maybe the SPI setup isn’t being done how we think it is somewhere.

Physical Pin number versus GP Number just caught me out on a Pico. And you’d think I’d know better having been dealing with it on a Pi all these years. I was doing my usual triple check and found my mistake. The next step in the build would have been soldering my Pico W on, covering up those solder pads. Would have been a real PITA to fix then.

Alrighty - tonight’s tests:

  1. Native nightly micropython with the suggested 4,6,7,14,17 pins + GND/3v3 = same error
  2. Powering with a 3.7v LiPo w/ shared ground (GND from Lipo, Pico, and NRF24L01+ all tied together, Pico from USB, NRF from LiPo) = same error.
  3. Attempted trying to hit direct Pin #s instead of GPIO #s just in case the driver wasn’t specific as well (even though pi docs imply those #s were GPIO #s) = same error

I’m at the “do I have bad hardware” stage, so tomorrow I’ll test the NRFs against the arduinos they came from from a previous project. If they work there, then ¯_(ツ)_/¯ no idea. If they don’t work there, then I had both go bad after about a year on the shelf doing nothing - :P

One thing to note: I’m just attempting to get the nrf24l01test.slave() function working, since that must start before the .master() function, so it should at least get to no errors if I get it working, which I haven’t. :)

both modules send and receive via Arduino - gonna retry clean again and hope I’m not fully insane…

Okay, re-connected both modules one to the existing Pico I’ve been using and one to an older Pico. The older pico worked flawlessly immediately. The new one is still giving me a hardware error. So I’m down to a firmware difference between the two devices most likely (the failed pico had the pimoroni firmware and then the latest micropython, the working one had a micropython from a few months ago). Otherwise, I have a board with a bad pin or similar somewhere in the loop, even though the pico explorer base seems to work flawlessly that I can tell.

[SOLVED IT] Not a firmware problem, a test program problem!
The nrf24l01test.py program only handles DEFAULT pins for non-ESP32 tools. For the others, it just ignores the custom pins for SCK, MOSI, and MISO. Fixing that fixed my issues and is now working!

Testing Tonight:

  1. I rolled back my failing pico to rp2-pico-w-20220712-unstable-v1.19.1-127-g74794d42b.uf2 and it worked w/ default pins.
  2. Flashing the pimoroni-picow-v1.19.6-micropython.uf2 seemed to work as well once I got it working on the July build I had w/ default pins.
  3. Flashed the latest pimoroni picow firmware just to be concise, and looks like it’s still working, soooo…
  4. Moved back to the pico explorer base, and original pinouts, and nothing worked :(
  5. Moved out of base and back to default pins by author of driver, and works fine, but that pinout wouldn’t work on the pico explorer base.
  6. Tried the pico explorer base pinout just on breadboard and no joy. Reset to default pins again.
  7. Started trying to move any of the pins one by one to another SPI0_x pin, and no joy.
  8. Moved CSN and CE pins to new spots (GPIO 1, GPIO 0 respectively) one by one and those work.
  9. Debugging the stock testing, since it’s clearly mis-handling the SPI pins somewhere. Noticed this:
    if cfg["spi"] == -1:
        spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
        nrf = NRF24L01(spi, csn, ce, payload_size=8)
    else:
        nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
  1. Since rp2 boards use 0 or 1 for the SPI buses, it will always drop through and not use the custom pinouts.
  2. Added the following to the if / else statement to detect an abnormal bus specification -2. This defaults to SPI bus 0, but honors the custom pins.
    if cfg["spi"] == -1:
        spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
        nrf = NRF24L01(spi, csn, ce, payload_size=8)
    elif cfg["spi"] == -2:
        spi = SPI(0, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
        nrf = NRF24L01(spi, csn, ce, payload_size=8)
    else:
        nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
  1. I then updated my cfg from the testing tool to enable that -2 value and the custom pinouts for the pico explorer base.
elif usys.platform == "rp2":  # PI PICO
    cfg = {"spi":-2, "miso": 16, "mosi": 19, "sck": 18, "csn": 7, "ce": 6}

  1. Tested in breadboard and everything’s A-OK. Wowzers!
  2. Move back to pico explorer base, and it’s all working.

Gotta say, this has been a good refresher in basic troubleshooting and eliminating variables. Also, that’s a really annoying bug. Will file a ticket with the library for this fix (or something similar).

Submitted issue with main library #539.