linux两个树莓派通信,Arduino与树莓派间的通信实践
最近需要在Arduino之间,以及Arduino和上位机(树莓派)之间传输数据,
原有APC220设备虽然可用,使用也方便,但成本太高,不容易批量,遂寻求其他方案。
一、方案选择
根据搜索的结果和前人经验,有如下几种可行方案:
nRF24L01+ (RF)
ESP8266(WIFI)
XBee (ZigBee)
ENC28J60(LAN)
W5100,W5500(LAN)
其中,Xbee为最优选,但成本太高。
LAN方案不方便,WIFI方案功耗高,蓝牙方案传输距离短,
故考虑RF方案,成本和效果平衡较好。
nRF24L01+价格便宜(5块左右,做工好带天线的15左右),编程简单,
且存在能同时支持树莓派、Arduino、Linux的RF24库。
Git连接为:https://github.com/TMRh20/RF24.git
便宜的(做工一般的)nRF24L01开发板:
二、接线
1、nRF24L01+引脚图
- 1:地
- 2:3.3V(切不可接5V,烧片)
- 3:CE(RF读写控制引脚)
- 4:CSN(选片引脚)
- 5:SCK(SPI时钟)
- 6:MOSI(SPI主出从入)
- 7:MISO(SPI主入从出)
- 8:IRQ(外部中断)
2、接线方法
编号
nRF24L01
Arduino Mega
Arduino UNO
Rpi(物理管脚)
1
GND
9
2
VCC
1
3
CE
7(可自定义)
7(可自定义)
15(GPIO22)
4
CSN
8(可自定义)
8(可自定义)
24(SPI0CS1)
5
SCK
52
13
23
6
MOSI
51
11
19
7
MISO
53
12
21
8
IRQ
-
-
-
接线示意图:
- Arduino UNO
- Arduino Mega
-
-
- RaspberryPi3
三、代码&运行
RF24库中自带的GettingStarted例子非常方便,其代码包含发送端和接收端两种类型,
默认为接受模式,输入T时切换为发送,输入R则切为接受模式,并有简单的超时判断。
为了易于理解,可简单修正代码,让接收端返回一自增数字。
1、 Arduino
1) RF24库安装
从https://github.com/TMRh20/RF24.git下载RF24后,
将其复制到Arduino安装目录下的libraries目录下,启动ArduinoIDE后,从例子中选择RF24->GettingStarted。
2) 代码修改
发送端不必修改,直接编译上传即可。(注意UNO和Mega的选择和串口选择)
接收端将代码中的radioNumber从默认的0修改为1。如下:
bool radioNumber = 0; (自身为2Node,发送给1Node)
->
bool radioNumber = 1;(自身为1Node,发送给2Node)
1
2
3
1
2
3
简言之,1Node为接收端,2Node为发送端。 建议:原代码中的got_time不易观察理解, 可将接收端中的got_time发送前赋值为一静态可增计数值。
3) 运行 发送端启动后,输入T,使其进入发送模式。 接受端启动即可,无需输入R。(默认为R接收模式) 如上述配置接线正常,可在Serial Monitor中看到发送方和接收方的输出,大致如下: 发送方图(静态自增变量):
2、 树莓派(RaspberryPi) 本文中使用的树莓派为 16年新发布的RPi3 B型,其管脚如下:
1) RF库安装 将RF24库复制到树莓派(或通过git直接获取)。进入RF24目录后执行如下命令,进行编译和安装(选择SPI方式)
./configure --driver=SPIDEV
sudo make install -B
1
2
1
2
2) 修改系统配置
修改/etc/modprobe.d/raspi-blacklist.conf,如果其中存在
blacklist spi-bcm2708,将其注释。
修改/etc/modules文件,在其中追加一行,开启SPI。
spidev
1
2
3
4
5
1
2
3
4
5
reboot重启树莓派后,/dev下会新增spidev0.0和spidev0.1两个设备文件。
3) 代码修改 修改RF24/example_linux/GettingStarted.cpp文件, 同上面的Arduino一样,发送端不必修改, 接收端将radioNumber从默认的0修改为1,并建议吧回送的时戳数据改为自增数字。 在当前目录下执行make后,生成GettingStarted的二进制文件。
4) 运行 使用sudo ./ GettingStarted执行,并输入0进入接收模式。 如Arduino的发送端配置、运行正常,则正常发送回应包。大致如下(自增变量版):
四、注意&体会
便宜版本的nRF24L01效果一般,很容易受到干扰。带天线的会好些,真做项目不可图便宜。 接线要准确,SPI要理解下原理。CE、CSN其实是可以任意指定的,只是要修改下RF24的初始化代码。
五、RH24例子代码简单说明
以下是RH24(TMRh20)自带的Arduino例子,简单说明一下, 树莓派上为C语言实现的版本,变量、语法略有区别,但逻辑是基本一致的。
变量定义
bool radioNumber = 1; // RF节点名称决定Flag
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
// 指定CE用GPIO7,CSN用GPIO8,需要和接线一致
// 如接线不采用7,8,代码这里需要修改。
RF24 radio(7, 8);
byte addresses[][6] = {"1Node", "2Node"}; // 两个节点名
bool role = 0; // 发送&接收模式Flag
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
初始化函数
void setup() {
Serial.begin(115200);
Serial.println(F("RF24/examples/GettingStarted"));
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
radio.begin();
radio.setPALevel(RF24_PA_LOW);
// Open a writing and reading pipe on each radio, with opposite addresses
if(radioNumber){
radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1,addresses[0]);
}else{
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1,addresses[1]);
}
// 默认为监听模式,开始监听
radio.startListening();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
执行逻辑
void loop() {
/****************** Ping Out Role ***************************/
if (role == 1) { // 发送模式
radio.stopListening(); // 发送数据前要停止监听
Serial.println(F("Now sending"));
unsigned long start_time = micros(); // 待发送的时戳
// RF24内部会自动处理payload和发送数据不等长的问题
if (!radio.write( &start_time, sizeof(unsigned long) )){ // 发送数据
Serial.println(F("failed"));
}
radio.startListening(); // 数据发送完,需要监听回应数据的到来
unsigned long started_waiting_at = micros();
boolean timeout = false;
while ( ! radio.available() ){ // 超时判断
if (micros() - started_waiting_at > 200000 ){
timeout = true;
break;
}
}
if ( timeout ){
Serial.println(F("Failed, response timed out."));
}else{ // 读数据并显示数据和间隔时间
unsigned long got_time;
radio.read( &got_time, sizeof(unsigned long) );
unsigned long end_time = micros();
// Spew it
Serial.print(F("Sent "));
Serial.print(start_time);
Serial.print(F(", Got response "));
Serial.print(got_time);
Serial.print(F(", Round-trip delay "));
Serial.print(end_time-start_time);
Serial.println(F(" microseconds"));
}
// Try again 1s later
delay(1000);
}
/****************** Pong Back Role ***************************/
if ( role == 0 ) { // 接收模式
static long count = 1; // 自增计数
unsigned long got_time = 0;
if( radio.available()){
while (radio.available()) { // 读数据
radio.read( &got_time, sizeof(unsigned long) );
}
got_time = count++; // 为便于理解,回送自增计数值
radio.stopListening();
radio.write( &got_time, sizeof(unsigned long) ); // 写回应
radio.startListening();
Serial.print(F("Sent response "));
Serial.println(got_time);
}
}
/****************** Change Roles via Serial Commands ***************************/
if ( Serial.available() ) { // 发送&接收模式通过串口决定
char c = toupper(Serial.read());
if ( c == 'T' && role == 0 ){ // 发送模式
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
role = 1;
}else
if ( c == 'R' && role == 1 ){ //接受模式
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
role = 0;
radio.startListening();
}
}
} // Loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
linux两个树莓派通信,Arduino与树莓派间的通信实践相关推荐
- java 线程间通信 handler_Handler不同线程间的通信
转http://www.iteye.com/problems/69457 Activity启动后点击一个界面按钮后会开启一个服务(暂定为padService),在padService中会启动一个线程( ...
- React组件通信-非父子组件间的通信
文章目录 React非父子组件通信 小知识点的补充 Context应用场景 Context相关API Context使用流程 React非父子组件通信 在React中, 非父子组件传递是通过一个API ...
- 【操作系统】进程间的通信——管道
进程间的通信-管道 管道 进程间的通信(IPC-Inter-Process Communication)有多种方式,管道是其中最基本的方式. 管道是半双工的,即是单向的. 管道是FIFO(先进先出)的 ...
- 思科三层交换机不同vlan互通_cisco(三层交换和动态路由,不同vlan间的通信,静态路由实现全网互通)...
之前是同vlan的通信 现在是不同vlan间的通信,不同网络之间的通信,不同网段间的通信,要用到路由器. 路由器上一个接口只能配一个网关.路由器接口少,怎么办? 在一个接口上划分出多个子接口. 单肩路 ...
- 树莓派php minicom,用DHT11实践树莓派与Arduino串口通信 | 树莓派实验室
Arduino具有丰富的外部接口,与树莓派的IO口最大的不同在于Arduino具有模拟输入接口,可以测量IO口上的模拟值.Arduino与Raspberry通过串口(Serial)通信的方案一般有两种 ...
- 树莓派和arduino的串口通信
一. 树莓派环境安装 1. 安装GPIO模块 wget https://sourceforge.net/projects/raspberry-gpio-python/files/RPi.GPIO-0. ...
- python树莓派串口通信实例_树莓派通过串口发送数据
可以通过串口登陆树莓派,也可以通过串口向其他主机发送数据.树莓派的串口接受数据科技爱好者博客已经写过,可以参考这篇文章:树莓派与arduino串口通信实践.这篇文章教大家如果通过树莓派的串口发送数据. ...
- 【物联网毕设】基于Arduino与树莓派的智能鱼缸【二】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.Arduino与树莓派进行通信 二.树莓派把数据上传到服务器 1.在树莓派上用Django搭建服务器 2.在树莓派 ...
- 新手选 Arduino 还是 树莓派?
参考来源 | 奇异思维 01 前言 Arduino 和 树莓派 都是电子.嵌入式工程师比较熟悉的两类开发板,也是很多新手都会考虑的开发板. 究竟该选择 Arduino 还是 树莓派? 02 背景 ...
- 树莓派学习笔记(五)串口通信
观看学习上官可编程陈立臣老师的树莓派视频, 在其过程中所记录的学习笔记 一.串口通信概念 1.串口通信用于多机通信 2.串口通信属于全双工通信,即双方可以同时进行交流 ...
最新文章
- RxJava使用(三)Scheduler 线程控制
- 那么多短视频特效,凭什么抖音出的这么火
- Tomcat+JSP经典配置实例
- 提高 Java 代码质量
- comp313 formal methods lec1
- codeforces National Property 2sat模板题
- python下载文件的第三方库_Python常用第三方库(转载)
- javascript-数据类型的转换
- Python 打印嵌套list中每个数据(遍历列表)
- 中文路径读取乱码,json乱码
- matlab数据栅格化,新手求卫星降水数据CMORPH_V1.0数据完整处理方法,有matlab打开的代码但是不会处理...
- SpringBoot学习---SpringSecurity与Shiro
- android 来电自动接听和自动挂断
- 《21世纪英汉汉英双向词典》《朗文当代英语辞典第五版》《牛津高阶英汉双解词典第7版》...
- JAVA 编程练习题
- Cobalt Strike(cs) 联动 msf
- JavaScript实现单击切换图片
- 2021期中考试总结
- 女性游戏市场崛起,B站能否能否抓住风口打造下一个FGO?
- 印会河《中医基础理论》笔记——阴阳学说、五行学说