活动介绍
file-type

Windows环境下C/C++编程:一阶惯性环节实现

版权申诉
5星 · 超过95%的资源 | 706B | 更新于2024-12-17 | 85 浏览量 | 1 下载量 举报 收藏
download 限时特惠:#9.90
知识点详细说明: 一、Windows编程基础 在Windows平台上进行编程,首先需要了解Windows编程的基本概念和技术。Windows编程通常涉及以下几个方面: 1. Windows API: Windows应用程序编程接口是操作系统提供的一组函数,用于实现各种Windows功能,如界面管理、文件操作、系统服务等。 2. 消息驱动: Windows是一个消息驱动的系统,所有的用户输入和系统通知都通过消息的形式发送给应用程序。 3. 窗口和控件: 理解如何创建和管理窗口(Windows),以及窗口内的控件(Controls),是Windows编程的基础。 4. GUI编程: 图形用户界面(Graphical User Interface)是用户与程序交互的视觉表示,涉及各种界面元素的设计与实现。 5. 多线程编程: Windows支持多线程,允许程序同时执行多个任务。线程的创建、管理和同步是提高程序性能和响应速度的关键。 6. 驱动程序开发: 在系统底层进行编程,需要对硬件进行直接控制,这通常涉及到编写Windows驱动程序。 二、C/C++编程语言 C/C++是Windows平台下广泛使用的编程语言,具有高效执行性能和灵活的系统级操作能力。 1. C语言基础: C语言是编程语言中的经典,具有过程化编程的特点,是系统编程的主要语言之一。 2. C++面向对象: C++是C语言的超集,引入了面向对象编程(OOP)的概念,支持类、继承和多态等特性。 3. 标准库: C/C++提供了丰富的标准库,包括输入/输出(iostream)、字符串处理(string)、容器(vector, map等)和算法等。 4. 内存管理: C/C++提供了直接的内存操作能力,包括动态内存分配和释放(malloc, free, new, delete等)。 5. 错误处理: C/C++中的错误处理通常依赖于返回值和异常机制。 三、WIN-TC环境 WIN-TC是一个集成开发环境(IDE),专注于C/C++语言的Windows平台应用程序开发。 1. 开发环境: WIN-TC为C/C++提供了一个便捷的开发环境,包括代码编辑、编译和调试等功能。 2. 资源管理: WIN-TC支持资源文件(如菜单、对话框和图标)的编辑与管理。 3. 调试工具: 通过WIN-TC内置的调试工具,开发者可以设置断点、单步执行程序并查看变量状态。 4. 文档管理: WIN-TC能够组织和管理项目文档,方便代码的版本控制和团队协作。 四、一阶惯性环节编程 在控制工程中,一阶惯性环节是常见的数学模型,通常用于描述具有延迟特性的系统。 1. 理论基础: 一阶惯性环节的数学表达式为τ·dy/dt + y = K·u,其中τ是时间常数,K是增益,u是输入,y是输出。 2. 数字仿真: 在编程中实现一阶惯性环节通常需要进行数值积分,常见的方法有欧拉法、龙格-库塔法等。 3. 控制系统设计: 在控制系统设计中,一阶惯性环节用于分析系统的响应特性,比如上升时间、过渡过程时间等。 4. 编程实现: 使用C/C++在WIN-TC环境下编程实现一阶惯性环节需要考虑算法的稳定性和精确性,同时也要考虑用户界面和交互方式。 文件《Inertia.c》中的程序代码很可能是围绕实现上述一阶惯性环节的数学模型进行编程设计的。代码中可能包含了算法实现、数据结构设计、输入输出处理等部分,并且应该能够通过WIN-TC环境进行编译和运行。 总结而言,文件《Inertia.rar_Windows编程_C/C++_》中的内容涉及了Windows操作系统下的编程实践、C/C++语言的高级特性、WIN-TC集成开发环境的使用,以及控制理论中的一阶惯性环节模拟和实现等知识点。这对于希望深入理解Windows编程和控制系统的开发者来说,是一个宝贵的学习资源。

相关推荐

filetype

