1 个不稳定版本

0.1.0 2024年4月9日

#76 in 无标准库

Apache-2.0

77KB
1.5K SLoC

continuous integration

ac-power

用于交流功率信号嵌入式处理的参考系、变换和三角函数。

参考系

库的核心是表示不同参考系中三相交流向量的数据结构。

该库支持6种不同的参考系。其中包括3个平衡参考系

  1. Polar - 极坐标表示(幅度和角度)
  2. AlphaBeta - 正交(alpha和beta)参考系表示
  3. Dq - 两个轴(d和q)旋转参考系表示

还有三个不平衡表示的参考系(支持零序分量)

  1. Abc - 瞬时信号
  2. AlphaBeta0 - 带零的正交(alpha和beta)参考系表示
  3. Dq0 - 带零的两个轴(d和q)旋转参考系表示

在参考系之间转换会调用功率理论变换。

use ac_power::{Abc, AlphaBeta0};

// create a vector in Abc reference frame
let abc = Abc {a: 100.0, b: 200.0, c: 50.0};

// convert to alpha-beta
let alpha_beta_zero = AlphaBeta0::from(abc);
此crate使用变换的功率变体而不是功率不变版本,这在行业工具和DSP中似乎更为常见。集成的功率计算考虑了这一点,并实现了适当的缩放。
由于浮点数舍入误差,这些变换不是完全可逆的。例如,如果您执行以下转换 Abc-->AlphaBeta-->Abc,结果Abc值不会与原始值完全相等。

三角函数

该库还包括一个trig模块,在转换静态和旋转参考系之间很有用。

use ac_power::{Abc, Dq0};
use ac_power::trig::{Theta, cos_sin};

// create a vector in Abc reference frame
let abc = Abc {a: 100.0, b: 200.0, c: 50.0};

// convert to Dq0
let (cos, sin) = cos_sin(Theta::from_degrees(90.0));
let dq0 = abc.to_dq0(cos, sin);

trig模块中还有其他函数,用于旋转Sin/Cos对或使用切比雪夫方法生成Sin(Nx),Cos(Nx)对。

Newtypes

从上面的例子中,我们可以看到这个crate中定义了一些newtypes。具体来说,在trig模块中有三个定义

  1. Theta(i32) - 介于-π和π弧度之间的角度
  2. Sin(f32) - 角度的正弦值
  3. Cos(f32) - 角度的余弦值

此外,此crate中还定义了4个额外的newtypes

  1. Voltage(f32) - 电压
  2. Current(f32) - 电流
  3. Power(f32) - 电力
  4. Impedance(f32) - 电阻

在类型不同的乘法过程中会自动发生有意义的类型转换。

use ac_power::{Voltage, Current, Power, Impedance};

let z = Impedance::from(10.0);
let i = Current::from(1.5);
let v: Voltage = i * z;
let p: Power = v * i;

参考系使用泛型实现,因此它们可以使用如上示例中的常规 f32 或任何实现所需数值特征的任何数据类型。上面定义的所有4个额外的 新类型 都可以。

use ac_power::{Abc, Voltage};

// define a voltage vector in Abc reference frame
let v: Abc::<Voltage> = Abc {a: 1.0.into(), b: 2.0.into(), c: 3.0.into()};

功率计算

当您从 电压电流 类型创建AC参考系向量时,它们可以相互乘以返回一个 Pq 结构体。这是一个基本用例,用于从三相电压和电流数据计算有功和无功功率。


use ac_power::{Abc, Dq0, AlphaBeta, Polar, Voltage, Current};
use ac_power::trig::{Theta, cos_sin};
use approx::assert_abs_diff_eq;

// set the magnitude of the voltage and current
let v_mag = Voltage::from(340.0);
let i_mag = Current::from(8.2);

// create voltage and current vectors in the Abc reference frame
let v = Abc::from_polar(v_mag, Theta::from_degrees(0.0));
let i = Abc::from_polar(i_mag, Theta::from_degrees(45.0));

// calculate P and Q
let pq = v * i;

// calculate the power factor
let pf = pq.power_factor();

// check the power factor
assert_abs_diff_eq!(f32::from(pf), 0.707, epsilon = 0.0001);

// convert v and i to alpha_beta
let v_alpha_beta = AlphaBeta::from(v);
let i_alpha_beta = AlphaBeta::from(i);

