当前位置:首页 > 公众号精选 > 嵌入式云IOT技术圈
[导读]上次我们基于小熊派光强传感器项目实现了光强读取并在LCD上显示,文章链接如下: 基于小熊派光强传感器BH1750状态机驱动项目升级(带LCD屏显示) 这一节,我们再次对这个项目升级下,配个带可缩放曲线的上位机读取光强进行显示吧! 本节,你将了解工作中上位机

上次我们基于小熊派光强传感器项目实现了光强读取并在LCD上显示,文章链接如下:

基于小熊派光强传感器BH1750状态机驱动项目升级(带LCD屏显示)

这一节,我们再次对这个项目升级下,配个带可缩放曲线的上位机读取光强进行显示吧!

本节,你将了解工作中上位机和MCU的是如何来配合使用的。

在工作中,我们常常需要对一些传感器的某些数值进行长时间的测试和观察,以了解传感器的性能,在电子工程里,我们经常听到的测试曲线莫过于电池充放电曲线了,通过电池充放电曲线,我们很容易可以知道电池在实际使用过程中满电和馈电的状态以及电池的使用周期等等,今晚,我们就让光强通过曲线显示出来,用QT+QCustomPlot来实现,最终效果如下视频操作所示:

一、QCustomPlot简介

以下是QCustomPlot的官网:

https://www.qcustomplot.com/


QCustomPlot是一个小型的Qt画图标类,支持绘制静态曲线、动态曲线、多重坐标曲线,柱状图,蜡烛图等。只需要在项目中加入头文件qcustomplot.h和qcustomplot.cpp文件,然后使一个widget提升为QCustomPlot类,即可使用。

二、更改上节的MCU端程序

这次,我们选用串口和上位机进行通信,所以我们需要设计一个传感器和上位机通信的协议,协议如下:

序号 光强值 \r\n

当序号大于等于65535时,自动清0。

修改上节的main函数为如下:

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/*流水号*/
int serial_number = 0;
char display_buf[20] = {0};
char procol_buf[20] = {0};
/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
/*串口初始化后加这个延时,防止后面的printf打印乱码*/
HAL_Delay(200);
LCD_Init();
LCD_Clear(BLACK);//清屏为黑色
LCD_ShowString(5, 10, 240, 32, 32, "BearPi LuxTest");//显示字符串,字体大小32*32
Init_BH750();
timer_init(&lsensor.timer1, lsensor.timeout_cb, 1, 1);
timer_start(&lsensor.timer1);
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
ReadBH1750(LUX_1_MODE);

if(1 == lsensor.Conver_completed)
{
++serial_number ;

if(65535 == serial_number)
serial_number = 0 ;

sprintf(display_buf, "%d%d%d%dLux", lsensor.Lux / 1000 % 100, lsensor.Lux / 100 % 10, lsensor.Lux / 10 % 10, lsensor.Lux % 10);
LCD_ShowString(80, 50 + 24 + 32, 240, 32, 32, display_buf); //显示字符串,字体大小32*32

if(lsensor.Lux > LIGHT_SENSOR_THREHOLD)
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}

sprintf(procol_buf, "%d%d%d%d%d %d%d%d%d%d",
serial_number / 10000,
serial_number / 1000 % 100 % 10,
serial_number / 100 % 10,
serial_number / 10 % 10,
serial_number % 10,
lsensor.Lux / 10000,
lsensor.Lux / 1000 % 100 % 10,
lsensor.Lux / 100 % 10,
lsensor.Lux / 10 % 10,
lsensor.Lux % 10
);
printf("%s \r\n", procol_buf);
}

timer_loop();

}

/* USER CODE END 3 */
}

下载后,打开串口调试助手可以看到:

三、光强曲线显示上位机应用开发

下面我先用QT画出一个简单的界面(已经将QCustomPlot用上了),如下:

这里我们需要使用QT5的串口库,还有QCustomPlot库,所以在.pro中需要添加对应的库:

#-------------------------------------------------
#
# Project created by QtCreator 2020-04-13T20:46:41
#
#-------------------------------------------------

QT += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport

TARGET = BearPi_QT
TEMPLATE = app
RC_FILE += app.rc

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
main.cpp \
mainwindow.cpp \
qcustomplot.cpp

HEADERS += \
mainwindow.h \
qcustomplot.h

FORMS += \
mainwindow.ui

在mainwindow.h中,需要添加头文件及变量还有相关的普通函数和槽函数的定义:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QDebug>
#include <QMainWindow>
#include <QSerialPort> //提供访问串口的功能
#include <QSerialPortInfo> //提供系统中存在的串口的信息
#include "qcustomplot.h" //包含Qcustomplot库

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
/*初始化串口参数*/
void Init_Serial_Para();
/*传感器数据画图前的处理*/
void sensor_data_preprocess(int x, int y) ;
/*画曲线函数*/
void Sensor_Draw_Plot(QCustomPlot *customPlot, QVector<double> x, QVector<double> y);

private:
Ui::MainWindow *ui;
QSerialPort *Serial ;
long last_index ;
QVector<double> display_x;
QVector<double> display_y;
QString Serial_Port , Serial_Bauardate,Serial_PariteyBit,Serial_DataBit,Serial_StopBit ;

private slots:
void Update_Serial_Port(QString Currnet_Select);
void Update_Serial_Baurdrate(QString Currnet_Select);
void Update_Serial_ParityBit(QString Currnet_Select);
void Update_Serial_DataBit(QString Currnet_Select);
void Update_Serial_StopBit(QString Currnet_Select);
void on_Connect_Device_clicked();
void on_Disconnect_Device_clicked();

void cmd_recv_process();
};

#endif // MAINWINDOW_H

在mainwindow.cpp太长我就不全贴出来了,解读一下核心的实现思路:

