【智能家居项目】裸机版本——网卡设备接入输入子系统 | 业务子系统 | 整体效果展示

🐱作者:一只大喵咪1201
🐱专栏:《智能家居项目》
🔥格言:你只管努力,剩下的交给时间!
请添加图片描述

目录

  • 🥞网卡设备接入输入子系统
    • 🍔测试
  • 🥞业务子系统
    • 🍔输入事件转换为统一参数
    • 🍔根据参数控制设备
    • 🍔定时器按键消抖
  • 🥞整体效果展示
  • 🥞项目总结
  • 🥞源码

🥞网卡设备接入输入子系统

图
网络子系统实现了,在我们整个项目框架中,网络子系统也输入子系统中输入设备的之一,所以现在要做的就是网络子系统接入到输入子系统中。

图
如上图所示,在输入子系统中增加网卡输入设备,在头文件net_input.h中提供了增加网卡输入设备的函数声明,在input_system.c中的增加输入设备函数中再增加一个网卡输入设备,此时在宏观层面上已经将网卡输入子系统作为输入设备接入到输入子系统中了。

但是网卡设备作为输入子系统的输入设备还需要去实现:

图

如上图源文件中代码所示,创建了一个全局的网卡输入设备并进行了初始化,还实现了添加网卡输入设备的函数。

在初始化网卡输入设备的时候,用ESP8266NetInputInit函数作为该设备的初始化方法,在该函数中仅做了注册输入数据处理回调函数的工作,只有在这里注册好了,接收中断发生后才会调用这个函数来处理数据。

输入数据处理回调函数的实现需要单独讲解一下:

图
如上图代码是输入数据处理的回调函数,同样也是使用状态机模型,有三个状态,前面AT层中详细讲解过,这里类似,不同之处在于对有效数据的处理。

当有效数据读取完毕以后,要构造输入事件,也就是给InputEvent类型变量event赋值,包括事件发生事件,事件类型,并且将有效数据拷贝到事件的str成员数组中去,最后要在数据末尾赋值'\0',因为这是一个字符串。

都事件构造好以后,需要将事件上报给业务子系统,也就是将输入事件放入到输入事件的环形缓冲区中,最后将状态机恢复到初始状态以便下一次数据处理。

此时网卡就作为输入设备接入到输入子系统中了,这个过程中的核心工作就是该UART3中断函数注册回调函数,下面来看测试代码。

🍔测试

图
如上图代码所示,在上篇文章网络子系统的测试代码中增加了部分内容,如蓝色框所示。

图
如上图所示,将程序烧带到开发板并且上电以后,准备工作完成,远端发送数据后,ESP8266模块接收到网络数据,并构造成为输入事件InputEvent类型,可以看到,事件类型type=2,并且显示了有效数据。

按键按下时也会产生输入事件,可以看到输入事件类型type=0。无论什么类型的事件,都会构造一个InputEvent类型变量放入输入子系统的环形缓冲区中,只需要不断读取环形缓冲区即可。

🥞业务子系统

现在所有的子系统都实现了,接下来就是要用这些子系统共同构成业务子系统,来看下整个业务子系统有什么功能:

  1. 使用按键控制LED
  • K1控制红灯:松开后改变LED状态
  • K2控制绿灯:松开后改变LED状态
  1. 通过网络控制LED、风扇

PC端的sscom或者用微信小程序给MCU板子发送网络数据,控制板子上的设备:

  • 控制灯:LEDDevice设为:lamp1、lamp2、lamp3,一共三个LED等。

控制命令如下:

状态命令
{“dev”:“lamp1”,“status”:“1”}
{“dev”:“lamp1”,“status”:“0”}
反转{“dev”:“lamp1”,“status”:“2”}
  • 控制风扇

控制命令如下:

状态命令
顺时针旋转{“dev”:“fan”,“status”:“1”}
逆时针旋转{“dev”:“fan”,“status”:“-1”}
停止{“dev”:“fan”,“status”:“0”}
  • 离家&回家模式:离家时将3个LED灯和1个风扇都关闭,回家时将3个LED灯和1个风扇都打开。

控制命令如下:

状态命令
回家{“dev”:“home”,“status”:“0”}
离家{“dev”:“home”,“status”:“1”}

上面的控制命令采用Json格式,以“名称 ":"值”对的方式存储数据,名称和值之间是以冒号间隔,例如"Name":"A-Big-MiaoMi"

