案例:蓝牙控制目标检测模型。
说明:本案例使用HC-06蓝牙模块,通过jetson nano的UART_2_TX和UART_2_RX进行串口通信,串口号为/dev/ttyTHS1;
实现功能:在手机端控制蓝牙终端工具与HC-06配对并连接,通过HC-06向jetson nano发送相应的消息,并通过串口发送到jetson nano,jeson nano中通过编写好的程序接收请求并响应,实现控制目标检测模型的开启和关闭功能;
这是jetson nano的GPIO口相关信息以及位置:
具体实现过程:
- 在主目录下创建一个文件夹bluetooth_launch_config,用于存放控制逻辑代码、运行和关闭模型的代码;
- 编写控制逻辑代码,我用python实现的,用来接收和处理蓝牙发送的指令,并进行控制和反馈;
- 编写快速启动的shell脚本:包含快速启动检测模型的脚本和关闭检测模型的脚本;
- 使用secureCrt等远程终端,控制jetson nano(可选)
整个项目的目录结构:
/home/zhw/
├── bluetooth_launch_config/
│ ├── bluetooth_control.py
│ ├── start_bluetooth_control.sh
│ ├── start_terminal_and_run.sh
├── deepLearning/
│ ├── yolov5-5.0/
│ │ ├── detect.py
│ │ ├── start_yolov5.sh
│ │ ├── stop_yolov5.sh
控制逻辑实现代码(python),bluetoth_control.py:
# -*- coding: utf-8 -*-
import serial
import os
import subprocess
import signal
import time
# 配置串口通信
ser = serial.Serial('/dev/ttyTHS1', baudrate=9600, timeout=1)
# 启动检测的命令
start_command = "on"
stop_command = "off"
# 定义检测进程变量
detection_process = None
def start_detection():
global detection_process
if detection_process is None:
print("检测模型开启中...")
detection_process = subprocess.Popen(['sh', '/home/zhw/bluetooth_launch_config/start_yolov5.sh'], preexec_fn=os.setsid)
print(f"YOLOv5 detection started with PID(进程号): {detection_process.pid}")
return "Detect Starting..."
else:
print("检测模型已经再运行了.")
return "Already Start..."
def stop_detection():
global detection_process
if detection_process:
print("停止检测...")
try:
os.killpg(os.getpgid(detection_process.pid), signal.SIGTERM)
detection_process = None
print("检测程序已关闭...")
return "Stop Running..."
except Exception as e:
print("Error while stopping detection:", e)
return "Error in STOP..."
else:
print("没有检测模型正在运行...。◕‿◕。")
return "No Running..."
def main():
print('----------------------------')
print("。◕‿◕。服务已启动。◕‿◕。(发送on开启检测,off停止检测)")
detection_running = False
while True:
if ser.in_waiting > 0:
command = ser.readline().decode('utf-8').strip()
print("接收到客户端请求: {}".format(command)) # 调试输出
if command == start_command:
if not detection_running:
response = start_detection()
detection_running = True
else:
print('----------------------------')
print("。◕‿◕。当前检测模型已开启,请不要重复操作。◕‿◕。")
time.sleep(1)
response = "Already Running..."
elif command == stop_command:
if detection_running:
response = stop_detection()
detection_running = False
time.sleep(1)
print('----------------------------')
print("。◕‿◕。继续接收检测服务请求。◕‿◕。")
else:
print("。◕‿◕。当前没有检测模型开启...。◕‿◕。")
time.sleep(1)
print('----------------------------')
print("。◕‿◕。继续接收检测服务请求。◕‿◕。")
response = "No Running."
else:
print("请检查你输入的指令...")
time.sleep(1)
print('----------------------------')
print("。◕‿◕。发送on开启检测,off停止检测。◕‿◕。")
response = "Check your commond..."
ser.write(response.encode('utf-8')) # 将响应发送回客户端
# print("{}".format(response)) # 调试输出
if __name__ == "__main__":
main()
编写快速启动检测模型的脚本,start_yolov5.sh:
#!/bin/bash
export PATH=/home/zhw/miniforge3/bin:$PATH
conda run -n pytorch python /home/zhw/deepLearning/yolov5-5.0/detect.py --source 2
编写关闭检测模型的脚本,stop_yolov5.sh:
#!/bin/bash
# 查找并杀掉 detect.py 进程
ps -ef | grep 'detect.py' | grep -v 'grep' | awk '{print $2}' | xargs -r kill
解释:这里关闭检测模型使用的方法是杀掉对应程序运行进程的方式,ps -ef | grep 'detect.py' | grep -v 'grep' 查询正在运的检测脚本detect.py的信息,awk '{print $2}'找到第列的值,这个是运行的端口号, xargs -r kill杀掉对应端口;
实际上,到这里已经可以在终端中运行bluetoth_control.py,处理手机控制指令了:
cd bluetooth_launch_config
python blue_control.py
但是呢?有一个不舒服的点是:jetson nano还需要连接键盘和鼠标,所以我使用secureCRT远程连接jetson nano,用于启动jetson nano上的控制程序;
但是,在secureCRT上远程直接运行bluetoth_control.py,遇到两个问题:
1.不会在jetson nano的显示器上显示交互的日志信息;
2.远程终端无法直接控制调用深度相机等硬件;
所以,我又写了两个shell脚本,用于启动jetson nano上的终端,并在这个终端上显示出交互信息:start_terminal_and_run.sh:
#!/bin/bash
# 设置串口设备权限
sudo chmod 666 /dev/ttyTHS1
# 设置DISPLAY变量
export DISPLAY=:0
# 启动gnome-terminal并运行Python脚本
gnome-terminal -- bash -c 'cd /home/zhw/bluetooth_launch_config && /usr/bin/python3 /home/zhw/bluetooth_launch_config/bluetooth_control.py; exec bash'
这个脚本用于快速设置串口权限、添加环境变量和启动Ubuntu内部自带的终端Terminal,并cd到目标目录下;
给脚本添加执行权限:
chmod +x /home/zhw/bluetooth_launch_config/start_terminal_and_run.sh
执行start_terminal_and_run.sh即可远程开启服务:
sh start_terminal_and_run.sh
最终效果演示:
以下部分使用Ubuntu内部自带的终端gnome-terminal暂时还未实现,不过,可以在Ubuntu中下载xterm终端,使用xterm可以实现服务的自启动,但是,xterm有些丑,且会出现中文乱码现象,遂还是倾向于使用内部自带终端。
以下是未完成的实现步骤:
创建 systemd 服务文件,这个设置可以实现开机自动启动运行脚本,以及杀掉后再次运行,确保控制脚本始终运行:
/etc/systemd/system/
目录下,创建一个 bluetooth_control_terminal.service
文件 :
终端使用如下指令进入编辑:
sudo nano /etc/systemd/system/bluetooth_control_terminal.service
复制粘贴如下代码:
[Unit]
Description=Bluetooth Control Terminal Service
After=network.target
[Service]
Type=simple
ExecStart=/home/zhw/bluetooth_launch_config/start_terminal_and_run.sh
Restart=on-failure
RestartSec=5s
Environment=DISPLAY=:0
[Install]
WantedBy=multi-user.target
可以使用ctrl + shift + v粘贴,使用crtl + o完成输入,enter确认名称并保存,ctrl + x退出;
启用和启动服务:
重新加载 systemd
配置,启用并启动服务:
sudo systemctl daemon-reload
sudo systemctl enable bluetooth_control_terminal.service
sudo systemctl start bluetooth_control_terminal.service
几种调试方法:
这个用来检查我们配置的自启动服务是否正常运行
sudo systemctl status bluetooth_control_terminal.service