1. Qt上位机
分为两个线程,分别是采集线程和绘制线程。
1.1 采集线程
采集线程面向过程,从buffer(C风格数组)中读取数据,并写入txt文本文件中。数据采集卡需要读取三个通道,分别代表编码器的 A 相,编码器的 B 相,以及同步信号。缓冲区的数据是同一时刻三个通道的数据是相邻的。然后通过 A 相和 B 相的脉冲数计算转过的角度,A 相在 B 相前角度就是正,A 相在 B 相后角度就是负。记录当前时间与开始时间的差值,作为绘制的 x 坐标,记录当前的角度,作为 y 坐标。这个 x 坐标和 y 坐标是 samplingForce 这个对象的成员变量。
ui 线程通过访问这个 samplingForce 的类成员来获取绘制的点。这中间涉及到线程安全问题以及面向对象的问题。
1.2 UI 采集线程
首先是通过 QChart 来绘制界面。通过 QPen 来设置曲线的参数,添加 QLineSeries 曲线用于指示,添加 QSplineSeries 用于绘制,这个是平滑曲线。这两条曲线要设置曲线的绘制参数,把前面的 pen 设置进去。然后就是要新建两个坐标轴,并把这两条坐标轴添加到创建的 QChart 里面,同时也要把两条曲线添加到 QChart 里面。最后再把坐标轴和曲线关联起来。
通过定时器来不断地往曲线上添加点,这里需要读取采集线程给出的绘制点。为了防止临界资源的冲突,这里肯定不能只加一般的锁因为采集线程不能阻塞,阻塞了就会丢点。所以需要构建一个共享类来分别处理读和写的情况,总结来说要注意以下几点:
- 采集线程要修改数据,所以调用共享类修改数值的成员函数,这个函数要使用写锁
QWriteLocker locker(&rwLock);
。 - ui绘制线程要访问数据,所以调用共享类返回数值的成员函数,这个函数要使用读锁
QReadLocker locker(const_cast<QReadWriteLock*>(&rwLock));
,同时添加const
关键字修饰,以确保数据不被修改。 - Qt 中的读写锁为
QReadWriteLock rwLock
。
在Qt中实现读写锁可以通过使用QReadWriteLock
类来完成。QReadWriteLock
提供了一个读写锁机制,允许多个读线程同时访问资源,但写线程访问资源时必须独占该资源。下面是一个简单的示例,展示了如何在Qt中使用读写锁来保护共享数据,以确保线程安全。
示例代码
假设我们有一个简单的应用程序,包含一个采集线程和一个UI线程,它们需要共享一些数据。
共享数据类
首先,定义一个包含共享数据的类,并使用QReadWriteLock
来保护数据的访问。
1 |
|
采集线程
接下来,定义一个采集线程,该线程定期更新共享数据。
1 |
|
UI线程
定义一个UI线程,该线程定期从共享数据中读取值并显示。
1 |
|
主函数
最后,在主函数中启动采集线程和UI线程。
1 |
|
说明
QReadWriteLock
:用于保护共享数据的读写操作。QWriteLocker
和QReadLocker
:分别用于写操作和读操作的锁定。QWriteLocker
会在构造时自动获取写锁,在析构时释放写锁;QReadLocker
则是在构造时获取读锁,在析构时释放读锁。CollectorThread
:模拟数据采集过程,每秒更新一次共享数据。MainWindow
:模拟UI线程,每秒从共享数据中读取值并更新显示。
通过这种方式,可以有效地实现线程间的同步,确保数据的一致性和线程的安全性。
2. ROS篮球机器人
3. SRTP项目
分为移动监测和数据分析两个部分。
3.1 移动监测
设计了基于 stm32 的原型机,主要有以下几个主要组成部分:
- M702七合一空气传感器:二氧化碳浓度(ppm),甲醛浓度(ug/m³),TVOC(总挥发性有机物)浓度(ug/m³),PM2.5浓度(ug/m³), PM10浓度(ug/m³),温度(℃),湿度(%)
- ATK M751 4G DTU
- STM32单片机
- GPS/BD 双模定位模块
进行了集成化,同时选用了功耗更低的模块:
GPRS模块 SIM800C:SIM800C是一款四频GSM/GPRS模块,为城堡孔封装。其性能稳定,外观小巧,性价比高,能满足客户的多种需求。SIM800C工作频率为GSM/GPRS850/900/1800/1900MHz,可以低功耗实现语音、SMS和数据信息的传输。
特性 说明 省电 SLEEP模式下的耗流为0.6毫安 (AT+CFUN=0 ) GPRS数据特性 GPRS 数据下行传输:最大 85.6 kbpsGPRS
数据上行传输:最大 85.6 kbps
编码格式:CS-1, CS-2, CS-3 和 CS-4
支持通常用于PPP连接的PAP(密码验证协议)协议
内嵌 TCP/IP 协议
支持分组广播控制信道(PBCCH)GPS模块 Ublox M8:
M702空气传感器
STM32单片机
TCP服务器配置
使用记事本打开并修改SD卡里的TCPconfig.cfg文件,其第一行为TCP服务器IP地址,第二行为端口号,配置好后将SD卡插回PCB板,将各个模块连接好通电即可。
字节 | 名称 | 说明 |
---|---|---|
B1 | 帧头 1 | 固定值 3Ch |
B2 | 帧头 2 | 固定值 02h |
B3 | 数据 | eCO2 高字节 |
B4 | 数据 | eCO2 低字节 |
B5 | 数据 | eCH2O 高字节 |
B6 | 数据 | eCH2O 低字节 |
B7 | 数据 | TVOC 高字节 |
B8 | 数据 | TVOC 低字节 |
B9 | 数据 | PM2.5 高字节 |
B10 | 数据 | PM2.5 低字节 |
B11 | 数据 | PM10 高字节 |
B12 | 数据 | PM10 低字节 |
B13 | 数据 | Temperature 整数部分 |
B14 | 数据 | Temperature 小数部分 |
B15 | 数据 | Humidity 整数部分 |
B16 | 数据 | Humidity 小数部分 |
B17 | 校验和 | 校验和 |
B18 | 数据 | 纬度最低字节 |
B19 | 数据 | 纬度低字节 |
B20 | 数据 | 纬度高字节 |
B21 | 数据 | 纬度最高字节 |
B22 | 数据 | 经度最低字节 |
B23 | 数据 | 经度低字节 |
B24 | 数据 | 经度高字节 |
B25 | 数据 | 经度最高字节 |
校验和 B17(8位无符号整数) 等于: B1+B2+······ B16 的值。
当温度的数据 B13 的 bit7=1 时, 代表是负温度, B13 的 bit7=0 时,是正温度。 例如, 当 B13=9Bh 时, 此时 bit7=1, 表示是负温度, 此时实际温度就是-27℃ ;如果 B13=1Bh,此时 bit7=0,代表是正温度, 此时实际温度就是 27℃ 。
温度和湿度的小数部分分辨率都是0.1,也就是说正常情况下,他们都是0到9的整数。
经纬度都是32位有符号整数(int32_t)。
当GNSS模块收到卫星信号的时候,获取到的传感器数据会保存在以当前日期命名的文本文件中(例如:2020-12-08.txt),文件中的内容如下:
2020-12-08 00:00:32 623 17 124 137 170 14.5 48.0 32.161813 118.686683
2020-12-08 00:00:34 623 17 124 138 171 14.5 48.0 32.161812 118.686683
2020-12-08 00:00:36 623 17 124 138 171 14.5 48.1 32.161809 118.686682
2020-12-08 00:00:38 623 17 124 139 173 14.5 48.1 32.161806 118.686681
2020-12-08 00:00:40 625 17 125 140 174 14.5 48.2 32.161804 118.686679
每一行从左到右的数据依次为:时间,二氧化碳浓度(ppm),甲醛浓度(ug/m³),TVOC浓度(ug/m³),PM2.5浓度(ug/m³), PM10浓度(ug/m³),温度(℃),湿度(%),纬度,经度。