#include "encoder.h" #include "main.h" #include "usart.h" #include "stdio.h" #include "tim.h" #include "math.h" #include "hall.h" #include "mymath.h" #include "gpio.h" #include "arm_math.h" #include "adc.h" #include "foc.h" float Encoder_Theta_coefficient; //编码器转换成电角度的系数值 float Encoder_Theta_m_coefficient; //编码器转换成机械角度的系数值 float We_coefficient; //编码器转电角速度的系数值 float Wm_coefficient; //编码器转机械角速度的系数值 float t; float Current_BandWidth; //电流环带宽 float CurrentLoop_Kpd; //电流环D轴比例增益 float CurrentLoop_Kid ; //电流环D轴积分增益 float CurrentLoop_Kpq ; //电流环Q轴比例增益 float CurrentLoop_Kiq; //电流环Q轴积分增益 int Speed_BandWidth ; //速度环带宽 float Ba ; //有功阻尼系数 float SpeedLoop_Kp ; //速度环比例增益 float SpeedLoop_Ki ; //速度环积分增益 float Theta_m_Set; // 目标机械角度(°) float Locate_Kp=1.0; // 位置环比例增益(P项) float Locate_Ki=0.5; // 位置环积分增益(I项) float Locate_Integral; // 积分累积量 float Locate_IntegralMax=500.0; // 积分限幅(防饱和) uint8_t UseScurve; // 启用S曲线平滑 void Foc_Init() { float temp1,temp2; Motor1.Theta_m_Set=0; Motor1.Wm_Set=0; Motor1.Id_Set=0; //设定为20k(电流采样由定时器1的PWM比较触发,频率也为20k) Motor1_Time.PWM_Fre = 168000000.0f / (TIM1_ARR * TIM1_PSC) / 2; Motor1_Time.PWM_Ts = 1 / Motor1_Time.PWM_Fre; //电流环:速度环:位置环的速度比例有多种,有16:4:1, 2:1:1, 1:1:1,都可以 Motor1_Time.Current_Loop_TimeGain = 1.0f; Motor1_Time.Speed_Loop_TimeGain = 1.0f; Motor1_Time.Locate_Loop_TimeGain = 1.0f; //计算频率设定为40k Motor1_Time.Calculate_Fre = 84000000.0f / (TIM2_ARR * TIM2_PSC ); Motor1_Time.Calculate_Ts = 1 / Motor1_Time.Calculate_Fre; //电流环设定为20k Motor1_Time.Current_Loop_Fre = Motor1_Time.Calculate_Fre / Motor1_Time.Current_Loop_TimeGain; Motor1_Time.Current_Loop_Ts = 1 / Motor1_Time.Current_Loop_Fre; //速度环设定为10k Motor1_Time.Speed_Loop_Fre = Motor1_Time.Calculate_Fre / Motor1_Time.Speed_Loop_TimeGain; Motor1_Time.Speed_Loop_Ts = 1 / Motor1_Time.Speed_Loop_Fre; //位置设定为10k Motor1_Time.Locate_Loop_Fre = Motor1_Time.Calculate_Fre / Motor1_Time.Locate_Loop_TimeGain; Motor1_Time.Locate_Loop_Ts = 1 / Motor1_Time.Locate_Loop_Fre; //编码器计数值转换为角度的系数值 Encoder_Theta_coefficient = 360 * MOTOR1_Pn /(ENCODER_NUMBER * 4); Encoder_Theta_m_coefficient = 360 /(ENCODER_NUMBER * 4); //编码器计数值转换为角速度的系数值 We_coefficient = 2* PI /(ENCODER_NUMBER * 4) / Motor1_Time.Speed_Loop_Ts; Wm_coefficient = 60.0f /(ENCODER_NUMBER * 4) / Motor1_Time.Speed_Loop_Ts; //计算电流环的PI系数 temp1=MOTOR1_Ld/MOTOR1_R; temp2=MOTOR1_Lq/MOTOR1_R; t=(temp1<temp2)?temp1:temp2; Current_BandWidth = 2*PI/t; //算出来的带宽太大了,有九千多,感觉是电机的参数给的可能有问题?不知道,反正不用这个带宽 //小了响应速度不够快,大了电流波动大 Current_BandWidth =1500; CurrentLoop_Kpd = Current_BandWidth * MOTOR1_Ld; CurrentLoop_Kid = Current_BandWidth * MOTOR1_R; CurrentLoop_Kpq = Current_BandWidth * MOTOR1_Ld; CurrentLoop_Kiq = Current_BandWidth * MOTOR1_R; //计算速度环的带宽 Speed_BandWidth = 150; Ba = (Speed_BandWidth *MOTOR1_J - MOTOR1_B ) / (1.5f * MOTOR1_Pn * MOTOR1_flux); //这个值在速度环我看别人的仿真不知道为啥给扔了,在速度环的时候不要这个 SpeedLoop_Kp = ( Speed_BandWidth * MOTOR1_J ) / (1.5f * MOTOR1_Pn * MOTOR1_flux) ; SpeedLoop_Ki = Speed_BandWidth * SpeedLoop_Kp; } //整个闭环控制计算可以满足40k的处理频率 void Foc_Control(void) { static int Number1=0,Number2=0,Number3=0; Motor1.Encoder_Value=Get_Encoder_Count(); //根据编码器计算角度 Motor1.Theta=Value_Limit(( Motor1.Encoder_Value + ENCODER_OFFSET ) * Encoder_Theta_coefficient,0.0f,360.0f); Motor1.Theta_m = Value_Limit(( Motor1.Encoder_Value + ENCODER_OFFSET ) * Encoder_Theta_m_coefficient,0.0f,360.0f); if(++Number1 >= Motor1_Time.Locate_Loop_TimeGain) { //执行位置环 Locate_Loop(); Number1= 0; } if(++Number2 >= Motor1_Time.Speed_Loop_TimeGain) { //执行速度环 Speed_Loop(); Number2= 0; } if(++Number3 >= Motor1_Time.Current_Loop_TimeGain) { //执行电流环 Current_Loop(); Number3= 0; } //对电压进行反Park变换 Park_Inverse_Transform(); //执行SVPWM并设定电机占空比 FOC_SVPWM(); //执行高频方波注入算法 // HFI_Sensorless(); } //SVPWM void FOC_SVPWM(void) { uint8_t N,A,B,C; float Vref1,Vref2,Vref3,X,Y,Z,temp1,Tfirst,Tsecond,T0,Ta,Tb,Tc,Tcm1,Tcm2,Tcm3; //计算转子所在的山区 Vref1=Motor1.Ubeta; Vref2=(SQRT_3* Motor1.Ualpha- Motor1.Ubeta)/2; Vref3=(-SQRT_3* Motor1.Ualpha- Motor1.Ubeta)/2; A=Vref1>0 ? 1 :0 ; B=Vref2>0 ? 1 :0 ; C=Vref3>0 ? 1 :0 ; N=4*C+2*B+A; temp1=SQRT_3* SVPWM_TS/ UDC; X=temp1*Vref1; Y=-temp1*Vref3; Z=-temp1*Vref2; //矢量作用时间计算 switch(N) { case 1: Tfirst= Z; Tsecond= Y; Motor1.Sector= 2; break; case 2: Tfirst= Y; Tsecond= -X; Motor1.Sector= 6; break; case 3: Tfirst= -Z; Tsecond= X; Motor1.Sector= 1; break; case 4: Tfirst= -X; Tsecond= Z; Motor1.Sector= 4; break; case 5: Tfirst= X; Tsecond= -Y; Motor1.Sector= 3; break; case 6: Tfirst= -Y; Tsecond= -Z; Motor1.Sector= 5; break; default: Tfirst= 0; Tsecond= 0; Motor1.Sector= 0; break; } //超限判断 if(( Tfirst + Tsecond )> SVPWM_TS) { Tfirst=(Tfirst/(Tfirst+Tsecond))/ SVPWM_TS; Tsecond=(Tsecond/(Tfirst+Tsecond))/ SVPWM_TS; } T0= (SVPWM_TS- Tfirst- Tsecond)/2; Ta=T0/2; Tb=Ta+Tfirst/2; Tc=Tb+Tsecond/2; //每相桥臂切换时间计算 switch(N) { case 1: Tcm1=Tb; Tcm2=Ta; Tcm3=Tc; break; case 2: Tcm1=Ta; Tcm2=Tc; Tcm3=Tb; break; case 3: Tcm1=Ta; Tcm2=Tb; Tcm3=Tc; break; case 4: Tcm1=Tc; Tcm2=Tb; Tcm3=Ta; break; case 5: Tcm1=Tc; Tcm2=Ta; Tcm3=Tb; break; case 6: Tcm1=Tb; Tcm2=Tc; Tcm3=Ta; break; default: break; } Motor1.Tcm1=Tcm1; Motor1.Tcm2=Tcm2; Motor1.Tcm3=Tcm3; //设置定时器1的PWM占空比 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,TIM1_ARR*(1-2*Tcm1/ SVPWM_TS)); __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,TIM1_ARR*(1-2*Tcm2/ SVPWM_TS)); __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,TIM1_ARR*(1-2*Tcm3/ SVPWM_TS)); } void ADC_Transform(void) { //顺便软件滤波一下 //按照无刷驱动板的原理图上的公式算的,0.02是电阻值,电流转成的电压 除以电阻就是电流 // Motor1.Ibeta=((HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1) * 3.3f /4095.0f) -1.24f)/8.0f/0.02f; 单位A Motor1.Ia =IRFilter1(HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1)) * 0.005f -7.75f; Motor1.Ib =IRFilter2(HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_2)) * 0.005f -7.75f; Motor1.Ic =IRFilter3(HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_3)) * 0.005f -7.75f; } //位置环 void Locate_Loop(void) { if (Motor1.Theta_m_Set == 0) return; // 跳过未设目标值 // 位置误差(处理360°边界) float error = Motor1.Theta_m_Set - Motor1.Theta_m; if (error > 180) error -= 360; else if (error < -180) error += 360; // PI控制器(输出为速度指令) float output = Locate_Kp * error + Locate_Integral; // 抗积分饱和:小误差时启用积分 if (fabs(error) < 5.0f) { Locate_Integral += Locate_Ki * error * Motor1_Time.Locate_Loop_Ts; Locate_Integral = Value_SetMaxMin(Locate_Integral, - Locate_IntegralMax, Locate_IntegralMax); } // 输出限幅(速度指令) Motor1.Wm_Set = Value_SetMaxMin(output, -1000, 1000); // 限制±1000 RPM } //速度环 void Speed_Loop(void) { static float temp; static int Encoder_Last; float Encoder_W_temp; if(Encoder_Z_Flag==1) { Encoder_W_temp = KalmanFilter(Motor1.Encoder_Value - Encoder_Last + Encoder_temp); Encoder_Z_Flag=0; } else Encoder_W_temp = KalmanFilter(Motor1.Encoder_Value - Encoder_Last); //根据编码器计算角速度 速度范围波动会比较大,因为采样频率太高了,编码器的分辨率又不够高,所以这是很正常的。降低采样频率(即减小TIM2的时钟频率)可以减小波动 Motor1.We = Encoder_W_temp * We_coefficient; //单位 rad/s(电角速度) Motor1.Wm = Encoder_W_temp * Wm_coefficient; //单位 RPM(角速度) Encoder_Last=Motor1.Encoder_Value; Motor1.Iq_Set = SpeedLoop_Kp * (Motor1.Wm_Set - Motor1.Wm) + temp; temp = Value_SetMaxMin(temp +SpeedLoop_Ki * (Motor1.Wm_Set - Motor1.Wm) * Motor1_Time.Speed_Loop_Ts,-10.0f,10.0f); //给个限值防止他一直往上加,一启动电机速度飞飚,这个值是慢慢试的,大概速度到3000RPM时,这个值为10.多 } //电流环 void Current_Loop(void) { static float temp,temp2; //对三相电流进行采样,三相电流相加不为0,是因为硬件上有误差(野火客服说的,可恶!) 电流采样频率和电流频率一样都为20k ADC_Transform(); //对电流进行Clark变换,再Park变换 Motor1.Ialpha = Motor1.Ia; Motor1.Ibeta = (Motor1.Ia + 2*Motor1.Ib)/SQRT_3; Motor1.Id = Motor1.Ialpha* qfcosd(Motor1.Theta)+ Motor1.Ibeta* qfsind(Motor1.Theta); Motor1.Iq = -Motor1.Ialpha* qfsind(Motor1.Theta)+ Motor1.Ibeta* qfcosd(Motor1.Theta); //PI环节 //这个电流环的积分项我没整明白,加上积分的话,积分项会直接冲到最大,且一直为最大,然后就电机转动也没有更好,感觉就是反作用,先不整了,把它干掉,后面再研究 Motor1.Ud = CurrentLoop_Kpd *(Motor1.Id_Set - Motor1.Id) + temp - Motor1.We * MOTOR1_Lq * Motor1.Iq; // temp = Value_SetMaxMin( temp+ CurrentLoop_Kid * (Motor1.Id_Set - Motor1.Id) * Motor1.Calculate_Ts, -0.1f, 0.1f); Motor1.Uq = CurrentLoop_Kpq *(Motor1.Iq_Set - Motor1.Iq) + temp2 + Motor1.We * (MOTOR1_Ld * Motor1.Id + MOTOR1_flux); // temp2 = Value_SetMaxMin( temp2+ CurrentLoop_Kiq * (Motor1.Iq_Set - Motor1.Iq) * Motor1.Calculate_Ts, -0.1f, 0.1f); //合成电压最大值为SQRT_3 * UDC / 3 = 13.85 , Ud 最大值设为3 是为了高频方波注入算法, 这些限值都是试出来的,我也不会算理论值;这样限值转速最大能到2600RPM左右,够了 Motor1.Ud = Value_SetMaxMin(Motor1.Ud,-3.0f,3.0f); Motor1.Uq = Value_SetMaxMin(Motor1.Uq,-12.0f,12.0f); // Motor1.Ud = 0; // Motor1.Uq = 2; } 我需要控制电机的位置,请检查上述驱动代码,

