首页 > 解决方案 > Python 通过串行到 Arduino,不能移动舵机

问题描述

我目前正在尝试将摄像机安装在由两个微型伺服系统组成的云台上来跟踪一张脸。我的 python 代码一直在工作,并且已经成功识别出一张脸,但是当 Arduino 不断闪烁时,我的伺服系统没有一个在移动,就好像它正在接收来自 Python 代码的输入一样。我无法让伺服系统根据我的 python 代码移动,但我在旁边编写了简单的代码,以确保伺服系统具有良好的连接并且它们自己可以正常工作。我不确定出了什么问题...

Python代码

import numpy as np6
import serial
import time
import sys
import cv2

arduino = serial.Serial('COM3', 9600)
time.sleep(2)
print("Connection to arduino...")


face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

cap = cv2.VideoCapture(0)

while 1:
    ret, img = cap.read()
    cv2.resizeWindow('img', 500,500)
    cv2.line(img,(500,250),(0,250),(0,255,0),1)
    cv2.line(img,(250,0),(250,500),(0,255,0),1)
    cv2.circle(img, (250, 250), 5, (255, 255, 255), -1)
    gray  = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3)

    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),5)
        roi_gray  = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]

        arr = {y:y+h, x:x+w}
        print (arr)

        print ('X :' +str(x))
        print ('Y :'+str(y))
        print ('x+w :' +str(x+w))
        print ('y+h :' +str(y+h))

        xx = int(x+(x+h))/2
        yy = int(y+(y+w))/2

        print (xx)
        print (yy)

        center = (xx,yy)

        print("Center of Rectangle is :", center)
        data =(“X {0: f} Y {1: f} Z” .format (xx, yy))
        print ("output = '" +data+ "'")
        arduino.write(data.encode())


    cv2.imshow('img',img)

    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

Arduino代码

#include<Servo.h>

Servo servoVer; //Vertical Servo
Servo servoHor; //Horizontal Servo

int x;
int y;

int prevX;
int prevY;

void setup()
{
  Serial.begin(9600);
  servoVer.attach(5); //Vertical Servo to Pin 5
  servoHor.attach(6); //Horizontal Servo to Pin 6
  servoVer.write(90);
  servoHor.write(90);
}

void Pos()
{
  if(prevX != x || prevY != y)
  {
    int servoX = map(x, 600, 0, 70, 179); 
    int servoY = map(y, 450, 0, 179, 95); 

    servoX = min(servoX, 179);
    servoX = max(servoX, 70);
    servoY = min(servoY, 179);
    servoY = max(servoY, 95);

    servoHor.write(servoX);
    servoVer.write(servoY);
  }
}

void loop()
{
  if(Serial.available() > 0)
  {
    if(Serial.read() == 'X')
    {
      x = Serial.parseInt();

      if(Serial.read() == 'Y')
      {
        y = Serial.parseInt();
       Pos();
      }
    }
    while(Serial.available() > 0)
    {
      Serial.read();
    }
  }
}

标签: pythonarduinopyserialservo

解决方案


一个大问题是您使用 Serial.read 的方式。该函数消耗缓冲区中的字符。你不会把同一篇读两遍。所以假设你发送一个'Y'。第一个 if 语句从串行缓冲区中读取 Y 并与“X”进行比较,这是错误的,所以它继续前进。然后它从串行中读取其他内容,如果没有内容可读取,则可能为 -1。但它没有看到“Y”,因为它是在第一个 if 中读取的。

您需要做的是从串行读取到 char 变量,然后在 if 语句中使用该 char 变量。

    char c = Serial.read();
    if(c == 'X')...

...  if (c == 'Y')...

推荐阅读