吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1050|回复: 1
收起左侧

[学习记录] 手撕算法

  [复制链接]
zzxxccqq 发表于 2023-6-28 16:54
本帖最后由 zzxxccqq 于 2023-6-28 17:01 编辑

自己学的一点框架,关于电机转子位置确定的一篇示例:(本示例是没有考虑运行在一些低算力应用场合的,若有算法大佬,可以根据这个思路重写算法,让它兼容性更好)
    代码部分:(仅供参考,欢迎各位指教)

//假设电机的数学模型是永磁同步电机的dq轴方程
//假设输出信号是定子d轴电流i_d
//假设状态变量是转子位置theta_e和转子速度omega_e
//假设已知的参数是定子电阻R_s,d轴电感L_d,q轴电感L_q,永磁体磁链psi_f
//假设输入信号是定子d轴电压u_d和定子q轴电压u_q
#include <math.h> //引入数学库
#define PI 3.1415926 //定义圆周率
//定义电机参数
double R_s = 0.5; //定子电阻,单位欧姆
double L_d = 0.01; //d轴电感,单位亨利
double L_q = 0.01; //q轴电感,单位亨利
double psi_f = 0.1; //永磁体磁链,单位韦伯
//定义滑膜面函数
double s(double i_d, double i_q, double omega_e)
{
        return i_d + omega_e * L_q * i_q + omega_e * psi_f; //返回滑膜面函数的值
}
//定义滑膜面函数的导数
double ds(double u_d, double u_q, double i_d, double i_q, double omega_e)
{
        return (u_d - R_s * i_d - L_d * omega_e * i_q) / L_d + omega_e * (u_q - R_s * i_q + L_q * omega_e * i_d) / L_q; //返回滑膜面函数的导数的值
}
//定义符号函数
double sgn(double x)
{
        if (x > 0)
                return 1.0; //如果x大于0,返回1
        else if (x < 0)
                return -1.0; //如果x小于0,返回-1
        else
                return 0.0; //如果x等于0,返回0
}
//定义滑膜控制律的函数
double u_d(double i_d, double i_q, double omega_e, double k, double lambda)
{
        return R_s * i_d + L_d * ds(i_d, i_q, omega_e) + k * sgn(s(i_d, i_q, omega_e)) / lambda; //返回滑膜控制律的值
}
//定义更新输出信号和状态变量的函数
void update(double* i_d, double* i_q, double* theta_e, double* omega_e, double u_d, double u_q, double dt)
{
//使用欧拉法近似更新输出信号和状态变量
        *i_d = *i_d + ds(u_d, u_q, *i_d, *i_q, *omega_e) * dt; //更新定子d轴电流
        *i_q = *i_q + ds(u_q, u_d, *i_q, *i_d, -*omega_e) * dt; //更新定子q轴电流
        *theta_e = fmod(*theta_e + *omega_e * dt, 2.0 * PI); //更新转子位置,并取余数保证在[0,2PI]范围内
        *omega_e = (*omega_e + psi_f / (L_q - L_d) / (*i_q + sgn(s(*i_d, *i_q, *omega_e)) / lambda)) \
        / (1.0 + psi_f / (L_q - L_d) / (*i_q + sgn(s(*i_d, *i_q, *omega_e)) / lambda) /  \
        (*i_q + sgn(s(*i_d, *i_q, *omega_e)) / lambda)); //更新转子速度,使用牛顿迭代法求解非线性方程
}

//主函数
int main() {
        //定义输入信号
        double u_q = 10.0; //定子q轴电压,单位伏特
        //定义输出信号和状态变量的初始值
        double i_d = 0.0; //定子d轴电流,单位安培
        double i_q = 0.0; //定子q轴电流,单位安培
        double theta_e = 0.0; //转子位置,单位弧度
        double omega_e = PI / 2.0; //转子速度,单位弧度/秒
        //定义滑膜控制律的参数
        double k = 10.0; //正常数,用来调节收敛速度和抗干扰能力
        double lambda = 1.0; //正常数,用来调节收敛速度和抗干扰能力
        //定义更新的时间间隔
        double dt = 0.001; //时间间隔,单位秒
        //定义循环的次数
        int n = 1000; //循环的次数
        //循环更新输出信号和状态变量
        for (int i = 0; i < n; i++)
                {
                        //计算滑膜控制律的值
                        double u_d_value = u_d(i_d, i_q, omega_e, k, lambda); //滑膜控制律的值

                        //打印滑膜控制律的值
                        printf("u_d = %f V\n", u_d_value);
                        //更新输出信号和状态变量
                        update(&i_d, &i_q, &theta_e, &omega_e, u_d_value, u_q, dt);

                        //打印输出信号和状态变量的值
                        printf("i_d = %f A\n", i_d);
                        printf("i_q = %f A\n", i_q);
                        printf("theta_e = %f rad\n", theta_e);
                        printf("omega_e = %f rad/s\n", omega_e);
                }
        return 0;
}
/*
以上代码逻辑:

首先,我引入了数学库,定义了圆周率和电机参数,这些都是为了后面的计算做准备。

然后,我定义了滑膜面函数和其导数的函数,这些函数根据电机的数学模型和滑膜观测的原理,\
计算出滑膜面函数和其导数的值。

滑膜面函数表示输出信号和状态变量之间的关系,其导数表示输出信号和输入信号之间的关系。

接着,我定义了符号函数,这个函数用来判断系统状态变量与滑膜面之间的相对位置。\
符号函数是滑膜控制律的一部分,用来产生切换控制作用。

然后,我定义了滑膜控制律的函数,这个函数根据滑膜控制的原理,计算出滑膜控制律的值。\
滑膜控制律是一个反馈控制律,用来使得输出信号能够在有限时间内收敛到滑膜面上,并在滑膜面上保持稳定。

接下来,我定义了更新输出信号和状态变量的函数,这个函数根据电机的数学模型和欧拉法近似,更新输出信号和状态变量的值。\
更新的过程中,需要用到牛顿迭代法求解转子速度的非线性方程。

最后,我定义了输入信号、输出信号和状态变量的初始值,并定义了滑膜控制律的参数、更新的时间间隔和循环的次数。\
然后我用一个for循环来更新输出信号和状态变量,并打印出每次更新后的值,以便观察。
*/

下面是一个简单的结构框图

u_α, u_β  ——> Clark变换 ——> u_d, u_q

i_α, i_β  ——> Clark变换 ——> i_d, i_q
u_d, u_q, i_d, i_q  ——> 滑膜观测器 ——> θ_r, ω_r
θ_r, ω_r  ——> Park逆变换 ——> θ_αβ, ω_αβ
θ_αβ, ω_αβ  ——> 矢量控制器 ——> u_d*, u_q*
u_d*, u_q*  ——> Park逆变换 ——> u_α*, u_β*
u_α*, u_β*  ——> 逆变器 ——> u_a*, u_b*, u_c*
其中,u表示电压,i表示电流,θ表示角度,ω表示角速度,*表示期望值,αβ表示静止坐标系,dq表示同步旋转坐标系,r表示转子。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| zzxxccqq 发表于 2023-6-28 17:08
其中double sgn(double x)函数被我简写了,需要的在留言区联系我
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 23:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表