• 【STM32】【HAL库】【实用制作】遥控关灯


    目录

    需求分析

    方案设计

    硬件设计

    电源

    stm32系统

    复位电路

     晶振

    引导跳线

    ​编辑

     STLink下载电路

    主芯片电源

     主芯片

     电压检测

    舵机驱动

    ​编辑

     红外

    软件部分

    思路

    运动过程

     HAL初始化

     代码

    低功耗

    电压检测

    LED

    开灯和关灯

    外部中断

    主函数

    成品


    需求分析

    房间里的灯的开关距离床铺较远,每次睡觉前都得爬下床去关灯

    因此设计一个可以远距离遥控的设备

    需要满足:

    • 无需修改家庭电路(怕被骂)
    • 使用电池供电(开关距离插座很远)
    • 低功耗 
    • 检测电池电压
    • 使用家用遥控器(废旧遥控器)
    • 可以不影响开关使用

    方案设计

    使用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发送中断

     

     代码

    低功耗

    进入休眠模式,外部中断可以将其唤醒,从这个函数的结束处继续运行

    1. /**
    2. * @brief 进入休眠模式
    3. * @param 无
    4. * @return 无
    5. * @author HZ12138
    6. * @date 2022-08-03 16:47:42
    7. */
    8. void enter_stop_mode(void)
    9. {
    10. __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    11. HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    12. }

    退出休眠模式为保证正常运行需要调用所有的hal库生成的初始化函数

    1. /**
    2. * @brief 退出休眠模式
    3. * @param 无
    4. * @return 无
    5. * @author HZ12138
    6. * @date 2022-08-03 16:47:54
    7. */
    8. void exit_stop_mode(void)
    9. {
    10. HAL_Init();
    11. SystemClock_Config();
    12. MX_GPIO_Init();
    13. MX_TIM3_Init();
    14. MX_TIM1_Init();
    15. MX_TIM2_Init();
    16. MX_ADC1_Init();
    17. }

    电压检测

    整个函数再定时器中断里调用,等待无操作6秒后调用

    检测电压,多次达到额定值以下触发报警 

    1. /**
    2. * @brief 电压检测
    3. * @param 无
    4. * @return 无
    5. * @author HZ12138
    6. * @date 2022-08-03 16:44:06
    7. */
    8. void Voltage_detection(void)
    9. {
    10. uint16_t V = 0;
    11. HAL_ADC_Start(&hadc1); //开启ADC
    12. HAL_ADC_PollForConversion(&hadc1, 100); //开启电压检测
    13. if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)) //转化完成
    14. {
    15. V = HAL_ADC_GetValue(&hadc1); //获取电压值
    16. if (V < 2600)
    17. {
    18. HAL_Delay(100);
    19. HAL_ADC_PollForConversion(&hadc1, 100); //去抖
    20. if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
    21. {
    22. V = HAL_ADC_GetValue(&hadc1);
    23. if (V < 2600)
    24. {
    25. HAL_Delay(100);
    26. HAL_ADC_PollForConversion(&hadc1, 100); //再去抖
    27. if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
    28. {
    29. V = HAL_ADC_GetValue(&hadc1);
    30. if (V < 2600)
    31. {
    32. // LED_Ctl = 0;
    33. STOP_Ctl = 0;
    34. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); //点亮灯
    35. }
    36. }
    37. }
    38. }
    39. }
    40. else
    41. {
    42. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); //关闭led
    43. }
    44. }
    45. HAL_ADC_Stop(&hadc1); //关闭adc
    46. }

    LED

    上电LED闪烁

    1. uint8_t LED_Ctl = 0; // LED控制计时
    2. /**
    3. * @brief 上电时LED闪
    4. * @param 无
    5. * @return 无
    6. * @author HZ12138
    7. * @date 2022-08-03 16:43:29
    8. */
    9. void INIT_LED(void)
    10. {
    11. if (LED_Ctl % 2)
    12. {
    13. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
    14. }
    15. else
    16. {
    17. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
    18. }
    19. LED_Ctl++;
    20. }

    LED与休眠控制

    1s定时器中断调用

    1. uint8_t STOP_Ctl = 0; //进入休眠模式计时
    2. /**
    3. * @brief led控制
    4. * @param 无
    5. * @return 无
    6. * @author HZ12138
    7. * @date 2022-08-03 16:46:48
    8. */
    9. void LED_Ctrl(void)
    10. {
    11. if (LED_Ctl < 6)
    12. {
    13. INIT_LED(); //前6秒闪烁
    14. }
    15. else
    16. {
    17. STOP_Ctl++;
    18. Voltage_detection();
    19. }
    20. if (STOP_Ctl >= 6)
    21. {
    22. STOP_Ctl = 0;
    23. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); //关灯
    24. enter_stop_mode(); //休眠
    25. exit_stop_mode(); //退出休眠
    26. }
    27. }

    开灯和关灯

    这部分的延迟时间需要根据自己的开关来调试和确定 

    1. /**
    2. * @brief 开灯
    3. * @param 无
    4. * @return 无
    5. * @author HZ12138
    6. * @date 2022-08-03 16:43:01
    7. */
    8. void OPEN(void)
    9. {
    10. Steering_Engine_360(0, 30);
    11. HAL_Delay(400);
    12. Steering_Engine_360(1, 50);
    13. HAL_Delay(100);
    14. Steering_Engine_Stop();
    15. HAL_Delay(2000);
    16. }
    17. /**
    18. * @brief 关灯
    19. * @param 无
    20. * @return 无
    21. * @author HZ12138
    22. * @date 2022-08-03 16:43:14
    23. */
    24. void CLOSE(void)
    25. {
    26. Steering_Engine_360(1, 30);
    27. HAL_Delay(400);
    28. Steering_Engine_360(0, 50);
    29. HAL_Delay(180);
    30. Steering_Engine_Stop();
    31. HAL_Delay(2000);
    32. }

    外部中断

    调用红外解码函数

    1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    2. {
    3. if (GPIO_Pin == GPIO_PIN_0)
    4. {
    5. IR_NEC_Read_Decode(air);
    6. STOP_Ctl = 0;
    7. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
    8. }
    9. }

    主函数

    读取成功标志,根据自己的遥控器判断信号是否触发

    之后调用之前的开关灯函数即可

    1. if (IR_NEC_Read_OK)
    2. {
    3. IR_NEC_Read_OK = 0;
    4. 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)
    5. {
    6. OPEN();
    7. }
    8. 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)
    9. {
    10. CLOSE();
    11. }
    12. 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)
    13. {
    14. OPEN();
    15. }
    16. 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)
    17. {
    18. CLOSE();
    19. }
    20. IR_NEC_Read_OK = 0;
    21. }

    成品

    遥控关灯,懒人福音

    Githubhttps://github.com/HZ1213825/HAL_STM32_Remote_Control_Lamp

  • 相关阅读:
    Linux系统目录结构
    Node-EventEmitter的用法
    帆软FineReport决策报表之页面布局
    机器学习——Machine Learning
    多段曲线控温“核函数“算法分析(完整梯形图源代码)
    GO语言网络编程(并发编程)Channel
    es: java->count统计、distinct去重
    vue3+Element-plus el-select 下拉选择 多选增加全选封装组件
    Flutter网络请求和数据解析
    acwing 826. 单链表 学习笔记
  • 原文地址:https://blog.csdn.net/m0_57585228/article/details/125458076