目录

1.项目简介

2.工具

3.步骤

1.手机端

(1)设置ip和端口

(2)遥控界面

2.树莓派

(1)给树莓派配置公网环境

(2)树莓派进行内网穿透

(3)树莓派UDP监听

(4)树莓派视频回传

3.电脑端

(1)电脑进行内网穿透

(2)视频接收代码


1.项目简介

基于公网环境进行UDP通信,使用手机APP发出指令,控制树莓派小车移动,并将树莓派小车搭载的摄像头采集到的画面回传到电脑上显示。

2.工具

Android studio(开发手机APP)

PyCharm Community Edition (电脑端python程序接收树莓派回传的视频)

网卡 SIM7600CE—CNSE(树莓派联网)

软件:natapp,花生壳(内网穿透)

树莓派小车,摄像头

3.步骤

1.手机端

(1)设置ip和端口

Android studio开发通信APP,这是ip和端口的设置界面及代码

public class MainActivity extends AppCompatActivity {private Button btn1;private EditText ip;private EditText port;private SharedPreferences.Editor spE;private SharedPreferences sp;;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btn1 = findViewById(R.id.bt_1);ip = findViewById(R.id.et_1);port = findViewById(R.id.et_2);sp = getSharedPreferences("ip", MODE_PRIVATE);sp = getSharedPreferences("port", MODE_PRIVATE);spE = sp.edit();ip.setText(sp.getString("ip", ""));port.setText(sp.getString("port",""));btn1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (ip.getText().toString().isEmpty() || port.getText().toString().isEmpty()) {Toast.makeText(MainActivity.this, "请输入ip地址", Toast.LENGTH_SHORT).show();//弹窗return;}spE.putString("ip", ip.getText().toString());spE.putString("port", port.getText().toString());spE.apply();Intent intent = new Intent(MainActivity.this, MainActivity_udp.class);startActivity(intent);}});}
}

(2)遥控界面

这是遥控界面的布局图片和代码,点击对应的图标就会有相应的指令发出

public class MainActivity3 extends AppCompatActivityimplements View.OnTouchListener
{private SharedPreferences sp;@SuppressLint("ClickableViewAccessibility")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main3);TextView tx_w =findViewById(R.id.tx_w);TextView tx_s =findViewById(R.id.tx_s);TextView tx_a =findViewById(R.id.tx_a);TextView tx_d =findViewById(R.id.tx_d);tx_w.setOnTouchListener(MainActivity3.this);tx_s.setOnTouchListener(MainActivity3.this);tx_a.setOnTouchListener(MainActivity3.this);tx_d.setOnTouchListener(MainActivity3.this);sp = getSharedPreferences("ip",MODE_PRIVATE);sp = getSharedPreferences("port",MODE_PRIVATE);}@SuppressLint({"ClickableViewAccessibility", "NonConstantResourceId"})@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (v.getId()) {case R.id.tx_w:if (event.getAction() == MotionEvent.ACTION_DOWN) {udp_Thread ut = new udp_Thread("w", sp.getString("ip", ""),sp.getString("port",""));ut.start();}// 抬起操作else if (event.getAction() == MotionEvent.ACTION_UP) {udp_Thread ut = new udp_Thread("p" , sp.getString("ip", ""),sp.getString("port",""));ut.start();}return true;case R.id.tx_s:if (event.getAction() == MotionEvent.ACTION_DOWN) {udp_Thread ut = new udp_Thread("s" , sp.getString("ip", ""),sp.getString("port",""));ut.start();}// 抬起操作else if (event.getAction() == MotionEvent.ACTION_UP) {udp_Thread ut = new udp_Thread("p", sp.getString("ip", ""),sp.getString("port",""));ut.start();}return true;case R.id.tx_a:if (event.getAction() == MotionEvent.ACTION_DOWN) {udp_Thread ut = new udp_Thread("a" , sp.getString("ip", ""),sp.getString("port",""));ut.start();}// 抬起操作else if (event.getAction() == MotionEvent.ACTION_UP) {udp_Thread ut = new udp_Thread("c" , sp.getString("ip", ""), sp.getString("port",""));ut.start();}return true;case R.id.tx_d:if (event.getAction() == MotionEvent.ACTION_DOWN) {udp_Thread ut = new udp_Thread("d" , sp.getString("ip", ""), sp.getString("port",""));ut.start();}// 抬起操作else if (event.getAction() == MotionEvent.ACTION_UP) {udp_Thread ut = new udp_Thread("c" , sp.getString("ip", ""), sp.getString("port",""));ut.start();}return true;}return true;}
}

