воскресенье, 12 апреля 2015 г.

Первая программа с PyQt5

Изучение любой библиотеки начинается с первой рабочей тестовой программы, но к сожалению зачастую первая такая программа описанная в документации, оказывается нерабочей. Из-за этого всегда тратится много времени на первую болванку.

Теперь приступим к первому тесту, то есть напишем программу, которая будет просто считать количество нажатий на кнопку.
Для этого создадим в Qt Designer вот такую форму:



Напишем следующую программку:
import sys
from PyQt5 import QtCore, QtGui, uic
from PyQt5.QtWidgets import *

# прототип главной формы
class MainForm(QMainWindow):
    cnt = 0
    # конструктор
    def __init__(self):
        super(MainForm, self).__init__()

        # динамически загружает визуальное представление формы
        uic.loadUi("gui.ui", self)

        # связывает событие нажатия на кнопку с методом
        self.pushButton.clicked.connect(self.setLabelText)

        self.show()

    def setLabelText(self):
        self.cnt += 1
        self.pushButton.setText(str(self.cnt))




def main():
    app = QApplication(sys.argv)  # создаёт основной объект программы
    form = MainForm()  # создаёт объект формы
    app.exec()  # запускает приложение

if __name__ == "__main__":
    sys.exit(main())
Примечание 1: Qt Designer  содержит три вида шаблонов: QMainWindow, QDialog, QWidget для правильной работы тип используемого шаблона и объекта к которому привязываем графику, должны соответствовать друг другу.

Примечания 2: для обращения к элементу формы используем его имя заданное в Qt Designer.

среда, 18 марта 2015 г.

Siemens S7-200 первое подключение

По ходу рабочей деятельности попал мне в руки ПЛК фирмы Siemens S7-200. И так как совсем недавно я вышел со студенческой скамьи и опыта работы с железом толком не было, долго и упорно пытался его подключить, чтобы залить на него тестовую программу.
Для первого подключения необходимы следующие аппаратные части:
 - USB PC adapter MPI;
 - контроллер Siemens S7-200;
 - ноутбук.
Из программного обеспечения потребуется Step 7-Micro/Win.
Далее рассмотрим действия по шагам:

  1. Запустить Step 7-Micro/Win.
  2. В левом столбце в самом низу открываем диалоговое окно "Set PG/PC interface".
  3. Из списка "Interface Parameter Assignment Used" выбираем "PC Adapter (PPI)".
  4. Нажимаем кнопку "Properties". После нажатия увидим диалоговое окно "Properties - PC Adapter (PPI)".
    Примечание: на это окно стоит обратить особое внимание, так как если скорость передачи данных "Transmition Rate" будет не соответствовать скорости передачи данных контроллера, то компьютер просто не увидит контроллер.
  5. Далее жмем "Ok" и открываем диалоговое окно "Communications" (левый столбец с иконками).
  6. Далее выполняем двойной нажатие левой клавишей мыши по иконке "Double-Click to Refresh". После чего, если была правильно выбрана скорость, мы увидим наш контроллер.
После всех вышеописанных действий, можно заливать программу и конфигурацию в контроллер через кабель "USB PC Adapter MPI".

Для того, чтобы увеличить или уменьшить скорость передачи данных контроллера, необходимо выполнить следующие действия:
  1. В дереве проекта в разделе "Communications" открыть диалоговое окно "Communication Ports".
  2. В полях ввода "Baud Rate" указать интересующую скорость.
  3. Изменить значение скорости передачи данных "Transmition Rate" в свойствах "PC Adapter MPI" (см. выше).
После всех выполненных операций можно сохранить проект, чтобы в дальнейшем не производить вышеуказанные настройки повторно.
Примечание: если при загрузке программы произойдет сбой, то необходимо снова выполнить поиск устройств подключенных к кабелю "USB PC Adapter MPI", то есть выполнить двойное нажатие левой клавишей мыши по иконке "Double-Click to Refresh" в диалоговом окне "Communications".

воскресенье, 7 декабря 2014 г.

Вспоминая Step 7

Задание:
Создать программу реализующую следующую функцию: если заканчиваются детали в магазине (эмулировать дискретный сигнал в симуляторе), то срабатывает сирена (мигает лампа) с частотой 2 Гц. Сброс сирены после удержания кнопки сброса в течение 3 с.

Решение:
Для начала опишем используемые переменные:
 - нет деталей в магазине (дискретный вход);
 - сброс (дискретный вход);
 - таймер сирены для положительной фазы генератора импульсов;
 - таймер сирены для отрицательной фазы генератора импульсов;
 - таймер сброса;
 - сигнал отключения сирены;
 - сирена (дискретный выход).

