MSP432 库函数实现 PID 电机调角度、调速

平台:Code Composer Studio 10.4.0
MSP432P401R SimpleLink™ 微控制器 LaunchPad™ 开发套件
(MSP-EXP432P401R)


编码器及所用改进型PID知识见【电赛PID半天入门】从接触编码器到调出好康的PID波形
工程示例

引脚配置

PWM引脚

在这里插入图片描述
在这里插入图片描述

外部中断测量编码器引脚配置

在这里插入图片描述
在这里插入图片描述

代码部分

初始化

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
	My_Task_Init(Key_Task, 1, 1024);
	My_Task_Init(LED_Task, 1, 1024);
    GPIO_enableInt(Encoder_1A);
    GPIO_enableInt(Encoder_1B);
    My_Uart_Init(&huart1, USB_UART, 115200);
    My_PWM_Hz_Init(&hpwm1, PWM_1A, 1000);
    My_PWM_Hz_Init(&hpwm2, PWM_1B, 1000);
    My_Task_Init(Motor_1_Task, 2, 1024);
    while(1)
    {
    	usleep(1000);
    }
}

编码器解读

由于使用的是外部中断检测,该程序仅适用于13线的霍尔编码器电机,
不适用500线的光电编码器电机,实测光电编码器电机在占空比大于44%的时候会由于高强度进入中断使得控制线程不能正常控制电机。

Encoder.c

/*
 * Encoder.c
 *
 *  Created on: 2021年8月2日
 *      Author: Royic
 */

#include "./inc/Encoder.h"

motor_type_def Motor_1;

int32_t Encoder_1_Count = 0;

const float Step_Angle = 360. / (Encoder_1_PPR * Encoder_1_Ratio * 2);

void Encoder_1A_Func(void)
{
	if(GPIO_read(Encoder_1A))
	{
		if(GPIO_read(Encoder_1B))
			Motor_1.angle -= Step_Angle;
		else
			Motor_1.angle += Step_Angle;
	}
	else
	{
		if(GPIO_read(Encoder_1B))
			Motor_1.angle += Step_Angle;
		else
			Motor_1.angle -= Step_Angle;
	}
}

void Encoder_1B_Func(void)
{
	if(GPIO_read(Encoder_1B))
	{
		if(GPIO_read(Encoder_1A))
			Motor_1.angle += Step_Angle;
		else
			Motor_1.angle -= Step_Angle;
	}
	else
	{
		if(GPIO_read(Encoder_1A))
			Motor_1.angle -= Step_Angle;
		else
			Motor_1.angle += Step_Angle;
	}
}

void Motor_Get_Speed(motor_type_def *Motor, float Angle_Now, float Delta_S)
{
	Motor->angle = Angle_Now;
	Motor->speed = (Motor->angle - Motor->angle_old)/Delta_S;
	Motor->angle_old = Angle_Now;
}

Encoder.h

/*
 * Encoder.h
 *
 *  Created on: 2021年8月2日
 *      Author: Royic
 */

#ifndef INC_ENCODER_H_
#define INC_ENCODER_H_

#include "./inc/main.h"

#include <ti/drivers/GPIO.h>

#define Encoder_1_PPR 	13
#define Encoder_1_Ratio 10

typedef struct
{
	double angle;
	double angle_old;
	double speed;
} motor_type_def;

void Motor_Get_Speed(motor_type_def *Motor, float Angle_Now, float Delta_S);

extern int32_t Encoder_1_Count;
extern float Motor_1_Angle;
extern motor_type_def Motor_1;

#endif

测速和控制部分

#define Motor_Angle_KP	0.5
#define Motor_Angle_KI	0.0025
#define Motor_Angle_KD	15

#define Motor_Speed_KP	0.1
#define Motor_Speed_KI	0.001
#define Motor_Speed_KD	1

uint8_t Angle_Or_Speed = 1;

float Target_Angle = 0;
float Target_Speed = 0;

pid_type_def Motor_Angle_PID;
pid_type_def Motor_Speed_PID;
const static fp32 motor_angle_pid[3]	= {Motor_Angle_KP, Motor_Angle_KI, Motor_Angle_KD};
const static fp32 motor_speed_pid[3]	= {Motor_Speed_KP, Motor_Speed_KI, Motor_Speed_KD};

Kalman_Typedef Speed_Kalman;

