| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- /*
- * led.c - 系统状态指示灯驱动(事件查询方式,100ms检查周期)
- * 硬件:PC0(红), PC1(绿), PC2(蓝) - 低电平点亮
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- /* 使用RT-Thread标准日志系统 */
- #define DBG_TAG "led"
- #define DBG_LVL DBG_WARNING
- #include <rtdbg.h>
- /**
- * @brief 外部引入的状态
- */
- #include "ym310_protecl.h"
- extern rt_bool_t ym310_mqtt_is_connected(rt_uint8_t client_idx);
- extern SYS_STATUS sys_sta;
- extern uint8_t calculate_hours_diff(uint8_t start, uint8_t end);
- #define PIN_LED_RED GET_PIN(B, 7)
- #define PIN_LED_GREEN GET_PIN(B, 8)
- #define PIN_LED_BLUE GET_PIN(C, 13)
- /* 时间常量定义(单位:100ms)*/
- #define LED_BLINK_ON_TIME 3 // 亮的时间:300ms
- #define LED_BLINK_OFF_TIME 2 // 灭的时间:200ms
- /* 闪烁次数(使用 light_work_duration)*/
- #define BLINK_COUNT (dev_info.light_work_duration) // 光控时长 = 闪烁次数
- #define SK_BLINK_COUNT (calculate_hours_diff(dev_info.time_start, dev_info.time_end)) // 时控时长 = 闪烁次数
- #define PAUSE_TIME 20 // 一组闪烁完成后暂停:2000ms
- /* 长工作状态(light_work_duration == 0):亮2秒,灭2秒 */
- #define LONG_WORK_ON_TIME 20 // 亮2秒
- #define LONG_WORK_OFF_TIME 20 // 灭2秒
- #define SET_EFFECT_BLINK_COUNT 3 // 设置生效闪烁次数
- /* LED 状态定义 */
- typedef enum
- {
- LED_STATE_NORMAL = 0,
- LED_STATE_ERROR,
- LED_STATE_POWER_OFF,
- } led_state_t;
- /* 异常类型定义 */
- typedef enum
- {
- ERROR_NONE = 0,
- ERROR_RAIN, // 雨控 - 黄色闪烁(带次数/联网指示)
- ERROR_TEMP, // 温控 - 黄色常亮
- ERROR_UNDER_VOLTAGE, // 欠压 - 红色闪烁(带次数/联网指示)
- ERROR_TILT, // 倾倒 - 红色常亮
- } error_type_t;
- /* LED 工作模式 */
- typedef enum
- {
- LED_MODE_NORMAL = 0,
- LED_MODE_SET_EFFECT,
- } led_mode_t;
- /* 工作状态变量 */
- static led_state_t current_state = LED_STATE_NORMAL;
- static error_type_t current_error = ERROR_NONE;
- static led_mode_t current_mode = LED_MODE_NORMAL;
- /* 设置生效事件标志 */
- static volatile uint8_t set_effect_pending = 0;
- /* 定时器控制块 */
- static rt_timer_t led_timer = RT_NULL;
- /* ========== 统一状态机变量 ========== */
- static uint32_t tick = 0; // 通用计时器
- static uint8_t phase = 0; // 0:亮状态, 1:灭状态, (长工作模式: 0亮1灭)
- static uint8_t blink_done = 0; // 当前已完成的闪烁次数
- static uint8_t in_pause = 0; // 是否处于长暂停状态
- static uint8_t need_reset = 1; // 是否需要重置状态机
- static uint8_t is_long_work = 0; // 是否处于长工作模式(duration==0)
- /* 设置生效事件变量 */
- static uint32_t set_effect_tick = 0;
- static uint8_t set_effect_phase = 0;
- static uint8_t set_effect_count = 0;
- /* ========== 颜色控制函数 ========== */
- static void set_led_color(uint8_t red, uint8_t green, uint8_t blue)
- {
- rt_pin_write(PIN_LED_RED, red ? PIN_HIGH : PIN_LOW);
- rt_pin_write(PIN_LED_GREEN, green ? PIN_HIGH : PIN_LOW);
- rt_pin_write(PIN_LED_BLUE, blue ? PIN_HIGH : PIN_LOW);
- }
- #define COLOR_OFF() set_led_color(0, 0, 0)
- #define COLOR_RED() set_led_color(1, 0, 0)
- #define COLOR_GREEN() set_led_color(0, 1, 0)
- #define COLOR_BLUE() set_led_color(0, 0, 1)
- #define COLOR_YELLOW() set_led_color(1, 1, 0)
- #define COLOR_CYAN() set_led_color(0, 1, 1)
- #define COLOR_WHITE() set_led_color(1, 1, 1)
- #define COLOR_PINK() set_led_color(1, 0, 1)
- /* ========== NTP时间同步判断 ========== */
- /**
- * @brief 判断NTP时间是否已同步成功
- * @return 1=已同步, 0=未同步
- *
- * 判断逻辑:当前系统时间若为2026年5月及以前,认为未同步
- * 因为设备实际运行时间在2026年6月之后
- */
- static uint8_t is_ntp_synced(void)
- {
- extern struct rtc_time time_now;
- /* 计算当前时间的 (年*12 + 月) 值 */
- uint32_t current_value = (uint32_t)(time_now.year - 2000) * 12 + time_now.month;
- /* 2026年5月的参考值:26*12 + 5 = 317 */
- uint32_t threshold = 26 * 12 + 5;
- // rt_kprintf("current_value %d threshold %d res = %d" , current_value ,threshold, (current_value > threshold));
- /* 如果当前时间 <= 2026年5月,认为NTP未同步 */
- if (current_value <= threshold)
- {
- return 0; /* 未同步 */
- }
- return 1; /* 已同步 */
- }
- /* ========== 辅助函数 ========== */
- static uint8_t is_power_off(void)
- {
- return (dev_info.power_state == 0);
- }
- /**
- * @brief 获取正常状态(无异常)下的基础颜色
- * @param charging 充电状态 (0:未充电, 2:充电中)
- */
- static void set_normal_color(uint8_t charging)
- {
- if (charging == 2)
- {
- COLOR_BLUE();
- }
- else if (dev_info.time_ctrl_enable == 0)
- {
- COLOR_GREEN(); // 光控
- }
- else
- {
- COLOR_PINK(); // 时控
- }
- }
- /**
- * @brief 获取当前应该显示的颜色(用于闪烁时的亮状态)
- * @param charging 充电状态 (0:未充电, 2:充电中)
- * @param network_ok 网络状态
- * @param is_last 是否为本次闪烁周期的最后一次
- */
- static void set_on_color(uint8_t charging, uint8_t network_ok, uint8_t is_last)
- {
- if (!network_ok && is_last)
- {
- COLOR_CYAN(); // 断网时显示青色
- return;
- }
- if (is_last && !is_ntp_synced()) // ntp失效 显示白色
- {
- COLOR_WHITE();
- return;
- }
- switch (current_error)
- {
- case ERROR_UNDER_VOLTAGE:
- COLOR_RED();
- break;
- case ERROR_RAIN:
- COLOR_YELLOW();
- break;
- default:
- set_normal_color(charging);
- break;
- }
- }
- /**
- * @brief 长工作模式处理(duration == 0):2秒亮,2秒灭
- * @param charging 充电状态
- * @param network_ok 网络状态(长工作模式下不使用断网指示)
- */
- static void long_work_mode_process(uint8_t charging, uint8_t network_ok)
- {
- tick++;
- if (phase == 0) /* 亮状态 */
- {
- if (tick >= LONG_WORK_ON_TIME)
- {
- COLOR_OFF();
- phase = 1;
- tick = 0;
- }
- }
- else /* 灭状态 */
- {
- if (tick >= LONG_WORK_OFF_TIME)
- {
- switch (current_error)
- {
- case ERROR_UNDER_VOLTAGE:
- COLOR_RED();
- break;
- case ERROR_RAIN:
- COLOR_YELLOW();
- break;
- default:
- set_normal_color(charging);
- break;
- }
- phase = 0;
- tick = 0;
- }
- }
- }
- /**
- * @brief 快速闪烁模式处理(duration >= 1):支持次数控制和断网指示
- * @param charging 充电状态
- * @param network_ok 网络状态
- * @param blink_count 闪烁次数
- */
- static void fast_blink_mode_process(uint8_t charging, uint8_t network_ok, uint8_t blink_count)
- {
- if (need_reset)
- {
- need_reset = 0;
- phase = 0;
- blink_done = 0;
- in_pause = 0;
- tick = 0;
- uint8_t is_last = (blink_count == 1);
- set_on_color(charging, network_ok, is_last);
- return;
- }
- tick++;
- if (in_pause)
- {
- if (tick >= PAUSE_TIME)
- {
- in_pause = 0;
- blink_done = 0;
- phase = 0;
- tick = 0;
- uint8_t is_last = (blink_count == 1);
- set_on_color(charging, network_ok, is_last);
- }
- return;
- }
- if (phase == 0)
- {
- if (tick >= LED_BLINK_ON_TIME)
- {
- COLOR_OFF();
- phase = 1;
- tick = 0;
- }
- }
- else
- {
- if (tick >= LED_BLINK_OFF_TIME)
- {
- blink_done++;
- if (blink_done >= blink_count)
- {
- in_pause = 1;
- tick = 0;
- return;
- }
- phase = 0;
- tick = 0;
- uint8_t is_last = (blink_done + 1 >= blink_count);
- set_on_color(charging, network_ok, is_last);
- }
- }
- }
- /**
- * @brief 统一状态处理(正常/闪烁类异常共用)
- */
- static void unified_state_process(void)
- {
- static uint8_t last_effective_count = 0xff;
- uint8_t charging = sys_sta.work_state;
- uint8_t network_ok = ym310_mqtt_is_connected(0);
- uint8_t effective_count;
- if (is_power_off())
- {
- COLOR_OFF();
- return;
- }
- uint8_t is_pink_mode = (current_state == LED_STATE_NORMAL && current_error == ERROR_NONE &&
- charging != 2 && dev_info.time_ctrl_enable == 1);
- if (is_pink_mode)
- {
- effective_count = SK_BLINK_COUNT;
- }
- else
- {
- effective_count = BLINK_COUNT;
- }
- if (last_effective_count != effective_count)
- {
- last_effective_count = effective_count;
- need_reset = 1;
- is_long_work = 0;
- tick = 0;
- phase = 0;
- blink_done = 0;
- in_pause = 0;
- }
- if (effective_count == 0)
- {
- if (!is_long_work)
- {
- is_long_work = 1;
- need_reset = 1;
- phase = 0;
- tick = 0;
- }
- long_work_mode_process(charging, network_ok);
- }
- else
- {
- if (is_long_work)
- {
- is_long_work = 0;
- need_reset = 1;
- }
- fast_blink_mode_process(charging, network_ok, effective_count);
- }
- }
- /**
- * @brief 常亮状态处理(温控、倾倒)
- */
- static void solid_state_process(void)
- {
- if (is_power_off())
- {
- COLOR_OFF();
- return;
- }
- switch (current_error)
- {
- case ERROR_TEMP:
- COLOR_YELLOW();
- break;
- case ERROR_TILT:
- COLOR_RED();
- break;
- default:
- COLOR_OFF();
- break;
- }
- }
- /**
- * @brief 设置生效事件处理
- */
- static void set_effect_process(void)
- {
- set_effect_tick++;
- if (set_effect_phase == 0)
- {
- if (set_effect_tick >= LED_BLINK_ON_TIME)
- {
- COLOR_OFF();
- set_effect_phase = 1;
- set_effect_tick = 0;
- }
- }
- else
- {
- if (set_effect_tick >= LED_BLINK_OFF_TIME)
- {
- set_effect_count++;
- if (set_effect_count >= SET_EFFECT_BLINK_COUNT)
- {
- LOG_I("Set effect completed\n");
- current_mode = LED_MODE_NORMAL;
- need_reset = 1;
- is_long_work = 0;
- return;
- }
- set_effect_phase = 0;
- COLOR_WHITE();
- set_effect_tick = 0;
- }
- }
- }
- /**
- * @brief 检查设置生效事件
- */
- static void check_set_effect_event(void)
- {
- if (set_effect_pending)
- {
- LOG_I("Set effect event triggered\n");
- set_effect_pending = 0;
- current_mode = LED_MODE_SET_EFFECT;
- set_effect_tick = 0;
- set_effect_phase = 0;
- set_effect_count = 0;
- COLOR_WHITE();
- }
- }
- /**
- * @brief 主定时器回调
- */
- static void led_timer_callback(void *parameter)
- {
- check_set_effect_event();
- if (current_mode == LED_MODE_SET_EFFECT)
- {
- set_effect_process();
- return;
- }
- if (is_power_off())
- {
- COLOR_OFF();
- return;
- }
- led_update_status();
- switch (current_state)
- {
- case LED_STATE_NORMAL:
- unified_state_process();
- break;
- case LED_STATE_ERROR:
- if (current_error == ERROR_RAIN || current_error == ERROR_UNDER_VOLTAGE)
- {
- unified_state_process(); // 闪烁,复用正常逻辑
- }
- else
- {
- solid_state_process(); // 常亮
- }
- break;
- default:
- COLOR_OFF();
- break;
- }
- }
- /* ========== 外部API ========== */
- void led_trigger_set_effect(void)
- {
- set_effect_pending = 1;
- LOG_I("Set effect event pending\n");
- }
- void led_update_status(void)
- {
- if (current_mode != LED_MODE_NORMAL)
- return;
- led_state_t old_state = current_state;
- error_type_t old_error = current_error;
- if (is_power_off())
- {
- current_state = LED_STATE_POWER_OFF;
- current_error = ERROR_NONE;
- COLOR_OFF();
- return;
- }
- if (sys_sta.tilt_protect == VALID)
- {
- current_error = ERROR_TILT;
- current_state = LED_STATE_ERROR;
- }
- else if (sys_sta.temp_protect == VALID)
- {
- current_error = ERROR_TEMP;
- current_state = LED_STATE_ERROR;
- }
- else if (sys_sta.undervolt_protect == VALID)
- {
- current_error = ERROR_UNDER_VOLTAGE;
- current_state = LED_STATE_ERROR;
- }
- else if (sys_sta.rain_protect == VALID)
- {
- current_error = ERROR_RAIN;
- current_state = LED_STATE_ERROR;
- }
- else
- {
- current_state = LED_STATE_NORMAL;
- current_error = ERROR_NONE;
- }
- if (old_state != current_state || old_error != current_error)
- {
- LOG_I("State: %s, error=%d\n",
- current_state == LED_STATE_NORMAL ? "NORMAL" : "ERROR", current_error);
- need_reset = 1;
- is_long_work = 0;
- tick = 0;
- }
- }
- /**
- * @brief LED初始化
- */
- int led_init(void)
- {
- rt_pin_mode(PIN_LED_RED, PIN_MODE_OUTPUT);
- rt_pin_mode(PIN_LED_GREEN, PIN_MODE_OUTPUT);
- rt_pin_mode(PIN_LED_BLUE, PIN_MODE_OUTPUT);
- COLOR_OFF();
- led_timer = rt_timer_create("led_timer",
- led_timer_callback,
- RT_NULL,
- RT_TICK_PER_SECOND / 10,
- RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
- if (led_timer == RT_NULL)
- {
- LOG_E("Failed to create led timer\n");
- return -RT_ERROR;
- }
- rt_timer_start(led_timer);
- LOG_I("LED driver initialized\n");
- LOG_I(" Light work duration: %d hours\n", BLINK_COUNT);
- LOG_I(" Duration=0: 2s ON/2s OFF (long work mode)\n");
- LOG_I(" Duration>=1: blink times depends on mode (pink uses time-control duration)\n");
- LOG_I(" Rain/Under-voltage: blink with color (Yellow/Red)\n");
- LOG_I(" Temp/Tilt: solid color (Yellow/Red)\n");
- LOG_I(" Last blink of each group: Cyan if disconnected\n");
- return RT_EOK;
- }
- INIT_APP_EXPORT(led_init);
|