编程技术分享

分享编程知识,探讨技术创新

0%

简介:交互式智能台灯,人来即亮,人走即灭。环境光照较强时,可自动降低亮度节省功耗,较暗时也可以自动升高亮度。“手势”交互(如调节亮度和番茄钟计时)。

我将为您详细阐述这款交互式智能台灯的嵌入式系统开发流程,并提供一个可靠、高效且可扩展的代码架构,以及具体的C代码实现。本项目旨在展示从需求分析到系统实现,再到测试验证和维护升级的完整嵌入式系统开发生命周期。
关注微信公众号,提前获取相关推文

1. 需求分析与系统设计

1.1 需求分析

基于产品简介,我们提取出以下核心需求:

  • 交互性: 通过手势进行用户交互,调节亮度和启动/停止番茄钟。
  • 智能性:
    • 人体感应: 人来即亮,人走即灭。
    • 环境光感应: 根据环境光强自动调节亮度,强光时降低,弱光时升高。
  • 节能性: 环境光强时降低亮度以节省功耗。
  • 可靠性: 系统运行稳定,功能可靠。
  • 高效性: 系统响应迅速,功耗控制合理。
  • 可扩展性: 系统架构应易于扩展新功能,如接入物联网、语音控制等。

1.2 系统设计

为了满足上述需求,我们设计如下系统架构:

1.2.1 硬件架构

  • 主控芯片 (MCU): 选择高性能、低功耗的嵌入式微控制器,例如 ARM Cortex-M 系列 (STM32F4/STM32G4 等)。 负责整个系统的控制、数据处理和任务调度。
  • 人体存在传感器 (PIR 传感器): 检测人体移动,用于实现人来即亮,人走即灭功能。
  • 环境光传感器 (光敏电阻或数字光照传感器): 检测环境光强度,用于自动亮度调节。
  • 手势传感器 (飞行时间 (ToF) 传感器 或 红外 (IR) 传感器阵列): 识别用户手势,用于亮度调节和番茄钟控制。
  • LED 灯条及驱动电路: 提供照明光源,并根据控制信号调节亮度。通常采用 PWM 调光方式。
  • 电源管理模块: 负责系统供电和功耗管理。
  • 调试接口 (如 UART 或 JTAG): 用于代码调试和系统监控。

1.2.2 软件架构

我们采用分层模块化的软件架构,以提高代码的可读性、可维护性和可扩展性。系统软件架构主要分为以下几层:

  • 硬件抽象层 (HAL - Hardware Abstraction Layer): 提供对底层硬件的抽象接口,屏蔽硬件差异,方便上层应用调用。包括 GPIO 驱动、ADC 驱动、PWM 驱动、定时器驱动、传感器驱动等。
  • 设备驱动层 (Device Driver Layer): 基于 HAL 层,实现具体硬件设备的功能驱动,例如 PIR 传感器驱动、光传感器驱动、手势传感器驱动、LED 驱动等。
  • 中间件层 (Middleware Layer): 提供通用的软件服务和组件,例如任务调度器 (RTOS 或简易调度器)、事件管理、配置管理、日志管理、通信协议栈等。
  • 应用层 (Application Layer): 实现系统的核心业务逻辑,包括人体感应逻辑、环境光感应逻辑、手势识别逻辑、亮度控制逻辑、番茄钟逻辑等。

1.2.3 软件模块划分

