目录
需求分析
房间里的灯的开关距离床铺较远,每次睡觉前都得爬下床去关灯
因此设计一个可以远距离遥控的设备
需要满足:
- 无需修改家庭电路(怕被骂)
- 使用电池供电(开关距离插座很远)
- 低功耗
- 检测电池电压
- 使用家用遥控器(废旧遥控器)
- 可以不影响开关使用
方案设计
使用stm32f103c6t6为主控(价格便宜 当前价格3r)
使用2节18650串联供电,使电压为7-8V(外置保护板)
通过ldo降压到3v3和5v(单片机和红外接收)
使用红外遥控(wifi/蓝牙需要的功耗很高,价格也较贵)
使用舵机来模拟人手控制开关
通过电阻分压获取当前电池的电压,在电压过低时发出信号
硬件设计
电源
使用AMS1117来获取3V3和5V电压给系统供电
stm32系统
复位电路
晶振
引导跳线
STLink下载电路
主芯片电源
主芯片
电压检测
舵机驱动
舵机是5V电压驱动的,需要使用开漏上拉使输出高电平为5V
红外
软件部分
思路
使用之前做好的红外库和舵机操控库
接收红外信号,当接收到指定的红外信号时
操作舵机打开开关或者关闭开关
通过定时器实现上电时LED闪烁
当电量较低时LED常亮报警
运动过程
默认状态
开灯状态
关灯状态
开灯流程
默认状态--->开灯状态---->默认状态
关灯流程
默认状态--->关灯状态---->默认状态
只需要给舵机一个较大的速度将开关冲过去即可
持续一段时间确保开关按到位(当然也可以加电流检测)
注意:这里用的是360°舵机
HAL初始化
红外解码需要:
1.外部中断,下降沿触发,上拉2.定时器,分频后为1us,中断时间大于15ms
舵机驱动需要:
1.GPIO 开漏浮空输出,外接5V上拉2.定时器20us触发中断
ADC需要
单通道
LED需要
GPIO推挽输出
定时器中断1s发送中断
代码
低功耗
进入休眠模式,外部中断可以将其唤醒,从这个函数的结束处继续运行
/**
* @brief 进入休眠模式
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:47:42
*/
void enter_stop_mode(void)
{
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
退出休眠模式为保证正常运行需要调用所有的hal库生成的初始化函数
/**
* @brief 退出休眠模式
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:47:54
*/
void exit_stop_mode(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
MX_TIM1_Init();
MX_TIM2_Init();
MX_ADC1_Init();
}
电压检测
整个函数再定时器中断里调用,等待无操作6秒后调用
检测电压,多次达到额定值以下触发报警
/**
* @brief 电压检测
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:44:06
*/
void Voltage_detection(void)
{
uint16_t V = 0;
HAL_ADC_Start(&hadc1); //开启ADC
HAL_ADC_PollForConversion(&hadc1, 100); //开启电压检测
if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)) //转化完成
{
V = HAL_ADC_GetValue(&hadc1); //获取电压值
if (V < 2600)
{
HAL_Delay(100);
HAL_ADC_PollForConversion(&hadc1, 100); //去抖
if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
V = HAL_ADC_GetValue(&hadc1);
if (V < 2600)
{
HAL_Delay(100);
HAL_ADC_PollForConversion(&hadc1, 100); //再去抖
if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
V = HAL_ADC_GetValue(&hadc1);
if (V < 2600)
{
// LED_Ctl = 0;
STOP_Ctl = 0;
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); //点亮灯
}
}
}
}
}
else
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); //关闭led
}
}
HAL_ADC_Stop(&hadc1); //关闭adc
}
LED
上电LED闪烁
uint8_t LED_Ctl = 0; // LED控制计时
/**
* @brief 上电时LED闪
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:43:29
*/
void INIT_LED(void)
{
if (LED_Ctl % 2)
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
LED_Ctl++;
}
LED与休眠控制
1s定时器中断调用
uint8_t STOP_Ctl = 0; //进入休眠模式计时
/**
* @brief led控制
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:46:48
*/
void LED_Ctrl(void)
{
if (LED_Ctl < 6)
{
INIT_LED(); //前6秒闪烁
}
else
{
STOP_Ctl++;
Voltage_detection();
}
if (STOP_Ctl >= 6)
{
STOP_Ctl = 0;
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); //关灯
enter_stop_mode(); //休眠
exit_stop_mode(); //退出休眠
}
}
开灯和关灯
这部分的延迟时间需要根据自己的开关来调试和确定
/**
* @brief 开灯
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:43:01
*/
void OPEN(void)
{
Steering_Engine_360(0, 30);
HAL_Delay(400);
Steering_Engine_360(1, 50);
HAL_Delay(100);
Steering_Engine_Stop();
HAL_Delay(2000);
}
/**
* @brief 关灯
* @param 无
* @return 无
* @author HZ12138
* @date 2022-08-03 16:43:14
*/
void CLOSE(void)
{
Steering_Engine_360(1, 30);
HAL_Delay(400);
Steering_Engine_360(0, 50);
HAL_Delay(180);
Steering_Engine_Stop();
HAL_Delay(2000);
}
外部中断
调用红外解码函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
IR_NEC_Read_Decode(air);
STOP_Ctl = 0;
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
}
主函数
读取成功标志,根据自己的遥控器判断信号是否触发
之后调用之前的开关灯函数即可
if (IR_NEC_Read_OK)
{
IR_NEC_Read_OK = 0;
if (IR_NEC_Read_Dat[0] == 0x4D && IR_NEC_Read_Dat[1] == 0xB2 && IR_NEC_Read_Dat[2] == 0xA3 && IR_NEC_Read_Dat[3] == 0x5C)
{
OPEN();
}
else if (IR_NEC_Read_Dat[0] == 0x4D && IR_NEC_Read_Dat[1] == 0xB2 && IR_NEC_Read_Dat[2] == 0x59 && IR_NEC_Read_Dat[3] == 0xA6)
{
CLOSE();
}
if (IR_NEC_Read_Dat[0] == 0x84 && IR_NEC_Read_Dat[1] == 0xff && IR_NEC_Read_Dat[2] == 0x81 && IR_NEC_Read_Dat[3] == 0x7e)
{
OPEN();
}
else if (IR_NEC_Read_Dat[0] == 0x84 && IR_NEC_Read_Dat[1] == 0xff && IR_NEC_Read_Dat[2] == 0x01 && IR_NEC_Read_Dat[3] == 0xfe)
{
CLOSE();
}
IR_NEC_Read_OK = 0;
}
成品
遥控关灯,懒人福音
Githubhttps://github.com/HZ1213825/HAL_STM32_Remote_Control_Lamp