И у меня работает, но когда я удалю последние 4 UMD то все данные перекашивает - то есть в панели я вижу одни нули. Не могу понять как неподключенные пустые UMD влияют на данные которые идут в сенсорную панель
Вид для печати
Кроме UMD надо ещё и структуры выровнять до 3 блоков, где было 1..7 поставить 1..3 в 5 местахВложение 71797
У меня все работает и с 3, ничего не съехало.Вложение 71798
Я хотел бы комментария, того кто в теме.
Сохраняемые и постоянные переменные в кодесисе 2.3 не одно и тоже, в отличие о текущей версии 3.5 (объявление persistent уже указывает на энергонезависимость) - это наталкивает на мысль, что директива компилятора работает с обеими областями памяти и не делает между ними разницы. Ведь в справке именно так и написано "энергонезависимая область". Более того в 3.5 есть подобная директива (прагма) {attribute 'no_instance_in_retain'} и там она кое как работает. (правда с ФБ та же беда)
Отсюда - либо опечатка, неверный перевод в мануале CDS 2.3, либо она работает иначе, есть какие-нибудь настройки, либо все зависит от целевой платформы. Вот и интересно - кто то разобрался в этой теме.
По моему все изменил на 3 компрессора, не могли бы вы проверить чего я не учел в коде?
При удалении хоть одного последнего UMD, данные в панели из структуры DATA_for_HMI становятся все по нулям:
Код:IF Active_PID = 1 THEN (*выводим на панель данные по активному пид*)
DATA_for_HMI.P_nominal := pid_struct_1.P_Nominal;
DATA_for_HMI.P_izmerennoe := P_izmer_pid;
DATA_for_HMI.Activ_pid := Active_PID;
DATA_for_HMI.Pid_Out := PID_1.OUT;
DATA_for_HMI.DBF_Actual := GET_DBF._DBF;
DATA_for_HMI.Count_Rele := CTUInst.CV * 4;
DATA_for_HMI.Poz_zadvigki := VALVE_REG1.VALVE_REG_NO_POS.VCURPOS;
DATA_for_HMI.Impuls_Dovodki := VALVE_REG1.VALVE_REG_NO_POS.PUSH_IMP;
DATA_for_HMI.bits2_0_7.0 := VALVE_REG1.VALVE_REG_NO_POS.LESS;
DATA_for_HMI.bits2_0_7.1 := VALVE_REG1.VALVE_REG_NO_POS.MORE;
ELSIF Active_PID = 2 THEN
;
ELSIF Active_PID = 3 THEN
;
END_IF;
На первый взляд всё правильно, разбираться во всём коде времени пока нет.
Советую вам проследить все параметры в программе, возможно при удалении UMD, у вас смещаются прямые адреса типа AT%QD,
которых вы бездумно напихали где не надо. Хотя вам писали адрес делать только один, указание на 1 регистр начала структуры.
Поторопился я радоваться ((
Проверил все прописанные адреса на структурах, причем я их в таблицу записываю, все правильно сделано, без накладок.
При добавлении UMD, адресА структур не смещаются. Так же и удаление UMD не влияет на адреса структур так как они идут по адресу QD7… а UMD привязывается к адресам QB6…
Чудес не бывает, если адреса не смещаются при удалении UMD, то они точно смещаются при уменьшении кол-ва 4BYTE. А их для 3 компрессоров надо меньше намного.
Ну и проверку в эмуляции никто не отменял, с подстановкой чисел.
И ещё после таких сильных изменений, обязательно очистить всё, компилировать всё.
Каким же образом могут влиять добавление/удаление UMD из Мастера на Регистры Slave? Адреса у них разные Например QB6.8.0 добавляю в него "Real Input module" QB6.8.0.0 и при этом на скрине видно что перестает писать значение в регистры P_izmer_pid AT %QD7.42.0
Вложение 71807
Мне всего то нужно добавить еще одну панель ИП320, но теперь ни удалить ни добавить UMD не могу, где же эта паразитная привязка?
Удалил весь код основной программы, оставил только присвоение:
Данные в all_ai[1].ai[8].value есть но в P_izmer_pid они не присваиваются. Куда копать, подскажите пожалуйста?Код:p1^ := original_8AC[1].Read[8,1] * 16#10000 + original_8AC[1].Read[8,2];
P_izmer_pid := all_ai[1].ai[8].value; (*давление измеренное в центральной магистрали*)
Могу сказать только одно, у вас не соответствие размера стуруктур, размеру выделенного места в слейве. Вы что то меняете, добавляете, но не учитывая, что и выделенное место тоже надо менять и проверять соответствие. То есть всё делать пошагово, проверяя на залезает ли одна структура на другую.
Кроме того, после сильных изменений, не делаете очистить всё, компилировать всё.
Блин, ну НЕ НАДО использовать дохрена прямых адресов!
Я выкладывал то, как делаю я, вот здесь: https://owen.ru/forum/showthread.php?t=38622
а) Собираю всё в ОДНУ структуру с вложенными
б) В конфигурации ПЛК вставляю одну, первую переменную от Slave (которая у тебя "Запасная переменная 0") и её адрес назначаю указателю на структуру.
После этого всё работает "само", и адреса тоже пересчитываются "сами".
Всё следует из того, что писал раньше. При больших изменениях новый код накладывается на старый, не удаляя накладки, в вашем случае старую структуру на новую.
Одно дело добавить в конце, что то новое и другое дело менять 7 UMD на 3, где сразу всё новое наложилось на старое.
Лучше почаще делать очистку, чем ломать потом голову, почему не работает. Кстати по поводу очистки, это уже наверно пятый раз написал за всё время.
И ещё не вставляйте большие куски в середину программы, как вы сделали с ПИДами. В случае ошибки, у вас не только новый код не заработает, но и старый в конце может перестать работать. Дописывайте всегда в конце.
Я бы стазу вынес опрос-присвоение структуры COMPRESSOR в новый ФБ или программу, а в пустой PLC_PRG уже писал программу с ПИДами.
Вместо трёх ФБ PID_1, PID_2, PID_3, написал один и сделал 3 экземпляра и вместо 3 структур PID_struct_ взял одну 3 раза.
Когда все закидываю в одну структуру мне так же нужно следить чтобы тип REAL или DWORD начинались с четного регистра?
Самому нужно выправлять это дополнительными переменными?
Например тут переменная temp_1 выравнивает и уже все REAL начинаются с четных регистров:
Код:STRUCT
(* ОБЩИЕУСТАВКИ ДЛЯ ВСЕХ КОМПРЕССОРОВ *)
temp_1 : WORD; (* Регистр 0 *) (**)
t_ust_1st : WORD; (* Регистр 1 *)
t_ust_2st : WORD; (* Регистр 2 *)
t_ust_oil : WORD; (* Регистр 3 *)
P_ust_1st : REAL; (* Регистр 4-5 *)
P_ust_2st : REAL; (* Регистр 6-7 *)
P_ust_oil_min : REAL; (* Регистр 8-9 *)
P_ust_oil_max : REAL; (* Регистр 10-11 *)
P_ust_water : REAL; (* Регистр 12-13 *)
END_STRUCT
Здравствуйте.
Подскажите пожалуйста, в Slave нужно теперь чтобы все подэлементы били WORD или DWORD для единой структуры? Или как у меня вначале WORD а потом все DWORD тоже будет корректно распределяться? Правда пришлось структуру объявить как QW -> MAIN_STRUCT AT %QW7.1.0 : MAIN_STRUCT;
Вложение 71839
Вот сейчас с этим и бьюсь, не могу подсчитать правильные номера регистров ((
Например массив структур как распределит переменные по регистрам, сначала первые 12 регистров будут compressors[1], потом 12 регистров compressors[2] итд?
compressors :ARRAY [1..3] OF COMPRESSOR;
По сути 12 *3 = 36 регистров, у меня так же 18шт DWORD задано, но все же тут получается перекос и следующая переменная хранится в последнем 36-м регистреКод:TYPE COMPRESSOR :
STRUCT
bSignal1 :BYTE;(*14-0-7; 26-0-7; 38-0-7*)
bSignal2 :BYTE;(*14-8-15; 26-8-15; 38-8-15*)
t_1st :INT;(*15; 27; 39*)
t_2st :INT;(*16; 28; 40*)
t_oil :INT;(*17; 29; 41*)
P_1st :REAL;(*18; 30; 42*)
P_2st :REAL;(*20; 32; 44*)
P_oil :REAL;(*22; 34; 46*)
P_water :REAL;(*24; 36; 48*)
END_STRUCT
END_TYPE
Так и есть 12 регистров занимает 1 структура COMPRESSOR, всего 3 труктуры, 36 регистров или 72 байта
12 регистров это 6 штук 4 BYTE, это всё уже обсуждалось, можно было взять и посмотреть в этой теме. Даже скрины выкладывал несколько раз. https://owen.ru/forum/showthread.php?t=10555&page=979
x:=SIZEOF(compressors); получается 72 байта, 36 регистров или 18 шт. 4BYTE. Скрин==>> Вложение 71853
И ответ зачем нужен command : DWORD; в структуре original_8AC :STRUCT размер структуры 80 байт (разница адресов S2 - S1=84 байт)
Не несите чушь. 8-битным не нужно выравнивание.
2 байта подряд стоящие с четного БАЙТА [или 0-ого] (не регистра) это 1 регистр (16-бит)
-
Там ровно 12 регистров
--
Какие-то странные прения. Непонимающим нужно маляром поработать, буквы через трафарет позакрашивать. Тогда сразу станет понятно как структуры к памяти прикладывать. Это одно и тоже
точно, спасибо!
Интересный размерчик получается...
Вложение 71861
Подскажите простой и быстрый способ, как можно сразу прочитать несколько дискретных входов контроллера и поместить входные значения в 16 битное слово (WORD). Задача осложняется тем, что дискретные входные сигналы расположены вроде рядышком, но находятся в трех группах (8-и битных), как показано на скрине.Вложение 71899. Хотелось бы видеть в WORD слове данные D14-D27.
Не знаю насколько быстро и просто, но что-то типа такого наверное:
Код:B2 AT %IB1.3: BYTE;
B1 AT %IB1.2 : BYTE;
B0 AT %IB1.1 : BYTE;
wRESULT : WORD;
wRESULT := DWORD_TO_WORD(SHR(SHL(SHL(BYTE_TO_DWORD(B2),8) OR BYTE_TO_DWORD(B1),8) OR BYTE_TO_DWORD(B0),4));
Спасибо. Буду пробовать. У меня до этого момента было 14 условных операторов IF для определения, какой вход активный. И в зависимости от ситуации, я в программе в специальную переменную записывал номер активного входа (датчика). И этот номер датчика потом использовал в программе. Но вот на днях, я решил немного оптимизировать программу. И был готов установить CASE для определения активного датчика. Ведь, я думал, что CASE будет быстрее определять номер активного датчика, нежели 14 отдельных условных операторов? Ну и столкнулся с проблемой, как прочитать множество входов и записать все скопом в одно слово для CASE. Думаю, что Ваша функция будет работать быстро.
Если так сделать, то D13 тоже попадает в WORD и биты будут не по порядку.
Можно ещё проще и ничего лишнего не будет и все биты по порядку, с D14 по D27 .
Код:w : WORD;
w.0:=D14; w.1:=D15; w.2:=D16; w.3:=D17; w.4:=D18; w.5:=D19; w.6:=D20; w.7:=D21;
w.8:=D22; w.9:=D23; w.10:=D24; w.11:=D25; w.12:=D26; w.13:=D27;
Убедительно, но интуиция подсказывает, что 16 отдельных IF будут работать медленнее, чем один CASE. Хотя...?
Ну и еще один тогда вопрос: имеется ли возможность в ПЛК110-24.69.Р(М02) работать с аппаратными прерываниями по дискретным входам? Уж очень утомительно контроллеру на каждом новом цикле работы опрашивать состояния каждого входа отдельно. А как было бы хорошо обслуживать дискретный вход только, если на нем появился сигнал. Только сразу не кидайте в меня тапки.
Мне IF требовались для простой задачи: - присвоение номера для активного входа. Например:
...
IF D1 THEN
COD_G_POZ_1 := 1;
END_IF
IF D2 THEN
COD_G_POZ_1 := 2;
END_IF
IF D3 THEN
COD_G_POZ_1 := 3;
END_IF
...
Я в программе работаю с номерами датчиков, которые подключены к отдельным дискретным входам. Датчиков бывает 25-30 шт. Возможно имеется более красивый способ формировать номер активного датчика.