Повторим какие типы данных поддерживает Step 7:


Для описания переменных в проекте Step 7 Manager откроем S7 Program(1):
Окно SIMATIC Manager
и далее откроем таблицу символов Symbols и отредактируем как показано на рисунке ниже:
Таблица символов STEP 7
Теперь реализуем сирену на языке LAD:
Блок реализации сирены
на рисунке выше два таймера объединены в генератор импульсов и тем самым сигнал меняется периодически.
Далее покажем, как реализуется сброс сирены:
После всех выполненных действий сохраняем программу и загружаем в контроллер. Задание выполнено.
Демонстрация работы программы в режиме симуляции:





среда, 12 марта 2014 г.

Заметки по Python

Заметка №1

Порой требуется, найти минимальные и максимальные значения списка вот такого списка:
>>> a[[5, 6], [7, 8], [-3, -10], [6, 12], [-4, 10]]
 Предположим, что это список координат точек, и требуется найти Xmax, Ymax, Xmin, Ymin. К сожалению, я не нашел более удобного способа сделать это в 1 строку, но вот способ в 2 строки.
>>> [X, Y] = zip(*a)>>> (Xmax, Ymax, Xmin, Ymin) = (max(X), max(Y), min(X), min(Y))
 Здесь я использовал распаковку списка, что позволит, нам посмотреть по отдельности максимальные и минимальные значения X и Y.
Теперь проверим правильность результатов:
>>> Xmax
7
>>> Ymax
12
>>> Xmin
-4
>>> Ymin
-10
Как видим результат соответствует желаемому.

вторник, 4 марта 2014 г.

unittest'ы в Python примеры использования на будущее

Не люблю долго описывать, то чем пользуюсь, ибо мне понятнее примеры, и поэтому зачастую пользуюсь старыми исходниками. Но так как были инциденты потери данных решил сохранить, важные разделы здесь.
Файл geometry.py
#coding=utf-8
# -*- coding: utf-8 -*-

from math import *
import sys

class point:
  def __init__(self, x, y):
    self.x = float(x)
    self.y = float(y)
    
  def __str__(self):
    return '({0}, {1})'.format(self.x, self.y)
  
  def __eq__(self, other):
    return True if ((self.x == other.x) and (self.y == other.y)) else False
  
  def __ne__(self, other):
    return True if ((self.x != other.x) or (self.y != other.y)) else False

Файл тестирования test_geometry.py:
#coding=utf-8
# -*- coding: utf-8 -*-

from geometry import *
import unittest

class testGeometry(unittest.TestCase):
  # Создадим 4 точки, которые будем использовать для тестирования
  def setUp(self):
    self.A = point(5, 6)
    self.B = point(6, 10)
    self.C = point(5.0, 6.0)
    self.D = point(-5, -6)

  # Тестируем создание точки
  def test_init(self):
    # Проверим правильность получения координат
    self.assertEqual((self.A.x, self.A.y), (float(5), float(6)), "Полученные значения не являются вещественными!!!")
    self.assertEqual((self.B.x, self.B.y), (float(6), float(10)), "Полученные значения не являются вещественными!!!")
    self.assertEqual((self.C.x, self.C.y), (float(5), float(6)), "Полученные значения не являются вещественными!!!")
    self.assertEqual((self.D.x, self.D.y), (float(-5), float(-6)), "Полученные значения не являются вещественными!!!")

  # Тестируем правильность формата печати
  def test_str(self):
    self.assertTrue(str(self.A) == "(5.0, 6.0)", "Неправильный вывод на экран!!!")
    self.assertTrue(str(self.B) == "(6.0, 10.0)", "Неправильный вывод на экран!!!")
    self.assertTrue(str(self.C) == "(5.0, 6.0)", "Неправильный вывод на экран!!!")
    self.assertTrue(str(self.D) == "(-5.0, -6.0)", "Неправильный вывод на экран!!!")

  # Тестируем операцию равенства
  def test_eq(self):
    self.assertTrue(self.A == self.C, "Данные две точки равны, а в результате тестирования, они оказались неравными!!!")
    self.assertFalse(self.A == self.B, "Данные две точки неравны, а в результате тестирования, они оказались равными!!!")
    self.assertFalse(self.A == self.D, "Данные две точки неравны, а в результате тестирования, они оказались равными!!!")
  
  def test_ne(self):
    self.assertFalse(self.A != self.C, "Данные две точки равны, а в результате тестирования, они оказались неравными!!!")
    self.assertTrue(self.A != self.B, "Данные две точки неравны, а в результате тестирования, они оказались равными!!!")
    self.assertTrue(self.A != self.D, "Данные две точки неравны, а в результате тестирования, они оказались равными!!!")

