倒立摆的实现 5.步进电机的控制

步进电机的控制

先是步进电机的头文件

/*
    ------------------------------------------------------------------------
  | 文件名     :motor.h
  | 文件描述   :本文件用于步进电机相关结构体的定义和函数接口
  | 作者       : pinocchio
  | 创建时间   :19.4.26
   ------------------------------------------------------------------------
	修改日期 :19.4.26
	修改人   :pinocchio
   ------------------------------------------------------------------------
  **************************************************************************
	* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil
	* 2. 本代码只适用于倒立摆,不建议用于其他用途
	* 3.本代码最终解释权归哈尔滨工业大学(深圳)所有 
	* 4.请勿转载!!!!!!!!!!!
	* 
	* Copyright (c) 2019 2019哈尔滨工业大学(深圳) 版权所有
	**************************************************************************

*/

#ifndef MOTOR_H_
#define MOTOR_H_

#define rotate 1
#define contrarotate -1
#define PI 3.1416
typedef struct 
{
  struct 
  {
  float KP;
  float KI;
  float KD;
	float error;
	float last_error;
	float integral;
  }pid;
	//就pid控制的定义
  
  float outputMAX;
  //防止输出速度过大,在1ms不能够输出
  float Ref_speed;
  //电机的目标速度
  int round_count;
	//用于脉冲的计数
	float rotate_times;
	//由目标速度换算出的输出脉冲数目
}Motor;
//定义电机的结构体
extern int tim_i;

void size_init(void);
extern Motor motor;
void motor_init(void);
void Rotate(void);
void Rontrarotate(void);
void motor_transmit(void);
float absolute_value(float i);
void auto_rotate(void);
//函数接口

#endif 

然后就是电机的控制.c文件

/*
    ------------------------------------------------------------------------
  | 文件名     :motor.c
  | 文件描述   :本文件用于步进电机控制
  | 作者       : pinocchio
  | 创建时间   :19.4.26
   ------------------------------------------------------------------------
	修改日期 :19.4.26
	修改人   :pinocchio
   ------------------------------------------------------------------------
  **************************************************************************
	* 1. 本代码基于STM32F427IIH(2018RM开发板A型)开发,编译环境为keil
	* 2. 本代码只适用于倒立摆,不建议用于其他用途
	* 3.本代码最终解释权归哈尔滨工业大学(深圳)所有 
	* 4.请勿转载!!!!!!!!!!!
	* 
	* Copyright (c) 2019 2019哈尔滨工业大学(深圳) 版权所有
	**************************************************************************

*/

#include "motor.h"
#include "main.h"
#include "tim.h"
#include "struct.h"
#include "encoder.h"


Motor motor;
Struct size;
//对电机结构体和尺寸的定义

void motor_init(void)
{
  motor.pid.KP = 10 ;
	motor.pid.KI = 0;
	motor.pid.KD = 0;
	motor.outputMAX = 0;
	motor.Ref_speed = 0; 
	motor.round_count=0;
	motor.rotate_times=0;
	motor.pid.error = 0;
	motor.pid.last_error = 0;
	motor.pid.integral = 0;
}
//电机相关数据初始化函数

void size_init(void)
{
	size.L = 0.1465;//编码器对应长度
	size.R = 0.195;//步进电机对应长度
}
//尺寸的初始化。这里后面根据目标修改


void motor_transmit(void)
{
   motor.rotate_times = (1.60 * motor.Ref_speed) / (2*PI*size.L) ;
	//计算出来达到目标速度需要输出多少个脉冲
	if(motor.rotate_times >= 0.5 )//判断正转
	{
		while (motor.round_count < motor.rotate_times)
		{
			Rotate();
		}
		motor.round_count=0;
	}
	else if (motor.rotate_times <= - 0.5  )//判断反转
	{
		while (motor.round_count > motor.rotate_times)
		{
			Rontrarotate();
		}
		motor.round_count=0;
	}
	else if (motor.rotate_times < 0.5&&motor.rotate_times > -0.5)
	{	
	}
	//如果脉冲数是0.6,那它会发一次脉冲,如果是0.4就不发脉冲
	//如果不写这个的话会导致0.01也会发1个脉冲0.99也是发一个脉冲
	//而1ms发一次脉冲,会导致有一个固定速度,导致难以控制
}


void Rotate(void)
{
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
	//这里是使能一次PWM,发送一个脉冲
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
	//这里是输出方向的
	motor.round_count ++;
}
//电机正向旋转的函数

void Rontrarotate(void)
{
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
	motor.round_count --;
}	
//电机反向旋转的函数

float absolute_value(float i)
{
	if(i>= 0 ) return i;
	else       return -i; 
}
//用于取绝对值的函数

void auto_rotate(void)
{ 
	motor.pid.last_error = motor.pid.error;
	
	//此处之所以要到0.8才控制是因为倒立摆要旋转到一定角度才可以控制
	//此处之所以只控制到0.995是因为如果已经控制完毕,就不发旋转信号,这样便于控制
	if( angle_position >= 0.80*PI&& angle_position <= 0.995*PI)
	{
	//你是正旋转的函数
		motor.pid.error = -(PI - absolute_value(angle_position));
		motor.Ref_speed = -(PI - absolute_value(angle_position)) * motor.pid.KP + motor.pid.KI * motor.pid.integral  + motor.pid.KD*( motor.pid.error-motor.pid.last_error) ;
		motor.pid.integral += motor.pid.error ;
	}
	if( angle_position <= -0.80*PI&& angle_position >= -0.995*PI)
	{
		motor.pid.error = PI - absolute_value(angle_position);
		motor.Ref_speed = (PI - absolute_value(angle_position))*motor.pid.KP + motor.pid.KI * motor.pid.integral + motor.pid.KD*( motor.pid.error-motor.pid.last_error) ;
		motor.pid.integral += motor.pid.error ;
	}
	
	
	if( (angle_position >= -0.80*PI && angle_position <= 0.80*PI)||angle_position >= 0.995*PI||angle_position <= -0.995*PI)
	{
		motor.Ref_speed = 0;
	}
	//此处是为了调试小角度时控制写的,因为摆一落下就没有力了,便于控制
	
	
}
//倒立摆控制函数

void start_rotate(void)
{
	
}
//用于起摆的函数,这里就不写了。留给大家写

那么现在步进电机的控制就写完了


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