根据软件架构,我们将系统软件划分为以下模块:

  • hal 模块 (硬件抽象层):
    • hal_gpio.c/h: GPIO 初始化、读写控制。
    • hal_adc.c/h: ADC 初始化、采样。
    • hal_pwm.c/h: PWM 初始化、占空比控制。
    • hal_timer.c/h: 定时器初始化、中断处理。
    • hal_uart.c/h: UART 初始化、数据收发 (用于调试)。
  • drivers 模块 (设备驱动层):
    • pir_sensor.c/h: PIR 传感器驱动,检测人体存在。
    • light_sensor.c/h: 光传感器驱动,读取环境光强度。
    • gesture_sensor.c/h: 手势传感器驱动,识别手势。
    • led_driver.c/h: LED 驱动,控制 LED 亮度。
  • middleware 模块 (中间件层):
    • task_scheduler.c/h (如果使用 RTOS,则替换为 RTOS API): 任务调度和管理。
    • event_manager.c/h: 事件管理,用于模块间异步通信。
    • config_manager.c/h: 配置管理,存储和加载系统配置参数。
    • log_manager.c/h: 日志管理,记录系统运行信息 (用于调试和维护)。
  • application 模块 (应用层):
    • presence_detection.c/h: 人体存在检测逻辑。
    • ambient_light_control.c/h: 环境光亮度自动调节逻辑。
    • gesture_recognition.c/h: 手势识别逻辑,解析手势数据。
    • brightness_control.c/h: LED 亮度控制逻辑,根据需求调节亮度。
    • tomato_timer.c/h: 番茄钟功能实现。
    • main_app.c: 主应用程序,初始化系统,调度各个模块。

2. 具体C代码实现

以下是各个模块的C代码实现,包含了详细的注释和错误处理,并考虑了代码的可读性、可维护性和可扩展性。

(以下代码为示例代码,需要根据具体的硬件平台和传感器型号进行适配和调整)

2.1 hal 模块 (硬件抽象层)

hal/hal_gpio.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#ifndef HAL_GPIO_H
#define HAL_GPIO_H

#include <stdint.h>
#include <stdbool.h>

// GPIO 端口定义 (根据具体 MCU 平台定义)
typedef enum {
GPIO_PORT_A,
GPIO_PORT_B,
GPIO_PORT_C,
// ... 其他端口
GPIO_PORT_MAX
} GPIO_Port_TypeDef;

// GPIO 引脚定义 (根据具体 MCU 平台定义)
typedef enum {
GPIO_PIN_0 = (1U << 0),
GPIO_PIN_1 = (1U << 1),
GPIO_PIN_2 = (1U << 2),
// ... 其他引脚
GPIO_PIN_ALL = 0xFFFFFFFFU
} GPIO_Pin_TypeDef;

// GPIO 工作模式定义
typedef enum {
GPIO_MODE_INPUT, // 输入模式
GPIO_MODE_OUTPUT, // 输出模式
GPIO_MODE_AF_PP, // 复用推挽输出
GPIO_MODE_AF_OD, // 复用开漏输出
GPIO_MODE_ANALOG // 模拟输入
} GPIO_Mode_TypeDef;

// GPIO 输出类型定义
typedef enum {
GPIO_OUTPUT_PP, // 推挽输出
GPIO_OUTPUT_OD // 开漏输出
} GPIO_OutputType_TypeDef;

// GPIO 上下拉电阻定义
typedef enum {
GPIO_PULL_NONE, // 无上下拉
GPIO_PULL_UP, // 上拉
GPIO_PULL_DOWN // 下拉
} GPIO_Pull_TypeDef;

// 初始化 GPIO
void HAL_GPIO_Init(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin, GPIO_Mode_TypeDef mode, GPIO_OutputType_TypeDef otype, GPIO_Pull_TypeDef pull);

// 设置 GPIO 输出电平
void HAL_GPIO_WritePin(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin, bool pinState);

// 读取 GPIO 输入电平
bool HAL_GPIO_ReadPin(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin);

#endif // HAL_GPIO_H

hal/hal_gpio.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "hal_gpio.h"
#include "stdio.h" // For error handling (printf)

// 假设使用 STM32 HAL 库, 需要根据实际 MCU 平台进行修改
#ifdef STM32F4xx
#include "stm32f4xx_hal.h"
#endif