Json数据由花括号括起来,可以包含多个“名称":"值”对,以逗号隔开,例如{"Name":"A-Big-MiaoMi","Sex":"Male","Age":"24"},此时就存在三对数据。


  • 底层由按键、网卡发出InputEvent输入事件。
  • 最上层用来控制设备。

根据底层发来的参数控制设备,要屏蔽底层设备细节及它发来的数据,上层不关心底下的是按键、遥控器还是小程序,只需要告诉上层要做什么。

所以要使用Json数据来统一的参数格式,比如{"dev":"lamp1","status":"1"},此时上层就知道要让设备lamp1的状态变成1,它根本不用管这个数据是怎么来的。

无论是按键产生的输入事件函数网络产生的输入事件,都要以Json数据格式交付给上层。

  • 需要一个中间层:将各类方式产生的InputEvent输入事件转为为Json格式的参数。

图
如上图所示,业务子系统要实现这个中间层message.c,然后再在smarthome.c中根据参数控制设备。

🍔输入事件转换为统一参数

图
如上图代码所示,当输入事件产生以后,就调用该函数ConvertInputEventToJson来转换为Json格式。

首先判断是什么类型的输入事件,如果是网络输入事件,则将网络数据直接作为Json数据,因为发送网络数据就是按照Json格式发送的,相当于是远端和MCU之间的约定。

  • 使用sscom发送数据时必须按照这个Json格式发送。
  • 使用小程序时,点下按键以后,后台会自动处理为Json格式并发送。

如果是按键输入事件,先要判断按键是否松开,如果没有松开则之间返回-1,上层不处理LED灯状态。如果松开,则再判断是哪个键按下,将对应设备名和状态构造成Json格式供上层去处理LED灯状态。

🍔根据参数控制设备

tu

  • 初始化各类设备
  • 连接WIFI
  • 在OLED上显示IP、端口
  • 读取InputEvent
  • 转换为Json格式的参数
  • 控制设备

按照上诉步骤来编写代码:

tu
如上图所示代码,先初始化所有设备和子系统,再显示启动信息,表明业务系统正在启动,再显示正在连接信息,连接WIFI,连接好之后显示ESP8266的IP地址和端口号,做好所有准备以后,在循环中检测输入事件,并转换为Json格式。

  • 本喵将WIFI名称和账号使用define内嵌到了程序中,可以根据具体WIFI情况作修改。

各个步骤都是用一个函数实现的,接下来就讲解一下这些函数的实现:

图
如上图所示代码,在初始化设备和子系统函数中,初始化了LED设备,风扇,显示设备,字库子系统,所有输入子系统,网络子系统,每一部分初始化都按照前面各个单元测试时的步骤来。

图

如上图所示代码,前两个函数只是用来表明业务子系统正在启动或者正在连接WIFI,都是通过OLED设备显示的。在连接WIFI的时候,放在一个循环中连接,直到连接成功。

图
如上图所示代码,WIFI连接成功以后,将ESP8266的IP地址和端口号以及作者信息显示到OLED屏幕上。

图
如上图所示代码是业务子系统根据Json数据来控制设备的,首先要解析Json数据格式,获取设备名称,以及设备状态,都是使用的C库函数strstr来查找字串。

获取到的设备状态有大于0小于0以及等于0三种情况,如果是小于0则状态部分有两个字节,第一个字节是-说明是一个负数,否则就是大于等于0的数。

  • ASCII码数字字符 - 0得到的就是整形数字。
  • 负的数字字符需要单独处理-和字符两个字节。

然后根据设备名字,使用C库函数strncmp来判断是哪个设备,如果是LED设备,则把状态值status给它的Control方法来改变LED灯状态,风扇也是同样的道理。

如果设备名是回家,则将所有LED和风扇都打开,如果是离家则都关闭。

  • 使用for循环打开3个LED灯这里不太完美,如果三个LED等的编号不是0,1,2则不能这样。

🍔定时器按键消抖

按键输入设备中,需要给按键消抖:

图
如上图所示,理想情况下,每按一次按键,产生一次按键中断,也就是按键所在引脚的电平由高电平直接变成低电平,记录一次数据。

图
如上图,但是实际情况是,按下按键以后,由于按键金属片的机械振动,会导致引脚电平发生反复变化,就会发生多次中断,假设发生了五次,难道这五次需要都记录吗?肯定不是,我们只按下一次,所以在程序理也需要只记录一次。

