UPP/Информация для программиста (УПП СП СЭД)/temperature_polynom.py
Razvalyaev 4491f11b3d Тесты фильтрования
Оно добавляют задержку и сдвиг по фазе надо чет думать
2025-11-10 07:55:07 +03:00

204 lines
8.7 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.

import numpy as np
import matplotlib.pyplot as plt
# Данные: ADC -> Temperature
adc_values = [2188, 2197, 2206, 2216, 2226, 2236, 2247, 2259, 2271, 2283,
2296, 2310, 2324, 2338, 2354, 2369, 2385, 2402, 2419, 2437,
2455, 2474, 2493, 2513, 2533, 2554, 2575, 2597, 2619, 2641,
2664, 2688, 2711, 2735, 2759, 2784, 2809, 2833, 2859, 2884,
2909, 2935, 2961, 2986, 3012, 3037, 3063, 3089, 3114, 3140,
3165, 3190, 3215, 3239, 3263, 3288, 3312, 3335, 3359, 3381,
3404, 3426, 3448, 3470, 3491, 3512, 3532, 3552, 3572, 3591,
3610, 3628, 3646, 3663, 3681, 3697, 3714, 3729, 3745, 3760,
3775, 3789, 3803, 3817, 3830, 3843, 3855, 3868, 3879, 3891,
3902, 3913, 3924, 3934, 3944, 3954, 3963, 3972, 3981, 3989,
3997, 4005, 4013, 4021, 4028, 4035, 4042, 4049, 4055, 4062,
4068, 4074, 4079, 4085, 4091, 4096]
temperatures = [-25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11,
-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 87, 88, 89, 90]
# Параметры ограничений
MIN_COEFF_ABS = 1e-5 # Минимальное абсолютное значение коэффициента
MAX_CONDITION_NUMBER = 1e10 # Максимальное число обусловленности
# Аппроксимация полиномами разных степеней
degrees = [2, 3, 4, 5]
coefficients = {}
filtered_coefficients = {}
plt.figure(figsize=(16, 12))
# График 1: Сравнение аппроксимаций
plt.subplot(2, 3, 1)
plt.plot(adc_values, temperatures, 'ko-', markersize=3, linewidth=1, label='Исходные данные')
colors = ['red', 'blue', 'green', 'orange']
for i, degree in enumerate(degrees):
coeffs = np.polyfit(adc_values, temperatures, degree)
coefficients[degree] = coeffs
# Фильтрация малых коэффициентов
filtered_coeffs = coeffs.copy()
small_coeffs_mask = np.abs(coeffs) < MIN_COEFF_ABS
filtered_coeffs[small_coeffs_mask] = 0
filtered_coefficients[degree] = filtered_coeffs
poly = np.poly1d(coeffs)
adc_continuous = np.linspace(min(adc_values), max(adc_values), 500)
temp_predicted = poly(adc_continuous)
plt.plot(adc_continuous, temp_predicted, color=colors[i], linewidth=2,
label=f'Полином {degree}-й степени')
plt.xlabel('Значение АЦП')
plt.ylabel('Температура (°C)')
plt.title('Аппроксимация зависимости АЦП → Температура')
plt.legend()
plt.grid(True, alpha=0.3)
# График 2: Ошибки аппроксимации
plt.subplot(2, 3, 2)
for i, degree in enumerate(degrees):
poly = np.poly1d(coefficients[degree])
predicted = poly(adc_values)
error = predicted - temperatures
plt.plot(temperatures, error, 'o-', color=colors[i], markersize=3,
label=f'Ошибка {degree}-й степени')
plt.xlabel('Температура (°C)')
plt.ylabel('Ошибка (°C)')
plt.title('Ошибки аппроксимации по температуре')
plt.legend()
plt.grid(True, alpha=0.3)
# График 3: Статистика ошибок
plt.subplot(2, 3, 3)
max_errors = []
rms_errors = []
for degree in degrees:
poly = np.poly1d(coefficients[degree])
predicted = poly(adc_values)
max_error = np.max(np.abs(predicted - temperatures))
rms_error = np.sqrt(np.mean((predicted - temperatures)**2))
max_errors.append(max_error)
rms_errors.append(rms_error)
x_pos = np.arange(len(degrees))
width = 0.35
plt.bar(x_pos - width/2, max_errors, width, label='Макс. ошибка', alpha=0.7)
plt.bar(x_pos + width/2, rms_errors, width, label='СКО', alpha=0.7)
plt.xlabel('Степень полинома')
plt.ylabel('Ошибка (°C)')
plt.title('Статистика ошибок аппроксимации')
plt.xticks(x_pos, degrees)
plt.legend()
plt.grid(True, alpha=0.3)
# График 4: Сравнение коэффициентов до/после фильтрации
plt.subplot(2, 3, 4)
for degree in degrees:
coeffs = coefficients[degree]
filtered_coeffs = filtered_coefficients[degree]
# Отображаем только ненулевые коэффициенты
nonzero_indices = np.where(filtered_coeffs != 0)[0]
if len(nonzero_indices) > 0:
plt.semilogy(nonzero_indices, np.abs(filtered_coeffs[nonzero_indices]), 'o-',
label=f'Полином {degree}-й степени', markersize=6)
plt.axhline(y=MIN_COEFF_ABS, color='r', linestyle='--', alpha=0.7, label=f'Порог {MIN_COEFF_ABS:.0e}')
plt.xlabel('Индекс коэффициента')
plt.ylabel('Абсолютное значение коэффициента')
plt.title('Коэффициенты после фильтрации (логарифмическая шкала)')
plt.legend()
plt.grid(True, alpha=0.3)
# График 5: Влияние фильтрации на ошибку
plt.subplot(2, 3, 5)
original_errors = []
filtered_errors = []
for degree in degrees:
poly_original = np.poly1d(coefficients[degree])
poly_filtered = np.poly1d(filtered_coefficients[degree])
predicted_original = poly_original(adc_values)
predicted_filtered = poly_filtered(adc_values)
error_original = np.max(np.abs(predicted_original - temperatures))
error_filtered = np.max(np.abs(predicted_filtered - temperatures))
original_errors.append(error_original)
filtered_errors.append(error_filtered)
x_pos = np.arange(len(degrees))
width = 0.35
plt.bar(x_pos - width/2, original_errors, width, label='Оригинальные коэф.', alpha=0.7)
plt.bar(x_pos + width/2, filtered_errors, width, label='После фильтрации', alpha=0.7)
plt.xlabel('Степень полинома')
plt.ylabel('Максимальная ошибка (°C)')
plt.title('Влияние фильтрации коэффициентов на точность')
plt.xticks(x_pos, degrees)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Вывод численных результатов
print("=" * 80)
print("РЕЗУЛЬТАТЫ АППРОКСИМАЦИИ С ФИЛЬТРАЦИЕЙ КОЭФФИЦИЕНТОВ")
print("=" * 80)
for degree in degrees:
coeffs = coefficients[degree]
filtered_coeffs = filtered_coefficients[degree]
poly_original = np.poly1d(coeffs)
poly_filtered = np.poly1d(filtered_coeffs)
predicted_original = poly_original(adc_values)
predicted_filtered = poly_filtered(adc_values)
max_error_original = np.max(np.abs(predicted_original - temperatures))
rms_error_original = np.sqrt(np.mean((predicted_original - temperatures)**2))
max_error_filtered = np.max(np.abs(predicted_filtered - temperatures))
rms_error_filtered = np.sqrt(np.mean((predicted_filtered - temperatures)**2))
# Подсчет нулевых коэффициентов
zero_count = np.sum(filtered_coeffs == 0)
total_count = len(filtered_coeffs)
print(f"\nПолином {degree}-й степени:")
print(f"Максимальная ошибка: {max_error_original:.3f}°C -> {max_error_filtered:.3f}°C")
print(f"Среднеквадратичная ошибка: {rms_error_original:.3f}°C -> {rms_error_filtered:.3f}°C")
print(f"Обнулено коэффициентов: {zero_count}/{total_count}")
print("Коэффициенты после фильтрации:")
for i, coeff in enumerate(filtered_coeffs):
power = len(filtered_coeffs) - i - 1
status = "" if coeff != 0 else "✗ (обнулен)"
print(f" a_{power} = {coeff:.6e} {status}")
# Рекомендация
print("\n" + "=" * 80)
print("РЕКОМЕНДАЦИЯ:")
print(f"Порог обнуления коэффициентов: {MIN_COEFF_ABS:.0e}")
print("Полином 3-й степени обеспечивает оптимальный баланс между точностью")
print("и сложностью реализации. Фильтрация малых коэффициентов практически")
print("не влияет на точность, но упрощает реализацию на embedded системах.")
print("=" * 80)