监控系统1 - 项目框架 | 线程邮箱
一、项目框架
1. ARM主机
电表:采集电流电压信息,监测设备电压380V以内和电流在正常阈值内
温度传感器:连接在火线上,监测电线温度
接触器:控制电灯原理,高电平信号使用电设备上电,可用于保护设备
继电器一般控制低电平,接触器一般控制工业设备(三根火线)
本地报警:声光报警(蜂鸣器,LED灯 / 工控灯)
存储模块:写入文件 / 存入数据库
FB:framebuffer(LCD,行场信号),表达状态信息(电流、电压、网络状态)
网络模块:通过网络发送数据到控制中心,便于集中管理(Mqtt外网服务、http局域网、云服务器)
2. 系统框图
服务器监测可实现一个服务器监测多个设备
3. 技术说明
1. 电表模块
通过modbus协议使用RS485(485转TTL工具使0 /1 统一)方式连接arm开发板。使用linux 串口编程技术,获得数据(最低要求可以获得数据)。用于检测设备状态
需要考虑超时处理,帧校验,数据采集频率(高要求)。 技术点:串口编程
RS485总线传输,一次传输多个,速率较低
三相电表
2. 温度传感器
adc(模拟转数字)字符设备驱动程序的编写,并加载到系统中正常使用。驱动中需要使用时间延时函数。延时函数精度的保证(实时性)。使用电桥测量高精度。
技术点:字符设备驱动的编写,字符设备驱动编写的框架,步骤。如何把驱动添加到linux系统中,正常工作。
驱动是ko文件,使用insmod命令加入内核中。除了这个办法。还有其他办法加入内核么,直接编译到内核中。驱动的编写涉及传感器的时序图。这个地方检测3路火线。
pt100 (电压)变送器
3. 网络编程
linux socket编程 tcp上传各个传感器收集到的数据。有好几种数据,需要自定义帧格式,保证数据的完整性。
第一种,上传到自己的web服务器上(这个和之前做的web商场技术是一样的,使用的是http 协议低要求的),编写自定义协议(放置tcp产生粘包,需要设计开头标志 /帧头、结尾标志 / 帧尾、数据类型、数据长度)
第二种,上传到百度云或 onenet云上,使用mqtt协议(mqtt是更适合物联网场景的协议),需要研究mqtt协议相关的内容,mqtt服务器的组成部分,如何运作。发布,订阅,qos(服务质量)使用mqtt协议中,使用了心跳包机制,检测网络是否掉线,第一种不需要掉线检测。
4. 数据存储
存储可以使用文件或数据数据库的设计,放入相应的配置信息,或必要的参数。
5. FB图像显示
linux标准设备,可以考虑使用数据结构处理。
技术点:通用显示设备的绘点技术framebuffer。
绘制一般的文字图形(低要求)。如果需要显示的图文是通过放置链表上,通过遍历链表实现显示(高要求)
6. 数据上传
数据上传到云服务器(主流协议有哪些),或web服务器。
技术点:云服务,mqtt协议(公网上的服务器,百度云,阿里云,腾讯云),web服务端http协议(自己写的服务器,需要有域名才可以更通用)。
7. 接触器
接触相当于电源的开关,当温度,电流达到上限值,设备需要断电。如果使用mqtt协议可以远程打开设备工作。
技术点:字符设备驱动,最简单的驱动编写和调试,和点led灯的驱动一样。
8. 多线程处理
多线程之间的数据共享处理。锁机制,同步。
技术点:线程邮箱 / 缓冲,使用多线程编程,互斥锁,链表,队列。需要考虑线程间的数据间交互。
二、线程邮箱 / 缓冲
1. MBS 系统
MBS:mail box system 定义获得指针mbs指向整个系统
1. head
头结点,指向一个(单向)链表,一个链代表一个线程
链表数据:name : 线程名字
tid: 线程id号
th: 线程函数,进入线程后要运行的函数
queue: 消息队列,使线程间通过队列连接,无需关心处理速度是否匹配
用于独立数据运行速度,不会产生阻塞
相较于全局变量更高效更高级
2. mutex
用于保证对共享资源(尤其是对链表的操作,如添加、删除节点)的线程安全访问,防止多个线程同时修改链表导致数据错乱
定义MBS类型和构建线程参数结构体
定义数据类型和构建队列参数结构体
2. 相关函数
1. createMBS
MBS *createMBS();
创建邮箱系统
2. register_TH
int register_TH(MBS *mbs, char *name, PFUN th);
创建启动线程
3. sendmsg
int sendMSG(MBS *mbs, datatype *data);
通过邮箱系统MBS发送数据,实现将数据从该队列向目的队列存入
明确系统中所执行的哪个线程函数的tid号时,使数据插入相应线程的队列
4. recvmsg
int recvMSG(MBS *mbs, datatype *data);
通过邮箱系统MBS接收数据,实现将数据从目的队列中取出,接收到该队列
当某一线程需要发送显示数据时,使该数据出队
5. wait_all_end
int wait_all_end(MBS *mbs);
等待进程结束再结束总进程
6. main.c
主函数:
线程(上锁错误):
3. Makefile
1. Makefile
相关注意点见注释
无注释版
当make没有对CC进行指示时,make使用gcc编译
当执行make CC=arm-linux-gnueabinf-gcc 命令,make使用arm编译
2. readelf -h app
用于查看编译器版本
PC版 / gcc
ARM版 / arm-linux-gnueabihf-gcc
4. 内核链表
双向循环链表
containerof
1. 相关函数
1. INIT_LIST_HEAD
实现自己指向自己,即一个空 / 头结点
2. list_add
头插法
3. list_add_tail
尾插法
4. list_del
链表的删除
5. list_for_each_safe
定义的一个宏,用于遍历
注意:__list_add 和 __list_del 等前加static,即 list 函数内部使用的函数,不进行调用