【AIMB-2210】AI编写小车控制界面
【前言】心心验验的智能小车底盘终于到货了
!(https://www.eefocus.com/forum/data/attachment/forum/202510/27/225747wnw92ww3p55wgz6a.png)
今天把蓝牙远程控制的简易界面写了出来,并进行验证。
【实验器材】
1、【AIMB-2210】电脑主机
2、智小能套件:
!(https://www.eefocus.com/forum/data/attachment/forum/202510/27/230009sfw0o2wsas44sas2.png)
3、蓝牙透传模块。
【实现原理】
1、使用两个可以透传的蓝牙模块,将PC端的远程控制命令通过蓝牙模块发送给小车。
2、智能小车将协议接收后传给智能小车主控,实现转向、前进等功能。
【代码编写】
在AIMB-2210上安装vscode+AI代码生成控制界面。
!(https://www.eefocus.com/forum/data/attachment/forum/202510/27/230337gpth9m3tijtsttuk.png)
在AIMB强大的支持下,快速生了python代码。界面如下:
!(https://www.eefocus.com/forum/data/attachment/forum/202510/27/230424mo5owodt5v5bx5zb.png)
【使用方法】
当我向三个速度数据框写入速度数据后,蓝牙小车就实时进行前进以及转弯了。
【项目推荐计划】
1、实时获取小车的信息,同时将小车的定位也通过电脑的定位模块进行定位,为下一步,远程自动控制做准备。
附AI生成的源码:
```
import serial
import time
import struct
import tkinter as tk
from tkinter import ttk, messagebox
import serial.tools.list_ports
def calculate_checksum(data):
"""
计算校验和:前面数据累加和的低8位
"""
return sum(data) & 0xFF
def send_x_protocol_frame(ser, frame_code, data):
"""
发送X-Protocol帧
Args:
ser: 串口对象
frame_code: 帧码
data: 数据字节串
"""
# 构造帧(不包括校验和)
frame = bytearray()
frame.append(0xAA)# 帧头1
frame.append(0x55)# 帧头2
frame.append(5 + len(data))# 帧长
frame.append(frame_code)# 帧码
frame.extend(data)# 数据
# 计算校验和(从第0位开始计算整个帧)
checksum = calculate_checksum(frame)
frame.append(checksum)# 校验和
# 发送帧
ser.write(frame)
print(f"发送帧: {' '.join(f'{b:02X}' for b in frame)}")
return len(frame)
def send_values(ser, frame_code, value1, value2, value3):
"""
发送三个16位整数
Args:
ser: 串口对象
frame_code: 帧码
value1, value2, value3: 三个16位整数
"""
# 构造6字节的有效数据
data = bytearray()
data.extend(struct.pack('>h', value1))# 第一个16位整数
data.extend(struct.pack('>h', value2))# 第二个16位整数
data.extend(struct.pack('>h', value3))# 第三个16位整数
# 发送帧
bytes_sent = send_x_protocol_frame(ser, frame_code, data)
print(f"发送数据: {value1}, {value2}, {value3}")
return bytes_sent
class XProtocolGUI:
def __init__(self, root):
self.root = root
self.root.title("X-Protocol 串口发送工具")
self.root.geometry("400x300")
self.ser = None
self.create_widgets()
self.refresh_ports()
def create_widgets(self):
# 主框架
main_frame = ttk.Frame(self.root, padding="10")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 串口选择
ttk.Label(main_frame, text="串口:").grid(row=0, column=0, sticky=tk.W, pady=5)
self.port_var = tk.StringVar()
self.port_combo = ttk.Combobox(main_frame, textvariable=self.port_var, width=15)
self.port_combo.grid(row=0, column=1, sticky=(tk.W, tk.E), pady=5)
# 刷新按钮
refresh_btn = ttk.Button(main_frame, text="刷新", command=self.refresh_ports)
refresh_btn.grid(row=0, column=2, padx=(10,0), pady=5)
# 连接按钮
self.connect_btn = ttk.Button(main_frame, text="连接", command=self.toggle_connection)
self.connect_btn.grid(row=0, column=3, padx=(10,0), pady=5)
# 分隔线
separator = ttk.Separator(main_frame, orient='horizontal')
separator.grid(row=1, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=10)
# 数据输入
ttk.Label(main_frame, text="数据1:").grid(row=2, column=0, sticky=tk.W, pady=5)
self.value1_var = tk.StringVar(value="100")
ttk.Entry(main_frame, textvariable=self.value1_var, width=10).grid(row=2, column=1, sticky=tk.W, pady=5)
ttk.Label(main_frame, text="数据2:").grid(row=3, column=0, sticky=tk.W, pady=5)
self.value2_var = tk.StringVar(value="0")
ttk.Entry(main_frame, textvariable=self.value2_var, width=10).grid(row=3, column=1, sticky=tk.W, pady=5)
ttk.Label(main_frame, text="数据3:").grid(row=4, column=0, sticky=tk.W, pady=5)
self.value3_var = tk.StringVar(value="0")
ttk.Entry(main_frame, textvariable=self.value3_var, width=10).grid(row=4, column=1, sticky=tk.W, pady=5)
# 帧码输入
ttk.Label(main_frame, text="帧码:").grid(row=5, column=0, sticky=tk.W, pady=5)
self.frame_code_var = tk.StringVar(value="50")
ttk.Entry(main_frame, textvariable=self.frame_code_var, width=10).grid(row=5, column=1, sticky=tk.W, pady=5)
# 发送按钮
self.send_btn = ttk.Button(main_frame, text="发送数据", command=self.send_data, state=tk.DISABLED)
self.send_btn.grid(row=6, column=0, columnspan=2, pady=20)
# 状态栏
self.status_var = tk.StringVar(value="请选择串口并连接")
self.status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN)
self.status_bar.grid(row=7, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=(10,0))
# 配置网格权重
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
main_frame.columnconfigure(1, weight=1)
def refresh_ports(self):
"""刷新可用串口列表"""
ports =
self.port_combo['values'] = ports
if ports:
self.port_combo.set(ports)
def toggle_connection(self):
"""切换串口连接状态"""
if self.ser is None:
self.connect_serial()
else:
self.disconnect_serial()
def connect_serial(self):
"""连接串口"""
try:
port = self.port_var.get()
if not port:
messagebox.showerror("错误", "请选择串口")
return
self.ser = serial.Serial(port, 230400, timeout=1)
self.connect_btn.config(text="断开")
self.send_btn.config(state=tk.NORMAL)
self.status_var.set(f"已连接到 {port}")
print(f"串口 {port} 打开成功")
except Exception as e:
messagebox.showerror("串口错误", f"无法打开串口: {str(e)}")
self.ser = None
def disconnect_serial(self):
"""断开串口连接"""
if self.ser:
self.ser.close()
self.ser = None
self.connect_btn.config(text="连接")
self.send_btn.config(state=tk.DISABLED)
self.status_var.set("已断开连接")
def send_data(self):
"""发送数据"""
if not self.ser:
messagebox.showerror("错误", "请先连接串口")
return
try:
# 获取输入值
value1 = int(self.value1_var.get())
value2 = int(self.value2_var.get())
value3 = int(self.value3_var.get())
frame_code = int(self.frame_code_var.get(), 16)# 帧码以十六进制解析
# 发送数据
send_values(self.ser, frame_code, value1, value2, value3)
self.status_var.set(f"已发送: {value1}, {value2}, {value3}")
except ValueError as e:
messagebox.showerror("输入错误", "请输入有效的整数")
except Exception as e:
messagebox.showerror("发送错误", f"发送失败: {str(e)}")
def on_closing(self):
"""关闭程序时断开串口"""
if self.ser:
self.ser.close()
self.root.destroy()
def main():
root = tk.Tk()
app = XProtocolGUI(root)
root.protocol("WM_DELETE_WINDOW", app.on_closing)
root.mainloop()
if __name__ == "__main__":
main()
```
页:
[1]