я побежал за ящЫком в магаз)) Колян, куда ехать?)) СПАСИБО ОГРОМНЕЙШЕЕ!!!!!!!!!
Вид для печати
Уважаемые коллеги! Попал в ситуацию. В общем есть устройство которое на запрос возвращает структуру вида:
hours1:BYTE;
minutes1:BYTE;
value1:INT;
rele1:BYTE;
hours2:BYTE;
minutes2:BYTE;
value2:INT;
rele2:BYTE;
hours3:BYTE;
minutes3:BYTE;
value3:INT;
rele3:BYTE;
hours4:BYTE;
minutes4:BYTE;
value4:INT;
rele4:BYTE;
hours5:BYTE;
minutes5:BYTE;
value5:INT;
rele5:BYTE;
hours6:BYTE;
minutes6:BYTE;
value6:INT;
rele6:BYTE;
я создаю такую структуру (тип А) и делаю переменную A_var: A;
Из устройства эти структура приходит просто в виде упорядоченного набора байт (массив). Т.е. та структура которую я указал только последовательно побайтно.
Переписываю этот массив в переменную A_var посредством указателя pt:POINTER TO A:
pt:=ADR(kadr[4]);
A_var:=pt^;
И в итоге некоторые байты переписываются с каким-то странным смещением на 1 байт, в общем некорректно. Вот сижу и не пойму то ли лыжи не едут, то ли у меня образованности не хватает. Если есть нюансы при работе с указателями подскажите плиз.
Если я правильно понял - идут 6 пакетиков по 5 байт ?
Или тот девайс - плк-слейв, а это его структура ?
PS
Мне привычней - т-щ ))
идет один пакет длиной 30 байт, который нужно просто переложить в соответствующую структуру. Тот девайс Слейв. Только не ПЛК, а регулятор с протоколом WAKE.
На данный момент взял все захардкодил, но выглядит это ужасающе порнографично. Однако работает безотказно если не учитывать, разницу в объеме кода...
Что делать ?
1.STRUCT_A
h,m : byte;
val : int;
rele : byte;
VAR
V : array [1..6] of STRUCT_A;
M : array [1..6,1..5] of byte;
2.Принять данные в M
3.Переложить M в V
for i := 1 to 6 do
V[i].h := M[i,1];
V[i].m := M[i,2];
V[i].val := 256 * M[i,4] + M[i,3]; (* или 256 * M[i,3] + M[i,4] ?*)
V[i].rele := M[i,5];
end_for
Кто виноват ? (кратко)
1.просто выравнивание
2.выравнивание структур особенно
спасибо! Смысл ясен)) Получается, что при инициализации структуры контроллер отводит память под неё как ему за хочется, а если мы инициализируем массив, то тут уже отводится последовательное кол-во байт. Вобщем следовало бы догадаться. Однако получится ли заполнить массив V [0..6] за раз посредством указателя? Или снова вмешается выравнивание в структуре лежащей по адресу V[i]? Что-то мне кажеся что вмешается. В таком случае получается не многим проще, чем захардкодить это переложение.
1.
Размер читаемой структуры 6 x 5 байт.
В подструктуре есть слово (val:int)
=> адреса этих слов - четный,нечетный, четный...
2.
Принимающая железка не может разместить слово по нечетному адресу. (Не Овен и даже не КДС, а именно железка) => будет выравнивание.
3.
Почему спросил - кто слейв ?
В предположении что слейв - ПЛК и имеет структуру:
слейв{
h1 : byte
m1 : byte
val1 : int
rele1 : byte
h2 : byte
m2 : byte
val2 : int
rele2 : byte
...
}
В таком случае неявное выравнивание в самом слейве было бы таково :
слейв{
h1 : byte
m1 : byte
val1 : int
rele1 : byte
x1 : byte
h2 : byte
m2 : byte
val2 : int
rele2 : byte
x2 : byte
...
}
Не знаю что такое "захардкодить". Если объявить VAR как выше в слейве и попытаться прочитать туда - неполучицца. По факту будет как с неявным (выше). Вы просто не сможете разместить данные как в посылке. Разве только:
h1 : byte
m1 : byte
val1_lo : byte
val1_hi : byte
rele1 : byte
...
А если сделаете :
то каждое второе p^ , в любую сторону, приведет к би-и-п. "Потеря связи.."Код:p : pointer to int;
p := adr(val?_lo)
Тоже самое c
p^ туда/сюда целиком - нормуль.Код:p : pointer to struct{h,m:byte; val:int; rele:byte}
p := adr(h?)
Но p^.val - приведет к тому же что выше
+
если будет фрагмент типа
где-нить в глобал, то можно бибикнуть при любом обращении даже к p^ (:= ADR(h6)), т.к. присутствует выход за пределы доступной памяти.Код:...
h6 : byte
m6 : byte
val6_lo : byte
val6_hi : byte
rele6 : byte
END_VAR
4.
В КДС размер любой структуры/фб - кратен 4. Отсюда :
STRUCT A{
h : byte
m : byte
val : int
rele : byte
}
равносильно
STRUCT A{
h : byte
m : byte
val : int
rele : byte
x : array[1..3] of byte
}
=> ... выводы по адресации делаем сами. И с учетом массива структур
Нету никаких "как ему за хочется". Все рассчитываемо если есть понимание механизма выравнивания
PS
на море .. на море ... на море ...
большое спасибо за пояснения. Я понимаю что нету как ему захочется. Я имел ввиду, что повлиять на это мы не можем и это нормально. Захардкодить я имел ввиду жестко в ручную писать переписывание из посылки в структуру каждой переменной. В конце концов проект этот пишется раз и на долгое время под массовый шкафчик. Так что лучше прописать все жестко. Займет больше строк кода и выглядеть будет не так красиво, зато надежно.
Возможно - ли как - то отключать измерение на несколько секунд с модуля ввода в программе на ПЛК, после достижения необходимого значения?
Подскажите, пожалуйста: в проекте имеется модуль modbus-slave-TCP, на компьютере запущен OPC-сервер, опрашивающий контроллер. Если я кратковременно (не более примерно 5-ти секунд) отключаю физически разъём от ethenet-а контроллера, восстановление опроса происходит быстро, однако если продержать разрыв чуть дольше восстановление связи с OPC-сервером происходит оочень долго, минут 5-10, несмотря на то что контроллер уже давно "пингуется". Если физически перезагрузить контроллер связь появляется сразу. Подскажите, можно ли настроить контроллер, чтобы связь восстанавливалась как только восстанавливается ethrnet-соединение? Подозреваю что дело именно в контроллере, т.к. помогает его физическая перезагрузка...
Подскажите по взаимодействию контроллера с панелью ИП320.
Например мне необходимо real переменную изменять. Учитывая, что переменная без знаков после запятой то все просто real_to_int - изменили, обратно int_to_real
А если мне необходим 10-тичный знак . Real*10 - real_to_int - отправить в панель с указанием показывать 1 знак после запятой. Изменить и вернуть обратно int_to_real /10
Как панель воспринимает указание, что необходимо показывать количество знаков после запятой ? или панели необходимо именно real значение для этого ?
capzap пробовал и читаю, но не совсем понял, как панель работает со знаком после запятой. Это только отображение, или таким образом можно дать ей целое число и просто указывать количество знаков.
Панели пока под руками нет.
capzap спасибо, как раз хотел избавиться от real в панели, всего один параметр, который мне необходимо изменять с десятыми долями.
здравствуйте, уважаемые профи кодесиса!! пишет Вам чайник)) может кто-нибудь может скинуть свои разработки в этой программе (какие-нибудь простенькие примеры). Уж ооочень хочется научиться программировать в кодесисе. большое спасибо заранее!! :rolleyes:
Valadar71 на языке ST есть примеры в разделах ПЛК. примеры программ
если на языке CFC то можно брать примеры программ для ПР110,114 и переделывать на ПЛК.
Добрый день, не подскажите, работаю с двумя библиотеками, Mercury.lib и SmsOwen.lib, в обеих этих библиотеках есть функциональные блоки OpenPort, при добвалении обеих кодесис начинает ругаться, говорит что POU с именем OpenPort включен уже в библиотеку, подскажите как быть?!
в кратце: вам не нужно создавать в проекте такой же ФБ как в библиотеке. Если вы добавили библиотеку в проект, значит все POU входящие в библиотеки уже присутствуют в проекте и для использования ФБ нужно просто объявить его экземпляр. Подробнее написано в руководстве по программированию и справке кодезиса.
Попробуйте в одной из библиотек удалить лишний ФБ.
Попробуйте сделать так
1. Добавить в проект только одну библиотеку.
2. Выбрать в меню Проект-->Опции...-->Генератор кода.
3. Нажать кнопку Исключить объекты
4. В дереве POU выбрать имя ФБ которое есть в обоих библиотеках.
5. Установить галку внизу, слева -Исключить.
6. Нажать ОК.
7. Сделать простейший проект ";". И откомпилировать его.
8. Добавить в проект вторую библиотеку. И будет Вам счастье.:)
А и не должен удаляться из библиотеки. Просто элемент исключенный из компиляции станет в библиотеке другого цвета(зеленого). И не будет участвовать в компиляции.
Когда писал свой совет,то проверял и у меня все получилось.
Сейчас проверил опять. НЕ РАБОТАЕТ!!!.
Но оказалось, что есть зависимость от места расположения библиотек в дереве
У меня нет, указанных Вами библиотек, но поясню на примере двух других библиотек. Например Pid_regulators и Owen_FB.
1. Вот так ругается компилятор, который нашел три одинаковых ФБ в обоих библиотеках
Вложение 9420
2. При исключении из компиляции элементов в библиотеке расположенной выше(по отношению ко второй) при компиляции получаю те же ошибки.
Вложение 9421
3. Но стоит включить исключенные ФБ в вышестоящей библиотеке, а в ниже стоящей эти ФБ исключить, то все прекрасно компилируется и ошибок нет.
Вложение 9422
Вложение 9423
Таким образом исключать ФБ из компиляции нужно у библиотеки более ниже расположенной в списке подключенных библиотек
Уважаемые коллеги! Помогите разобраться. Нужно из программы сделать функциональный блок. Что то не получается. Подскажите как это правильно делать. В программе есть retain-блок.
Спасибо Kolyan. Буду разбираться. Если есть возможность и время, прошу подсказать, как правильно, и главное без ошибок, создавать ФБ.
И снова здрасьте...
Начал пытаться осваивать ОРС.
На вложенной картинке видно, что есть внешний модуль ModBus, пристегнутый к контроллеру по 485. С него получаю температуру. Модуль slave, PLC - master.
В конфигурации создал модуль модбас слейв, чтобы скада была мастером, и пытаюсь прицепить это дело к ОРС через ethernet.
И тут же возник вопрос с адресацией и типами. В CodeSys про переменные написано:
Как мне получить в том же Lectus'e данные либо с самих датчиков (TEMP01), либо из переменной T01?Код:VAR
T01: REAL; (* Датчик температуры 1 *)
T02: REAL; (* Датчик температуры 2 *)
T03: REAL; (* Датчик температуры 3 *)
END_VAR
(* Смотрим температуру с 1-Wire *)
T01 := INT_TO_REAL(WORD_TO_INT(TEMP01)) / 100.0;
T02 := INT_TO_REAL(WORD_TO_INT(TEMP02)) / 100.0;
T03 := INT_TO_REAL(WORD_TO_INT(TEMP03)) / 100.0;
Неужели для каждой переменной из проекта надо будет в модуле ModBus Slave заводить свою? Или я чего-то недопонимаю?
Из контроллера, но имя уже будет другим ;)
Сеть у Вас уже другая, а контроллер всё тот же. Это значит, что переменные в новой сети должны быть описаны каждая заново и персонально. Не все из проекта, а те которые Вы будете передавать через OPC.
Имена переменных в том же контроллере повторятся не могут. Типы переменных лучше оставить такими же и в новой сети - меньше путаницы. Хотя можете и преобразовать под свои нужды - дело Ваше.
Адреса переменным в новой сети в соответствии с их типом Вы назначаете в контроллере.
В конфигурации OPC Вы заново будете описывать все переменные, давая им имена (можно уже другие, но зачем?) и указывая назначенный в контроллере адрес и тип.
Ну, а потом в SCADA в базу тэгов будете вносить имена OPC переменных. Но там проще - обычно в SCADA есть визард для этого.
Вот как-то так.