一、引言
前面帖子也分享了正常驱动DS18B20模块,今天分享一下,在上期工程的基础上,增加驱动电机模块,实现一个简易的夏季降温控制装置。夏季到来,南方室内温度过高,很难入睡。一整晚开着空调觉得太费电,整夜开着吊扇又怕着凉感冒,那如果使用一套自动控温装置,既能实现节能减排,又能达到精准降温,非常适用。
二、电机驱动模块
原本使用42步进电机驱动器去驱动42步进电机,结果没有相应的风扇叶,驱动演示效果不怎么理想。然后选择采用L298N电机驱动模块,连接12V直流电机,并拧紧风扇叶片,驱动效果非常不错。
下面介绍一下L298N模块的基本资料。
由上图可知,该驱动板可驱动两路直流电机,使能端ENA,ENB为高电平有效,控制方式及直流电机状态表如下所示:
若要对直流电机进行PWM调速控制,则需要设置IN1和IN2,确定电机的转动方向,然后对使能端输出PWM脉冲,即可实现调速。注意当使能信号为0时,电机处于自动停止状态;当使能信号为1,且IN1和IN2为00或11时,电机处于制动状态,阻止电机转动。
三、硬件接口
根据《DS_AT32M412_416_V2.01_ZH.pdf》数据手册,结合《AT_START_M412_V1.0_SCH.pdf》原理图,管脚复用关系,选择相应IO口。为了更好的交互体验,这里还引入蜂鸣报警器模块,占用一个GPIO口。综上情况,实验中使用到的硬件接口关系列表如下:
因为电机是12V直流电机,因此L298N模块采用12V供电。结合板上的VCC与GND管脚分布,硬件实物连接图见如下:
四、驱动源码
原本使用GPIO中断方式触发电机启动,然而LCD屏显示温度变的没那么流畅,因此直接采用循环检测模式,体验效果还不错。之前也分享了LCD、DS18B20的驱动源码,今儿就不再分享这部分代码,有需要的网友请翻阅前期发布的帖子。
L298N与Beep初始化驱动部分代码如下:
motor.h
复制
; ; ;
motor.c
复制
{ crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); } { gpio_init_type gpio_init_struct; gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_pins = GPIO_PINS_1; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE1, GPIO_MUX_2); gpio_init_struct.gpio_pins = GPIO_PINS_2 | GPIO_PINS_10; gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOB, &gpio_init_struct); } { gpio_init_type gpio_init_struct; gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_pins = GPIO_PINS_5; gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOB, &gpio_init_struct); gpio_bits_reset(GPIOB,GPIO_PINS_5); }
main.c
复制
tmr_output_config_type tmr_oc_init_structure; crm_clocks_freq_type crm_clocks_freq_struct = {}; temperature = ; ccr1_val = ; ccr2_val = ; ccr3_val = ; ccr4_val = ; prescalervalue = ; { i, DS18B20ID[]; str[]; system_clock_config(); at32_board_init(); motor_crm_configuration(); crm_clocks_freq_get(&crm_clocks_freq_struct); motor_gpio_configuration(); beep_gpio_configuration(); uart_print_init(); prescalervalue = () ((crm_clocks_freq_struct.apb1_freq) / ) - ; tmr_base_init(TMR3, , prescalervalue); tmr_cnt_dir_set(TMR3, TMR_COUNT_UP); tmr_clock_source_div_set(TMR3, TMR_CLOCK_DIV1); tmr_output_default_para_init(&tmr_oc_init_structure); tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A; tmr_oc_init_structure.oc_idle_state = FALSE; tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH; tmr_oc_init_structure.oc_output_state = TRUE; tmr_output_channel_config(TMR3, TMR_SELECT_CHANNEL_4, &tmr_oc_init_structure); tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_4, ccr1_val); tmr_output_channel_buffer_enable(TMR3, TMR_SELECT_CHANNEL_4, TRUE); tmr_period_buffer_enable(TMR3, TRUE); tmr_counter_enable(TMR3, TRUE); tmr_output_enable(TMR3, TRUE); LcdInit(); (); LcdFill(,,,,BLACK); LcdShowString(,,,RED, BLACK,); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); delay_ms(); (DS18B20_Init()) { (); LcdFill(,,,,BLACK); LcdShowString(,,,RED, BLACK,); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); delay_ms(); } (); LcdFill(,,,,BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShowString(,,,RED, BLACK,); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShowString(,,,YELLOW, BLACK,); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); DS18B20_ReadId(DS18B20ID); (); ( i = ; i < ; i ++ ) ( , DS18B20ID[i]); (); (str,,DS18B20ID[],DS18B20ID[],DS18B20ID[],DS18B20ID[], DS18B20ID[],DS18B20ID[],DS18B20ID[],DS18B20ID[]); LcdShowString(,,,RED, BLACK,); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShowString(,,str,RED,BLACK,); delay_ms(); () { temperature = DS18B20_GetTemp_MatchRom(DS18B20ID); (,temperature); LcdFill(,,,,BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LcdShow16x16Hz(, , , YELLOW, BLACK); LCD_ShowFloatNum1(,,temperature,,RED, BLACK,); LcdShow16x16Hz(, , , RED, BLACK); delay_ms(); (temperature <= TEMP_THRESHOLD) { tmr_output_enable(TMR3, FALSE); gpio_bits_reset(GPIOB,GPIO_PINS_5); gpio_bits_reset(GPIOB,GPIO_PINS_2); gpio_bits_reset(GPIOB,GPIO_PINS_10); } (temperature-TEMP_THRESHOLD <= ) { gpio_bits_reset(GPIOB,GPIO_PINS_10); gpio_bits_set(GPIOB,GPIO_PINS_2); tmr_output_enable(TMR3, FALSE); tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_4, ccr1_val); tmr_output_enable(TMR3, TRUE); gpio_bits_toggle(GPIOB,GPIO_PINS_5); delay_ms(); } (temperature-TEMP_THRESHOLD <= ) { tmr_output_enable(TMR3, FALSE); tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_4, ccr2_val); tmr_output_enable(TMR3, TRUE); gpio_bits_toggle(GPIOB,GPIO_PINS_5); delay_ms(); } (temperature-TEMP_THRESHOLD <= ) { tmr_output_enable(TMR3, FALSE); tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_4, ccr3_val); tmr_output_enable(TMR3, TRUE); gpio_bits_toggle(GPIOB,GPIO_PINS_5); delay_ms(); } (temperature-TEMP_THRESHOLD <= ) { tmr_output_enable(TMR3, FALSE); tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_4, ccr4_val); tmr_output_enable(TMR3, TRUE); gpio_bits_toggle(GPIOB,GPIO_PINS_5); delay_ms(); } { tmr_output_enable(TMR3, FALSE); gpio_bits_reset(GPIOB,GPIO_PINS_5); gpio_bits_reset(GPIOB,GPIO_PINS_2); gpio_bits_reset(GPIOB,GPIO_PINS_10); } } }
根据以上代码可知,温度门限控制在31.8℃以下,高于该温度0.5℃内为一等级预警;高于1.5℃为二等级报警;高于2.5℃为三等级鸣警;高于3.5℃为四等级超温告警。每等级驱动的PWM占空比不同,因此驱动电机的转速也不同,蜂鸣器告警的频率也不同。
五、效果演示
使用手指触摸DS18B20给温度传感器加温,当温度超过限定阀值时,则启动风机,并唤起蜂鸣器报警提示,吹风给DS18B20模块降温;当温度还持续加热,则启动更高等级的风速与报警频率,等级越高,风速越快越大,因此降温越快。风吹着降温明显,正如演示视频当中,用手指加温的同时,风机启动了加温进度明显减慢了。