从Arduino的串口读取实时数据到python脚本中

2024-10-03 13:30:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过Pyserial lib读取来自Arduino的数据。我遇到的问题,它拒绝访问COM端口读取数据。你知道吗

python脚本是一个OpenCV程序,用于跟踪对象,它请求一个边界框,然后在摄影机流中跟踪该框。它还将向屏幕输出Arduino上红外传感器读取的距离。你知道吗

我试图清除Arduino代码并再次闪烁它,但没有帮助。我关闭了串行监视器,似乎有一次帮助,但它不会再工作,由于某种原因。你知道吗

arduino代码是:

#include <SharpIR.h>
SharpIR DETECTORsensor( SharpIR::GP2Y0A21YK0F, A0 );

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

void loop()
{
  int distance = DETECTORsensor.getDistance(); 
  Serial.println( distance );
  delay(500);
}

Python代码如下:

import cv2
import sys
import serial


if __name__ == '__main__' :

    # Set up tracker.
    tracker = cv2.TrackerMIL_create()

    # Read video
    video = cv2.VideoCapture(0)

    # Exit if video not opened.
    if not video.isOpened():
        print ("Could not open video")
        sys.exit()

    # Read first frame.
    ok, frame = video.read()
    if not ok:
        print ('Cannot read video file')
        sys.exit()



#Define ROI
    bbox = cv2.selectROI(frame, False)

    # Initialize tracker with first frame and bounding box
    ok = tracker.init(frame, bbox)

    while True:
        # Read a new frame
        ok, frame = video.read()
        if not ok:
            break

        # Start timer, FPS only
        timer = cv2.getTickCount()

        # Update tracker
        ok, bbox = tracker.update(frame)

        # Calculate Frames per second (FPS)
        fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer);

        #calculate Distance from Raspi
        focallength = 480.20
        knownwidth = 30.480 #Almost the same size as A4 paper
        perwidth = bbox[2] #This is what will update every frame, unable to update for now
        RaspiDist = (knownwidth*focallength)/perwidth

        #Calculate distance from IR sensor
        ser_data = serial.Serial("COM3",9600)

        # Draw bounding box
        if ok:
            # Tracking success
            p1 = (int(bbox[0]), int(bbox[1]))
            p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
            cv2.rectangle(frame, p1, p2, (0,255,255), 2, 1)
        else :
            # Tracking failure
            cv2.putText(frame, "Tracking failure detected", (100,80), cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)

#Display tracker type on frame
        cv2.putText(frame, "MIL Tracker", (0,20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);

#Display FPS on frame
        cv2.putText(frame, "FPS : " + str(int(fps)), (0,50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);

#Display Distance on frame
        cv2.putText(frame, "RaspiDistance : " + str(int(RaspiDist))+" cms", (0,75), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);
        cv2.putText(frame, "IRDistance : " + str(int(ser_data)), (0,100), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0,255,255), 2);

        # Display result [2] 
        cv2.imshow("Tracking", frame)

        # Exit if ESC pressed
        k = cv2.waitKey(1) & 0xff

# Destroy all windows
cv2.destroyAllWindows()

错误是:

File "C:\Users\XXX\Anaconda3\envs\py36\lib\site-packages\serial\serialwin32.py", line 62, in open raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))

SerialException: could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5)


Tags: ifvideonotokopencv2trackerframe
2条回答

我怀疑这是因为主循环中有ser_data = serial.Serial("COM3",9600)。这意味着在第二个循环中,它将尝试打开一个已经在使用的连接。所以被拒绝了。您应该将该行移出主循环,并在脚本结束时正确地关闭它。你知道吗

或者你可以使用

with serial.Serial() as ser:
    [loop here]

您还应该知道,当前您的代码没有从串行连接读取任何数据。为此,必须使用read()

x = ser.read()          # read one byte
s = ser.read(10)        # read up to ten bytes (timeout)

我建议您首先创建一个可以读取IR数据的小脚本,这样您就知道这是可行的。文档非常有用,请阅读它here。你知道吗

这里是一个最小的代码,您可以用来测试您的串行端口。Arduino密码

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

void loop()
{
  int distance = 123;
  Serial.println(distance);
  delay(500);
}

还有Python脚本

from serial import Serial

port = "COM3"
baudrate = 9600

with Serial(port=port, baudrate=baudrate, timeout=1) as port_serie:
    if port_serie.isOpen():
        port_serie.flush()
        for i in range(20):
            try:
                ligne = port_serie.readline()
                print(str(ligne))
            except:
                print("Exception")
        port_serie.close()

这个最小的代码只运行20次迭代。我删除了while True,因为我不喜欢调试时可能出现的无限循环。如果脚本运行正常,那么您可以使用while,在Arduino上包含所有视频内容和距离检测

相关问题 更多 >