Я в таких случаях делаю задержку разрешения обработки аналоговых сигналов после включения питания на время, достаточное чтобы периферия "пришла в себя". По-старинке именую сей таймер "задержка на прогрев". Пол-минуты обычно достаточно.
Вид для печати
И как делать эту задержку, можно по подробней? Пробовал после LE ставить AND и TON , но что то не получилось. Единственное может я время мало ставил, секунд 5Цитата:
Я в таких случаях делаю задержку
У меня проблема в том, что при подачи питания на плк и мв 8а на LE проскакивает импульс который активирует триггеры , хотя не должен температура плюсовая.
http://www.owen.ru/forum/attachment....2&d=1392751544Блин, столько постов наплодили.
Ни каких отрицательных значений при включении не проскакивает!
Ну не ужели не понятно, что условие "LE" по русски "меньше или равно". При старте программы переменная a_p однозначно равна "0" до тех пор пока не прочитается значение из модуля МВ. По этому при старте программы условие a_p=0 выполняется всегда, R_TRIG срабатывает и Ваши Pusk1 и A_pusk закономерно установятся в TRUE. Это даже в эмуляции можно проверить.
Вложение 18370http://www.owen.ru/forum/attachment....3&d=1392751579
Замените "LE" на "LT", или сравнивайте не с "0", а с"-0.5", например.
ЗЫ. Если уж очень хочется строгое выполнение условия "<=", то сделать так
Вложение 18371
Порядок ФБ важен, таймер ТР должен выполнятся раньше чем LE. Уставку для таймера подобрать по факту.
Спасибо, всё заработало.
Есть ПЛК63 с модулем МК110.8Д.4Р
в основной программе реализована связь между ними
в подпрограммах ST_1; - ST_5; реализация плавного регулирования 5ти групп светильников подключенных на выхода 0-10V от кнопок пульта(задание сцен освещения 4шт) и от выключателей.
От выключателей все работает нормально, каждая отдельная группа регулируется своим выключателем плавно изменяется напряжение на выходе от 0 до 10 или от 10 до 0
От одной кнопоки пульта регулируются сразу все группы освещения, так называемая сцена освещения.
Проблема: регулировка на первых двух выходах(AO2,АО3) происходит плавно, а на последних трех(АО4,5,6) скачком, хотя все подпрограммы одинаковы и в онлайн симуляции регулирование плавное, в реальности проверено тестером на выходах скачок
Пробовал увеличить время цикла выполнения программы отличное от 1ms - тогда пропадает связь.
Пробовал заменить контроллер - все тоже, плавности нет
задача перегнать bit в word и обратно, подскажите пожалуйста все ли я правильно делаю
Код:PROGRAM PLC_PRG
VAR
Var_Word: WORD;
Byte_low: BYTE;
Byte_hi: BYTE;
Byte_low2: BYTE;
Byte_hi2: BYTE;
Bit1: BOOL;
Bit2: BOOL;
Bit3: BOOL;
Bit4: BOOL;
Bit5: BOOL;
Bit7: BOOL;
Bit8: BOOL;
Bit9: BOOL;
Bit10: BOOL;
Bit6: BOOL;
Bit11: BOOL;
Bit12: BOOL;
Bit13: BOOL;
Bit14: BOOL;
Bit15: BOOL;
Bit16: BOOL;
Bits: ARRAY [1..16] OF BOOL;
UNPACK1: UNPACK;
UNPACK2: UNPACK;
PACK1: UNPACK;
PACK2: UNPACK;
END_VAR
(*заполняем биты (библиотека UTIL)*)
Bit1:=1;
Bit2:=0;
Bit3:=0;
Bit4:=0;
Bit5:=0;
Bit6:=0;
Bit7:=0;
Bit8:=0;
Bit9:=1;
Bit10:=0;
Bit11:=0;
Bit12:=0;
Bit13:=0;
Bit14:=0;
Bit15:=0;
Bit16:=0;
(*упаковываем биты в байты*)
Byte_low2:=PACK(Bit1,Bit2,Bit3,Bit4,Bit5,Bit6,Bit7,Bit8);
Byte_hi2:=PACK(Bit9,Bit10,Bit11,Bit12,Bit13,Bit14,Bit15,Bit16);
(*ну и байты в слово объединям*)
Var_Word:=SHL(BYTE_TO_WORD(Byte_hi2),8) OR BYTE_TO_WORD(Byte_low2);
(*ОБРАТНАЯ ПРОЦЕДУРА Переменная Var_Word разбивается на два байта*)
Byte_low:=WORD_TO_BYTE(Var_word);
Byte_hi:=WORD_TO_BYTE(Var_word/256);
(*байты раскладываются на биты с помощью ФБ Unpack (библиотека UTIL)*)
UNPACK1(
B:=Byte_low ,
B0=>Bits[1],
B1=>Bits[2] ,
B2=>Bits[3] ,
B3=>Bits[4] ,
B4=>Bits[5] ,
B5=>Bits[6] ,
B6=>Bits[7] ,
B7=>Bits[8] );
UNPACK2(
B:=Byte_hi ,
B0=>Bits[9] ,
B1=>Bits[10] ,
B2=>Bits[11] ,
B3=>Bits[12],
B4=>Bits[13] ,
B5=>Bits[14],
B6=>Bits[15],
B7=>Bits[16]);
(*все получили массив Bits заполненный (другая переменная чтобы легче было оценивать результат) *)
Мда..... куда тут уж проще... жесть, товарищи
Вот это, просто.
ps. Еще интересно, писал в WORD_cmd, а читал из WORD_sts.Код:if bBool
then
wWord.0 := true;
wWord.1 := false;
wWord.2 := true;
wWord.3 := false;
wWord.4 := true;
...
wWord.14 := true;
wWord.15 := false;
end_if
Без всяких массивов, просто и сердито
В обратную сторону аналогично, используем Bxx:=W.xx, где хх=0,1,2,...15Код:FUNCTION PACK_W : WORD
VAR_INPUT
B0: BOOL;
B1: BOOL;
B2: BOOL;
B3: BOOL;
B4: BOOL;
B5: BOOL;
B6: BOOL;
B7: BOOL;
B8: BOOL;
B9: BOOL;
B10: BOOL;
B11: BOOL;
B12: BOOL;
B13: BOOL;
B14: BOOL;
B15: BOOL;
END_VAR
VAR
END_VAR
(*Тело функции*)
PACK_W.0:=B0;
PACK_W.1:=B1;
PACK_W.2:=B2;
PACK_W.3:=B3;
PACK_W.4:=B4;
PACK_W.5:=B5;
PACK_W.6:=B6;
PACK_W.7:=B7;
PACK_W.8:=B8;
PACK_W.9:=B9;
PACK_W.10:=B10;
PACK_W.11:=B11;
PACK_W.12:=B12;
PACK_W.13:=B13;
PACK_W.14:=B14;
PACK_W.15:=B15;
Или еще вариант
А зачем их вообще упаковывать/распаковывать? Не проще ли просто использовать обращение к отдельным битам WORD?Код:FUNCTION PACK_W2 : WORD
VAR_INPUT
B0: BOOL;
B1: BOOL;
B2: BOOL;
B3: BOOL;
B4: BOOL;
B5: BOOL;
B6: BOOL;
B7: BOOL;
B8: BOOL;
B9: BOOL;
B10: BOOL;
B11: BOOL;
B12: BOOL;
B13: BOOL;
B14: BOOL;
B15: BOOL;
END_VAR
VAR
BYTE_0: BYTE;
BYTE_1: BYTE;
END_VAR
(*Тело функции*)
BYTE_0:=SHL(SHL(SHL(SHL(SHL(SHL(SHL(BOOL_TO_BYTE(B7),1) OR BOOL_TO_BYTE(B6),1) OR BOOL_TO_BYTE(B5),1) OR BOOL_TO_BYTE(B4),1)
OR BOOL_TO_BYTE(B3),1) OR BOOL_TO_BYTE(B2),1) OR BOOL_TO_BYTE(B1),1) OR BOOL_TO_BYTE(B0);
BYTE_1:=SHL(SHL(SHL(SHL(SHL(SHL(SHL(BOOL_TO_BYTE(B15),1) OR BOOL_TO_BYTE(B14),1) OR BOOL_TO_BYTE(B13),1) OR BOOL_TO_BYTE(B12),1)
OR BOOL_TO_BYTE(B11),1) OR BOOL_TO_BYTE(B10),1) OR BOOL_TO_BYTE(B9),1) OR BOOL_TO_BYTE(B8);
PACK_W2:=SHL(BYTE_TO_WORD(BYTE_1),8) OR BYTE_TO_WORD(BYTE_0);
а мой пример можете адаптировать к Вашему методу, а то появляется много вопросов
т.е. пример загнать 16 бит в слово и потом это слово снова разложить на 16 бит
вот мое предположение как это должно выглядеть:
Код:
(*заполняем биты (библиотека UTIL)*)
Bit1:=1;
Bit2:=0;
Bit3:=0;
Bit4:=0;
Bit5:=0;
Bit6:=0;
Bit7:=0;
Bit8:=0;
Bit9:=1;
Bit10:=0;
Bit11:=0;
Bit12:=0;
Bit13:=0;
Bit14:=0;
Bit15:=0;
Bit16:=0;
(*упаковываем биты в байты*)
IF Bit1 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit2 HEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit3 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit4 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit5 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit6 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit7 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit8 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit9 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit10 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit11 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit12 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit13 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit14 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit15 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
IF Bit16 THEN Var_Word:=Var_Word OR 1024; ELSE Var_Word:=Var_Word AND NOT 1024; END_IF;
(*ОБРАТНАЯ ПРОЦЕДУРА*)
(*байты раскладываются на биты*)
IF (Var_Word AND 1024)<>0 THEN Bits[1]:=TRUE; ELSE Bits[1]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[2]:=TRUE; ELSE Bits[2]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[3]:=TRUE; ELSE Bits[3]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[4]:=TRUE; ELSE Bits[4]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[5]:=TRUE; ELSE Bits[5]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[6]:=TRUE; ELSE Bits[6]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[7]:=TRUE; ELSE Bits[7]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[8]:=TRUE; ELSE Bits[8]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[9]:=TRUE; ELSE Bits[9]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[10]:=TRUE; ELSE Bits[10]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[11]:=TRUE; ELSE Bits[11]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[12]:=TRUE; ELSE Bits[12]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[13]:=TRUE; ELSE Bits[13]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[14]:=TRUE; ELSE Bits[14]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[15]:=TRUE; ELSE Bits[15]:=FALSE; END_IF;
IF (Var_Word AND 1024)<>0 THEN Bits[16]:=TRUE; ELSE Bits[16]:=FALSE; END_IF;
(*все получили массив Bits заполненный (другая переменная чтобы легче было оценивать результат) *)
да что это за порно!
на мой пост глянь. писать word.0 := true читать if word.0 then ...
http://www.owen.ru/forum/showthread....l=1#post172569
в панель передать чтобы, Bool значения нужно загнать в WORD, и соответсвенно когда их принимаем, тоже считываем их word блоками, вот для этих целей эти манипуляции и нужны,
Ваш метод с обращением намного проще, я и не знал что можно обращаться по битно к word, а dword тоже так можно?
Я уже показал, как загнать 16 бит в WORD
Обратная процедураКод:FUNCTION PACK_W : WORD
VAR_INPUT
B0: BOOL;
B1: BOOL;
B2: BOOL;
B3: BOOL;
B4: BOOL;
B5: BOOL;
B6: BOOL;
B7: BOOL;
B8: BOOL;
B9: BOOL;
B10: BOOL;
B11: BOOL;
B12: BOOL;
B13: BOOL;
B14: BOOL;
B15: BOOL;
END_VAR
VAR
END_VAR
(*Тело функции*)
PACK_W.0:=B0;
PACK_W.1:=B1;
PACK_W.2:=B2;
PACK_W.3:=B3;
PACK_W.4:=B4;
PACK_W.5:=B5;
PACK_W.6:=B6;
PACK_W.7:=B7;
PACK_W.8:=B8;
PACK_W.9:=B9;
PACK_W.10:=B10;
PACK_W.11:=B11;
PACK_W.12:=B12;
PACK_W.13:=B13;
PACK_W.14:=B14;
PACK_W.15:=B15;
Да не нужны эти манипуляции с "загнать в WORD", "разогнать из WORD". Все прекрасно передается на панели и из нее.Код:FUNCTION_BLOCK UNPACK_W
VAR_INPUT
In_W: WORD;
END_VAR
VAR_OUTPUT
B0: BOOL;
B1: BOOL;
B2: BOOL;
B3: BOOL;
B4: BOOL;
B5: BOOL;
B6: BOOL;
B7: BOOL;
B8: BOOL;
B9: BOOL;
B10: BOOL;
B11: BOOL;
B12: BOOL;
B13: BOOL;
B14: BOOL;
B15: BOOL;
END_VAR
VAR
END_VAR
B0:=In_W.0;
B1:=In_W.1;
B2:=In_W.2;
B3:=In_W.3;
B4:=In_W.4;
B5:=In_W.5;
B6:=In_W.6;
B7:=In_W.7;
B8:=In_W.8;
B9:=In_W.9;
B10:=In_W.10;
B11:=In_W.11;
B12:=In_W.12;
B13:=In_W.13;
B14:=In_W.14;
B14:=In_W.15;
Просто в программе вместо переменных BOOL манипулируйте сразу отдельными битами переменной WORD, которая определена в конфигурации для связи с панелью.
Неудобно обращаться по номерам разрядов? Тогда обращайтесь к ним по именам.
-определить в глобальных переменных константы INT для отдельных разрядов
Вложение 18502
Теперь для переменной WORD, через которую идет обмен с панелью
Вложение 18503
можно в программе, вместо номера разряда в переменной можно обращаться по имени этого разряда
Вложение 18504
т.е. например, вместо CMD_Panel.0 использовать CMD_Panel.cmdUrov_man.
Можно было еще проще сделать.
В том месте конфигурации ПЛК, где у меня была переменная CMD_Panel, вместо модуля 2 byte вставить два модуля 8bits
Вложение 18505
И тогда можно эти BOOL переменные использовать в программе, а в панели будет обращаться к двум модулям 8bits как к одному регистру.
да, интересный подход, с константами замечательно придумано!
День добрый!
Подскажите, возможно ли сформировать строку указателем прям с начала структуры?
Например:
STRUCT
BYTE
BYTE
WORD
WORD
DWORD
DWORD
DT
DT
end_struct
Занимает она 20 байт. Храню я её на Flash.
Сейчас я вычитываю её в массив Read (тип STRUCT), переделываю в строки и отправляю дальше.
Но я хочу отправить одну строку c содержимым всего файла.
Т.е. вычитали из файла, встали в начало файла и отправили строку байт.
По идее берем p:=ADR(Read);
Где p:pointer to string;
Определяем длину нашего массива (20 байт * кол-во данных + 1)
И загоняем в SysSockSend.
Сейчас пробую без отправки, просто вычитываю массив и пытаюсь сформировать из него строку - а в переменной вижу лишь это:
Вложение 18536
В данном примере testData - array [0..20] of byte;
Если использовать testDate - STRUCT - значения такие же.
Может просто строка не отображается правильно, а на деле будет работать?
Лишку я дал с Word :)
STRUCT
BYTE
BYTE
WORD
DWORD
DWORD
DT
DT
end_struct
По факту 20 байт, и на Flash сохраняется соответственно кратно 20.
Я могу и не отказываться от структуры, мне не понятно почему присваивая значение указателя строке - я получаю пару пробелов.
По поводу проекта - вот пример.
Файлик - пример данных. Разархивировать и в папку C:\Program Files (x86)\3S CODESYS\GatewayPLC
C Control Win V3 работает.
По факту получаем строку длиной в 3 символа.
а загляните в этот проект, может вместо массива указатель на строку читать из файла, так не проще будет
http://www.owen.ru/forum/showthread....l=1#post141820
ЗЫ это при условии что у Вас в файле строчные символы, если же это бинарник из числовых типов данных, то кроме как преобразовать "ручками" в проекте подругому не получится, и строка у Вас выдается правильно, просто нечитаемые символы не видны
03 01 07 00 00 00 00 00 A2 07 00 00 33 0F A4 55 34 0F A4 55
Два раза в одни и те же грабли ;)
Валенок уже говорил про это месяц тому назад, в этой же теме, по похожему вопросу :)
В общем отправлять через SendByte либо SysSockSend должен нормально, но в строке мы это не увидим :)
В очередной раз Всем спасибо!
Пойду пытать HyperTerminal и отправлять в него.
Подскажите, поиском не нашел.
Как сохранить скомпилированный код программы из ПЛК110, чтобы потом можно было загрузить обратно.
Исходники остались на другом компе, доступа к которому пока нет, а поэксперементировать нужно.
П.С. проекта в памяти ПЛК нет, только скомпилированная программа.
Ладно с этим разобрался, просто не записываю в загрузочную область проект, а когда требуется вернуться просто нажимаю кнопку сброс.
Теперь другой вопрос:
У меня контроллер ModBus to DMX512 принимает на вход команды Holding Registers, то есть двухбайтовые значения, но т.к. один канал это один байт получается один регистр управляет сразу двумя каналами. А хотелось бы управлять каналами как отдельными байтами. Как это можно реализовать?
Традиционное решение "в лоб" состоит из:
1. Чтения всего регистра (двух каналов);
2. Изменения нужного байта;
3. Записи нового значения в регистр.
Всем привет! Вот начал изучать программирование в СoDeSys v2.3. Ну и начал со стандартной книги по руководству codesys_v23_ru. Ну и в первом же разделе наткнулся на проблемку, есть функция пример.
Пример функции, написанной на языке IL:
FUNCTION Fct :INT
VAR_INPUT
PAR1:INT;
PAR2:INT;
PAR3:INT;
END_VAR
_______________
LD PAR1
MUL PAR2
DIV PAR3
ST Fct
Ну вот, проект я скомпилировал все нормально ошибок нет. Но как присвоить этим переменным значения численные сломал голову. Там говорится: Вот пример функции, написанной на IL, которая использует три входных пе-
ременных и возвращает результат деления произведения первых двух на третью. А как увидеть это наглядно в цифрах?? Хто знает подскажите хочу продвигатся дальше а тут ступор. ЗАРАНЕЕ СПАСИБО!!!
Можно задавать начальные значения для переменных
Вложение 18561
После запуска программы
Вложение 18562
ЗЫ. При работающей программе
Вложение 18563
Получится так
Вложение 18564
Что бы изменения вступили в силу нажать F7
Вложение 18565
Как можно собрать схему на CFC и сохранить как шаблон чтобы по 100 раз не писать одно и тоже?
Если можно то скриншот.
Ну если я правильно понял то это оно?Вложение 18571 а если это то то потом как его сохранить?
(Я новичок)
Это оно и оно само сохранится, как и ПРГ.Вложение 18574
Какой есть FB в CFC что на панельки вводишь значение (пример) от 1 до 10 (WORD) а на выходе есть 10 выходов (BOOL) которые переключаются в зависимости от указанной цифры
Организовал управление ПЧ с ПЛК160 по RS-485. Обратил внимание, что набор частоты (уставка с ПИД-регулятора) на ПЧ идёт заметными рывками. При этом скорость опроса стояла по умолчанию - 100 мс. Увеличение скорости с 9600 на 19200 эффекта не дало. Снизил время опроса ПЧ до 10 мс стало всё ровно. В связи с этим возник вопрос, это нормально или нет? Мне казалось что 10 раз в секунду более чем адекватная скорость.