however, this hasn't worked at all for me yet. The micropython side running the slave just keeps waiting. On the arduino blue pill side, all I see are send failures. I've tried to match up all the params of the radio based on the constructor code in micropython and ardunio.
Has anyone used arduino/micropython comms with NRF24L01+ successfully? If so, could you please post details of your setup and any obvious gotchas I might be missing. Code for both micropython and ardunio below.
ESP32 receiver:
Code: Select all
"""Test for nrf24l01 module. Portable between MicroPython targets."""
import sys
import ustruct as struct
import utime
from machine import Pin, SPI, resetWDT
from nrf24l01 import NRF24L01
from micropython import const
# Slave pause between receiving data and checking for further packets.
_RX_POLL_DELAY = const(15)
# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before
# transmitting to allow the (remote) master time to get into receive mode. The
# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266.
_SLAVE_SEND_DELAY = const(10)
if sys.platform == 'pyboard':
cfg = {'spi': 2, 'miso': 'Y7', 'mosi': 'Y8', 'sck': 'Y6', 'csn': 'Y5', 'ce': 'Y4'}
elif sys.platform == 'esp8266': # Hardware SPI
cfg = {'spi': 1, 'miso': 12, 'mosi': 13, 'sck': 14, 'csn': 4, 'ce': 5}
elif 'esp32' in sys.platform: # Software SPI
cfg = {'spi': 1, 'miso': 12, 'mosi': 13, 'sck': 14, 'csn': 15, 'ce': 27}
else:
raise ValueError('Unsupported platform {}'.format(sys.platform))
pipes = (b'\xf0\xf0\xf0\xf0\xe1', b'\xf0\xf0\xf0\xf0\xd2')
nrf = None
def initspi():
global nrf
if nrf:
return
didInit = True
csn = Pin(cfg['csn'], mode=Pin.OUT, value=1)
ce = Pin(cfg['ce'], mode=Pin.OUT, value=0)
spi = SPI(cfg['spi'], sck=Pin(cfg['sck']),
mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso']))
nrf = NRF24L01(spi, csn, ce, payload_size=8)
def master():
initspi()
nrf.open_tx_pipe(pipes[0])
nrf.open_rx_pipe(1, pipes[1])
nrf.start_listening()
num_needed = 16
num_successes = 0
num_failures = 0
led_state = 0
print('NRF24L01 master mode, sending %d packets...' % num_needed)
while num_successes < num_needed and num_failures < num_needed:
# stop listening and send packet
nrf.stop_listening()
millis = utime.ticks_ms()
led_state = max(1, (led_state << 1) & 0x0f)
print('sending:', millis, led_state)
try:
nrf.send(struct.pack('i', millis))
except OSError:
pass
# start listening again
nrf.start_listening()
# wait for response, with 250ms timeout
start_time = utime.ticks_ms()
timeout = False
while not nrf.any() and not timeout:
if utime.ticks_diff(utime.ticks_ms(), start_time) > 250:
timeout = True
if timeout:
print('failed, response timed out')
num_failures += 1
else:
# recv packet
got_millis, = struct.unpack('i', nrf.recv())
# print response and round-trip delay
print('got response:', got_millis, '(delay', utime.ticks_diff(utime.ticks_ms(), got_millis), 'ms)')
num_successes += 1
# delay then loop
utime.sleep_ms(250)
print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures))
nrf.stop_listening()
nrf.powerDown()
def slave():
initspi()
nrf.open_tx_pipe(pipes[1])
nrf.open_rx_pipe(1, pipes[0])
nrf.start_listening()
print('NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)')
while True:
resetWDT()
if nrf.any():
while nrf.any():
buf = nrf.recv()
millis = struct.unpack('i', buf)
led_state = 0
print('received:', millis, led_state)
for led in leds:
if led_state & 1:
led.on()
else:
led.off()
led_state >>= 1
utime.sleep_ms(_RX_POLL_DELAY)
# Give master time to get into receive mode.
utime.sleep_ms(_SLAVE_SEND_DELAY)
nrf.stop_listening()
try:
nrf.send(struct.pack('i', millis))
except OSError:
pass
print('sent response')
nrf.start_listening()
try:
import pyb
leds = [pyb.LED(i + 1) for i in range(4)]
except:
leds = []
print('NRF24L01 test module loaded')
print('NRF24L01 pinout for test:')
print(' CE on', cfg['ce'])
print(' CSN on', cfg['csn'])
print(' SCK on', cfg['sck'])
print(' MISO on', cfg['miso'])
print(' MOSI on', cfg['mosi'])
print('run nrf24l01test.slave() on slave, then nrf24l01test.master() on master')
Blue pill sender (arduino)
Code: Select all
#include "WProgram.h"
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <stdio.h>
//
// Hardware configuration
//
#define PIN_START PB9
int CE_PIN = PB0;
int CSN_PIN = PA4;
// SPI Class for communication with SPI
SPIClass SPI_1(1);
RF24 radio(SPI_1, CE_PIN, CSN_PIN);
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = {0xF0F0F0F0E1, 0xF0F0F0F0D2};
void setup(void)
{
delay(5000);
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
SPI_1.begin();
SPI_1.setDataMode(SPI_MODE0);
SPI_1.setBitOrder(MSBFIRST);
pinMode(PIN_START, INPUT_PULLDOWN);
delay(5);
while (!digitalRead(PIN_START))
{
Serial.println("Pull pin PB9 high to start");
delay(1000);
}
radio.begin();
radio.setChannel(46);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setRetries(6, 8);
radio.setPayloadSize(8);
radio.setPayloadSize(8);
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1, pipes[1]);
radio.startListening();
//
// Dump the configuration of the rf unit for debugging
//
radio.printDetails();
}
void toggleLED()
{
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void loop(void)
{
toggleLED();
// First, stop listening so we can talk.
radio.stopListening();
// Take the time, and send it. This will block until complete
unsigned long time = millis();
printf_P("Now sending %lu...", time);
bool ok = radio.write(&time, sizeof(unsigned long));
if (ok)
Serial.println("ok...\r\n");
else
Serial.println("failed.\r\n");
// Now, continue listening
radio.startListening();
// Wait here until we get a response, or timeout (250ms)
unsigned long started_waiting_at = millis();
bool timeout = false;
while (!radio.available() && !timeout)
if (millis() - started_waiting_at > 200)
timeout = true;
// Describe the results
if (timeout)
{
Serial.println("Failed, response timed out.\r\n");
}
else
{
// Grab the response, compare, and send to debugging spew
unsigned long got_time;
radio.read(&got_time, sizeof(unsigned long));
// Spew it
printf_P("Got response %lu, round-trip delay: %lu\r\n", got_time, millis() - got_time);
}
toggleLED();
// Try again 1s later
delay(1000);
}