工具类udp_Thread(udp通信代码)

public class udp_Thread extends Thread {private String str;private String ip;private String port;public udp_Thread(String str, String ip, String port) {this.str = str;this.ip = ip;this.port = port;}@Overridepublic void run() {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}DatagramSocket socket = null;try {if (socket == null) {socket = new DatagramSocket(null);socket.setReuseAddress(true);socket.bind(new InetSocketAddress(Integer.parseInt(port)));}} catch (SocketException e) {e.printStackTrace();}//实例化socket套接字InetAddress serverAddress = null;try {serverAddress = InetAddress.getByName(ip);} catch (UnknownHostException e) {e.printStackTrace();}//设置ipbyte[] data = str.getBytes();System.out.println(str);System.out.println(ip);System.out.println(port);DatagramPacket packages = new DatagramPacket(data, data.length, serverAddress, Integer.parseInt(port));//封装报文try {assert socket != null;socket.send(packages);} catch (IOException e) {e.printStackTrace();}//发送socket.close();}}

至此,手机APP已经编写好了,设置正确的IP和端口就可以将指令发到树莓派上了

(W:电机正转 S:电机反转 A:舵机左转 D:舵机右转 P:电机停止 C:舵机回正)

2.树莓派

(1)给树莓派配置公网环境

我用的这种 网卡 (主要是支持Linux系统,比较方便)淘宝上买的,有点小贵。

也可以使用电脑上插得那种网卡,然后在树莓派上配置它的驱动

这是拨号教程

(2)树莓派进行内网穿透

1.不进行内网穿透的话,树莓派的ip(不管是局域网还是移动网络的ip都不是公网ip)只是在当前节点的局域网内的ip,不能进行公网通信。

2.穿透之后相当于给树莓派ip在公网环境中找了个爹(公网ip),手机APP的指令先发到他爹哪里(公网ip),他爹在转发给树莓派ip(节点内局域网ip)

3.具体步骤可以参考这篇文章NATAPP使用笔记—内网穿透,透内通外_信看的博客-CSDN博客。(使用普通网卡的也可以参考这个,不局限于网卡设备)

4.配置好内网穿透之后,在APP的ip和端口设置界面输入ip和端口号,就可以发送指令到树莓派了。(server.natappfree.cc是域名,转换成ip就行了)

(3)树莓派UDP监听

树莓派里面运行python程序

sockfd=socket(AF_INET,SOCK_DGRAM)
server_addr=('0.0.0.0',8003)
sockfd.bind(server_addr)def S_UDP():data,addr=sockfd.recvfrom(1024)if not data:print(waiting)id= data.decode()print('收到的信息:\nid:%s' % (id))if __name__ == "__main__":while True:S_UDP()

这样树莓派就可以接收到来自手机APP的指令了。

然后根据接收到的指令控制小车的移动