1、用户配置完串口参数,然后 连接信号与槽:

connect(this->Serial,SIGNAL(readyRead()),this,SLOT(cmd_recv_process()));

2、当上位机接受到MCU端发来的数据时,会触发readyRead()信号,进而调用cmd_recv_process()槽函数,实现如下:

/*数据接收*/
void MainWindow::cmd_recv_process()
{
QString data ;
QStringList list ;
/*光强传感器序号*/
QString Sensor_Serial_Number ;
/*光强传感器光强值*/
QString Sensor_light_Value ;
long int s1 = 0, v1 = 0;
last_index =0;
if(Serial->canReadLine())
{
QByteArray temp = Serial->readAll();

if(!temp.isEmpty())
{
data = temp ;
list = data.split(" ");
if(3 == list.length())
{
Sensor_Serial_Number = list[0];
Sensor_light_Value = list[1];
/*取到对应参数后立刻开始画图*/
s1 = Sensor_Serial_Number.toInt();
v1 = Sensor_light_Value.toInt();
ui->light_sensor_value->setText(QString::number(v1));
if (last_index == 0 || (last_index < s1 && s1 - last_index >=1 && s1 - last_index <= 10 ))
{
last_index = s1;
sensor_data_preprocess(s1,v1);
}
}
}
}
}

这里会判断是否满足读取一行数据的条件,如果满足则会读取一行数据,接下来对数据进行分割,取出传感器上报的序号、光强两个字段,序号作为曲线图的横坐标,光强作为曲线图的纵坐标进行显示。

例程下载

链接:https://pan.baidu.com/s/1ujo0TE3pS-1RFVvylnCyKQ
提取码:48jp
复制这段内容后打开百度网盘手机App,操作更方便哦

公众号粉丝福利时刻

这里我给大家申请到了福利,本公众号读者购买小熊派开发板可享受9折优惠,有需要购买小熊派的朋友,淘宝搜索即可,跟客户说你是公众号:嵌入式云IOT技术圈 的粉丝,立享9折优惠!

往期精彩

网红物联网开发板小熊派使用评测

超轻量级网红软件定时器multi_timer(51+stm32双平台实战)

基于小熊派光强传感器BH1750实践(multi_timer+状态机工程应用)

基于小熊派光强传感器BH1750状态机驱动项目升级(带LCD屏显示)

若觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

上位机串口通信是指在上位机(通常是计算机或微控制器)与外部设备之间通过串行通信协议进行数据传输和通信的过程。在串口通信中,数据以位为单位按顺序传送,通常使用一个或两个物理线路(通常是两条线)来实现数据的发送和接收。

关键字: 上位机 串口通信

摘要:以地铁BAS实训系统为研究对象,按照集中管理、分散控制的设计思想,基于Niagara软件平台设计和搭建了一套3层分布式地铁BAS实训系统,分为管理层、控制层、现场层,包含空调送回风和智能照明两个监控子系统。首先建立...

关键字: BAS实训系统 上位机 监控

摘要:基于传统直角坐标机器人控制技术,以蓄电池极板连续生产线的码垛机器人为应用案例,根据设备需求、机器人控制原理和系统状态机的设计,介绍了一种通用的、灵活的、开发周期短的多轴直角坐标机器人控制方法。该机器人经过实践,验证...

关键字: 直角坐标机器人 状态机 控制系统

无论是水厂、污水厂还是供水、排水、污水泵站的运行核心就是控制系统,而控制系统的核心就是以PLC为主体的自动控制系统。关于自控系统的控制方案有很多种,但并不是都有实效。现在,就以水厂中的沉淀池吸泥桁车为例子,讲一讲智慧水务...

关键字: 上位机 现场总线

▼点击下方名片,关注公众号▼欢迎关注【玩转单片机与嵌入式】公众号,回复关键字获取更多免费资料。回复【加群】,限时免费进入知识共享群;回复【3D封装库】,常用元器件的3D封装库;回复【电容】,获取电容、元器件选型相关的内容...

关键字: 单片机 状态机 传感器中

摘 要 :设计一辆基于单片机的手机可控多功能智能小车,小车与手机采用无线传输技术通信。智能小车主要分为手机 APP、控制器模块、传感器模块、执行器模块以及报警模块五个部分。传感器模块感知外部环境信息并把数据传送至控制器,...

关键字: APP 智能控制 无线监控 传感技术 上位机 报警

在单片机裸机的编程方法中,状态机的方法是比较好的,经典的比如按键的检测判断等。其实,有很多地方可以使用这种思想,比如传感器的数据采集。因为单片机不可能一直等待着运行,那样的效率是很低的,通常都是结合fsmtimer的方式...

关键字: 单片机 状态机

这两天看文的人比较少,先来分享一篇非常简单的关于虚拟串口软件的使用的小短文。在编写串口上位机时,需要进行调试。一种方式是与下位机进行通信进行测试;另一种方式是借助虚拟串口软件来进行测试。虚拟串口软件使用演示虚拟串口软件是...

关键字: 上位机 软件 调试

摘 要 :随着汽车保有量的飞速发展,城市交通所面临的拥堵问题倍受人们关注。针对这一问题,提出一种基于 ZigBee 无线网络的智能交通系统。该系统可实时采集道路信息,利用 ZigBee 模块进行信息传输,通过上位机实现...

关键字: 智能交通 Zigbee 无线网络 车流检测 上位机 车载终端

摘要:针对目前市场上存在的一些电磁继电器参数检测仪器的缺点,为了能够精确采集电磁继电器的吸合电压等主要参数,采用ARM技术和上、下位机方法,设计了一款基于ARMCortex-M3芯片STM32F103ZET6单片机控制的...

关键字: STM32 电磁继电器 检测仪 上位机
关闭
关闭