Files

389 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
2026/3/29
"""
import struct
import math
def calc_telem(value: float, method: str, param_str: str, ref_cache: dict) -> float:
#def telem_calc(value: float, method: str, param_str: str, ref_cache: dict) -> float:
try:
x = value
# 空方法:原值
if not method:
return x
# 数值拟合 y = a*x + b
if method == "数值拟合":
a, b = map(float, param_str.split(','))
return a * x + b
# 电压1V = D/255*5.1 D无符号整型
elif method == "电压1":
D = int(x)
return D / 255.0 * 5.1
# 电压6V = D*20/65535 D有符号整型
elif method == "电压6":
D = int(x)
return D * 20.0 / 65535.0
# 电压3V = D*0.000305185 D有符号整型
elif method == "电压3":
D = int(x)
return D * 0.000305185
# 电压2V= D *10/4096-5 D有符号整型
elif method == "电压2":
D = int(x )
return D * 10 / 4096 - 5
# # 电阻拟合1
# elif method == "电阻拟合1":
# D = int(x)
# V = D / 255.0 * 5.1
# ref_key = param_str.strip()
# Vref = ref_cache.get(ref_key, 5.1)
# if abs(Vref - V) < 1e-12:
# return 0.0
# Rr = 10000.0
# return V * Rr / (Vref - V)
# 电阻拟合1
elif method == "电阻拟合1":
D = int(x)
V = D / 255.0 * 5.1
# V基准固定为 5.0V
Vref = 5.0
if abs(Vref - V) < 1e-12:
return 0.0
Rr = 10000.0
return V * Rr / (Vref - V)
# # 特殊公式8按你描述完整实现
# elif method == "特殊公式8":
# raw = int(x)
# if param_str:
# parts = param_str.split(',')
# else:
# parts = []
# flag = int(parts[0]) if len(parts) >= 1 else 0
# if flag == 0:
# # 遥测状态字16位处理
# w = raw & 0xFFFF
# bh = (w >> 8) & 0xFF
# bl = w & 0xFF
# bh8 = bh + 0x8
# bl8 = bl + 0x8
# h4 = (bh8 >> 4) & 0xF
# l4 = (bl8 >> 4) & 0xF
# B1 = (l4 << 4) | h4
# else:
# # 遥控状态字8位直接用
# B1 = raw & 0xFF
# # 后面位比较逻辑你需要我也可以补全
# return float(B1)
elif method == "特殊公式8":
"""
最新规则:
1) 原始值取整
2) 低 16bit低位
3) 高 4bit :高位
4) 合并 = (高位4bit << 16) | 低位16bit
5) 结果 = 合并值 × 0.00205479
"""
raw_int = int(x) & 0xFFFFFFFF # 取32位无符号
# 低位 16bit
low16 = raw_int & 0xFFFF
# 高位 4bit最后4bit
high4 = (raw_int >> 28) & 0x0F
# 合并 20bit高4位 <<16 | 低16位
combined = (high4 << 16) | low16
# 乘以系数
result = combined * 0.00205479
return float(result)
# 状态量 / 10进制不处理
elif method in ["状态量", "10进制"]:
return x
return x
except Exception as e:
return value
import struct
import math
def poly4_calc(D):
"""正向 4 次多项式计算 y"""
y = (-49.736 * (D ** 4)
+ 383.38 * (D ** 3)
- 1068.5 * (D ** 2)
+ 1309.9 * D
- 684.71)
return y
def inverse_poly4_fit(y):
"""
逆运算:已知 y → 求 D
适用于y ∈ [-112, 42]
"""
if not (-112 <= y <= 42):
return 0.0 # 超范围保护
# 二分法区间(根据你的遥测范围实测得出)
left = 1.5
right = 4.5
eps = 1e-5
for _ in range(50):
mid = (left + right) / 2
current_y = poly4_calc(mid)
if current_y < y:
left = mid
else:
right = mid
return (left + right) / 2
# 固定系数
Rr = 10000.0
A = -6.01188
B = 4622.53337
C = -86421.72414
def calc_t_from_V(V):
"""正向V → t内部用"""
if V >= 5.0:
V = 4.9999
if V <= 0:
V = 0.0001
R = V * Rr / (5.0 - V)
lnR = math.log(R)
sqrt_val = math.sqrt(B**2 - 4 * C * (A - lnR))
t = 2 * C / (sqrt_val - B) - 273.15
return t
def calc_V_from_t(t_target):
"""
逆运算:已知温度 t → 求遥测电压 V
:param t_target: 目标温度 ℃
:return: V (V),精度 0.0001
"""
# 电压范围 0 ~ 5V
left = 0.0001
right = 4.9999
eps = 1e-5
# 二分法迭代 50 次足够精确
for _ in range(50):
mid = (left + right) / 2
t_mid = calc_t_from_V(mid)
if t_mid < t_target:
left = mid
else:
right = mid
return (left + right) / 2
def inverse_quadratic_fit(y, coeffs, y_min, y_max):
"""
通用二次多项式逆运算3个拟合参数
公式y = a2*D² + a1*D + a0
已知 y → 求 D只返回合法正根
参数:
y: 目标物理值
coeffs: 拟合系数 [a2, a1, a0]
y_min: y 有效最小值
y_max: y 有效最大值
返回:
D: 原始码值
"""
# 1. 边界限幅
y_clamped = max(y_min, min(y, y_max))
# 2. 取出系数
a2, a1, a0 = coeffs
# 3. 构建一元二次方程标准形式A*D² + B*D + C = 0
A = a2
B = a1
C = a0 - y_clamped
# 4. 求判别式
delta = B ** 2 - 4 * A * C
if delta < 0:
delta = 0 # 防止无实根
# 5. 求正根遥测D一定为正
D = (-B + (delta ** 0.5)) / (2 * A)
# 6. 保证 D 不为负
return max(D, 0.0)
def calc_telem_reverse(result: float, method: str, param_str: str) -> float:
"""
【逆运算】
输入A 软件发来的 结果值
输出:反推出来的 原始值 D
完全按你提供的处理方法反向计算
"""
try:
y = result
# ===================== 空方法:直接返回 =====================
if not method:
return y
# ===================== 数值拟合Y = a*x + b → x=(y-b)/a =====================
if method == "数值拟合":
a, b = map(float, param_str.split(','))
x = (y - b) / a
return x
# ===================== 电压1V = D/255*5.1 → D=V*255/5.1 =====================
elif method == "电压1":
D = y * 255.0 / 5.1
return float(int(round(D))) # 原始是无符号整型
# ===================== 电压6V = D*20/65535 → D=V*65535/20 =====================
elif method == "电压6":
D = y * 65535.0 / 20.0
return float(int(round(D))) # 有符号整型
# ===================== 电压3V = D*0.000305185 → D=V / 0.000305185 =====================
elif method == "电压3":
D = y / 0.000305185
return float(int(round(D))) # 有符号整型
# ===================== 电压2V电压2 = D *10/4096-5其中D为无符号整型计算时转化成十进制数。 → D=V + 5*409.6 =====================
elif method == "电压2":
D = (y + 5) * 409.6
return float(int(round(D))) # 有符号整型
# ===================== 电阻拟合1 → 逆运算 =====================
# 公式:
# V = D/255*5.1
# R = V*10000/(5.0 - V)
# 逆推 D
#2026/3/30手算验证公式是正确的
elif method == "电阻拟合1":
R = y
Vref = 5.0
Rr = 10000.0
# 逆推 V
if R <= 0.0:
V = 0.0
else:
V = (R * Vref) / (R + Rr)
# 逆推 D
D = V * 255.0 / 5.1
return float(int(round(D)))
# ===================== 特殊公式8逆运算 =====================
# 正向combined = (high4 <<16) | low16 result = combined * 0.00205479
# 逆向combined = y / 0.00205479
# high4 = (combined >> 16) & 0xF
# low16 = combined & 0xFFFF
# raw = (high4 << 28) | low16
elif method == "特殊公式8":
combined = int(round(y / 0.00205479))
low16 = combined & 0xFFFF
high4 = (combined >> 16) & 0x0F
raw = (high4 << 28) | low16
return float(raw)
# ===================== 状态量 / 10进制直接返回 =====================
elif method in ["状态量", "10进制"]:
return y
elif method == "特殊公式11-1":
"""
M057JG023 / M057JG024 专用逆运算
输入:物理值 y
输出:原始值 m用于组帧
"""
# if y < (0.0973 * 1840 + 180): # 区间1y < 359.032
# m = (y - 180) / 0.0973
# elif y > (0.0974 * 1840 - 179.46): # 区间2y > -0.444
# m = (y + 179.46) / 0.0974
# else: # m=1840
# m = 1840.0
#2026/5/7修正公式
if y < (180): # 区间1
m = (y + 179.46) / 0.0974
elif y > (180): # 区间2
m = (y - 180) / 0.0973
else: # m=1840
m = 0.0
# 组帧需要整数,返回四舍五入
return float(round(m))
elif method == "电压2数值拟合":
"""
逆运算先反解数值拟合再反推电压2
"""
a, b = map(float, param_str.split(','))
x = (y - b) / a
D = (x + 5) * 409.6## 电压2
return float(int(round(D))) # 有符号整型
elif method == "电压1数值拟合":
"""
逆运算先反解数值拟合再反推电压2
"""
a, b = map(float, param_str.split(','))
x = (y - b) / a
D = x * 255.0 / 5.1## 电压1
return float(int(round(D))) # 有符号整型
elif method == "电压1数值拟合5":
"""
逆运算先反解数值拟合5次方程再反推电压2
"""
x = inverse_poly4_fit(y) ##2分法求解5次方程
D = x * 255.0 / 5.1## 电压1
return float(int(round(D))) # 有符号整型
elif method == "电阻拟合1,MF501(电阻)":
x = calc_V_from_t(y) #2分法
R = x
Vref = 5.0
Rr = 10000.0
# 逆推 V
if R <= 0.0:
V = 0.0
else:
V = (R * Vref) / (R + Rr)
# 逆推 D
D = V * 255.0 / 5.1
return float(int(round(D)))
elif method == "电压1数值拟合3":
a, b,c,y_min,y_max = map(float, param_str.split(','))
coeffs = [a,b,c]
return inverse_quadratic_fit(y, coeffs, y_min, y_max)
elif method == "电压6数值拟合":
"""
逆运算先反解数值拟合再反推电压2
"""
a, b = map(float, param_str.split(','))
x = (y - b) / a
D = x * 65535.0 / 20.0 #电压6
return float(int(round(D))) # 有符号整型
except Exception as e:
return result