STM32舵机设备实现门锁功能详解

概述

需求来源:

门锁的开启和关闭,就是电机来控制。这里不进行实际门锁机械结构的设计,选择用舵机或者电机转动一定的角度,就代表门锁开启。

舵机开发整体思路:

  1. 使用STM32裸机开发舵机,使得舵机可以实现基本的转动功能
  2. 封装接口,使得主函数调用一个函数,传入指定角度即可控制舵机旋转
  3. 分层硬件与设备,建立一个STM32的硬件控制文件和一个舵机角度算法文件,使得舵机角度控制可以容易的移植到其他的芯片上。
  4. 使用封装好的.c .h文件,将功能再FreeRTOS上实现应用编程(在其他博文中,暂未实现)

代码层级关系:

舵机控制裸机实现

1、舵机控制原理

舵机的型号为sg90,它有3根线:黄色为PWM信号线,红色VCC接3.3v,棕色GND

实物图如下:

舵机转动的角度与PWM信号的高电平时间有关,角度范围为0~180°

该舵机的PWM信号要求为50Hz,高电平时间与角度关系如下:

2、配置STM32的PWM输出

使用STM32CubeMx对STM32进行PWM输出的初始化配置。

这里使用的是STM32F103C8T6的TIM3_CH1作为PWM输出端口,对应引脚为PA6。

分频系数PSC配置为72-1

其余的基本配置为:使用外部晶振8MHz,最终输入到定时器的时钟频率为72MHz

3、编写STM32控制PWM文件

3.1 文件及公式

在KEIL中创建两个文件my_pwm.c和my_pwm.h。这两个文件主要实现硬件的控制,向上提供硬件控制的接口。

