【风电控制】FPGA采集Vdc的ADC增益系数解析——从数字码到实际电压的桥梁

【风电控制】FPGA采集Vdc的ADC增益系数解析------从数字码到实际电压的桥梁


一、问题本质

FPGA采集直流母线电压(Vdc)时,ADC输出的是数字码(如0~65535),而不是实际电压值(如1800V)。需要一个**增益系数(gain)**将数字码转换为实际电压。

复制代码
实际物理世界              ADC硬件              FPGA数字域
                                    
 Vdc = 1800V  ──→  数字码 = 41268  ──→  实际Vdc = 41268 × 0.0436041090223524 = 1800V
                                    
                   ADC输出            乘以gain后
                   (无物理单位)        (有物理单位: V)

增益系数 0.0436041090223524 的含义:ADC每输出1个数字码,对应的实际电压是 0.0436V。


二、ADC增益系数的计算原理

2.1 基本公式

实际电压=数字码×gain \text{实际电压} = \text{数字码} \times \text{gain} 实际电压=数字码×gain

反推:

gain=实际电压数字码 \text{gain} = \frac{\text{实际电压}}{\text{数字码}} gain=数字码实际电压

2.2 gain的完整推导链

gain不是凭空来的,它由硬件电路决定,需要从实际电压一直推导到数字码:

复制代码
实际电压 Vdc (如1800V)
    │
    ▼
┌─────────────────────────────────────────────────────┐
│ 电压调理电路 (分压 + 滤波 + 钳位)                      │
│                                                     │
│  分压比 K_div = R_low / (R_high + R_low)             │
│  如: R_high = 1MΩ, R_low = 5kΩ                       │
│  K_div = 5k / (1M + 5k) ≈ 0.004975                  │
│                                                     │
│  ADC输入电压 = Vdc × K_div                           │
│  如: 1800V × 0.004975 ≈ 8.955V                       │
│                                                     │
│  (实际中还需经过运放调理,调整到ADC的输入范围)           │
└─────────────────────┬───────────────────────────────┘
                      ▼
┌─────────────────────────────────────────────────────┐
│ ADC量化                                              │
│                                                     │
│  ADC参考电压 Vref (如3.3V)                            │
│  ADC分辨率 N (如16位)                                 │
│  最大数字码 D_max = 2^N - 1 = 65535                   │
│                                                     │
│  数字码 = ADC输入电压 / Vref × D_max                  │
│  如: 8.955V / 3.3V × 65535 ≈ ???                     │
│                                                     │
│  等等, 8.955V > 3.3V? 这超出了ADC范围!                │
│  需要更精细的分压或运放调理...                         │
└─────────────────────────┬───────────────────────────┘
                          ▼

2.3 反推gain = 0.0436041090223524的硬件参数

已知:

  • 额定电压 P_Dat_NomDcVolt = 1800V
  • gain = 0.0436041090223524 V/count
  • 对应的额定数字码 = 1800 / 0.0436041090223524 ≈ 41268

反推ADC输入电压(假设16位ADC,Vref = 3.3V):

VADC,input=4126865535×3.3V=2.077V V_{ADC,input} = \frac{41268}{65535} \times 3.3V = 2.077V VADC,input=6553541268×3.3V=2.077V

反推分压比

Kdiv=VADC,inputVdc=2.0771800=0.001154 K_{div} = \frac{V_{ADC,input}}{V_{dc}} = \frac{2.077}{1800} = 0.001154 Kdiv=VdcVADC,input=18002.077=0.001154

反推分压电阻(假设R_high = 390kΩ × 2):

Rlow=Kdiv×Rhigh1−Kdiv=0.001154×780k1−0.001154≈900Ω R_{low} = \frac{K_{div} \times R_{high}}{1 - K_{div}} = \frac{0.001154 \times 780k}{1 - 0.001154} \approx 900\Omega Rlow=1−KdivKdiv×Rhigh=1−0.0011540.001154×780k≈900Ω

完整的信号链

复制代码
Vdc = 1800V
    │
    ▼