# Запускаем тестирование, если файл запущен без аргументов
if __name__ == '__main__':
    unittest.main()
Данных примеров лично мне хватит для большинства целей, если честно я даже понять не могу зачем нужны функции assertEqual и assertNotEqual, если есть  accertTrue и assertFalse, хотя на вкус и цвет фломастеров нет.
******************
Наткнулся на еще один интересный момент, если хочется проверить, отработку, какого-либо исключения, придется повыеживаться. Приведу пример.
Тестируемый код:
class segment:
  def __init__(self, point0, point1):
    if point0 == point1:
      raise(NameError("Это не отрезок, это точка!!!"))
    else:
      self.begin = point0
      self.end = point1
Тестирование:
# Проверим инициализацию отрезков
    try:
      self.AC = segment(self.A, self.C)
    except:
      self.assertTrue(True, "Не возникает ошибки при задании точки вместо отрезка!")
Далее, если наткнусь на интересные аспекты, дополню раздел.






четверг, 6 февраля 2014 г.

Трудности с черновой обработкой

Порой, очень сложно, что-либо понять сразу, и только после этого начинаешь вести записи, чтобы понять себя, и разгрести всю кашу, которая в голове образовалась.
Сейчас я пишу диплом на Python'е, и столкнулся с такой пренеприятной сложностью: я понять не могу, как будет работать мой алгоритм.
С одной стороны в голове я выстроил план:

  1. Выделить участки контуров пересекающих канал черновой обработки.
  2. Проанализировать их, для того, чтобы понять откуда должна будет прийти фреза для черновой обработки (справа или слева по каналу), а в дальнейшем этот анализ будет использоваться и для чистовой обработки, но если для чистовой обработки достаточно знать внутренний это контур или внешний, то для чистовой обработки, нужно точно знать справа или слева ждать фрезу и это конкретно усложняет задачу.
    Также проблему представляет сортировка. как сортировать эти участки.
  3. Если все-таки получится придумать пункт 2, то нужно будет придумать способ определения положения центра фрезы при приближении к участку, для этих целей есть учебник аналитической геометрии.

понедельник, 30 декабря 2013 г.

Непонятная ошибка eskdx

Порой сталкиваешься с ошибкой и понять не можешь, как же ее решить, или если решил проблему, то почему она решилась, и что ты сделал такого для ее решения?
Для меня такой ошибкой явилась следующая ошибка интерпретатора latex:
! Undefined control sequence.
\ESKDcolumnXVIname ->\No 
                         \ \cyrp \cyro \cyrd \cyrl .
l.9 \begin{document}
 Честно сказать сам не знаю почему, но при замене в файле eskdrussian.def из пакета eskdx строчек:
\newcommand{\ESKDcolumnXVIname}{%
  \No\ \cyr\cyrd\cyro\cyrk\cyru\cyrm.}
 на
\newcommand{\ESKDcolumnXVIname}{%
  \cyr\CYRL\cyri\cyrs\cyrt}
 Вторую строчку я взял из вышеприведенной в файле операции \newcommand.
\newcommand{\ESKDcolumnXVname}{%
  \cyr\CYRL\cyri\cyrs\cyrt}
\newcommand{\ESKDcolumnXVIname}{%
  \cyr\CYRL\cyri\cyrs\cyrt}
Как ни странно, но заработало. Разницы в документах я не заметил и лично у меня вопрос, почему проблема решилась? Да и вообще почему она возникла после обновления дистрибутива?
*******************************************************************************************************
Благодаря jamesjames7 я узнал, что причина в том, что поддержка \No (символ №) убрана из babel и вместо него теперь используется \textnumero.
По совету jamesjames7 посетил сайт, где описывается решение проблемы.
Вариант с глобальной заменой у меня почему-то не заработал. Но и файл оказался по другому адресу:
/usr/share/texlive/texmf-dist/tex/generic/babel-russian/russianb.ldf
Вставлял в конец файла строчку:
\DeclareRobustCommand{\No}{\ifmmode{\nfss@text{\textnumero}}\else\textnumero\fi}
Зато вставка строчки:
\newcommand{\No}{\textnumero}
в eskdrussian.def помогла, за что jamesjames7 огромное человеческое спасибо. :)