使用NRF24L01进行故障排除Arduino/PI4通信
我有一个项目需要在没有 WiFi 的情况下进行短距离通信,因此我尝试使用一些 nRF24L01 收发器来实现这一点。
我使用 Arduino Uno 传输数据,使用 Raspberry Pi 4 接收数据,但到目前为止 Pi 还没有收到任何消息。目前我已经浏览了各种教程和包/库,但完全没有成功。
我是一位经验丰富的软件开发人员,但对 Arduino 方面的经验并不丰富。
配置如下:
Arduino:
nrf24 | arduino |
---|---|
Vin | 3V3 |
GND | GND |
CE | Pin 9 |
CNS | Pin 10 |
MOSI | Pin 11 |
MISO | Pin 12 |
SCK | Pin 13 |
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "printf.h"
RF24 radio(9, 10);
void setup() {
printf_begin();
Serial.begin(9600);
radio.begin();
radio.setChannel(0x76);
const uint64_t address = 0xfd7dfdfdfd;
radio.setPALevel(RF24_PA_MIN);
radio.setCRCLength(RF24_CRC_16);
radio.enableDynamicPayloads();
radio.enableAckPayload();
radio.setDataRate(RF24_1MBPS);
radio.openWritingPipe(address);
radio.stopListening();
radio.printDetails();
}
void loop() {
bool sendResult;
if (radio.available()){
Serial.println("Radio is available");
} else {
Serial.println("Radio is unavailable");
}
char text[32] = "Testeroni";
sendResult = radio.write(&text, sizeof(text));
if (sendResult) {
Serial.println("Message sent");
} else {
Serial.println("Message not sent");
}
delay(1000);
}
Pi 4:
使用lib_nrf24
包。
SPI 使能:
$ stat /dev/spidev0.0
File: /dev/spidev0.0
Size: 0 Blocks: 0 IO Block: 4096 character special file
Device: 5h/5d Inode: 420 Links: 1 Device type: 99,0
Access: (0660/crw-rw----) Uid: ( 0/ root) Gid: ( 999/ spi)
Access: 2022-04-02 16:16:46.749999997 -0500
Modify: 2022-04-02 16:16:46.749999997 -0500
Change: 2022-04-02 16:16:46.749999997 -0500
Birth: -
nrf24 | pi/GPIO |
---|---|
Vin | Pin 17 / 3V3 |
GND | Pin 20 / GND |
CE | Pin 22 / GPIO 25 |
CNS | Pin 24 / GPIO 8 / SPI0_CE0_N |
MOSI | Pin 19 / GPIO 10 / SPI0_MOSI |
MISO | Pin 21 / GPIO 9 / SPI0_MISO |
SCK | Pin 23 / GPIO 11 / SPI0_CLK |
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
import time
import spidev
from lib_nrf24 import NRF24
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0, 7)
radio.setRetries(15, 15)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MIN)
radio.setCRCLength(NRF24.CRC_8)
radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openReadingPipe(0, [0xfd, 0x7d, 0xfd, 0xfd, 0xfd])
radio.startListening()
radio.stopListening()
radio.printDetails()
radio.startListening()
c = 1
while True:
akpl_buf = [c,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8]
while not radio.available([0]):
time.sleep(10000/1000000.0)
recv_buffer = []
radio.read(recv_buffer, radio.getDynamicPayloadSize())
if recv_buffer:
print(f'Received: {recv_buffer}')
c += 1
if c&1 == 0:
radio.writeAckPayload(1, akpl_buf, len(akpl_buf))
time.sleep(1)
启动
我首先启动 Raspberry Pi 接收器:
$ sudo python library_listener.py
/home/pokeybill/lib_nrf24.py:377: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
self.GPIO.setup(self.ce_pin, self.GPIO.OUT)
STATUS = 0x03 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=1 TX_FULL=1
RX_ADDR_P0-1 =
0xffdfffffff 0xf87878f8f8
RX_ADDR_P2-5 =
0xf8
0xf9
0xf9
0xf9
TX_ADDR =
0xfdfdfdfdfd
RX_PW_P0-6 =
0x81
0x80
0x80
0x80
0x80
0xc0
EN_AA =
0x8f
EN_RXADDR =
0xc0
RF_CH =
0x9f
RF_SETUP =
0xff
CONFIG =
0x98
DYNPD/FEATURE =
0x83
0x81
Data Rate = 1MBPS
Model = nRF24L01
CRC Length = 8 bits
PA Power = PA_HIGH
Received: [128, 0, 0, 0, 0]
然后启动 Arduino Uno,这是串行输出:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xfd7dfdfdfd 0x0104030201
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xfd7dfdfdfd
RX_PW_P0-6 = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x76
RF_SETUP = 0x01
CONFIG = 0x0a
DYNPD/FEATURE = 0x3f 0x06
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 8 bits
PA Power = PA_MIN
Radio is unavailable
Message not sent
我立即注意到警告:
RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
self.GPIO.setup(self.ce_pin, self.GPIO.OUT)
但是,似乎无论我做什么,我总是收到此警告。我尝试多次重新启动 pi 并显式调用 GPIO.cleanup() ,但没有任何乐趣。
另外,似乎无论我在 Raspberry Pi 代码中使用什么管道地址,它们都与我看到的接收器配置不匹配。
arduino radio.available()
调用永远不会返回 true,并且 radio.write
调用永远不会被确认。
Raspberry Pi 偶尔会收到随机噪音,但从未收到来自 arduino 的消息。当我在代码中明确将通道设置为 0x76
时,pi 似乎也有一个 RF_CH=0x1f
。对我来说,感觉好像我错过了 Pi 方面的一些东西,但我真的不知道足够理解我在这里错过了什么。
弄清楚这一点所需的信息可能在无线电详细信息输出中,但我只是不确定在哪里查看。我尝试过改变 CRC 长度、PA 功率和写/读管道地址 - 对这些值的调整没有产生任何差异。
I've got a project which requires short-range communication without WiFi available, so I'm trying to use some nRF24L01 transceivers to make this happen.
I'm using an Arduino Uno to transmit data, and a Raspberry Pi 4 to receive that data, but so far the Pi has not received a single message. I've been through a variety of tutorials and packages/libraries at this point with absolutely no success.
I'm a seasoned software developer, but not as experienced with the Arduino side of things.
Here is the configuration:
Arduino:
nrf24 | arduino |
---|---|
Vin | 3V3 |
GND | GND |
CE | Pin 9 |
CNS | Pin 10 |
MOSI | Pin 11 |
MISO | Pin 12 |
SCK | Pin 13 |
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "printf.h"
RF24 radio(9, 10);
void setup() {
printf_begin();
Serial.begin(9600);
radio.begin();
radio.setChannel(0x76);
const uint64_t address = 0xfd7dfdfdfd;
radio.setPALevel(RF24_PA_MIN);
radio.setCRCLength(RF24_CRC_16);
radio.enableDynamicPayloads();
radio.enableAckPayload();
radio.setDataRate(RF24_1MBPS);
radio.openWritingPipe(address);
radio.stopListening();
radio.printDetails();
}
void loop() {
bool sendResult;
if (radio.available()){
Serial.println("Radio is available");
} else {
Serial.println("Radio is unavailable");
}
char text[32] = "Testeroni";
sendResult = radio.write(&text, sizeof(text));
if (sendResult) {
Serial.println("Message sent");
} else {
Serial.println("Message not sent");
}
delay(1000);
}
Pi 4:
Using the lib_nrf24
package.
SPI is enabled:
$ stat /dev/spidev0.0
File: /dev/spidev0.0
Size: 0 Blocks: 0 IO Block: 4096 character special file
Device: 5h/5d Inode: 420 Links: 1 Device type: 99,0
Access: (0660/crw-rw----) Uid: ( 0/ root) Gid: ( 999/ spi)
Access: 2022-04-02 16:16:46.749999997 -0500
Modify: 2022-04-02 16:16:46.749999997 -0500
Change: 2022-04-02 16:16:46.749999997 -0500
Birth: -
nrf24 | pi/GPIO |
---|---|
Vin | Pin 17 / 3V3 |
GND | Pin 20 / GND |
CE | Pin 22 / GPIO 25 |
CNS | Pin 24 / GPIO 8 / SPI0_CE0_N |
MOSI | Pin 19 / GPIO 10 / SPI0_MOSI |
MISO | Pin 21 / GPIO 9 / SPI0_MISO |
SCK | Pin 23 / GPIO 11 / SPI0_CLK |
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
import time
import spidev
from lib_nrf24 import NRF24
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0, 7)
radio.setRetries(15, 15)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MIN)
radio.setCRCLength(NRF24.CRC_8)
radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openReadingPipe(0, [0xfd, 0x7d, 0xfd, 0xfd, 0xfd])
radio.startListening()
radio.stopListening()
radio.printDetails()
radio.startListening()
c = 1
while True:
akpl_buf = [c,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8]
while not radio.available([0]):
time.sleep(10000/1000000.0)
recv_buffer = []
radio.read(recv_buffer, radio.getDynamicPayloadSize())
if recv_buffer:
print(f'Received: {recv_buffer}')
c += 1
if c&1 == 0:
radio.writeAckPayload(1, akpl_buf, len(akpl_buf))
time.sleep(1)
Startup
I begin by starting the Raspberry Pi Receiver:
$ sudo python library_listener.py
/home/pokeybill/lib_nrf24.py:377: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
self.GPIO.setup(self.ce_pin, self.GPIO.OUT)
STATUS = 0x03 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=1 TX_FULL=1
RX_ADDR_P0-1 =
0xffdfffffff 0xf87878f8f8
RX_ADDR_P2-5 =
0xf8
0xf9
0xf9
0xf9
TX_ADDR =
0xfdfdfdfdfd
RX_PW_P0-6 =
0x81
0x80
0x80
0x80
0x80
0xc0
EN_AA =
0x8f
EN_RXADDR =
0xc0
RF_CH =
0x9f
RF_SETUP =
0xff
CONFIG =
0x98
DYNPD/FEATURE =
0x83
0x81
Data Rate = 1MBPS
Model = nRF24L01
CRC Length = 8 bits
PA Power = PA_HIGH
Received: [128, 0, 0, 0, 0]
Then I fire up the Arduino Uno, here is the serial output:
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xfd7dfdfdfd 0x0104030201
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xfd7dfdfdfd
RX_PW_P0-6 = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x76
RF_SETUP = 0x01
CONFIG = 0x0a
DYNPD/FEATURE = 0x3f 0x06
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 8 bits
PA Power = PA_MIN
Radio is unavailable
Message not sent
Immediately I notice the warning:
RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
self.GPIO.setup(self.ce_pin, self.GPIO.OUT)
however, it seems like no matter what I do, I always get this warning. I've tried rebooting the pi multiple times and explicitly calling GPIO.cleanup()
without any joy.
Also, it seems like no matter what I use for the pipe addresses in the Raspberry Pi code, they do not match up with the receiver configuration I see.
The arduino radio.available()
call never returns true, and the radio.write
call is never acknowledged.
The pi occasionally receives random noise, but never receives a message from the arduino. The pi also seems to have an RF_CH=0x1f
when I explicitly set the channel to 0x76
in the code. To me it feels like I'm missing something with the Pi side of things, but I really don't know enough to understand what I'm missing here.
Its possible the information required to get to the bottom of this is in the radio detail output, but I'm just not sure where to look. I've tried varying CRC length, PA power, and the write/read pipe address - no adjustments to these values have made any difference.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于日志开头警告的问题,您可以按照以下步骤操作: http://raspi.tv/2013/rpi-gpio-basics-3-how-to-exit-gpio-programs-cleanly-avoid-warnings-and-protect-your-pi 并实施try:、exception: 和finally: 结构。它帮助我摆脱了这个警告。
但是,我担心我的 arduino - 树莓派与 NRF24L01 的链接存在同样的问题。事实上,我没有实现使用相同的库让它工作。我使用 printDetails 方法返回的配置与我之前配置的不对应。
Regarding to your problem with the warning at the beginning of the logs, you can follow this: http://raspi.tv/2013/rpi-gpio-basics-3-how-to-exit-gpio-programs-cleanly-avoid-warnings-and-protect-your-pi and implement the try:, exception: and finally: structures. It helped me getting rid of this warning.
However, I am concerned with the same issue with my arduino - raspberry link with NRF24L01. Indeed, I did not achieve to get it worked using the same library. The configuration that i get back with the printDetails method does not correspond to what I configured previously.