BLE_TYQ_BJQ_CH32V303/bsp/src/bsp_mq.c

199 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author : stark1898y 1658608470@qq.com
* @Date : 2024-06-18 15:48:01
* @LastEditors: mbw && 1600520629@qq.com
* @LastEditTime: 2024-12-01 13:13:26
* @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_mq.c
* @Description :
*
* Copyright (c) 2024 by yzy, All Rights Reserved.
*/
/*
* @Author : yzy
* @Date : 2023-01-30 15:40:07
* @LastEditors : stark1898y 1658608470@qq.com
* @LastEditTime : 2023-09-19 16:25:03
* @FilePath : \JT-DT-YD1F01_RTT_Nano\bsp\src\bsp_mq.c
* @Description :
*
* Copyright (c) 2023 by yzy, All Rights Reserved.
*/
#include "bsp_mq.h"
#include "bsp_adc.h"
#include "bsp_flash.h"
#include "bsp_rtc.h"
#include "user_sys.h"
#define LOG_TAG "bsp_mq" // 该模块对应的标签。不定义时默认NO_TAG
#define LOG_LVL LOG_LVL_DBG // 该模块对应的日志输出级别。不定义时,默认:调试级别
#include <ulog.h> // 必须在 LOG_TAG 与 LOG_LVL 下面
ALIGN(RT_ALIGN_SIZE)
static char sensor_thread_stack[GAS_SNESOR_THREAD_STACK_SIZE];
static struct rt_thread Sensor_Thread;
TsSensor_t Sensor_device;
uint16_t Get_Gas_VoltageInt1000x(void)
{
uint16_t voltage = (Get_ADC_Average(kGasAdc) * 3.3 / 4096) * MQ_VOLTAGE_RATIO * 1000;
return voltage;
}
#ifdef TEST_ENABLE
static void TEST_Get_Gas_VoltageInt1000x(void)
{
LOG_D("Get_Gas_VoltageInt1000x = %04d", Get_Gas_VoltageInt1000x());
}
MSH_CMD_EXPORT(TEST_Get_Gas_VoltageInt1000x, TEST_Get_Gas_VoltageInt1000x);
#endif
static uint8_t Sensor_Count(const rt_uint8_t *buffer, uint8_t value, uint8_t size)
{
uint8_t count = 0;
for (uint8_t i = 0; i < size; i++)
{
if (buffer[i] == value)
{
count++;
}
}
return count;
}
static void Sensor_HandleAlarm(uint8_t count, uint8_t *flag, uint8_t threshold)
{
if (count > threshold && *flag == 0)
{
Sensor_device.detection_flag = kSensorAlarm;
Send_Laser_Alarm_Event(kAlarmEvent);
*flag = 1;
}
else if (*flag == 1 && count < threshold)
{
*flag = 0;
Send_Laser_Alarm_Event(kAlarmRcyEvent);
}
}
static void Sensor_HandleFault(uint8_t count, uint8_t *flag, uint8_t threshold)
{
if (count > threshold && *flag != 1)
{
*flag = 1;
Sensor_device.detection_flag = kSensorFault;
Send_Laser_Alarm_Event(kFaultEvent);
}
else if (*flag == 1 && count < threshold)
{
*flag = 0;
Send_Laser_Alarm_Event(kFaultRcyEvent);
}
}
static uint8_t Sensor_CheckData(void)
{
static rt_uint8_t alarm_count = 0, fault_count = 0;
static rt_uint8_t alarm_flag = 0, fault_flag = 0;
static rt_uint8_t index = 0;
static rt_uint8_t alarm_status_buffer[SENSOR_SAMPLING_TIMS] = {0};
static rt_uint8_t fault_buf[SENSOR_SAMPLING_TIMS] = {0};
rt_uint16_t voltage = Get_Gas_VoltageInt1000x();
alarm_status_buffer[index] = (voltage < Sensor_device.alarm_value) ? kSensorNormal : kSensorAlarm;
fault_buf[index] = ((voltage < MQ_VOLTAGE_LOW_LIMIT) || (voltage > MQ_VOLTAGE_LOW_LIMIT)) ? kSensorNormal : kSensorFault;
index++;
if (index >= SENSOR_SAMPLING_TIMS)
{
index = 0;
}
alarm_count = Sensor_Count(alarm_status_buffer, kSensorAlarm, SENSOR_SAMPLING_TIMS);
fault_count = Sensor_Count(fault_buf, kSensorFault, SENSOR_SAMPLING_TIMS);
Sensor_HandleAlarm(alarm_count, &alarm_flag, SENSOR_SAMPLING_TIMS / 2 + 1);
Sensor_HandleFault(fault_count, &fault_flag, SENSOR_SAMPLING_TIMS / 2 + 1);
return RT_EOK;
}
// TODO: 寿命检测
uint8_t IS_EndOfLife(void)
{
if (RTC_GetCounter() >= Sensor_device.expiration_seconds)
{
Sensor_device.end_of_life = 1;
}
return Sensor_device.end_of_life;
}
// MQ检测线程函数
static void Sensor_detection_thread_entry(void *param)
{
TuFlashProductTimeLimitFrame LimitTime;
if (Flash_GetProductTimeLimit(&LimitTime, kExpirationTimeId) == READY)
{
// 计算出 到期时间对应的RTC秒数
Sensor_device.expiration_seconds = DateTime2Seconds(LimitTime.Struct.year,
LimitTime.Struct.month, LimitTime.Struct.day, LimitTime.Struct.hour,
LimitTime.Struct.minute, LimitTime.Struct.second);
LOG_D("device_expiration_time:%04d-%02d-%02d,%02d:%02d",
LimitTime.Struct.year, LimitTime.Struct.month, LimitTime.Struct.day,
LimitTime.Struct.hour, LimitTime.Struct.minute, LimitTime.Struct.second);
}
if (Flash_GetNum_Records(kRecordSensoEndOfLife) == 1)
{
Sensor_device.end_of_life = 1;
LOG_W("寿命已到期");
TotalRecords.sensor_failure++;
}
// 寿命到期检测
if (IS_EndOfLife())
{
if (Flash_GetNum_Records(kRecordSensoEndOfLife) == 0)
{
Flash_Write_Record(kRecordSensoEndOfLife);
}
}
while (1)
{
if (SysControl.status > kPreheatingEvent)
{
Sensor_CheckData();
}
rt_thread_mdelay(1000);
}
}
int BSP_MQ_Init(void)
{
Sensor_device.alarm_value = Flash_Get_SysCfg(kAlarmLValueId);
LOG_D("报警阈值为:%d", Sensor_device.alarm_value);
rt_thread_init(&Sensor_Thread, //可以用定时器做,没必要线程
"sensor_thread",
Sensor_detection_thread_entry,
RT_NULL,
&sensor_thread_stack[0],
sizeof(sensor_thread_stack),
GAS_SENSOR_THREAD_PRIORITY, GAS_SENSOR_THREAD_TIMESLICE);
rt_thread_startup(&Sensor_Thread);
return 0;
}
#ifdef RT_USING_COMPONENTS_INIT
INIT_DEVICE_EXPORT(BSP_MQ_Init);
#endif
#ifdef TEST_ENABLE
static void TEST_MQ_EndOfLife(void)
{
Sensor_device.end_of_life = 1;
}
MSH_CMD_EXPORT(TEST_MQ_EndOfLife, TEST_MQ_EndOfLife);
#endif