分压电阻: R_high = 780kΩ, R_low = 900Ω
    │
    │  V_adc = 1800 × 900 / (780000 + 900) = 2.074V
    ▼
运放调理 (可能有增益/偏移调整)
    │
    │  V_adc_conditioned ≈ 2.077V
    ▼
ADC量化 (16位, Vref = 3.3V)
    │
    │  数字码 = 2.077 / 3.3 × 65535 ≈ 41268
    ▼
增益系数: gain = 1800 / 41268 = 0.0436041090223524 V/count

三、增益系数的精确含义

3.1 gain包含了整条信号链的总增益

gain=Vdc,ratedDrated=Vdc,ratedVdc,rated×Kdiv×GopampVref×(2N−1) \text{gain} = \frac{V_{dc,rated}}{D_{rated}} = \frac{V_{dc,rated}}{\frac{V_{dc,rated} \times K_{div} \times G_{opamp}}{V_{ref}} \times (2^N - 1)} gain=DratedVdc,rated=VrefVdc,rated×Kdiv×Gopamp×(2N−1)Vdc,rated

简化:

gain=VrefKdiv×Gopamp×(2N−1) \boxed{\text{gain} = \frac{V_{ref}}{K_{div} \times G_{opamp} \times (2^N - 1)}} gain=Kdiv×Gopamp×(2N−1)Vref

其中:

  • VrefV_{ref}Vref:ADC参考电压(如3.3V)
  • KdivK_{div}Kdiv:分压电阻比
  • GopampG_{opamp}Gopamp:运放增益
  • NNN:ADC位数(如16位)

gain是整条硬件信号链的"等效转换系数"------它把分压、运放、ADC量化三个环节的增益合并为一个数字。

3.2 为什么gain这么精确(小数点后14位)?

0.0436041090223524 这个精度看起来夸张,但有其工程原因:

原因 说明
出厂标定 每台设备在出厂前用标准电压源标定,记录精确的gain
电阻精度 分压电阻有±0.1%的公差,需要标定补偿
运放偏移 运放有输入偏置电压(mV级),需要标定补偿
ADC非线性 ADC存在DNL/INL误差,精确gain可以部分补偿
温度漂移 不同温度下的gain略有不同,可能需要温度补偿表

实际上,这个精度可能是过度标定的结果。在工程中,保留6~8位有效数字就足够了(如0.0436041)。


四、FPGA中的实现

4.1 乘法实现

verilog 复制代码
module adc_to_voltage (
    input              clk,
    input  [15:0]      adc_code,       // ADC数字码 (0~65535)
    input  [31:0]      gain_fixed,     // 增益系数 (Q格式定点数)
    output reg [31:0]  voltage_fixed   // 实际电压 (Q格式定点数)
);
    // gain = 0.0436041090223524
    // 用Q16定点表示: 0.0436041090223524 × 2^16 ≈ 2858
    // 或更精确: 0.0436041090223524 × 2^24 ≈ 731335
    
    // 定点乘法: 电压 = adc_code × gain
    always @(posedge clk) begin
        // 16位 × 24位 = 40位乘法
        voltage_fixed <= adc_code * gain_fixed;
        // 结果右移24位得到实际电压 (Q0格式)
    end
endmodule

4.2 C2000 DSP中的实现

c 复制代码
// 在DSP中, 通常用浮点乘法
#define VDC_ADC_GAIN    0.0436041090223524f

float Convert_ADC_to_Vdc(uint16_t adc_code) {
    return (float)adc_code * VDC_ADC_GAIN;
}

// 或使用Q格式定点 (节省计算时间)
// gain_fixed = 0.0436041090223524 × 2^15 = 1429 (Q15格式)
#define VDC_ADC_GAIN_Q15    1429

int32_t Convert_ADC_to_Vdc_Q15(uint16_t adc_code) {
    return ((int32_t)adc_code * VDC_ADC_GAIN_Q15) >> 15;
    // 结果单位: 0.01V (需要进一步处理得到实际电压)
}

4.3 SafeDivide模块的作用

