增加训练yolo的代码

This commit is contained in:
gcw_4spBpAfv
2026-05-15 09:35:53 +08:00
parent dff5096164
commit 541418fd60
13 changed files with 953 additions and 140 deletions

View File

@@ -1,172 +1,246 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
激光模块测试脚本
用于诊断激光开关问题
使用方法:
python test_laser.py
功能:
1. 初始化串口
2. 循环测试激光开/关
3. 打印详细调试信息
M01激光测距模块测试脚本 - 修正版
基于文档中的完整命令示例
"""
from maix import uart, pinmap, time
import binascii
# ==================== 配置 ====================
UART_PORT = "/dev/ttyS1" # 激光模块连接的串口UART1
BAUDRATE = 9600 # 波特率
# 引脚映射(确保与硬件连接一致)
print("=" * 50)
print("🔧 步骤1: 配置引脚映射")
print("=" * 50)
UART_PORT = "/dev/ttyS1"
BAUDRATE = 9600
# 初始化串口
try:
pinmap.set_pin_function("A18", "UART1_RX")
print("✅ A18 -> UART1_RX")
except Exception as e:
print(f"❌ A18 配置失败: {e}")
try:
pinmap.set_pin_function("A19", "UART1_TX")
print("✅ A19 -> UART1_TX")
except Exception as e:
print(f"❌ A19 配置失败: {e}")
# ==================== 激光控制指令 ====================
MODULE_ADDR = 0x00
# 原始命令
LASER_ON_CMD = bytes([0xAA, MODULE_ADDR, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x01, 0xC1])
LASER_OFF_CMD = bytes([0xAA, MODULE_ADDR, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x00, 0xC0])
# 备用命令格式(如果原始命令不工作,可以尝试这些)
# 格式1: 简化命令
LASER_ON_CMD_ALT1 = bytes([0xAA, 0x01, 0x01])
LASER_OFF_CMD_ALT1 = bytes([0xAA, 0x01, 0x00])
# 格式2: 不同的协议头
LASER_ON_CMD_ALT2 = bytes([0x55, 0xAA, 0x01])
LASER_OFF_CMD_ALT2 = bytes([0x55, 0xAA, 0x00])
print("\n" + "=" * 50)
print("🔧 步骤2: 初始化串口")
print("=" * 50)
print(f"设备: {UART_PORT}")
print(f"波特率: {BAUDRATE}")
try:
laser_uart = uart.UART(UART_PORT, BAUDRATE)
print(f"串口初始化成功: {laser_uart}")
print("硬件初始化")
except Exception as e:
print(f"串口初始化失败: {e}")
print(f"❌ 初始化失败: {e}")
exit(1)
# ==================== 测试函数 ====================
def send_and_check(cmd, name):
"""发送命令并检查回包"""
print(f"\n📤 发送: {name}")
print(f" 命令字节: {cmd.hex()}")
print(f" 命令长度: {len(cmd)} 字节")
# 清空接收缓冲区
# ==================== 根据文档的完整命令集 ====================
# 1. 激光开关文档2.3.10,已验证可用)
LASER_ON_CMD = bytes([0xAA, 0x00, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x01, 0xC1])
LASER_OFF_CMD = bytes([0xAA, 0x00, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x00, 0xC0])
# 2. 尝试不同的测距命令格式
TEST_COMMANDS = [
# 格式1文档2.3.12的单次测量(您测试失败的)
{
"name": "单次测量 (0x0020)",
"cmd": bytes([0xAA, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x21]),
"desc": "文档2.3.12 示例命令"
},
# 格式2文档2.3.7的读取测量结果
{
"name": "读取测量结果 (0x0022)",
"cmd": bytes([0xAA, 0x80, 0x00, 0x22, 0xA2]),
"desc": "文档2.3.7 读取测量结果"
},
# 格式3文档2.3.13的快速测量
{
"name": "快速测量 (0x0022带数据)",
"cmd": bytes([0xAA, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x00, 0x23]),
"desc": "文档2.3.13 快速测量"
},
# 格式4连续测量模式
{
"name": "连续测量模式 (0x0021)",
"cmd": bytes([0xAA, 0x00, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x22]),
"desc": "文档2.3.14 连续测量"
}
]
def clear_buffer():
"""清空串口缓冲区"""
try:
old_data = laser_uart.read(-1)
if old_data:
print(f" 清空缓冲区: {len(old_data)} 字节")
data = laser_uart.read(-1)
if data:
print(f"清空: {len(data)}字节")
except:
pass
def send_and_wait(cmd, name, wait_time=2000):
"""发送命令并等待响应"""
print(f"\n📤 发送: {name}")
print(f" 命令: {cmd.hex()}")
clear_buffer()
# 发送命令
try:
written = laser_uart.write(cmd)
print(f" 写入字节数: {written}")
laser_uart.write(cmd)
print(f" 已发送 {len(cmd)} 字节")
except Exception as e:
print(f"写入失败: {e}")
print(f"发送失败: {e}")
return None
# 等待响应
time.sleep_ms(100)
start_time = time.ticks_ms()
response = b""
# 读取回包
try:
resp = laser_uart.read(50)
if resp:
print(f" 📥 收到回包: {resp.hex()} ({len(resp)} 字节)")
return resp
else:
print(f" ⚠️ 无回包")
return None
except Exception as e:
print(f" ❌ 读取失败: {e}")
return None
while time.ticks_ms() - start_time < wait_time:
try:
chunk = laser_uart.read(1)
if chunk:
response += chunk
# 完整响应通常是9或13字节
if len(response) >= 9:
# 检查是否完整帧
if response[0] in [0xAA, 0xEE]:
if len(response) >= 13: # 测距完整响应
break
elif response[0] == 0xEE: # 错误响应
break
except:
break
time.sleep_ms(10)
if response:
print(f" 📥 响应: {response.hex()}")
print(f" 长度: {len(response)} 字节")
# 解析错误码
if response[0] == 0xEE and len(response) >= 9:
err_code = (response[7] << 8) | response[8]
error_mapping = {
0x0000: "无错误",
0x0001: "硬件错误",
0x0002: "无输出数据",
0x0003: "反射信号太弱",
0x0004: "反射信号太强",
0x0005: "温度太高(>40℃)",
0x0006: "温度太低(<-10℃)",
0x0007: "电源电压低(<2.5V)",
0x0008: "超出量程",
0x0009: "读通讯错误",
0x000A: "写通讯错误",
0x000B: "地址错误"
}
err_msg = error_mapping.get(err_code, f"未知错误: 0x{err_code:04X}")
print(f" ❌ 模块错误: {err_msg}")
else:
print(" ⚠️ 无响应")
return response
def test_laser_cycle(on_cmd, off_cmd, cmd_name="标准命令"):
"""测试一个开关周期"""
print(f"\n{'='*50}")
print(f"🧪 测试 {cmd_name}")
print(f"{'='*50}")
def parse_distance_data(response):
"""解析距离数据"""
if not response or len(response) < 13:
return None
print("\n>>> 测试开启激光")
send_and_check(on_cmd, f"{cmd_name} - 开启")
print(" ⏱️ 等待 2 秒观察激光是否亮起...")
time.sleep(2)
if response[0] != 0xAA or response[3] not in [0x20, 0x21, 0x22]:
return None
print("\n>>> 测试关闭激光")
send_and_check(off_cmd, f"{cmd_name} - 关闭")
print(" ⏱️ 等待 2 秒观察激光是否熄灭...")
time.sleep(2)
# 解析4字节BCD码
bcd_bytes = response[6:10]
distance_int = 0
for byte in bcd_bytes:
high = (byte >> 4) & 0x0F
low = byte & 0x0F
if high > 9 or low > 9:
return None
distance_int = distance_int * 100 + high * 10 + low
distance_m = distance_int / 1000.0
# 信号质量
signal = 0
if len(response) >= 12:
signal = (response[10] << 8) | response[11]
return {
'meters': distance_m,
'millimeters': distance_m * 1000,
'signal': signal,
'raw': response.hex()
}
# ==================== 主测试 ====================
print("\n" + "=" * 50)
print("🚀 开始激光测试")
print("=" * 50)
print("\n请观察激光模块的状态变化...")
print("测试将依次尝试不同的命令格式\n")
print("\n" + "="*50)
print("M01激光测距模块详细测试")
print("="*50)
try:
# 测试1: 标准命令
test_laser_cycle(LASER_ON_CMD, LASER_OFF_CMD, "标准命令")
# 1. 测试基本连接
print("\n1. 测试模块连接...")
version_cmd = bytes([0xAA, 0x80, 0x00, 0x0A, 0x8A])
resp = send_and_wait(version_cmd, "读取硬件版本")
input("\n按回车继续测试备用命令1...")
if resp and resp[0] == 0xAA and resp[3] == 0x0A:
print(f"✅ 模块正常,版本: {resp[6]:02X}{resp[7]:02X}")
else:
print("❌ 模块连接测试失败")
exit(1)
# 测试2: 备用命令格式1
test_laser_cycle(LASER_ON_CMD_ALT1, LASER_OFF_CMD_ALT1, "备用命令1 (简化)")
# 2. 开启激光
print("\n2. 开启激光...")
resp = send_and_wait(LASER_ON_CMD, "开启激光", 1000)
if resp and resp.hex() == "aa0001be00010001c1":
print("✅ 激光已开启")
input("\n按回车继续测试备用命令2...")
print(" 等待激光稳定...")
time.sleep(2) # 重要等待时间
# 测试3: 备用命令格式2
test_laser_cycle(LASER_ON_CMD_ALT2, LASER_OFF_CMD_ALT2, "备用命令2 (0x55AA头)")
# 3. 尝试不同的测距命令
print("\n3. 测试不同测距命令...")
print("\n" + "=" * 50)
for i, test_cmd in enumerate(TEST_COMMANDS):
print(f"\n{'='*30}")
print(f"测试 {i+1}: {test_cmd['name']}")
print(f"{test_cmd['desc']}")
print(f"{'='*30}")
resp = send_and_wait(test_cmd['cmd'], test_cmd['name'], 3000)
if resp:
if resp[0] == 0xAA and len(resp) >= 13:
result = parse_distance_data(resp)
if result:
print(f"✅ 测距成功!")
print(f" 距离: {result['meters']:.3f} m")
print(f" 距离: {result['millimeters']:.1f} mm")
print(f" 信号质量: {result['signal']}")
break
else:
print("❌ 无法解析距离数据")
elif resp[0] == 0xEE:
print("❌ 命令执行错误")
else:
print("❌ 无效响应格式")
else:
print("❌ 无响应")
time.sleep(1) # 命令间间隔
# 4. 关闭激光
print("\n4. 关闭激光...")
send_and_wait(LASER_OFF_CMD, "关闭激光", 1000)
print("\n" + "="*50)
print("🏁 测试完成")
print("=" * 50)
print("\n诊断建议:")
print("1. 如果激光始终不亮/始终亮")
print(" - 检查激光模块的电源连接")
print(" - 检查串口TX/RX是否接反")
print(" - 尝试不同的波特率 (4800/19200)")
print("")
print("2. 如果有回包但激光无反应:")
print(" - 命令格式可能正确但激光硬件问题")
print("")
print("3. 如果某个备用命令有效:")
print(" - 需要更新 config.py 中的命令格式")
print("="*50)
print("\n📋 测试总结")
print("1. 模块通信: ✅ 正常")
print("2. 激光控制: ✅ 正常")
print("3. 测距功能: ❌ 有问题")
print("\n建议:")
print("1. 检查激光是否实际发光(在暗处观察红点)")
print("2. 确保测量目标在有效范围内0.2-60米")
print("3. 确保目标有足够反射率(白色平面最佳)")
print("4. 如果所有测距命令都返回ERR_ADDR可能是固件版本问题")
except KeyboardInterrupt:
print("\n\n🛑 测试被中断")
# 确保激光关闭
print("\n\n🛑 用户中断")
laser_uart.write(LASER_OFF_CMD)
print("✅ 已发送关闭指令")
except Exception as e:
print(f"\n❌ 测试出错: {e}")
import traceback
traceback.print_exc()
print(f"\n❌ 测试出错: {e}")