You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F446RE实现50Hz正弦波90度相移的替代方案咨询

针对STM32F446RE生成90度相移正弦波的可行方案

针对你在STM32F446RE项目中,实时采集50Hz正弦波并生成正交beta信号的需求,以下是几种替代希尔伯特滤波和LUT的方案:

1. 二阶广义积分器(SOGI)

SOGI是电力电子领域常用的正交信号生成方法,能实时跟踪输入正弦波的频率和幅值,输出严格正交的信号,适合50Hz这类固定或小幅波动频率的场景,计算量小,STM32上运行无压力。

实现代码示例

#include <math.h>

typedef struct {
    float omega;       // 谐振角频率,50Hz对应2*PI*50=314.16rad/s
    float k;           // 阻尼系数,通常取1.414(sqrt(2))
    float v_alpha;     // 输入信号
    float v_beta;      // 正交输出信号
    float x_alpha;     // 内部状态变量
    float x_beta;      // 内部状态变量
} SOGI_HandleTypeDef;

void SOGI_Init(SOGI_HandleTypeDef *hsogi) {
    hsogi->omega = 2 * M_PI * 50.0f;
    hsogi->k = sqrt(2.0f);
    hsogi->x_alpha = 0.0f;
    hsogi->x_beta = 0.0f;
    hsogi->v_beta = 0.0f;
}

void SOGI_Update(SOGI_HandleTypeDef *hsogi, float input, float Ts) {
    // Ts为ADC采样周期,比如采样率1kHz的话Ts=0.001s
    hsogi->v_alpha = input;
    
    // 更新状态方程
    hsogi->x_alpha = hsogi->x_alpha + Ts * hsogi->omega * (hsogi->v_alpha - hsogi->x_alpha - hsogi->k * hsogi->x_beta);
    hsogi->x_beta = hsogi->x_beta + Ts * hsogi->omega * (hsogi->x_alpha - hsogi->x_beta);
    
    // 正交输出beta信号
    hsogi->v_beta = hsogi->x_alpha - hsogi->k * hsogi->x_beta;
}

使用说明

  • 初始化时设置omega为50Hz对应的角频率,k取√2保证动态响应和稳态精度平衡
  • 每次ADC采样完成后,调用SOGI_Update,传入采样值和采样周期Ts,即可从hsogi->v_beta得到正交信号
  • 该方法对50Hz信号的相移精度高,幅值几乎无失真,且能适应小幅频率波动

2. 二阶全通滤波器

设计一个针对50Hz的二阶全通滤波器,可实现90度相移,同时保持幅值不变,阶数低,计算量小,失真远低于高阶希尔伯特滤波。

离散化实现(双线性变换)

假设采样率为$F_s$,离散化后的差分方程实现如下:

#include <math.h>

typedef struct {
    float b0, b1, b2;
    float a1, a2;
    float x_prev1, x_prev2;
    float y_prev1, y_prev2;
} AllPassFilter_HandleTypeDef;

void AllPassFilter_Init(AllPassFilter_HandleTypeDef *hfilter, float Fs) {
    float omega0 = 2 * M_PI * 50.0f;
    float T = 1.0f / Fs;
    float omega0T = omega0 * T;
    float denom = 4.0f + 2.0f * omega0T + omega0T * omega0T;
    
    hfilter->b0 = 4.0f - 2.0f * omega0T + omega0T * omega0T;
    hfilter->b1 = 2.0f * omega0T * omega0T - 8.0f;
    hfilter->b2 = 4.0f - 2.0f * omega0T + omega0T * omega0T;
    hfilter->a1 = 2.0f * omega0T * omega0T - 8.0f;
    hfilter->a2 = 4.0f - 2.0f * omega0T + omega0T * omega0T;
    
    // 归一化系数
    hfilter->b0 /= denom;
    hfilter->b1 /= denom;
    hfilter->b2 /= denom;
    hfilter->a1 /= denom;
    hfilter->a2 /= denom;
    
    // 初始化历史值
    hfilter->x_prev1 = 0.0f;
    hfilter->x_prev2 = 0.0f;
    hfilter->y_prev1 = 0.0f;
    hfilter->y_prev2 = 0.0f;
}

float AllPassFilter_Process(AllPassFilter_HandleTypeDef *hfilter, float x) {
    float y = hfilter->b0 * x + hfilter->b1 * hfilter->x_prev1 + hfilter->b2 * hfilter->x_prev2 
              - hfilter->a1 * hfilter->y_prev1 - hfilter->a2 * hfilter->y_prev2;
    
    // 更新历史值
    hfilter->x_prev2 = hfilter->x_prev1;
    hfilter->x_prev1 = x;
    hfilter->y_prev2 = hfilter->y_prev1;
    hfilter->y_prev1 = y;
    
    return y;
}

使用说明

  • 初始化时传入ADC采样率Fs(比如1kHz、2kHz)
  • 每次采样后调用AllPassFilter_Process,输入alpha信号,输出即为90度相移的beta信号
  • 该滤波器仅对50Hz信号实现严格90度相移,幅值无变化,低阶设计保证信号失真极小

3. 锁相环(PLL)+ 正交信号生成

如果需要同时跟踪信号频率和相位,可以先通过PLL锁定alpha信号的相位,再用三角函数生成正交信号。适合信号频率可能小幅波动的场景。

简化实现代码

#include <math.h>
#include <stdlib.h>

typedef struct {
    float omega;       // 估计的角频率
    float theta;       // 估计的相位
    float kp;          // 比例系数
    float ki;          // 积分系数
    float integral;    // 积分项
    float alpha_amp;   // 估计的幅值
} PLL_HandleTypeDef;

void PLL_Init(PLL_HandleTypeDef *hpll) {
    hpll->omega = 2 * M_PI * 50.0f;
    hpll->theta = 0.0f;
    hpll->kp = 10.0f;
    hpll->ki = 1.0f;
    hpll->integral = 0.0f;
    hpll->alpha_amp = 0.0f;
}

float PLL_Update(PLL_HandleTypeDef *hpll, float alpha, float Ts) {
    // 简单幅值估计:滑动平均
    hpll->alpha_amp = 0.9f * hpll->alpha_amp + 0.1f * fabs(alpha);
    
    // 计算相位误差
    float error = alpha - hpll->alpha_amp * sin(hpll->theta);
    
    // 更新频率和相位
    hpll->integral += error * Ts;
    hpll->omega = 2 * M_PI * 50.0f + hpll->kp * error + hpll->ki * hpll->integral;
    
    hpll->theta += hpll->omega * Ts;
    if (hpll->theta > 2 * M_PI) hpll->theta -= 2 * M_PI;
    else if (hpll->theta < 0) hpll->theta += 2 * M_PI;
    
    // 生成正交beta信号
    return hpll->alpha_amp * cos(hpll->theta);
}

使用说明

  • 初始化时设置PLL的初始频率为50Hz,调整kp和ki参数保证锁相速度和稳定性
  • 每次采样后调用PLL_Update,输入alpha信号,输出即为beta信号
  • 该方法能适应频率波动,若STM32浮点运算性能有限,可改用定点运算优化三角函数和系数计算

内容的提问来源于stack exchange,提问作者user13224079

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:54:53