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

🐱作者:一只大喵咪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.rhkb.cn/news/157189.html

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

相关文章

PostGIS导入shp文件报错:dbf file (.dbf) can not be opened.

一、报错 刚开始以为是SRID输入错误,反复尝试SRID的输入,还是报错! 后来看到了这篇博客,解决了!https://blog.csdn.net/Fama_Q/article/details/117381378 二、导致报错的原因 导入的shp文件路径太深,换…

Jackson+Feign反序列化问题排查

概述 本文记录在使用Spring Cloud微服务开发时遇到的一个反序列化问题,RPC/HTTP框架使用的是Feign,JSON序列化反序列化工具是Jackson。 问题 测试环境的ELK告警日志如下: - [43f42bf7] 500 Server Error for HTTP POST "/api/open/d…

洗地机哪款最好用?口碑最好的家用洗地机推荐

洗地机方便快捷的清洁方式,如今融入到我们的日常生活需求中来了,然而,在市面上琳琅满目的洗地机品牌中,究竟哪款洗地机比较好用呢?今天,笔者将向大家推荐四款口碑最好的家用洗地机,让你在挑选时…

Java实现防重复提交,使用自定义注解的方式

目录 1.背景 2.思路 3.实现 创建自定义注解 编写拦截器 4.使用 5.验证 6.总结 1.背景 在进行添加操作时,防止恶意点击,后端进行请求接口的防重复提交 2.思路 通过拦截器搭配自定义注解的方式进行实现,拦截器拦截请求,使…

JS加密/解密之webpack打包代码逆向

Webpack 是一个强大的打包工具,能够将多个文件打包成一个或多个最终的文件。然而,将已经经过打包的代码还原回原始源代码并不是一件直接的事情,因为 webpack 打包的过程通常会对代码进行压缩、混淆和优化,丢失了部分变量名和代码结…

Gralloc ION DMABUF in Camera Display

目录 Background knowledge Introduction ia pa va and memory addressing Memory Addressing Page Frame Management Memory area management DMA IOVA and IOMMU Introduce DMABUF What is DMABUF DMABUF 关键概念 DMABUF APIS –The Exporter DMABUF APIS –The…

Flutter - 波浪动画和lottie动画的使用

demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新,请前往github查看最新代码 波浪动画三方库wave lottie动画 Lottie 是 Airbnb 开发的一款能够为原生应用添加动画效果的开源工具。具有丰富的动画效果和交互功能。 # 波浪动画 https://pub-web…

高并发下的服务容错

在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络 原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会 出现网络延迟&#xf…

线性回归模型进行特征重要性分析

目的 线性回归是很常用的模型;在局部可解释性上也经常用到。 数据归一化 归一化通常是为了确保不同特征之间的数值范围差异不会对线性模型的训练产生过大的影响。在某些情况下,特征归一化可以提高模型的性能,但并不是所有情况下都需要进行归一…

PG学习笔记(PostgreSQL)

PG学习笔记(PostgreSQL) 1、PG特点 项目极限值最大单个数据库大小不限最大最大数据单表大小32 TB单条记录最大1.6TB单字段最大允许1GB单表允许最大记录数不限单表最大字段数250~1600(取决于字段类型)单表最大索引数不限 2、PG安…

go-gin-api 本地部署调试问题总结

1.告警邮箱设置 保存后会自动将配置信息保存在fat_configs.toml 文件中; 可能出现问题:报错 550和 anth 问题,说明你的邮箱配置有问题(密码或者授权码); 2.生成数据表curd 执行结果报错 exec: “gormge…

Win10 系统中用户环境变量和系统环境变量是什么作用和区别?

环境: Win10专业版 问题描述: Win10 系统中用户环境变量和系统环境变量是什么作用和区别? 解答: 在Windows 10系统中,用户环境变量和系统环境变量是两个不同的环境变量,它们具有不同的作用和区别 1.用…

UE4中无法保存项目问题

系列文章目录 文章目录 系列文章目录前言一、解决方法 前言 取消:停止保存所有资产并返回编辑器。 重试:尝试再次保存资产。 继续:仅跳过保存该资产。 当我点击继续时,关闭项目,然后重新打开项目,发现之前…

geecg-uniapp 同源策略 数据请求 获取后台数据 进行页面渲染 ui库安装 冲突解决(3)

一,同源策略 (1)首先找到env 要是没有env 需要创建一个替换成后端接口 (2)因为他封装了 先找到 http 请求位置一级一级找 然后进行接口修改 (3)appUpdata 修改接口 运行即可 &#x…

idea中父工程Project创建

1.file-->new-->Project 2.选择maven包和JavaSDK 3.填写项目名,选择文件目录,项目包等 4.配置maven tip:约定>配置>编码 5.设置项目编码 6.注解生效激活,便于项目中使用注解 7.Java编译版本选择8 8.File Type 过滤&a…

【C++STL基础入门】list基本使用

文章目录 前言一、list简介1.1 list是什么1.2 list的头文件 二、list2.1 定义对象2.2 list构造函数2.3 list的属性函数 总结 前言 STL(Standard Template Library)是C标准库的一个重要组成部分,提供了一套丰富的数据结构和算法,可…

对CU50的修改(未使用)

目的是把CU50中的选择配置拿出来,再把最后BOM的结果拿出来。2023.10.13 一、CU50里面2个标准函数有修改: ----------LCUKOF01----函数----------------CALL FUNCTION CU01_DISPLAY_BOMEXPORTINGmasterdata rcuko-ukompRESULT …

LoRa技术未来发展前景:物联网和边缘计算的引领者

随着物联网和边缘计算的快速发展,低功耗广域网(LoRa)技术在连接远距离设备、实现长距离通信和满足低功耗需求方面崭露头角。本文将分析LoRa技术在未来的发展前景,尤其是在物联网和边缘计算领域的潜在影响。 LoRa技术的核心优势 1…

python:使用卷积神经网络(CNN)进行回归预测

作者:CSDN @ _养乐多_ 本文详细记录了从Excel或者csv中读取用于训练卷积神经网络(CNN)模型的数据,包括多个自变量和1个因变量数据,以供卷积神经网络模型的训练。随后,我们将测试数据集应用于该CNN模型,进行回归预测和分析。 该代码进一步修改可用于遥感影像回归模型. …

Android位置服务和应用权限

Github:https://github.com/MADMAX110/Odometer 一、使用位置服务 之前的Odometer应用是显示一个随机数,现在要使用Android的位置服务返回走过的距离。 修改getDiatance方法使其返回走过的距离,为此要用Android的位置服务。这些服务允许你得到用户的当…