python

Моделирование электрической цепи

  • понедельник, 13 марта 2017 г. в 03:13:47
https://habrahabr.ru/post/323590/
  • Программирование
  • Python



В данной публикации представлена инструкция по моделированию электрической цепи методом переменных состояния.

Эта публикация для того, чтобы был на русском языке хотя бы один how2 по моделированию электрических схем этим методом. В своё время я очень много гуглил и ни разу мне не попадалось нормального материала. Все методички и учебники содержали в себе только теорию. Вдобавок ни в одном, из найденных мной материалов, не было полного цикла решения: схема⟶уравнения⟶численное решение⟶графики. Собственно, это и есть алгоритм действий.

Схема есть, теперь нужно составить уравнения, используя законы Ома и Кирхгофа.

Компонентные уравнения:

$C*\frac{d{U_{c}}}{d{t}}=i_{c}; L*\frac{d{i_{l}}}{d{t}}=U_{L}; $


$U_{1}=i_{1}*R_{1}; U_{2}=i_{2}*R_{2}; U_{3}=i_{3}*R_{3}; U_{4}=i_{4}*R_{4}; U_{1}=i_{1}*R_{1};$


Контурные уравнения:

$E-U_{L}-U_{1}=0; $


$U_{1}-U_{2}-U_{3}=0;$


$U_{3}-U_{C}-U_{4}=0;$


Узловые уравнения:

$i_{L} - i_{1} - i_{2} = 0;$


$i_{2} - i_{3} - i_{4} = 0;$


$i_{c} = i_{4};$



Теперь нужно вывести дифференциальные уравнения. Отмечу, что в этом методе за переменные состояния принято брать заряды конденсаторов и потокосцепления индуктивностей. Зная эти величины, можно вывести любые напряжения и токи узлов и ветвей. Также:
  1. Уравнения должны быть независимыми;
  2. В уравнения должны входить только переменные состояния и источников; все остальные переменные должны быть выражены через переменные состояния;
  3. В левую часть каждого уравнения должна войти первая производная из переменных состояния; в правой части не должно быть производных.


Выведем первое дифференциальное уравнение:

$U_{L}=E-U_{1};$


$U_{1}=i_{1}*R_{1}=(i_{L}-i_{2})*R_{1};$


$i_{2}=\frac{U_{2}}{R_{2}}=\frac{U_{1}}{R_{2}+R_{3}}=\frac{i_{1}*R_{1}}{R_{2}+R_{3}}$


$i_{1}=i_{L}-i_{2}=i_{L}-\frac{i_{1}*R_{1}}{R_{2}+R_{3}}⟶i_{1}=i_{L}*\frac{R_{2}+R_{3}}{R_{1}+R_{2}+R_{3}};$


$U_{L}=E-i_{L}*\frac{R_{2}+R_{3}}{R_{1}+R_{2}+R_{3}}*R_{1};$


$L*\frac{d{i_{l}}}{d{t}}=E-i_{L}*\frac{R_{2}+R_{3}}{R_{1}+R_{2}+R_{3}}*R_{1};$


Выведем второе дифференциальное уравнение:

$i_{C}=i_{4}=\frac{U_{4}}{R_{4}}=\frac{U_{3}-U_{C}}{R_{4}};$


$U_{3}=U_{1}*\frac{R_{3}}{R_{2}+R_{3}}=i_{1}*R_{1}*\frac{R_{3}}{R_{2}+R_{3}};$


$U_{3}=i_{L}*\frac{R_{2}+R_{3}}{R_{1}+R_{2}+R_{3}}*R_{1}*\frac{R_{3}}{R_{2}+R_{3}}⟶U_{3}=i_{L}*\frac{R_{1}*R_{3}}{R_{1}+R_{2}+R_{3}};$


$C*\frac{d{U_{c}}}{d{t}}=(\frac{i_{L}*R_{1}*R_{3}}{R_{1}+R_{2}+R_{3}}-U_{C})*\frac{1}{R_{4}};$



