基于STM32与红外感应开关的自动门设计与实现
采用STM32作为主控,设计了自动和手动开门装置,MLX90614作为设计测温装置。
前言说明
元器件清单说明
- STM32F103C8T6系统板
- 微型滑台,步进电机
- TMC2208步进电机驱动器
- 红外接近开关
- MLX90614测温模块
- 四线0.96寸OLED屏幕
- 按键
- 限位触碰开关
Soildworks模型绘制
原理图绘制
TMC2208驱动介绍
TMC2208是一款超静音的两相步进电机驱动芯片,持续驱动电流1.4A,峰值电流2A,电压范围4.75V-36V,256细分;灵活的microPlyer插值单元,可提供高达256的细分,即使是在脉冲频率有限的系统中仍可完美地实现正弦控制;由于stealthChop2超静音技术在3D打印中被广泛应用,因此这些组件的设计也与现有3D打印机电子设备兼容,省去了重新设计所产生的昂贵费用。具有标准的step/dir接口,使用起来简单方便。可以替代原有的TMC2100,更低的发热量,特别适合3D打印市场。关键引脚说明
引脚 | 说明 |
---|
GND | 地 | VM | 我给的是5V1A | VIN | 逻辑电平输入3-5V | 1A | 相A+ | 2A | 相B+ | 1B | 相A- | 2B | 相B- | DIR | 方向输入 | EN | 使能,低电平有效 | STEP | 输入脉冲数 | MS1 | 细分 | MS2 | 细分 |
步进电机介绍
采用SM15-80L微型滑台作为门的载体,该滑台属于步进电机控制直接给高低电平是驱动不了的。
关键代码
下面展示一些 内联代码片 。
void EXTI0_IRQHandler(void)
{
delay_ms(10);
if(KEY_Limit_Switch==0)
{
Limit_Switch_Finish=0;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
void EXTI4_IRQHandler(void)
{
delay_ms(10);
u8 i,j;
float Temperature = 0;
char TempValue[80] = {0};
if(KEY_Infrared==0&&Opening==0)
{
Opening=1;
Door_Open_Flag = 1;
Locate_Rle3(5000,CCW,24000);
Temperature = SMBus_ReadTemp();
sprintf(TempValue,"%.1f", Temperature);
for(i = 6;i < 7;i++)
{
j = i - 6;
OLED_ShowCHinese16x16(i*16,4,j,TempCompany);
}
OLED_ShowString(40,4,(uint8_t *)TempValue,16);
}
else if(KEY_Infrared==0&&Opened==1)
{
Door_Opened_Flag = 1;
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
void EXTI15_10_IRQHandler(void)
{
delay_ms(10);
u8 i,j;
float Temperature = 0;
char TempValue[80] = {0};
if(KEY==0&&Opening==0)
{
Opening=1;
Door_Open_Flag = 1;
Locate_Rle3(5000,CCW,24000);
Temperature = SMBus_ReadTemp();
sprintf(TempValue,"%.1f", Temperature);
for(i = 6;i < 7;i++)
{
j = i - 6;
OLED_ShowCHinese16x16(i*16,4,j,TempCompany);
}
OLED_ShowString(40,4,(uint8_t *)TempValue,16);
}
else if(KEY==0&&Opened==1)
{
Door_Opened_Flag = 1;
}
EXTI_ClearITPendingBit(EXTI_Line15);
}
程序主要是通过外部引起中断执行的,一共用了三个中断,分别对应着手动开门,红外感应开门以及限位开关三个部分。
驱动代码块
#include "driver.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
long current_pos[2]={0,0};
u16 Motor_Step;
DIR_Type motor_dir3=CW;
u16 count[3]={0,0,0};
extern u8 Door_Open_Flag;
extern u8 Limit_Switch_Finish;
u8 Time_Flag=0;
u8 Limit_Switch_Flag=0;
u8 Flag=0;
extern u8 Opening;
u8 Opened=0;
void Driver_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
Limit_Switch_Flag=1;
Locate_Limit(5000,CCW);
while(Flag==0);
Flag=0;
Locate_Limit(5000,CW);
}
void TIM3_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
TIM_UpdateRequestConfig(TIM3,TIM_UpdateSource_Regular);
TIM_SelectOnePulseMode(TIM3,TIM_OPMode_Single);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = arr>>1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_Update ,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
TIM_Cmd(TIM3, DISABLE);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_FLAG_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update);
if(motor_dir3==CW)
{
TIM_GenerateEvent(TIM3,TIM_EventSource_Update);
TIM_Cmd(TIM3, ENABLE);
if(Limit_Switch_Finish==0)
{
Limit_Switch_Finish=1;
Opening = 0;
TIM_Cmd(TIM3, DISABLE);
}
}
else
{
if(Limit_Switch_Flag==1)
{
count[0]++;
TIM_GenerateEvent(TIM3,TIM_EventSource_Update);
TIM_Cmd(TIM3, ENABLE);
if(count[0]==1000)
{
count[0]=0;
Flag=1;
TIM_Cmd(TIM3, DISABLE);
LED0=0;
Limit_Switch_Flag=0;
}
}
else
{
count[1]++;
TIM_GenerateEvent(TIM3,TIM_EventSource_Update);
TIM_Cmd(TIM3, ENABLE);
if(count[1]==Motor_Step)
{
Opened = 1;
count[1]=0;
TIM_Cmd(TIM3, DISABLE);
if(Door_Open_Flag==1)
{
Time_Flag=1;
}
}
}
}
}
}
void TIM3_Startup(u32 frequency)
{
u16 temp_arr=1000000/frequency-1;
TIM_SetAutoreload(TIM3,temp_arr);
TIM_SetCompare2(TIM3,temp_arr>>1);
TIM_SetCounter(TIM3,0);
TIM_Cmd(TIM3, ENABLE);
}
void Locate_Rle3(u32 frequency,DIR_Type dir,u16 step)
{
if(TIM3->CR1&0x01)
{
return;
}
if((frequency<20)||(frequency>100000))
{
return;
}
motor_dir3=dir;
DRIVER_DIR3=motor_dir3;
Motor_Step = step;
TIM3_Startup(frequency);
LED0=1;
}
void Locate_Limit(u32 frequency,DIR_Type dir)
{
if(TIM3->CR1&0x01)
{
return;
}
if((frequency<20)||(frequency>100000))
{
return;
}
motor_dir3=dir;
DRIVER_DIR3=motor_dir3;
TIM3_Startup(frequency);
}
|