所以就要消除这个机械抖动,通常有三种方式:

  • 硬件消抖

就是在机械结构或者电路中设计一些消抖结构或者消抖电路,对于我们写软件的人来说,这种方式不必考虑。

  • 延时消抖

在前面的图中可以看到,虽然电平会因为抖动而反复变化,但最终还是会稳定到低电平,可以让程序在机械抖动这个过程中停止不动,也就是延时,待抖动停止后再读取这个数据,这就是延时消抖。

但是在使用HAL库的HAL_Delay()函数在按键中断中消抖时会出现问题,HAL_Delay是使用SysTick计时的,它也会产生中断。

但是默认情况下,SysTick中断的优先级是最低的,而我们一般设置的中断优先级都是比较高的,所以在我们的中断函数中调用HAL_Delay时,SysTick的中断就无法打断我们的中断,就无法执行延时函数。

而我们的中断函数中,它在等SysTick中断函数执行完毕才会继续向下执行,此时就会导致程序卡死了,不再动了。

  • 我们自己的中断函数中不能调用HAL_Dealy延时函数,否则会卡死不动。
  • 定时器消抖

图
如上图,同样是延时消抖的思想,假设我们给它设置了10ms延时,也就是一个timer,每发生一次中断,就延时一个timer,直到不再抖动稳定下来才记录。

这种方式中,每发生一次中断,延时就推后一个timer,也就是从头开始计时一个timer

  • 按键中断这里采用的是上升和下降沿都触发。

图
如上图所示代码,在按键设备中的头文件gpio_key.h中增加获取按键的定时时间(延时多久了),设置按键的定时器事件(要延时多久),以及一个对按键定时器处理的函数。

图

如上图对应gpio_key.c中的源文件,创建一个timers数组,大小为2,因为只有两个按键,这个数组中存放的是对应按键要延时的时间值。

获取按键定时器时间就是获得这个数组中的值,表示按键会延时多久,设置定时器事件就是给这个数组设置值,表示按键要要是多久。

对于按键定时器的处理中,对两个定时器都要判断,首先要判断定时器的值不是0,说明该按键在延时,同时再判断当前系统的时间值是否大于这个定时的值,如果小于说明定时没到,大于则说明到了。

定时到了之后,要构建输入事件InputEvent,并且放入到输入事件的环形缓冲区中,上报给上层,任何将定时器值赋值为0,表示该定时器现在不用了。

  • 上报输入事件的工作在这里干了,不用在按键中断函数中上报了!!!

那么是谁来设置这个定时器时间呢?按键中断函数:

图

如上图所示按键中断函数的回调函数中,每发生一次按键中断,就给对应按键的定时器timers[i]在当前时间基础上增加20作为新的定时时间。

  • 此时中断函数不再负责上报输入事件了,只负责设置定时器事件。
  • 当抖动时,中断会产生多次,定时时间也会不断推后,每次推后20。

现在定时器已经设置好了,处理定时器的方法也有了,那么是谁去处理定时器并上报事件呢?SysTick处理函数:

图
如上图所示,在SysTick_Handler函数中调用按键定时器处理函数,相当于在让系统调用这个处理函数,因为这个SysTick_Handler属于裸机内核的函数。

🥞整体效果展示

将串口调试助手打开,程序烧录到开发板中并且上电:

图
如上图所示,此时串口助手会打印很多调试信息,之后最后出现OK等字眼,说明程序启动成功。

图
如上图,此时在OLED屏幕上会显示ESP8266模块的IP地址端口号,以及项目作者。

图
如上图所示,在微信小程序上搜索“百问网嵌入式物联网”,使用百问网已经做好的配套小程序,将OLED屏幕上显示的IP地址和端口号填进去,然后提交。

图
如上图所示,在小程序中点击3种颜色的灯,通过串口调试助手的调试信息可以看到:

图
如上图,可以看到受到了3个灯的Json格式数据,程序中会解析这几个数据并且控制相应的设备:

图
如上图,此时三个灯就都亮了,同样可以使用两个按键控制白灯和蓝灯。

风扇也可以通过小程序界面去控制,还有离家模式和回家模式,本喵就不一一展示了。