filetype

在qt中运行以下程序提示报错 #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/filters/voxel_grid.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/common/time.h> //计时 #include <pcl/filters/passthrough.h> #include <pcl/filters/statistical_outlier_removal.h> #include <pcl/ModelCoefficients.h> // 模型系数 #include <pcl/sample_consensus/model_types.h> // 分割模型类型 #include <pcl/segmentation/sac_segmentation.h> // RANSAC #include <pcl/filters/model_outlier_removal.h> // 模型滤波器 #include <pcl/visualization/cloud_viewer.h> // 可视化 #include <pcl/visualization/pcl_visualizer.h> #include <pcl/sample_consensus/sac_model_cylinder.h> // 圆柱 #include <pcl/filters/extract_indices.h> #include <pcl/common/pca.h> #include <pcl/sample_consensus/ransac.h> // RANSAC #include <pcl/search/kdtree.h> // KDtree搜索 #include <pcl/features/normal_3d.h> // 法线估计 #include <pcl/features/normal_3d_omp.h> #include <pcl/segmentation/region_growing.h> //区域生长 #include <pcl/common/angles.h> #include <pcl/search/search.h> #include <pcl/filters/project_inliers.h> #include <pcl/filters/crop_box.h> #include <pcl/features/moment_of_inertia_estimation.h> #include <pcl/sample_consensus/sac_model_circle3d.h> // 拟合3D圆 #include <pcl/visualization/pcl_visualizer.h> #include <pcl/common/common.h> #include<pcl/octree/octree.h> #include <opencv2/opencv.hpp> #include <opencv2/core.hpp> #include <opencv2/core/core_c.h> #include <opencv2/imgproc.hpp> #include <opencv2/calib3d.hpp> #include <opencv2/core/eigen.hpp> #include "EuclideanCluster.h" #include <pcl/console/time.h> // 控制台计算时间 #include <QApplication> #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; using pcl::visualization::PointCloudColorHandlerGenericField; using pcl::visualization::PointCloudColorHandlerCustom; typedef struct Point3D { Mat_<double> mat1 ; float angle; }; pcl::PointCloud<pcl::PointXYZ>::Ptr Voxel_Grid_Filtering(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud,int numb