首次提交完整的python工程代码
This commit is contained in:
389
processor/telm_calc.py
Normal file
389
processor/telm_calc.py
Normal file
@@ -0,0 +1,389 @@
|
||||
"""
|
||||
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
|
||||
|
||||
# 电压1:V = D/255*5.1 D无符号整型
|
||||
elif method == "电压1":
|
||||
D = int(x)
|
||||
return D / 255.0 * 5.1
|
||||
|
||||
# 电压6:V = D*20/65535 D有符号整型
|
||||
elif method == "电压6":
|
||||
D = int(x)
|
||||
return D * 20.0 / 65535.0
|
||||
|
||||
# 电压3:V = D*0.000305185 D有符号整型
|
||||
elif method == "电压3":
|
||||
D = int(x)
|
||||
return D * 0.000305185
|
||||
|
||||
# 电压2:V= 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
|
||||
|
||||
# ===================== 电压1:V = D/255*5.1 → D=V*255/5.1 =====================
|
||||
elif method == "电压1":
|
||||
D = y * 255.0 / 5.1
|
||||
return float(int(round(D))) # 原始是无符号整型
|
||||
|
||||
# ===================== 电压6:V = D*20/65535 → D=V*65535/20 =====================
|
||||
elif method == "电压6":
|
||||
D = y * 65535.0 / 20.0
|
||||
return float(int(round(D))) # 有符号整型
|
||||
|
||||
# ===================== 电压3:V = D*0.000305185 → D=V / 0.000305185 =====================
|
||||
elif method == "电压3":
|
||||
D = y / 0.000305185
|
||||
return float(int(round(D))) # 有符号整型
|
||||
|
||||
# ===================== 电压2:V电压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): # 区间1:y < 359.032
|
||||
# m = (y - 180) / 0.0973
|
||||
# elif y > (0.0974 * 1840 - 179.46): # 区间2:y > -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
|
||||
Reference in New Issue
Block a user