在系统中,SafeDivide模块用于计算额定电压对应的数字码

CoefNomDcVolt=P_Dat_NomDcVoltP_HW_UnitDcVoltAdcGain=18000.0436041090223524≈41268.5 \text{CoefNomDcVolt} = \frac{\text{P\_Dat\_NomDcVolt}}{\text{P\_HW\_UnitDcVoltAdcGain}} = \frac{1800}{0.0436041090223524} \approx 41268.5 CoefNomDcVolt=P_HW_UnitDcVoltAdcGainP_Dat_NomDcVolt=0.04360410902235241800≈41268.5

这个系数的用途

用途 说明
标定验证 41268应该是额定电压下的ADC读数,用于验证硬件标定是否正确
归一化基准 将ADC读数归一化为标幺值:Vdc,pu=adc_code/CoefNomDcVoltV_{dc,pu} = \text{adc\_code} / \text{CoefNomDcVolt}Vdc,pu=adc_code/CoefNomDcVolt
保护阈值 过压保护阈值 = CoefNomDcVolt × 1.1(如45395对应1980V)
增益校验 如果实际ADC读数与41268偏差较大,说明硬件需要重新标定
c 复制代码
// 归一化计算示例
float CoefNomDcVolt = P_Dat_NomDcVolt / P_HW_UnitDcVoltAdcGain;  // 41268.5

// 将ADC读数转为标幺值
float Vdc_pu = (float)adc_code / CoefNomDcVolt;

// 额定运行时: Vdc_pu ≈ 1.0
// 过压保护: Vdc_pu > 1.1 → 报警
// 欠压保护: Vdc_pu < 0.85 → 报警

五、完整的Vdc采集信号链

复制代码
┌──────────────────────────────────────────────────────────────────┐
│  物理层                                                          │
│                                                                  │
│  直流母线正极 ──┬──[R_high 780kΩ]──┬──[运放]──┬──[ADC]──→ FPGA  │
│                 │                  │          │                   │
│                 └──[R_low 900Ω]───┘          │                   │
│                                             Vref=3.3V            │
│  直流母线负极 ────────────────────────────────┘                   │
│                                                                  │
│  信号变化:                                                       │
│  Vdc = 1800V → 分压 → 2.077V → ADC → 41268 → ×gain → 1800V     │
└──────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────┐
│  FPGA逻辑层                                                      │
│                                                                  │
│  1. ADC接口: SPI读取数字码 (41268)                               │
│  2. 校准: 减去零偏 (如 adc_code - offset)                        │
│  3. 增益转换: Vdc = adc_code × gain (0.0436041090223524)        │
│  4. 滤波: 低通滤波去除PWM开关纹波                                │
│  5. 保护: 与阈值比较 (如 > 1980V → 过压报警)                     │
│  6. 输出: 将Vdc值传给DSP (通过共享RAM或SPI)                      │
└──────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────┐
│  DSP算法层                                                       │
│                                                                  │
│  1. 接收Vdc值                                                    │
│  2. 电压环PI: VdcRef - Vdc → id_ref                              │
│  3. 弱磁控制: Vdc作为电压极限的基准                               │
│  4. 保护判断: Vdc用于过压/欠压保护                                │
└──────────────────────────────────────────────────────────────────┘

六、增益系数的标定方法

6.1 工厂标定流程

复制代码
Step 1: 施加已知标准电压 (如用高精度电压源施加1000V)
Step 2: 记录ADC数字码 (如 adc_code = 22927)
Step 3: 计算gain = 1000 / 22927 = 0.043617...

Step 4: 施加另一个标准电压 (如1500V)
Step 5: 记录ADC数字码 (如 adc_code = 34393)
Step 6: 验证: 34393 × 0.043617 ≈ 1500.1V ✓

Step 7: 多点标定, 取平均或拟合直线
Step 8: 将gain写入EEPROM: P_HW_UnitDcVoltAdcGain = 0.0436041090223524

6.2 在线自校准

