电赛-stm32f103zet6-减速电机配置-pid控制(简单使用)

前期准备:

要实现减速电机的配置,首先我们要了解自己的电机上编码器的参数。例如这款电机型号为:CHR-GM37-520

其参数如下图:

 从图上的基础脉冲数为11PPR我们可以看出电机轴转一圈可以产生11个脉冲信号

在电机的标签上看到电机减速比为1:90

那么电机转动一圈实际上产生脉冲数就是:90*11 = 990;

在单片机采用4倍频计数提高精度之后脉冲数:990 * 4 = 3,960;

这就意味着电机一圈的转动我们的单片机就会捕获3960个脉冲信号。

测速方法:在一定时间内,捕获脉冲数。

实际速度:一圈对应3960个脉冲,物理计算出一圈的长度,除以时间,得到实际速度。

驱动使用:l298n

 由图可知单片机需要输出3个信号:一个pwm信号,2个方向控制信号。

code : timer 

TIM1:PWM输出        TIM3:输入捕获        TIM4:定时器(都在里面运行)        

GPIOA: 3,4方向控制信号线        8,11pwm输出控制线

#ifndef __TIMER_H
#define __TIMER_H

#include "sys.h"

extern float cnt;
extern int Tim3_Arr;
extern int Tim3_Psc;

void Encoder_Init_TIM3(void);

void Pwm_Init_TIM1(u16 arr, u16 psc);

void Timer_Init_TIM4(u16 arr, u16 psc);

int Read_Encoder(void);

 
#endif



#include "timer.h"
#include "sys.h"
#include "delay.h"
#include "led.h"

uint16_t TIM1_CCR1_Val = 2000;
uint16_t TIM1_CCR4_Val = 18000;
uint16_t DEMO = 1000;

float zheng;
float fu;
float cnt;
int Tim3_Arr = 5999;
int Tim3_Psc = 0;
void Encoder_Init_TIM3(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_ICInitTypeDef TIM_ICInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = Tim3_Arr;
	TIM_TimeBaseInitStructure.TIM_Prescaler = Tim3_Psc;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	
	TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_ICFilter = 10;		//滤波器值
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);	//允许TIM3溢出中断
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01; 
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);

	TIM_SetCounter(TIM3, 0);	//TIM3 ->CNT = 0
	TIM_Cmd(TIM3, ENABLE);
}

void Timer_Init_TIM4(u16 arr, u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  ///使能TIM4时钟
	
	TIM_TimeBaseInitStructure.TIM_Period = arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);//初始化TIM4
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //允许定时器4更新中断
	TIM_Cmd(TIM4,ENABLE); //使能定时器4
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; //定时器3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00; //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}

void Pwm_Init_TIM1(u16 arr, u16 psc)
{
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	NVIC_InitTypeDef NVIC_InitSture;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// //使能定时器1的时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIO外设时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
		
	//PA8 TIM1_CH1 PA11 TIM1_CH4
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_11; //TIM_CH1    
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 80K
	TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	
	TIM_OCInitStructure.TIM_Pulse = TIM1_CCR1_Val;  
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
	
	TIM_OCInitStructure.TIM_Pulse = TIM1_CCR4_Val;		
	TIM_OC4Init(TIM1, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);

	TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_CtrlPWMOutputs(TIM1,ENABLE);	//MOE 主输出使能

	NVIC_InitSture.NVIC_IRQChannel = TIM1_UP_IRQn;
	NVIC_InitSture.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitSture.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitSture.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&NVIC_InitSture);

	TIM_Cmd(TIM1,ENABLE);  //使能TIM1
}


void Data_Prc(void)
{
	if(cnt < Tim3_Arr/2)
	{
		zheng = cnt/3960;
	}
	else if(cnt > Tim3_Arr/2)
	{
		fu = (cnt - Tim3_Arr)/3960;
	}
}



void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)//溢出中断
	{
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位	     	    	
	}				   
	
}

void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET) //溢出中断
	{
		LED0 = !LED0;
		cnt=TIM_GetCounter(TIM3);
		Data_Prc();
		TIM_SetCounter(TIM3,0);
		TIM_SetCounter(TIM4,0);
		TIM_SetCompare1(TIM1, DEMO);
		TIM_SetCompare4(TIM1, DEMO);
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  //清除中断标志位
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
	}	
}


code: main

#include "stm32f10x.h"
#include "sys.h"
#include "timer.h"
#include "delay.h"
#include "moter.h"

int main(void)
{	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	
	Pwm_Init_TIM1(19999,71);
	Moter_Init();
	Encoder_Init_TIM3();
	Timer_Init_TIM4(999, 7199);
	delay_init();
	
	while(1)
	{
		
		Motor_Forward();
	}
}



code:motor

#ifndef __MOTER_H
#define __MOTER_H

#include "sys.h"

#define M1_P PAout(4)
#define M1_N PAout(5)

void Moter_Init(void);

void Moter_Stop(void);

void Motor_Forward(void);

void Motor_Recede(void);

#endif



#include "moter.h"
#include "led.h"

void Moter_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	    //使能PA端口时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;		//端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 	//IO口速度为50MHz
	GPIO_Init(GPIOA, &GPIO_InitStructure);						//根据设定参数初始化PA4/5
}


void Moter_Stop(void)
{
	M1_P = 0;
	LED0 = 0;
	M1_N = 0;
	LED1 = 0;
	
}

void Motor_Forward(void)
{
	M1_P = 1;
	LED0 = 1;
	M1_N = 0;
	LED1 = 0;
}

void Motor_Recede(void)
{
	M1_P = 0;
	LED0 = 0;
	M1_N = 1;
	LED1 = 1;
}

这样就能简单的控制减速电机CHR-GM37-520转动拉。


版权声明:本文为weixin_45770795原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。