1. 多对一(多个监测设备检测,数据发送给一个服务器)
2. 原理
充电桩温度变化引起PT100阻值变换(测温电流衰减微弱,几乎恒定,电压随之变化),经过测温模块转化成电压的变化(内部是电流的变化),输出电压值,模拟电压值经过ADS1115转化成数字量的温度值
3. 存储使用本地文件而非数据库,数据量小,不需要数据库
4. 每天十二点之后,要关闭当前文件夹,新建新的一天文件夹进行数据存储
5. 采集一组数据,去掉最小最大值,计算平均值,防止误差
6. 采集端
1. 多久采集一次
2. 采集后给发送给其余模块,线程邮箱
实操
1. 线程随机生成检测的数据,先写软件、后加硬件
1. 先采集(随机生成)
2. 存储
3. 显示(简单)
4. 网络发送
5. 告警
6. 服务器
线程邮箱
1. 用链表将各个线程串联起来,各个线程内容使用结构体保存,使用队列保存各个线程间的数据,线程间共享数据,通过遍历链表名,或者线程id找到对应要发送数据的位置,使用队列,将数据入队到目的队列中,获取接收到的数据时,使用getpid或者线程名找到自己的结构体,找到自己的队列,出队数据
2. 每次入队出队数据要加锁,资源保护
线程邮箱代码
1. create_msg_box();创建空链表
2. 注册线程任务
3. 发送函数,遍历链表寻找要发送的线程名称,将所要发送的数据入队
4. 接收数据,遍历链表找自己,出队数据
项目一
客户端
1.采集端使用何种平台实现
分析不同平台的优缺点:树莓派、单片机、stm32、2440
2. 确定每个项目中需要检测哪些数据指标?使用哪些传感器来完成?
3. 如何实现屏幕显示?(LVGL、QT、Framebuffer)(为什么要选framebuffer)
屏幕最好做到人机交互
1. 界面显示实时信息
2. 输入阈值
3. 如何实现界面跳转
4. 图像显示
柱状图、折线图、饼状图、曲线
4. 数据如何实现记录?(多大数据量需要数据库)
5. 使用网络编程(TCP、UDP)
采集端
1. 第三方平台:(阿里云、腾讯云)MQTT
2. 如何编写服务器端
1. 如何实现并发接收
2. 如何管理数据(分库、分表)
3. http服务器搭建
任务
1. 确定题目
2. 确定项目框架
3. 绘制软件框图
项目软件如何划分?每个模块实现哪些功能?利用何种技术实现该功能?
项目二
1. 基于单片机与K210的人脸追踪相机(机器视觉)
人脸识别
2. 基于人工智能模型的对话系统(机器听觉、对话)
ACR220E电表与2440通信流程步骤总结(7.22)
1. 根据所采集的电压、电流数值范围选择合适的电表(额定电压、额定电流大小、适用环境)
2. 在百度、CSDN、Chatgpt、淘宝寻找对应型号的电表说明书
3. 查阅电表设备说明书、了解电表的详细信息以及如何使用
4. 电表通过连接充电桩的火线、零线和地线来采集电压和电流值,通过RS485总线的A线和B线,连接RS485转RS232转接口,接入2440的DB9接口,2440内部有MAX2323能够实现232电平标准和TTL电平标准的相互转化,使用2440的UART0的中断方式进行两者间的通信。
5. 若要采集数据,2440作为上位机,通过应用程序打开UART设备,通过set_port函数接口,设置串口通信参数,串口设备文件描述符、波特率、有效数据位、停止位、校验位,通过UART向电表发送MODBUS命令读取电压和电流数据,并使用接收数据的函数。通过UART中断方式ACR220E发送到的数据存入UART0接收寄存器中,通过解析接收寄存器中的值,完成电表的电流电压数据采集
6. 电表将采集的存储在寄存器里面的电压、电流值通过MODBUS格式发送给应用程序,应用程序进行数据拆解,并进行CRC验证,获得采集的数据。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
// CRC计算函数
unsigned short calculate_crc(unsigned char *buf, int len) {
unsigned short crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (unsigned short)buf[pos];
for (int i = 8; i != 0; i--) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// 发送命令函数
void send_command(int fd, unsigned char* cmd, int len) {
write(fd, cmd, len);
}
// 接收响应函数
int receive_response(int fd, unsigned char* buf, int len) {
return read(fd, buf, len);
}
void read_voltage_current(int fd) {
unsigned char voltage_cmd[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02};
unsigned char current_cmd[] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x02};
unsigned char recv_buf[9];
unsigned short crc;
// 计算并添加CRC到电压命令
crc = calculate_crc(voltage_cmd, 6);
voltage_cmd[6] = crc & 0xFF;
voltage_cmd[7] = (crc >> 8) & 0xFF;
// 发送读取电压命令
send_command(fd, voltage_cmd, 8);
// 接收响应
if (receive_response(fd, recv_buf, 9) == 9) {
// 计算CRC
crc = calculate_crc(recv_buf, 7);
// 验证CRC
if (crc == (recv_buf[7] | (recv_buf[8] << 8))) {
// 处理电压数据
unsigned short voltage = (recv_buf[3] << 8) | recv_buf[4];
printf("Voltage: %d\n", voltage);
} else {
printf("Voltage data CRC error!\n");
}
}
// 计算并添加CRC到电流命令
crc = calculate_crc(current_cmd, 6);
current_cmd[6] = crc & 0xFF;
current_cmd[7] = (crc >> 8) & 0xFF;
// 发送读取电流命令
send_command(fd, current_cmd, 8);
// 接收响应
if (receive_response(fd, recv_buf, 9) == 9) {
// 计算CRC
crc = calculate_crc(recv_buf, 7);
// 验证CRC
if (crc == (recv_buf[7] | (recv_buf[8] << 8))) {
// 处理电流数据
unsigned short current = (recv_buf[3] << 8) | recv_buf[4];
printf("Current: %d\n", current);
} else {
printf("Current data CRC error!\n");
}
}
}
int main() {
int fd = open("/dev/ttySAC0", O_RDWR | O_NOCTTY | O_NDELAY); // 打开串口
if (fd == -1) {
perror("open_port: Unable to open /dev/ttySAC0");
return -1;
}
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
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);
read_voltage_current(fd);
close(fd);
return 0;
}