c 复制代码
// 利用已知的参考电压进行在线校准
void ADC_SelfCalibrate(void) {
    // 在停机状态下, 直流母线电压由预充电电路确定
    // 已知预充电电压 = V_precharge (如1000V)
    
    float V_precharge = 1000.0f;  // 标准电压
    uint16_t adc_code_measured = ADC_Read(CH_VDC);  // 读取ADC
    
    // 更新gain
    float gain_new = V_precharge / (float)adc_code_measured;
    
    // 与存储的gain比较, 如果偏差 > 1%, 报警
    if (fabsf(gain_new - gain_stored) / gain_stored > 0.01f) {
        FAULT_Set(FAULT_ADC_CALIBRATION);
    }
    
    // 更新gain (可选, 需要谨慎)
    gain_stored = 0.9f * gain_stored + 0.1f * gain_new;  // 缓慢更新
}

七、常见问题

问题1:gain会随温度变化吗?

会。 分压电阻和运放都有温度系数。对于高精度应用(如计量级),需要温度补偿:

gain(T)=gain(25°C)×(1+α×(T−25)) \text{gain}(T) = \text{gain}(25°C) \times (1 + \alpha \times (T - 25)) gain(T)=gain(25°C)×(1+α×(T−25))

其中 α\alphaα 为温度系数(通常 < 50ppm/°C)。

问题2:为什么不用整数比例?

gain=VrefKdiv×Gopamp×(2N−1) \text{gain} = \frac{V_{ref}}{K_{div} \times G_{opamp} \times (2^N - 1)} gain=Kdiv×Gopamp×(2N−1)Vref

由于分压电阻、运放增益、ADC参考电压都是物理量,它们的比值几乎不可能是"整齐"的数字。0.0436041090223524 这个"丑陋"的数字恰恰反映了硬件的真实特性

问题3:gain精度需要多少位?

应用场景 gain精度要求 说明
保护判断 ±1% 只需4位有效数字
控制反馈 ±0.1% 需要6位有效数字
功率计量 ±0.05% 需要8位有效数字
电能质量分析 ±0.01% 需要10位以上

工程建议:对于变流器控制,gain保留8位有效数字(如0.04360411)即可,多余的精度被ADC本身的DNL/INL误差淹没。


八、总结

问题 答案
gain是什么? ADC数字码到实际电压的转换系数,单位 V/count
gain = 0.0436041090223524 的含义? ADC每输出1个数字码,对应 0.0436V 的实际电压
gain怎么来的? 由硬件信号链决定:分压比 × 运放增益 × ADC量化系数的总等效增益
gain用在哪里? ADC数字码 × gain = 实际Vdc;Vdc / gain = 额定数字码(用于标定和保护)
gain需要多精确? 变流器控制:8位有效数字足够
gain会变吗? 会随温度和器件老化漂移,高精度应用需要在线校准

一句话:增益系数是连接"模拟世界"和"数字世界"的桥梁------它让FPGA知道,ADC输出的数字码41268到底代表多少伏特的电压。

相关推荐
TDengine (老段)1 小时前
TDengine 压缩编码机制 — 双层压缩架构与类型特化算法
大数据·数据库·物联网·算法·时序数据库·tdengine·涛思数据
妄想出头的工业炼药师2 小时前
LVIO鲁棒
算法·开源
aini_lovee2 小时前
MATLAB 图像修复 — 偏微分方程方法
算法
Cthy_hy2 小时前
Python算法竞赛:排列组合核心用法
开发语言·python·算法
大圣编程3 小时前
面向对象深度理解
java·开发语言·算法
爱喝水的鱼丶3 小时前
SAP-ABAP:SAP 简单报表输出开发系列(共6篇) 第四篇:SAP 报表异常处理机制:数据校验与消息提示规范落地
开发语言·数据库·学习·算法·sap·abap
wabs6663 小时前
关于贪心算法【划分字母区间】的问题总结(C++语法)
算法·贪心算法
啦啦啦啦啦zzzz4 小时前
数据结构:二叉树的线索化
数据结构·算法
2401_872418784 小时前
算法入门:并查集(Disjoint Set / Union-Find):连通性问题的利器
算法