// 初始化 GPIO
void HAL_GPIO_Init(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin, GPIO_Mode_TypeDef mode, GPIO_OutputType_TypeDef otype, GPIO_Pull_TypeDef pull) {
// 错误检查
if (port >= GPIO_PORT_MAX) {
printf("HAL_GPIO_Init Error: Invalid GPIO Port\n");
return;
}

// 根据具体 MCU 平台配置 GPIO
#ifdef STM32F4xx
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_TypeDef *GPIOx;

switch (port) {
case GPIO_PORT_A: GPIOx = GPIOA; break;
case GPIO_PORT_B: GPIOx = GPIOB; break;
case GPIO_PORT_C: GPIOx = GPIOC; break;
// ... 其他端口
default:
printf("HAL_GPIO_Init Error: Unsupported GPIO Port for STM32F4\n");
return;
}

GPIO_InitStruct.Pin = pin;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Pull = pull;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 可根据需求调整速度

if (mode == GPIO_MODE_OUTPUT || mode == GPIO_MODE_AF_PP || mode == GPIO_MODE_AF_OD) {
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.OutputType = (otype == GPIO_OUTPUT_PP) ? GPIO_OUTPUTTYPE_PP : GPIO_OUTPUTTYPE_OD;
} else if (mode == GPIO_MODE_INPUT) {
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
} else if (mode == GPIO_MODE_ANALOG) {
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
} else {
printf("HAL_GPIO_Init Error: Invalid GPIO Mode\n");
return;
}

HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);

#else
// 其他 MCU 平台的 GPIO 初始化代码 (需要根据平台 datasheet 实现)
printf("HAL_GPIO_Init: Platform specific implementation needed.\n");
#endif
}

// 设置 GPIO 输出电平
void HAL_GPIO_WritePin(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin, bool pinState) {
// 错误检查
if (port >= GPIO_PORT_MAX) {
printf("HAL_GPIO_WritePin Error: Invalid GPIO Port\n");
return;
}

#ifdef STM32F4xx
GPIO_TypeDef *GPIOx;
switch (port) {
case GPIO_PORT_A: GPIOx = GPIOA; break;
case GPIO_PORT_B: GPIOx = GPIOB; break;
case GPIO_PORT_C: GPIOx = GPIOC; break;
// ... 其他端口
default:
printf("HAL_GPIO_WritePin Error: Unsupported GPIO Port for STM32F4\n");
return;
}
HAL_GPIO_WritePin(GPIOx, pin, pinState ? GPIO_PIN_SET : GPIO_PIN_RESET);
#else
// 其他 MCU 平台的 GPIO 输出代码 (需要根据平台 datasheet 实现)
printf("HAL_GPIO_WritePin: Platform specific implementation needed.\n");
#endif
}

// 读取 GPIO 输入电平
bool HAL_GPIO_ReadPin(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin) {
// 错误检查
if (port >= GPIO_PORT_MAX) {
printf("HAL_GPIO_ReadPin Error: Invalid GPIO Port\n");
return false;
}

#ifdef STM32F4xx
GPIO_TypeDef *GPIOx;
switch (port) {
case GPIO_PORT_A: GPIOx = GPIOA; break;
case GPIO_PORT_B: GPIOx = GPIOB; break;
case GPIO_PORT_C: GPIOx = GPIOC; break;
// ... 其他端口
default:
printf("HAL_GPIO_ReadPin Error: Unsupported GPIO Port for STM32F4\n");
return false;
}
return (HAL_GPIO_ReadPin(GPIOx, pin) == GPIO_PIN_SET);
#else
// 其他 MCU 平台的 GPIO 输入代码 (需要根据平台 datasheet 实现)
printf("HAL_GPIO_ReadPin: Platform specific implementation needed.\n");
return false;
#endif
}

(其他 hal 模块的代码, 例如 hal_adc.c/h, hal_pwm.c/h, hal_timer.c/h, hal_uart.c/h 的实现方式类似,需要根据具体的 MCU 平台和外设进行编写,这里省略代码以避免篇幅过长,但需要包含 ADC 初始化、采样,PWM 初始化、占空比控制,定时器初始化、中断处理,UART 初始化、数据收发等功能。)

2.2 drivers 模块 (设备驱动层)

drivers/pir_sensor.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef PIR_SENSOR_H
#define PIR_SENSOR_H