 if order == 'a':Motor.ChangeDutyCycle(MotorCenter + Motor_sensitivity)elif order == 'd':Motor.ChangeDutyCycle(MotorCenter - Motor_sensitivity)if order == 'w':Servo.ChangeDutyCycle(ServoCenter + Servo_sensitivity)elif order == 's':Servo.ChangeDutyCycle(ServoCenter - Servo_sensitivity)if order == 'c':Motor.ChangeDutyCycle(MotorCenter)if order == 'p':Servo.ChangeDutyCycle(ServoCenter)

控制小车移动的代码取决于你使用的树莓派小车的底层,我这个只做参考

(4)树莓派视频回传

代码运行需要opencv,安装教程网上比较多,不在赘述,记得换源就行了


import cv2
import socketIP=103.46.128.49
PORT=13415
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)WIDTH=320
HEIGHT=240print('now starting to send frames...')
capture=cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FRAME_WIDTH,WIDTH)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT,HEIGHT)
try:while True:success,frame=capture.read()if success and frame is not None:result,imgencode=cv2.imencode('.jpg',frame,[cv2.IMWRITE_JPEG_QUALITY,90])server.sendto(imgencode,(IP, PORT))except Exception as e:print(e)capture.release()server.close()

视频回传是回传到电脑端,所以这里的ip要设置电脑的公网ip(电脑内网穿透获取到的公网ip)

3.电脑端

(1)电脑进行内网穿透

电脑端使用花生壳配置内网穿透,下载花生壳,操作很简单,配置成功后如图所示:

如图所示,右上角访问地址4y4399t29.wicp.vip:13415就是电脑内网穿透之后获取的公网ip和端口4y4399t29.wicp.vip是域名(对应ip:103.46.128.49),13415是端口。内网主机就是自己电脑的ip和端口,端口在运行的python程序中设置,ip查看方法如下:

键盘按Windows+R输入“cmd”并确定后,命令窗口中输入“ipconfig”,回车,找到ipv4对应的ip地址,就是你电脑的ip地址。

配置成功后向103.46.128.49:13415发送的数据就会转发到你的电脑上(100.23.89.197:8888)

(2)视频接收代码

import cv2
import numpy
import socketHOST = '0.0.0.0'
PORT = 8888
buffSize = 65535server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建socket对象
server.bind((HOST, PORT))
print('now waiting for frames...')
while True:data, address = server.recvfrom(buffSize)  # 先接收的是字节长度data = numpy.array(bytearray(data))  # 格式转换imgdecode = cv2.imdecode(data, 1)  # 解码print('have received one frame')cv2.imshow('frames', imgdecode)  # 窗口显示if cv2.waitKey(1) == 27:break
server.close()
cv2.destroyAllWindows()

电脑收到树莓派发送的视频后就会显示在屏幕上。

第一次写文章,分享自己玩的树莓派4G小车,看的不明白的地方留言提问。

