使用 fprintf 连续写入字符串

write string continously using fprintf

本文关键字:字符串 连续 fprintf 使用      更新时间:2023-10-16

我的项目正在使用opencv跟踪对象,并将坐标作为tx发送到arduino,并使用另一个带有"SoftwareSerial"的arduino(rx(读取数据。对象跟踪、知道坐标和 2 个 arduino 之间的通信没有问题。问题是我无法在"跟踪器"运行时发送坐标,但是当我关闭"跟踪器"时,数据开始出现在串行通信中。

OpenCV代码

using namespace cv;
using namespace std;
//default capture width and height
int FRAME_WIDTH = 320; //640 320
int FRAME_HEIGHT = 240; //480 240
int MIN_OBJECT_AREA = 10*10;
int iLowH = 16;
int iHighH = 104;
int iLowS = 110; 
int iHighS = 164;
int iLowV = 63;
int iHighV = 255;
int centerX, centerY;
int Xg,Yg;
int Modefilter = 1;
FILE *fp;
bool kirim=false;
string intToString(int number){

    std::stringstream ss;
    ss << number;
    return ss.str();
}
void detect(){
}
int main( int argc, char** argv ){
    //open serial
    FILE* serial = fopen("\\.\COM3", "w+");
    if (serial == 0) {
        printf("Failed to open serial portn");
    }

    //capture the video from web cam
    VideoCapture cap(0);
    // if not success, exit program
    if ( !cap.isOpened() ){  
        cout << "Cannot open the web cam" << endl;
        return -1;
    }
    //set height and width of capture frame
    cap.set(CV_CAP_PROP_FRAME_WIDTH,FRAME_WIDTH);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,FRAME_HEIGHT);
    //create a window called "Control"
    namedWindow("Control", CV_WINDOW_AUTOSIZE);
    //Create trackbars in "Control" window
    cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
    cvCreateTrackbar("HighH", "Control", &iHighH, 179);
    cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
    cvCreateTrackbar("HighS", "Control", &iHighS, 255);
    cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255)
    cvCreateTrackbar("HighV", "Control", &iHighV, 255);

    string XX,YY,parser1,parser2,result;
    while (serial!=0){
        Mat imgOriginal;
        bool bSuccess = cap.read(imgOriginal); // read a new frame from video
        if (!bSuccess){ //if not success, break loop
            cout << "Cannot read a frame from video stream" << endl;
            break;
        }
        //Convert the captured frame from BGR to HSV
        Mat imgHSV;
        cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); 
        //find center point
        centerX = FRAME_WIDTH/2;
        centerY = FRAME_HEIGHT/2;
        putText(imgOriginal, "Tekan", Point(5,10), FONT_HERSHEY_COMPLEX, 0.35, Scalar(0, 255, 0), 0.25, 8);
        putText(imgOriginal, "a : Mulai Mengikuti Objek", Point(5,20), FONT_HERSHEY_COMPLEX, 0.35, Scalar(0, 255, 0), 0.25, 8);
        putText(imgOriginal, "b : Berhenti Mengikuti Objek", Point(5,30), FONT_HERSHEY_COMPLEX, 0.35, Scalar(0, 255, 0), 0.25, 8);
        //create cross line
        line(imgOriginal,Point(centerX, centerY-20), Point(centerX, centerY+20), Scalar(0,255,0), 1.5);
        line(imgOriginal,Point(centerX-20, centerY), Point(centerX+20, centerY), Scalar(0,255,0), 1.5);
        //Threshold the image
        Mat imgThresholded;
        inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded);
        //morphological opening (remove small objects from the foreground)
        erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
        dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) ); 
        //morphological closing (fill small holes in the foreground)
        dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) ); 
        erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
        //these two vectors needed for output of findContours
        vector< vector<Point> > contours;
        vector<Vec4i> hierarchy;
        Mat imgContour;
        imgThresholded.copyTo(imgContour);
        //find contours of filtered image using openCV findContours function
        findContours(imgContour,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );
        //use moments method to find our filtered object
        double refArea = 0;
        if (hierarchy.size() > 0) {
            int numObjects = hierarchy.size();
            for (int index = 0; index >= 0; index = hierarchy[index][0]) {
                Moments moment = moments((cv::Mat)contours[index]);
                double area = moment.m00;
                if(area>MIN_OBJECT_AREA){ //jika area kontur lebih besar dari minimum area object maka gambar lingkaran dan tulis koordinat
                    kirim=true;
                    double x = moment.m10/area;
                    double y = moment.m01/area;
                    double r = sqrt(area/3.14);
                    Xg=(int) x;
                    Yg=(int) y;
                    circle(imgOriginal, Point(x,y), r, Scalar(0,0,255), 1.5, 8);
                    line(imgOriginal, Point(x,y-r-5), Point(x,y+r+5), Scalar(0,0,255), 1.5, 8);
                    line(imgOriginal, Point(x-r-5,y), Point(x+r+5,y), Scalar(0,0,255), 1.5, 8);
                    putText(imgOriginal, intToString(x) + "," + intToString(y), Point(x,y+10), FONT_HERSHEY_COMPLEX, 0.25, Scalar(0, 255, 0), 0.3, 8);
                    // send x,y coordinate to arduino
                    parser1="*"; parser2="!";
                    ostringstream xxx,yyy ;
                    xxx << Xg;
                    yyy << Yg;
                    XX=xxx.str(); YY=yyy.str();
                    result=parser1+XX+parser2+YY;
                    cout << result << endl; 
                    fprintf(serial, "%sn", result.c_str());    
                    fflush(serial);         
                }//end if
            }//end for
        }//end if

        //show the thresholded image
        Mat dstimgThresholded;
        resize(imgThresholded, dstimgThresholded, Size(), 2, 2, INTER_CUBIC);
        imshow("Thresholded Image", dstimgThresholded);
        //show the original image 
        Mat dstimgOriginal;
        resize(imgOriginal, dstimgOriginal, Size(), 2, 2, INTER_CUBIC);
        imshow("Original", dstimgOriginal);     
        ///send data        
        if (waitKey(5) == 27) {//wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
            cout << "esc key is pressed by user" << endl;
            break; 
        }
    } //end while
    return 0;
}

