嵌入式工程|Arduino通过nrf24l01与树莓派通信,并通过蓝牙转发给安卓手机

本科毕设通信模块,首次嵌入式工程尝试,集CSDN众多大家之成果,期间依旧遇坑无数,在此Mark,以便后续参考。
通信过程大致描述如下:树莓派通过2.4GHz廉价模块nrf24l01,发送无线数据给同样连接nrf24l01模块的Arduino模块,Arduino通过串口蓝牙将数据转发给安卓手机。
本文将分别记录以上通信实现过程,着重描述遇到的问题与解决方法。期间参考前辈教程攻略如下:
NF库:https://github.com/TMRh20/RF24.git
树莓派与Arduino通信 http://shumeipai.nxez.com/2017/03/20/communication-between-arduino-and-raspberry-pi.html
安卓蓝牙编程 https://blog.csdn.net/qq_30379689/article/details/52621769
【嵌入式工程|Arduino通过nrf24l01与树莓派通信,并通过蓝牙转发给安卓手机】树莓派波特率的修改 https://www.cnblogs.com/mengfanrong/p/4272038.html
一、模块选取 以下雷区,请避开:
1、 便宜的Arduino常常存在各种各样的问题,不要图便宜,请使用正版Arduino
2、 便宜的nRF24L01模块(价格在10元附近),传输距离有时只有数米甚至更短。
如果想要完成类似本项目的百米无线通信,需要选用带有PA+LNA的模块,其理论通信距离甚至可以达到千米,其价格在单只20元左右。
做项目请不要图便宜。

二、树莓派/Arduino UNO/蓝牙2.0模块/nRF24L01相互连接

序号 nRF24L01 树莓派 Arduino UNO 蓝牙2.0
1 VCC
1 3.3V(接5v 烧坏)
2 GND 9 GND
3 CE 15 7(按照程序自定义)
4 CSN 24 8(按照程序自定义)
5 SCK 23 13
6 MOSI 19 11
7 MISO 21 12
8 TX RX
9 RX TX
10 5V +5V
11 GND GND

nRF24L01的管脚参考下图,参考模块上印的格子,参照点是角落着重标出的接地线方格。
嵌入式工程|Arduino通过nrf24l01与树莓派通信,并通过蓝牙转发给安卓手机
文章图片

树莓派管脚图如下(图片来自网络)
嵌入式工程|Arduino通过nrf24l01与树莓派通信,并通过蓝牙转发给安卓手机
文章图片

三、代码与实现 1.树莓派端发送代码 gettingstarted.cpp
此部分参考直接引用http://shumeipai.nxez.com/2017/03/20/communication-between-arduino-and-raspberry-pi.html
1)RF库安装
将https://github.com/TMRh20/RF24.git上的RF24库复制到树莓派(或通过git直接获取)。进入RF24目录后执行如下命令,进行编译和安装(选择SPI方式)
1
2
./configure --driver=SPIDEV
sudo make install -B
2) 修改系统配置
1
2
3
4
5
修改/etc/modprobe.d/raspi-blacklist.conf,如果其中存在
blacklist spi-bcm2708,将其注释。

修改/etc/modules文件,在其中追加一行,开启SPI。
spidev
reboot重启树莓派后,/dev下会新增spidev0.0和spidev0.1两个设备文件。
3)代码修改
修改RF24/example_linux/GettingStarted.cpp文件,
由于设备的一些原因,树莓派不能及时收到ack信号,但是数据均可正确发送。在要求不严格的情况下,不妨先删掉检测ack的相关代码,待发送的数据来自程序外I/O输入。更改后输入模式下的代码如下所示:
if (role == role_ping_out){ // First, stop listening so we can talk. radio.stopListening(); printf("Now sending...\n"); unsigned long time = millis(); // 将程序外输入的数据发送出去 string tmp_input; getline(cin, tmp_input); const char* input_str = tmp_input.c_str(); count++; bool ok = radio.write( input_str, strlen(input_str) ); printf("Have sent: %s\n", input_str); sleep(1); }

(修改后的代码可以参考https://github.com/iAlexKai/Raspberry2Arduino_send/blob/master/examples_linux/gettingstarted.cpp)
在当前目录下执行make后,生成GettingStarted的二进制文件。
4)运行
使用sudo ./ GettingStarted执行,并输入1进入发送模式。
2.Arduino接收端代码
1. 将从https://github.com/TMRh20/RF24.git下载来的代码,直接复制到Arduino安装目录的libraries目录下,启动ArduinoIDE,从示例中找到RF24 -> gettingStarted
2. 将代码中radioNumber 0 改为 1 :
bool radioNumber = 0; -> bool radioNumber = 1;

注意,Arduino和树莓派的radioNumber必须一个为0,一个为1,表示建立通道的两个端
3. 由于我们将蓝牙模块接入了Arduino的输入输出端,蓝牙通信属于串口通信。代码中的Serial.println()发出的数据均可通过蓝牙发送。因此设备连接上此蓝牙模块后即可收到Arduino发出的数据。
(接收端代码可参考https://github.com/iAlexKai/Raspberry2Arduino_recv)
3.实现细节
1. 蓝牙模块需要接入Arduino的5v管脚,在程序从电脑上传到Arduino板子上时需要拔掉此5v接线,否则由于并联的关系会导致程序无法上传。
2.两个模块进行数据收发时,要保证波特率一致。由于最终接收终端是安卓手机,安卓端并不提供更改波特率的接口,因此需要修改蓝牙模块以及树莓派的波特率为9600Baud,从而适应蓝牙模块。
Arduino可以通过直接修改代码中串口初始化参数即可更改波特率
Serial.begin(9600);

树莓派的波特率更改方式参考:https://www.cnblogs.com/mengfanrong/p/4272038.html
需要改动/boot/cmdline.txt文件删除原始的console=ttyAMA0,115200 kgdboc=ttyAMA0,115200
改动 /etc/inittab注释掉最后一行-L ttyAMA0 115200 vt100
通过apt-get安装minicom,root账户后输入minicom -s,找到波特率修改项,更改为9600Baud

    推荐阅读