#include <stdbool.h>

// 初始化 PIR 传感器
bool PIR_Sensor_Init(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin);

// 读取 PIR 传感器状态,返回 true 表示检测到人体,false 表示未检测到
bool PIR_Sensor_IsDetected(void);

#endif // PIR_SENSOR_H

drivers/pir_sensor.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "pir_sensor.h"
#include "hal_gpio.h"
#include "stdio.h" // For error handling (printf)

static GPIO_Port_TypeDef pir_port;
static GPIO_Pin_TypeDef pir_pin;

// 初始化 PIR 传感器
bool PIR_Sensor_Init(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin) {
pir_port = port;
pir_pin = pin;

// 初始化 PIR 传感器引脚为输入模式
HAL_GPIO_Init(pir_port, pir_pin, GPIO_MODE_INPUT, GPIO_OUTPUT_PP, GPIO_PULL_DOWN); // 假设 PIR 传感器输出高电平表示检测到

// 简单延时,等待传感器稳定 (根据实际传感器 datasheet 调整)
for (volatile int i = 0; i < 100000; i++);

printf("PIR Sensor Initialized on Port %d, Pin %d\n", pir_port, pir_pin);
return true;
}

// 读取 PIR 传感器状态,返回 true 表示检测到人体,false 表示未检测到
bool PIR_Sensor_IsDetected(void) {
return HAL_GPIO_ReadPin(pir_port, pir_pin);
}

drivers/light_sensor.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef LIGHT_SENSOR_H
#define LIGHT_SENSOR_H

#include <stdint.h>

// 初始化光传感器
bool Light_Sensor_Init(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin);

// 读取光照强度值,返回 ADC 原始值 (需要根据实际传感器和 ADC 配置进行转换)
uint16_t Light_Sensor_ReadRawValue(void);

// 将 ADC 原始值转换为光照强度百分比 (0-100%)
uint8_t Light_Sensor_ConvertToPercentage(uint16_t rawValue);

#endif // LIGHT_SENSOR_H

drivers/light_sensor.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "light_sensor.h"
#include "hal_adc.h"
#include "stdio.h" // For error handling (printf)

static GPIO_Port_TypeDef light_sensor_port;
static GPIO_Pin_TypeDef light_sensor_pin;

// 初始化光传感器
bool Light_Sensor_Init(GPIO_Port_TypeDef port, GPIO_Pin_TypeDef pin) {
light_sensor_port = port;
light_sensor_pin = pin;

// 初始化 ADC (假设 ADC 通道已在 hal_adc.c 中配置)
if (!HAL_ADC_Init()) {
printf("Light_Sensor_Init Error: ADC Initialization failed\n");
return false;
}

printf("Light Sensor Initialized on Port %d, Pin %d\n", light_sensor_port, light_sensor_pin);
return true;
}

// 读取光照强度值,返回 ADC 原始值
uint16_t Light_Sensor_ReadRawValue(void) {
return HAL_ADC_GetValue(); // 假设 HAL_ADC_GetValue() 返回 ADC 原始值
}

// 将 ADC 原始值转换为光照强度百分比 (0-100%)
uint8_t Light_Sensor_ConvertToPercentage(uint16_t rawValue) {
// 假设 ADC 是 12 位,最大值为 4095
// 需要根据实际光传感器的特性和测试数据进行校准和映射
uint32_t percentage = (uint32_t)rawValue * 100 / 4095;
if (percentage > 100) percentage = 100;
return (uint8_t)percentage;
}

(其他 drivers 模块的代码, 例如 gesture_sensor.c/h, led_driver.c/h 的实现方式类似, gesture_sensor.c/h 需要根据具体的手势传感器类型和通信协议进行编写,例如 I2C 或 SPI 通信,并实现手势数据解析和识别逻辑。 led_driver.c/h 需要使用 PWM 控制 LED 亮度,并提供亮度设置接口。 这里省略代码以避免篇幅过长。)

2.3 middleware 模块 (中间件层)

