Skip to content

Commit 8202d5c

Browse files
committed
add: 添加了文件
0 parents  commit 8202d5c

File tree

8 files changed

+1022
-0
lines changed

8 files changed

+1022
-0
lines changed

.gitignore

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
.vscode
3+
.pyenv
4+
5+
target
6+
build
7+
target
8+
Core
9+
Drivers
10+
FATFS
11+
Middlewares
12+
USB_Device
13+
HTML
14+
15+
!*.c
16+
!*.h
17+
!*.cpp
18+
!*.hpp
19+
20+
!Makefile
21+
22+
!*.a
23+
24+
!*.s
25+
!*.ld
26+
27+
!Doxyfile

COPYING

+504
Large diffs are not rendered by default.

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
SOGI-PLL
2+
========
3+
4+
Phase-Locked Loop Based Second Order Generalized Integrator for power electric application.
5+
6+

inc/mc_config.h

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: LGPL-2.1
2+
3+
/**
4+
* @file mc_config.h
5+
* @brief 控制系统配置
6+
* @author 向阳 ([email protected])
7+
* @date 2022-07-27
8+
*
9+
* @copyright Copyright (C) 向阳 2022
10+
*/
11+
#if !defined(__INCLUDE_CONTROL_MC_CONFIG_H__)
12+
#define __INCLUDE_CONTROL_MC_CONFIG_H__
13+
#include <float.h>
14+
namespace control
15+
{
16+
//! 运算的值类型
17+
using value_t = float;
18+
19+
//! 控制周期
20+
constexpr value_t T = 1 / 12800.0f;
21+
22+
//! 常量值表
23+
template<typename T>
24+
struct constant_value;
25+
26+
27+
template<>
28+
struct constant_value<value_t>
29+
{
30+
//! 零
31+
static constexpr value_t ZERO = 0;
32+
33+
//! 圆周率
34+
static constexpr value_t PI = 3.14159265358979323f;
35+
36+
//! 1/2 * 圆周率
37+
static constexpr value_t HALF_PI = PI / 2;
38+
39+
//! 2 * 圆周率
40+
static constexpr value_t TAU = PI * 2;
41+
42+
//! 最大值
43+
static constexpr value_t MAX = FLT_MAX;
44+
45+
//! 最小
46+
static constexpr value_t MIN = FLT_MIN;
47+
};
48+
49+
}
50+
#endif // __INCLUDE_CONTROL_MC_SPLL_H__

inc/mc_pid.h

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// SPDX-License-Identifier: LGPL-2.1
2+
3+
/**
4+
* @file ma_pid.h
5+
* @brief 数字PID控制器
6+
* @author 向阳 ([email protected])
7+
* @date 2022-07-16
8+
*
9+
* @copyright Copyright (C) 向阳 2022
10+
*/
11+
#if !defined(__INCLUDE_CONTROL_MC_PID_H__)
12+
#define __INCLUDE_CONTROL_MC_PID_H__
13+
#include "mc_config.h"
14+
namespace control
15+
{
16+
/**
17+
* @brief 带退饱和反馈和积分限幅的PID控制器(float32)
18+
*
19+
*/
20+
class PID final
21+
{
22+
public:
23+
/**
24+
* @brief 控制器参数
25+
*
26+
*/
27+
struct Factors
28+
{
29+
//! 比例系数
30+
value_t kp;
31+
32+
//! 积分系数
33+
value_t ki;
34+
35+
//! 微分系数
36+
value_t kd;
37+
38+
//! 微分增益
39+
value_t kg;
40+
41+
//! 饱和系数
42+
value_t kc;
43+
44+
//! 积分器限幅(min)
45+
value_t i_min;
46+
47+
//! 积分器限幅(max)
48+
value_t i_max;
49+
};
50+
51+
PID() = default;
52+
~PID() = default;
53+
54+
PID(const PID &) = delete;
55+
PID &operator=(const PID &) = delete;
56+
57+
PID(PID &&) = delete;
58+
PID &operator=(PID &&) = delete;
59+
60+
//! @get
61+
//! @set
62+
//! 控制器参数
63+
Factors param = {0};
64+
65+
/**
66+
* @brief 重置调节器状态
67+
*
68+
*/
69+
void reset() noexcept;
70+
71+
/**
72+
* @brief 数字P
73+
*
74+
* @param [in] e: 输入, error
75+
*
76+
* @return value_t: 输出
77+
*
78+
*/
79+
value_t p_transfer(value_t e) noexcept;
80+
81+
/**
82+
* @brief 数字PI
83+
*
84+
* @param [in] e: 输入, error
85+
*
86+
* @return value_t: 输出
87+
*
88+
*/
89+
value_t pi_transfer(value_t e) noexcept;
90+
91+
/**
92+
* @brief 数字PD
93+
*
94+
* @param [in] e: 输入, error
95+
*
96+
* @return value_t: 输出
97+
*
98+
*/
99+
value_t pd_transfer(value_t e) noexcept;
100+
101+
/**
102+
* @brief 数字PID
103+
*
104+
* @param [in] e: 输入, error
105+
*
106+
* @return value_t: 输出
107+
*
108+
*/
109+
value_t pid_transfer(value_t e) noexcept;
110+
111+
private:
112+
//! 饱和误差
113+
value_t sat_err = 0;
114+
115+
//! 积分值
116+
value_t i_sum = 0;
117+
};
118+
}
119+
#endif // __INCLUDE_CONTROL_MC_PID_H__

