80 lines
2.6 KiB
C
80 lines
2.6 KiB
C
#include "adc.h"
|
||
#include "hlw8032.h"
|
||
#include "main.h"
|
||
#include "network.h"
|
||
#include "led.h"
|
||
#include "reset_log.h"
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
|
||
ADC_HandleTypeDef hadc1;
|
||
|
||
void adcInit(void)
|
||
{
|
||
ADC_ChannelConfTypeDef sConfig = {0};
|
||
hadc1.Instance = ADC1;
|
||
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
|
||
hadc1.Init.ContinuousConvMode = DISABLE;
|
||
hadc1.Init.DiscontinuousConvMode = DISABLE;
|
||
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
|
||
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
|
||
hadc1.Init.NbrOfConversion = 1;
|
||
if (HAL_ADC_Init(&hadc1) != HAL_OK) Error_Handler();
|
||
|
||
sConfig.Channel = ADC_CHANNEL_0;
|
||
sConfig.Rank = ADC_REGULAR_RANK_1;
|
||
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
|
||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) Error_Handler();
|
||
}
|
||
|
||
uint16_t getAdc(void)
|
||
{
|
||
uint16_t adc_value = 0;
|
||
HAL_ADC_Start(&hadc1);
|
||
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {
|
||
adc_value = HAL_ADC_GetValue(&hadc1);
|
||
}
|
||
HAL_ADC_Stop(&hadc1);
|
||
return adc_value;
|
||
}
|
||
|
||
void update_batter(void)
|
||
{
|
||
static _Bool powoff = 0;
|
||
uint16_t adc_value = getAdc();
|
||
float batter_valtage = adc_value * (3.3 / 4096.0);
|
||
batter_valtage = batter_valtage * 11.0;
|
||
batter_valtage += 0.6;
|
||
batter_valtage = 100 * (batter_valtage - 10.8) / (12.6 - 10.8);
|
||
/* 限幅 0~100%:法拉电容放电时 3.3V 基准下跌,ADC 读数失真可能算出负数 */
|
||
if (batter_valtage < 0) batter_valtage = 0;
|
||
if (batter_valtage > 100) batter_valtage = 100;
|
||
|
||
/* 电量 <10% 基本等同外部 12V 断开。法拉电容(5.5F)续航有限,
|
||
* 首次低于阈值立即 50ms 快速复核 2 次(约 100ms 出结果),仍低马上按断电处理:
|
||
* 优先把掉电消息发出去,再做本地记录,最后留 500ms 让模组把报文真正发完 */
|
||
if (batter_valtage < 10 && powoff == 0) {
|
||
uint8_t confirm = 1;
|
||
for (int k = 0; k < 2; k++) {
|
||
HAL_Delay(50);
|
||
adc_value = getAdc();
|
||
float v = adc_value * (3.3 / 4096.0);
|
||
v = v * 11.0 + 0.6;
|
||
v = 100 * (v - 10.8) / (12.6 - 10.8);
|
||
if (v >= 10) { confirm = 0; break; }
|
||
}
|
||
if (!confirm) return;
|
||
|
||
powoff = 1;
|
||
log_info("> 电量低: %d%%", (int)batter_valtage);
|
||
NET_publish_power(0); /* 优先发掉电消息 */
|
||
hlw8032_save(); /* 本地记录:电量、断电原因(都很快) */
|
||
reset_log_power_loss();
|
||
HAL_Delay(500); /* 给模组把 MQTT 报文发出去的时间 */
|
||
NVIC_SystemReset();
|
||
/* BootLoader 会检测主电源,12V 未恢复前不跳 APP,防止外设没上电时程序乱跑 */
|
||
}
|
||
/* LED1: 低电量时常亮 */
|
||
if (powoff) LED1_ON; else LED1_OFF;
|
||
}
|