图
如上图所示,也可以通过远端软件sscom发送Json格式的数据,如绿色框中所示,但是切记不要加回车换行,此时远端就会将数据发送给ESP8266,然后通过串口调试助手打印接收到的信息,MCU会解析数据,进而控制风扇设备反转。

  • 使用sscom发送的数据必须是Json格式的,而且设备名也必须是文章开头提到的,因为这是我们和MCU之间的约定。
  • 在点下小程序的某个控制块后,它也会在后台发送对应的Json数据给ESP8266,只是我们在手机上看不到,但是可以通过串口调试助手看到。

🥞项目总结

至此智能家居的项目裸机版本就实现了,整个项目中最重要的就是在传递:

  • 面向对象的编程思想和方法
  • 分层的思想和编程架构

无论使用哪种设备,哪种子系统,在业务子系统层面都不用关心它们的底层实现,只需要调用提供的结构就行,都是按照这样的顺序来用:

  • 创建设备对象
  • 添加所有设备
  • 获取需要的设备并进行初始化
  • 调用设备的操作方法。

几乎都是按照这样的顺序去使用,如果需要配合其他系统则添加相应的系统并初始化就可以了。

🥞源码

完整裸机版智能家居项目源码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/103195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【业务功能篇 131】23种设计模式介绍

第一章 设计模式概述 1.1 代码质量好坏如何评价? 要想学习设计模式呢 我们就必须搞清楚设计模式到底在我们的编程过程中起到了怎样的作用,在编程世界中它处在一个什么样的位置,它到底是一种抽象的设计思想,还是一套具体的落地方案. 在学习设计模式之前呢 我们需要了解一下 代…

CRM系统:快速实现外勤出差人员远程访问企业提升工作效率!

🎬 鸽芷咕:个人主页 🔥 个人专栏:《速学数据结构》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活! 文章目录 快速实现外勤出差人员远程访问企业CRM系统前言1. 无需公网IP,高效低成本实现CRM系统远程访问1.1 下…

Docker 的数据管理和Dockerfile镜像的创建

目录 Docker 的数据管理 管理 Docker 容器中数据的方式 端口映射 容器互联(使用centos镜像) Docker 镜像的创建 Dockerfile 操作常用的指令 编写 Dockerfile 时格式 Dockerfile 案例 Docker 的数据管理 管理 Docker 容器中数据的方式 管理 Doc…

C# AnimeGAN 漫画风格迁移 动漫风格迁移 图像卡通化 图像动漫化

效果 项目 模型 animeganv3_H40_model.onnx animeganv3_H50_model.onnx animeganv3_H64_model.onnx AnimeGANv3_JP_face_v1.0.onnx AnimeGANv3_PortraitSketch_25.onnx Hayao-60.onnx Hayao_64.onnx Paprika_54.onnx Shinkai_53.onnx 下载 可执行文件exe下载 源码下载

JAVA IO 流分类整理

一、JAVA IO 流分为三种: 1、按照流向:输入流和输出流 2、按照操作单元:字节流和字符流 3、按照流的角色:节点流和处理流 二、JAVA IO 流的40多个类都派生自4个抽象类 1、字节输入流(InputStream) 、 2、字…

Pycharm 2023 设置远程调试

pycharm 版本 : 2023.2.1 整体流程参考:https://blog.csdn.net/xuanhaolaile/article/details/128293254 首先确定远程服务器上已经安装好 requirements.txt 中所需的依赖包。 1、SSH Configurations 添加远程服务器 2、Python Interpreter 注意&…

spring boot自定义配置时在yml文件输入有提示

自定义一个配置类&#xff0c;然后在yml文件具体配置值时&#xff0c;一般不会有提示&#xff0c;这个解决这个问题 依赖 <!--自定义配置类&#xff0c;在yml文件写的时候会有提示--><dependency><groupId>org.springframework.boot</groupId><arti…

Godot2D角色导航-自动寻路教程(Godot实现角色随鼠标移动)

文章目录 运行结果2D导航概述开始前的准备2D导航创建导航网格创建角色 其他文章 运行结果 2D导航概述 Godot为2D和3D游戏提供了多个对象、类和服务器&#xff0c;以便于基于网格或基于网格的导航和路径查找。 说到导航&#xff0c;就得说一下导航网格&#xff0c;导航网格定义…

多标签分类论文笔记 | ML-Decoder: Scalable and Versatile Classification Head

个人论文精读笔记&#xff0c;主要是翻译心得&#xff0c;欢迎旁观&#xff0c;如果有兴趣可以在评论区留言&#xff0c;我们一起探讨。 Paper: https://arxiv.org/pdf/2111.12933.pdf Code: https://github.com/Alibaba-MIIL/ML_Decoder 文章目录 0. 摘要1. 介绍2. 方法2.1 Ba…