(此处仅提供 config_manager.c/h 的示例,其他中间件模块例如 task_scheduler.c/h, event_manager.c/h, log_manager.c/h 的实现方式类似,需要根据具体的需求和设计进行编写。 如果使用 RTOS,则 task_scheduler.c/h 可以省略,直接使用 RTOS API。 event_manager.c/h 可以实现一个简单的事件队列和事件处理机制。 log_manager.c/h 可以实现简单的日志记录功能,例如通过 UART 输出日志信息。)

middleware/config_manager.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef CONFIG_MANAGER_H
#define CONFIG_MANAGER_H

#include <stdint.h>

// 系统配置参数结构体
typedef struct {
uint8_t auto_brightness_enabled; // 自动亮度调节使能
uint8_t gesture_control_enabled; // 手势控制使能
uint8_t presence_detection_enabled; // 人体感应使能
uint8_t brightness_level; // 默认亮度级别 (0-100%)
uint16_t tomato_timer_duration_minutes; // 番茄钟默认时长 (分钟)
// ... 其他配置参数
} SystemConfig_TypeDef;

// 初始化配置管理器
bool Config_Manager_Init(void);

// 加载配置参数
bool Config_Manager_LoadConfig(SystemConfig_TypeDef *config);

// 保存配置参数
bool Config_Manager_SaveConfig(const SystemConfig_TypeDef *config);

// 获取配置参数
const SystemConfig_TypeDef* Config_Manager_GetConfig(void);

#endif // CONFIG_MANAGER_H

middleware/config_manager.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "config_manager.h"
#include "stdio.h" // For error handling (printf)

static SystemConfig_TypeDef current_config;
static bool config_initialized = false;

// 默认配置参数
static const SystemConfig_TypeDef default_config = {
.auto_brightness_enabled = 1,
.gesture_control_enabled = 1,
.presence_detection_enabled = 1,
.brightness_level = 50,
.tomato_timer_duration_minutes = 25
};

// 初始化配置管理器
bool Config_Manager_Init(void) {
if (config_initialized) return true; // 避免重复初始化

// 初始化配置参数为默认值
current_config = default_config;

// TODO: 从非易失性存储器 (例如 Flash 或 EEPROM) 加载配置参数 (此处省略具体实现)
// 如果加载失败,则使用默认配置

config_initialized = true;
printf("Config Manager Initialized\n");
return true;
}

// 加载配置参数
bool Config_Manager_LoadConfig(SystemConfig_TypeDef *config) {
if (!config_initialized) {
printf("Config_Manager_LoadConfig Error: Config Manager not initialized\n");
return false;
}

// TODO: 从非易失性存储器加载配置参数到 *config (此处省略具体实现)
// 如果加载成功,则更新 current_config
// 如果加载失败,则保持 current_config 不变,并返回 false

// 示例: 假设加载成功,复制 current_config 到 *config
*config = current_config;

printf("Config Loaded\n");
return true; // 假设加载成功
}

// 保存配置参数
bool Config_Manager_SaveConfig(const SystemConfig_TypeDef *config) {
if (!config_initialized) {
printf("Config_Manager_SaveConfig Error: Config Manager not initialized\n");
return false;
}

// 更新 current_config
current_config = *config;

// TODO: 将 current_config 保存到非易失性存储器 (此处省略具体实现)

printf("Config Saved\n");
return true; // 假设保存成功
}

// 获取配置参数
const SystemConfig_TypeDef* Config_Manager_GetConfig(void) {
if (!config_initialized) {
printf("Config_Manager_GetConfig Error: Config Manager not initialized\n");
return NULL;
}
return &current_config;
}

2.4 application 模块 (应用层)

application/presence_detection.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef PRESENCE_DETECTION_H
#define PRESENCE_DETECTION_H

#include <stdbool.h>

// 初始化人体存在检测模块
bool Presence_Detection_Init(void);

// 获取人体存在状态,返回 true 表示有人存在,false 表示无人存在
bool Presence_Detection_IsSomeonePresent(void);

