eefocus_3914144 发表于 2025-10-27 23:07:58

【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]
查看完整版本: 【AIMB-2210】AI编写小车控制界面