TX Arduino

#include <SoftwareSerial.h>
SoftwareSerial SWsend(2, 3); // (rx,tx)
String data;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  SWsend.begin(4800);
  //pinMode(12,INPUT_PULLUP);
}
void Send_SSIDandPWD_ToESP01() {
  while (!SWsend) {
    ; // wait for serial port to connect.
    Serial.println(F("wait for serial port to connect."));
  }
  while (Serial.available()) {
    data = Serial.readString();
    //data = Serial.read();
    Serial.print(F("Send:"));
    Serial.println(data);
    SWsend.print(data);
  }
}
void loop() {
  // put your main code here, to run repeatedly:
  Send_SSIDandPWD_ToESP01();
  delay(25);
}

RX Arduino

#include <SoftwareSerial.h>
SoftwareSerial SWrecv(2, 3); //(rx,tx)
String strSSID = "";         // a string to hold incoming data
String strPWD = "";
bool keepSSID = false;
bool keepPWD = false;
boolean stringComplete = false;  // whether the string is complete
void setup() {
  // initialize serial:
  Serial.begin(115200);
  SWrecv.begin(4800);
  // Turn on the blacklight and print a message.
  Serial.println(F("Hello, world!"));
}
void loop() {
  // print the string when a newline arrives:
  SWrecvEvent();
  if (stringComplete) {
    Serial.println("X:" + strSSID  + ", Y:" + strPWD);
    // clear the string:
    //  inputString = "";
    if (strSSID == "")
    {
      Serial.println("SSID:not config");
    }
    strSSID = "";         // a string to hold incoming data
    strPWD = "";
    stringComplete = false;
  }
}
void SWrecvEvent() {
  while (SWrecv.available()) {
    // get the new byte:
    char inChar = (char)SWrecv.read();
    //Serial.print(inChar); ///////////////////string asli
    // add it to the inputString:
    switch (inChar ) {
      case '*':
        {
          keepSSID = true;
          keepPWD = false;
        }
        break;
      case '!':
        {
          keepSSID = false;
          keepPWD = true;
        }
        break;
      default:
        {
          if (inChar == 'n') {
            stringComplete = true;
            keepSSID = false;
            keepPWD = false;
            return;
          }
          if (keepSSID == true )
          {
            strSSID += inChar;
          }
          else if (  keepPWD == true )
          {
            strPWD += inChar;
          }
        }
        break;
    }
  }
}

在跟踪器运行时,我应该怎么做才能按计数写入坐标?

可能是 IO 正在缓冲,并且仅在退出 tx 程序时刷新。 尝试调用 Flush 以强制发送数据。