Программирование ПЛК Siemens на Simatic Step7
Добрый день, хабровчане! Полазив по Хабру, мною было обнаружено всего несколько топиков, в котором упоминалось бы словосочетание «Simatic Step 7». Хочу поделиться с Вами небольшой частью информации, накопленной мною за все время работы с программируемыми логическими контроллерами, и показать, что из себя представляют ПЛК, оболочка и что мне приходилось на них строить.
Данный пост содержит общую ознакомительную информацию о программировании ПЛК Siemens.
Введение
Устроилась я в эту фирму еще на 5м курсе института. К слову, образование мое к программированию относится весьма косвенно и было это больше увлечением. Познания мои на тот момент ограничивались курсом Delphi и весьма базовым Ассемблером. Компания занималась (да и занимается) проектированием, строительством и обслуживанием грузоподъемных машин, таких как погрузчики, портальные, козловые, мостовые и прочие краны. К ГП машинам мое образование имело еще меньше отношения. Поэтому я решила попробовать. 🙂
Программируемые логические контроллеры Siemens
ПЛК фирмы Siemens — это промышленные контроллеры и используются для автоматизации технологических процессов. У нас, в частности, использовались для автоматизации работы грузоподъемных машин.
Simatic включает в себя несколько линеек ПЛК — Simatic S5 и Simatic S7. В свою очередь линейка Simatic S7 содержит семейства S7-200, S7-300, S7-400 и S7-1200.
Чаще всего мы использовали ПЛК семейств S7-300 и S7-400, для которых компанией Siemens было разработано собственное программное обеспечение Simatic Step 7.
Кроме этого, к ПЛК через сеть Profibus подключалось большое количество ведомых устройств, таких как частотные преобразователи, приводы, абсолютные/инкрементные энкодеры и пр.
Вся работа ГП машины по максимуму автоматизировалась и крановщику нужно применять минимум усилий для управления оной.
Что из себя представляет Simatic Step 7?
Главной утилитой является Step 7 — Simatic Manager, которая позволяет производить конфигурацию ПЛК и сетей (утилиты HWConfig и NetPro).
В процессе конфигурации определяется состав оборудования, способы подключения, используемые сети, адреса, выбираются настройки для используемых модулей. Готовая конфигурация загружается в ПЛК, что так же является настройкой оборудования.
Утилиты конфигурации позволяют осуществлять диагностику оборудования, обнаруживать аппаратные ошибки или неправильный монтаж.
ПЛК выполняет команды в порядке, определяемом программой, сверху вниз, затем начинает сначала.
С помощью редактора STL всегда можно посмотреть или отредактировать программы, созданные на LAD или FBD, обратное не всегда возможно.
Я работала с самого начала в STL, пробовала LAD, мне показался слишком непонятным и многие вещи таки не удавалась так просто в нем сделать, как в STL. Плюс еще в том, что при загрузке программы в ПЛК, она компилируется в STL и, соответственно, при выкачке ее из ПЛК на программатор она так же представлена в STL.
Вместо заключения
Программирование ПЛК занятие увлекательное, особенно когда это не стенд, а реальное оборудование.
Моя работа заключалась в создании программы на ПЛК для управления всей ГП машины либо отдельных ее частей, а так же загрузке программного обеспечения непосредственно в оборудование и его отладке.
Случалось разное, но работать с железом было очень интересно, хоть и не легко иногда.
А строили мы вот такие ГП машины:
Программирование Modbus RTU Master на примере Simatic S7-1200 и ПЧ Sinamics V20
Давно хотел рассказать про тонкости программирования обмена по протоколу Modbus RTU в случае, когда контроллер (в нашем случае S7-1214) выступает RTU Master’ом. Недавно меня попросили помочь с обменом между ПЛК и частотным преобразователем Sinamics V20, ну и почему бы не написать заодно заметку, постаравшись приблизить решение задачи к боевым условиям.
Собственно говоря, сами немцы эту тему давно осветили:
Смотрите этот пример, он сделан очень толково, с визуализацией, диалогами и квестами и возможностью расширить прикладную программу до опроса множества ПЧ V20 по нескольким интерфейсам (S7-1200 позволяет установить в свою корзину до 4 портов RS-485/422). Пример сделан очень хорошо и очень педантично. Вопросов коммуникаций по протоколу Modbus TCP я уже касался ранее, они есть на Хабре.
Поэтому некоторые нюансы я повторно объяснять не буду, просто сразу напишу, как стоит делать правильно и удобно с моей точки зрения конкретно в случае опроса V20. Первоначальная настройка преобразователя частоты описана в документации, в том числе и в сопутствующей документации к вышеуказанному примеру. Вынесем лишь важные для нас пункты в качестве вводных.
Адрес подчиненного устройства модбас в сети: 1
Параметры связи: 9600 8-Even-1
Регистры хранения подчиненного устройства для чтения:
40110 ZSW «Слово состояния»
40111 HIW «Текущая скорость»
Регистры хранения для записи:
40100 STW «Слово управления»
40101 HSW «Задание скорости»
Параметр частотника «Telegram off time (ms)» P2014[0] рекомендую оставить по умолчанию, равным в 2000 мс (2 секунды), хоть пример и рекомендует снизить эту величину до 130 мс. Конкретно к протоколу Modbus это замечание не относится, разумеется, просто у меня при таймауте в 130 мс, ПЧ терял связь и выдавал ошибку Fault 72.
С частотником разобрались. Теперь о моей конфигурации ПЛК. Это S7-1214 с коммуникационным модулем 1241 под RS-485/422:
Среда программирования Step 7 V15.1 Update 4, версия прошивки CPU — 4.3.
Итак, приступим. Для опроса подчиненных устройств с контроллера Simatic нам необходимо применить два функциональных блока: Modbus_Comm_Load (единовременно, только для конфигурации коммуникационного процессора) и Modbus_Master (циклически для чтения и/или записи регистров/катушек). Поэтому в программе экземпляр FB Modbus_Comm_Load у нас будет встречаться только один раз, а экземпляр Modbus_Master — несколько раз, но с разными входными параметрами, в зависимости от адреса подчиненного устройства, типа читаемых данных и их количества, а так же направления передачи данных (чтение или запись). Обращаю ваше внимание, что для одного коммуникационного процессора (а их в системе может быть очень много) у вас не может быть больше одного экземпляра каждого блока данных.
С моей точки зрения весь обмен удобнее завернуть в один внешний функциональный блок, а сам блок, с учетом необходимости разбирать данные, реализовать на текстовом языке SCL. Поэтому создаем в проекте функциональный блок с именем ModbusMasterV20 на языке SCL. Сразу после создания открываем его свойства и снимаем настройку «оптимизированный доступ», т.е. используем стандартный доступ. Личный опыт показал, что использование оптимизированного доступа рано или поздно приведет к ошибкам работы блока Modbus_Master и невозможности обмена. Это связано с порядком, в котором переменные идут в объявленной структуре данных, при стандартном доступе порядок соответствует заданному в программе, при оптимизированном — система сама «раскидывает» переменные, как сочтет нужным.
Объявляем следующие входные переменные
Init (Bool) — инициализация коммуникационного процессора, ее необходимо выполнить один раз перед началом обмена
PORT (PORT) — аппаратный идентификатор коммуникационного процессора
BAUD (UDINT) — скорость обмена по порту
STOP_BITS (USINT) — количество стоповых бит «кадра»
PARITY (USINT) — четность, где 0 — нет четности, 1 — odd, нечет, 2 — even, чет
В статической области переменных так же прописываем переменную с именем Step и типом UInt, она отвечает за «номер опроса» или «шаг работы алгоритма»
Так же в статической области объявляем экземпляры ФБ для работы по протоколу Modbus RTU
Строки программы, отвечающие за инициализацию обмена.
По флагу инициализации выставляем номер шага 1. Следующие строчки очень важны для работы
#instModbusCommLoad.MODE := 4; //для линии RS-485 должна быть 4!
Тут мы задаем значения статических переменных экземпляра ФБ Modbus_Comm_Load, которые отвечают за «физику» передачи. Не понимаю, почему немцы поместили эти важные конфигурационные параметры в статическую область, а не в область входов. Дело в том, что они (переменные) все описаны во встроенной справке. Беда лишь в том, что большинство ленивых жоп новичков до этого пункта справку не читает, а потом тратят несколько часов, а то и дней, пока не найдут ответ. А справка-то, вот она:
Переменная MODE отвечает за режим, в котором будет работать коммуникационный процессор. Как видно из справки, для RS-485 надо явно выставить 4. Значение по умолчанию 0, от этого большинство ошибок у программистов.
STOP_BITS — количество стоповых бит.
Далее следует вызов блока настройки коммуникационного интерфейса Modbus_Comm_Load. Про параметр PORT (аппаратный идентификатор) будет рассказано чуть ниже. Параметры BAUD и PARITY — скорость и четность — приходят на вход «внешнего» блока данных, куда мы и завернули весь обмен. А вот параметр MB_DB интересен. На этот вход надо подать структуру типа P2P_MB_BASE, которая находится в области статических переменных экземпляра функционального блока Modbus_Master. Этот экземпляр в нашем «большом» функциональном блоке уже объявлен, привожу скриншот:
Следующая часть: функциональный блок приступает к циклическому обмену.
Я сразу «заворачиваю» обмен в CASE, чтобы не переписывать код в дальнейшем, но пока мы ограничимся чтением слова состояния и скорости ПЧ, т.е. прочитаем два регистра хранения.
Давайте посмотрим на вызов блока Modbus Master повнимательнее:
Входной параметр REQ — включить опрос. Пока на входе TRUE, он выполняется, если FALSE — не выполняется. Нет необходимости подавать положительный фронт на этот вход самостоятельно (в отличии от работы Modbus RTU в системах S7-300/S7-400), поэтому я просто даю TRUE константой
MB_ADDR — адрес подчиненного устройства Modbus RTU. В моем случае адрес частотника = 1.
MODE — направление передачи данных, 0 — чтение, 1 — запись
DATA_ADDR — адрес интересуемых нас данных. В моем случае необходимо прочитать два регистра хранения (поэтому первая цифра 4), начиная со 110го. В протоколе Modbus (что RTU, что TCP) очень часто возникает путаница в понятиях «адрес» и «номер». И очень часто производитель оборудования эту путаницу добавляет в свою систему. Вот смотрите. Мы должны прочитать 2 регистра, начиная с адреса 40110. Для чтения регистров хранения в протоколе Modbus используется функция с номером 3. Именно 3 будет передаваться в телеграмме Modbus. А в качестве адреса в телеграмме будет передаваться не 40110, а 109. Связано это с тем, что код функции уже содержит описание области данных. А в самой телеграмме мы передаем не адрес, а номер требуемого регистра или катушки. И эта нумерация идет не с единицы, а с нуля. Сейчас я работаю именно с адресами и режимом (чтении или запись), поэтому мне достаточно указать то, что я нашел в документации. Если же в вашем устройстве будет указано «входной регистр номер 0 содержит текущий статус устройства», то вам на вход DATA_ADDR необходимо будет подать 30001. Так же имейте в виду, что из-за частой путаницы с номерами и адресами, иногда эта адресация съезжает на «единицу», поэтому не бойтесь экспериментировать. Если вместо полезных данных по запросу 16ого регистра вам прилетает полная чехарда, не имеющая ничего общего с документацией, прочитайте 15ый регистр. Не помогло? Опрашивайте 17ый. Более подробно с материалом необходимо ознакомиться опять же во встроенной справке.
DATA_LEN — количество читаемых регистров, их 2
DATA_PTR — указатель на область памяти, куда необходимо «положить» результат чтения регистров. Собственно, это те данные, которые мы прочитали и необходимо подсказать функциональному блоку, куда эти данные надо записать. С моей точки зрения самый удобный способ в этом случае — это объявить в области STAT неименованную структуру должного размера. Поля структуры мы объявляем, в зависимости от самих читаемых данных, ведь это могут быть и наборы бит, и вещественные числа (расположенные в двух соседних регистрах). И нам еще повезет, если порядок байт в слове и слов в двойных словах контроллера и подчиненного устройства совпадут, иначе нам еще потребуется осуществить сдвиги байт/слов.
В данном случае я счел уместным объявить структуру из двух слов и скормить ее на вход FB:
ZSW — слово состояния (так оно называется в документации на ПЧ)
HIW — скорость вращения двигателя
После вызова блока мастера, необходимо проанализировать успех или неуспех его выполнения. В принципе, на этом скриншоте в комментариях уже все написано:
В случае успешного чтения необходимо полученные сырые данные как-то разобрать или переложить в другую область, и перейти к следующему опросу (у нас пока только один опрос, так что мы остаемся на шаге №1). При ошибке чтения данных минимальный разумный ход — выставить где-нибудь флаг недостоверности и перейти к другому опросу.
Пока оставляем прием данных без обработки, компилируем и грузим программу, смотрим на результат. Кстати, обращаю еще внимание на один факт. Поскольку мы работаем, завернув системные вызовы в свой функциональный блок, то любое изменение «своего» ФБ с последующей загрузкой ПЛК, будет нарушать обмен в связи с переинициализацией экземпляра нашего ФБ. Например, будет уходить в ноль значение «шага обмена». Да и внутренние статические переменные коммуникационных вызовов тоже пострадают. Самый простой способ — стоп и старт контроллера. В боевом проекте это опасно, поэтому там на вход Init я бы подал еще одну переменную и поднимал ее самостоятельно после изменений в коммуникациях. Пока же боремся с остановом обмена простым стоп-стартом ПЛК.
Добавляем вызов нашего функционального блока в OB1 и грузим CPU:
Переменная FirstScan имеет значение «истина» при первом цикле выполнения программы OB. Она назначается операционной системой ПЛК автоматически, ее применение настраивается в свойствах CPU.
Port. Это значение смотрим в проекте Step 7, аппаратная конфигурация:
Остальные параметры касаются скорости, четности и количества стоповых бит. Загружаем контроллер и смотрим, что нам приходит в ответ на единственный циклический запрос, открыв экземпляр нашего ФБ:
В слове состояния что-то есть, скорость равна нулю. Открываем документацию и смотрим состав слова состояния ZSW:
Low enabled в примечаниях означает инверсию. К примеру, бит №15, перегрузка частотника, возникает, когда этот бит равен 0, а в нормальном состоянии приходит значение 1. Посмотрим на это слово состояния в watch table и посмотрим, какие его биты выставлены, а какие — нет, оценим общее состояние ПЧ:
Тут нам везет, порядок байт в словах совпадают. Если вкратце, то видно, что ПЧ не готов, не включен, и сейчас активен сигнал аварии (fault, бит №3).
Далее я попытался разложить слово состояния в биты состояния, заменив WORD на структуру из бит, но что-то явно пошло не так.
Если посмотреть внимательно, то в таком представлении нулевой и первый байты явно не на своих местах. В общем, вопрос порядка следования информации в зависимости от того или иного представления — он всегда важный и требует вдумчивости. Получил на этом этапе облом, я решаю вернуться к хранению внутри нашего ФБ только сырых данных, а удобочитаемый для человека формат представления информации перенести куда-нибудь во внешний глобальный блок. Добавляю в проект блок данных DataV20:
После чего задумываюсь, убираю из имен переменных окончание Inv и дописываю функциональный блок:
Теперь в глобальном блоке данных у нас находятся статусные биты преобразователя частоты без какой-либо инверсии:
Думаю, что сразу в блок данных надо вписать переменную типа Real, которая будет содержать текущие обороты двигателя. Текущие обороты приходят от ПЧ в виде определенного численного кода, и мы вольны трактовать этот код, как нам удобнее. Допустим, что хочу трактовать этот код, как Герцы, поданные на двигатель.
Пока не будем пересчитывать коды в физические величины и перейдем к следующему шагу — к записи слова управления и задания частоты. Вернемся к обработке текущей скорости чуть позже.
Обратимся к документации и посмотрим состав слова управления частотным преобразователем:
Знаете, мне, откровенно говоря, лень писать все эти переменные в глобальном интерфейсном блоке данных. В моей практике управление простыми технологическими процессами с применением преобразователей частоты ограничивалось командами включить, квитировать аварию и дать задание скорости. Поэтому, пойдем на поводу моей лени и в блоке данных V20Data пропишем всего лишь бит включить, бит квитировать и задание частоты в формате Real.
Изменю алгоритм на шаге №1, при успешном или неуспешном завершении опроса сделаю переход на шаг №2.
Добавим еще локальную структуру ФБ, которая содержит слово управления и слово задания скорости:
Дорабатываю программу обмена. Не забываем, что при изменении переменных функционального блока, после загрузки изменений в ПЛК происходит его переинициализация, посему надо выполнять стоп/старт CPU.
Параметры функционального блока модбас в данном случае отличаются от первого вызова. Разумеется, у нас тут другой адрес регистра. А так же отличается режим (MODE), он равен 1, так как в данном случае данные не читаются с частотника, а записываются в него. Разумеется, указатель на область данных так же другой.
Обратите внимание, что некоторые биты слова управления я принудительно выставляю в истину, другие — в ложь. Всего два бита управления (включить и квитировать) доступны для внешней программы. Необходимое значение бит управления я вычитал в документации примера. Разумеется, это указано и в документации на сам преобразователь частоты. Изучая исходный пример, я обратил внимание, что если частотнику отдавать «пустое» (все биты выставлены в ноль) слово управления, то это подчиненное устройство модбас возвращает ошибку Invalid data. Однако, в этом примере я пробовал слать полностью «пустое» слово управления, и V20 принимал его. Однако, некоторые биты управления, все равно, должны быть установлены. К примеру, если снять бит «Control by PLC», то запускаться ПЧ не будет. RTFM, как говорится!
Теперь пора перейти к регистру, который отвечает за задание скорости (ну и сразу же к регистру, который отображает текущую скорость). Из исходного примера я понял, что этот регистр меняет свое значение в пределах от 0 до 16384. Это же мельком нашел и в документации. Пока не будем делать никаких переводов величин, и зададим ПЧ максимальную скорость жестко прямо в программном коде.
Откроем наш блок данных DataV20 и выставим команду «пуск»:
V20 запустился и работает, судя по индикации своего экранчика, на максимальной скорости, т.е. на 50 Гц. Давайте посмотрим еще сырые данные его скорости, которые приходит по modbus.
Значит, пришло время доработать шаг №1 обмена (перевести коды скорости в герцы), ну и шаг №2 в части обратного преобразования, герцы в численное значение задания скорости. «Математика» самая простая, без проверок на достоверность и выход за диапазон, хотя все это не помешает.
После загрузки изменений откроем блок данных DataV20 и поуправляем частотником из него.
Даем задание 25 Гц, даем пуск и наблюдаем за появлением сигнала Running и текущей скоростью.
Все регистры, которые можно считать с V20, описаны в документе по ссылке.
Судя по описанию регистров, есть и другие способы управления, но нас сейчас интересует не это. В моей практике с преобразователей частоты еще частенько просили считать ток(и), напряжение(я), мощность, детализацию ошибок и т.д. Давайте последуем этой старой-доброй традиции и считаем дополнительно вот эти параметры, а так же переведем их в понятное представление:
Параметры, разумеется, могут быть любыми, но предположим, что заказчику очень хочется именно эти. Я не буду подробно описывать процесс программирования и сразу покажу результат.
В принципе, мотор маленький, крутится без нагрузки, поэтому значения похожи на достоверные. Тем не менее, задача стоит в демонстрации считывания данных, поэтому будем считать наличие хоть каких-либо «цифры» за огромный технологический прорыв. Итак, вы уже заметили, что я добавил читаемые параметры в блок данных DataV20. Дополнительно был доработан функциональный блок коммуникаций:
Читаются (mode = 0) четыре регистра хранения по адресу 40025. Результат помещается во внутренний статический массив [0..4] of WORD. Далее эти слова переводятся в формат Real и помещаются во внешний блок данных в результате несложных преобразований.
Ну, и напоследок остается проанализировать качество связи. Ведь не зря же на каждом шаге после выполнения ФБ Modbus_Master смотрю его флаги DONE или Error (кстати, эти флаги имеют значение «истина» только на протяжении одного вызова после успешного или неуспешного выполнения запросы, в остальное время — ложь). Для этого я объявил массив из булевых переменных
Массив размерностью три, по количеству запросов Modbus. Соответственно, если на шине будет 10 частотников, по три запроса к каждому, то размерность этого массива, как и количество «шагов» алгоритма, будет равно 30. Ну, и в конце каждого опроса, при анализе флагов, наконец, прописываем присвоение флагам значения.
Будем считать, что частотник стабильно обменивается информацией с ПЛК, когда все три запроса к нему выполнены успешно. Поэтому самая последняя строчка нашего функционального блока будет такой (предварительно добавим булевую переменную Connected в блоке данных DataV20):
Как и обещал, программирование промышленных контроллеров Siemens
Siemens занимает 37 процентов мирового рынка автоматизации. Сегодня существует контроллеры 300, 400, 1200, 1500 серии. 300 и 400 серии проверенные, устаревшие, надежные, контроллеры. Уже несколько лет, представители Siemens утверждают что эти серии перестанут выпускать- однако, они выпускаются и еще долго будут выпускаться(мое мнение)
Сегодня будем разбирать программирование 300 и 400 серий. Выглядят оно как на картинке сверху. Заранее оговорюсь, 300 и 400 серии программируются в среде Simatic Step 7, а 1200 и 1500 программируются в TIAPortal.(По пожеланию, кому интересно, могу сделать пост по TIA)
Непосредственно к самому программированию. Для начала нужно сконфигурировать Hardware. Что это такое? Допустим Вам требуется что то автоматизировать, и в зависимости от поставленных задач, выбираете контроллер под определенные задачи из определенной серии. У нас в примере выбран S7 315 2-DP. Иначе говоря мы говорим среде что мы будем писать программу для вот именно такого контроллера к которому по ProfiBus’у подключена децентрализованная периферия(кому нужно, могу подробно сделать отдельный пост). На картинке выше показано что у нас 315 2-DP и к нему подключено 5 корзин и в выделенной корзине, установлены модули 3 Analog Input, 2 Digital Output, 1 Analog Output, 1 CP 341(для подключения к какому устройству по RS485)
На второй картинке в папке Bloks находятся куча блоков. Существуют основные блоки OB, FB, FC, DB, DT, VT которые вы можете создать.
Даже не знаю как проще обьяснить(привет из лиги лени). Оооооочень грубо говоря, в ОВ1 построчно будет обрабатываться ваша программа. Существует ОВ1,ОВ10-17, ОВ20-23, ОВ30-38, ОВ40-47, ОВ55-57, ОВ60(Если кому надо, напишу отдельно подробно)
FB(функциональный блок)-для удобства, вы можете написать программу в функциональном блоке и вызвать его в OB1. Попробую проще обьяснить- у Вас стоит задача управления 4 одинаковыми насосами. Чтоб 4 раза не писать программу управления для каждого, просто пишите программу управления в функциональном блоке и 4 раза вызываете в OB1 и привязываете соответствующие входы и выходы.
DB- дата блоки, блоки где хранятся данные. Если Вы написали программу, где производите какие то операции над числами, Вам нужно их где то хранить. Вы и указываете номер DB и адрес в нем.
На картинке мой OB1, как вы видите, я вызываю функциональные блоки- привязываю входные ножки и указываю DB. Это сделано на языке программирования FBD(об этом позже)
Так выглядит мой функциональный блок- язык FBD
Наконец-то добрались к языкам программирования. STL, FBD, LAD- их 3
STL- это язык программирования Список операторов. Мне кажется этот язык больше похож на Ассамблер.
LAD- язык программирования для «электриков», релейные схемы(графический язык)
FBD- язык программирования для «электронщиков» блочные схемы(графический язык)
Тоже самое, только в LAD
То же самое, на FBD
Выделим основные моменты:
2) Для удобства- нужно заполнить таблицу символов(блин,вспомнил в конце поста)
Смотрите, допустим у Вас 2 насоса, которыми нужно управлять. Вы создали 2 корзины в HW, поставили модуль Analog Input(допустим для контроля вибрации в подшипниках). Когда вы в HW ставите модуль- он автоматически прописывает адреса входов(3 картина). в моем примере 448. 463. И в папке S7 Program. в следующем фото
в этой папке есть таблица символов. Открываем его.
3) Выбираете удобный для Вас язык программирования и начинаете работать
Понимаю, что все ооочень поверхностно, ну как смог.













