基于opencv的图像分析,PID算法,串口发送,单片机接收,输出脉冲继而控制步进电机转动

2019-04-15 18:56发布

基于opencv的图像分析串口发送,单片机接收,输出脉冲继而控制步进电机转动 mainwindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H#include #include #include #include #include "imagebuffer.h"#include "wlinkusbcamera.h"using namespace cv;#includenamespace 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 #include "opencv2highguihighgui.hpp"#include #includeMainWindow::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()<"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"< 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]"<<"["<","<","<"]"<<"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()<data ; qDebug()<cols <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);}