Qt中Qchart插件实现PMW3901迷你光流模块上位机(串口通信)

Qt中Qchart插件实现PMW3901迷你光流模块上位机

光流计介绍

首先PMW3901 是一款迷你光流模块具有一下特点:

  • 体积小、重量轻 仅0.6g
  • 精度高
  • 价格便宜
  • 串口通信

PMW3901
PMW3901淘宝一搜一大片。串口通信协议如下图:
通信协议

上位机

上位机使用Qt中的Qchart插件实现,实时显示X轴和Y轴速度变化量和X轴Y轴位移(这是在调试飞机时添加的,可以用软件里一个宏USE_UAV设置)。可以直观的看出速度的变化,方便调试。主界面如下:
上位机主界面
Qchart使用方便一下代码是在窗口构造函数中添加的创建chart和坐标轴的函数:

 	m_chart = new QChart();
    QChartView *chartView = new QChartView(m_chart);
    chartView->setMinimumSize(800, 600);
    m_chart->addSeries(m_seriesX); //一共添加四条曲线
    m_chart->addSeries(m_seriesY);
    m_chart->addSeries(m_distX);
    m_chart->addSeries(m_distY);

    axisX = new QValueAxis; //设置图标坐标和文字等
    axisX->setRange(0, index_max);
    axisX->setLabelFormat("%g");
    axisX->setTitleText("sample");

    axisY = new QValueAxis;
    axisY->setRange(-indexY_range, indexY_range);
    axisY->setTitleText("speed");

    axis2Y = new QValueAxis();
    axis2Y->setRange(-50,50);
    axis2Y->setLabelFormat("%g");
    axis2Y->setTitleText("distance");

    axisY->setTickCount(11);  //设置Y轴上的网格数,11代表10个空格
    m_chart->setAxisX(axisX,m_seriesX);
    m_chart->setAxisY(axisY,m_seriesX);
    m_chart->setAxisX(axisX,m_seriesY);
    m_chart->setAxisY(axisY,m_seriesY);
    m_chart->addAxis(axis2Y,Qt::AlignRight);
    m_chart->setAxisY(axis2Y,m_distX);
    m_chart->setAxisY(axis2Y,m_distY);
    m_chart->setAxisX(axisX,m_distX);
    m_chart->setAxisX(axisX,m_distY);

    m_chart->legend()->setVisible(true);
    m_chart->legend()->setAlignment(Qt::AlignBottom);
    m_chart->setTitle("Optcial Flow Data");

然后在串口接收函数里更新chart:

/*串口数据接收处理槽函数*/
void Widget::SerialReceive()
{
    requestData = serial->readAll();
    uint8_t head,tail,sum;
#define USE_UAV 0  //通过无人机发数据还是直接用光流计

#if USE_UAV
    head = requestData[0];
    tail = requestData[12];
    flow_sum  = requestData[10];

    count++;  /*统计帧率*/

    if(index_x>index_max)
    {
        index_x=0;
        m_seriesX->clear();
        m_distX->clear();
    }
    if(index_y>index_max)
    {
        index_y=0;
        m_seriesY->clear();
        m_distY->clear();
    }
    if(head == 0xFE && tail ==0xAA) //根据协议解包
    {
        sum = requestData[2]+requestData[3]+requestData[4]+requestData[5]
                +requestData[6]+requestData[7]+requestData[8]+requestData[9];
        if(sum == flow_sum)
        {
            flow_SQUAL = requestData[11];

            dist_x = (int16_t)(requestData[2]<<8 | requestData[3]);
            dist_y = (int16_t)(requestData[4]<<8 | requestData[5]);
            flow_x = (int16_t)(requestData[6]<<8 | requestData[7]);
            flow_y = (int16_t)(requestData[8]<<8 | requestData[9]);
            m_seriesX->append(index_x,flow_x); //在曲线最末端追加一个点
            m_seriesY->append(index_y,flow_y);
            m_distX->append(index_x,dist_x);
            m_distY->append(index_y,dist_y);
            index_x++;
            index_y++;
            sum_data++;
            sum_label->setNum(sum_data);

        }
    }
    // qDebug()<<"head:"<<head<<"tail:"<<tail<<"sum:"<<sum<<"SQUAL:"<<SQUAL;
    // qDebug()<<"head:"<<head<<"tail:"<<tail<<"flow_sum:"<<flow_sum<<"sum:"<<sum;
     qDebug()<<"head:"<<head<<"tail:"<<tail<<"flow_x:"<<flow_x<<"flow_y:"<<flow_y;
#else
    head = requestData[0];
    tail = requestData[8];
    flow_sum  = requestData[6];

    count++;  /*统计帧率*/

    if(index_x>index_max)
    {
        index_x=0;
        m_seriesX->clear();
    }
    if(index_y>index_max)
    {
        index_y=0;
        m_seriesY->clear();
    }
    if(head == 0xFE && tail ==0xAA)
    {
        sum = requestData[2]+requestData[3]+requestData[4]+requestData[5];

        if(sum == flow_sum)
        {
            flow_SQUAL = requestData[7];
            flow_x = (int16_t)(requestData[3]<<8 | requestData[2]);
            flow_y = (int16_t)(requestData[5]<<8 | requestData[4]);
            m_seriesX->append(index_x++,flow_x); 
            m_seriesY->append(index_y++,flow_y);
            sum_data++;
            sum_label->setNum(sum_data);

        }
    }
    // qDebug()<<"head:"<<head<<"tail:"<<tail<<"sum:"<<sum<<"SQUAL:"<<SQUAL;
    // qDebug()<<"head:"<<head<<"tail:"<<tail<<"flow_sum:"<<flow_sum<<"sum:"<<sum;
     qDebug()<<"head:"<<head<<"tail:"<<tail<<"flow_x:"<<flow_x<<"flow_y:"<<flow_y;
#endif

}

完整工程猛戳这儿

pmw3901是一款光流传感器,适用于机器人、无人机等应用的姿态估计和导航。它能够通过感知周围环境光流变化来计算出自身的运动状态。 在使用stm32进行pmw3901的开发过程,一般需要进行以下几个步骤: 1. 硬件连接: 首先,将pmw3901与stm32芯片进行连接。pmw3901一般通过SPI接口与stm32进行通信,因此需要将其MISO、MOSI、SCK、CS等引脚与stm32相连。此外,还需要为pmw3901提供适当的电源供电。 2. 驱动程序: 接下来,需要编写相应的驱动程序来实现pmw3901的通信。可以使用stm32提供的SPI库函数来进行SPI通信,通过读写寄存器来配置pmw3901的参数和获取传感器数据。根据pmw3901的数据手册和官方提供的驱动代码,可以实现pmw3901的基本控制和数据读取。 3. 数据处理: 获取到pmw3901传感器的数据后,需要对其进行处理和解析。根据pmw3901的数据格式和数据手册的说明,可以计算出光流位移和速度等信息。可以使用滤波算法对数据进行平滑处理,以提高精度和稳定性。 4. 应用开发: 最后,根据具体的应用需求,可以将pmw3901的数据应用到相应的算法或控制。比如,在机器人导航,可以使用pmw3901的数据来实现姿态估计和位置控制,从而实现自主导航。 以上是使用stm32进行pmw3901开发的基本步骤。在实际开发过程,还需要根据具体情况进行调试和优化。同时,也可以参考其他开源项目或社区的相关资源来加快开发进度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liangtao`

请作者喝杯咖啡吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值