串级PID控制3508(2)(单环角度环+单环角速度环+串级PID)

这篇PID的调制就知识我自己个人对于PID的理解了,看了B站好多大佬的视频所以有问题请大家见谅,也请大家多多指正。

这里给大家介绍一个学习PID现象的网页

https://pid-simulator-web.skythinker.top/

首先我们要知道,DJM3508+C620电调的反馈值上的编码值是相对编码值,所以我们要将相对编码值转化为绝对编码值

这里给大家提供一个思路代码

cpp 复制代码
void CAN_GetMotorData(motor_measure_t * motor )
{
	
	if(motor->ecd - motor->last_ecd>4096)
	{
		motor->circle--;
	}
	
	else if(motor->ecd - motor->last_ecd< -4096)
	{
		motor->circle++;
	}
	 
	//计算转动的绝对编码值
	motor->encoder = motor->circle*8192+motor->last_ecd;
	
	//RPM换算到rad/s
	motor ->speed_rpm = (motor ->speed_rpm* 3.14)/60;
	
	//解算角度
	
	motor ->angle = (double)motor->encoder/8192*2*3.14;
	
	
	motor->last_ecd = motor->ecd;
	
}

这个代码的转换思路大致是,电机转动的速度是有最多上线的,也就是说在我的测量时间下,两次的差值不可能超过半圈,所以默认为超过半圈就是淘券了也就是转完一圈了。

然后再下面就是PID的基本代码了

大家有不懂得可以看我前面的文章,但是我想告诉大家的是PID是一种控制算法,以结果为准,不用把所有的附加算法全部加上,要根据现象添加算法

cpp 复制代码
#include "PID.h"

PID_typedef PID_speed =
{
	.Kp = 5,
	.Ki = 0.8,
	.Kd = 5,
	.Max_iout = 100,
	.Max_out = 16384,
	
};

PID_typedef PID_angle =
{
	.Kp = 0.4,
	.Ki = 0.3,
	.Kd = 0.3,
	.Max_iout = 10,
	.Max_out = 450,
};



float PID_Update(PID_typedef *PID1)
{
  


    PID1->error[1] = PID1->error[0];


	PID1->error[0] = PID1->target - PID1->Actual;
    //LimitMax(&PID->Iout, PID->Max_iout);


    //if (PID->error[0] < 0)
        //PID->error[0] =  -PID->error[0];
    //else
       // return PID->error[0];
		//if(PID->error[0] < PID->Ki_divider)
		{

        PID1->Iout += PID1->Ki * PID1->error[0];
    }
    //else
		{

        //float fast_Iout = PID->fast_Ki * (PID->error[0] - PID->error[1]);
        //LimitMax(&fast_Iout, PID->Max_fast_iout);
        //PID->Iout += fast_Iout;
    }


    LimitMax(&PID1->Iout, PID1->Max_iout);

    PID1->D_item = (PID1->error[0] - PID1->error[1]);
    PID1->Dout = PID1->Kd * PID1->D_item;


    LimitMax(&PID1->Iout, PID1->Max_out);


    PID1->OUT = PID1->Kp * PID1->error[0] + PID1->Iout + PID1->Dout;
    LimitMax(&PID1->OUT, PID1->Max_out);

    return PID1->OUT;
}
cpp 复制代码
#ifndef PID_H
#define PID_H

#include "main.h"

typedef struct 
{
    float Kp;              /* 比例系数 Proportional coefficient */
    float Ki;              /* 积分系数 Integral coefficient */
    float fast_Ki;         /* 快速积分系数 Fast integral coefficient */
    float Kd;              /* 微分系数 Derivative coefficient */
    float Actual;         /* 测量值 Measured value */
    float target;          /* 目标值 Target value */
    float error[3];        /* 误差数组 Error array */
    float Pout;            /* 比例输出 Proportional output */
    float Iout;            /* 积分输出 Integral output */
    float D_item;          /* 微分项 Derivative item */
    float Dout;            /* 微分输出 Derivative output */
    float OUT;             /* 总输出 Total output */
    float Max_iout;        /* 积分输出限幅 Integral output limit */
    float Max_fast_iout;   /* 快速积分输出限幅 Fast integral output limit */
    float Max_out;         /* 总输出限幅 Total output limit */
    float Ki_divider;      /* 积分分离阈值 Integral separation threshold */
} PID_typedef;



float PID_Update(PID_typedef *PID1);


#endif /* PID_H */
cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2026 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp_can.h"
#include "CAN_receive.h"
#include "PID.h"
#include <stdio.h>
/* USER CODE END Includes */
void LimitMax(float *value, float max_value)
{
    if(*value > max_value)
        *value = max_value;
    else if(*value < -max_value)
        *value = -max_value;
}
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
extern PID_typedef PID_angle;
extern PID_typedef PID_speed;
extern motor_measure_t motor_chassis[7];

float out_angle = 0 ;
float out_speed = 0 ;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 10);
    
    while((huart1.Instance->SR & USART_SR_TXE) == 0)
    {
        ;
    }
    
    huart1.Instance->DR = *(uint8_t*)&ch;

    return ch;
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN1_Init();
  MX_CAN2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	can_filter_init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  	if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0)
		{
			HAL_Delay(20);
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0);
			
			
			PID_angle.target += 5000;
//			PID_Motor1.Target += (6.28*0.5);
			
		}
	  
	 out_angle = PID_Update(&PID_angle);
	  
	  PID_speed.target = out_angle;
	  out_speed = PID_Update(&PID_speed);
	  
	  CAN_cmd_chassis(500,out_speed,500,500);

//	  CAN_cmd_chassis(500,400,500,500);
	  HAL_Delay(10);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 6;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
相关推荐
九.九8 小时前
ops-transformer:AI 处理器上的高性能 Transformer 算子库
人工智能·深度学习·transformer
春日见8 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
恋猫de小郭8 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
YJlio8 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
deephub8 小时前
Agent Lightning:微软开源的框架无关 Agent 训练方案,LangChain/AutoGen 都能用
人工智能·microsoft·langchain·大语言模型·agent·强化学习
大模型RAG和Agent技术实践9 小时前
从零构建本地AI合同审查系统:架构设计与流式交互实战(完整源代码)
人工智能·交互·智能合同审核
老邋遢9 小时前
第三章-AI知识扫盲看这一篇就够了
人工智能
互联网江湖9 小时前
Seedance2.0炸场:长短视频们“修坝”十年,不如AI放水一天?
人工智能
PythonPioneer9 小时前
在AI技术迅猛发展的今天,传统职业该如何“踏浪前行”?
人工智能
冬奇Lab9 小时前
一天一个开源项目(第20篇):NanoBot - 轻量级AI Agent框架,极简高效的智能体构建工具
人工智能·开源·agent