plcforum.uz.ua

International PLC Forum
It is currently Fri Oct 19, 2018 11:05 pm

All times are UTC + 3 hours


Forum rules


Please click here to view the forum rules



Post new topic Reply to topic  [ 23 posts ] 
Author Message
PostPosted: Mon Sep 17, 2018 12:17 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
Здравствуйте.
На заводе есть линия - ПЛК S7-300, панель Siemens и частотник ABB 880. Сеть - PROFIBUS.
Стали возникать проблемы, начал искать их корень в проекте. Исходника нет, слил из контроллера. Без комментариев соответственно. Шел-шел и дошел до FC на STL. В остальных местах язык инструкций тоже встречался, но там было как-то легче, разбирался. а тут уперся и все, не могу пройти дальше. Поэтому прошу помощи. Функция довольно большая, поэтому выкладывать весь код не буду. Напишу несколько мест, которые меня больше всего интересуют, если надо больше информации - предоставлю.
Итак
Code:
A     L     52.3
      L     B [AR1,P#8.0]
      L     B#16#46
      =     L     52.3
      ==I   
      A     L     52.3
      O     L     52.2
      JCN   M001

меня интересует то, что происходит в позиции M001. Если я правильно понял, чтобы в нее попасть, нужно, чтобы L52.3 оказалось ложью. А для этого надо, чтобы B [AR1,P#8.0] стало НЕравно 16#46.
Так вот не понимаю, как формируется и откуда берется B [AR1,P#8.0]

Есть в этой функции еще строки
Code:
L     P##IN0
      LAR1 
      L     W [AR1,P#0.0]
      T     LW    54
      OPN   DB [LW 54]
      L     D [AR1,P#2.0]
      LAR1 

мне кажется из них потом формируется B [AR1,P#8.0], но я вообще не понимаю эти инструкции во втором куске кода.
Очень жду советов!


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 1:27 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
Похоже, что это было написано на SCL.
Ну, если я не ошибаюсь, первый кусок работает примерно так: if (not(B [AR1,P#8.0] <> B#16#46)and(L52.3)or(L52.2)), то прыжок.
Второй кусок:
Code:
L     P##IN0          //Загружается адрес входа #IN0
      LAR1                      //Помещается в AR1
      L     W [AR1,P#0.0]  //Считывается значение типа ВОРД из #IN0
      T     LW    54           //Помещается в LW    54
      OPN   DB [LW 54]      //Открывается DB номер [LW    54] (#IN0)
      L     D [AR1,P#2.0]    //Считывается значение типа DВОРД по адресу AR1 + 2 байта
      LAR1                       //Помещается в AR1
 


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 2:05 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
Usver, хорошо, спасибо. Неясно как работает указатель p#
Перепишу код с комментариями и еще добавлю своих
Code:
L     P##IN0          //Загружается адрес входа #IN0. При вызове IN0 = DB10.DBX0.0
         LAR1                      //Помещается в AR1. Т.е. в AR1 лежит DB10.DBX0.0?
         L     W [AR1,P#0.0]  //Считывается значение типа ВОРД из #IN0
         T     LW    54           //Помещается в LW    54. я не знаю почему, но если мониторить значения онлайн, то в LW лежит "10"
         OPN   DB [LW 54]      //Открывается DB номер [LW    54] (#IN0). Открываем DB10?...
         L     D [AR1,P#2.0]    //Считывается значение типа DВОРД по адресу AR1 + 2 байта. это получается DB10.DBD2?
         LAR1                       //Помещается в AR1
 


Вопросы собственно в комментариях к коду. интуитивно понял, что это дело вращается вокруг DB10. этот блок данных, во-первых, не формируется в программе. не считая DB10.DBX55.0
Во-вторых, его содержимое - массив из 9 переменных CHAR, потом массив 14 переменных CHAR, потом строка из элементов первого массива, потом строка из эл-ов 2-ого массива, потом один логический бит. зачем там какие-то Char-ы...


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 2:36 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
Quote:
При вызове IN0 = DB10.DBX0.0

Хотите сказать, что IN0 типа BOOL? Напишите интерфейс функции.
Quote:
я не знаю почему, но если мониторить значения онлайн, то в LW лежит "10"

в онлайне смотрели в представлении НЕХ или десятичный?
Quote:
Неясно как работает указатель p#

в каком месте неясно?


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 2:49 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
Quote:
в каком месте неясно?

стало ясно после прочтения документа по STL.
Quote:
в онлайне смотрели в представлении НЕХ или десятичный?

пойду еще смотреть. но вроде десятичный скорее.
Quote:
Хотите сказать, что IN0 типа BOOL? Напишите интерфейс функции

нет. IN0 есть array [0..8] of char.

DB10 имеет такой вид:
0.0 array [0..8] of char
10.0 array [0..14] of char
26.0 string[9]
38.0 string [15]
55.0 bool

откуда после массивов берутся по лишнему байту? как я считаю, второй массив должен занимать адрес начиная с 9.0...


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 3:20 pm 

Joined: Wed Oct 13, 2010 11:44 am
Posts: 232
Location: Russian Federation
IN0 у тебя является указателем, на что намекает инструкция L P##IN0.
Чтобы работать с указателем, надо его закинуть в AR1.
Дальше читаем хелп, что есть указатель и из чего состоит.
Команда L W [AR1,P#0.0] берет слово из указателя по смещению 0, где (внезапно!) лежит № DB.
А команда L D [AR1,P#2.0] берет двойное слово по смещению 2, которое само является внутризонным указателем. Поэтому его снова кидаем в AR1.

Поэтому, в итоге, при вызове с IN0 = DB10.DBX0.0 ты получаешь LW54 = 10, а двойное слово будет D#16#8400 0000. Если же DB10 является инстансной для FB, то D#16#8500 0000.
Открыв полученный номер DB в OPN DB [LW 54] и загнав внутризонный указатель в AR1, они получили возможность обращаться к элементам внутри DB по индексу: L x [AR1, P#y.z].

Раз у вас первым в DB лежит массив CHAR'ов от 0 до 8, то как раз последний символ (L B [AR1,P#8.0] они проверяют на код 46, т.е. "F". Почему и зачем - вам виднее....


Last edited by Rex2701 on Mon Sep 17, 2018 3:37 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 3:24 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
ну в целом понял. после второй команды LAR мы начинаем работать с DB10, но не с начала, а с байта 2.0 кмк.
В любом случае это печально, потому что я не вижу, чтобы DB10 (он блок с данными, НЕ экземпляр) где-то явно формировался. поэтому дальнейшие изыскания малоперспективны.
спасибо.


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 3:39 pm 

Joined: Wed Oct 13, 2010 11:44 am
Posts: 232
Location: Russian Federation
franzferdinand wrote:
откуда после массивов берутся по лишнему байту? как я считаю, второй массив должен занимать адрес начиная с 9.0...

STEP7 все разнородные данные выравнивает на границу слова, т.е. четные адреса.


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 4:15 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
ну так-то IN0 не может быть DB10.DBX0.0. Вызов функции д.б.
Code:
call fc number
IN0 = P#DB10.DBX0.0 BYTE 9
...

Поэтому номер ДБ для открытия лежит по адресу DB10.DBW0.
Quote:
Вопросы собственно в комментариях к коду. интуитивно понял, что это дело вращается вокруг DB10. этот блок данных, во-первых, не формируется в программе. не считая DB10.DBX55.0

Об этом Вы не можете знать наверняка, т.к. работа с DB10 может быть организована также, как и в этой ф-ции.


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 4:22 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
franzferdinand wrote:
ну в целом понял. после второй команды LAR мы начинаем работать с DB10, но не с начала, а с байта 2.0 кмк.
В любом случае это печально, потому что я не вижу, чтобы DB10 (он блок с данными, НЕ экземпляр) где-то явно формировался. поэтому дальнейшие изыскания малоперспективны.
спасибо.

разумеется малоперспективны, если программа большая.


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 4:57 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
Usver wrote:
ну так-то IN0 не может быть DB10.DBX0.0. Вызов функции д.б..
Code:
call fc number
IN0 = P#DB10.DBX0.0 BYTE 9
...

и тем не менее вызов именно такой: IN0 := P#DB10.DBX0.0
без BYTE 9


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 5:27 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
Quote:
и тем не менее вызов именно такой: IN0 := P#DB10.DBX0.0
без BYTE 9

ну верится с трудом, т.к.
franzferdinand wrote:
IN0 есть array [0..8] of char.

DB10 имеет такой вид:
0.0 array [0..8] of char
10.0 array [0..14] of char
26.0 string[9]
38.0 string [15]
55.0 bool
, а P#DB10.DBX0.0 это адрес откуда брать (это не равносильно DB10.DBX0.0), а дальше должно указываться количество байт. Вы курсором в степе кликните по этому месту может появится продолжение.
Ну тем не менее адрес для открытия ДБ должен находится в DB10.DBW0. И если это 10, то Указатель на адрес для работы с этой ДБ должен находиться по адресу DB10.DBD2.


Top
 Profile  
 
PostPosted: Mon Sep 17, 2018 8:46 pm 

Joined: Wed Oct 13, 2010 11:44 am
Posts: 232
Location: Russian Federation
POINTER не может содержать количество данных, для этого есть ANY.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 6:33 am 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
Rex2701 wrote:
POINTER не может содержать количество данных, для этого есть ANY.

Сегодня проверил на степе, да запись действительно такая, как POINTER. Но тем не менее на вход должен передаваться массив array [0..8] of char.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 1:56 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
Usver, вероятно указатель лишь указал функции точку, с которой начинать отсчет, а она, основываясь на своем интерфейсе, взяла нужное количество данных?
в любом случае я Вам предоставил 100% точную информацию по программе.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 2:07 pm 

Joined: Wed Oct 13, 2010 11:44 am
Posts: 232
Location: Russian Federation
Usver wrote:
Rex2701 wrote:
POINTER не может содержать количество данных, для этого есть ANY.

Сегодня проверил на степе, да запись действительно такая, как POINTER. Но тем не менее на вход должен передаваться массив array [0..8] of char.

Вы определённо не понимаете специфику Simatic - через входы-выходы нельзя передавать ничего кроме элементарных типов данных. И чтобы работать с массивами и структурами - придумали указатели POINTER и ANY, чтобы работать с ними косвенно "по удалёнке". Поэтому ваша функция получив указатель, работает с массивом поэлементно через AR1 + смещение.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 2:28 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
franzferdinand wrote:
Usver, вероятно указатель лишь указал функции точку, с которой начинать отсчет, а она, основываясь на своем интерфейсе, взяла нужное количество данных?

Ну тут не совсем так. Если Вы создадите новый проект и в нем сделаете FC, у которого IN0 будет array [0..8] of char, сделаете такой же DB10 и в вызове функции напишите
Code:
call fc number
IN0 = P#DB10.DBX0.0
, то увидите что P#DB10.DBX0.0 подсветится красным цветом. В информации об ошибке будет сказано, что тип POINTER не может использоваться для вызова этой FC, т.к. IN0 - это ARRAY. А если DB10 дать имя (допустим "QWE") и дать имя массиву в этой ДБ (допустим "rty") и в вызове написать IN0 = "QWE".rty, тогда все будет нормально. И в коментарии увидите P#DB10.DBX0.0. Я пару лет назад с таким сталкивался, тогда у меня на входе было UDT.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 5:08 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
Rex2701 wrote:
Вы определённо не понимаете специфику Simatic
Ну на счет определенно или нет, наверно Вам виднее. Но все равно передается МАССИВ. Разумеется он передается через указатель, но передается именно он. (Если не верите, возьмите и сами попробуйте.) Другое дело, если Вы будете писать вызов этой функции с параметром IN0 = P#DB10.DBX0.0, то вряд ли получится (для степа на данном этапе P#DB10.DBX0.0 - ПОИНТЕР и информации о типе, т.е. что находится по этому адресу он не знает. Я тут не причем.) . А вот если бы можно было так :IN0 = P#DB10.DBX0.0 AS ARRAY [0..8] OF CHAR ... Да к сожалению такой записи не может быть.
Ну запамятовал как вызываются такие функции, ну с кем не бывает?
Rex2701 wrote:
через входы-выходы нельзя передавать ничего кроме элементарных типов данных

Если я не ошибаюсь, это у Бергера написано. Читали когда-то. Давненько правда, но читали.
Rex2701 wrote:
И чтобы работать с массивами и структурами - придумали указатели POINTER и ANY, чтобы работать с ними косвенно "по удалёнке"
Ну так этот принцип давно был придуман, и что-то я так подозреваю, что придуман он был не в Сименсе.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 7:28 pm 

Joined: Tue Dec 26, 2006 8:21 am
Posts: 561
Location: Russia
Пипец, кино и немцы.


Top
 Profile  
 
PostPosted: Tue Sep 18, 2018 7:51 pm 

Joined: Fri Feb 24, 2012 11:28 am
Posts: 116
Dfcz wrote:
Пипец, кино и немцы.

они самые)))))))))))))))


Top
 Profile  
 
PostPosted: Wed Sep 19, 2018 4:40 pm 

Joined: Tue Dec 26, 2006 8:21 am
Posts: 561
Location: Russia
А как хорошо все начиналось:
franzferdinand wrote:
...
Стали возникать проблемы, начал искать их корень в проекте....


И докатилось все до чего:
Rex2701 wrote:
…. специфику Simatic - через входы-выходы нельзя передавать ничего кроме элементарных типов данных. И чтобы работать с массивами и структурами - придумали указатели POINTER и ANY, чтобы работать с ними косвенно "по удалёнке". Поэтому ваша функция получив указатель, работает с массивом поэлементно через AR1 + смещение.


А корень-то проблем в 99 случаев из 100 не в проекте.


Top
 Profile  
 
PostPosted: Wed Sep 19, 2018 4:45 pm 

Joined: Wed Mar 14, 2018 1:46 pm
Posts: 12
Ценю Ваше желание помочь (а оно ведь есть, раз отвечаете), но пост из серии "лишь бы написать", учитывая, что Вы не знаете всю историю.
Ответы на вопросы по теме я получил, спасибо.


Top
 Profile  
 
PostPosted: Wed Sep 19, 2018 8:29 pm 

Joined: Tue Dec 26, 2006 8:21 am
Posts: 561
Location: Russia
Ну, в коде вы разобрались, теперь осталось найти проблему и ее решение.
:)
Удачи.
:)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ] 

All times are UTC + 3 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by International PLCforum® Forum Software © PLCforum
Mobile version