基于STM32与红外感应开关的自动门设计与实现(结构+设计)

基于STM32与红外感应开关的自动门设计与实现

采用STM32作为主控,设计了自动和手动开门装置,MLX90614作为设计测温装置。

前言说明

元器件清单说明

  1. STM32F103C8T6系统板
  2. 微型滑台,步进电机
  3. TMC2208步进电机驱动器
  4. 红外接近开关
  5. MLX90614测温模块
  6. 四线0.96寸OLED屏幕
  7. 按键
  8. 限位触碰开关

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);     //清除EXTI0线路挂起位
}

 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);     //CCW往电机
		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);//在在OLED上显示实际测量的温度
	}
	else if(KEY_Infrared==0&&Opened==1)
	{
		Door_Opened_Flag = 1;
	}
	
 	 EXTI_ClearITPendingBit(EXTI_Line4);    //清除LINE5上的中断标志位	
}

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);     //CCW往电机
		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);//在在OLED上显示实际测量的温度
	}
	else if(KEY==0&&Opened==1)
	{
		Door_Opened_Flag = 1;
	}
	 EXTI_ClearITPendingBit(EXTI_Line15);  //清除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);	//使能PA端口时钟

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	            //PC0.2 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//根据设定参数初始化GPIOA
	GPIO_SetBits(GPIOA,GPIO_Pin_5);						 	//PA8输出高 顺时针方向  DRIVER_DIR
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOB,GPIO_Pin_1);						//PA11输出低 使能输出  DRIVER_OE
	
	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)     //24000
				{
					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);  
}
/********************************************
//相对定位函数 
//num 0~2147483647
//frequency: 20Hz~100KHz
//dir: CW(顺时针方向)  CCW(逆时针方向)
*********************************************/
void Locate_Rle3(u32 frequency,DIR_Type dir,u16 step) //相对定位函数
{
	
	if(TIM3->CR1&0x01)
	{
//		printf("\r\nThe last time pulses is not send finished,wait please!\r\n");
		return;
	}
	if((frequency<20)||(frequency>100000))
	{
//		printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");
		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)
	{
//		printf("\r\nThe last time pulses is not send finished,wait please!\r\n");
		return;
	}
	if((frequency<20)||(frequency>100000))
	{
//		printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");
		return;
	}
	motor_dir3=dir;
	DRIVER_DIR3=motor_dir3;
	TIM3_Startup(frequency);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DN36

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值