You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于人脸距离的树莓派-Arduino直流电机串口控制异常排查

解决树莓派与Arduino串口通信指令偶尔失效的问题

问题根源

  1. 指令无界定符,接收逻辑模糊:Arduino用Serial.readString()读取数据时,会持续读取到串口缓冲区为空,若树莓派频繁发送相同指令,会导致缓冲区出现拼接数据(如onon),无法匹配预设指令。
  2. 重复发送冗余指令:树莓派每帧检测到距离符合条件就发送指令,大量重复指令挤占串口带宽,引发丢包或粘包。
  3. Arduino初始化延迟:树莓派打开串口后,Arduino会自动重启,此时立即发送的指令会直接丢失。

解决方案

1. 给指令添加结束符,修正Arduino接收逻辑

给树莓派发送的指令加上换行符\n,让Arduino准确识别完整指令;同时修改Arduino的读取方式,仅读取到换行符为止,并清理冗余字符。

树莓派代码修改(指令发送部分):

将原发送代码:

usb.write(b'of') 
# 和
usb.write(b'on')

改为:

usb.write(b'of\n')  # 添加换行符作为指令结束标记
usb.flush()  # 确保数据全部发送
# 和
usb.write(b'on\n')
usb.flush()

Arduino代码修改(读取逻辑):

void loop() {
   if (Serial.available()) {
      String command = Serial.readStringUntil('\n'); // 读取到换行符为止
      command.trim(); // 移除换行符、空格等冗余字符
      if (command == "on"){
        forward();
      }else if(command == "of"){
       mstop();
      }
   }
}

2. 避免重复发送相同指令

在树莓派代码中记录上一次发送的指令,仅当指令发生变化时才发送,减少串口通信量。

树莓派代码修改:

  • 新增导入time模块:
import time
  • 打开串口后添加延时,等待Arduino重启完成:
try:
   usb = serial.Serial(USB_PORT, 9600, timeout=2)
   time.sleep(2)  # 等待Arduino重启初始化
except:
   print("ERROR - Could not open USB serial port.  Please check your port name and permissions.")
   print("Exiting program.")
   exit()
  • 主循环前定义变量记录上一次指令:
last_command = None
  • 修改距离判断的发送逻辑:
if face_width_in_frame != 0:
    Distance = Distance_finder(Focal_length_found, Known_width, face_width_in_frame)
    # 原有的绘图代码保持不变
    
    current_command = None
    if Distance < 50 :
        print("back")
    elif 50 < Distance < 80:
        current_command = "of"
        if current_command != last_command:
            print("stop")
            usb.write(b'of\n')
            usb.flush()
            last_command = current_command
    elif Distance > 80:
        current_command = "on"
        if current_command != last_command:
            print("forward")
            usb.write(b'on\n')
            usb.flush()
            last_command = current_command

修改后的完整关键代码

树莓派代码(关键片段)

import numpy as np
import cv2 
import serial
import time

USB_PORT = "/dev/ttyUSB0"

try:
   usb = serial.Serial(USB_PORT, 9600, timeout=2)
   time.sleep(2)
except:
   print("ERROR - Could not open USB serial port.  Please check your port name and permissions.")
   print("Exiting program.")
   exit()

# 原有的常量、函数定义保持不变

cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()

last_command = None
while True:
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    
    face_width_in_frame = face_data(frame)

    if face_width_in_frame != 0:
        Distance = Distance_finder(Focal_length_found, Known_width, face_width_in_frame)
        # 原有的绘图代码保持不变
        
        current_command = None
        if Distance < 50 :
            print("back")
        elif 50 < Distance < 80:
            current_command = "of"
            if current_command != last_command:
                print("stop")
                usb.write(b'of\n')
                usb.flush()
                last_command = current_command
        elif Distance > 80:
            current_command = "on"
            if current_command != last_command:
                print("forward")
                usb.write(b'on\n')
                usb.flush()
                last_command = current_command

    cv2.imshow('frame', frame)
    if cv2.waitKey(1) == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

Arduino代码(完整)

#include <AFMotor.h>

AF_DCMotor motor(1);

void setup() {
  Serial.begin(9600);
}

void loop() {
   if (Serial.available()) {
      String command = Serial.readStringUntil('\n');
      command.trim();
      if (command == "on"){
        forward();
      }else if(command == "of"){
       mstop();
      }
   }
}

void forward(){
  motor.setSpeed(200);
  motor.run(FORWARD);
}

void mstop(){
  motor.run(RELEASE);
}

内容的提问来源于stack exchange,提问作者iulian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 05:01:25