首页 > 解决方案 > 如何将 Python IDE 中的串行输出数据转换为 C 中的整数?

问题描述

所以我想在python中使用来自面部扫描的位置数据,然后将数据转换为两个伺服电机(x和y)的旋转指令我基本上已经设置好了我只需要知道如何让Arduino将字节与串行分离到2 个整数读数。这是我到目前为止所拥有的
Python

import numpy as np
import serial
import time
import sys
import cv2
face_cascade = cv2.CascadeClassifier('cascades/data/haarcascade_frontalface_alt2.xml')
serialcomm = serial.Serial('COM5', 9600)
serialcomm.timeout = 1
cap = cv2.VideoCapture(0)
#
while(True):
        ret, frame = cap.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.5,  5)
        for(x, y , w , h) in faces:
           # print(x,y,w,h)
            roi_gray = gray[y:y+h, x:x+w] 
            roi_color = frame[y:y+h, x:x+w]
           # stringx = str(y) +'\n'
            #serialcomm.write(stringx.encode())
            color = (255, 0, 0)
            stroke = 2
            end_cord_x= x+w
            end_cord_y = y + h
            cv2.rectangle(frame, (x,y),(end_cord_x,end_cord_y), color, stroke)
            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:d}Y{1:d}Z".format(x,y)
            print ("output = '" +data+ "'")
            print(data.encode())
            #serialcomm.write(data.encode())
        cv2.imshow('frame',frame)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break

cap.release()
cv2.destroyAllWindows()

阿杜诺

#include<Servo.h>
Servo servoVer; //Vertical Servo
Servo servoHor; //Horizontal Servo
int x;
int y;
int prevX;
int prevY;
int ledgreen = 7;
int ledred = 8;
void setup()
{
  Serial.begin(9600);
  servoVer.attach(9); //Attach Vertical Servo to Pin 9
  servoHor.attach(8); //Attach Horizontal Servo to Pin 8
  servoVer.write(90);
  servoHor.write(90);
  pinMode(ledgreen, OUTPUT);
  pinMode(ledred, INPUT);
}
void Pos()
{
  if(prevX != x || prevY != y)
  {
    int servoX = map(x, 0, 400, 70, 130);
    int servoY = map(y, 0, 400, 95,130);
    servoX = max(servoX, 130);
    servoX = min(servoX, 70);
    servoY = max(servoY, 130);
    servoY = min(servoY, 95);
    
    servoHor.write(servoX);
    servoVer.write(servoY);
  }
}
void loop()
{
  if(Serial.available() > 0)
  {
    if(Serial.read() == 'X')
    {
      x = Serial.parseInt();
       digitalWrite(ledred, HIGH);
      }
      if(Serial.read() == 'Y')
      {
        y = Serial.parseInt();
       Pos();
       digitalWrite(ledgreen, HIGH);
      }
    }
    while(Serial.available() > 0)
    {
      Serial.read();
    }
  }
}

基本上我无法从 COM5 端口打开终端,因为它已经被 Arduino 和 Python 代码占用,因此我不知道我是否建立了正确的协议来读取代码。但是,我希望输出是一个看起来像X223Y156Z但我不知道如何确定我是否完全正确的字符串。当我运行代码时,伺服系统会响应但动作不稳定,所以我假设问题出在代码中

标签: pythonarduinoembedded

解决方案


我认为问题的出现是因为您没有给出角度的相对变化,而是给出了绝对值。

//Variables for keeping track of the current servo positions.
char servoTiltPosition = 90;
char servoPanPosition = 90;
//The pan/tilt servo ids for the Arduino serial command interface.
char tiltChannel = 0;
char panChannel = 1;


//These variables hold the x and y location for the middle of the detected face.
int midFaceY=0;
int midFaceX=0;
//The variables correspond to the middle of the screen, and will be compared to the midFace values
int midScreenY = (height/2);
int midScreenX = (width/2);
int midScreenWindow = 10;  //This is the acceptable 'error' for the center of the screen.


//The degree of change that will be applied to the servo each time we update the position.
int stepSize=1;

如果找到任何面,则首先计算面的中点:

midFaceY = faces[0].y + (faces[0].height/2);
midFaceX = faces[0].x + (faces[0].width/2);
//Find out if the Y component of the face is below the middle of the screen.

if(midFaceY < (midScreenY - midScreenWindow)){
  if(servoTiltPosition >= 5)servoTiltPosition -= stepSize; //If it is below the middle of the screen, update the tilt position variable to lower the tilt servo.
}
//Find out if the Y component of the face is above the middle of the screen.
else if(midFaceY > (midScreenY + midScreenWindow)){
  if(servoTiltPosition <= 175)servoTiltPosition +=stepSize; //Update the tilt position variable to raise the tilt servo.
}
//Find out if the X component of the face is to the left of the middle of the screen.
if(midFaceX < (midScreenX - midScreenWindow)){
  if(servoPanPosition >= 5)servoPanPosition -= stepSize; //Update the pan position variable to move the servo to the left.
}
//Find out if the X component of the face is to the right of the middle of the screen.
else if(midFaceX > midScreenX + midScreenWindow){
  if(servoPanPosition <= 175)servoPanPosition +=stepSize; //Update the pan position variable to move the servo to the right.
}

发送数据

ser.write(tiltChannel);      //Send the tilt servo ID
ser.write(servoTiltPosition); //Send the updated tilt position.
ser.write(panChannel);        //Send the Pan servo ID
ser.write(servoPanPosition);  //Send the updated pan position.
delay(1);

推荐阅读