- •Задание на курсовое проектирование по дисциплине «Основы теории управления»
- •2 Макарова, л. Ф. Основы теории управления: конспект лекций / л. Ф. Макарова. – сПб.: сПбГти(ту). – 2015. 24
- •3 Портал Python 2.7.4 Documentation [Электронный ресурс]: Электронные данные – Режим доступа: https://docs.Python.Org 24
- •5 Портал Stack Overflow [Электронный ресурс]: Электронные данные – Режим доступа: http://stackoverflow.Com 24
- •Цель и задачи курсового проекта
- •Введение
- •1 Аналитическая часть
- •1.1 Построение лачх
- •1.2 Построение желаемой лачх
- •1.3 Построение лфчх
- •1.4 Анализ устойчивости
- •2 Практическая часть
- •2.1 Анализ передаточной функции заданного соединения звеньев
- •2.2 Построение лачх
- •2.3 Построение лфчх
- •2.4 Блок-схема алгоритма
- •2.5 Основные дисплейные фрагменты
- •Список используемых источников
- •Приложение а
- •Описание компакт диска
- •Приложение б
- •Синтез сау методом лачх
- •Синтез сау методом лачх
- •Аннотация
- •Содержание
- •1 Общие сведения о программе
- •Текст программы
1 Общие сведения о программе
Данная программа предназначена для синтеза САУ, путем построения ЛАЧХ и ЛФЧХ, выполненного при различных условиях.
Требования к техническим средствам:
персональная ЭВМ, совместимая с IBM PC/AT;
процессор Pentium-III-800 MHz;
объем оперативной памяти не менее 128 Mb;
свободное дисковое пространство не менее 5 Mb;
Требования к общесистемному программному обеспечению:
интерпретатор Python 2.7.4
графический NUI фрэймворк Kivy 1.9.1
2 СТРУКТУРА ПРОГРАММЫ
В состав программы входят модули:
модуль формирования передаточной функции
модуль построения графиков
3 НАСТРОЙКА ПРОГРАММЫ И СООБЩЕНИЯ СИСТЕМНОМУ ПРОГРАММИСТУ
3.1 Установка программы для операционной системы Microsoft Windows:
Для установки необходимо выполнить скрипт ms_setup.bat.
3.2 Установка программы для операционной системы Linux:
Для установки необходимо выполнить скрипт setup.sh. Для запуска программы необходимо вызвать в терминале frequence_response.
4 ПРОВЕРКА ПРОГРАММЫ
Проверка программного обеспечения Синтез САУ методом ЛАЧХ производилась на различных операционных системах семейства 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()
Санкт-Петербург
2015