Теперь у нас есть система дифференциальных уравнений, которые можно решить численно:

$ \begin{cases} C*\frac{d{U_{c}}}{d{t}}=(\frac{i_{L}*R_{1}*R_{3}}{R_{1}+R_{2}+R_{3}}-U_{C})*\frac{1}{R_{4}}; \\ L*\frac{d{i_{l}}}{d{t}}=E-i_{L}*\frac{R_{2}+R_{3}}{R_{1}+R_{2}+R_{3}}*R_{1}; \end{cases}$



Воспользуемся методом Эйлера т.к. он самый простой и воспользуемся Python:

$X_{i}=X_{i-1} + h*\frac{d{X_{i-1}}}{d{t}}$


Программа
import numpy as np
import matplotlib.pyplot as plt

#Input voltage amplitude
AMP = 21.0

#Active components
r1 = 2000.0; r2 = 10.0; r3 = 10.0; r4 =2000.0;

#Reactive components
c=0.0001; l=0.06;

#Time components
T=0.01; t0=0.0; step=T/1000;
tf=T*10

steps=int(tf/step);

#Input voltage
def E(t):
    n=int(t/T)
    if ((t >= n*T )and(t <= n*T + T/2)):
        return AMP
    else:
        return 0.0


time = np.arange(t0, tf, step)

ul = []; il = []; uc = []; ic = []; y = [];

for i in range(0, steps, 1):
    y.append(E(time[i]))

def dIl_dt(t):
    return float((1.0/l)*(E(t) - (r2+r3)*il[int(t/step)]*r1/(r1+r2+r3)))

def dUc_dt(t):
    return float((1.0/c)*((r3*r1*il[int(t/step)]/(r1+r2+r3) - uc[int(t/step)])/r4))

#Uc
def Uc(t):
    return float((il[int(t/step)] - ic[int(t/step)])*r3 - ic[int(t/step)]*r4)
#Il
def Il(t):
    return float(((E(t)-ul[int(t/step)])*(r1*(r2+r3) + r1)/(r1*r1*(r2+r3))) + ic[int(t/step)])

#Start condition
ul.append(E(0)); il.append(0.0); uc.append(0.0); ic.append(0.0);

#Euler method
for i in range(1, steps, 1):
    il.append(il[i-1] + step*dIl_dt(time[i-1]))
    uc.append(uc[i-1] + step*dUc_dt(time[i-1]))
    ul.append(l*dIl_dt(time[i]))
    ic.append(c*dUc_dt(time[i]))

plt.figure("charts")
e = plt.subplot(311)
e.plot(time, y)
e.set_xlabel('time (s)')
e.set_ylabel('E(t), (V)', color='b')
plt.grid(True)

UL = plt.subplot(312)
UL.plot(time, ul)
UL.set_xlabel('time (s)')
UL.set_ylabel('Ul(t), (V)', color = 'b')

IL = UL.twinx()
IL.plot(time, il, 'r')
IL.set_ylabel('Il(t), (A)', color = 'r')
plt.grid(True)

UC = plt.subplot(313)
UC.plot(time, uc)
UC.set_xlabel('time (s)')
UC.set_ylabel('Uc(t), (V)', color = 'b')

IC = UC.twinx()
IC.plot(time, ic, color = 'r')
IC.set_ylabel('Ic(t), (A)', color = 'r')
plt.grid(True)

plt.show()



Результаты моделирования:


Использовать для реальных расчётов лучше другие методы решения дифур, а для получения графиков напряжений и токов элементов для самообучения достаточно и простейшего метода Эйлера. В электронике самый распространённый метод Ньютона-Рафсона- в большинстве САПР используется именно этот метод.

Из литературы советую книги Матханова П.Н. и Зевеке Г.В.
А методички всяких политехов (МГТУ, Питерский, Томский и т.п.) и подобный материал легче выкинуть, чем понять, что там написано. Здесь очень к месту крылатая фраза: «упрощять- сложно, усложнять- легко».