void *Motor_1_Task(void *arg0)
{
	float Control_Var = 0;
	PID_init(&Motor_Angle_PID, PID_POSITION, motor_angle_pid, 100, 100, 30, 2);
	PID_init(&Motor_Speed_PID, PID_POSITION, motor_speed_pid, 100, 100, 500, 0);
	Kalman_Init(&Speed_Kalman, 1e-6, 0.001);
	while(1)
	{
		Motor_Get_Speed(&Motor_1, Motor_1.angle, 0.001);
		KalmanFilter(&Speed_Kalman, Motor_1.speed);
		if(Angle_Or_Speed)
		{
			PID_calc(&Motor_Angle_PID, Motor_1.angle, Target_Angle);
			Control_Var = Motor_Angle_PID.out;
		}
		else
		{
			PID_calc(&Motor_Speed_PID, Speed_Kalman.out, Target_Speed);
			Control_Var = Motor_Speed_PID.out;
		}
		if(Control_Var > 0)
		{
			My_PWM_setDuty(&hpwm1, Control_Var);
			My_PWM_setDuty(&hpwm2, 0);
		}
		else
		{
			My_PWM_setDuty(&hpwm1, 0);
			My_PWM_setDuty(&hpwm2, -Control_Var);
		}
		if(Angle_Or_Speed)
			UART_printf(huart1, "%d.%d, %d.%d\r\n", (int)Motor_1.angle, (int)(Motor_1.angle * 100) % 100 , (int)Target_Angle, (int)(Target_Angle * 100) % 100);
		else
			UART_printf(huart1, "%d.%d, %d.%d, %d.%d\r\n", (int)Speed_Kalman.out, (int)(Speed_Kalman.out * 100) % 100 , (int)Target_Speed, (int)(Target_Speed * 100) % 100, (int)Motor_1.speed, (int)(Motor_1.speed * 100) % 100);
		usleep(1000);
	}
}

卡尔曼滤波器,用于对所测速度进行滤波

kalman.c

/*
卡尔曼滤波器
整理By 乙酸氧铍
*/
#include "kalman.h"

double KalmanFilter(Kalman_Typedef *klm, double input)
{
    //预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差
    klm->Now_P = klm->LastP + klm->Q;
    //卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差)
    klm->Kg = klm->Now_P / (klm->Now_P + klm->R);
    //更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值)
    klm->out = klm->out + klm->Kg * (input -klm->out);//因为这一次的预测值就是上一次的输出值
    //更新协方差方程: 本次的系统协方差赋给 klm->LastP 为下一次运算准备。
    klm->LastP = (1-klm->Kg) * klm->Now_P;
	
	return (klm->out);
}

void Kalman_Init(Kalman_Typedef *klm, const double klm_Q, const double klm_R)//温度klm_Q=0.01 klm_R=0.25
{
	klm->LastP=0.02;		//上次估算协方差
	klm->Now_P=0;			//当前估算协方差
	klm->out=0;				//卡尔曼滤波器输出
	klm->Kg=0;				//卡尔曼增益
	klm->Q=klm_Q;			//Q:过程噪声协方差 Q参数调滤波后的曲线平滑程度,Q越小越平滑;
	klm->R=klm_R;			//R:观测噪声协方差 R参数调整滤波后的曲线与实测曲线的相近程度,R越小越接近(收敛越快)
}

kalman.h

#ifndef __KALMAN_H__
#define __KALMAN_H__

typedef struct
{
    /*不用动*/
    double LastP;//上次估算协方差
    double Now_P;//当前估算协方差
    double out;//卡尔曼滤波器输出
    double Kg;//卡尔曼增益
	double Q;
	double R;
}Kalman_Typedef;

void Kalman_Init(Kalman_Typedef *klm, const double klm_Q, const double klm_R);
double KalmanFilter(Kalman_Typedef *klm, double input);

#endif

实验效果

速度滤波效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

控速效果

先加速再减速
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

控角效果

在这里插入图片描述
在这里插入图片描述

  • 34
    点赞
  • 209
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 34
    评论
MSP432库函数是用于开发MSP432微控制器的函数库。要使用MSP432库函数,首先需要下载并安装CCS(Code Composer Studio)开发工具。CCS是由德州仪器(Texas Instruments)公司提供的代码开发和试套件。可以从TI官网下载CCS并按照安装指南进行安装\[1\]。 在CCS中创建一个新的MSP432项目后,可以下载MSP432库函数。可以从TI官网下载MSP432库函数,并解压缩文件\[2\]。然后,在CCS中右键单击项目文件,选择"Add Existing Files",将下载的函数库文件添加到项目中\[3\]。 通过部署函数库,可以在CCS项目中使用MSP432库函数。在CCS中右键单击项目文件,选择"Add New",然后创建一个名为"driverlib"的新文件。将下载的函数库文件添加到"driverlib"文件中\[3\]。 通过以上步骤,就可以在CCS中使用MSP432库函数进行开发了。MSP432库函数提供了一系列函数和工具,可以帮助开发者更方便地编写和试MSP432微控制器的应用程序。 #### 引用[.reference_title] - *1* *2* [安装TI_MSP432库和导入CCS工程](https://blog.csdn.net/weixin_42717467/article/details/115005171)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [MSP430F5529基于CCS库函数开发——软件安装与库函数配置](https://blog.csdn.net/weixin_44098974/article/details/125686172)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 34
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乙酸氧铍

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

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

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

打赏作者

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

抵扣说明:

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

余额充值