#endif // PRESENCE_DETECTION_H

application/presence_detection.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "presence_detection.h"
#include "pir_sensor.h"
#include "config_manager.h"
#include "stdio.h" // For error handling (printf)

// 初始化人体存在检测模块
bool Presence_Detection_Init(void) {
const SystemConfig_TypeDef *config = Config_Manager_GetConfig();
if (!config) {
printf("Presence_Detection_Init Error: Config Manager not initialized\n");
return false;
}

if (!config->presence_detection_enabled) {
printf("Presence Detection Disabled by Config\n");
return true; // 如果配置禁用,则初始化成功,但功能不启用
}

// 初始化 PIR 传感器 (假设 PIR 传感器引脚已在配置中定义)
if (!PIR_Sensor_Init(GPIO_PORT_B, GPIO_PIN_0)) { // 示例引脚,需要根据实际硬件连接修改
printf("Presence_Detection_Init Error: PIR Sensor Initialization failed\n");
return false;
}

printf("Presence Detection Initialized\n");
return true;
}

// 获取人体存在状态,返回 true 表示有人存在,false 表示无人存在
bool Presence_Detection_IsSomeonePresent(void) {
const SystemConfig_TypeDef *config = Config_Manager_GetConfig();
if (!config || !config->presence_detection_enabled) {
return false; // 如果配置禁用或配置管理器未初始化,则默认无人存在
}

return PIR_Sensor_IsDetected();
}

application/ambient_light_control.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef AMBIENT_LIGHT_CONTROL_H
#define AMBIENT_LIGHT_CONTROL_H

#include <stdint.h>

// 初始化环境光亮度控制模块
bool Ambient_Light_Control_Init(void);

// 根据环境光强度调节亮度
void Ambient_Light_Control_AdjustBrightness(void);

#endif // AMBIENT_LIGHT_CONTROL_H

application/ambient_light_control.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "ambient_light_control.h"
#include "light_sensor.h"
#include "led_driver.h"
#include "config_manager.h"
#include "stdio.h" // For error handling (printf)

// 亮度调节阈值 (百分比)
#define BRIGHT_THRESHOLD 70 // 环境光强于 70% 时降低亮度
#define DIM_THRESHOLD 30 // 环境光弱于 30% 时升高亮度

// 初始化环境光亮度控制模块
bool Ambient_Light_Control_Init(void) {
const SystemConfig_TypeDef *config = Config_Manager_GetConfig();
if (!config) {
printf("Ambient_Light_Control_Init Error: Config Manager not initialized\n");
return false;
}

if (!config->auto_brightness_enabled) {
printf("Auto Brightness Control Disabled by Config\n");
return true; // 如果配置禁用,则初始化成功,但功能不启用
}

// 初始化光传感器 (假设光传感器引脚已在配置中定义)
if (!Light_Sensor_Init(GPIO_PORT_A, GPIO_PIN_0)) { // 示例引脚,需要根据实际硬件连接修改
printf("Ambient_Light_Control_Init Error: Light Sensor Initialization failed\n");
return false;
}

printf("Ambient Light Control Initialized\n");
return true;
}

// 根据环境光强度调节亮度
void Ambient_Light_Control_AdjustBrightness(void) {
const SystemConfig_TypeDef *config = Config_Manager_GetConfig();
if (!config || !config->auto_brightness_enabled) {
return; // 如果配置禁用或配置管理器未初始化,则不进行亮度调节
}

uint8_t light_percentage = Light_Sensor_ConvertToPercentage(Light_Sensor_ReadRawValue());
uint8_t current_brightness = LED_Driver_GetBrightness(); // 获取当前亮度 (假设 LED_Driver 模块提供此接口)
uint8_t target_brightness = current_brightness;

if (light_percentage > BRIGHT_THRESHOLD) {
// 环境光强,降低亮度
target_brightness = current_brightness * (100 - (light_percentage - BRIGHT_THRESHOLD)) / 100; // 线性降低
if (target_brightness < 10) target_brightness = 10; // 最小亮度限制
printf("Ambient Light: %d%%, Reducing Brightness to %d%%\n", light_percentage, target_brightness);
} else if (light_percentage < DIM_THRESHOLD) {
// 环境光弱,升高亮度
target_brightness = current_brightness + (100 - current_brightness) * (DIM_THRESHOLD - light_percentage) / 100; // 线性升高
if (target_brightness > 100) target_brightness = 100; // 最大亮度限制
printf("Ambient Light: %d%%, Increasing Brightness to %d%%\n", light_percentage, target_brightness);
} else {
// 环境光适中,保持当前亮度
printf("Ambient Light: %d%%, Maintaining Brightness\n", light_percentage);
return; // 无需调节
}

LED_Driver_SetBrightness(target_brightness); // 设置目标亮度 (假设 LED_Driver 模块提供此接口)
}

