|
clear all;
|
|
clc;
|
|
|
|
|
|
% --- Charger les données du tableau Excel ---
|
|
opts = detectImportOptions('Log1.xlsx');
|
|
opts.VariableNamingRule = 'preserve';
|
|
data = readtable('Log1.xlsx', opts);
|
|
|
|
% --- Initialisation des données ---
|
|
dt = 0.2; % Intervalle de temps (secondes)
|
|
I = data.Current; % Courant (A)
|
|
V_meas = data.Voltage; % Tension mesurée (V)
|
|
|
|
% Tableau OCV-SOC
|
|
soc_table = ([100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0]) / 100;
|
|
ocv_table = [4.1269, 4.0825, 4.0515, 3.9422, 3.8545, 3.7481, ...
|
|
3.6186, 3.5414, 3.44, 3.2358, 2.7565];
|
|
|
|
% Paramètres de la batterie
|
|
Q_nom = 18000; % Capacité nominale (Coulombs)
|
|
soc_initial = 0.6466; % SOC initial (100 %)
|
|
soc = soc_initial + cumsum(I) * dt / Q_nom; % Calcul du SOC
|
|
soc(soc < 0) = 0; % Limiter SoC à 0 %
|
|
soc(soc > 1) = 1; % Limiter SoC à 100 %
|
|
|
|
% Interpolation pour V_OC
|
|
Voc = interp1(soc_table, ocv_table, soc, 'linear', 'extrap');
|
|
|
|
% --- Initialisation des paramètres ---
|
|
% Initialisation des paramètres
|
|
params = [0.023, 0.05985, 7345.99, 0.0068, 1073.25]; % [R0, R1, C1, R2, C2]
|
|
lb = [0.025, 0.05, 500, 0.005, 500];% Limites inférieures
|
|
ub = [0.1, 0.06, 7350, 0.007, 1100];% Limites supérieures
|
|
|
|
|
|
t = (0:length(I)-1)' * dt; % Vecteur temps (colonne)
|
|
|
|
% --- Fonction pour le modèle 2RC avec mise à jour exponentielle ---
|
|
model_2RC = @(params, Voc, I, dt) ...
|
|
calculate_vsim(params, Voc, I, dt);
|
|
|
|
% --- Boucle d'identification récursive ---
|
|
max_iterations = 10; % Limite de sécurité pour convergence
|
|
tolerance = 1e-2;
|
|
learning_rate = 0.01; % Taux d'apprentissage pour la correction des paramètres
|
|
prev_params = params;
|
|
error_history = zeros(max_iterations, 1); % Pour tracer les erreurs
|
|
|
|
for iter = 1:max_iterations
|
|
% Étape 1 : Simulation de la tension prédite
|
|
V_sim = model_2RC(prev_params, Voc, I, dt);
|
|
|
|
% Étape 2 : Calcul de l'erreur de prédiction
|
|
error = V_meas - V_sim; % \Delta Z
|
|
|
|
|
|
error_norm = norm(error);
|
|
error_history(iter) = error_norm;
|
|
|
|
% Étape 3 : Ajustement des paramètres
|
|
params_opt = lsqcurvefit(@(params, t) model_2RC(params, Voc, I, dt), ...
|
|
prev_params, t, V_meas, lb, ub);
|
|
|
|
% Étape 4 : Correction des paramètres en fonction de l'erreur
|
|
params_opt(1) = params_opt(1) + learning_rate * mean(error) * sign(params_opt(1)); % Mise à jour de R0
|
|
params_opt(2) = params_opt(2) + learning_rate * mean(error) * sign(params_opt(2)); % Mise à jour de R1
|
|
params_opt(3) = params_opt(3) + learning_rate * mean(error) * sign(params_opt(3)); % Mise à jour de C1
|
|
params_opt(4) = params_opt(4) + learning_rate * mean(error) * sign(params_opt(4)); % Mise à jour de R2
|
|
params_opt(5) = params_opt(5) + learning_rate * mean(error) * sign(params_opt(5)); % Mise à jour de C2
|
|
|
|
% Vérification de convergence
|
|
if norm(params_opt - prev_params) < tolerance
|
|
fprintf('Convergence atteinte à l''itération %d\n', iter);
|
|
break;
|
|
end
|
|
|
|
% Ajout de la vérification sur la variation de l'erreur
|
|
if iter > 1 && abs(error_history(iter) - error_history(iter-1)) < 1e-1
|
|
fprintf('Convergence atteinte après %d itérations.\n', iter);
|
|
break;
|
|
end
|
|
|
|
% Mise à jour pour l'itération suivante
|
|
prev_params = params_opt;
|
|
|
|
% Affichage des résultats intermédiaires
|
|
fprintf('Itération %d : R0 = %.4f, R1 = %.4f, C1 = %.4f, R2 = %.4f, C2 = %.4f\n', ...
|
|
iter, params_opt(1), params_opt(2), params_opt(3), params_opt(4), params_opt(5));
|
|
end
|
|
|
|
% --- Résultats finaux ---
|
|
R0 = params_opt(1);
|
|
R1 = params_opt(2);
|
|
C1 = params_opt(3);
|
|
R2 = params_opt(4);
|
|
C2 = params_opt(5);
|
|
|
|
% Calcul des constantes de temps
|
|
tau1 = R1 * C1; % Constante de temps RC1
|
|
tau2 = R2 * C2; % Constante de temps RC2
|
|
|
|
fprintf('Paramètres finaux estimés :\n');
|
|
fprintf('R0 = %.4f Ω\n', R0);
|
|
fprintf('R1 = %.4f Ω\n', R1);
|
|
fprintf('C1 = %.4f F\n', C1);
|
|
fprintf('R2 = %.4f Ω\n', R2);
|
|
fprintf('C2 = %.4f F\n', C2);
|
|
fprintf('Tau1 = %.4f s, Tau2 = %.4f s\n', tau1, tau2);
|
|
|
|
% --- Visualisation des résultats ---
|
|
figure;
|
|
plot(t, V_meas, 'b', 'LineWidth', 1.5); hold on;
|
|
plot(t, V_sim, 'r--', 'LineWidth', 1.5);
|
|
xlabel('Temps (s)');
|
|
ylabel('Tension (V)');
|
|
legend('Tension mesurée', 'Tension simulée');
|
|
title('Comparaison des tensions mesurée et simulée après identification');
|
|
grid on;
|
|
|
|
figure;
|
|
plot(t, V_meas, 'b', 'LineWidth', 1.5); hold on;
|
|
plot(t, Voc, 'g--', 'LineWidth', 1.5);
|
|
plot(t, V_sim, 'r:', 'LineWidth', 1.5);
|
|
xlabel('Temps (s)');
|
|
ylabel('Tension (V)');
|
|
legend('Tension mesurée', 'Tension OCV', 'Tension simulée');
|
|
title('Décomposition des tensions simulées');
|
|
grid on;
|
|
|
|
% Calcul et affichage de l'erreur au fil du temps
|
|
figure;
|
|
plot(t, error, 'm', 'LineWidth', 1.5);
|
|
xlabel('Temps (s)');
|
|
ylabel('Erreur (V)');
|
|
title('Erreur entre la tension mesurée et simulée');
|
|
grid on;
|
|
|
|
|
|
% --- Fonction de calcul de la tension simulée ---
|
|
function V_sim = calculate_vsim(params, Voc, I, dt)
|
|
% Initialisation des tensions dynamiques
|
|
V_RC1 = 0; % Tension initiale sur RC1
|
|
V_RC2 = 0; % Tension initiale sur RC2
|
|
V_sim = zeros(size(I)); % Tension simulée
|
|
|
|
for k = 2:length(I)
|
|
% Mise à jour exponentielle pour RC1 et RC2
|
|
V_RC1 = params(2) * (1 - exp(-dt / (params(2) * params(3)))) * I(k);
|
|
V_RC2 = params(4) * (1 - exp(-dt / (params(4) * params(5)))) * I(k);
|
|
|
|
% Tension simulée
|
|
V_sim(k) = Voc(k) - params(1) * I(k) - V_RC1 - V_RC2;
|
|
end
|
|
end
|