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

来源:互联网 发布:淘宝售后处理规则 编辑:程序博客网 时间:2024/05/16 14:12
基于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_OBJECT
public:
    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);
}
 
阅读全文
0 0
原创粉丝点击