树莓派小车的4G遥控和视频回传内网穿透
目录
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;;
-
-
-
protected 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() {
-
-
-
public 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 AppCompatActivity
-
implements View.OnTouchListener
-
{
-
private SharedPreferences sp;
-
@SuppressLint("ClickableViewAccessibility")
-
@Override
-
protected 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"})
-
@Override
-
public 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;
-
}
-
-
-
public 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();
-
}//设置ip
-
-
byte[] 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)
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 socket
-
-
IP=103.46.128.49
-
PORT=13415
-
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
-
-
WIDTH=320
-
HEIGHT=240
-
-
print('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 socket
-
-
HOST = '0.0.0.0'
-
PORT = 8888
-
buffSize = 65535
-
-
server = 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小车,看的不明白的地方留言提问。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgbeief
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01