1 Теория автоматического управления: учеб. для вузов. В 2 ч. – Ч.1: Теория линейных систем автоматического управления / Н. А. Бабаков, А. А. Воронов [ и др. ]; под ред. А. А. Воронова. – М.: Высш. шк., 1986. – 367 с.
2 Макарова, Л. Ф. Основы теории управления: конспект лекций / Л. Ф. Макарова. – СПб.: СПбГТИ(ТУ). – 2015.
3 Портал Python 2.7.4 Documentation [Электронный ресурс]: Электронные данные – Режим доступа: https://docs.python.org
4 Портал Welсome to Kivy [Электронный ресурс]: Электронные данные – Режим доступа: https://kivy.org/docs
5 Портал Stack Overflow [Электронный ресурс]: Электронные данные – Режим доступа: https://stackoverflow.com
ПРИЛОЖЕНИЕ А
(обязательное)
ОПИСАНИЕ КОМПАКТ ДИСКА
CD с программным продуктом записан с помощью Command Line tools.
Диск содержит:
· Скрипт для установки программы
· Папку с программой
· Пояснительную записку к курсовому проекту
ПРИЛОЖЕНИЕ Б
(обязательное)
Минобрнауки России
федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
«Санкт-Петербургский государственный технологический институт
(технический университет)»
УТВЕРЖДАЮ
Зав. каф. САПР и У, проф., д.т.н.
___________ Т.Б.Чистякова
___________
Синтез САУ методом ЛАЧХ
Руководство системного программиста
ЛИСТ УТВЕРЖДЕНИЯ
460.2.030.00001-01 32 01-ЛУ
Руководитель курсового проекта
___________ Л.Ф. Макарова
___________
Исполнитель, студент
___________ А.А. Макеев
___________
Нормоконтролер
___________ Л.Ф. Макарова
___________
Продолжение приложения Б
Минобрнауки России
федеральное государственное бюджетное образовательное учреждение
высшего профессионального образования
|
«Санкт-Петербургский государственный технологический институт
(технический университет)»
УТВЕРЖДЕН
460.2.030.00001-01 32 01-ЛУ
Синтез САУ методом ЛАЧХ
Руководство системного программиста
460.2.030.00001-01 32 01
Листов
Продолжение приложения Б
460.2.030.00001-01 32 01
АННОТАЦИЯ
Настоящий документ предназначен для системного программиста как руководство по настройке конфигурации программного обеспечения синтеза САУ методом ЛАЧХ.
Документ содержит информацию об установке и настройке программы.
Продолжение приложения Б
460.2.030.00001-01 32 01
Содержание
ОБЩИЕ СВЕДЕНИЯ О ПРОГРАММЕ
СТРУКТУРА ПРОГРАММЫ
НАСТРОЙКА ПРОГРАММЫИ СООБЩЕНИЯ СИСТЕМНОМУ ПРОГРАММИСТУ
ПРОВЕРКА ПРОГРАММЫ
Продолжение приложения Б
460.2.30.01-01 2 01
ОБЩИЕ СВЕДЕНИЯ О ПРОГРАММЕ
Данная программа предназначена для синтеза САУ, путем построения ЛАЧХ и ЛФЧХ, выполненного при различных условиях.
Требования к техническим средствам:
- персональная ЭВМ, совместимая с IBM PC/AT;
- процессор Pentium-III-800 MHz;
- объем оперативной памяти не менее 128 Mb;
- свободное дисковое пространство не менее 5 Mb;
Требования к общесистемному программному обеспечению:
- интерпретатор Python 2.7.4
- графический NUI фрэймворк Kivy 1.9.1
СТРУКТУРА ПРОГРАММЫ
В состав программы входят модули:
- модуль формирования передаточной функции
- модуль построения графиков
НАСТРОЙКА ПРОГРАММЫИ СООБЩЕНИЯ СИСТЕМНОМУ ПРОГРАММИСТУ
3.1 Установка программы для операционной системы Microsoft Windows:
|
Для установки необходимо выполнить скрипт ms_setup.bat.
3.2 Установка программы для операционной системы Linux:
Для установки необходимо выполнить скрипт setup.sh. Для запуска программы необходимо вызвать в терминале frequence_response.
ПРОВЕРКА ПРОГРАММЫ
Проверка программного обеспечения Синтез САУ методом ЛАЧХ производилась на различных операционных системах семейства Linux и MS Windows. Критических сбоев обнаружено не было.
ПРИЛОЖЕНИЕ В
(обязательное)
ТЕКСТ ПРОГРАММЫ
Файл test.py
from enum import Enum
class Type(Enum):
aperiodic_first_order = -20
aperiodic_second_order = -40
oscillatory = -40
differentiating = 20
forsing_first_order = 20
forsing_second_order = 40
Файл compute.py
from math import log, atan, pi
from enum import Enum
from type import Type
class Compute:
def __init__(self, w, k=1.):
self.w = w
self.k = k
self.units = []
self.frequency_points = []
for item in w:
try:
temp = item[1].index('s**2')
a = float(item[1][:temp])
item[1] = item[1][temp+4:]
except ValueError:
a = 0
temp = item[1].index('s')
b = float(item[1][:temp])
try:
temp = item[1].rindex('+')
except ValueError:
temp = item[1].rindex('-')
c = float(item[1][temp:])
a = a / abs(c)
b = b / abs(c)
if item[0]:
self.k /= abs(c)
if a == 0:
t = b
type = Type.aperiodic_first_order
else:
t = a **.5
type = Type.oscillatory
else:
self.k *= abs(c)
if a == 0:
t = b
type = Type.forsing_first_order
else:
t = a **.5
type = Type.forsing_second_order
c = c / abs(c)
if item[0]:
self.units.append([True, a, b, c])
Продолжение приложения В
else:
self.units.append([False, a, b, c])
lg = round(log(1./t, 10), 2)
self.frequency_points.append([lg, type])
self.frequency_points.sort(key=lambda x: x[0])
def get_fi(self, omega):
fi = -90
for unit in self.units:
if unit[0]:
fi -= atan((unit[2] * omega)/(unit[1] * omega ** 2 + unit[3])) * (180/pi)
else:
fi += atan((unit[2] * omega)/(unit[1] * omega ** 2 + unit[3])) * (180/pi)
return fi
Файл __init__.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from math import log
from time import sleep
from random import uniform
from type import Type
from compute import Compute
from graph import Graph, MeshLinePlot, LinePlot
|
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock
from kivy.config import Config
from kivy.uix.screenmanager import ScreenManager, Screen
Config.set('graphics', 'width', '1920')
Config.set('graphics', 'height', '1080')
class Main(App):
def __init__(self, **kwargs):
super(Main, self).__init__(**kwargs)
self.screen_manager = ScreenManager()
self.input_screen = Screen(name='input')
self.plot_screen = Screen(name='plot')
self.main = FloatLayout()
self.main.add_widget(Label(text='Logarithmic frequency response',
pos_hint={'center_x':.5,'center_y':.93},
font_size='20sp'))
self.main.add_widget(Label(text='Logarithmic phase response',
pos_hint={'center_x':.5,'center_y':.46},
font_size='20sp'))
self.frequency_graph = Graph(
xlabel='lg w', ylabel='20lgA',
x_ticks_minor=5, x_ticks_major=.2,
y_ticks_major=10, y_grid_label=True,
x_grid_label=True, padding=10,
Продолжение приложения В
x_grid=True, y_grid=True,
xmin=-1, xmax=1,
ymin=-40, ymax=40,
size_hint=(1,.45),
pos_hint={'center_x':.5,'center_y':.7})
self.phase_graph = Graph(
xlabel='delta f', ylabel='f(w)',
x_ticks_minor=5, x_ticks_major=.2,
y_ticks_major=45,
y_grid_label=True, x_grid_label=True,
padding=10, x_grid=True, y_grid=True,
xmin=-1, xmax=1,
ymin=-270, ymax=90,
size_hint=(1,.45),
pos_hint={'center_x':.5,'center_y':.225})
self.main.add_widget(self.frequency_graph)
self.main.add_widget(self.phase_graph)
back_btn = Button(text='Back', size_hint=(.2,.04), pos_hint={'center_x':.2,'center_y':.95})
back_btn.bind(on_press=lambda x: self.go_to_input_screen(self.main))
self.main.add_widget(back_btn)
plot = MeshLinePlot(
color=[.866666667,.866666667,.866666667,.7])
plot.points = [(0, -40), (0, 40)]
self.frequency_graph.add_plot(plot)
self.plot_screen.add_widget(self.main)
self.frequency_points = []
self.phase_points = []
self.numerator = []
self.denominator = []
self.performance = []
self.max_performance_label = Label(pos_hint={'center_x':.8,'center_y':.95}, font_size='20sp')
self.main.add_widget(self.max_performance_label)
self.k = TextInput(
text='1',
hint_text='k',
size_hint=(.04,.04),
pos_hint={'center_x':.15, 'center_y':.7},
font_size='22sp'
)
for i in range(7):
if i == 0:
self.numerator.append(
TextInput(
text='15s+5',
size_hint=(.1,.04), font_size='22sp',
pos_hint={'center_x':.225, 'center_y':.725})
)
self.denominator.append(
TextInput(
text='30s+3',
size_hint=(.1,.04), font_size='22sp',
pos_hint={'center_x':.225, 'center_y':.675})
)
elif i == 1:
self.numerator.append(
TextInput(
text='30s-30',
size_hint=(.1,.04), font_size='22sp',
pos_hint={'center_x':.225+i/9.8, 'center_y':.725})
Продолжение приложения В
)
self.denominator.append(
TextInput(
text='.45s**2+2.4s+5',
size_hint=(.1,.04), font_size='22sp',
pos_hint={'center_x':.225+i/9.8, 'center_y':.675})
)
else:
self.numerator.append(
TextInput(
size_hint=(.1,.04),
pos_hint={'center_x':.225+i/9.8, 'center_y':725},
font_size='22sp')
)
self.denominator.append(
TextInput(
size_hint=(.1,.04),
pos_hint={'center_x':.225+i/9.8, 'center_y':675},
font_size='22sp')
)
def draw_max_performance(self):
self.max_performance_label.text = 'Max cut-off frequency (W c) is %f' % max(self.performance)
def go_to_input_screen(self, main):
self.frequency_points = []
self.phase_points = []
self.screen_manager.current = 'input'
def go_to_plot_screen(self):
self.color_a = uniform(0, 1)
self.color_b = uniform(0, 1)
self.color_c = uniform(0, 1)
self.plot_layout()
self.screen_manager.current = 'plot'
def get_a(self, x1,y1,x2,y2):
return (y2-y1)/(x2-x1)
def get_b(self, x1,y1,x2,y2):
return (x2*y1-x1*y2)/(x2-x1)
def add_new_points(self):
w = []
for item in self.numerator:
if item.text!= '':
w.append([False, item.text])
for item in self.denominator:
if item.text!= '':
w.append([True, item.text])
k = float(self.k.text)
t =.1
c = Compute(w,k=k)
values = c.frequency
n = log(c.k, 10.0)
k = 20 * n
xmin = values[0][0] - 1.0
xmax = values[len(values) - 1][0] + 3.0
ymin = - k * 1.5
ymax = k * 1.5 +.1
def plot_layout(self):
w = []
for item in self.numerator:
if item.text!= '':
w.append([False, item.text])
for item in self.denominator:
Продолжение приложения В
if item.text!= '':
w.append([True, item.text])
k = float(self.k.text)
t =.1
c = Compute(w,k=k)
values = c.frequency_points
n = log(c.k, 10.0)
k = 20 * n
xmin = values[0][0] - 1.0
xmax = values[len(values) - 1][0] + 3.0
ymin = - k * 1.5
ymax = k * 1.5 +.1
if xmin < self.frequency_graph.xmin:
self.frequency_graph.xmin = xmin
self.phase_graph.xmin = xmin
if xmax > self.frequency_graph.xmin:
self.frequency_graph.xmax = xmax
self.phase_graph.xmax = xmax
plot = MeshLinePlot(
color=[.866666667,.866666667,.866666667,.7])
plot.points = [(xmin, 0), (xmax, 0)]
self.frequency_graph.add_plot(plot)
for item in values:
plot = LinePlot(
line_width=1, color=[.38,.67,.54, 1])
plot.points = [(item[0], -40), (item[0], 40)]
self.frequency_graph.add_plot(plot)
frequency_plot = LinePlot(
line_width=2, color=[self.color_a, self.color_b, self.color_c, 1])
points = []
points.append([xmin, k])
points.append([values[0][0], k])
self.frequency_graph.add_plot(frequency_plot)
incline = 0
current_ordinate = k
for i in range(len(values)):
incline = incline + values[i][1].value
if i!= len(values) - 1:
current_ordinate = current_ordinate + incline * (values[i+1][0] - values[i][0])
points.append([values[i + 1][0], current_ordinate])
else:
points.append([values[i][0] + 3, incline])
for i in range(len(points) - 1):
a = self.get_a(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1])
b = self.get_b(points[i][0], points[i][1], points[i + 1][0], points[i + 1][1])
for i in range(int(points[i][0] * 100), int(points[i + 1][0] * 100)):
self.frequency_points.append([i / 100., a * (i / 100.) + b])
for i in range(-180, 90, 90):
phase_plot = LinePlot(
line_width=1, color=[.93,.46, 0,.7])
phase_plot.points = [(xmin, i), (xmax, i)]
self.phase_graph.add_plot(phase_plot)
phase_plot = LinePlot(
line_width=2, color=[self.color_a, self.color_b, self.color_c, 1])
Продолжение приложения В
for i in range(int(xmin * 100), int(xmax * 100), 1):
self.phase_points.append([i / 100., c.get_fi(i / 100.)])
self.phase_graph.add_plot(phase_plot)
Clock.schedule_once(lambda x: self.draw_phase(phase_plot),.5)
Clock.schedule_once(lambda x: self.draw_frequency(frequency_plot),.5)
def draw_frequency(self, plot):
if len(self.frequency_points) == 0:
self.performance.append(self.temp)
self.draw_max_performance()
return
if int(self.frequency_points[0][1]) == 0:
self.temp = self.frequency_points[0][0]
plot.points = plot.points + [(self.frequency_points[0][0], self.frequency_points[0][1])]
del self.frequency_points[0]
Clock.schedule_once(lambda x: self.draw_frequency(plot))
def draw_phase(self, plot):
if len(self.phase_points) == 0:
return
plot.points = plot.points + [(self.phase_points[0][0], self.phase_points[0][1])]
del self.phase_points[0]
Clock.schedule_once(lambda x: self.draw_phase(plot))
def input_layout(self):
layout = FloatLayout()
layout.add_widget(Label(text='W(s) = ', pos_hint={'center_x':.1, 'center_y':.7}, font_size='30sp'))
layout.add_widget(self.k)
add_to_numerator_btn = Button(text='Add new W to numerator', size_hint=(.15,.05), pos_hint={'center_x':.2, 'center_y':.25})
add_to_numerator_btn.bind(on_press=lambda x: self.add_widget_to_numerator())
remove_from_numerator_btn = Button(text='Remove last from numerator', size_hint=(.15,.05), pos_hint={'center_x':.2, 'center_y':.19})
remove_from_numerator_btn.bind(on_press=lambda x: self.remove_widget_from_numerator())
layout.add_widget(add_to_numerator_btn)
layout.add_widget(remove_from_numerator_btn)
add_to_denominator_btn = Button(text='Add new W to denominator', size_hint=(.15,.05), pos_hint={'center_x':.36, 'center_y':.25})
add_to_denominator_btn.bind(on_press=lambda x: self.add_widget_to_denominator())
remove_from_denominator_btn = Button(text='Remove last from denominator', size_hint=(.15,.05), pos_hint={'center_x':.36, 'center_y':.19})
remove_from_denominator_btn.bind(on_press=lambda x: self.remove_widget_from_denominator())
layout.add_widget(add_to_denominator_btn)
layout.add_widget(remove_from_denominator_btn)
continue_btn = Button(text='Continue', size_hint=(.15,.11), pos_hint={'center_x':.52, 'center_y':.22})
continue_btn.bind(on_press=lambda x: self.go_to_plot_screen())
layout.add_widget(continue_btn)
for item in self.numerator:
layout.add_widget(item)
for item in self.denominator:
layout.add_widget(item)
return layout
def build(self):
self.input_screen.add_widget(self.input_layout())
self.screen_manager.add_widget(self.input_screen)
self.screen_manager.add_widget(self.plot_screen)
return self.screen_manager
Продолжение приложения В
def add_widget_to_numerator(self):
for item in self.numerator:
if item.pos_hint['center_y']!=.725:
item.pos_hint = {'center_y':.725}
return
def add_widget_to_denominator(self):
for item in self.denominator:
if item.pos_hint['center_y']!=.675:
item.pos_hint = {'center_y':.675}
return
def remove_widget_from_numerator(self):
for item in reversed(self.numerator):
if item.pos_hint['center_y']!= 725:
item.pos_hint = {'center_y':725}
item.text = ''
return
def remove_widget_from_denominator(self):
for item in reversed(self.denominator):
if item.pos_hint['center_y']!= 675:
item.pos_hint = {'center_y':675}
item.text = ''
return
if __name__ == '__main__':
Main().run()