inc/mc_spll.h

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// SPDX-License-Identifier: LGPL-2.1
2+
3+
/**
4+
* @file mc_spll.h
5+
* @brief 数字锁相环
6+
* @author 向阳 ([email protected])
7+
* @date 2022-07-27
8+
*
9+
* @copyright Copyright (C) 向阳 2022
10+
*/
11+
#if !defined(__INCLUDE_CONTROL_MC_SPLL_H__)
12+
#define __INCLUDE_CONTROL_MC_SPLL_H__
13+
#include <tuple>
14+
#include "mc_pid.h"
15+
#include <stddef.h>
16+
#include <stdint.h>
17+
#include "mc_config.h"
18+
namespace control
19+
{
20+
class SPLL final
21+
{
22+
public:
23+
//! SPLL工作周期
24+
static constexpr value_t Ti = T;
25+
26+
//! SPLL期望频率(Hz)
27+
static constexpr value_t TARGET_FREQ = 50;
28+
29+
//! 计算1个周期有多少个点
30+
static constexpr size_t N_SAMPLE = static_cast<size_t>((1 / Ti) / TARGET_FREQ);
31+
32+
SPLL();
33+
~SPLL() = default;
34+
35+
SPLL(SPLL&&) = delete;
36+
SPLL& operator=(SPLL&&) = delete;
37+
38+
SPLL(const SPLL &) = delete;
39+
SPLL& operator=(const SPLL &) = delete;
40+
41+
/**
42+
* @brief 复位
43+
*
44+
*/
45+
void reset();
46+
47+
/**
48+
* @brief 进行一次计算
49+
*
50+
* @note 按照Ti等间隔调用本方法, 实现PLL
51+
*
52+
*/
53+
void transfer_1phase(value_t val);
54+
55+
/**
56+
* @brief 判断PLL是否已经锁定
57+
*
58+
* @param [in] th: 比较阈值
59+
*
60+
*/
61+
bool is_lock(value_t th = 1e-2f) const;
62+
63+
/**
64+
* @brief 取得当前信号的频率
65+
*
66+
* @return value_t: 频率
67+
*
68+
*/
69+
inline value_t freq() const noexcept
70+
{
71+
return omega / constant_value<value_t>::TAU;
72+
}
73+
74+
/**
75+
* @brief 取得当前信号的相位
76+
*
77+
* @return value_t: 相位
78+
*
79+
*/
80+
inline value_t phase() const noexcept
81+
{
82+
return cur_phase;
83+
}
84+
private:
85+
//! PI
86+
PID pid;
87+
88+
//! 是否启动环路
89+
bool launch_loop;
90+
91+
//! 采样点索引, 最大到N_SAMPLE / 4
92+
uint16_t sample_index;
93+
94+
//! 角速度
95+
value_t omega;
96+
97+
//! 角度积分值, 作为相位wt
98+
value_t cur_phase;
99+
100+
//! 自动归零: 最大值和最小值
101+
value_t auto_offset_min;
102+
value_t auto_offset_max;
103+
104+
//! SOGI的积分值
105+
value_t sogi_s1;
106+
value_t sogi_s2;
107+
108+
109+
//! 上次的环路error
110+
value_t last_error;
111+
112+
/**
113+
* @brief 按照历史最大值和最小值进行归中
114+
* @param [in] inp: 输入
115+
*
116+
* @return value_t: 归中后的值
117+
*
118+
*/
119+
value_t auto_offset(value_t inp);
120+
};
121+
}
122+
#endif // __INCLUDE_CONTROL_MC_SPLL_H__

src/mc_pid.cpp

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: LGPL-2.1
2+
3+
/**
4+
* @file mc_pid.cpp
5+
* @brief 数字PID控制器
6+
* @author 向阳 ([email protected])
7+
* @date 2022-07-16
8+
*
9+
* @copyright Copyright (C) 向阳 2022
10+
*/
11+
#include "mc_pid.h"
12+
13+
using namespace control;
14+
15+
void PID::reset() noexcept
16+
{
17+
i_sum = 0;
18+
sat_err = 0;
19+
}
20+
21+
value_t PID::p_transfer(value_t e) noexcept
22+
{
23+
value_t m = param.kp * e;
24+
value_t out
25+
= m > param.i_max ? param.i_max
26+
: m < param.i_min ? param.i_min
27+
: m;
28+
return out;
29+
}
30+
31+
value_t PID::pi_transfer(value_t e) noexcept
32+
{
33+
value_t sat = param.kp * e + i_sum;
34+
// PI输出
35+
// U(s) = kp * E(s) + ki * E(s) / s
36+
value_t out
37+
= sat > param.i_max ? param.i_max
38+
: sat < param.i_min ? param.i_min
39+
: sat;
40+
// 饱和误差
41+
value_t sat_err = out - sat;
42+
// 累积积分, 加上饱和误差
43+
i_sum += param.ki * e + param.kc * sat_err;
44+
// 积分限幅, clamp
45+
if (i_sum > param.i_max)
46+
{
47+
i_sum = param.i_max;
48+
}
49+
else if (i_sum < param.i_min)
50+
{
51+
i_sum = param.i_min;
52+
}
53+
//
54+
return out;
55+
}
56+
57+
value_t PID::pd_transfer(value_t e) noexcept
58+
{
59+
return 0;
60+
}
61+
62+
value_t PID::pid_transfer(value_t e) noexcept
63+
{
64+
return 0;
65+
}

0 commit comments

Comments
 (0)