免疫球蛋白介绍

免疫球蛋白&#xff08;Immunoglobulin&#xff0c;Ig&#xff09;是广泛存在于哺乳动物血清、淋巴液、组织液和外分泌液中的一种具有抗体活性或化学结构与抗体相似的球蛋白&#xff0c;在机体防御疾病的重要成分在疾病研究、药物研发、疫苗评价中具有重要作用。抗体&#xff0…

【实训项目】“优品果园”-线上水果商城小程序

1.项目背景 随着现代人对消费水平的追求以及对食物安全的需要&#xff0c;无污染、产地直销的有机水果受到越来越多市民的喜欢。交易过程的简洁化是现代消费者的追求&#xff0c;产地直销也是近期流行的一种新型的交易模式。产地直销的交易模式使得交易过程更加简便快捷&#…

【MySQL】关于MySQL升级到8.0版本的实践方案

关于MySQL升级到8.0版本的实践方案 关于数据库版本升级,一直都是热议话题,对于升级的缘由各家也有所不同,有业务驱动的,有DBA自发驱动的,有规划导向也有方向指引的……抛开各种原因,当升级这个决定落下来的时候,对于DBA手头的几百几千套数据库来说,就好比是一场动物大…

[电源选项]没有系统散热方式,没有被动散热选项

背景 笔记本的风扇声音太大&#xff0c;想改成被动散热方式&#xff0c;又不想影响性能。 于是我打开了控制面板\所有控制面板项\电源选项&#xff0c;点更改计划设置-> 更改高级电源设置。 想把散热方式改成被动散热。发现win11中好像没有这个选项了&#xff01; 如何…

198、RabbitMQ 的核心概念 及 工作机制概述; Exchange 类型 及 该类型对应的路由规则;了解什么是JMS。

目录 JMS 讲解★ RabbitMQ的核心概念★ RabbitMQ工作机制★ Connection&#xff08;连接&#xff09; 与 Channel&#xff08;通信信道&#xff09;★ Exchange★ Exchange与Queue★ Exchange的类型&#xff08;4种&#xff09;及 该类型对应的路由规则 看RabbitMQ 之前&#x…

技术分享| 二进制部署MySQL

一、介绍 ​MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database Management System&#x…

拼多多历史价格数据接口,拼多多商品历史价格接口,拼多多API接口

采集拼多多商品历史价格接口可以采用以下方式&#xff1a; 使用价格监控工具。价格监控工具是一种可以自动监测商品价格变化的工具&#xff0c;它可以帮助消费者快速采集拼多多商品价格信息&#xff0c;还可以提供价格变动趋势的图表分析&#xff0c;使消费者更好地掌握商品价…

PLL的环路滤波器

本篇文章仅为分享PLL学习过程及一些公式推导&#xff0c;如有错误&#xff0c;还请批评指正&#xff01; 文章目录 1、一阶RC低通滤波器&#xff08;II类锁相环&#xff09;2、二阶RC低通滤波器A、加电容型B、加RC低通滤波器型 3、三阶低通滤波器 锁相环3大组成部分&#xff1…

Unity 表面凝结水珠效果(无需编码案例分享)

文章目录 前言正文1、准备工作2、瓶子的表面会先慢慢变白3、身周围的物体的反射会慢慢变得模糊4、周围的反射又会慢慢的变回清晰5、出现一个个不跪着的小水珠 结语 前言 今天跟大家分享一一个非常简单的使用Unity制作出在物体便面凝结小水珠的过程动画&#xff0c;老规矩先上图…

JMeter三种常用的逻辑控制器

一. 如果&#xff08;if&#xff09;控制器 1.1 使用js语法来判断&#xff1a; ## 1.2 使用jexl3函数来判断性能好&#xff1a; 二. 循环控制器 三. ForEach控制器 ForEach控制器一般和用户自定义变量或者正则表达式提取器一起使用&#xff0c;其在用户自定义变量或者从正…

c++视觉处理---均值滤波

均值滤波 cv::blur()函数是OpenCV中用于应用均值滤波的函数。均值滤波是一种简单的平滑技术&#xff0c;它计算每个像素周围像素的平均值&#xff0c;并用该平均值替代原始像素值。这有助于降低图像中的噪声&#xff0c;并可以模糊图像的细节。 以下是cv::blur()函数的基本用…