如何解决加速与 Arduino C++ 的串行通信
第一次发帖,抱歉。
我正在尝试使用相机作为传感器制作球和光束项目,并尝试使串行通信正常工作。 如果我将 waitKey 设置为 (1000),代码当前可以工作,但这对于项目的工作来说还不够快,并且需要一些帮助来加快它的速度。
输出往往只读取我发送的第一个字符串,然后忽略其他任何内容,直到通过在输出屏幕上按住滑块几秒钟来暂停程序。
我尝试使用更快的波特率,但问题仍然存在。
这是C++代码
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <vector>
#include "SerialPort.h"
#include <string.h>
#include <stdlib.h>
#include <string>
using namespace cv;
using namespace std;
//global for the image processing
Mat imgGray,imgCanny,imgBlur,imgDil;
Mat imgHSV,mask;
//int hmin = 53,smin = 102,vmin = 35; //green
//int hmax = 93,smax = 253,vmax = 169;
/* //green ball
int hmin = 41,smin = 93,vmin = 49;
int hmax = 93,smax = 243,vmax = 192; //p
*/
//purple ball
int hmin = 117,smin = 26,vmin = 63;
int hmax = 179,smax = 113,vmax = 169;
//global for the serial
char output[MAX_DATA_LENGTH];
char incomingData[MAX_DATA_LENGTH];
char port[] = " ////.//COM3";
int PosX;
// this will convert the output into the correct string because the "stoi" function doesn't work as intended
String intToString(int I)
{
String J;
if (I ==80 )
{
J ="80" ;
}
else if (I ==81 )
{
J = "81";
}
else if (I ==82 )
{
J = "82";
}
else if (I == 83)
{
J = "83";
}
else if (I ==84 )
{
J = "84";
}
else if (I == 85)
{
J = "85";
}
else if (I == 86)
{
J = "86";
}
else if (I ==87 )
{
J = "87";
}
else if (I ==88 )
{
J = "88";
}
else if (I ==89 )
{
J = "89";
}
else if (I ==90 )
{
J = "90";
}
else if (I ==91 )
{
J = "91";
}
else if (I == 92)
{
J = "92";
}
else if (I == 93)
{
J = "93";
}
else if (I == 94)
{
J = "94";
}
else if (I == 95)
{
J = "95";
}
else if (I == 96)
{
J = "96";
}
else if (I == 97)
{
J = "97";
}
else if (I == 98)
{
J = "98";
}
else if (I == 99)
{
J = "99";
}
else if (I == 100)
{
J = "100";
}
else if (I > 100)
{
J = "100";
}
else if (I < 80)
{
J = "80";
}
return (J);
}
// calculation to make the output between outMin and outMax taken from arduino website and transformed into calculation
int map(int x,int in_min,int in_max,int out_min,int out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// just the P of the PID controller
int PCONTROL(int xPos)
{
int P,Kp = 1,Proportional,error;
error = 240 - xPos; //240 is the middle of the camera and xPos is the current position
Proportional = Kp * error;
P = map(Proportional,-240,240,80,100); // calculation to make the output between 80&100 taken from arduino website and transformed into calculation
return (P);
}
// this is the function made to be the PID contol loop
int PIDCONTROL(int xPos)
{
int error_prior = 0,error,integral_prior = 0,Kp,Ki,Kd,integral,derivative,proportional,outPut,PID_total,period = 50;
// I have set the Kp and Ki to zero when testing the P contoller
Kp = 1;
Ki = 0;
Kd = 0;
//error = (img.rows/2) - xPos; // 640 is the desired Value
error = (480/2) - xPos; // this is if I got the wrong part of the resolution
proportional = Kp * error;
integral = integral_prior + error;
derivative = (error - error_prior)/period;
PID_total = ((Kp * proportional) + (Ki * integral) + (Kd * derivative)); //this is the calculation for the PID controller
error_prior = error;
integral_prior = integral;
outPut = map(PID_total,100);
cout << "output = " << outPut << endl;
return (outPut);
}
// this code will get the x and y values of the ball,draw a Box around it and lable it
// this is what i need for the project
void getContours(Mat imgDil,Mat img)
{
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
string objectType;
string x,y;
findContours(imgDil,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
//drawContours(img,-1,Scalar(255,255),2); //draws everything
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]);
//cout << area << endl; //displays the area of the ball
vector<vector<Point>>conpoly(contours.size());
vector<Rect>boundRect(contours.size());
if (area > 1000 && area < 5000) //filters out smaller and larger objects
{
float peri = arcLength(contours[i],true);
approxpolyDP(contours[i],conpoly[i],0.02 * peri,true);
drawContours(img,i,2); // with a filter applyed
boundRect[i] = boundingRect(conpoly[i]); //draw a Box around the ball
rectangle(img,boundRect[i].tl(),boundRect[i].br(),Scalar(0,255,0),5);
putText(img,"Ball",{ boundRect[i].x,boundRect[i].y - 5 },FONT_HERShey_PLAIN,1,69,2); //display text above the Box saying ball
//cout << "X = " << boundRect[i].x << endl;// << "Y = " << boundRect[i].y << endl; //print the x and y values
PosX = boundRect[i].x;
}
}
}
void main()
{
VideoCapture cap(0);
Mat img;
string xposSrg;
//int TempData;
Mat Reimg,Reimg2;
string data;
//char TrackbarName[50];
const int alpha_slider_max = 100;
int xPos,preData = 0;
createTrackbar("Hue Min","Trackbars",&hmin,179);
SerialPort arduino(port);
if (arduino.isConnected()) {
cout << "Connection" << endl << endl;
}
else {
cout << "Error Connecting" << endl << endl;
}
while (arduino.isConnected()) // no point do it if not connected
{
cap.read(img);
//prepocessing
Mat imgGray,Reimg,Reimg2;
//cvtColor(img,imgGray,COLOR_BGR2GRAY);
//pyrDown(img,Size(img.cols / 2,img.rows / 2)); // downsample for faster processing
cvtColor(img,imgHSV,COLOR_BGR2HSV); // get the big wierd colours
Scalar lower(hmin,smin,vmin);
Scalar upper(hmax,smax,vmax);
inRange(imgHSV,lower,upper,mask); // make only the green ball visible
GaussianBlur(mask,Size(3,3),3,0);
Canny(imgBlur,25,75);
Mat kernel = getStructuringElement(MORPH_RECT,3));
dilate(imgCanny,imgDil,kernel);
getContours(imgDil,img); // use only the visible green to the contours fuction
//displaying processes used in debuging
/*
imshow("Ball",img);
imshow("Gray",imgGray);
imshow("Blur",imgBlur);
imshow("Canny",imgCanny);
imshow("Dil",imgDil);
*/
//cout << img.rows << endl;;
//display the orginal img with the contors drawn on to it
imshow("img",img);
// do the PID controller calculations
preData = PIDCONTROL(PosX);
//send the data to the arduino
data = intToString(preData);
cout << "Data =" << data << "." << endl;
char* chararray = new char[data.size() +1];
copy(data.begin(),data.end(),chararray);
chararray[data.size()] = '\n';
arduino.writeSerialPort(chararray,MAX_DATA_LENGTH);
arduino.readSerialPort(output,MAX_DATA_LENGTH);
cout << " Arduino >> " << output << "." << endl;
delete[] chararray;
waitKey(1); //work as fast as possible
// turns out this library can only output every second
}
}
这是Arduino代码
#include <Servo.h>
Servo myservo;
String info;
void setup() {
Serial.begin(9600);
//pinMode(led,OUTPUT);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
myservo.write(90); // set the starting position to 90 degrees(flat)
}
// this is the one for on using 10 degrees
void loop()
{
if (Serial.available() >0)
{
info = Serial.readStringUntil('\n');
}
Serial.flush();
//check what the imput is then change the servo level (every 10 degrees) and output the level
// checking the string other ways caused errors dunno why
if (info.equals("0"))
{
Serial.println("Not Receiving Data");
myservo.write(90);
}
else if (info.equals("80"))
{
Serial.println("80");
myservo.write(80);
}
else if (info.equals("81"))
{
Serial.println("81");
myservo.write(81);
}
else if (info.equals("82"))
{
Serial.println("82");
myservo.write(82);
}
else if (info.equals("83"))
{
Serial.println("83");
myservo.write(83);
}
else if (info.equals("84"))
{
Serial.println("84");
myservo.write(84);
}
else if (info.equals("85"))
{
Serial.println("85");
myservo.write(85);
}
else if (info.equals("86"))
{
Serial.println("86");
myservo.write(86);
}
else if (info.equals("87"))
{
Serial.println("87");
myservo.write(87);
}
else if (info.equals("88"))
{
Serial.println("88");
myservo.write(88);
}
else if (info.equals("89"))
{
Serial.println("89");
myservo.write(89);
}
else if (info.equals("90"))
{
Serial.println("90");
myservo.write(90);
}
else if (info.equals("91"))
{
Serial.println("91");
myservo.write(91);
}
else if (info.equals("92"))
{
Serial.println("92");
myservo.write(92);
}
else if (info.equals("93"))
{
Serial.println("93");
myservo.write(93);
}
else if (info.equals("94"))
{
Serial.println("94");
myservo.write(94);
}
else if (info.equals("95"))
{
Serial.println("95");
myservo.write(95);
}
else if (info.equals("96"))
{
Serial.println("96");
myservo.write(96);
}
else if (info.equals("97"))
{
Serial.println("97");
myservo.write(97);
}
else if (info.equals("98"))
{
Serial.println("98");
myservo.write(98);
}
else if (info.equals("99"))
{
Serial.println("99");
myservo.write(99);
}
else if (info.equals("100"))
{
Serial.println("100");
myservo.write(100);
}
}
这是从 https://www.youtube.com/watch?v=8BWjyZxGr5o 中提取的头文件
#ifndef SERIALPORT_H
#define SERIALPORT_H
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 256
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class SerialPort
{
private:
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
SerialPort(char* portName);
~SerialPort();
int readSerialPort(char* buffer,unsigned int buf_size);
bool writeSerialPort(char* buffer,unsigned int buf_size);
bool isConnected();
};
#endif // SERIALPORT_H
#include "SerialPort.h"
SerialPort::SerialPort(char* portName)
{
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),GENERIC_READ | GENERIC_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_norMAL,NULL);
if (this->handler == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
printf("ERROR: Handle was not attached. Reason: %s not available\n",portName);
}
else
{
printf("ERROR!!!");
}
}
else {
DCB dcbSerialParameters = { 0 };
if (!GetCommState(this->handler,&dcbSerialParameters)) {
printf("Failed to get current serial parameters");
}
else {
dcbSerialParameters.Baudrate = CBR_9600;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = OnesTOPBIT;
dcbSerialParameters.Parity = nopARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler,&dcbSerialParameters))
{
printf("ALERT: Could not set Serial port parameters\n");
}
else {
this->connected = true;
PurgeComm(this->handler,PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort()
{
if (this->connected) {
this->connected = false;
CloseHandle(this->handler);
}
}
int SerialPort::readSerialPort(char* buffer,unsigned int buf_size)
{
DWORD bytesRead;
unsigned int toRead = 0;
ClearCommError(this->handler,&this->errors,&this->status);
if (this->status.cbInQue > 0) {
if (this->status.cbInQue > buf_size) {
toRead = buf_size;
}
else toRead = this->status.cbInQue;
}
if (ReadFile(this->handler,buffer,toRead,&bytesRead,NULL)) return bytesRead;
return 0;
}
bool SerialPort::writeSerialPort(char* buffer,unsigned int buf_size)
{
DWORD bytesSend;
if (!WriteFile(this->handler,(void*)buffer,buf_size,&bytesSend,0)) {
ClearCommError(this->handler,&this->status);
return false;
}
else return true;
}
bool SerialPort::isConnected()
{
return this->connected;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。