-
图像分析处理技术是计算机视觉领域的核心,涉及图像的获取、处理、分析和理解。随着人工智能和机器学习技术的飞速发展,图像分析处理技术在各行各业中扮演着越来越重要的角色。本文将探讨图像识别、图像分析以及图像处理技术的特点、应用场景和技术方案,并展望其未来的发展趋势与挑战。一、图像识别技术图像识别是图像分析处理技术的一个重要分支,它涉及到从图像中识别出特定的对象、场景或活动。这一技术的核心是模式识别,即通过算法识别图像中的模式并将其与已知的模式进行匹配。特点自动化:自动识别图像中的对象,无需人工干预。高效率:能够快速处理大量图像数据。高准确率:随着模型训练的深入,识别准确率可以非常高。可扩展性:可以应用于不同的图像识别任务,如面部识别、车牌识别等。应用场景面部识别:用于安全验证和个人身份确认。物体识别:在零售、物流等领域自动识别商品。场景识别:在自动驾驶中识别道路和交通标志。典型技术方案卷积神经网络(CNN):一种深度学习模型,特别适用于图像识别任务。支持向量机(SVM):一种监督学习模型,用于分类和识别。深度信念网络(DBN):由多个受限玻尔兹曼机堆叠而成的深度学习模型。二、图像分析技术图像分析不仅包括图像识别,还包括对图像内容的深入分析和理解。图像分析通常涉及到图像的预处理、特征提取、模式识别和决策制定。特点复杂性:分析过程涉及多个步骤,需要复杂的算法。多维度:不仅识别图像中的对象,还分析其属性和关系。适应性:能够适应不同的图像条件和环境。应用场景医疗图像分析:在放射学中分析X光片、CT扫描和MRI图像。卫星图像分析:用于地理信息系统(GIS)和环境监测。视频监控分析:在安全监控中分析视频流以检测异常行为。典型技术方案图像分割:将图像分割成多个区域或对象的技术。特征提取:从图像中提取关键特征,如边缘、角点等。机器学习算法:包括决策树、随机森林等,用于图像分析的分类和回归任务。三、图像处理技术图像处理技术是图像分析处理技术的基础,它涉及到对图像数据的修改、改善和转换,以满足特定的应用需求。特点多样性:处理方法多样,可以根据需求选择不同的技术。实时性:许多图像处理操作可以实时进行,适用于视频流等动态图像。可定制性:可以根据具体的应用场景定制处理流程。应用场景图像增强:提高图像的可见性,如对比度增强、亮度调整等。滤波:去除图像噪声,如高斯滤波、中值滤波等。图像变换:进行图像的几何变换,如旋转、缩放、裁剪等。典型技术方案图像滤波器:用于平滑图像或突出图像的某些特征。图像变换算法:如傅里叶变换、小波变换等,用于分析图像的频域特性。图像增强技术:包括直方图均衡化、锐化等,用于改善图像的视觉质量。四、技术对比虽然图像识别、图像分析和图像处理紧密相关,但它们各自有不同的侧重点和应用场景:图像识别:侧重于从图像中识别出特定的对象或场景;通常需要较高的计算资源,依赖于复杂的算法和模型。图像分析:不仅识别图像内容,还深入分析图像的特征和属性;侧重于理解和解释图像内容,可能涉及到复杂的决策过程。图像处理:更多关注图像质量的改善和信息的提取,不一定需要复杂的模型;更多是技术性的,关注图像数据的修改和转换。尽管存在差异,但这些技术经常相互融合,共同解决复杂的图像分析问题。例如,图像处理可以作为图像识别和分析的预处理步骤,而图像分析的结果又可以用于指导图像处理的方向。五、应用方向图像分析处理技术的应用领域非常广泛,以下是一些主要的应用方向:工业自动化在工业自动化中用于质量控制、机器人导航和装配线监控。通过图像识别和分析,机器可以自动检测产品缺陷、分类物品和执行精确的操作。医疗健康在医疗领域,图像分析处理技术用于诊断、治疗规划和手术辅助。例如,通过分析医学影像,医生可以更准确地识别疾病和制定治疗方案。安全监控安全监控是图像分析技术的另一个重要应用领域。通过实时视频分析,可以检测异常行为、入侵者和其他安全威胁。社交媒体与娱乐在社交媒体和娱乐行业,图像分析用于内容推荐、用户交互和增强现实(AR)体验。例如,通过面部识别技术,用户可以在社交媒体上创建有趣的滤镜和效果。交通管理图像分析在交通管理中用于交通流量监控、事故检测和交通违规识别。这有助于提高道路安全性和交通效率。农业监测在农业领域,图像分析用于作物监测、病虫害检测和产量预测。通过分析卫星图像和无人机拍摄的图像,农民可以更好地管理作物和资源。六、未来趋势与挑战图像分析处理技术正在快速发展,同时也面临着一些挑战。技术发展趋势更深层次的网络结构:随着计算能力的提升,更深的网络结构正在被开发,以提高识别和分析的准确性。端到端学习:从输入到输出的端到端学习正在成为趋势,减少了对中间特征工程的依赖。多模态学习:结合视觉信息和其他类型的数据(如文本、声音)进行多模态学习。面临的挑战数据隐私:随着图像数据的大量收集和分析,如何保护个人隐私成为一个重要问题。算法偏见:机器学习模型可能会学习到训练数据中的偏见,导致不公平的结果。可解释性:深度学习模型通常被认为是“黑箱”,提高模型的可解释性是一个挑战。潜在的解决方案隐私保护技术:如差分隐私和联邦学习,可以在不泄露个人数据的情况下进行学习。公平性算法:开发新的算法来减少模型的偏见,提高决策的公平性。模型解释性:研究新的技术来解释深度学习模型的决策过程。七、总结图像分析处理技术是当今科技领域中最活跃和最有前景的领域之一。从基础的图像处理到复杂的图像识别和分析,这些技术正在不断进步,并被应用于各种实际问题中。图像分析处理技术对于提高生产效率、改善生活质量、增强安全保障等方面发挥着重要作用。不同的技术方案针对不同的应用场景,显示了这一领域的多样性和创新性。随着技术的发展,我们也必须面对数据隐私、算法偏见和模型可解释性等挑战。图像分析处理技术将继续发展,新的技术、算法和应用将不断涌现,为社会带来更多的价值。
-
是啥问题呢?使用的固件是1471
-
一、前言1.1 项目介绍项目设计里用到的全部工具软件都可以在这里下载。cid:link_2【1】项目开发背景随着现代生活节奏的加快,人们对于健康管理的需求日益增长,尤其是对于睡眠健康的关注度显著提升。良好的睡眠质量不仅关系到个人的精神状态,更直接影响着工作和学习效率乃至整体生活质量。然而,快节奏的生活压力、不规律的生活作息等因素导致越来越多的人遭受睡眠障碍的困扰。传统的睡眠监测方式通常需要佩戴设备或接触式传感器,这可能会干扰到用户的自然睡眠状态,从而影响监测结果的准确性。因此,开发一种非接触式的睡眠监测系统,成为了提高睡眠质量研究的重要方向之一。非接触式睡眠监测技术的发展,得益于近年来毫米波雷达技术的进步。毫米波雷达具有高精度、强穿透力的特点,可以在不直接接触人体的情况下,精准地捕捉到人体微动,如呼吸和心跳等细微动作。这种技术的应用,不仅可以避免传统监测手段可能带来的不适感,还能在用户不知情的状态下进行连续监测,保证了数据的真实性和有效性。与此同时,物联网技术的发展使得数据的远程传输与分析成为可能,进一步推动了智能健康监测系统的普及。本项目正是基于这样的背景下展开的。它利用了60GHz毫米波雷达技术,结合高性能的STM32微控制器,设计了一套完整的非接触式睡眠监控系统。该系统不仅能准确地获取用户的睡眠信息,还能通过Wi-Fi连接云端,让用户可以通过手机应用程序随时查看自己的睡眠报告。此外,系统还具备异常生理指标报警功能,能够在第一时间提醒用户注意健康状况,为用户提供了一个全方位、智能化的健康管理方案。通过这一创新性的解决方案,期望能够帮助更多人改善睡眠质量,提升生活质量。设备安装角度:【2】设计实现的功能(1)人体存在感知与运动感知:通过使用60GHz频段的毫米波雷达模块,系统能够感知房间内是否存在人体以及人体的微小运动,如呼吸和心跳的变化。(2)睡眠状态监测:系统能够根据睡眠过程中身体的运动幅度变化和呼吸心率的变化,实时判断目标的睡眠状态,并在睡眠周期结束后提供一个综合的睡眠评分。(3)生理指标检测:系统能够检测并记录睡眠者的心率、呼吸频率等重要生理指标,这些数据有助于分析睡眠质量。(4)远程数据上传与查看:系统集成了Wi-Fi模块,可以将监测到的睡眠数据上传到华为云物联网平台,用户可以通过智能手机应用程序远程查看每天的睡眠质量报告和其他生理指标。(5)异常情况报警:当检测到的生理指标超出预设的安全阈值时,系统会触发报警机制,及时通知用户或监护人可能存在健康风险。(6)本地数据显示:系统配备了1.44寸SPI协议的TFT LCD显示屏,用于实时显示监测到的生理指标及环境相关信息,便于用户即时查看。(7)体温检测:通过集成MLX90614红外体温传感器,系统能够检测人体体温,并将其作为一项重要的生理参数纳入睡眠质量评估体系中。【3】项目硬件模块组成(1)主控单元:选用STM32F103RCT6微控制器作为核心处理单元,负责接收来自各传感器的数据,并处理和控制系统的各项功能。(2)毫米波雷达模块:采用60GHz频段的R60ABD1毫米波雷达模块,用于非接触式地检测人体的存在、呼吸频率和心率等生理信号。(3)无线通信模块:集成ESP8266-Wi-Fi模块,实现数据的无线传输功能,确保睡眠数据能够实时上传至华为云物联网平台。(4)显示模块:采用1.44寸TFT LCD显示屏,分辨率为128x128像素,通过SPI协议与主控单元通讯,用于显示监测到的生理指标和环境信息。(5)体温检测模块:采用MLX90614红外体温传感器,用于无接触地测量人体体温,提供额外的健康监测数据。(6)电源管理模块:采用外置的5V稳压电压,包括电源转换电路和电池管理电路,确保整个系统能够稳定运行,并为各个模块提供所需电压。(7)报警模块:设计蜂鸣器声音形式的报警装置,当系统检测到异常生理指标时,能够及时提醒用户。【4】需求总结项目:基于STM32+微波雷达设计的非接触式睡眠监控系统1. 可以实现 人体存在感知、人体运动感知、根据睡眠过程中的身体运动幅度变化和呼吸心率变化,对目标的睡眠状态、呼吸心跳频率进行实时判断,在一段睡眠过程结束后输出睡眠评分呼吸、能够检测心率、睡眠时长、睡眠质量等生理指标(此功能采用60GHz频段的毫波雷达来实现)2. 可以实现能将数据通过 ESP8266-WIFI上传到华为云物联网云平台、设计手机APP可以远程查看每天的睡眠质量、生理指标、环境相关信息。3. 可以实现当检测到的生理指标数据超过阈值时,系统发出报警提醒。 4. 可以实现能在本地LCD显示屏显示监测到的生理指标、环境相关信息。5. 支持检测人体体温。 硬件选型:主控芯片选择 STM32F103RCT6LCD显示屏采用1.44寸 SPI协议的 TFT显示屏,分辨率是128x128。人体体温检测采用MLX90614红外体温传感器。人体的呼吸、心率、采用60G毫米波 生物感知雷达R60ABD1模块来实现检测。呼吸睡眠雷达基于毫米波雷达体制实现人体生物存在感知及人体运动感知,持续记录人体存在情况,根据睡眠过程中的身体运动幅度变化和呼吸心率变化,对目标的睡眠状态、呼吸心跳频率进行实时判断,在一段睡眠过程结束后输出睡眠评分,根据相关睡眠参数的输出结合到健康康养的应用上。1.2 设计思路设计思路源于对现代人睡眠健康需求的关注以及对现有睡眠监测技术局限性的思考。在设计之初,注意到传统的睡眠监测手段往往依赖于接触式的穿戴设备,这种方式虽然能够提供较为精确的数据,但却有可能影响用户的自然睡眠状态。因此,设计目标是创造一个非侵入式的睡眠监控系统,能够让用户在自然的睡眠环境中得到准确而有效的监测。为了实现这一目标,选择了60GHz频段的毫米波雷达技术作为主要的监测手段。毫米波雷达具有非接触、高分辨率和强穿透性等特点,非常适合用来监测人体微弱的生理信号,如呼吸和心跳。通过算法优化,能够从雷达回波中提取出稳定的呼吸和心跳信号,并据此评估睡眠质量和生理指标。考虑到用户体验的重要性,决定将系统与互联网技术相结合,通过ESP8266-Wi-Fi模块将睡眠数据上传至云端,方便用户通过智能手机应用程序随时随地查看自己的睡眠报告。同时,为了应对突发状况,设计了阈值报警机制,当检测到异常生理指标时,系统能够立即向用户发出警告,以确保用户的安全。硬件选型方面,选择了性能稳定且广泛使用的STM32F103RCT6作为主控芯片,以确保系统的可靠性和可扩展性。为了直观展示数据,选用了1.44寸的TFT LCD显示屏,它可以清晰地显示监测到的各项生理指标和环境信息。此外,还加入了MLX90614红外体温传感器,以便系统能够监测用户的体温变化,进一步完善健康监测功能。总体的设计思路是在不干扰用户正常生活的情况下,利用先进的毫米波雷达技术和物联网平台,创建一个能够全天候监测睡眠状态、生理指标,并及时反馈给用户的智能系统。这样不仅能够帮助用户更好地了解自己的睡眠质量,还能在出现异常时提供及时的帮助,从而提升整体的生活品质。1.3 系统功能总结功能类别描述人体存在感知利用60GHz毫米波雷达检测房间内是否有人存在。运动感知感知人体的微小运动,如呼吸和心跳。睡眠状态监测根据身体运动幅度变化和呼吸心率变化实时判断睡眠状态。生理指标检测记录并分析心率、呼吸频率等重要生理指标。远程数据上传通过ESP8266-Wi-Fi模块将监测数据上传至华为云物联网平台。移动端查看用户可以通过手机应用程序远程查看睡眠质量报告和其他生理指标。异常报警当检测到的生理指标超过设定阈值时,系统会发出报警提醒。本地数据显示通过1.44寸TFT LCD显示屏实时显示监测到的生理指标和环境信息。体温检测使用MLX90614红外体温传感器检测人体体温,并将其纳入健康监测数据中。1.4 开发工具的选择【1】设备端开发STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。【2】上位机开发上位机的开发选择Qt框架,编程语言采用C++;Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt能轻松创建具有原生C++性能的连接设备、用户界面(UI)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。1.5 模块的技术详情介绍【1】ESP8266-WIFI模块ESP8266是一款广受欢迎的低成本、低功耗的Wi-Fi模块,广泛应用于物联网(IoT)领域。它由乐鑫科技(Espressif Systems)开发,最初作为一款简单易用的无线模块推向市场,但因其强大的功能和灵活性迅速获得了开发者们的青睐。ESP8266内置了Tensilica L106超低功耗32位微处理器,主频最高可达160MHz,并且拥有512KB的SRAM,这使得它不仅能够作为一个简单的Wi-Fi模块使用,还可以作为独立的微控制器来执行复杂的任务。ESP8266模块支持IEEE 802.11 b/g/n标准,能够工作在2.4GHz频段上。它具有多种工作模式,包括Station模式(客户端)、Access Point模式(热点)以及Station+AP模式(同时作为客户端和热点)。这意味着它可以连接到现有的Wi-Fi网络,也可以自己创建一个Wi-Fi热点供其他设备连接,极大地增加了其在不同应用场景中的适用性。对于开发者而言,ESP8266的一个重要优势在于其丰富的开发资源和支持。乐鑫科技提供了详细的开发文档,包括硬件接口说明、固件升级指南和API参考手册等。此外,ESP8266还支持多种编程语言,如C/C++和Lua,同时还有成熟的开发框架如Arduino IDE的支持,使得开发者能够快速上手,并利用各种库函数简化开发流程。ESP8266的低功耗特性也是一大亮点,它提供了多种省电模式,可以根据实际应用需求调整工作状态,以延长电池寿命。这对于那些依赖电池供电的物联网设备来说尤为重要。ESP8266凭借其出色的性价比、强大的功能、易于开发的特性以及广泛的社区支持,已经成为许多DIY项目、智能家居设备和小型物联网应用的理想选择。无论是作为独立的微控制器还是作为Wi-Fi模块,ESP8266都能够满足大多数物联网项目的需求。【2】MLX90614红外体温传感器MLX90614红外体温传感器是由Melexis公司生产的一款高性能、非接触式温度测量传感器。这款传感器集成了红外温度测量功能与环境温度测量功能于一体,适用于需要快速、准确测量物体表面温度的应用场合。由于其非接触式的特点,MLX90614特别适合用于医疗领域,如监测人体体温,以及其他工业或商业用途,例如食品温度检测、设备过热保护等。MLX90614的工作原理基于红外辐射理论。所有物体都会发射红外辐射,其强度与物体的温度成正比。MLX90614通过检测目标物体发射的红外辐射能量,并结合传感器所在环境的温度,计算出目标物体的表面温度。这款传感器具有较高的灵敏度,能够检测到非常微小的温度变化,并且具有较好的响应速度。从硬件角度来看,MLX90614采用了SMD(Surface Mount Device)封装,使其易于集成到各种设备中。它具有数字I²C接口,可以方便地与微控制器或其他数字系统进行通信。此外,MLX90614还提供了不同的视场角版本,允许用户根据具体的应用需求选择最适合的角度,从而获得最准确的测量结果。在使用MLX90614时,需要注意几个关键参数。首先是距离系数(Distance-to-Spot Size Ratio),即传感器与目标之间的距离与目标面积直径之比。这个参数决定了传感器的有效测量区域大小。其次是传感器的温度测量范围,一般为-70°C至+380°C,足以覆盖大部分日常应用。此外,MLX90614还具备较高的测温精度,通常在±0.5°C左右,这使得它在医疗和工业应用中具有很高的实用性。对于开发人员来说,MLX90614的另一个优点是其易于集成。Melexis提供了详尽的技术文档和支持,包括电路设计指南、编程示例等资源,使得开发者能够快速地将MLX90614集成到他们的产品中。此外,市面上也有许多现成的开发板和库文件,可以帮助开发者简化开发流程,加速产品的上市时间。综上所述,MLX90614红外体温传感器以其高精度、非接触式测量的特点,在多个行业中得到了广泛应用,尤其是在需要快速、准确温度读数的场合。【3】微波雷达模块生物感知雷达R60ABD1模块是一款基于60GHz毫米波雷达技术的产品,专为人体呼吸心率感知及睡眠评估而设计。它采用FMCW(调频连续波)雷达体制,能够针对特定场合内的人员进行呼吸心率频率的输出,并结合长时间的睡眠姿态体动采集,及时上报人员的睡眠状态和历史记录。模块的一发三收天线形式使得它适合于置顶安装模式,能够精准扫描人体全身的动作层析,实现人体动静态时的睡眠探测和不同姿态下的呼吸心率采集。该模块的工作原理基于雷达天线发射电磁波信号,并接收目标反射回来的回波信号。通过雷达处理器解析不同接收天线回波信号的波形参量之间的相位差和能量变化,从而反馈目标运动的微动能量变化、距离、方向和速度等信息。这使得R60ABD1模块能够探测目标的运动状态和胸腔呼吸起伏的频次状态。在雷达探测范围内,即便是轻微的手部晃动或呼吸引起的胸腔起伏等微小运动,也能够被模块捕捉到。R60ABD1模块具有多种功能,包括运动检测、呼吸探测、呼吸心率频率采集等功能。模块能够检测到诸如走动或小幅度手晃动等运动,并触发有人状态的指示。当人处于静止状态时,模块也能检测到由呼吸引起的胸腔起伏,并维持有人状态的输出。更重要的是,它能统计呼吸心跳引起的胸腔起伏,并输出每分钟的呼吸心跳数值。这些功能使得该模块在全屋智能、智能家电、区域人员探测和睡眠看护等领域有着广泛的应用前景。该模块的电气特性包括工作电压在4.6V至6V之间,典型工作电流为93mA,工作温度范围从-20°C至+60°C,存储温度范围则从-40°C至+105°C。其RF性能方面,工作频率位于61GHz至61.5GHz区间,发射功率不超过6dBm。天线增益为4dBi,水平和垂直波束宽度均为20°(-3dB点)。R60ABD1模块提供了标准的UART通信接口,并支持涂鸦协议,便于与其他设备集成。模块尺寸小巧,体积仅为35mm×31mm×7.5mm,并配有双排插针接口,接口间距为2.0mm。这些接口包括电源输入、地、串口接收和发送端、以及多个可定义的通用I/O引脚。其中,部分引脚可用于输出有人/无人状态、活跃/静止状态、体征参数等信息。此外,模块还支持多种参数设置,如人体存在开关、呼吸探测开关、心跳探测开关、睡眠探测开关以及探测模式切换开关(实时探测/睡眠模式)。这些设置使得模块可以根据不同应用场景的需求进行灵活配置。在安装方面,R60ABD1模块推荐倾斜安装,并且平行于扫描面的距离不超过1.5米。特别是用于睡眠呼吸心跳探测时,雷达应安装在床头正上方1米的高度,向下倾斜45°对着床中间,确保雷达与人体胸腔的距离在1.5米范围内,以确保雷达正常进行探测。1.6 微波雷达安装说明生物感知雷达R60ABD1模块的安装需要遵循特定的指导原则以确保其最佳性能。首先,雷达模块应该朝向为丝印标识的方向进行安装,这意味着在安装时需要确保雷达的正面朝向正确。为了达到理想的探测效果,R60ABD1雷达模块建议采用倾斜安装的方式,倾斜角度应在30到45度之间。这种安装方式有助于雷达的波束覆盖到所需的探测区域,并且可以减少因环境因素引起的误报。在确定雷达的具体安装位置时,建议将雷达安装在床头正上方大约1米的高度处,这样可以确保雷达的主要波束能够覆盖到床的中心区域。这样做是为了确保雷达可以有效地探测到床上人的呼吸和心跳活动,同时也能够监测到人体的其他微动。安装高度的选择也是基于雷达波束覆盖范围的考虑,以确保人体存在检测的最大距离为约2.5米,而人体呼吸频率检测的最大距离约为1.5米。除了正确的安装位置和角度外,还需要注意避免雷达前方出现明显的金属或电解质遮挡物。这是因为毫米波雷达的探测机制依赖于雷达波的反射,如果存在金属或电解质遮挡物,则可能会影响雷达波的反射路径,从而影响到雷达的探测准确性。因此,在安装雷达时,应确保雷达前方没有诸如金属窗帘条、风扇、空调电机等潜在的干扰源。在实际安装过程中,还应当注意雷达模块的安装高度和角度会影响到其探测效果。为了使雷达的主波束能够覆盖到整个睡眠区域,雷达的安装高度应该保持在与床面的高度差在0.9米左右,误差不超过0.2米。同时,雷达模块的安装需要保证其前方没有明显的遮挡物,尤其是金属材质的物体,因为这些物体可能会反射雷达波,造成干扰。为了确保雷达能够正常工作,安装完成后还需注意雷达模块的供电稳定性。雷达模块对电源品质有一定的要求,需要无门限毛刺或纹波现象,并且需要有效屏蔽来自附近设备的电源噪声。为了保证模块内部VCO电路的正常工作,雷达模块需要+5V到+6V的供电,且电压纹波不能超过100mV。外部电源还需要提供足够的电流输出能力和瞬态响应能力,以防止由于电源不稳定导致的探测距离缩短或误报率增加等问题。1.7 微波雷达的完整功能概述(快速上手)R60ABD1呼吸睡眠雷达模组是一款基于60GHz毫米波雷达技术设计的非接触式生物感知设备,主要用于人体存在感知及运动感知。它能够根据睡眠过程中身体运动幅度变化和呼吸心率变化,实时判断目标的睡眠状态、呼吸心跳频率,并在睡眠结束后输出睡眠评分。该模组的探测功能不受温度、湿度、噪声气流、尘埃、光照和人体完全静止等因素的影响,适合安装在室内顶部使用。模组具备多种功能,包括有人/无人状态检测、人体静止/活跃状态切换检测、人体距离主动上报、体动幅度参数输出、人体方位上报、心跳数值及波形输出、呼吸数值及波形输出、入床/离床状态判断、睡眠状态(清醒/浅睡/深睡)识别、清醒/浅睡/深睡时长统计、睡眠质量评分、睡眠异常上报、异常挣扎上报、无人计时上报以及睡眠质量评级上报等。这些功能通过不同的数据点(DP)以特定的时间间隔或状态变化时上报。为了确保雷达的准确探测,模组的安装需要遵循一定的规范。雷达应该安装在床头正上方1米的高度,向下倾斜30至45度,以确保主波束能够覆盖到睡眠区域。此外,雷达前方不应有明显的金属或电解质遮挡物,以免影响探测效果。在安装过程中,还需确认雷达探测范围内是否存在干扰源,如空调、风扇等,并尽可能移除这些干扰源。模组的引脚包括电源输入、地、串口接收与发送端、以及若干备用扩展引脚。其中,部分引脚可以根据用户需求重新定义功能。为了便于用户操作,在官方的文档还介绍了如何准备必要的工具,如TTL串口工具、杜邦线、PC电脑、串口助手终端和Radar-EVB demo板,并给出了上电及工作的数据上报规则和睡眠模式检测逻辑。在官方的文档最后提供了主要功能测试指引,包括睡眠质量状态判断测试、入离床状态判断测试、离床状态判断测试、呼吸频率测试以及心跳频率测试等。每项测试都有明确的操作步骤和判定标准,以帮助用户验证模组的功能是否正常。此外,官方的文档还对体动幅度参数的输出进行了详细说明,并附带了相关的测试表格格式,便于用户记录和分析测试结果。二、微波雷达调试过程2.1 接线说明2.2 安装说明倾斜安装: * 确保雷达探测准确性,建议安装在床头上方,以 45°斜向下安装! R60ABD1-呼吸睡眠雷达倾斜安装,倾斜角度为 30~45°,安装在床头上方,雷达安装高度建议为高于床面 0.8-1m;保证雷达主波束覆盖探测区域;雷达前面无明显(金属/电解质)遮挡物及覆盖物。受雷达安装高度及雷达波束范围影响,在该安装模式下,人体存在检测最大距离 L3 ≈ 2.5 米;睡眠检测最大距离 L2 ≈ 2.5 米;人体呼吸频率检测最大距离 L1 ≈ 1.5 米。2.3 连接电脑调试将60G毫米波雷达模块与电脑连接,调试模块是否正常可以运行,60G毫米波雷达模块默认的波特率是115200GND-----GNDVCC-----VCCTX------RXRX------TX串口调试助手返回的数据:睡眠雷达上位机:三、华为云服务器部署与上位机APP开发这里直接看视频,可以了解的更加清楚。(1)华为云物联网开发(一)设备上云:cid:link_0(2)华为云物联网云平台对应的上位机开发步骤:cid:link_1四、STM32代码开发(微波雷达模块数据处理)4.1 微波雷达数据处理(头文件)#ifndef _DATAHANDLE_H#define _DATAHANDLE_H#include "stdint.h"/* 定义包头及指令信息 *///帧头#define HEADER1 0x53#define HEADER2 0x59//控制字#define CMD_TICK 0x01 //心跳包#define CMD_PRODUCT_INFO 0x02 //产品信息#define CMD_OTA 0x03 // OTA升级#define CMD_WORK_STATE 0x05 //工作状态#define CMD_RADAR_DETECT_RANGE 0x07 //雷达探测范围#define CMD_BODY_EXIST_DETECT 0x80 //人体存在检测#define CMD_BREATH_DETECT 0x81 //呼吸检测#define CMD_SLEEP_DETECT 0x84 //睡眠检测#define CMD_HEART_DETECT 0x85 //心率检测//帧尾#define END1 0x54#define END2 0x43/* 枚举读取数据报文的状态 */typedef enum{ IDLE, SEEN_HEADER1, SEEN_HEADER2, SEEN_CONTROL, SEEN_COMMAND, SEEN_LENGTH, SEEN_DATA, SEEN_SUM, SEEN_END1, SEEN_END2} rx_datagram_state_t;/* 枚举控制模式 */typedef enum{ MODE_IDLE, MODE_SEND_TICK, MODE_SEND_PRODUCT_INFO, MODE_SEND_OTA, MODE_SEND_WORK_STATE, MODE_SEND_RADAR_DETECT_RANGE, MODE_SEND_BODY_EXIST_DETECT, MODE_SEND_BREATH_DETECT, MODE_SEND_SLEEP_DETECT, MODE_SEND_HEART_DETECT} control_mode_t;/*******************************************************************************///人体存在功能typedef struct{ uint8_t body_exist_flag; //有人无人检测标志 uint8_t work_state; //运动状态 uint8_t body_move_param; //体动参数 uint16_t body_distance; //人体距离 uint8_t body_direction[3]; //人体方位} body_exist_detect_t;//呼吸检测功能typedef struct{ uint8_t breath_detect_switch; //开关呼吸功能 uint8_t breath_detect_state; //呼吸检测状态 uint8_t breath_detect_value; //呼吸检测值 uint8_t breath_wave_data[5]; //呼吸波形} breath_detect_t;//睡眠评分typedef struct{ uint8_t sleep_detail_exist; //睡眠详细状态 uint8_t sleep_detail_state; //睡眠详细评分 uint8_t sleep_detail_score; //睡眠评分 uint16_t sleep_detail_time; //睡眠时间 uint8_t sleep_detail_awake; //清醒时长占比 uint8_t sleep_detail_light; //浅睡时长占比 uint8_t sleep_detail_deep; //深睡时长占比 uint8_t sleep_detail_away; //离床时长占比 uint8_t sleep_detail_away_times; //离床次数 uint8_t sleep_detail_turn_over_times; //翻身次数 uint8_t sleep_detail_avg_breath; //平均呼吸 uint8_t sleep_detail_avg_heart; //平均心率 uint8_t sleep_detail_breath_stoptimes; //呼吸停顿次数 uint8_t sleep_detail_turn_over_L; //大动作次数 uint8_t sleep_detail_turn_over_S; //小动作次数} sleep_detail_t;//睡眠检测功能typedef struct{ uint8_t sleep_detect_switch; //开关睡眠功能 uint8_t sleep_bed_state; //入床/离床状态 uint8_t sleep_detect_state; //睡眠检测状态 uint8_t sleep_wake_hour; //清醒时间 uint8_t sleep_light_hour; //浅睡时长 uint8_t sleep_deep_hour; //深睡时长 uint8_t sleep_score; //睡眠质量评分 sleep_detail_t sleep_score_detail; //睡眠质量评分详情 sleep_detail_t sleep_score_detail_1; //睡眠质量评分详情1 uint8_t sleep_score_detail_err; //睡眠质量评分详情2} sleep_detect_t;//心率检测功能typedef struct{ uint8_t heart_detect_switch; //开关心率功能 uint8_t heart_detect_value; //心率检测值 uint8_t heart_wave_data[5]; //心率波形} heart_detect_t;//数据变化标志typedef struct{ unsigned data_change_body_exist : 1; unsigned data_change_breath : 1; unsigned data_change_sleep : 1; unsigned data_change_heart : 1;} data_change_t;void ProcessRx(uint8_t *buff,uint8_t size);// void ProcessRx(void);extern body_exist_detect_t body_exist_detect;extern breath_detect_t breath_detect;extern sleep_detect_t sleep_detect;extern heart_detect_t heart_detect;#endif4.2 微波雷达数据处理(源文件)#include "datahandle.h"#include "debug.h"body_exist_detect_t body_exist_detect = {0};breath_detect_t breath_detect = {0};sleep_detect_t sleep_detect = {0};heart_detect_t heart_detect = {0};data_change_t data_change = {0};/* 定义数据包接收状态的变量,并初始化为空闲状态 */rx_datagram_state_t rx_datagram_state = IDLE;control_mode_t control_mode = MODE_IDLE;/* 协议数据处理函数 */void ProcessRx(uint8_t *buff, uint8_t size){ /****************************************************************************/ uint8_t receivedbyte, rx_sum, command; //数据存储数组 uint8_t rx_data[10]; uint16_t rx_dategram_len; while (size) { switch (rx_datagram_state) { case IDLE: //在空闲时,判断是否读取帧头1 { receivedbyte = *buff; if (HEADER1 == receivedbyte) { // printf("HEADER1:%x\n", *buff); rx_sum = 0; rx_sum += receivedbyte; rx_datagram_state = SEEN_HEADER1; buff++; } break; } case SEEN_HEADER1: //读取第一帧之后,判断是否读取帧头2 { receivedbyte = *buff; if (HEADER2 == receivedbyte) { // printf("HEADER2:%x\n", *buff); rx_sum += receivedbyte; rx_datagram_state = SEEN_HEADER2; buff++; } break; } case SEEN_HEADER2: //读取第二帧后,根据控制字判断数据模式 { uint8_t ctrl_mode = *buff; //控制字 rx_sum += ctrl_mode; if (ctrl_mode == CMD_TICK) control_mode = MODE_SEND_TICK; else if (ctrl_mode == CMD_PRODUCT_INFO) control_mode = MODE_SEND_PRODUCT_INFO; else if (ctrl_mode == CMD_OTA) control_mode = MODE_SEND_OTA; else if (ctrl_mode == CMD_WORK_STATE) control_mode = MODE_SEND_WORK_STATE; else if (ctrl_mode == CMD_RADAR_DETECT_RANGE) control_mode = MODE_SEND_RADAR_DETECT_RANGE; else if (ctrl_mode == CMD_BODY_EXIST_DETECT) control_mode = MODE_SEND_BODY_EXIST_DETECT; else if (ctrl_mode == CMD_BREATH_DETECT) control_mode = MODE_SEND_BREATH_DETECT; else if (ctrl_mode == CMD_SLEEP_DETECT) control_mode = MODE_SEND_SLEEP_DETECT; else if (ctrl_mode == CMD_HEART_DETECT) control_mode = MODE_SEND_HEART_DETECT; else control_mode = MODE_IDLE; rx_datagram_state = SEEN_CONTROL; // printf("SEEN_CONTROL:%x\n", ctrl_mode); buff++; } break; case SEEN_CONTROL: //读取控制字后,判断命令字 { command = *buff; //命令字 rx_sum += command; rx_datagram_state = SEEN_COMMAND; // printf("SEEN_COMMAND:%x\n", command); buff++; } break; case SEEN_COMMAND: //读取命令字后,识别数据长度 { uint8_t len_temp[2]; len_temp[0] = *buff; rx_sum += len_temp[0]; buff++; len_temp[1] = *buff; rx_sum += len_temp[1]; rx_dategram_len = (len_temp[0] << 8) | len_temp[1]; rx_datagram_state = SEEN_LENGTH; // printf("SEEN_LENGTH:%x\n", rx_dategram_len); buff++; } break; case SEEN_LENGTH: //读取数据长度后,保存数据 { if (size < (int)rx_dategram_len) //判断数据包是否完整 { rx_datagram_state = IDLE; return; } uint8_t readlen = rx_dategram_len; //数据包长度 uint8_t tmp[rx_dategram_len]; //数据包缓存 uint8_t *ptmp = tmp; //数据包缓存指针 while (readlen--) { receivedbyte = *buff; *ptmp++ = receivedbyte; //将数据存入缓存 rx_sum += receivedbyte; //校验和 } // TODO 使用上面操作,可以直接操作rx_data指针,不用拷贝数据到rx_data数组中 for (uint8_t i = 0; i < rx_dategram_len; i++) //将数据存储到数组中 { rx_data[i] = tmp[i]; } rx_datagram_state = SEEN_DATA; buff++; } break; case SEEN_DATA: //读取数据后,判断校验和,根据数据、控制字、命令字读取状态 { uint8_t getsum = *buff; //判断校验和是否正确 if (getsum != rx_sum) { rx_datagram_state = IDLE; return; } else { //判断控制字模式 switch (control_mode) { case MODE_SEND_TICK: //心跳包 { printf("MODE_SEND_TICK\n"); } break; case MODE_SEND_PRODUCT_INFO: //产品信息 { printf("MODE_SEND_PRODUCT_INFO\n"); } break; case MODE_SEND_OTA: // OTA升级 { printf("MODE_SEND_OTA\n"); } break; case MODE_SEND_WORK_STATE: //工作状态 { printf("MODE_SEND_WORK_STATE\n"); } break; case MODE_SEND_RADAR_DETECT_RANGE: //雷达检测范围 { printf("MODE_SEND_RADAR_DETECT_RANGE\n"); } break; case MODE_SEND_BODY_EXIST_DETECT: //人体存在检测 { data_change.data_change_body_exist = 1; switch (command) { case 1: { //检测人体存在 body_exist_detect.body_exist_flag = (0 != rx_data[0]) ? 1 : 0; printf("Body Exist flag State:%d\n", body_exist_detect.body_exist_flag); } break; case 2: { //运动状态 body_exist_detect.work_state = rx_data[0]; printf("Move State:%d\n", body_exist_detect.work_state); } break; case 3: { //运动值 body_exist_detect.body_move_param = rx_data[0]; printf("Body Move Value:%d\n", body_exist_detect.body_move_param); } break; case 4: { //人体距离 body_exist_detect.body_distance = (rx_data[0] << 8) | rx_data[1]; printf("Body Distance:%d\n", body_exist_detect.body_distance); } break; case 5: { //人体方位 body_exist_detect.body_direction[0] = (rx_data[0] << 8) | rx_data[1]; body_exist_detect.body_direction[1] = (rx_data[2] << 8) | rx_data[3]; body_exist_detect.body_direction[2] = (rx_data[4] << 8) | rx_data[5]; } break; } } break; case MODE_SEND_BREATH_DETECT: //呼吸检测 { data_change.data_change_breath = 1; switch (command) { case 1: { //呼吸检测状态 breath_detect.breath_detect_state = rx_data[0]; printf("Breath State:%d\n", breath_detect.breath_detect_state); } break; case 2: { //呼吸值 breath_detect.breath_detect_value = rx_data[0]; printf("Breath Value:%d\n", breath_detect.breath_detect_value); } } } break; case MODE_SEND_SLEEP_DETECT: //睡眠检测 { data_change.data_change_sleep = 1; //判断命令字 switch (command) { case 1: { //入床/离床状态 sleep_detect.sleep_bed_state = rx_data[0]; printf("Sleep1 State:%d\n", sleep_detect.sleep_bed_state); } break; case 2: { //睡眠状态 sleep_detect.sleep_detect_state = rx_data[0]; printf("Sleep State:%d\n", sleep_detect.sleep_detect_state); } break; case 3: { //清醒时长 sleep_detect.sleep_wake_hour = (rx_data[0] << 8) | rx_data[1]; printf("Sleep Wake Hours:%d\n", sleep_detect.sleep_wake_hour); } break; case 4: { //浅睡时长 sleep_detect.sleep_light_hour = (rx_data[0] << 8) | rx_data[1]; printf("Sleep Light Hours:%d\n", sleep_detect.sleep_light_hour); } break; case 5: { //深睡时长 sleep_detect.sleep_deep_hour = (rx_data[0] << 8) | rx_data[1]; printf("Sleep Deep Hours:%d\n", sleep_detect.sleep_deep_hour); } break; case 0x06: { //睡眠质量评分 sleep_detect.sleep_score = rx_data[0]; printf("Sleep Score:%d\n", sleep_detect.sleep_score); } break; case 0x0c: { //睡眠检测结果 sleep_detect.sleep_score_detail.sleep_detail_exist = rx_data[0]; sleep_detect.sleep_score_detail.sleep_detail_state = rx_data[1]; sleep_detect.sleep_score_detail.sleep_detail_avg_breath = rx_data[2]; sleep_detect.sleep_score_detail.sleep_detail_avg_heart = rx_data[3]; sleep_detect.sleep_score_detail.sleep_detail_turn_over_times = rx_data[4]; sleep_detect.sleep_score_detail.sleep_detail_turn_over_L = rx_data[5]; sleep_detect.sleep_score_detail.sleep_detail_turn_over_S = rx_data[6]; sleep_detect.sleep_score_detail.sleep_detail_breath_stoptimes = rx_data[7]; } break; case 0x0d: { //睡眠详情 sleep_detect.sleep_score_detail_1.sleep_detail_score = rx_data[0]; sleep_detect.sleep_score_detail_1.sleep_detail_time = (rx_data[1] << 8) | rx_data[2]; sleep_detect.sleep_score_detail_1.sleep_detail_awake = rx_data[3]; sleep_detect.sleep_score_detail_1.sleep_detail_light = rx_data[4]; sleep_detect.sleep_score_detail_1.sleep_detail_away = rx_data[5]; sleep_detect.sleep_score_detail_1.sleep_detail_away_times = rx_data[6]; sleep_detect.sleep_score_detail_1.sleep_detail_avg_breath = rx_data[7]; sleep_detect.sleep_score_detail_1.sleep_detail_avg_heart = rx_data[8]; sleep_detect.sleep_score_detail_1.sleep_detail_breath_stoptimes = rx_data[9]; } break; case 0x0e: { //异常检测 sleep_detect.sleep_score_detail_err = rx_data[0]; } break; } } break; case MODE_SEND_HEART_DETECT: //心率检测 { data_change.data_change_heart = 1; switch (command) { case 0: { //开关心率检测 } break; case 2: { //心率值 heart_detect.heart_detect_value = rx_data[0]; printf("Heart rate Value:%d\n", heart_detect.heart_detect_value); } break; case 5: { //心率波形 heart_detect.heart_wave_data[0] = rx_data[0]; heart_detect.heart_wave_data[1] = rx_data[1]; heart_detect.heart_wave_data[2] = rx_data[2]; heart_detect.heart_wave_data[3] = rx_data[3]; heart_detect.heart_wave_data[4] = rx_data[4]; } break; } } break; case MODE_IDLE: //空闲 { } break; } } rx_datagram_state = SEEN_SUM; buff++; } break; case SEEN_SUM: //读取校验后,判断帧尾1 { rx_datagram_state = (END1 == *buff) ? SEEN_END1 : IDLE; } break; case SEEN_END1: //读取帧尾1后,判断帧尾2 { rx_datagram_state = (END2 == *buff) ? SEEN_END2 : IDLE; } break; case SEEN_END2: //判断帧尾2后,设置接收完成标志 { // rx_flag = 1; rx_datagram_state = IDLE; } break; default: { receivedbyte = 0; rx_datagram_state = IDLE; size = 0; break; } } size--; }}五、总结本项目开发一种非接触式的睡眠监控系统,该系统利用先进的60GHz毫米波雷达技术和STM32微控制器,实现了对人体在睡眠过程中的存在感知、运动感知以及生理指标如呼吸频率、心率的实时监测。系统能够自动评估睡眠质量,并在用户睡眠周期结束时提供睡眠评分。为了确保用户能够在任何地点了解自己的睡眠状况,系统集成了Wi-Fi模块,可以将收集到的数据上传至华为云物联网平台,并通过专门设计的移动应用程序供用户远程访问。此外,系统还具备超阈值报警功能,当检测到异常的生理指标时会发出警报提醒。本地1.44寸TFT LCD显示屏用于实时显示监测到的信息,包括生理指标和环境数据。为了全面监测用户的健康状况,系统还加入了MLX90614红外体温传感器来检测人体体温。通过集成多种传感器和技术,该项目为健康管理和智能家居应用提供了有力支持。
-
一、前言随着物联网(IoT)技术的飞速发展,越来越多的设备开始连接到互联网,形成了一个万物互联的世界。在这个背景下,设备与云端之间的通讯变得尤为重要。本文将探讨几种常见的无线通信模块——EC20-4G、Air724ug-4G、NBIOT-BC26 和 ESP8266-WIFI,并展示如何通过发送AT指令来控制这些模块,利用MQTT协议连接华为云物联网平台,实现数据的高效上传。EC20-4G 和 Air724ug-4G 模块以其高速的数据传输能力和广泛的网络覆盖成为4G LTE通信的理想选择;NBIOT-BC26 模块则专为低功耗广域网(LPWAN)设计,特别适合于要求低带宽、远距离传输的应用场景;而 ESP8266-WIFI 模块则凭借其成本效益高、易于集成的特点,在Wi-Fi连接领域备受青睐。下面将逐一介绍这些模块的基础配置方法,并通过具体的实例说明如何使用AT指令建立与华为云物联网平台的安全连接。介绍MQTT协议的优势,包括其轻量化、低延迟和高可靠性等特性,这些特性使得MQTT成为物联网领域中最受欢迎的消息传递协议之一。通过这些模块的学习,可以了解到如何选择适合自己项目的通信模块,还能掌握实际的操作步骤,从硬件初始化到软件编程,最终成功地将传感器数据上传到云端。二、模块介绍2.1 EC20-4G模块EC20-4G是Quectel(Quectel Wireless Solutions)公司推出的一款4G LTE无线通信模块,它主要面向全球市场,支持多个频段的4G LTE网络以及向下兼容的3G和2G网络。这款模块非常适合用于数据传输速率要求较高的应用场合,如工业路由器、移动支付终端、远程医疗设备、车联网和其他M2M(Machine to Machine)通讯领域。EC20-4G模块采用LGA封装形式,拥有紧凑的设计,使得它可以轻松集成到各种类型的设备中,即便是在空间有限的应用环境中也能发挥良好的性能。该模块支持多种网络协议,例如TCP/IP, FTP, HTTP等,这使得开发者可以灵活地根据不同的应用场景选择合适的网络协议栈。除了基本的数据传输功能外,EC20-4G还具备丰富的扩展接口,包括UART、USB、GPIO等,方便与其他硬件组件进行连接和交互。此外,还支持多种定位技术,比如GPS/GLONASS/Galileo/QZSS,使得集成位置服务成为可能。在软件支持方面,EC20-4G提供了广泛的AT指令集,便于开发人员进行编程控制。同时,Quectel也为这款模块提供了详尽的技术文档和支持,帮助开发人员快速完成产品的开发和上市。2.2 ESP8266-WIFI模块ESP8266是一款由乐鑫科技(Espressif Systems)开发的高度集成的Wi-Fi SoC(系统级芯片),它专为移动设备、可穿戴技术和物联网应用而设计。ESP8266芯片内部集成了一个Tensilica L106超低功耗32位微处理器,主频可达80MHz至160MHz,拥有512KB的SRAM,以及内置的Wi-Fi模块,支持IEEE 802.11 b/g/n标准。这些特性使ESP8266成为一种成本效益高的解决方案,能够快速实现设备的Wi-Fi连接功能。ESP8266模块通常以小型化的形式出现,比如ESP-01,它是一个非常小巧的模块,尺寸仅约为25mm x 18mm,却包含了所有必要的Wi-Fi功能。这样的尺寸使得它非常适合集成到空间受限的项目中。ESP8266模块通过简单的AT命令集来进行配置和控制,这让它对于那些希望快速添加互联网连接功能到现有产品中的工程师来说非常有吸引力。除了作为独立的微控制器运行之外,ESP8266还可以作为从机与另一个主控器(如Arduino或树莓派、STM32、51单片机)配合工作,通过串口接收命令来执行Wi-Fi相关的任务。这种方式允许开发者利用ESP8266的强大网络功能,同时保持主控器对整个系统的控制。2.3 BC26-NBIOT模块BC26-NB是Quectel公司推出的一款窄带物联网(NB-IoT)模块,它专门针对低功耗广域网(LPWAN)的应用需求进行了优化。BC26-NB模块支持3GPP Release 13 NB-IoT标准,适用于各种需要长距离、低功耗、可靠连接的物联网应用,如智能计量、资产追踪、智慧城市基础设施监测等场景。该模块采用了紧凑型设计,适合集成到空间受限的设备中。BC26-NB模块不仅支持NB-IoT网络,还具备低功耗模式,使得它可以在电池供电的情况下长时间运行,这对于需要长期部署在野外或难以更换电池的设备来说是非常有利的特点。此外,它还提供了一系列的硬件接口,如UART、SPI、I2C、PWM等,方便与外部传感器或其他硬件设备进行连接和数据交换。在软件支持方面,BC26-NB模块配备了全面的AT指令集,简化了模块的初始化和配置过程。开发人员可以通过这些指令来控制模块的网络连接、数据传输等功能。Quectel公司还提供了详细的开发指南和技术支持,帮助用户快速地将BC26-NB模块集成到他们的物联网解决方案中。由于NB-IoT网络覆盖范围广、穿透力强,BC26-NB模块可以实现深覆盖区域内的可靠通信,即使是在地下室或偏远地区也能保持稳定的连接。这种能力对于需要在复杂环境中工作的物联网设备来说至关重要。2.4 Air724-UG-4G模块Air724-UG是Quectel公司推出的一款高性能的4G无线通信模块,它专为全球市场设计,支持多个频段的4G LTE Cat 4网络,同时兼容3G和2G网络,以便在全球范围内提供广泛的网络覆盖。该模块特别适合应用于需要高数据传输速率和稳定连接的行业解决方案中,如车载系统、工业路由器、远程监控系统以及移动支付终端等。Air724-UG模块采用了LGA封装,具有紧凑的外形尺寸,这使其能够轻松地集成到空间受限的产品设计中。它支持多种网络协议,包括TCP/IP、FTP、HTTP等,这使得开发人员可以根据具体的应用场景灵活选择适当的协议栈。此外,Air724-UG还具备多个物理接口,如UART、USB、GPIO等,便于与其他硬件组件进行连接,从而增强系统的功能性和互操作性。在功能特性方面,Air724-UG模块不仅支持高速数据传输,最高可达下行150Mbps和上行50Mbps的速率,还提供了丰富的扩展能力和附加功能。例如,它支持GNSS(全球导航卫星系统)功能,可用于定位服务;具备语音通话功能,适用于某些需要语音支持的应用场景;同时,该模块还支持多种安全机制,如SSL/TLS加密,保障了数据的安全传输。Quectel为Air724-UG模块提供了详尽的技术文档和支持资源,包括开发指南、参考设计和SDK等,帮助开发人员快速启动项目并缩短产品上市时间。模块的易用性和Quectel的技术支持使得Air724-UG成为了一款理想的4G LTE解决方案,适用于多种专业领域的设备连接需求。三、MQTT协议介绍MQTT协议概述MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,它被设计用来提供一对多的消息分发和应用之间的通讯,尤其适用于远程位置的设备和高延迟或低带宽的网络。MQTT协议基于客户端-服务器架构,客户端可以订阅任意数量的主题,并可以发布消息到这些主题。服务器(通常称为MQTT Broker)则负责接受来自客户端的连接请求,并转发消息给感兴趣的客户端。MQTT协议特点MQTT协议具有以下主要特点:轻量级:MQTT协议的实现非常轻巧,占用资源少,非常适合于资源受限的设备,如传感器、嵌入式设备等。低带宽需求:MQTT协议的设计考虑到了带宽的高效利用,其报头非常小,这使得它能够在低带宽环境下有效工作。可靠的消息传递:MQTT提供了三种服务质量等级(QoS),允许发布者和订阅者之间选择合适的服务质量级别。支持多种传输层:虽然MQTT最初是基于TCP/IP设计的,但它也支持使用WebSockets和其他传输协议,以便更好地集成到现代Web应用中。安全性:MQTT支持TLS加密通信,保证了数据的安全性,并可以通过认证机制增强安全性。MQTT协议的基本概念MQTT协议的核心概念包括客户端、服务器(Broker)、主题和消息。客户端(Client):任何连接到Broker的应用程序都可以被称为客户端。客户端可以订阅感兴趣的主题,接收其他客户端发布的消息,也可以发布消息。服务器(Broker):MQTT服务器或Broker是消息的中心节点,它接受客户端的连接请求,存储订阅关系,并将消息从发布者路由到订阅者。主题(Topic):主题是一个字符串,用于标识消息的类别或目的。客户端订阅主题后,可以接收到发布到该主题的所有消息。消息(Message):消息是由客户端发布的一组数据,它包含两部分:主题名和消息体。MQTT协议的工作流程MQTT的工作流程如下:连接:客户端向Broker发送连接请求,包含客户端ID、用户名、密码等信息。订阅:一旦连接成功,客户端可以订阅一个或多个主题。发布:客户端可以向特定主题发布消息。接收:如果客户端订阅了一个主题,则它可以接收该主题下的消息。断开连接:当客户端完成所有操作后,可以断开与Broker的连接。MQTT协议的应用场景由于其轻量级特性和高效的消息传递能力,MQTT协议广泛应用于物联网(IoT)领域,特别是在智能家居、工业自动化、远程监控等领域。此外,随着移动互联网的发展,MQTT也被用于移动应用程序中的实时数据更新和推送服务。四、上云测试【1】MQTT服务器地址信息下面的这个我华为云IOT物联网服务器的设备信息,方便下面进行测试。连接这个服务器。IP地址:117.78.5.125端口号:1883ClientId 64000697352830580e48df07_dev1_0_0_2023030206Username 64000697352830580e48df07_dev1Password a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449订阅主题:$oc/devices/64000697352830580e48df07_dev1/sys/messages/down发布主题:$oc/devices/64000697352830580e48df07_dev1/sys/properties/report发布的消息:{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}【2】ESP8266-WIFI连接要通过ESP8266模块使用AT指令来连接MQTT服务器,订阅特定的主题,并发布消息,可以按照以下步骤操作。请注意,这里提供的AT命令序列是基于ESP8266模块支持的MQTT功能。下面是一个示例流程:初始化ESP8266AT+RST 重启模块AT 测试模块是否响应AT+CIPMUX=1 设置多连接模式(可选)AT+CIPRXGET=1,100 设置接收数据的方式(可选)设置Wi-Fi连接AT+CWMODE=3 设置为Station+AP模式(通常只需要Station模式即可,即设置为1)AT+CWJAP="yourSSID","yourPassword" 连接到Wi-Fi网络配置MQTT客户端AT+CIPMQTTCFG="117.78.5.125",1883,"64000697352830580e48df07_dev1_0_0_2023030206","64000697352830580e48df07_dev1","","a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449",0,0,60 配置MQTT客户端参数,包括服务器地址、端口、客户端ID、用户名、密码等连接MQTT服务器AT+CIPMQTTC=1 连接到MQTT服务器订阅主题AT+CIPMQTTSUB=0,"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down",2 订阅指定的主题发布消息AT+CIPMQTTPUB=0,"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report",2,0,0,"{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}" 发布消息到指定主题断开MQTT连接AT+CIPMQTTDISC=0 断开与MQTT服务器的连接关闭TCP/IP连接AT+CIPCLOSE 关闭当前的TCP/IP连接注意,在使用中,需要将"yourSSID"和"yourPassword"替换为实际使用的Wi-Fi网络的SSID和密码。【3】NBIOT-BC26使用NBIoT-BC26模块连接MQTT服务器的过程与使用ESP8266类似,但是命令集有所不同。以下是使用NBIoT-BC26模块通过AT指令连接MQTT服务器、订阅主题以及发布消息的示例流程:初始化模块AT 检查模块是否在线ATE0 关闭回显AT+CFUN=1 启用射频功能AT+CGATT=1 附着到网络设置网络参数AT+CNOPS=0 设置网络操作模式AT+CGDCONT=1,"IP","your_apn" 设置PDP上下文,使用您的运营商提供的APN激活PDP上下文AT+CGACT=1,1 激活PDP上下文配置MQTT客户端AT+QMTOPEN=0,"tcp","117.78.5.125",1883 打开一个TCP连接到MQTT服务器建立MQTT连接使用AT+QMTCONN命令进行连接,此命令会发送MQTT CONNECT包给服务器。AT+QMTCONN=0,"64000697352830580e48df07_dev1_0_0_2023030206",60,0,1,0,"64000697352830580e48df07_dev1","a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449" 连接MQTT服务器,参数包括客户端ID,保持活动时间,Clean Session标志,Will标志,Will QoS,Will保留位,用户名和密码。订阅主题AT+QMTSUB=0,2,"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down" 订阅主题发布消息AT+QMTPUB=0,1,"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report",0,0,0,512 开始发送消息{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]} 发送的消息内容断开MQTT连接AT+QMTDISC=0 断开MQTT连接关闭TCP连接AT+QMTCLS=0 关闭TCP连接去激活PDP上下文AT+CGACT=1,0 去激活PDP上下文上述命令序列是基于NBIoT-BC26模块的MQTT功能。【4】EC20-4G模块对于EC20模块(通常是4G LTE模块),连接MQTT服务器、订阅主题和发布消息的AT指令会有所不同。以下是使用EC20模块通过AT指令完成这些操作的流程:初始化EC20模块AT检查EC20是否正常工作。设置工作模式为数据模式(如果尚未设置)AT+QCFG="nwscanmode",0,1设置网络扫描模式为自动。连接到移动网络AT+QNWINFO检查网络连接状态。设置MQTT服务器的IP地址和端口AT+QMTOPEN=0,"117.78.5.125",1883连接到MQTT服务器的指定IP和端口。登录MQTT服务器AT+QMTCONN=0,"64000697352830580e48df07_dev1","a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449",0,0使用客户端ID、用户名和密码连接MQTT服务器。订阅MQTT主题AT+QMTSUB=0,"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down",1订阅指定的MQTT主题。发布消息到MQTT主题AT+QMTPUB=0,"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report",0,0,{"services":[{"service_id":"stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}向指定的MQTT主题发布消息。断开MQTT连接AT+QMTDISC=0断开与MQTT服务器的连接。关闭EC20模块(如果需要)AT+QPOWD=1关闭EC20模块或使其进入省电模式。检查状态(可选)AT+QMTSTAT=0检查MQTT连接状态。请注意:AT+QMTOPEN、AT+QMTCONN、AT+QMTSUB 和 AT+QMTPUB 命令中的第一个参数 0 是连接的会话编号。可以根据需要调整它。发布的消息格式要符合MQTT协议的要求,可能需要根据具体的EC20模块固件版本调整。确保你已经在模块中设置了正确的APN,并成功连接到移动网络。
-
一、前言在当今万物互联的时代背景下,物联网技术的快速发展极大地推动了智能化社会的构建。作为其中的关键一环,设备与云端平台之间的通信变得尤为重要。本文介绍如何在Linux操作系统环境下,利用串口通信来实现EC20模块与华为云物联网平台的有效连接。使用Linux下的/dev/ttyUSB0设备文件通过AT指令来配置EC20模块,采用C语言和Python这两种编程语言实现这一过程。EC20 是Quectel 生产的 4G LTE 模块。是一个多功能的通信模块,广泛应用于各种 IoT(物联网)设备中,提供了可靠的无线通信能力。EC20 支持 LTE FDD、LTE TDD、WCDMA 和 GSM 网络,能够实现高速的数据传输和稳定的语音通信。EC20 模块支持全球主要的频段,使其能够在多个国家和地区的网络环境中正常工作。它能够提供最高达 150 Mbps 的下行速率和 50 Mbps 的上行速率,这使得它非常适合需要高带宽的应用场景,如视频流、远程监控和数据传输。该模块具有强大的数据通信能力,包括支持 TCP/IP 和 UDP 协议的网络连接。EC20 还支持各种 AT 命令,通过这些命令用户可以控制模块的操作,配置网络设置,发送和接收数据。其内置的网络协议栈使得模块可以直接进行 MQTT、HTTP、FTP 等网络协议的通信,为开发者提供了极大的便利。除了数据通信功能,EC20 模块还支持语音通话和短信功能。这使得它不仅可以用于数据传输,还可以作为语音通信解决方案。通过 AT 命令,用户可以方便地进行拨打和接听电话,发送和接收短信,满足不同应用场景的需求。在电源管理方面,EC20 模块具有低功耗模式,能够有效地延长设备的电池寿命。它支持多种电源管理功能,包括睡眠模式和省电模式,使得它在不使用的时候能够降低功耗,减少能量消耗。模块的物理接口包括多个 UART 串口、USB 接口和 GPIO 引脚,这些接口允许模块与其他硬件进行连接。通过这些接口,用户可以实现串口通信、USB 数据传输以及各种数字信号的输入输出,提供了高度的灵活性和可扩展性。在设计和生产方面,EC20 模块遵循了工业标准,确保其在各种恶劣环境下的可靠性。它的设计小巧且坚固,适合嵌入到各种嵌入式系统和终端设备中。Quectel 提供了详细的技术文档和开发工具,帮助开发者快速集成和部署模块。二、实例代码2.1 服务器信息下面是我的华为云物联网服务器设备信息。关于创建过程,可以看视频:cid:link_0IP地址:117.78.5.125端口号:1883ClientId 64000697352830580e48df07_dev1_0_0_2023030206Username 64000697352830580e48df07_dev1Password a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449订阅主题:$oc/devices/64000697352830580e48df07_dev1/sys/messages/down发布主题:$oc/devices/64000697352830580e48df07_dev1/sys/properties/report发布的消息:{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}2.2 Python代码本小节介绍 通过串口 /dev/ttyUSB0 发送 AT 指令以控制 EC20 模块连接华为云物联网平台,并完成 MQTT 通信,使用 Python 脚本实现。AT 指令:AT+RST: 重启模块AT+CSIM=1: 设置工作模式为数据模式(请根据实际模块手册确认是否需要此指令)AT+QMTOPEN=0,"IP地址",端口号: 连接到 MQTT 服务器AT+QMTCONN=0,"ClientId","Username","Password": 使用提供的 ID、用户名和密码连接到 MQTT 服务器AT+QMTSUB=0,0,"主题",1: 订阅指定主题AT+QMTPUB=0,0,0,0,"主题",消息内容: 发布消息到指定主题下面是实现代码,展示了如何用 Python 通过串口发送 AT 指令来配置 EC20 模块并连接到华为云物联网平台:# -*- coding: utf-8 -*-import serialimport time# 串口配置SERIAL_PORT = '/dev/ttyUSB0'BAUDRATE = 115200TIMEOUT = 1# MQTT 服务器信息MQTT_SERVER_IP = '117.78.5.125'MQTT_SERVER_PORT = '1883'MQTT_CLIENT_ID = '64000697352830580e48df07_dev1_0_0_2023030206'MQTT_USERNAME = '64000697352830580e48df07_dev1'MQTT_PASSWORD = 'a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449'# 发布的消息PUBLISH_MESSAGE = '{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}'# 发送 AT 指令并获取响应def send_at_command(serial_conn, command, response_termination='OK', delay=1): print(f"Sending command: {command}") serial_conn.write((command + '\r\n').encode()) time.sleep(delay) response = serial_conn.read(serial_conn.inWaiting()).decode() print(f"Response: {response}") if response_termination and response_termination not in response: raise Exception(f"Unexpected response: {response}") return responsedef main(): # 打开串口连接 with serial.Serial(SERIAL_PORT, BAUDRATE, timeout=TIMEOUT) as ser: try: # 重启模块 send_at_command(ser, 'AT+RST') # 设置工作模式为数据模式 send_at_command(ser, 'AT+CSIM=1') # 连接到 MQTT 服务器 send_at_command(ser, f'AT+QMTOPEN=0,"{MQTT_SERVER_IP}",{MQTT_SERVER_PORT}') send_at_command(ser, 'AT+QMTCONN=0,"{MQTT_CLIENT_ID}","{MQTT_USERNAME}","{MQTT_PASSWORD}"') time.sleep(5) # 等待连接 # 订阅主题 send_at_command(ser, 'AT+QMTSUB=0,0,"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down",1') # 发布消息 send_at_command(ser, f'AT+QMTPUB=0,0,0,0,"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report",{PUBLISH_MESSAGE}') except Exception as e: print(f"An error occurred: {e}")if __name__ == "__main__": main()运行命令:root@flexusx-1a58:~# python3 mqtt_connect.py 2.3 C语言代码本小节介绍 用 C 语言实现通过串口发送 AT 指令来控制 EC20 模块并完成 MQTT 通信。下面是实现代码,通过串口配置 EC20 模块并连接到 MQTT 服务器:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <errno.h>#define SERIAL_PORT "/dev/ttyUSB0"#define BAUDRATE B115200int setup_serial_port(const char *port) { int fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, BAUDRATE); cfsetospeed(&options, BAUDRATE); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; tcsetattr(fd, TCSANOW, &options); return fd;}void send_at_command(int fd, const char *command) { write(fd, command, strlen(command)); write(fd, "\r\n", 2); usleep(100000); // Wait for 100ms for the module to respond char response[256]; int n = read(fd, response, sizeof(response) - 1); if (n > 0) { response[n] = '\0'; printf("Response: %s\n", response); } else { printf("No response or read error.\n"); }}int main() { int fd = setup_serial_port(SERIAL_PORT); // 1. Reset the module send_at_command(fd, "AT+RST"); // 2. Connect to MQTT server char command[300]; snprintf(command, sizeof(command), "AT+QMTOPEN=0,\"%s\",%d", "117.78.5.125", 1883); send_at_command(fd, command); snprintf(command, sizeof(command), "AT+QMTCONN=0,\"%s\",\"%s\",\"%s\"", "64000697352830580e48df07_dev1_0_0_2023030206", "64000697352830580e48df07_dev1", "a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449"); send_at_command(fd, command); usleep(5000000); // Wait 5 seconds for connection to establish // 3. Subscribe to a topic send_at_command(fd, "AT+QMTSUB=0,0,\"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down\",1"); // 4. Publish a message sprintf(command, "AT+QMTPUB=0,0,0,0,\"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report\",\"{\\\"services\\\": [{\\\"service_id\\\": \\\"stm32\\\",\\\"properties\\\":{\\\"DHT11_T\\\":18,\\\"DHT11_H\\\":80,\\\"MQ2\\\":1,\\\"water\\\":1,\\\"flame\\\":1,\\\"light\\\":0,\\\"LED1\\\":0,\\\"LED2\\\":0,\\\"LED3\\\":0}}]}\""); send_at_command(fd, command); close(fd); return 0;}编译运行:root@flexusx-1a58:~# gcc mqtt_connect.c root@flexusx-1a58:~# ./a.out 2.4 创建虚拟串口方便测试在与硬件通信之前,可以先建立一个虚拟串口测试一下。创建一个虚拟的串口设备 /dev/ttyUSB0 主要有两种方式:使用 socat 工具创建虚拟串口对(虚拟串口设备),或者使用 tty0tty 驱动来创建虚拟串口对。方法 1: 使用 socat 创建虚拟串口socat 是一个强大的网络工具,可以创建虚拟串口设备。下面是如何使用 socat 创建两个虚拟串口对:安装 socat: 在大多数 Linux 发行版上,可以使用包管理工具安装 socat。例如,在 Debian 或 Ubuntu 上运行:sudo apt-get install socat创建虚拟串口对: 运行以下命令来创建两个虚拟串口设备 /dev/ttyV0 和 /dev/ttyV1:socat -d -d PTY,link=/dev/ttyV0,raw,echo=0 PTY,link=/dev/ttyV1,raw,echo=0这将创建两个虚拟串口设备 /dev/ttyV0 和 /dev/ttyV1,它们会像物理串口一样工作,可以在程序中使用它们进行测试。使用虚拟串口设备:可以将一个设备用于发送数据,另一个设备用于接收数据进行测试。例如,可以将一个串口设备配置为连接到模拟的设备,另一个设备配置为模拟的串口设备的接收端。方法 2: 使用 tty0tty 驱动tty0tty 是一个内核模块,用于创建虚拟串口对。以下是如何安装和使用 tty0tty:安装 tty0tty: 需要从源代码编译和安装 tty0tty。按照以下步骤进行:sudo apt-get install build-essential linux-headers-$(uname -r)git clone https://github.com/ntop/tty0tty.gitcd tty0ttymakesudo make installsudo depmod -a加载内核模块: 运行以下命令加载 tty0tty 内核模块:sudo modprobe tty0tty这将创建虚拟串口设备 /dev/ttyt0 和 /dev/ttyt1。使用虚拟串口设备:/dev/ttyt0 和 /dev/ttyt1 现在可以作为虚拟串口设备使用。可以在程序中将它们作为串口设备来进行测试。示例代码假设已经创建了 /dev/ttyV0 和 /dev/ttyV1(使用 socat),可以在 Python 中使用这些虚拟串口设备进行测试。例如:import serial# 打开虚拟串口ser1 = serial.Serial('/dev/ttyV0', 115200, timeout=1)ser2 = serial.Serial('/dev/ttyV1', 115200, timeout=1)# 发送数据ser1.write(b'Hello, world!\n')# 读取数据response = ser2.readline()print('Received:', response.decode('utf-8'))# 关闭串口ser1.close()ser2.close()
-
是我的固件有问题吗?顺便问一下设备上发版本号,MQTT发送的问题,我虽然我这样发送过去,也受到了url。谢谢各位!!!!
-
一、前言1.1 项目介绍项目设计里用到的全部工具软件和文档源码,都可以在这里下载。cid:link_10【1】项目开发背景矿山环境作业安全监测系统的开发背景主要源于对矿井作业环境中潜在危险因素的有效监控需求。矿山作为重要的资源开采场所,其工作环境往往存在诸多安全隐患,如瓦斯爆炸、粉尘超标等,这些因素不仅威胁着矿工的生命安全,还可能导致严重的经济损失和社会影响。因此,建立一个能够实时监测矿井内环境状况,并能在危险发生前及时预警的安全监测系统显得尤为重要。随着物联网技术的发展,利用先进的传感器技术与无线通信技术相结合,可以实现对矿山环境的全方位监控。本项目选择以STM32F103RCT6单片机作为核心控制器,因其具备高性能、低功耗的特点,非常适合用于此类环境下的数据采集与控制任务。通过集成DHT11温湿度传感器、MQ5气体传感器、PM2.5传感器等,系统能够实时获取环境数据,并依据预设的阈值进行判断,从而采取相应的措施,比如启动通风装置降低瓦斯浓度或通过喷淋系统减少空气中的颗粒物含量。此外,为了使矿山管理人员能够远程监控矿井内的实际情况,本项目还将通过BC26(NBIOT)模块将收集到的数据上传至华为云物联网平台,实现了数据的云端存储与分析。同时,借助移动应用技术,开发了一款APP,以便于工作人员随时查看环境参数及接收警报信息,进一步增强了系统的实用性和灵活性。本项目的开发提供一套高效、可靠的矿山环境作业安全监测解决方案,通过技术手段提升矿山安全管理效率,保障矿工的人身安全,促进矿山行业的可持续发展。【2】设计实现的功能(1) 本项目设计的核心是以STM32F103RCT6单片机作为主控单元,负责整个系统的协调控制,实现对矿山环境各项关键参数的监测与管理。(2) 采用DHT11温湿度传感器进行环境温度和湿度的实时采集,一旦检测到的数值超出安全范围,则通过蜂鸣器发出警报信号。(3) 使用MQ5气体传感器监测瓦斯浓度,当浓度达到预设阈值时,系统将通过控制继电器启动风扇,以稀释瓦斯浓度。(4) 配备PM2.5传感器用以检测空气中颗粒物的浓度,当浓度超标时,激活雾化喷淋系统以降低灰尘含量。(5) 选用OLED显示屏作为人机交互界面,实时显示由各传感器采集到的环境数据。(6) 利用BC26(NBIOT)模块将现场采集到的数据上传至华为云物联网平台,便于远程监控和数据分析。(7) 实现自动模式功能,系统能够按照预先设定的阈值自动监测环境参数,并在必要时触发警报或执行相应控制动作,如启动风扇或喷淋系统。(8) 提供手动模式功能,允许用户通过按键直接控制风扇和雾化降尘设备的开关状态,并且开发了基于Qt框架的Android平台手机APP,以便于远程控制这些设备的运行状态。(9) 设计中考虑了系统的稳定供电方案,采用5V 2A的外部稳压电源为系统供电。(10) 风扇和雾化降尘设备均采用5V电源供电,并通过继电器模块实现开关控制。(11) OLED显示屏采用SPI协议进行数据传输,以确保信息显示的准确性和实时性。【3】项目硬件模块组成(1) 控制核心模块:STM32F103RCT6单片机最小系统模块,作为整个监测系统的控制中心。(2) 温湿度采集模块:DHT11温湿度传感器,用于实时检测环境的温度和湿度。(3) 气体检测模块:MQ5气体传感器,用于监测环境中的瓦斯浓度。(4) 颗粒物检测模块:PM2.5传感器,用于检测空气中悬浮颗粒物的浓度。(5) 显示模块:0.96寸OLED显示屏,采用SPI协议连接至控制核心,显示各项环境参数。(6) 报警模块:蜂鸣器,当检测到环境参数异常时发出声音警报。(7) 执行机构控制模块:继电器模块,用于控制风扇和雾化降尘设备的开关状态。(8) 通风设备:风扇,由继电器控制,用于降低瓦斯浓度。(9) 降尘设备:雾化喷淋系统,同样由继电器控制,用于减少空气中颗粒物含量。(10) 远程通信模块:BC26(NBIOT)模块,负责将采集到的数据通过窄带物联网技术上传至云端。(11) 电源供应模块:5V 2A外部稳压电源,为整个系统提供稳定的电力支持。(12) 操作接口:按键模块,允许用户手动控制设备的开启与关闭。(13) 移动终端交互模块:基于Qt开发的Android平台手机APP,实现远程监控和控制功能。【4】需求总结项目名称:基于STM32单片机设计的矿山环境作业安全监测系统1、本次设计以 STM32F103RCT6 单片机最小系统模块作为系统控制核心,确定各种传感器模块选型,完成系统硬件结构设计。2、采用 DHT11 温湿度采集模块进行环境温湿度检测。当传感器检测到环境值超过控制系统设定的阀值参数时,可触发蜂鸣器报警。3、采用 MQ5气体传感器来检测环境的瓦斯浓度。当瓦斯浓度达到阈值时,控制系统控制继电器开关模块动作,实现风扇自动控制功能。4、采用 PM2.5 传感器检测环境中的颗粒物,超过阈值触发报警,可打开雾化模块进行喷淋降低。5、采用 OLED 显示屏作为显示模块显示实时数据。6、将采集到的环境信息通过BC26(NBIOT)模块将数据上传到华为云物联网平台。7、自动模式功能根据预设的阈值设定,监测环境参数,并在超过阈值时触发警报和控制设备使用定时器进行周期性的环境参数监测。设计逻辑判断程序,根据环境参数触发不同的处理动作。8、手动模式功能实现按键功能,根据用户的操作控制风扇和雾化降尘设备的开关状态。开发手机 APP,使用Qt作为 Android 平台的开发工具实现与BC26(NBIOT)模块的通信和数据显示功能。在手机 APP 上实现远程控制风扇和雾化降尘设备的开关功能以及显示实时监测到的环境参数和警报信息9、供电采用 5V 2A外部稳压电源10、风扇和雾化降尘设备采用5V加湿器模块,通过继电器控制开关。11、OLED显示屏采用SPI协议的0.96寸OLED显示屏1.2 设计思路设计思路的核心是围绕提高矿山作业环境的安全性展开,考虑到矿山环境复杂多变的特点,本项目构建一个能够实时监测并有效应对潜在危险因素的自动化系统。该系统的设计从硬件选型到软件架构都遵循了模块化和易维护的原则,确保了系统的可靠性和扩展性。在硬件层面,选择了性能稳定且易于编程的STM32F103RCT6单片机作为中央处理器,这是因为STM32系列芯片拥有丰富的外设接口,能够方便地与各种传感器和执行机构进行通信。同时,考虑到矿山环境的特殊性,传感器的选择上优先考虑了可靠性与准确性,如DHT11用于温湿度监测,MQ5用于瓦斯浓度检测,PM2.5传感器则用于颗粒物浓度测量。此外,为了实现环境参数的直观展示,选用了OLED显示屏作为人机交互界面,并通过继电器模块来控制风扇和雾化喷淋系统,以应对不同的紧急情况。软件方面,系统的设计着重于逻辑清晰的程序架构,通过编写高效的算法来处理来自不同传感器的数据,并依据预设的安全阈值进行逻辑判断。当环境参数超出正常范围时,系统会自动触发相应的警报机制,并启动相应的应急措施,例如启动通风设备降低瓦斯浓度或启用喷淋系统减少粉尘。此外,为了便于远程监控,系统集成了BC26(NBIOT)模块,能够将采集到的数据上传至华为云物联网平台,同时开发了配套的手机应用程序,使得管理者能够随时随地查看环境状况,并进行远程控制。整体而言,该项目的设计思路充分结合了现代物联网技术和传统矿山安全管理的需求,力求通过智能化手段提升矿山作业的安全水平,减少事故发生的可能性,保障矿山工作的顺利进行。1.3 系统功能总结功能类别描述环境监测实时采集矿山环境的温度、湿度、瓦斯浓度、颗粒物浓度等数据。自动警报当环境参数超过预设安全阈值时,自动触发蜂鸣器警报。自动控制达到特定阈值时,自动控制风扇和雾化喷淋系统,以降低瓦斯浓度和颗粒物含量。数据显示OLED显示屏实时显示采集到的各种环境参数。数据上传通过BC26(NBIOT)模块将环境数据上传至华为云物联网平台,便于远程监控和数据分析。定时监测使用定时器进行周期性的环境参数监测,确保数据的连续性和及时性。手动控制用户可以通过按键手动控制风扇和雾化降尘设备的开关状态。远程控制开发了基于Qt框架的Android平台手机APP,实现远程控制风扇和雾化降尘设备的开关功能。数据可视化在手机APP上显示实时监测到的环境参数和警报信息。稳定供电采用5V 2A外部稳压电源为系统提供稳定的电力支持。设备控制风扇和雾化降尘设备采用5V电源供电,并通过继电器模块实现开关控制。人机交互OLED显示屏采用SPI协议,保证信息显示的准确性和实时性。1.4 开发工具的选择【1】设备端开发STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。【2】上位机开发上位机的开发选择Qt框架,编程语言采用C++;Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt能轻松创建具有原生C++性能的连接设备、用户界面(UI)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。1.5 模块的技术详情介绍【1】BC26-NBIOT模块BC26-NBIOT模块是一款专为窄带物联网(Narrow Band Internet of Things, NB-IoT)设计的无线通信模块,适用于低功耗广域网络(LPWAN)的应用场景。该模块主要针对物联网市场的需求而开发,尤其适用于那些需要长距离通信、低功耗、低成本和高容量的应用场合,如智能城市、环境监测、智能家居等领域。BC26-NBIOT模块具备良好的网络覆盖能力,能够在较远的距离内保持稳定的通信连接,这对于矿山环境作业安全监测系统来说至关重要。由于矿山内部结构复杂,通信条件苛刻,传统的无线通信技术可能难以满足要求,而NB-IoT技术凭借其优秀的穿透能力和低功耗特性,可以在这种环境下实现可靠的通信。BC26-NBIOT模块支持全球主流运营商的NB-IoT频段,这意味着它可以无缝接入不同的网络环境,为用户提供灵活的部署选项。这使得矿山监测系统不仅可以在国内使用,也可以在全球范围内实施,增强了系统的通用性和适用性。在能耗方面,BC26-NBIOT模块设计有低功耗模式,可以在不活跃期间大幅降低功耗,这对于延长电池寿命或减少系统整体功耗非常重要。尤其是在矿山这样的环境中,由于电源可能不是随时可得,低功耗特性就显得尤为关键。模块还提供了丰富的接口,包括UART、GPIO、PWM等,便于与其他传感器或执行器进行连接和数据交换。这使得开发者可以根据具体的应用需求,灵活地构建起复杂的物联网系统。同时,BC26-NBIOT模块通常支持AT命令集,这简化了开发过程,使得开发人员能够更快地上手进行开发工作。BC26-NBIOT模块以其卓越的通信性能、广泛的兼容性和低功耗特性,成为矿山环境作业安全监测系统中的理想选择,能够有效地支持数据的远程传输和系统的远程管理,提高了矿山作业的安全性和管理效率。【2】DHT11温湿度模块DHT11温湿度模块是一种经济实惠且广泛使用的数字温湿度传感器,它集成了温度和湿度感应元件以及一个信号转换电路。这款模块因其简单易用、成本低廉而被众多DIY爱好者和专业开发者所青睐,在智能家居、气象站、农业自动化等多种应用场景中都有广泛的应用。DHT11模块的核心是由一个NTC热敏电阻和一个湿度敏感电容组成的复合传感器。NTC热敏电阻用于检测环境温度的变化,而湿度敏感电容则用于检测空气中的水分含量。这些原始数据经过内部电路的处理后,通过单线串行接口输出给外部微控制器。这种集成化的处理方式大大简化了传感器的使用,使得开发人员无需关心内部的具体实现细节。在硬件接口方面,DHT11模块通常配备四个引脚,分别是电源正极(VCC)、电源地(GND)、信号输出(DATA)和预留的空引脚。其中,VCC引脚提供工作电压,通常为3.3V到5V之间;GND引脚接地;DATA引脚则是用于与外部微控制器进行数据通信的串行接口。为了保证数据传输的稳定性,通常会在DATA引脚与GND之间接一个上拉电阻。在软件层面上,DHT11模块的操作相对简单,它遵循一种特定的通信协议。当微控制器想要读取温湿度数据时,需要向DHT11发送一个启动信号,然后等待DHT11回应一个确认信号。之后,DHT11会依次发送湿度整数部分、湿度小数部分、温度整数部分、温度小数部分以及一个校验位。开发人员只需要编写简单的函数来发送启动信号,并接收和解析返回的数据即可。DHT11模块具有价格优势和易于使用的特性,它的精度不高,湿度测量范围为20%RH至90%RH,精度±5%RH;温度测量范围为0℃至50℃,精度±2℃。【3】PM2.5粉尘模块PM2.5粉尘模块是一种专门用于检测空气中细颗粒物(Particulate Matter 2.5,简称PM2.5)浓度的传感器。PM2.5是指直径小于或等于2.5微米的颗粒物,这类颗粒物因为体积小、面积大、活性强,容易携带污染物,对人体健康尤其是呼吸系统有着较大的危害。因此,监测PM2.5浓度对于环境保护和个人健康具有重要意义。PM2.5粉尘模块通常基于光散射原理工作。当空气中的颗粒物通过传感器时,内置的光源(通常是红外LED)会照射这些颗粒物,导致光的散射。传感器内部装有一个光电二极管,用来接收散射光,并将其转换成电信号。通过分析这些电信号的强度,就可以估算出空气中PM2.5颗粒物的浓度。这种检测方法简单、快速,适用于各种便携式或固定式的空气质量监测设备。市场上常见的PM2.5粉尘模块如PMS5003、SDS011等,它们通常具备较小的尺寸和较低的功耗,适合集成到各种物联网设备中。这些模块一般都提供标准的串行通信接口(如TTL UART),可以直接与微控制器(如STM32系列)相连,进行数据的读取和处理。此外,一些高级模块还支持I2C或SPI接口,提供更多的配置选项和更高的数据传输速率。在硬件设计上,PM2.5粉尘模块内部集成了气流通道、光源、光接收器以及信号处理电路。为了保证测量结果的准确性,模块内部通常设有风机来确保空气能够均匀流动并通过传感器区域。此外,为了防止外界干扰,传感器通常会配备有防尘网或过滤器,以保护内部元件不受污染。从软件角度来看,使用PM2.5粉尘模块相对简单。开发人员只需要按照模块提供的数据手册编写相应的驱动程序,就能实现对模块的初始化和数据读取。大多数模块都会提供一整套的通信协议,其中包括了如何发送查询命令以及如何解析返回的数据格式。例如,一些模块会以ASCII码形式返回数据,包含PM2.5、PM10等不同粒径颗粒物的浓度值,以及其他辅助信息如温度、湿度等。值得注意的是,虽然PM2.5粉尘模块在一定程度上能够提供准确的颗粒物浓度数据,但在实际应用中,还需要考虑诸如环境温度、湿度等因素对测量结果的影响。此外,为了确保数据的长期稳定性和准确性,定期对传感器进行校准也是非常必要的。PM2.5粉尘模块作为一种有效的颗粒物浓度监测工具,已经广泛应用于家庭、办公室、工厂等各种环境下的空气质量监测系统中,为人们提供了便捷的方式来监控和改善生活环境质量。二、BC26-NBIOT模块调试过程2.1 模块调试接线2.2 测试模块第一步接上之后,串口调试助手选择波特率为115200,勾选软件上的发送新行选项。发送AT过去,正常模块会返回OK。只有收到了OK,才表示模块工作正常。2.3 上电初始化操作【1】查询模块是否正常ATOK【2】获取卡号,查询卡是否插好AT+CIMI460041052911195OK【3】激活网络AT+CGATT=1OK【4】获取网络激活状态AT+CGATT?+CGATT: 1OK【5】查询网络质量AT+CSQ+CSQ: 26,0OK 【6】 检查网络状态AT+CEREG=? //+CEREG: 0,1 //找网成功OK2.4 开启GPS定位如果需要使用GPS定位就开,不需要使用就不用管。使用GPS定位还需要将模块上的GPS天线接好,否则也是没有信号的。官方文档:【1】激活GPS,要等一段时间AT+QGNSSC=1OK【2】查询激活状态,1表示成功激活AT+QGNSSC?+QGNSSC: 1OK【3】获取一次GPS定位语句AT+QGNSSRD="NMEA/RMC"+QGNSSRD: $GNRMC,120715.00,A,3150.78179,N,11711.93433,E,0.000,,310818,,,A,V*19OK二、部署华为云物联网平台华为云官网: cid:link_11打开官网,搜索物联网,就能快速找到 设备接入IoTDA。2.1 物联网平台介绍华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助我们快速构筑物联网解决方案。使用物联网平台构建一个完整的物联网解决方案主要包括3部分:物联网平台、业务应用和设备。物联网平台作为连接业务应用和设备的中间层,屏蔽了各种复杂的设备接口,实现设备的快速接入;同时提供强大的开放能力,支撑行业用户构建各种物联网解决方案。设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台,并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台,平台也可以将控制命令下发给设备。业务应用通过调用物联网平台提供的API,实现设备数据采集、命令下发、设备管理等业务场景。2.2 开通物联网服务地址: cid:link_8点击立即创建。正在创建标准版实例,需要等待片刻。创建完成之后,点击实例名称。 可以看到标准版实例的设备接入端口和地址。在上面也能看到 免费单元的限制。开通之后,点击总览,也能查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。总结:端口号: MQTT (1883)| MQTTS (8883) 接入地址:ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com根据域名地址得到IP地址信息:打开Windows电脑的命令行控制台终端,使用ping 命令。ping一下即可。Microsoft Windows [版本 10.0.19045.4170](c) Microsoft Corporation。保留所有权利。C:\Users\11266>ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com正在 Ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:来自 117.78.5.125 的回复: 字节=32 时间=35ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=39ms TTL=93117.78.5.125 的 Ping 统计信息: 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),往返行程的估计时间(以毫秒为单位): 最短 = 35ms,最长 = 39ms,平均 = 36msC:\Users\11266>MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口比较合适。 接下来的ESP8266就采用1883端口连接华为云物联网平台。2.3 创建产品(1)创建产品(2)填写产品信息根据自己产品名字填写,下面的设备类型选择自定义类型。(3)产品创建成功创建完成之后点击查看详情。(4)添加自定义模型产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。模型简单来说: 就是存放设备上传到云平台的数据。你可以根据自己的产品进行创建。比如:烟雾可以叫 MQ2温度可以叫 Temperature湿度可以叫 humidity火焰可以叫 flame其他的传感器自己用单词简写命名即可。 这就是你的单片机设备端上传到服务器的数据名字。先点击自定义模型。再创建一个服务ID。接着点击新增属性。2.4 添加设备产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。(1)注册设备(2)根据自己的设备填写(3)保存设备信息创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。(4)设备创建完成(5)设备详情2.5 MQTT协议主题订阅与发布(1)MQTT协议介绍当前的设备是采用MQTT协议与华为云平台进行通信。MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端,已经形成了初步的生态系统。MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;MQTT协议是工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;所以,只要具备TCP协议栈的网络设备都可以使用MQTT协议。 本次设备采用的ESP8266就具备TCP协议栈,能够建立TCP连接,所以,配合STM32代码里封装的MQTT协议,就可以与华为云平台完成通信。华为云的MQTT协议接入帮助文档在这里: cid:link_6业务流程:(2)华为云平台MQTT协议使用限制描述限制支持的MQTT协议版本3.1.1与标准MQTT协议的区别支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msgMQTTS支持的安全等级采用TCP通道基础 + TLS协议(最高TLSv1.3版本)单帐号每秒最大MQTT连接请求数无限制单个设备每分钟支持的最大MQTT连接数1单个MQTT连接每秒的吞吐量,即带宽,包含直连设备和网关3KB/sMQTT单个发布消息最大长度,超过此大小的发布请求将被直接拒绝1MBMQTT连接心跳时间建议值心跳时间限定为30至1200秒,推荐设置为120秒产品是否支持自定义Topic支持消息发布与订阅设备只能对自己的Topic进行消息发布与订阅每个订阅请求的最大订阅数无限制(3)主题订阅格式帮助文档地址:cid:link_6对于设备而言,一般会订阅平台下发消息给设备 这个主题。设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。如果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。以当前设备为例,最终订阅主题的格式如下:$oc/devices/{device_id}/sys/messages/down 最终的格式:$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down(4)主题发布格式对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。这个操作称为:属性上报。帮助文档地址:cid:link_2根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结如下:发布的主题格式:$oc/devices/{device_id}/sys/properties/report 最终的格式:$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report发布主题时,需要上传数据,这个数据格式是JSON格式。上传的JSON数据格式如下:{ "services": [ { "service_id": <填服务ID>, "properties": { "<填属性名称1>": <填属性值>, "<填属性名称2>": <填属性值>, .......... } } ]}根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。根据这个格式,组合一次上传的属性数据:{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}2.6 MQTT三元组MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像我们平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。接下来介绍,华为云平台的MQTT三元组参数如何得到。(1)MQTT服务器地址要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。帮助文档地址:cid:link_1MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。根据上面的域名和端口号,得到下面的IP地址和端口号信息: 如果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。 (IP地址就是域名解析得到的)华为云的MQTT服务器地址:117.78.5.125华为云的MQTT端口号:1883如何得到IP地址?如何域名转IP? 打开Windows的命令行输入以下命令。ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com(2)生成MQTT三元组华为云提供了一个在线工具,用来生成MQTT鉴权三元组: cid:link_7打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。下面是打开的页面:填入设备的信息: (上面两行就是设备创建完成之后保存得到的)直接得到三元组信息。得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。ClientId 663cb18871d845632a0912e7_dev1_0_0_2024050911Username 663cb18871d845632a0912e7_dev1Password 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac2372.7 模拟设备登录测试经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。(1)填入登录信息打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。(2)打开网页查看完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。点击详情页面,可以看到上传的数据:到此,云平台的部署已经完成,设备已经可以正常上传数据了。(3)MQTT登录测试参数总结MQTT服务器: 117.78.5.125MQTT端口号: 183//物联网服务器的设备信息#define MQTT_ClientID "663cb18871d845632a0912e7_dev1_0_0_2024050911"#define MQTT_UserName "663cb18871d845632a0912e7_dev1"#define MQTT_PassWord "71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237"//订阅与发布的主题#define SET_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down" //订阅#define POST_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report" //发布发布的数据:{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}2.8 创建IAM账户创建一个IAM账户,因为接下来开发上位机,需要使用云平台的API接口,这些接口都需要token进行鉴权。简单来说,就是身份的认证。 调用接口获取Token时,就需要填写IAM账号信息。所以,接下来演示一下过程。地址: cid:link_4【1】获取项目凭证 点击左上角用户名,选择下拉菜单里的我的凭证项目凭证:28add376c01e4a61ac8b621c714bf459【2】创建IAM用户鼠标放在左上角头像上,在下拉菜单里选择统一身份认证。点击左上角创建用户。创建成功:【3】创建完成用户信息如下:主用户名 l19504562721IAM用户 ds_abc密码 DS123456782.9 获取影子数据帮助文档:cid:link_5设备影子介绍:设备影子是一个用于存储和检索设备当前状态信息的JSON文档。每个设备有且只有一个设备影子,由设备ID唯一标识设备影子仅保存最近一次设备的上报数据和预期数据无论该设备是否在线,都可以通过该影子获取和设置设备的属性简单来说:设备影子就是保存,设备最新上传的一次数据。我们设计的软件里,如果想要获取设备的最新状态信息,就采用设备影子接口。如果对接口不熟悉,可以先进行在线调试:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow在线调试接口,可以请求影子接口,了解请求,与返回的数据格式。调试完成看右下角的响应体,就是返回的影子数据。设备影子接口返回的数据如下:{ "device_id": "663cb18871d845632a0912e7_dev1", "shadow": [ { "service_id": "stm32", "desired": { "properties": null, "event_time": null }, "reported": { "properties": { "DHT11_T": 18, "DHT11_H": 90, "BH1750": 38, "MQ135": 70 }, "event_time": "20240509T113448Z" }, "version": 3 } ]}调试成功之后,可以得到访问影子数据的真实链接,接下来的代码开发中,就采用Qt写代码访问此链接,获取影子数据,完成上位机开发。链接如下:https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow三、上位机开发为了方便查看设备上传的数据,接下来利用Qt开发一款Android手机APP 和 Windows上位机。使用华为云平台提供的API接口获取设备上传的数据,进行可视化显示,以及远程控制设备。3.1 Qt开发环境安装Qt的中文官网: cid:link_12QT5.12.6的下载地址:cid:link_9或者去网盘里下载:cid:link_10打开下载链接后选择下面的版本进行下载:qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details软件安装时断网安装,否则会提示输入账户。安装的时候,第一个复选框里勾选一个mingw 32编译器即可,其他的不管默认就行,直接点击下一步继续安装。选择MinGW 32-bit 编译器: (一定要看清楚了)说明: 我这里只是介绍PC端,也就是Windows系统下的Qt环境搭建。 Android的开发环境比较麻烦,如果想学习Android开发,想编译Android程序的APP,需要自己去搭建Android环境。也可以看下面这篇文章,不过这个文章是在Qt开发专栏里付费的,需要订阅专栏才可以看。 如果不想付费看,也可以自行找其他教程,自己搭建好必须的环境就行了Android环境搭建的博客链接: cid:link_33.2 新建上位机工程前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。【1】新建工程【2】设置项目的名称。【3】选择编译系统【4】选择默认继承的类【5】选择编译器【6】点击完成【7】工程创建完成3.3 设计UI界面与工程配置【1】打开UI文件打开默认的界面如下:【2】开始设计界面根据自己需求设计界面。3.5 编译Windows上位机点击软件左下角的绿色三角形按钮进行编译运行。编译之后的效果:3.6 配置Android环境如果想编译Android手机APP,必须要先自己配置好自己的Android环境。(搭建环境的过程可以自行百度搜索学习)然后才可以进行下面的步骤。【1】选择Android编译器【2】创建Android配置文件创建完成。【3】配置Android图标与名称【3】编译Android上位机Qt本身是跨平台的,直接选择Android的编译器,就可以将程序编译到Android平台。然后点击构建。成功之后,在目录下可以看到生成的apk文件,也就是Android手机的安装包,电脑端使用QQ发送给手机QQ,手机登录QQ接收,就能直接安装。生成的apk的目录在哪里呢? 编译完成之后,在控制台会输出APK文件的路径。知道目录在哪里之后,在Windows的文件资源管理器里,找到路径,具体看下图,找到生成的apk文件。D:/linux-share-dir/QT/build-app_Huawei_Eco_tracking-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk四、STM32代码开发4.1 MQTT协议设计代码字数过多,无法显示...4.2 PM2.5与MQ5采集代码#include "adc.h"#include "delay.h" //初始化ADC1//这里我们仅以规则通道为例//我们默认仅开启通道1 void Adc_Init(void){ //先初始化IO口 RCC->APB2ENR|=1<<2; //使能PORTA口时钟 GPIOA->CRL&=0XFFFFFF0F;//PA1 anolog输入 RCC->APB2ENR|=1<<9; //ADC1时钟使能 RCC->APB2RSTR|=1<<9; //ADC1复位 RCC->APB2RSTR&=~(1<<9);//复位结束 RCC->CFGR&=~(3<<14); //分频因子清零 //SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M! //否则将导致ADC准确度下降! RCC->CFGR|=2<<14; ADC1->CR1&=0XF0FFFF; //工作模式清零 ADC1->CR1|=0<<16; //独立工作模式 ADC1->CR1&=~(1<<8); //非扫描模式 ADC1->CR2&=~(1<<1); //单次转换模式 ADC1->CR2&=~(7<<17); ADC1->CR2|=7<<17; //软件控制转换 ADC1->CR2|=1<<20; //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发 ADC1->CR2&=~(1<<11); //右对齐 ADC1->SQR1&=~(0XF<<20); ADC1->SQR1|=0<<20; //1个转换在规则序列中 也就是只转换规则序列1 //设置通道1的采样时间 ADC1->SMPR2&=~(3*1); //通道1采样时间清空 ADC1->SMPR2|=7<<(3*1); //通道1 239.5周期,提高采样时间可以提高精确度 ADC1->CR2|=1<<0; //开启AD转换器 ADC1->CR2|=1<<3; //使能复位校准 while(ADC1->CR2&1<<3); //等待校准结束 //该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。 ADC1->CR2|=1<<2; //开启AD校准 while(ADC1->CR2&1<<2); //等待校准结束 //该位由软件设置以开始校准,并在校准结束时由硬件清除 } //获得ADC1某个通道的值//ch:通道值 0~16//返回值:转换结果u16 Get_Adc(u8 ch) { //设置转换序列 ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道ch ADC1->SQR3|=ch; ADC1->CR2|=1<<22; //启动规则转换通道 while(!(ADC1->SR&1<<1));//等待转换结束 return ADC1->DR; //返回adc值 }//获取通道ch的转换值,取times次,然后平均 //ch:通道编号//times:获取次数//返回值:通道ch的times次转换结果平均值u16 Get_Adc_Average(u8 ch,u8 times){ u32 temp_val=0; u8 t; for(t=0;t<times;t++) { temp_val+=Get_Adc(ch); delay_ms(5); } return temp_val/times;} 4.3 DHT11温湿度采集代码#include "dht11.h"#include "delay.h"//IO方向设置#define DHT11_IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}#define DHT11_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}////IO操作函数 #define DHT11_DQ_OUT PGout(11) //数据端口 PG11 #define DHT11_DQ_IN PGin(11) //数据端口 PG11u8 DHT11_Init(void); //初始化DHT11u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度u8 DHT11_Read_Byte(void); //读出一个字节u8 DHT11_Read_Bit(void); //读出一个位u8 DHT11_Check(void); //检测是否存在DHT11void DHT11_Rst(void); //复位DHT11 //复位DHT11void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us}//等待DHT11的回应//返回1:未检测到DHT11的存在//返回0:存在u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0;}//从DHT11读取一个位//返回值:1/0u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; }//从DHT11读取一个字节//返回值:读到的数据u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat;}//从DHT11读取一次数据//temp:温度值(范围:0~50°)//humi:湿度值(范围:20%~90%)//返回值:0,正常;1,读取失败u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } }else return 1; return 0; }//初始化DHT11的IO口 DQ 同时检测DHT11的存在//返回1:不存在//返回0:存在 u8 DHT11_Init(void){ RCC->APB2ENR|=1<<8; //使能PORTG口时钟 GPIOG->CRH&=0XFFFF0FFF;//PORTG.11 推挽输出 GPIOG->CRH|=0X00003000; GPIOG->ODR|=1<<11; //输出1 DHT11_Rst(); return DHT11_Check();}五、总结该项目开发一种基于STM32单片机的矿山环境作业安全监测系统,以提高矿山作业的安全性和效率。系统集成了多种传感器,包括DHT11温湿度传感器、MQ5气体传感器和PM2.5传感器,用于实时监测矿山环境中的关键参数,如温度、湿度、瓦斯浓度和颗粒物含量。通过这些传感器,系统能够及时发现潜在的安全隐患,并采取必要的预防措施。在硬件设计方面,系统采用了STM32F103RCT6单片机作为核心控制器,配合蜂鸣器、继电器模块、OLED显示屏等组件,形成了一个完整的监测与控制系统。当检测到的环境参数超过预设的安全阈值时,系统能够自动触发报警,并通过控制风扇和雾化喷淋系统来降低瓦斯浓度和颗粒物含量,从而保障矿工的生命安全。此外,为了实现远程监控与管理,项目还引入了BC26(NBIOT)模块,将环境数据上传至华为云物联网平台,并开发了一款基于Qt框架的Android平台手机应用程序。该应用程序不仅能够实时显示环境参数,还能接收警报信息,并允许用户远程控制风扇和雾化降尘设备的开关状态,极大地提升了系统的实用性和灵活性。该矿山环境作业安全监测系统通过集成先进的传感技术和物联网技术,实现了对矿山环境的全方位监控,能够在危险发生之前提供预警,并采取有效的防护措施,对于提升矿山作业的安全管理水平具有重要意义。
-
一、前言1.1 项目介绍【1】项目开发背景随着现代农业技术的发展,智能农业逐渐成为提高农作物产量和品质的关键手段之一。传统的农业生产方式依赖于人工经验,这种方式不仅效率低下,而且难以应对气候变化带来的挑战。特别是在水资源管理和光照控制方面,传统方法往往无法提供精确的控制,这直接影响到了农作物的生长周期和最终产量。在此背景下,基于现代物联网技术的农作物生长管理系统应运而生。这类系统能够通过各种传感器实时监测农田环境,如土壤湿度、光照强度、空气温度和湿度等,并根据这些数据自动调整灌溉、照明等设施的工作状态。这种智能化的管理不仅大大减轻了农民的劳动强度,而且通过优化资源利用,提高了农作物的生产效率。本项目提出了一种基于STM32微控制器和NBIOT通信技术的农作物生长管理系统设计方案。通过将先进的微处理器技术与窄带物联网(NBIOT)结合,本系统能够在无人干预的情况下,实现对农田环境的精确控制。系统还具备远程监控和控制功能,用户可以通过手机应用程序随时查看农田的实时数据,并根据需要调整设备的工作模式。随着科技的进步和人们对食品安全重视程度的提高,智能农业管理系统的需求日益增长。本项目的开发不仅有助于推动农业向更加科学化、精准化的方向发展,同时也为实现可持续农业生产和保障粮食安全提供了技术支持。通过本系统的应用,可以预见未来的农业生产将更加高效、环保,同时也为农民带来了更大的经济效益和社会效益。【2】设计实现的功能(1)实时检测土壤含水量,并根据预设的阈值自动判断是否需要补水,进而实现自动化的灌溉控制。(2)除了自动补水功能外,系统还提供了本地按钮控制补水选项,同时支持通过远程控制手段进行手动补水操作,增加了补水控制的灵活性。(3)系统支持植物补光灯亮度的PWM自动调节,可以根据环境亮度的变化动态调整灯光亮度,以确保植物获得最佳光照条件。(4)环境温度与湿度检测功能也是系统的重要组成部分,当检测到空气温度或湿度超出设定的安全范围时,系统会触发相应的警报机制。(5)本地OLED屏幕显示当前环境的各项参数,如温度、湿度、土壤含水量以及光线照射强度,方便用户随时查看环境状态。(6)为了及时响应异常情况,系统配备了蜂鸣器报警功能。一旦发现温度、湿度或土壤含水量不符合预设的健康范围,系统会通过蜂鸣器发出声音报警。这些阈值可以通过手机应用程序进行设定。(7)为了避免由于温度突变引起的误操作,系统采用了适当的控制方法,在设定温度发生大变动时延迟系统的反应调节时间,确保系统的稳定性和准确性。(8)通过NBIOT-BC26模块,整个设备可以连接至华为云IoT物联网平台,并采用MQTT协议上传数据。基于此,设计了Android手机APP,以便用户能够远程查看设备上传的数据,并实现远程控制设备的功能,如设置设备的温度阈值等。(9)采用Qt框架开发Android手机应用程序【3】项目硬件模块组成(1)主控芯片:采用STM32F103RCT6作为核心处理器,负责处理系统中所有的逻辑运算和控制任务。(2)环境光照强度检测模块:使用BH1750传感器来测量环境光照强度,为补光灯的亮度调节提供数据支持。(3)环境温湿度检测模块:采用DHT11传感器,用于监测环境中的温度和湿度,确保农作物处于适宜的生长环境中。(4)OLED显示屏模块:选用0.96寸的SPI协议OLED显示屏,用于显示当前环境参数,如温度、湿度、土壤含水量及光线强度等信息。(5)补光灯模块:使用白色LED灯作为植物补光灯,通过PWM技术调节亮度,以适应不同环境下的光照需求。(6)声音报警模块:采用蜂鸣器作为报警装置,当环境参数超出预设阈值时,通过蜂鸣器发出声音警报。(7)土壤湿度检测模块:使用带有ADC模拟量接口的土壤湿度检测传感器,用于实时监测土壤含水量,确保适时补水。(8)网络通信模块:采用NBIOT-BC26模块,实现设备与华为云IoT物联网平台之间的数据传输,通过MQTT协议上传数据。(9)补水控制模块:使用继电器驱动5V抽水电机,根据土壤湿度传感器的反馈信息自动或手动控制补水过程。(10)供电模块:采用USB线5V供电方式,为整个系统提供稳定的电力供应,简化了设备的安装和使用流程。【4】需求总结项目名字: 基于STM32+NBIOT设计的农作物生长管理系统实现功能:1. 实时检测土壤含水量,根据设置的阀值判断实现自动补水2. 本地可用按钮控制补水、远程手动控制补水3. 支持植物补光灯亮度PWM自动调节,可根据环境亮度调节灯光亮度4. 支持检测环境温度、湿度,当空气温度、湿度超过设定值范围时会报警。5. 本地0LED屏幕显示当前环境温度、湿度、土壤含水量、光线照射强度等参数。6. 支持蜂鸣器报警提醒,当温度、湿度、土壤含水量阀值不符合设定值时通过蜂鸣器发出声音报警(阀值可通过手机APP设定)7.采用合适的控制方法,当设定温度发生大突变时,为了防止误设置,延迟系统的反应调节时间。8. 整个设备会通过NBIOT-BC26连接华为云IOT物联网平台,通过MQTT协议上传数据到物联网云平台,再设计Android手机APP实现远程显示设备上传的数据,同时可以远程控制设备,设置设备温度阀值等等。9. 采用Qt(C++)设计Android手机APP,实现数据远程监测显示和远程控制。硬件选型:1. 主控芯片选择STM32F103RCT62. 环境光照强度检测采用BH17503. 环境温湿度检测采用DHT114. OLED显示屏采用0.96寸SPI协议显示屏5. 补光灯采用白色LED灯6. 声音报警采用蜂鸣器7. 土壤湿度检测采用ADC模拟量接口的土壤湿度检测传感器8. 联网采用NBIOT-BC26模块9. 植物补水采用继电器驱动5V抽水电机抽水进行补水。10.供电电源:采用USB线-5V供电。1.2 设计思路本项目的设计思路围绕着实现一个高度自动化、智能化的农作物生长管理系统展开,通过现代电子技术与物联网技术的融合,为农作物提供最佳的生长环境。首先,系统的核心是基于STM32F103RCT6微控制器,这是因为该芯片具备高性能、低功耗的特点,非常适合用于需要实时处理大量数据的应用场景。通过集成多种传感器,系统能够实时采集环境数据,如土壤湿度、光照强度、温度和湿度等,为后续的决策和控制提供依据。在环境监测方面,系统选用了BH1750光照强度传感器和DHT11温湿度传感器。BH1750能够精确测量光照强度,从而支持植物补光灯的PWM自动调节功能;而DHT11则用于监测空气中的温度和湿度,当这些参数超出预设的安全范围时,系统会通过蜂鸣器报警,提醒用户采取措施。系统配置了土壤湿度检测传感器,它可以实时检测土壤的含水量,并根据设定的阈值自动控制补水,确保植物获得充足的水分。为了使用户能够直观地了解环境状态,系统配备了一块0.96寸的OLED显示屏,通过SPI协议与主控芯片相连,实时显示各项环境参数。这样,即使在没有智能手机的情况下,用户也能通过显示屏掌握当前的环境状况。在联网功能上,系统采用了NBIOT-BC26模块,通过窄带物联网技术实现设备与华为云IoT物联网平台的连接。借助MQTT协议,系统能够将采集到的数据上传至云端,用户可以通过Android手机APP实时查看数据,并远程控制设备。为了进一步增强用户体验,项目还计划使用Qt框架开发Android版的应用程序,以便于用户更方便地进行远程监控和管理。在控制策略上,系统特别考虑到了温度突变可能引发的误操作问题。为此,设计了适当的延时控制机制,即当设定温度发生较大变化时,系统不会立即作出反应,而是经过一段时间的延迟后再进行调节,从而避免了因温度波动导致的误动作。在供电方面,系统选择了简单且可靠的USB线5V供电方式,不仅便于安装和维护,也确保了系统的稳定性。通过这一系列的设计思路,本项目打造一个高效、可靠且易于使用的农作物生长管理系统,助力现代农业的智能化转型。1.3 系统功能总结功能类别描述实时土壤含水量检测与自动补水系统能够实时检测土壤含水量,并根据预设阈值自动判断是否需要启动补水机制。本地与远程补水控制用户可以通过本地按钮手动控制补水,也可以通过远程手段(如手机APP)进行手动补水控制。补光灯亮度自动调节根据环境亮度变化,系统能够自动调节补光灯的亮度,以满足植物生长所需的光照条件。环境温湿度检测与报警通过传感器检测环境温度和湿度,当检测到的数值超出设定范围时,系统会触发报警机制。环境参数本地显示OLED屏幕实时显示当前环境的温度、湿度、土壤含水量及光线照射强度等参数。蜂鸣器声音报警当温度、湿度或土壤含水量不符合预设的健康范围时,系统通过蜂鸣器发出声音报警。温度突变延迟控制针对温度突变的情况,系统采用了延迟反应机制,以防止因温度快速变化而导致的误操作。数据上传与远程监控通过NBIOT-BC26模块将数据上传至华为云IoT平台,并通过MQTT协议传输数据,支持远程监控。远程控制与设置用户可以通过设计的Android手机APP实现远程控制设备,包括查看数据、控制设备和设置温度阈值等功能。1.4 开发工具的选择【1】设备端开发STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。【2】上位机开发上位机的开发选择Qt框架,编程语言采用C++;Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt能轻松创建具有原生C++性能的连接设备、用户界面(UI)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。二、部署华为云物联网平台华为云官网: cid:link_11打开官网,搜索物联网,就能快速找到 设备接入IoTDA。2.1 物联网平台介绍华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助我们快速构筑物联网解决方案。使用物联网平台构建一个完整的物联网解决方案主要包括3部分:物联网平台、业务应用和设备。物联网平台作为连接业务应用和设备的中间层,屏蔽了各种复杂的设备接口,实现设备的快速接入;同时提供强大的开放能力,支撑行业用户构建各种物联网解决方案。设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台,并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台,平台也可以将控制命令下发给设备。业务应用通过调用物联网平台提供的API,实现设备数据采集、命令下发、设备管理等业务场景。2.2 开通物联网服务地址: cid:link_8点击立即创建。正在创建标准版实例,需要等待片刻。创建完成之后,点击实例名称。 可以看到标准版实例的设备接入端口和地址。在上面也能看到 免费单元的限制。开通之后,点击总览,也能查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。总结:端口号: MQTT (1883)| MQTTS (8883) 接入地址:ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com根据域名地址得到IP地址信息:打开Windows电脑的命令行控制台终端,使用ping 命令。ping一下即可。Microsoft Windows [版本 10.0.19045.4170](c) Microsoft Corporation。保留所有权利。C:\Users\11266>ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com正在 Ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:来自 117.78.5.125 的回复: 字节=32 时间=35ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=39ms TTL=93117.78.5.125 的 Ping 统计信息: 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),往返行程的估计时间(以毫秒为单位): 最短 = 35ms,最长 = 39ms,平均 = 36msC:\Users\11266>MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口比较合适。 接下来的ESP8266就采用1883端口连接华为云物联网平台。2.3 创建产品(1)创建产品(2)填写产品信息根据自己产品名字填写,下面的设备类型选择自定义类型。(3)产品创建成功创建完成之后点击查看详情。(4)添加自定义模型产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。模型简单来说: 就是存放设备上传到云平台的数据。你可以根据自己的产品进行创建。比如:烟雾可以叫 MQ2温度可以叫 Temperature湿度可以叫 humidity火焰可以叫 flame其他的传感器自己用单词简写命名即可。 这就是你的单片机设备端上传到服务器的数据名字。先点击自定义模型。再创建一个服务ID。接着点击新增属性。2.4 添加设备产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。(1)注册设备(2)根据自己的设备填写(3)保存设备信息创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。(4)设备创建完成(5)设备详情2.5 MQTT协议主题订阅与发布(1)MQTT协议介绍当前的设备是采用MQTT协议与华为云平台进行通信。MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端,已经形成了初步的生态系统。MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;MQTT协议是工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;所以,只要具备TCP协议栈的网络设备都可以使用MQTT协议。 本次设备采用的ESP8266就具备TCP协议栈,能够建立TCP连接,所以,配合STM32代码里封装的MQTT协议,就可以与华为云平台完成通信。华为云的MQTT协议接入帮助文档在这里: cid:link_6业务流程:(2)华为云平台MQTT协议使用限制描述限制支持的MQTT协议版本3.1.1与标准MQTT协议的区别支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msgMQTTS支持的安全等级采用TCP通道基础 + TLS协议(最高TLSv1.3版本)单帐号每秒最大MQTT连接请求数无限制单个设备每分钟支持的最大MQTT连接数1单个MQTT连接每秒的吞吐量,即带宽,包含直连设备和网关3KB/sMQTT单个发布消息最大长度,超过此大小的发布请求将被直接拒绝1MBMQTT连接心跳时间建议值心跳时间限定为30至1200秒,推荐设置为120秒产品是否支持自定义Topic支持消息发布与订阅设备只能对自己的Topic进行消息发布与订阅每个订阅请求的最大订阅数无限制(3)主题订阅格式帮助文档地址:cid:link_6对于设备而言,一般会订阅平台下发消息给设备 这个主题。设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。如果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。以当前设备为例,最终订阅主题的格式如下:$oc/devices/{device_id}/sys/messages/down 最终的格式:$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down(4)主题发布格式对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。这个操作称为:属性上报。帮助文档地址:cid:link_2根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结如下:发布的主题格式:$oc/devices/{device_id}/sys/properties/report 最终的格式:$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report发布主题时,需要上传数据,这个数据格式是JSON格式。上传的JSON数据格式如下:{ "services": [ { "service_id": <填服务ID>, "properties": { "<填属性名称1>": <填属性值>, "<填属性名称2>": <填属性值>, .......... } } ]}根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。根据这个格式,组合一次上传的属性数据:{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}2.6 MQTT三元组MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像我们平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。接下来介绍,华为云平台的MQTT三元组参数如何得到。(1)MQTT服务器地址要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。帮助文档地址:cid:link_1MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。根据上面的域名和端口号,得到下面的IP地址和端口号信息: 如果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。 (IP地址就是域名解析得到的)华为云的MQTT服务器地址:117.78.5.125华为云的MQTT端口号:1883如何得到IP地址?如何域名转IP? 打开Windows的命令行输入以下命令。ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com(2)生成MQTT三元组华为云提供了一个在线工具,用来生成MQTT鉴权三元组: cid:link_7打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。下面是打开的页面:填入设备的信息: (上面两行就是设备创建完成之后保存得到的)直接得到三元组信息。得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。ClientId 663cb18871d845632a0912e7_dev1_0_0_2024050911Username 663cb18871d845632a0912e7_dev1Password 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac2372.7 模拟设备登录测试经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。(1)填入登录信息打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。(2)打开网页查看完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。点击详情页面,可以看到上传的数据:到此,云平台的部署已经完成,设备已经可以正常上传数据了。(3)MQTT登录测试参数总结MQTT服务器: 117.78.5.125MQTT端口号: 183//物联网服务器的设备信息#define MQTT_ClientID "663cb18871d845632a0912e7_dev1_0_0_2024050911"#define MQTT_UserName "663cb18871d845632a0912e7_dev1"#define MQTT_PassWord "71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237"//订阅与发布的主题#define SET_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down" //订阅#define POST_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report" //发布发布的数据:{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}2.8 创建IAM账户创建一个IAM账户,因为接下来开发上位机,需要使用云平台的API接口,这些接口都需要token进行鉴权。简单来说,就是身份的认证。 调用接口获取Token时,就需要填写IAM账号信息。所以,接下来演示一下过程。地址: cid:link_4【1】获取项目凭证 点击左上角用户名,选择下拉菜单里的我的凭证项目凭证:28add376c01e4a61ac8b621c714bf459【2】创建IAM用户鼠标放在左上角头像上,在下拉菜单里选择统一身份认证。点击左上角创建用户。创建成功:【3】创建完成用户信息如下:主用户名 l19504562721IAM用户 ds_abc密码 DS123456782.9 获取影子数据帮助文档:cid:link_5设备影子介绍:设备影子是一个用于存储和检索设备当前状态信息的JSON文档。每个设备有且只有一个设备影子,由设备ID唯一标识设备影子仅保存最近一次设备的上报数据和预期数据无论该设备是否在线,都可以通过该影子获取和设置设备的属性简单来说:设备影子就是保存,设备最新上传的一次数据。我们设计的软件里,如果想要获取设备的最新状态信息,就采用设备影子接口。如果对接口不熟悉,可以先进行在线调试:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow在线调试接口,可以请求影子接口,了解请求,与返回的数据格式。调试完成看右下角的响应体,就是返回的影子数据。设备影子接口返回的数据如下:{ "device_id": "663cb18871d845632a0912e7_dev1", "shadow": [ { "service_id": "stm32", "desired": { "properties": null, "event_time": null }, "reported": { "properties": { "DHT11_T": 18, "DHT11_H": 90, "BH1750": 38, "MQ135": 70 }, "event_time": "20240509T113448Z" }, "version": 3 } ]}调试成功之后,可以得到访问影子数据的真实链接,接下来的代码开发中,就采用Qt写代码访问此链接,获取影子数据,完成上位机开发。链接如下:https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow三、上位机开发为了方便查看设备上传的数据,接下来利用Qt开发一款Android手机APP 和 Windows上位机。使用华为云平台提供的API接口获取设备上传的数据,进行可视化显示,以及远程控制设备。3.1 Qt开发环境安装Qt的中文官网: cid:link_12QT5.12.6的下载地址:cid:link_9或者去网盘里下载:cid:link_10打开下载链接后选择下面的版本进行下载:qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details软件安装时断网安装,否则会提示输入账户。安装的时候,第一个复选框里勾选一个mingw 32编译器即可,其他的不管默认就行,直接点击下一步继续安装。选择MinGW 32-bit 编译器: (一定要看清楚了)说明: 我这里只是介绍PC端,也就是Windows系统下的Qt环境搭建。 Android的开发环境比较麻烦,如果想学习Android开发,想编译Android程序的APP,需要自己去搭建Android环境。也可以看下面这篇文章,不过这个文章是在Qt开发专栏里付费的,需要订阅专栏才可以看。 如果不想付费看,也可以自行找其他教程,自己搭建好必须的环境就行了Android环境搭建的博客链接: cid:link_33.2 新建上位机工程前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。【1】新建工程【2】设置项目的名称。【3】选择编译系统【4】选择默认继承的类【5】选择编译器【6】点击完成【7】工程创建完成3.3 设计UI界面与工程配置【1】打开UI文件打开默认的界面如下:【2】开始设计界面根据自己需求设计界面。3.5 编译Windows上位机点击软件左下角的绿色三角形按钮进行编译运行。编译之后的效果:3.6 配置Android环境如果想编译Android手机APP,必须要先自己配置好自己的Android环境。(搭建环境的过程可以自行百度搜索学习)然后才可以进行下面的步骤。【1】选择Android编译器【2】创建Android配置文件创建完成。【3】配置Android图标与名称【3】编译Android上位机Qt本身是跨平台的,直接选择Android的编译器,就可以将程序编译到Android平台。然后点击构建。成功之后,在目录下可以看到生成的apk文件,也就是Android手机的安装包,电脑端使用QQ发送给手机QQ,手机登录QQ接收,就能直接安装。生成的apk的目录在哪里呢? 编译完成之后,在控制台会输出APK文件的路径。知道目录在哪里之后,在Windows的文件资源管理器里,找到路径,具体看下图,找到生成的apk文件。D:/linux-share-dir/QT/build-app_Huawei_Eco_tracking-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk四、STM32代码开发4.1 MQTT协议设计代码字数过多,无法显示...4.2 OLED显示屏驱动代码#include "oled.h"#include "stdlib.h"#include "oledfont.h" #include "delay.h"//OLED模式设置//0: 4线串行模式 (模块的BS1,BS2均接GND)//1: 并行8080模式 (模块的BS1,BS2均接VCC)#define OLED_MODE 1 //---------------------------OLED端口定义-------------------------- #define OLED_CS PDout(6)#define OLED_RST PGout(15) #define OLED_RS PDout(3)#define OLED_WR PGout(14) #define OLED_RD PGout(13) //PC0~7,作为数据线#define DATAOUT(x) GPIOC->ODR=(GPIOC->ODR&0xff00)|(x&0x00FF); //输出 //使用4线串行接口时使用 #define OLED_SCLK PCout(0)#define OLED_SDIN PCout(1) #define OLED_CMD 0 //写命令#define OLED_DATA 1 //写数据//OLED控制用函数void OLED_WR_Byte(u8 dat,u8 cmd); void OLED_Display_On(void);void OLED_Display_Off(void);void OLED_Refresh_Gram(void); void OLED_Init(void);void OLED_Clear(void);void OLED_DrawPoint(u8 x,u8 y,u8 t);void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size); //OLED的显存//存放格式如下.//[0]0 1 2 3 ... 127 //[1]0 1 2 3 ... 127 //[2]0 1 2 3 ... 127 //[3]0 1 2 3 ... 127 //[4]0 1 2 3 ... 127 //[5]0 1 2 3 ... 127 //[6]0 1 2 3 ... 127 //[7]0 1 2 3 ... 127 u8 OLED_GRAM[128][8]; //更新显存到LCD void OLED_Refresh_Gram(void){ u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7) OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址 OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA); } }#if OLED_MODE==1 //8080并口 //向SSD1306写入一个字节。//dat:要写入的数据/命令//cmd:数据/命令标志 0,表示命令;1,表示数据;void OLED_WR_Byte(u8 dat,u8 cmd){ DATAOUT(dat); OLED_RS=cmd; OLED_CS=0; OLED_WR=0; OLED_WR=1; OLED_CS=1; OLED_RS=1; } #else//向SSD1306写入一个字节。//dat:要写入的数据/命令//cmd:数据/命令标志 0,表示命令;1,表示数据;void OLED_WR_Byte(u8 dat,u8 cmd){ u8 i; OLED_RS=cmd; //写命令 OLED_CS=0; for(i=0;i<8;i++) { OLED_SCLK=0; if(dat&0x80)OLED_SDIN=1; else OLED_SDIN=0; OLED_SCLK=1; dat<<=1; } OLED_CS=1; OLED_RS=1; } #endif //开启OLED显示 void OLED_Display_On(void){ OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON}//关闭OLED显示 void OLED_Display_Off(void){ OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF} //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! void OLED_Clear(void) { u8 i,n; for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00; OLED_Refresh_Gram();//更新显示}//画点 //x:0~127//y:0~63//t:1 填充 0,清空 void OLED_DrawPoint(u8 x,u8 y,u8 t){ u8 pos,bx,temp=0; if(x>127||y>63)return;//超出范围了. pos=7-y/8; bx=y%8; temp=1<<(7-bx); if(t)OLED_GRAM[x][pos]|=temp; else OLED_GRAM[x][pos]&=~temp; }//x1,y1,x2,y2 填充区域的对角坐标//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63 //dot:0,清空;1,填充 void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot) { u8 x,y; for(x=x1;x<=x2;x++) { for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot); } OLED_Refresh_Gram();//更新显示}//在指定位置显示一个字符,包括部分字符//x:0~127//y:0~63//mode:0,反白显示;1,正常显示 //size:选择字体 12/16/24void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode){ u8 temp,t,t1; u8 y0=y; u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数 chr=chr-' ';//得到偏移后的值 for(t=0;t { if(size==12)temp=asc2_1206[chr][t]; //调用1206字体 else if(size==16)temp=asc2_1608[chr][t]; //调用1608字体 else if(size==24)temp=asc2_2412[chr][t]; //调用2412字体 else return; //没有的字库 for(t1=0;t1<8;t1++) { if(temp&0x80)OLED_DrawPoint(x,y,mode); else OLED_DrawPoint(x,y,!mode); temp<<=1; y++; if((y-y0)==size) { y=y0; x++; break; } } } }//m^n函数u32 mypow(u8 m,u8 n){ u32 result=1; while(n--)result*=m; return result;} //显示2个数字//x,y :起点坐标 //len :数字的位数//size:字体大小//mode:模式 0,填充模式;1,叠加模式//num:数值(0~4294967295); void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size){ u8 t,temp; u8 enshow=0; for(t=0;t { temp=(num/mypow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { OLED_ShowChar(x+(size/2)*t,y,' ',size,1); continue; }else enshow=1; } OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); }} //显示字符串//x,y:起点坐标 //size:字体大小 //*p:字符串起始地址 void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size){ while((*p<='~')&&(*p>=' '))//判断是不是非法字符! { if(x>(128-(size/2))){x=0;y+=size;} if(y>(64-size)){y=x=0;OLED_Clear();} OLED_ShowChar(x,y,*p,size,1); x+=size/2; p++; } } //初始化SSD1306 void OLED_Init(void){ RCC->APB2ENR|=1<<4; //使能PORTC时钟 RCC->APB2ENR|=1<<5; //使能PORTD时钟 RCC->APB2ENR|=1<<8; //使能PORTG时钟 GPIOD->CRL&=0XF0FF0FFF;//PD3,6 推挽输出 GPIOD->CRL|=0X03003000; GPIOD->ODR|=1<<3; GPIOD->ODR|=1<<6; #if OLED_MODE==1 //8080并口模式 GPIOC->CRL=0X33333333; //PC0~7 OUT GPIOC->ODR|=0X00FF; GPIOG->CRH&=0X000FFFFF; //PG13,14,15 OUT GPIOG->CRH|=0X33300000; GPIOG->ODR|=7<<13; #else //4线SPI模式 GPIOC->CRL&=0XFFFFFF00; //PC0,1 OUT GPIOC->CRL|=0X00000033; GPIOC->ODR|=3<<0; GPIOG->CRH&=0X0FFFFFFF; //RST GPIOG->CRH|=0X30000000; GPIOG->ODR|=1<<15;#endif OLED_CS=1; OLED_RS=1; OLED_RST=0; delay_ms(100); OLED_RST=1; OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示 OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率 OLED_WR_Byte(80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率 OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数 OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移 OLED_WR_Byte(0X00,OLED_CMD); //默认为0 OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数. OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置 OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭 OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式 OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127; OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置 OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置 OLED_WR_Byte(0x81,OLED_CMD); //对比度设置 OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮) OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期 OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2; OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率 OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 OLED_Clear();} 4.3 DHT11温湿度模块驱动代码#include "dht11.h"#include "delay.h"//IO方向设置#define DHT11_IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}#define DHT11_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}////IO操作函数 #define DHT11_DQ_OUT PGout(11) //数据端口 PG11 #define DHT11_DQ_IN PGin(11) //数据端口 PG11u8 DHT11_Init(void); //初始化DHT11u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度u8 DHT11_Read_Byte(void); //读出一个字节u8 DHT11_Read_Bit(void); //读出一个位u8 DHT11_Check(void); //检测是否存在DHT11void DHT11_Rst(void); //复位DHT11 //复位DHT11void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us}//等待DHT11的回应//返回1:未检测到DHT11的存在//返回0:存在u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0;}//从DHT11读取一个位//返回值:1/0u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; }//从DHT11读取一个字节//返回值:读到的数据u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat;}//从DHT11读取一次数据//temp:温度值(范围:0~50°)//humi:湿度值(范围:20%~90%)//返回值:0,正常;1,读取失败u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } }else return 1; return 0; }//初始化DHT11的IO口 DQ 同时检测DHT11的存在//返回1:不存在//返回0:存在 u8 DHT11_Init(void){ RCC->APB2ENR|=1<<8; //使能PORTG口时钟 GPIOG->CRH&=0XFFFF0FFF;//PORTG.11 推挽输出 GPIOG->CRH|=0X00003000; GPIOG->ODR|=1<<11; //输出1 DHT11_Rst(); return DHT11_Check();}4.4 定时器配置代码#include "timer.h"#include "led.h"//定时器3中断服务程序 void TIM3_IRQHandler(void){ if(TIM3->SR&0X0001)//溢出中断 { LED1=!LED1; } TIM3->SR&=~(1<<0);//清除中断标志位 }//通用定时器3中断初始化//这里时钟选择为APB1的2倍,而APB1为36M//arr:自动重装值。//psc:时钟预分频数//这里使用的是定时器3!void TIM3_Int_Init(u16 arr,u16 psc){ RCC->APB1ENR|=1<<1; //TIM3时钟使能 TIM3->ARR=arr; //设定计数器自动重装值//刚好1ms TIM3->PSC=psc; //预分频器7200,得到10Khz的计数时钟 TIM3->DIER|=1<<0; //允许更新中断 TIM3->CR1|=0x01; //使能定时器3 MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2 }//TIM3 PWM部分初始化 //PWM输出初始化//arr:自动重装值//psc:时钟预分频数void TIM3_PWM_Init(u16 arr,u16 psc){ //此部分需手动修改IO口设置 RCC->APB1ENR|=1<<1; //TIM3时钟使能 RCC->APB2ENR|=1<<3; //使能PORTB时钟 GPIOB->CRL&=0XFF0FFFFF; //PB5输出 GPIOB->CRL|=0X00B00000; //复用功能输出 RCC->APB2ENR|=1<<0; //开启辅助时钟 AFIO->MAPR&=0XFFFFF3FF; //清除MAPR的[11:10] AFIO->MAPR|=1<<11; //部分重映像,TIM3_CH2->PB5 TIM3->ARR=arr; //设定计数器自动重装值 TIM3->PSC=psc; //预分频器不分频 TIM3->CCMR1|=7<<12; //CH2 PWM2模式 TIM3->CCMR1|=1<<11; //CH2预装载使能 TIM3->CCER|=1<<4; //OC2 输出使能 TIM3->CR1=0x0080; //ARPE使能 TIM3->CR1|=0x01; //使能定时器3 } //定时器5通道1输入捕获配置//arr:自动重装值//psc:时钟预分频数void TIM5_Cap_Init(u16 arr,u16 psc){ RCC->APB1ENR|=1<<3; //TIM5 时钟使能 RCC->APB2ENR|=1<<2; //使能PORTA时钟 GPIOA->CRL&=0XFFFFFFF0; //PA0 清除之前设置 GPIOA->CRL|=0X00000008; //PA0 输入 GPIOA->ODR|=0<<0; //PA0 下拉 TIM5->ARR=arr; //设定计数器自动重装值 TIM5->PSC=psc; //预分频器 TIM5->CCMR1|=1<<0; //CC1S=01 选择输入端 IC1映射到TI1上 TIM5->CCMR1|=0<<4; //IC1F=0000 配置输入滤波器 不滤波 TIM5->CCMR1|=0<<10; //IC2PS=00 配置输入分频,不分频 TIM5->CCER|=0<<1; //CC1P=0 上升沿捕获 TIM5->CCER|=1<<0; //CC1E=1 允许捕获计数器的值到捕获寄存器中 TIM5->DIER|=1<<1; //允许捕获中断 TIM5->DIER|=1<<0; //允许更新中断 TIM5->CR1|=0x01; //使能定时器2 MY_NVIC_Init(2,0,TIM5_IRQn,2);//抢占2,子优先级0,组2 }//捕获状态//[7]:0,没有成功的捕获;1,成功捕获到一次.//[6]:0,还没捕获到高电平;1,已经捕获到高电平了.//[5:0]:捕获高电平后溢出的次数u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态 u16 TIM5CH1_CAPTURE_VAL; //输入捕获值//定时器5中断服务程序 void TIM5_IRQHandler(void){ u16 tsr; tsr=TIM5->SR; if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获 { if(tsr&0X01)//溢出 { if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平了 { if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了 { TIM5CH1_CAPTURE_STA|=0X80;//标记成功捕获了一次 TIM5CH1_CAPTURE_VAL=0XFFFF; }else TIM5CH1_CAPTURE_STA++; } } if(tsr&0x02)//捕获1发生捕获事件 { if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿 { TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽 TIM5CH1_CAPTURE_VAL=TIM5->CCR1; //获取当前的捕获值. TIM5->CCER&=~(1<<1); //CC1P=0 设置为上升沿捕获 }else //还未开始,第一次捕获上升沿 { TIM5CH1_CAPTURE_STA=0; //清空 TIM5CH1_CAPTURE_VAL=0; TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿 TIM5->CNT=0; //计数器清空 TIM5->CCER|=1<<1; //CC1P=1 设置为下降沿捕获 } } } TIM5->SR=0;//清除中断标志位 }五、总结本项目致力于构建一套基于STM32F103RCT6微控制器和NBIOT-BC26通信模块的农作物生长管理系统。系统的核心功能在于实时监测农田环境中的关键参数,例如土壤含水量、环境光照强度、温度与湿度,并据此实现自动化管理。具体而言,系统能够依据预设的阈值自动控制补水,同时允许用户通过本地按钮或远程控制的方式进行手动补水。此外,系统还能根据环境亮度的变化自动调节补光灯的亮度,以保证植物获得适宜的光照条件。为了保障作物生长环境的安全性,系统配置了环境温湿度传感器(DHT11),并在检测到温度或湿度超出预设范围时触发蜂鸣器报警。这些阈值可以通过手机应用程序进行设定,使得系统更加灵活易用。系统还配备了一块0.96寸的OLED显示屏,用于实时显示环境温度、湿度、土壤含水量以及光照强度等重要参数,使用户能够直观地了解当前的环境状况。考虑到突然的温度变化可能导致误操作,系统采用了适当的控制策略,在设定温度出现较大波动时延迟系统的反应调节时间,从而避免不必要的误动作。整个设备通过NBIOT-BC26模块连接至华为云IoT平台,并采用MQTT协议上传数据,使得用户能够借助微信小程序远程监控设备状态并进行控制,包括调整设备的温度阈值等设置。项目利用Qt框架开发了一个Android版的应用程序,进一步增强了系统的远程监控与控制能力。该应用程序不仅可以显示远程监测数据,还可以让用户随时随地控制设备的各项功能。供电方面,系统选择了简便且易于获取的USB线5V供电方案,方便用户安装与使用。该项目通过集成先进的传感器技术和物联网应用,为现代化农业生产提供了一套高效、便捷且智能化的解决方案。
-
请教下,使用ArkTs在请求Token时,响应头使用 类ModelAccToken去对齐,为啥只有connection、date、server这三个字段能对齐呢,带“-”的字段解析不到。这种需要如何解析export class ModelAccToken { connection = ""; content_length = 0; content_type = ""; date = ""; server = ""; strict_transport_security = ""; x_content_type_options = ""; x_download_options = ""; x_frame_options = ""; x_iam_trace_id = ""; x_request_id = ""; x_subject_token = ""; x_xss_protection = '';}接口响应头如下:
-
一、前言1.1 项目介绍项目设计里用到的全部工具软件和文档源码,都可以在这里下载。https://pan.quark.cn/s/145a9b3f7f53【1】项目开发背景随着信息技术的发展,数据中心和通信机房作为信息处理的核心枢纽,在各行各业中扮演着越来越重要的角色。然而,由于设备密集且持续运行,机房内的温度和湿度控制成为保证设备正常运行的关键因素之一。传统的机房环境管理方式往往依赖于定期的人工巡检和手动调节,这种方式不仅效率低下,而且容易出现管理疏漏,导致设备过热或湿度过高,进而影响设备的稳定性和使用寿命。针对这一现状,本项目提出了一种基于STM32微控制器的通信机房空调与新风系统联动装置的设计方案。通过集成环境温湿度传感器、风扇控制模块以及4G通信模块,实现了对机房环境的实时监测和智能调控。特别是在数据传输方面,借助华为云IOT物联网云平台的强大功能,不仅可以远程监控机房内的环境变化,还能及时调整空调和新风系统的运行策略,确保机房环境始终处于最佳状态。同时,考虑到实际应用中的便捷性,本装置还提供了本地控制功能,用户可以通过直观的OLED显示屏了解当前环境状态,并通过简单的按键操作来调整设置,增强了用户体验。通过这样的设计,本项目不仅解决了传统机房管理中存在的问题,还极大地提高了机房环境管理的智能化水平,为机房管理人员提供了一个高效、可靠、易于操作的解决方案,进一步保障了通信设备的稳定运行,降低了运维成本。【2】设计实现的功能(1)实时采集环境参数:系统配备了DHT11温湿度传感器,能够连续不断地获取机房内的环境温度和湿度数据。(2)风扇通风散热控制:通过继电器模块控制两个5V直流电机小风扇的启停,以达到通风散热的效果,确保机房内部温度维持在安全范围内。(3)数据远程上传:利用合宙Air724UG 4G模块,将环境监测数据上传至华为云IOT物联网云平台,实现数据的云端存储与管理。(4)远程监控与控制:用户可以通过Windows客户端应用程序实时查看机房内的温度、湿度、风扇状态等信息,并能远程设置温度湿度阈值,选择运行模式(自动/手动),以及远程控制风扇的开关。(5)本地控制功能:在没有网络连接的情况下,用户依然可以通过设备上的按键来控制风扇的开关状态,以及切换设备的运行模式。(6)OLED显示屏信息展示:装置上安装了一个0.96寸的OLED显示屏,用于显示两页信息:第一页显示环境温度、湿度、温度和湿度阈值;第二页显示设备运行模式和风扇的开关状态。【3】项目硬件模块组成(1)主控模块:采用STM32F103RCT6微控制器作为核心处理器,负责处理各种传感器数据、控制输出信号以及与外部设备的通信。(2)环境监测模块:使用DHT11温湿度传感器来实时采集机房内的温度和湿度数据,为后续的环境控制提供依据。(3)显示模块:配置了一块0.96寸的OLED显示屏,通过SPI协议接口与主控芯片相连,用于显示当前环境的温度、湿度、设定阈值以及设备的运行状态。(4)风扇控制模块:包括两个5V直流电机的小风扇,通过继电器控制风扇的启动和停止,实现通风散热功能。(5)通信模块:采用合宙Air724UG 4G模块,支持全网通4G网络,用于将采集到的数据上传至华为云IOT物联网云平台,同时也支持接收来自云端的控制指令。(6)人机交互模块:包括若干个按键,允许用户进行本地控制,如设置温度湿度阈值、切换设备运行模式以及控制风扇的开关。(7)电源模块:系统使用一个5V 2A的稳压模块来提供稳定的电力供应,确保各个模块的正常工作。这些硬件模块相互协作,共同构成了一个完整的智能通信机房空调与新风系统联动装置,能够实现环境参数的实时监测、数据的远程传输与控制、以及本地的人机交互等功能。【4】需求总结项目名称: 基于STM32设计的通信机房空调与新风系统联动装置支持的功能:(1) 能够实时采集环境温度与湿度。(2) 能够控制2个风扇进行通风扇热。(3) 设备端的数据通过4G网络上传到华为云IOT物联网云平台。(4) 能够通过Windows大屏远程查看设备上传的温度、湿度,风扇开关状态,设备运行的模式。(5) 能够通过Windows大屏远程设置温度和湿度阀值,设置运行模式(自动模式和手动模式),以及控制风扇的开启和关闭。(6) 本地设备也可以通过按键控制风扇的开关,以及切换设备运行模式。(7) 本地设备带了一个0.96寸的OLED显示屏,一共显示2个页面。 第一个页面显示: 可以显示环境的温度、环境的湿度、温度阀值、湿度阀值。 第二个页面显示: 设备运行模式、风扇的开关状态。硬件选型:(1)主控芯片选择STM32F103RCT6(2)OLED显示屏选择SPI协议接口的0.96寸OLED显示屏。(3)4G模块采用合宙的Air724UG 4G模块,支持全网通4G网络。(4)环境温湿度检测采用DHT11模块。(5)风扇采用5V直流电机的小风扇,通过继电器控制风扇的开和关。(6)系统电源采用5V 2A的稳压模块进行供电,提供稳定电源。1.2 设计思路本项目的设计思路主要围绕提高通信机房环境管理的智能化和自动化水平展开。鉴于机房内设备众多且运行负荷大的特点,环境温湿度的实时监测显得尤为重要。选择了DHT11温湿度传感器来持续采集环境数据,确保能够及时反映机房内的温度和湿度变化情况。为了有效控制机房内的温度,设计中引入了风扇控制模块。通过继电器模块来驱动5V直流电机的小风扇,可以根据采集到的温度数据自动或手动控制风扇的开关,以此来调节机房内的温度,防止设备因过热而损坏。考虑到远程监控的需求,选用了合宙Air724UG 4G模块,通过4G网络将环境数据上传至华为云IOT物联网云平台,使得管理者能够在任何地点通过Windows客户端实时查看机房状态,并作出相应的调整。在本地控制方面,为了便于现场工作人员的操作,设计中加入了按键控制功能。通过简单的按键输入,可以实现风扇开关的控制以及设备运行模式的切换。为了使用户能够直观地了解当前机房的状态,项目中还配备了一块0.96寸的OLED显示屏,用以显示环境参数、设置阈值及设备运行模式等重要信息。系统整体采用STM32F103RCT6作为主控芯片,该芯片具备足够的性能来处理传感器数据、执行控制逻辑以及管理与其他模块之间的通信。为了保证系统的稳定运行,采用了5V 2A的稳压电源模块来提供可靠的电力供应。本项目的设计思路是在充分理解通信机房环境管理需求的基础上,结合现代物联网技术和智能控制手段,构建一个集数据采集、分析处理、远程监控与本地控制于一体的智能化管理系统,以提高机房环境管理的效率和可靠性。1.3 系统功能总结功能类别描述环境监测实时采集机房内的温度和湿度数据,使用DHT11模块。风扇控制通过继电器模块控制两个5V直流风扇的启停,实现通风散热。数据传输利用合宙Air724UG 4G模块将环境数据上传至华为云IOT物联网云平台。远程监控通过Windows客户端远程查看温度、湿度、风扇状态及设备运行模式。远程设置允许用户远程设置温度和湿度阈值,切换运行模式(自动/手动),控制风扇开关。本地控制提供按键输入功能,实现风扇开关控制及设备运行模式切换。显示信息OLED显示屏显示环境参数、设置阈值、设备运行模式及风扇状态。电源管理采用5V 2A稳压电源模块,确保系统稳定运行。1.4 开发工具的选择【1】设备端开发STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。【2】上位机开发上位机的开发选择Qt框架,编程语言采用C++;Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt能轻松创建具有原生C++性能的连接设备、用户界面(UI)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。二、部署华为云物联网平台华为云官网: cid:link_9打开官网,搜索物联网,就能快速找到 设备接入IoTDA。2.1 物联网平台介绍华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助我们快速构筑物联网解决方案。使用物联网平台构建一个完整的物联网解决方案主要包括3部分:物联网平台、业务应用和设备。物联网平台作为连接业务应用和设备的中间层,屏蔽了各种复杂的设备接口,实现设备的快速接入;同时提供强大的开放能力,支撑行业用户构建各种物联网解决方案。设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台,并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台,平台也可以将控制命令下发给设备。业务应用通过调用物联网平台提供的API,实现设备数据采集、命令下发、设备管理等业务场景。2.2 开通物联网服务地址: cid:link_8点击立即创建。正在创建标准版实例,需要等待片刻。创建完成之后,点击实例名称。 可以看到标准版实例的设备接入端口和地址。在上面也能看到 免费单元的限制。开通之后,点击总览,也能查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。总结:端口号: MQTT (1883)| MQTTS (8883) 接入地址:ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com根据域名地址得到IP地址信息: 打开Windows电脑的命令行控制台终端,使用ping 命令。ping一下即可。Microsoft Windows [版本 10.0.19045.4170](c) Microsoft Corporation。保留所有权利。C:\Users\11266>ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com正在 Ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:来自 117.78.5.125 的回复: 字节=32 时间=35ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93来自 117.78.5.125 的回复: 字节=32 时间=39ms TTL=93117.78.5.125 的 Ping 统计信息: 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),往返行程的估计时间(以毫秒为单位): 最短 = 35ms,最长 = 39ms,平均 = 36msC:\Users\11266>MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口比较合适。 接下来的ESP8266就采用1883端口连接华为云物联网平台。2.3 创建产品(1)创建产品(2)填写产品信息根据自己产品名字填写,下面的设备类型选择自定义类型。(3)产品创建成功创建完成之后点击查看详情。(4)添加自定义模型产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。模型简单来说: 就是存放设备上传到云平台的数据。你可以根据自己的产品进行创建。比如:烟雾可以叫 MQ2温度可以叫 Temperature湿度可以叫 humidity火焰可以叫 flame其他的传感器自己用单词简写命名即可。 这就是你的单片机设备端上传到服务器的数据名字。先点击自定义模型。再创建一个服务ID。接着点击新增属性。2.4 添加设备产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。(1)注册设备(2)根据自己的设备填写(3)保存设备信息创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。(4)设备创建完成(5)设备详情2.5 MQTT协议主题订阅与发布(1)MQTT协议介绍当前的设备是采用MQTT协议与华为云平台进行通信。MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端,已经形成了初步的生态系统。MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;MQTT协议是工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;所以,只要具备TCP协议栈的网络设备都可以使用MQTT协议。 本次设备采用的ESP8266就具备TCP协议栈,能够建立TCP连接,所以,配合STM32代码里封装的MQTT协议,就可以与华为云平台完成通信。华为云的MQTT协议接入帮助文档在这里: cid:link_6业务流程:(2)华为云平台MQTT协议使用限制描述限制支持的MQTT协议版本3.1.1与标准MQTT协议的区别支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msgMQTTS支持的安全等级采用TCP通道基础 + TLS协议(最高TLSv1.3版本)单帐号每秒最大MQTT连接请求数无限制单个设备每分钟支持的最大MQTT连接数1单个MQTT连接每秒的吞吐量,即带宽,包含直连设备和网关3KB/sMQTT单个发布消息最大长度,超过此大小的发布请求将被直接拒绝1MBMQTT连接心跳时间建议值心跳时间限定为30至1200秒,推荐设置为120秒产品是否支持自定义Topic支持消息发布与订阅设备只能对自己的Topic进行消息发布与订阅每个订阅请求的最大订阅数无限制(3)主题订阅格式帮助文档地址:cid:link_6对于设备而言,一般会订阅平台下发消息给设备 这个主题。设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。如果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。以当前设备为例,最终订阅主题的格式如下:$oc/devices/{device_id}/sys/messages/down 最终的格式:$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down(4)主题发布格式对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。这个操作称为:属性上报。帮助文档地址:cid:link_2根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结如下:发布的主题格式:$oc/devices/{device_id}/sys/properties/report 最终的格式:$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report发布主题时,需要上传数据,这个数据格式是JSON格式。上传的JSON数据格式如下:{ "services": [ { "service_id": <填服务ID>, "properties": { "<填属性名称1>": <填属性值>, "<填属性名称2>": <填属性值>, .......... } } ]}根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。根据这个格式,组合一次上传的属性数据:{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}2.6 MQTT三元组MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像我们平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。接下来介绍,华为云平台的MQTT三元组参数如何得到。(1)MQTT服务器地址要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。帮助文档地址:cid:link_1MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。根据上面的域名和端口号,得到下面的IP地址和端口号信息: 如果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。 (IP地址就是域名解析得到的)华为云的MQTT服务器地址:117.78.5.125华为云的MQTT端口号:1883如何得到IP地址?如何域名转IP? 打开Windows的命令行输入以下命令。ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com(2)生成MQTT三元组华为云提供了一个在线工具,用来生成MQTT鉴权三元组: cid:link_7打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。下面是打开的页面:填入设备的信息: (上面两行就是设备创建完成之后保存得到的)直接得到三元组信息。得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。ClientId 663cb18871d845632a0912e7_dev1_0_0_2024050911Username 663cb18871d845632a0912e7_dev1Password 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac2372.7 模拟设备登录测试经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。(1)填入登录信息打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。(2)打开网页查看完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。点击详情页面,可以看到上传的数据:到此,云平台的部署已经完成,设备已经可以正常上传数据了。(3)MQTT登录测试参数总结MQTT服务器: 117.78.5.125MQTT端口号: 183//物联网服务器的设备信息#define MQTT_ClientID "663cb18871d845632a0912e7_dev1_0_0_2024050911"#define MQTT_UserName "663cb18871d845632a0912e7_dev1"#define MQTT_PassWord "71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237"//订阅与发布的主题#define SET_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down" //订阅#define POST_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report" //发布发布的数据:{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}2.8 创建IAM账户创建一个IAM账户,因为接下来开发上位机,需要使用云平台的API接口,这些接口都需要token进行鉴权。简单来说,就是身份的认证。 调用接口获取Token时,就需要填写IAM账号信息。所以,接下来演示一下过程。地址: cid:link_4【1】获取项目凭证 点击左上角用户名,选择下拉菜单里的我的凭证项目凭证:28add376c01e4a61ac8b621c714bf459【2】创建IAM用户鼠标放在左上角头像上,在下拉菜单里选择统一身份认证。点击左上角创建用户。创建成功:【3】创建完成用户信息如下:主用户名 l19504562721IAM用户 ds_abc密码 DS123456782.9 获取影子数据帮助文档:cid:link_5设备影子介绍:设备影子是一个用于存储和检索设备当前状态信息的JSON文档。每个设备有且只有一个设备影子,由设备ID唯一标识设备影子仅保存最近一次设备的上报数据和预期数据无论该设备是否在线,都可以通过该影子获取和设置设备的属性简单来说:设备影子就是保存,设备最新上传的一次数据。我们设计的软件里,如果想要获取设备的最新状态信息,就采用设备影子接口。如果对接口不熟悉,可以先进行在线调试:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow在线调试接口,可以请求影子接口,了解请求,与返回的数据格式。调试完成看右下角的响应体,就是返回的影子数据。设备影子接口返回的数据如下:{ "device_id": "663cb18871d845632a0912e7_dev1", "shadow": [ { "service_id": "stm32", "desired": { "properties": null, "event_time": null }, "reported": { "properties": { "DHT11_T": 18, "DHT11_H": 90, "BH1750": 38, "MQ135": 70 }, "event_time": "20240509T113448Z" }, "version": 3 } ]}调试成功之后,可以得到访问影子数据的真实链接,接下来的代码开发中,就采用Qt写代码访问此链接,获取影子数据,完成上位机开发。链接如下:https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow三、上位机开发为了方便查看设备上传的数据,接下来利用Qt开发一款Android手机APP 和 Windows上位机。使用华为云平台提供的API接口获取设备上传的数据,进行可视化显示,以及远程控制设备。3.1 Qt开发环境安装Qt的中文官网: https://www.qt.io/zh-cn/QT5.12.6的下载地址:https://download.qt.io/archive/qt/5.12/5.12.6或者去网盘里下载:https://pan.quark.cn/s/145a9b3f7f53打开下载链接后选择下面的版本进行下载:qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details软件安装时断网安装,否则会提示输入账户。安装的时候,第一个复选框里勾选一个mingw 32编译器即可,其他的不管默认就行,直接点击下一步继续安装。选择MinGW 32-bit 编译器: (一定要看清楚了)说明: 我这里只是介绍PC端,也就是Windows系统下的Qt环境搭建。 Android的开发环境比较麻烦,如果想学习Android开发,想编译Android程序的APP,需要自己去搭建Android环境。也可以看下面这篇文章,不过这个文章是在Qt开发专栏里付费的,需要订阅专栏才可以看。 如果不想付费看,也可以自行找其他教程,自己搭建好必须的环境就行了Android环境搭建的博客链接: cid:link_33.2 新建上位机工程前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。【1】新建工程【2】设置项目的名称。【3】选择编译系统【4】选择默认继承的类【5】选择编译器【6】点击完成【7】工程创建完成3.3 设计UI界面与工程配置【1】打开UI文件打开默认的界面如下:【2】开始设计界面根据自己需求设计界面。3.5 编译Windows上位机点击软件左下角的绿色三角形按钮进行编译运行。编译之后的效果:3.6 配置Android环境如果想编译Android手机APP,必须要先自己配置好自己的Android环境。(搭建环境的过程可以自行百度搜索学习)然后才可以进行下面的步骤。【1】选择Android编译器【2】创建Android配置文件创建完成。【3】配置Android图标与名称【3】编译Android上位机Qt本身是跨平台的,直接选择Android的编译器,就可以将程序编译到Android平台。然后点击构建。成功之后,在目录下可以看到生成的apk文件,也就是Android手机的安装包,电脑端使用QQ发送给手机QQ,手机登录QQ接收,就能直接安装。生成的apk的目录在哪里呢? 编译完成之后,在控制台会输出APK文件的路径。知道目录在哪里之后,在Windows的文件资源管理器里,找到路径,具体看下图,找到生成的apk文件。D:/linux-share-dir/QT/build-app_Huawei_Eco_tracking-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk四、STM32代码开发4.1 MQTT协议设计代码字数过多,无法显示...4.2 OLED显示屏驱动代码#include "oled.h"#include "stdlib.h"#include "oledfont.h" #include "delay.h"//OLED模式设置//0: 4线串行模式 (模块的BS1,BS2均接GND)//1: 并行8080模式 (模块的BS1,BS2均接VCC)#define OLED_MODE 1 //---------------------------OLED端口定义-------------------------- #define OLED_CS PDout(6)#define OLED_RST PGout(15) #define OLED_RS PDout(3)#define OLED_WR PGout(14) #define OLED_RD PGout(13) //PC0~7,作为数据线#define DATAOUT(x) GPIOC->ODR=(GPIOC->ODR&0xff00)|(x&0x00FF); //输出 //使用4线串行接口时使用 #define OLED_SCLK PCout(0)#define OLED_SDIN PCout(1) #define OLED_CMD 0 //写命令#define OLED_DATA 1 //写数据//OLED控制用函数void OLED_WR_Byte(u8 dat,u8 cmd); void OLED_Display_On(void);void OLED_Display_Off(void);void OLED_Refresh_Gram(void); void OLED_Init(void);void OLED_Clear(void);void OLED_DrawPoint(u8 x,u8 y,u8 t);void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size); //OLED的显存//存放格式如下.//[0]0 1 2 3 ... 127 //[1]0 1 2 3 ... 127 //[2]0 1 2 3 ... 127 //[3]0 1 2 3 ... 127 //[4]0 1 2 3 ... 127 //[5]0 1 2 3 ... 127 //[6]0 1 2 3 ... 127 //[7]0 1 2 3 ... 127 u8 OLED_GRAM[128][8]; //更新显存到LCD void OLED_Refresh_Gram(void){ u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7) OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址 OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA); } }#if OLED_MODE==1 //8080并口 //向SSD1306写入一个字节。//dat:要写入的数据/命令//cmd:数据/命令标志 0,表示命令;1,表示数据;void OLED_WR_Byte(u8 dat,u8 cmd){ DATAOUT(dat); OLED_RS=cmd; OLED_CS=0; OLED_WR=0; OLED_WR=1; OLED_CS=1; OLED_RS=1; } #else//向SSD1306写入一个字节。//dat:要写入的数据/命令//cmd:数据/命令标志 0,表示命令;1,表示数据;void OLED_WR_Byte(u8 dat,u8 cmd){ u8 i; OLED_RS=cmd; //写命令 OLED_CS=0; for(i=0;i<8;i++) { OLED_SCLK=0; if(dat&0x80)OLED_SDIN=1; else OLED_SDIN=0; OLED_SCLK=1; dat<<=1; } OLED_CS=1; OLED_RS=1; } #endif //开启OLED显示 void OLED_Display_On(void){ OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON}//关闭OLED显示 void OLED_Display_Off(void){ OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令 OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF} //清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! void OLED_Clear(void) { u8 i,n; for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00; OLED_Refresh_Gram();//更新显示}//画点 //x:0~127//y:0~63//t:1 填充 0,清空 void OLED_DrawPoint(u8 x,u8 y,u8 t){ u8 pos,bx,temp=0; if(x>127||y>63)return;//超出范围了. pos=7-y/8; bx=y%8; temp=1<<(7-bx); if(t)OLED_GRAM[x][pos]|=temp; else OLED_GRAM[x][pos]&=~temp; }//x1,y1,x2,y2 填充区域的对角坐标//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63 //dot:0,清空;1,填充 void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot) { u8 x,y; for(x=x1;x<=x2;x++) { for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot); } OLED_Refresh_Gram();//更新显示}//在指定位置显示一个字符,包括部分字符//x:0~127//y:0~63//mode:0,反白显示;1,正常显示 //size:选择字体 12/16/24void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode){ u8 temp,t,t1; u8 y0=y; u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数 chr=chr-' ';//得到偏移后的值 for(t=0;t { if(size==12)temp=asc2_1206[chr][t]; //调用1206字体 else if(size==16)temp=asc2_1608[chr][t]; //调用1608字体 else if(size==24)temp=asc2_2412[chr][t]; //调用2412字体 else return; //没有的字库 for(t1=0;t1<8;t1++) { if(temp&0x80)OLED_DrawPoint(x,y,mode); else OLED_DrawPoint(x,y,!mode); temp<<=1; y++; if((y-y0)==size) { y=y0; x++; break; } } } }//m^n函数u32 mypow(u8 m,u8 n){ u32 result=1; while(n--)result*=m; return result;} //显示2个数字//x,y :起点坐标 //len :数字的位数//size:字体大小//mode:模式 0,填充模式;1,叠加模式//num:数值(0~4294967295); void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size){ u8 t,temp; u8 enshow=0; for(t=0;t { temp=(num/mypow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { OLED_ShowChar(x+(size/2)*t,y,' ',size,1); continue; }else enshow=1; } OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); }} //显示字符串//x,y:起点坐标 //size:字体大小 //*p:字符串起始地址 void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size){ while((*p<='~')&&(*p>=' '))//判断是不是非法字符! { if(x>(128-(size/2))){x=0;y+=size;} if(y>(64-size)){y=x=0;OLED_Clear();} OLED_ShowChar(x,y,*p,size,1); x+=size/2; p++; } } //初始化SSD1306 void OLED_Init(void){ RCC->APB2ENR|=1<<4; //使能PORTC时钟 RCC->APB2ENR|=1<<5; //使能PORTD时钟 RCC->APB2ENR|=1<<8; //使能PORTG时钟 GPIOD->CRL&=0XF0FF0FFF;//PD3,6 推挽输出 GPIOD->CRL|=0X03003000; GPIOD->ODR|=1<<3; GPIOD->ODR|=1<<6; #if OLED_MODE==1 //8080并口模式 GPIOC->CRL=0X33333333; //PC0~7 OUT GPIOC->ODR|=0X00FF; GPIOG->CRH&=0X000FFFFF; //PG13,14,15 OUT GPIOG->CRH|=0X33300000; GPIOG->ODR|=7<<13; #else //4线SPI模式 GPIOC->CRL&=0XFFFFFF00; //PC0,1 OUT GPIOC->CRL|=0X00000033; GPIOC->ODR|=3<<0; GPIOG->CRH&=0X0FFFFFFF; //RST GPIOG->CRH|=0X30000000; GPIOG->ODR|=1<<15;#endif OLED_CS=1; OLED_RS=1; OLED_RST=0; delay_ms(100); OLED_RST=1; OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示 OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率 OLED_WR_Byte(80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率 OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数 OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移 OLED_WR_Byte(0X00,OLED_CMD); //默认为0 OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数. OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置 OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭 OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式 OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127; OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置 OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置 OLED_WR_Byte(0x81,OLED_CMD); //对比度设置 OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮) OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期 OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2; OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率 OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 OLED_Clear();} 4.3 DHT11温湿度模块驱动代码#include "dht11.h"#include "delay.h"//IO方向设置#define DHT11_IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}#define DHT11_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}////IO操作函数 #define DHT11_DQ_OUT PGout(11) //数据端口 PG11 #define DHT11_DQ_IN PGin(11) //数据端口 PG11u8 DHT11_Init(void); //初始化DHT11u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度u8 DHT11_Read_Byte(void); //读出一个字节u8 DHT11_Read_Bit(void); //读出一个位u8 DHT11_Check(void); //检测是否存在DHT11void DHT11_Rst(void); //复位DHT11 //复位DHT11void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us}//等待DHT11的回应//返回1:未检测到DHT11的存在//返回0:存在u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0;}//从DHT11读取一个位//返回值:1/0u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; }//从DHT11读取一个字节//返回值:读到的数据u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat;}//从DHT11读取一次数据//temp:温度值(范围:0~50°)//humi:湿度值(范围:20%~90%)//返回值:0,正常;1,读取失败u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } }else return 1; return 0; }//初始化DHT11的IO口 DQ 同时检测DHT11的存在//返回1:不存在//返回0:存在 u8 DHT11_Init(void){ RCC->APB2ENR|=1<<8; //使能PORTG口时钟 GPIOG->CRH&=0XFFFF0FFF;//PORTG.11 推挽输出 GPIOG->CRH|=0X00003000; GPIOG->ODR|=1<<11; //输出1 DHT11_Rst(); return DHT11_Check();}五、总结本项目设计一种基于STM32微控制器的智能通信机房空调与新风系统联动装置,以提升通信机房的环境管理效率和自动化水平。该装置能够实时监测机房内的环境温度和湿度,并根据预设阈值自动控制风扇进行散热,从而保持机房内部环境的适宜条件。系统利用合宙Air724UG 4G模块将采集到的数据上传至华为云IOT物联网云平台,支持远程监控及控制功能。通过Windows客户端界面,管理员可以实时查看机房内环境参数,调整设定值,并控制风扇的工作状态。此外,本地操作也得到了考虑,通过简单的按键输入即可完成风扇控制和工作模式的切换。为了方便现场人员查看当前状态,设备还配备了一块0.96寸的OLED显示屏,用于显示环境参数、设置值及运行状态等信息。整个系统由一个5V 2A的稳压电源模块供电,确保了系统的稳定性和可靠性。此项目的实施有助于提高通信机房的智能化管理水平,减少人工干预,降低维护成本。
-
求助下,这个请求头中的 Authorization 和 X-Security-Token 怎么算的,有没有个ArkTs的demo这里指引的查找AK/SK也没说哪个是Authorization啊
-
体验活动介绍华为云物联网平台设备接入云服务(IoTDA)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助您快速构筑物联网解决方案。本次活动体验如何使用IoT Device SDK(C)将燃气表接入华为云IoTDA平台,并实现数据上报,获取使用燃气量。实现命令下发,对燃气表进行远程控制。 活动时间2024年9月10日~2024年10月13日活动流程一、下载附件并完成《使用IoT SDK快速体验燃气表云端控制》体验任务。 二、将完成实验的截图微信反馈给小助手进行抽奖(100%中奖,微信号:hwc-iot)。截图需显示完整的华为云账号及消息状态,截图示例如下三、云声建议体验IoTDA并通过<华为云 · 云声>提交优化建议,(关联产品请选择“设备接入IoTDA”)产品侧审核采纳后可获得相应礼品!为方便交流与礼品发放,请添加小助手(微信号:hwc-iot),私聊发送关键词“体验”进群。体验内容不限于本次活动手册,还可对>>>华为云设备接入IoTDA官网、>>>华为云设备接入IoTDA文档 等进行体验;(如需使用代金券,请查看微信群公告,填写申请表)本活动为华为云IoTDA专属活动,已同步上线至“云声·建议活动”区;活动奖励可以与云声活动月度积分奖励兼得,参与情况及获奖结果也将在“云声·建议活动”中公示。奖品设置奖品获奖要求华为手表、华为10000mAh 移动电源、开发者杜邦纸双肩包、物联网书籍、华为周边礼品…完成体验任务参与抽奖,100%中奖价值50元礼品1份(桌面电脑支架等)被采纳用户体验类建议≥1条小熊派鸿蒙开发板-BearPi-HM Nano 智慧路灯被采纳用户体验类建议≥3条或功能/缺陷类建议1条*如礼品库存不足将存在替换成等价值礼品的可能;用户体验类指不影响产品基本功能的使用的建议;功能、缺陷类建议指会影响开发者完整使用产品功能或能帮助产品提升竞争力的建议;具体建议类别以产品评估为准。扫码添加小助手(微信号:hwc-iot),私聊发送关键词“体验”即可加入本次体验活动交流群!
-
获取到iot云mqtt接入信息后只能在线一个设备,如何才能让设备和手机同时都接入呢,实现手机上下发数据监控设备运行状况呢
-
微信小程序获取影子数据显示授权问题,但是我的IAM用户以及授权给IOT设备接入服务用postman测试也显示一样问题求大佬解决,以及想了好几天了 555555555555~
-
一、前言在当今这个数字化时代,软件开发与硬件交互的技术日益进步,各种编程技巧和应用解决方案层出不穷。从高效的数据处理到多媒体内容的创作,再到物联网(IoT)设备的智能互联,技术社区不断贡献着宝贵的资源与知识。本文汇总2024年8月论坛里精选的技术讨论帖,涵盖从基础算法实现到复杂系统集成的多个方面的知识。二、文章合集【1】C语言实现SHA-256算法校验文件(win32-API)cid:link_4在信息安全领域,确保数据完整性至关重要。本文将带领读者深入探讨如何使用C语言结合Windows API来实现SHA-256算法,从而有效地进行文件校验。无论是对于想要保护本地文件免受篡改的专业人士,还是对密码学感兴趣的开发者,这都是一篇不可多得的指南。【2】生成图片的base64编码(纯C语言实现)cid:link_5随着Web技术的发展,Base64编码成为了一种广泛使用的数据传输方式。本教程详细介绍了如何仅使用C语言来生成图像的Base64编码,这对于那些希望直接在C语言环境中处理图像数据的开发者来说是非常有用的。【3】基于纠错码的哈希函数构造方案cid:link_6本文提出了一个新颖的方法——利用纠错码来构建哈希函数,这种方法能够在一定程度上提高数据处理的安全性和效率。对于正在寻找创新哈希技术的研究人员和工程师而言,这篇文章提供了一个有价值的参考方向。【4】编译 ffmpeg 以支持AVS格式视频解码与解码cid:link_0FFmpeg作为一款强大的多媒体框架,支持多种视频格式。本指南专注于如何配置和编译FFmpeg,使其能够支持中国国家标准AVS视频格式,对于那些致力于在中国市场开发多媒体应用程序的开发人员来说尤为适用。【5】算法篇_C语言实现霍夫曼编码算法cid:link_7数据压缩技术在现代信息技术中扮演着重要角色。本文通过C语言实现霍夫曼编码算法,向读者展示了如何有效地压缩数据。无论您是学生还是专业开发人员,都可以从这篇教程中学到实用的压缩技巧。【6】算法篇_RGB图像数据压缩与解压(单片机使用)cid:link_1对于在资源受限环境下工作的嵌入式系统而言,高效的图像处理算法是必不可少的。本文将指导您如何在单片机上实现RGB图像的压缩与解压,适合任何希望优化其嵌入式项目图像处理能力的人士。【7】单片机拍照_将采集的RGB图像封装为BMP格式保存到SD卡cid:link_2在物联网(IoT)项目中,能够捕捉并存储图像的能力变得越来越重要。本文详细说明了如何使用单片机将拍摄的RGB图像转换成BMP格式,并存储至SD卡中,为那些正着手开发具备图像记录功能的IoT设备的工程师提供了宝贵的信息。【8】QT For Android开发-打开PPT文件cid:link_8随着移动应用的普及,跨平台开发框架如Qt成为了开发者的首选。本文将展示如何使用Qt for Android开发环境创建应用程序来打开PPT文件,为Android平台上的文档查看应用开发提供了一条清晰路径。【9】LibJPEG库使用_通过LibJPEG将RGB数据保存为JPG图片存储到磁盘cid:link_9LibJPEG是一个广泛使用的JPEG图像处理库。本教程详细讲解了如何利用LibJPEG库将RGB图像数据转换为JPEG格式并保存到磁盘上,这对于那些需要在其应用中集成JPEG支持的开发者来说非常有用。【10】局域网内探测在线好友是如何做到的?cid:link_10本文探讨了在网络技术中一个有趣的应用场景——如何在局域网内检测哪些朋友在线。它不仅解释了基本原理,还提供了一些实际案例分析,适合对网络通信有兴趣的学习者和研究者。【11】Linux下编译Eclipse Paho库采用MQTT协议连接MQTT服务器cid:link_11Eclipse Paho是一个流行的MQTT客户端库。本文将指导读者如何在Linux操作系统中编译该库,并使用MQTT协议连接到MQTT服务器,非常适合那些希望构建物联网应用的Linux开发者。【12】AI视频生成-一键创作动漫cid:link_12利用人工智能技术生成视频内容正在成为一种趋势。本文介绍了一种使用AI技术快速创建动漫视频的方法,对于创意工作者以及想要探索AI视频生成领域的个人来说都是一个很好的起点。【13】Linux下常见的几个MQTT协议库cid:link_13MQTT作为一种轻量级的消息队列传输协议,在物联网领域有着广泛的应用。本文列举并比较了几种常用的Linux下的MQTT库,帮助开发者选择最适合他们项目的库。【14】智慧鱼缸接入华为智慧生活生态链cid:link_3随着智能家居概念的兴起,越来越多的设备开始融入到生态链中。本文以智慧鱼缸为例,详细描述了如何将其接入华为智慧生活平台,展示了物联网技术在日常生活中的应用前景。
上滑加载中
推荐直播
-
全面解析华为云EI-API服务:理论基础与实践应用指南
2024/11/29 周五 18:20-20:20
Alex 华为云学堂技术讲师
本期直播给大家带来的是理论与实践结合的华为云EI-API的服务介绍。从“主要功能,应用场景,实践案例,调用流程”四个维度来深入解析“语音交互API,文字识别API,自然语言处理API,图像识别API及图像搜索API”五大场景下API服务,同时结合实验,来加深开发者对API服务理解。
正在直播 -
企业员工、应届毕业生、在读研究生共探项目实践
2024/12/02 周一 19:00-21:00
姚圣伟 在职软件工程师 昇腾社区优秀开发者 华为云云享专家 HCDG天津地区发起人
大神带你一键了解和掌握LeakyReLU自定义算子在ONNX网络中应用和优化技巧,在线分享如何入门,以及在工作中如何结合实际项目进行学习
即将直播 -
昇腾云服务ModelArts深度解析:理论基础与实践应用指南
2024/12/03 周二 14:30-16:30
Alex 华为云学堂技术讲师
如何快速创建和部署模型,管理全周期AI工作流呢?本期直播聚焦华为昇腾云服务ModelArts一站式AI开发平台功能介绍,同时结合基于ModelArts 的实践性实验,帮助开发者从理论到实验更好地理解和使用ModelArts。
去报名
热门标签