树莓派小车的4G遥控与视频回传(内网穿透)相关推荐

  1. 公网SSH远程树莓派【内网穿透】 1-2

    在上篇介绍中,我们为大家详细介绍了如何在局域网环境下,用电脑设备登录和操作树莓派.但在某些情况下,我们会需要远程(不在同一局域网内)登录位于本地的树莓派进行操作和设置,那这时又应该如何操作呢.现在,就 ...

  2. 树莓派远程4G遥控车教程(四)-实时监控内网穿透及集成舵机控制功能

    树莓派远程4G遥控车教程(四)- 内网穿透及监控页面集成舵机控制功能 树莓派远程4G遥控车教程(一)-准备工作 树莓派远程4G遥控车教程(二)-相机云台舵机初步调试 树莓派远程4G遥控车教程(三)-摄 ...

  3. 基于4G LTE模块的树莓派远程SSH连接方案(内网穿透)

    关键词: 树莓派  Raspberry  4G  LTE  华为  Huawei  ME909  移远  EC20  公网服务器  远程连接  远程SSH  MobaXterm  内网穿透 概述:树莓 ...

  4. 树莓派+内网穿透实现远程监控

    一.工具 1.硬件 树莓派.摄像头(我用的是树莓派官方摄像头,某宝有,十几块一个) 2.软件 (1)云服务器,我是买的腾讯云云服务器,1核2G5M.SSD50G的配置,33r包年,某宝上买的.可能是因 ...

  5. 树莓派mjpg-streamer+内网穿透

    树莓派mjpg-streamer+内网穿透 一.背景 二.你需要的材料 三.视频传送 四.内网穿透 五.应用及效果 一.背景 我相信很多小伙伴和我一样,对物联网很感兴趣,就算你的专业.工作不是物联网方 ...

  6. 树莓派操作及搭建frp实现内网穿透

    买了个树莓派4b,折腾玩玩 一.安装 安装方法都一样,下载镜像,烧录到内存卡,将内存卡插入树莓派,启动即可 我试过的有ubuntu,centos8,树莓派官方系统(应该是Debian的),还有个复古游 ...

  7. 基于树莓派的远程实时监控(内网穿透)

    /*本文系湛江市第十七中学星火创客团队及岭南师范学院物联网俱乐部原创部分参赛项目,转载请保留声明 */ 一.项目背景与目标: 此项目基于一个师弟的留言:如何实现在学校的校园网(办公网)内实现内网穿透. ...

  8. 树莓派摄像头使用 motion + frp内网穿透 实时视频显示

    本文主要介绍motion的使用,frp内网穿透步骤. 一.准备材料 二.motion的下载安装 三.motion的使用 四.frp的下载安装 五.frp内网穿透服务器配置步骤 六.frp内网穿透客户端 ...

  9. SSH远程连接访问树莓派【无公网IP做内网穿透】

     系列文章 树莓派搭建网站,并免费内网穿透发布上线到公网 树莓派搭建WordPress网站,并内网穿透发布上线无需公网IP服务器 为树莓派上的WordPress网站配置自己的域名,并内网穿透发布上线公 ...

最新文章

  1. easyui datalist 动态绑定数据_一文看懂动态链接
  2. 转: 网卡名字eth0,eth1的修改方法
  3. Nginx集群session管理的两种方式
  4. android系统三防机,这才是真正给老人设计的智能手机:三防+安卓系统+超大音量,AGM H2...
  5. 程序人家:你的老板逼你上微服务了吗??
  6. 面向对象:类的定义和使用
  7. 企业需要成熟的云安全进程
  8. 关于行内元素的margin padding一些说明;background-color的范围
  9. p语言是python吗-Python 这语言真是混乱和原始
  10. 【一文搞懂】【WIN32】(_beginthread、_beginthreadex)和CreateThread
  11. C#获取电脑硬盘序列号
  12. php把buffer转化为图片_PHP简单实现图片格式转换(jpg转png,gif转png等)
  13. linux安装android x86_64,在VirtualBox上安装Android-X86
  14. Edge/IE浏览器主页被篡改为360导航的快捷解决方法
  15. Scrum立会报告+燃尽图(Final阶段第七次)
  16. 军事武器开发使用c语言吗,【单选题】( )是军事革命的前提条件和物质基础,是军事革命的“硬件”。 A. 先进的技术和武器系统 B. 科学的体制编制 C. 创新的军事理论 D. 富有才干的领导人...
  17. 【干货】PS通道精讲
  18. Elasticsearch Compound queries 学习总结
  19. Henry前端笔记之 UI组件库中table与slot相关理解
  20. IDEA版最新SMM整合,根据手机号实现登录/注册/修改密码

热门文章

  1. Android全面屏显示不全下方有黑色解决方案
  2. Quagga.js库
  3. druid连接泄漏GetConnectionTimeoutException: wait millis 60000, active 5, maxActive 5, creating 0
  4. json 在 Flutter(Dart)中的使用
  5. 2017届中兴校招综合面试之软件测试工程师面试经历
  6. JS 判断数组中是否包含某个值
  7. 推荐7个超棒的监控工具
  8. 抖音释放实名,身份证方法
  9. 埃森哲最新研究发现,随着企业加大云迁移的投入,云上转型是当务之急 | 美通社头条...
  10. # java学习笔记 2020 2/8(十二)慕课网 构造方法