# 调试小车,windows版本代码 # 可以按格式发送、接受数据 import serial import time import struct import keyboard import sys import msvcrt # Windows 环境下用于捕捉键盘输入 class SerialPort: def __init__(self, port, baudrate=9600, timeout=1): self.port = port self.baudrate = baudrate self.timeout = timeout self.serial = None def open(self): try: self.serial = serial.Serial(self.port, self.baudrate, timeout=self.timeout) print(f"成功打开串口: {self.port}") except serial.SerialException as e: print(f"打开串口失败: {e}") self.serial = None def close(self): if self.serial and self.serial.is_open: self.serial.close() print("串口已关闭") def write(self, data): if self.serial and self.serial.is_open: if isinstance(data, str): data = data.encode() self.serial.write(data) def write_hex(self, data): if self.serial and self.serial.is_open: self.serial.write(data) def read(self, size=22): if self.serial and self.serial.is_open: data = self.serial.read(size) hex_data = ', '.join(f'0x{byte:02X}' for byte in data) print(f"接收数据: {hex_data}") return data return None def parse_serial_feedback(data): struct_format = '<HhhhhhhhhHH' struct_size = struct.calcsize(struct_format) if len(data) < struct_size: raise ValueError("接收到的数据长度不足,无法解析。") parsed_data = struct.unpack(struct_format, data[:struct_size]) feedback = { 'start': parsed_data[0], 'cmd1': parsed_data[1], 'cmd2': parsed_data[2], 'speedR_meas': parsed_data[3], 'speedL_meas': parsed_data[4], 'wheelR_cnt': parsed_data[5], 'wheelL_cnt': parsed_data[6], 'batVoltage': parsed_data[7] / 100.0, 'boardTemp': parsed_data[8] / 10.0, 'cmdLed': parsed_data[9], 'checksum': parsed_data[10] } print(feedback) return feedback def calculate_checksum(data): checksum = sum(data) & 0xFFFF return checksum def send_speed_command(serial_port, steer, speed): start_frame = 0xABCD command_format = '<HhhH' command_data = struct.pack(command_format, start_frame, steer, speed, 0) checksum = (start_frame ^ steer ^ speed) & 0xFFFF command_data = struct.pack(command_format, start_frame, steer, speed, checksum) hex_data = ', '.join(f'0x{byte:02X}' for byte in command_data) print(f"发送: {hex_data}, {hex(checksum)}") print(f"发送字节流: {command_data}") serial_port.write_hex(command_data) def set_speed(serial_port, ls, rs): set_speed_l = ls / 0.10472 set_speed_r = rs / 0.10472 print(ls, rs) speed = (int)((set_speed_l + set_speed_r) / 2.0) steer = (int)((set_speed_l - speed) * 2.0) send_speed_command(serial_port, steer, speed) def get_key(): """捕捉 Windows 上的键盘输入""" if msvcrt.kbhit(): return msvcrt.getch().decode('utf-8') return None if __name__ == "__main__": # 修改为 Windows 上的串口名称,例如 'COM3' port_name = 'COM9' baudrate = 115200 serial_port = SerialPort(port=port_name, baudrate=baudrate) serial_port.open() ls = 3 rs = 3 try: while True: time.sleep(0.1) key = get_key() # 获取按键输入 if key == 'w': # Up arrow ls += 3 rs += 3 elif key == 's': # Down arrow ls = 1 rs = 1 elif key == 'a': # Left arrow ls = 0.5 rs += 3 elif key == 'd': # Right arrow ls += 3 rs = 0.5 elif key == 'q': # 按 'q' 键退出 break if ls < 0: ls = 0 if rs < 0: rs = 0 set_speed(serial_port, ls, rs) received_data = serial_port.read(44) parse_serial_feedback(received_data) # 重置速度 if key is None: # 如果没有按下键,重置速度 ls = 0 rs = 0 except KeyboardInterrupt: print("停止机器人") finally: serial_port.close()