基于opencv的图像分析串口发送,单片机接收,输出脉冲继而控制步进电机转动
mainwindow.h#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>#include <QDebug>#include <QtSerialPort/QSerialPort>#include <QtSerialPort/QSerialPortInfo>#include "imagebuffer.h"#include "wlinkusbcamera.h"using namespace cv;
#include<QTimer>namespace Ui
{
class MainWindow;}
class MainWindow
:
public QMainWindow{
Q_OBJECTpublic:
explicit MainWindow(QWidget
*parent
=
0);
~MainWindow();
void Init()
;
void PidControl(
int,
int,
int,
int);
void sendSerialPortData(
long ,
char,
long );
void handleSerialError(QSerialPort::SerialPortError
error,
bool &);
private slots:
void on_clearButton_clicked();
void on_sendButton_clicked();
void on_openButton_clicked();
void Read_Data();
void slot1();
void on_PidChange_valueChanged(
int value);
void on_PidChange_sliderReleased();
void on_PidChange_sliderPressed();
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
private:
Ui::MainWindow
*ui;
QSerialPort
*serial;
WLinkUsbCamera
*tab
;
QTimer
*timer;
int LastError;
//Error[-1]上一次 int PrevError;
//Error[-2]上两次 int Output;};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"#include "ui_mainwindow.h"#include <opencv2/opencv.hpp>#include "opencv2\highgui\highgui.hpp"#include <QMessageBox>#include<QDebug>MainWindow::MainWindow(
QWidget *parent)
:
QMainWindow(parent),
ui(
new Ui::
MainWindow),
LastError(
0),
PrevError(
0),
Output(
0){
ui->setupUi(
this);
Init();
qDebug()<<
"sioflong"<<
sizeof(
long)<<
sizeof(
int)<<
sizeof(
char);
//查找可用的串口 foreach(
const QSerialPortInfo &info,
QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.
open(
QIODevice::
ReadWrite))
{
ui->
PortBox->addItem(serial.portName());
serial.
close();
}
}
//设置波特率下拉菜单默认显示第三项 ui->
BaudBox->setCurrentIndex(
3);
//关闭发送按钮的使能 ui->
sendButton->setEnabled(
false);
ui->
groupBox_2->setEnabled(
false);
qDebug()<<tr(
"Interface settings successful!");}
MainWindow::~
MainWindow(){
delete ui;
delete tab;}
void MainWindow::Init(){
tab =
new WLinkUsbCamera()
;
tab->start();
timer =
new QTimer(
this);
connect(
timer,
SIGNAL(timeout()),
this,
SLOT(slot1()));
timer->start(
60);}
void MainWindow::handleSerialError(
QSerialPort::
SerialPortError error,
bool &TxEnTemp){
if (error
==
QSerialPort::
ResourceError)
{
QMessageBox::critical(
this,
tr(
"Error"),
"串口连接中断,请检查是否正确连接!");
// QMessageBox::critical(this, tr("Error"), com->errorString()); // CloseSerialPort(); }
else {
TxEnTemp=
true;
}}
void MainWindow::slot1(){
if(
ImageBuffer::Instance()->getSizeOfBuf()>
0)
{
DStruct *temp=
new DStruct;
Mat img;
Point pointbuf(
0,
0);
int PointChange=
0;
int dec;
bool ok;
QString str;
int SetKp=
30,SetKi=
0,SetKd=
0;
str
=
ui->
SetKpUi->text();
dec
=
str.toInt(&ok,
10);
SetKp=dec;
str
=
ui->
SetKiUi->text();
dec
=
str.toInt(&ok,
10);
SetKi=dec;
str
=
ui->
SetKdUi->text();
dec
=
str.toInt(&ok,
10);
SetKd=dec;
temp=
ImageBuffer::Instance()->getFrame();
img=temp->
data;
pointbuf=temp->
currentpoint;
PointChange=temp->
displacement;
img.col(pointbuf.
x).setTo(
cv::
Scalar(
244));
img.row(pointbuf.
y).setTo(
cv::
Scalar(
244));
imshow(
"pid2",img);
qDebug()<<
"PointChange"<<PointChange;
PidControl(PointChange,SetKp,SetKi,SetKd);
}}
void MainWindow::PidControl(
int iError,
int kp,
int ki
,
int kd){
//△u(k)=u(k)-u(k-1)=Kp△e(k)+Kie(k)+Kd[△e(k)-△e(k-1)]//式中△e(k)= e(k)¬-e(k-1)int P,I,D;
long PulseNumBuf=
0;
char CwCcwBuf=
0;
long rateBuf=
0;
// iError; //iError[o]当前误差P=kp*(iError-
LastError);I=ki*iError;D=kd*(iError-
LastError)-kd*(
LastError-
PrevError);
Output+=P+I+D;
LastError=iError;
PrevError=
LastError;
qDebug()<<
"[Kp,Ki,Kd]"<<
"["<<kp<<
","<<ki<<
","<<kd<<
"]"<<
"output"<<
Output;
if(iError>
0){
CwCcwBuf=
0x01;}
else{
CwCcwBuf=
0x11;}PulseNumBuf=
Output;
if(
ui->
openButton->text()==tr(
"关闭串口")){
bool TxEn=
false;
QSerialPort::
SerialPortError error=
serial->error();
handleSerialError(error,TxEn);
if(TxEn)
{
sendSerialPortData(PulseNumBuf,CwCcwBuf,rateBuf);
}}}
//清空接受窗口void MainWindow::on_clearButton_clicked(){
ui->
textEdit->clear();
cv::
Mat img=
cv::imread(
"C:/Users/Administrator/Desktop/SerialPort/SerialPort/SerialPort/earth.jpg",
1);
qDebug()<<img.
data ;
qDebug()<<img.
cols <<img.
rows ;
cv::imshow(
"MyWindow",
img);}
//发送数据void MainWindow::on_sendButton_clicked(){
serial->write(
ui->
textEdit_2->toPlainText().toLatin1());}
void MainWindow::sendSerialPortData(
long PulseNumTemp,
char CwCcwTemp,
long rateTemp){
QByteArray Bin_Order;
//帧头 Bin_Order.append(
0x55);
//1// bool ok ;//正转0x11 “01”,反转0x01 “11” ,停止0xx0; Bin_Order.append(CwCcwTemp);
//2/*//频率个数 Bin_Order.append(0x80);//3 Bin_Order.append(0x0c);//4 Bin_Order.append((char)0x0);//5 Bin_Order.append((char)0x0);//6*/ //频率个数 char buf=
0;
buf=PulseNumTemp|buf;
Bin_Order.append(buf);
//3 buf=
0;
buf=PulseNumTemp>>
8|buf;
Bin_Order.append(buf);
//4 buf=
0;
buf=PulseNumTemp>>
16|buf;;
Bin_Order.append(buf);
//5 buf=
0;
buf=PulseNumTemp>>
24|buf;
Bin_Order.append(buf);
//6//脉冲频率/* Bin_Order.append(0xd0);//7 Bin_Order.append(0x07);//8 Bin_Order.append((char)0x0);//9 Bin_Order.append((char)0x0);//10*/ buf=rateTemp|buf;
Bin_Order.append(buf);
//3 buf=
0;
buf=rateTemp>>
8|buf;
Bin_Order.append(buf);
//4 buf=
0;
buf=rateTemp>>
16|buf;;
Bin_Order.append(buf);
//5 buf=
0;
buf=rateTemp>>
24|buf;
Bin_Order.append(buf);
//6//帧尾 //“aa” Bin_Order.append(
0xaa);
//11 serial->write(Bin_Order);
//55 11 b8 0b 00 00 d0 07 00 00 aa}
//读取接收到的数据void MainWindow::Read_Data(){
QByteArray buf;
buf
=
serial->readAll();
if(!buf.isEmpty())
{
QString str
=
ui->
textEdit->toPlainText();
str+=tr(buf);
ui->
textEdit->clear();
ui->
textEdit->append(str);
}
buf.clear();}
void MainWindow::on_openButton_clicked(){
if(
ui->
openButton->text()==tr(
"打开串口"))
{
serial =
new QSerialPort;
//设置串口名 serial->setPortName(
ui->
PortBox->currentText());
//打开串口 serial->
open(
QIODevice::
ReadWrite);
//设置波特率 serial->setBaudRate(
ui->
BaudBox->currentText().toInt());
//设置数据位数 switch(
ui->
BitNumBox->currentIndex())
{
case 8:
serial->setDataBits(
QSerialPort::
Data8);
break;
default:
break;
}
//设置奇偶校验 switch(
ui->
ParityBox->currentIndex())
{
case 0:
serial->setParity(
QSerialPort::
NoParity);
break;
default:
break;
}
//设置停止位 switch(
ui->
StopBox->currentIndex())
{
case 1:
serial->setStopBits(
QSerialPort::
OneStop);
break;
case 2:
serial->setStopBits(
QSerialPort::
TwoStop);
break;
default:
break;
}
//设置流控制 serial->setFlowControl(
QSerialPort::
NoFlowControl);
//关闭设置菜单使能 ui->
PortBox->setEnabled(
false);
ui->
BaudBox->setEnabled(
false);
ui->
BitNumBox->setEnabled(
false);
ui->
ParityBox->setEnabled(
false);
ui->
StopBox->setEnabled(
false);
ui->
openButton->setText(tr(
"关闭串口"));
ui->
sendButton->setEnabled(
true);
ui->
groupBox_2->setEnabled(
true);
//连接信号槽 QObject::connect(
serial,
&
QSerialPort::readyRead,
this,
&
MainWindow::Read_Data);
}
else {
//关闭串口 serial->clear();
serial->
close();
serial->deleteLater();
//恢复设置使能 ui->
PortBox->setEnabled(
true);
ui->
BaudBox->setEnabled(
true);
ui->
BitNumBox->setEnabled(
true);
ui->
ParityBox->setEnabled(
true);
ui->
StopBox->setEnabled(
true);
ui->
openButton->setText(tr(
"打开串口"));
ui->
sendButton->setEnabled(
false);
ui->
groupBox_2->setEnabled(
false);
}}
void MainWindow::on_PidChange_valueChanged(
int value){
ui->
SetPidV->setText(
QString::number(value));}
void MainWindow::on_PidChange_sliderReleased(){
int dec=
ui->
PidChange->value();
if(
ui->
KpChoose->isChecked())
{
ui->
SetKpUi->setText(
QString::number(dec));
}
if(
ui->
KiChoose->isChecked())
{
ui->
SetKiUi->setText(
QString::number(dec));
}
if(
ui->
KdChoose->isChecked())
{
ui->
SetKdUi->setText(
QString::number(dec));
}
qDebug()<<
"ui->PidChange->"<<
ui->
SetKpUi->text();}
void MainWindow::on_PidChange_sliderPressed(){
if(
ui->
KpChoose->isChecked())
{
QString str
=
ui->
SetKpUi->text();
bool ok;
int dec
=
str.toInt(&ok,
10);
ui->
PidChange->setValue(dec);
ui->
PidChange->setMinimum(dec-
100);
ui->
PidChange->setMaximum(dec+
100);
}
if(
ui->
KiChoose->isChecked())
{
QString str
=
ui->
SetKiUi->text();
bool ok;
int dec
=
str.toInt(&ok,
10);
ui->
PidChange->setValue(dec);
ui->
PidChange->setMinimum(dec-
100);
ui->
PidChange->setMaximum(dec+
100);
}
if(
ui->
KdChoose->isChecked())
{
QString str
=
ui->
SetKdUi->text();
bool ok;
int dec
=
str.toInt(&ok,
10);
ui->
PidChange->setValue(dec);
ui->
PidChange->setMinimum(dec-
1000);
ui->
PidChange->setMaximum(dec+
1000);
}}
void MainWindow::on_pushButton_clicked(){
sendSerialPortData(
3200,
0x11,
2000);}
void MainWindow::on_pushButton_2_clicked(){
sendSerialPortData(
3200,
0x01,
2000);}
void MainWindow::on_pushButton_3_clicked(){
sendSerialPortData(
3200,
0x00,
2000);}