// verify the power factor is still correct
let pf = (v_alpha_beta * i_alpha_beta).power_factor();
assert_abs_diff_eq!(f32::from(pf), 0.707, epsilon = 0.0001);

高级用例

许多实现高级电网控制或电网形成控制的逆变器控制系统也依赖于这个crate中实现的转换。使用这个crate不仅可以使应用程序代码更易于阅读,还可以通过这个crate的广泛优化和验证提高性能并消除错误。以下是一些示例。

电网同步锁相环(PLL)

以下是简单三相锁相环实现的一个示例,这是逆变器控制和高级功率计中常见的DSP模块,用于说明如何使用crate来实现此类应用。

use ac_power::{Abc, AlphaBeta, Dq};
use ac_power::trig::{cos_sin, Cos, Sin, Theta};
use ac_power::Voltage;
use idsp::iir::{Action, Biquad, Pid};

pub struct Pll {
    fref: f32,

    // loop filter
    filter: Biquad<f32>,
    filter_state: [f32; 2],

    // frequency/angle
    pub theta: Theta,
    pub sin: Sin,
    pub cos: Cos,
    pub f: f32,

    // rotating reference frames
    pub dq_pos: Dq<Voltage>,
    pub dq_neg: Dq<Voltage>,

    // theta integration constant
    k_theta: f32,
}

impl Pll {
    pub fn new(fref: f32, kp: f32, ki: f32, max_integral: f32, ts: f32) -> Self {
        // calculate the theta integration constant
        let k_theta = ts * (u32::MAX as f32);

        // create the Pi frequency lock filter
        let mut filter: Biquad<f32> = Pid::default()
            .period(ts)
            .gain(Action::Kp, kp)
            .gain(Action::Ki, ki)
            .build()
            .unwrap()
            .into();
        filter.set_max(max_integral);
        filter.set_min(-max_integral);

        Self {
            fref,
            filter,
            filter_state: [0.0, 0.0],
            theta: 0.into(),
            sin: 0.0.into(),
            cos: 1.0.into(),
            f: fref,
            dq_pos: Dq::zero(),
            dq_neg: Dq::zero(),
            k_theta,
        }
    }

    pub fn update(&mut self, abc: Abc<Voltage>) {
        // clarke transform
        let alpha_beta = AlphaBeta::from(abc);

        // park transforms
        self.dq_pos = alpha_beta.to_dq(self.cos, self.sin);
        self.dq_neg = alpha_beta.to_dq(self.cos, -self.sin);

        // PI loop filter
        self.f = self.fref + self.filter.update(&mut self.filter_state, self.dq_pos.q.into());

        // update the phase info
        self.theta += (self.f * self.k_theta) as i32;
        (self.cos, self.sin) = cos_sin(self.theta);
    }
}

三相波形发生器

以下是三相波形发生器的一个示例,它支持不平衡表示以及谐波。

use ac_power::number::Num;
use ac_power::trig::{chebyshev, cos_sin, Cos, Sin, Theta};
use ac_power::{Abc, Dq};

pub struct Waveform<T, const N: usize> {
    pub positive: [Dq<T>; N],
    pub negative: [Dq<T>; N],
    pub zero: Dq<T>,
}

impl<T: Num, const N: usize> Waveform<T, N> {
    pub fn new() -> Self {
        Self {
            positive: [Dq::zero(); N],
            negative: [Dq::zero(); N],
            zero: Dq::zero(),
        }
    }

    pub fn calculate(&self, theta: Theta) -> Abc<T> {
        let (cos, sin) = cos_sin(theta);

        let mut abc = Abc::zero() + self.zero.d * sin + self.zero.q * cos;

        // add the harmonics
        let (mut cosn1, mut sinn1) = (Cos::from(1.0), Sin::from(0.0));
        let (mut cosn, mut sinn) = (cos, sin);
        for (pos, neg) in self.positive.iter().zip(self.negative.iter()) {
            abc += pos.to_abc(cosn, sinn);
            abc += neg.to_abc(cosn, -sinn);

            // use chebychev function to calculate cos, sin of next harmonic
            let cosn2 = cosn1;
            let sinn2 = sinn1;
            cosn1 = cosn;
            sinn1 = sinn;
            (cosn, sinn) = chebyshev(cos, cosn1, sinn1, cosn2, sinn2);
        }

        abc
    }
}

依赖关系

~1.2–1.9MB
~40K SLoC