(其他 application 模块的代码, 例如 gesture_recognition.c/h, brightness_control.c/h, tomato_timer.c/h, main_app.c 的实现方式类似。 gesture_recognition.c/h 需要实现手势数据的接收、解析和识别,并触发相应的事件。 brightness_control.c/h 需要实现亮度调节逻辑,例如通过手势或环境光传感器调节亮度。 tomato_timer.c/h 需要实现番茄钟计时功能,例如倒计时、提醒等。 main_app.c 是主应用程序入口,负责初始化所有模块,并实现主循环或任务调度,处理各种事件,例如人体感应事件、手势事件、定时器事件等,并控制台灯的整体运行逻辑。 这里省略代码以避免篇幅过长,但需要包含以上功能模块的完整实现。)

3. 测试验证

为了确保系统的可靠性和功能完整性,需要进行全面的测试验证,包括:

  • 单元测试: 针对每个模块进行独立测试,验证模块功能的正确性。例如,测试 PIR 传感器驱动是否能准确检测人体存在,光传感器驱动是否能正确读取光照强度,LED 驱动是否能正确调节亮度等。
  • 集成测试: 将各个模块集成在一起进行测试,验证模块之间的协同工作是否正常。例如,测试人体感应和亮度控制模块是否能协同工作,实现人来即亮,人走即灭的功能,以及环境光感应和亮度控制模块是否能协同工作,实现自动亮度调节功能。
  • 系统测试: 对整个系统进行全面测试,验证系统是否满足所有需求。例如,测试手势交互功能是否灵敏可靠,番茄钟功能是否准确计时,系统运行是否稳定可靠,功耗是否符合预期等。
  • 用户体验测试: 邀请用户进行实际使用测试,收集用户反馈,评估用户体验,并根据用户反馈进行优化改进。

4. 维护升级

为了保持系统的长期稳定运行和功能扩展,需要考虑以下维护升级策略:

  • 固件升级: 预留固件升级接口 (例如 UART 或 OTA - Over-The-Air),方便后续升级固件,修复 bug 或添加新功能。
  • 模块化设计: 模块化设计使得系统易于维护和升级。当需要修改或升级某个模块时,只需修改该模块的代码,而不会影响其他模块。
  • 日志管理: 完善的日志管理功能可以帮助开发者快速定位和解决问题,提高维护效率。
  • 版本控制: 使用版本控制系统 (例如 Git) 管理代码,方便代码的版本管理和协同开发。
  • 文档记录: 编写详细的开发文档和用户手册,方便后续维护和升级,以及用户使用。

5. 总结

本方案详细阐述了交互式智能台灯的嵌入式系统开发流程,从需求分析到系统实现,再到测试验证和维护升级。通过采用分层模块化的软件架构和具体的C代码实现,构建了一个可靠、高效且可扩展的系统平台。 代码示例覆盖了硬件抽象层、设备驱动层、中间件层和应用层的主要模块,并提供了详细的注释和错误处理。
请注意: 以上代码仅为示例代码,为了满足篇幅要求而进行了扩展,实际应用中需要根据具体的硬件平台、传感器型号和功能需求进行裁剪和优化。

欢迎关注我的其它发布渠道