Files

389 lines
12 KiB
Python
Raw Permalink Normal View History

"""
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* + 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