代码功能总述:

  • 对PWM进行一些初始化:MyPWM_Init()
  • 将所需频率转换为ARR的值:PWM_FreqToARR()
  • 将所需占空比转换为CCR的值:PWM_DutyToCCR()
  • PWM硬件控制接口:PWM_Set()
  • 重要计算公式:

  • 定时器溢出时间计算公式:
  • 占空比计算公式:
  •  3.2 .h文件代码实现

    该.h文件主要去定义一些宏,方便后面移植代码时的参数修改。

    //PWM初始化参数
    #define __TIM_F 	72000000U //时钟
    #define __PSC 		(72-1)    //分频系数
    #define __FREQ		1000      //频率
    #define __DUTY      50		  //占空比

    3.3 .c文件代码实现

    3.3.1 MyPWM_Init()

    该函数的作用是对PWM进行一些初始化,让PWM输出1000Hz,占空比为50%的信号。

    具体函数实现如下:

    /*
     * MyPWM_Init:对PWM进行一些初始化1000Hz-50%
    */
    void MyPWM_Init(void){
    	
    	uint32_t PWM_ARR = 0;
    	uint32_t PWM_CCR = 0;
    	
    	//1.开启TIM3_CH1的PWM通道
    	HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
    	//2.将频率、占空比转为ARR、CCR
    	PWM_ARR = PWM_FreqToARR(__TIM_F,__FREQ,__PSC);
    	PWM_CCR = PWM_DutyToCCR(__DUTY,PWM_ARR);
    	//3.写入ARR、CCR寄存器
    	__HAL_TIM_SET_AUTORELOAD(&htim3,PWM_ARR);
    	HAL_TIM_GenerateEvent(&htim3,TIM_EVENTSOURCE_UPDATE);
    	__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,PWM_CCR);
    }
    3.3.2 PWM_FreqToARR()

    该函数的作用是将所需频率转换为ARR的值。根据的公式就是定时器溢出时间计算公式。

    具体代码实现如下:

    /*
     * PWM_FreqToARR:将所需频率转换为ARR的值
     * param TIM_F:定时器的时钟频率
     * param Freq:所需要的频率
     * param PSC:分频系数
     * @ret  由频率转换的ARR数值
    */
    uint32_t PWM_FreqToARR(uint32_t TIM_F,uint32_t Freq,uint32_t PSC){
    	
    	uint32_t PWM_ARR = 0;
    	
    	PWM_ARR = (double)TIM_F/((PSC+1)*Freq) - 1 + 0.5;
    	
    	return PWM_ARR;
    }
    3.3.3 PWM_DutyToCCR()

    该函数的作用是将所需占空比转换为CCR的值,根据的公式就是占空比计算公式。

    具体代码实现如下:

    /*
     * PWM_DutyToCCR:将所需占空比转换为CCR的值
     * param Duty:所需要的占空比
     * param ARR:定时器的ARR数值
     * @ret  由占空比转换的CCR数值
    */
    uint32_t PWM_DutyToCCR(double Duty,uint32_t ARR){
    	
    	uint32_t PWM_CCR = 0;
    	
    	PWM_CCR = (double)(ARR+1)*Duty/100 + 0.5;
    	
    	return PWM_CCR;
    }
    3.3.4 PWM_Set()

    该函数的作用是设置所需PWM输出的频率和占空比参数,这是向上提供的硬件控制接口。

    具体函数实现如下:

    /*
     *PWM_Set:设置所需PWM输出的频率和占空比参数
     * param Freq:所需要的频率
     * param Duty:所需要的占空比
    */
    void PWM_Set(uint32_t Freq,double Duty){
    	
    	uint32_t PWM_ARR = 0;
    	uint32_t PWM_CCR = 0;
    	
    	//1.将频率、占空比转为ARR、CCR
    	PWM_ARR = PWM_FreqToARR(__TIM_F,Freq,__PSC);
    	PWM_CCR = PWM_DutyToCCR(Duty,PWM_ARR);
    	
    	//2.写入ARR、CCR寄存器
    	__HAL_TIM_SET_AUTORELOAD(&htim3,PWM_ARR);
    	HAL_TIM_GenerateEvent(&htim3,TIM_EVENTSOURCE_UPDATE);
    	__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,PWM_CCR);
    }

    4、编写舵机角度算法

    4.1 文件

    在KEIL中创建两个文件sg90.c和sg90.h。这两个文件主要是实现舵机角度与硬件接口参数的对接。最终再向上提供一个接口,以便应用层代码的使用。

    代码功能总述:

  • 初始化sg90舵机设备:Sg90_Init()
  • 将传入的角度转为占空比:Sg90_AngleToDuty()
  • SG90设备控制接口:Sg90_Control()
  • 4.2 .h文件代码实现

    该.h文件主要将舵机设备抽象成一个结构体,以及舵机设备一些固定参数的宏定义

    //舵机设备
    typedef struct{
    	
    	int angle;
    	int speed;
    	
    }DevSg90,*PDevSg90;
    extern DevSg90 Sg90;  //.c定义的全局变量,设备结构体
    extern PDevSg90 pSg90;//.c定义的全局变量,设备结构体指针
    
    //舵机参数
    #define SG90_PWM_FREQ 50      //工作的PWM频率50Hz-20ms
    #define SG90_MAX_HIGH_TIM 2.5 //最大高电平时间,单位ms
    #define SG90_MIN_HIGH_TIM 0.5 //最小高电平时间ms
    #define SG90_MAX_ANGLE	  180 //最大转动角度
    #define SG90_MIN_ANGLE    0   //最小转动角度

    4.3 .c文件代码实现

    4.3.1 Sg90_Init()

    该函数的作用是初始化sg90舵机设备,设置设备初始角度为0度,速度-1代表任意(后续没编写)

    具体代码实现如下:

    /*
     * Sg90_Init:初始化sg90舵机设备
     * param pDev:sg90设备指针
     * @ret  -1--err  0--success
    */
    int Sg90_Init(PDevSg90 pDev){
    	
    	//1.参数有效性判断
    	if(pDev == NULL){
    		printf("pDev is NULL \r\n");
    		return -1;
    	}
    	pDev->angle = 0;
    	pDev->speed = -1;//-1代表默认
    	return 0;
    }
    4.3.2 Sg90_AngleToDuty()

    该函数的作用是将传入的角度转为占空比。

    代码设计思路:

    根据" 1.舵机控制原理 "章节可以得知,高电平时间与转度的关系是线性的,因此可以使用归一化的方法去实现高电平时间与转度的转换。

    因为硬件接口提供的PWM控制只有频率和占空比两个参数,所以还需要将高电平时间转为占空比的值。根据" 1.舵机控制原理 "章节可以得知,该舵机的PWM控制信号是固定的50Hz,因此使用公式"占空比 = 高电平时间/总周期时间"即可进行转换。

    具体代码实现如下:

    /*
     * Sg90_AngleToDuty:将传入的角度转为占空比
     * param angle: 需要的角度
     * @ret -1--err  other--转换后的占空比
    */
    double Sg90_AngleToDuty(double angle){
    	
    	double percentAngel = 0;
    	double highTime = 0;
    	double duty = 0;
    	
    	//1.参数有效性判断
    	if(angle > 180 || angle < 0){
    			printf("angle err\r\n");
    			return -1;
    	}
    	//2.开始转换
    	percentAngel = angle/(SG90_MAX_ANGLE-SG90_MIN_ANGLE);
    	//printf("Debug:percentAngel = %lf\r\n",percentAngel);
    	highTime = percentAngel*(SG90_MAX_HIGH_TIM - SG90_MIN_HIGH_TIM)+SG90_MIN_HIGH_TIM;
    	duty = highTime/((double)1/SG90_PWM_FREQ*1000)*100;//注意单位换算
    	return duty;
    }
    4.3.3 Sg90_Control()

    该函数的作用是SG90设备控制接口,这是应用层调用控制舵机的代码。

    具体的函数实现如下:

    /*
     * Sg90_Control:SG90设备控制接口
     * param angle:所需转动的角度
     * @ret  -1--err  0--success
    */
    int Sg90_Control(double angle){
    	
    	double duty = 0;
    	
    	//1.参数有效性判断
    	if(angle > 180 || angle < 0){
    			printf("angle err\r\n");
    			return -1;
    	}
    	//printf("Debug:angle=%lf\r\n",angle);
    	//2.计算占空比
    	duty = Sg90_AngleToDuty(angle);
    	//printf("Debug:duty=%lf\r\n",duty);
    	//3.调用硬件代码进行控制
    	PWM_Set(SG90_PWM_FREQ,duty);
    	return 0;
    }

    5、整体调试

    调试代码如下:

    MyPWM_Init();				//初始化PWM硬件
    Sg90_Init(pSg90);			//初始化舵机设备
    pSg90->angle = 180;			//设置转动角度为180°
    Sg90_Control(pSg90->angle); //驱动舵机转动

    作者:荣世蓥

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32舵机设备实现门锁功能详解

    发表回复