# car_j **Repository Path**: jiang-linhu/car_j ## Basic Information - **Project Name**: car_j - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-02 - **Last Updated**: 2026-09-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 阿克曼小车控制 APP + 树莓派网关 基于 **uni-app (Vue 3)** 的安卓 APP,通过 **WiFi WebSocket** 连到树莓派 4; 树莓派作为**协议网关**,把 JSON 指令翻译成 STM32 二进制串口协议(`0xAA 0x55` 帧格式), 驱动阿克曼小车的电机桥和转向舵机,并把 STM32 回传的传感器/里程计数据转发给 APP。 ## 总体架构 ``` 手机APP(uni-app) ──WS/JSON──► 树莓派4(car_server.py) ──[AA55帧]──► STM32 ──► 电机/舵机 ◄──hello/status/hw/pong── ◄──READY/ACK/0x82 STATUS────── ``` - **APP→Pi**:`{"type":"cmd","speed":-100~100,"angle":-25~25}`(speed 正前进,angle 右正左负) - **Pi→STM32**:阿克曼专用 `0x0C ACK_DRIVE`(int16 油门‰ + float 前轮转角°),20Hz 控制流 **安全优先**:APP 断连、切后台、0.8s 无指令、STM32 无应答、服务退出都会停车回正。 ## 树莓派端文件 ``` raspberrypi/ ├── car_link.py # STM32 协议封装:组帧/解帧/ACK等待/STATUS解析/串口热插拔 ├── car_server.py # WebSocket↔串口网关(推荐从这开始) ├── requirements.txt # websockets + pyserial └── car_server.service # systemd 开机自启模板(已按用户 cui 配好) ``` ### 1. 硬件连接(树莓派 ↔ STM32) **方式 A(推荐):USB-TTL 模块**(CH340/CP2102/FT232,无需改系统配置,电气隔离好) | USB-TTL | STM32 | | --- | --- | | RXD | PA9 (USART1_TX) | | TXD | PA10 (USART1_RX) | | GND | GND(必须共地) | | 3.3V | **不要接 5V**,模块 3.3/5V 选 3.3 | 模块插树莓派 USB,设备名 `/dev/ttyUSB0`;若 STM32 用 USB CDC 直连则是 `/dev/ttyACM0`。 脚本**自动探测**这两类设备(以及 `/dev/ttyAMA0`/`/dev/ttyS0`),一般无需指定。 **方式 B:GPIO 串口直连** | STM32 | 树莓派 40Pin | | --- | --- | | PA9 (TX) | Pin10 GPIO15(RXD) | | PA10 (RX) | Pin8 GPIO14(TXD) | | GND | Pin6 GND | TX/RX 必须**交叉接**;双方都是 3.3V,不要接 5V。Ubuntu 下配置方法见文末附录。 ### 2. 安装依赖与传文件 ```bash # 树莓派上准备目录与虚拟环境 mkdir -p ~/car_server && cd ~/car_server python3 -m venv .venv source .venv/bin/activate pip install websockets "pyserial>=3.5" # 从 Windows 传文件(在电脑 PowerShell 执行;旧的 pigpio 脚本可以删掉) # scp D:\HBuilderX\project\Car_APP\raspberrypi\* cui@192.168.31.233:/home/cui/car_server/ ``` 系统级备选:`sudo apt install -y python3-serial`(注意要装在运行用的环境里)。 ### 3. 先测 Pi ↔ STM32 这一段(不经过手机) ⚠️ **先架空驱动轮**。在树莓派上执行: ```bash cd ~/car_server source .venv/bin/activate # 单次自检:自动找串口 → PING → 读一帧 STATUS python car_link.py --check ``` 预期输出:`PING ACK = 0` 和 13 个状态量(speed/yaw/pos_x 等),最后 `✅ 串口链路正常`。 常见问题: | 现象 | 处理 | | --- | --- | | `未发现串口设备` | USB 线插好没?`ls /dev/ttyUSB* /dev/ttyACM*` 看一眼;很多 USB 线只能充电不能传数据 | | `PING 无应答` | TX/RX 接反(要交叉)、GND 没共地、波特率不一致(默认 **115200**,改 `car_server.py` 顶部 `BAUD` 和 `car_link.py` 的 `DEFAULT_BAUD`) | | 持续 `校验错误,丢帧` | 波特率不匹配、共地不良、线上干扰;先缩短杜邦线验证 | | ACK=1/2/4 | ACK 1 未知命令(固件太旧不支持 0x0C?)、2 数据长度错、4 转角超界(本服务已夹紧不会触发) | | 启动时乱码 | 正常,STM32 上电英文 printf 杂散字节,解帧器会自动跳过 | 自检通过后可以键盘遥控再确认电机和舵机: ```bash python car_link.py # w/s 油门±20%,a/d 前轮±5°,空格停车回正,p 查状态,o 里程计复位,q 退出 ``` ### 4. 启动网关,用 APP 控制 ```bash python car_server.py ``` 看到 `网关已启动:APP 端口 ws://0.0.0.0:8765,串口 自动探测 @ 115200`,且日志里有 `串口已连接` 和 `STM32 READY`,即可用 APP 连 `192.168.31.233:8765`。 连接时终端会打印 `APP 已连接` 和 `APP指令 speed=… angle=… | 下发 throttle=…‰ steer=…°`。 控制页右上角 **STM32 芯片标绿** = 串口链路正常;红色并出现警告条 = 串口断开或 STM32 无应答。 ### 5. 开机自启(手动跑通后再配) ```bash sudo cp car_server.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now car_server journalctl -u car_server -f # 看日志 ``` 模板已按用户 `cui`、目录 `/home/cui/car_server`、虚拟环境 Python 配好。 另外需要把用户加入串口设备组(默认一般已在):`sudo usermod -aG dialout $USER`,重新登录生效。 ## APP 侧说明 ### 运行 打开本目录,**运行 → 运行到 Android App 基座**;手机与 Pi 同一 WiFi, 输入 `192.168.31.233`、`8765` 连接。正式用可云打包 APK。 ### 控制约定 - 摇杆左右 = 前轮转角,**左右满偏均为 25°**(与固件 ±25° 行程一致,网关还会二次夹紧) - 松杆 / 按急停 / 切后台 / 断连 → 立即 `(0,0)` - 仪表显示:指令速度、方向、实测车速 (m/s)(来自 STM32 STATUS)、STM32 在线状态、WiFi 延时 ### 与 STM32 协议的映射 | APP 发的 JSON | 树莓派转换 | STM32 命令 | |---|---|---| | `speed: 30`(30%) | 30×10 = 300‰ | `0x0C ACK_DRIVE` | | `angle: -25`(左转25°) | float -25.0 小端 `00 00 C8 C1` | 同上,一帧原子完成 | | 松手 `(0,0)` | throttle 0 + 转角 0 | 停车回正 | | 2s 一次的 `ping` | Pi 回 pong(仅测 WiFi 延时) | —(Pi 另每 2s PING 一次 STM32) | ### 通信协议 | 方向 | 报文 | | --- | --- | | APP→Pi | `{"type":"cmd","speed":-100~100,"angle":-25~25}` / `{"type":"ping","t":ms}` | | Pi→APP | `{"type":"hello","minAngle":-25,"maxAngle":25,"serial":bool}` | | Pi→APP | `{"type":"hw","serial":bool}`(串口/STM32 状态变化时推送) | | Pi→APP | `{"type":"status",...13个字段}`(每 200ms,speed/speed_l/rpm_l/accel_*/yaw_rate/yaw/servo_deg/pos_x/pos_y) | | Pi→APP | `{"type":"pong","t":ms}` | ## 安全设计 1. **APP 侧**:松杆立刻发 0;按住急停持续发 0;切后台立刻发 0;20Hz + 每 300ms 保活 2. **网关侧**:APP 断连立刻 `ACK_DRIVE(0,0)` + `STOP(0x01)`;0.8s 没收到指令自动停车; 转角在 **Pi 就夹紧到 ±25°**(固件自身也会限幅并回 ACK 3,网关提前拦住避免无谓应答) 3. **STM32 侧**:按你的固件实现(0x01 STOP 关环 PWM=0) 4. **退出**:Ctrl+C / kill 时 `halt()` 停车回正再关串口 ## 附录:Ubuntu 上启用 GPIO 硬件串口(仅方式 B 需要) ```bash sudo raspi-config # Ubuntu 上没有 raspi-config,直接配内核: ``` Ubuntu for Pi 无需关闭串口 shell(默认没有 serial-getty 在 PL011 上,但确认一下): ```bash # 若 ttyAMA0 被控制台占用: sudo systemctl disable --now serial-getty@ttyAMA0.service # 稳定使用 PL011(让蓝牙挪走),编辑 /boot/firmware/config.txt 末尾加: # dtoverlay=disable-bt sudo reboot # 重启后设备为 /dev/ttyAMA0,组通常是 dialout;脚本会自动探测 ls -l /dev/ttyAMA0 ``` ## 后续可扩展 - 仪表盘增加 RPM、yaw、里程计轨迹、加速度曲线 - PID 在线整定页(`0x05 SET_PID` 已在 car_link.py 封装) - 摄像头第一视角、蓝牙备用链路等