Просмотр полной версии : FIFO (очередь) ПЛК110-60 MS4D
Vadik2881
31.01.2025, 11:52
Ребята приветствую, помогите с алгоритмом, кто может.
На ПЛК110-60 MS4D хочу реализовать очередь. Есть 32 входа и 32 выхода. Кто первый пришёл - тот первый и ушёл.
На OwenLogic тут нашёл готовый макрос, сделанный Сергей0308
https://owen.ru/forum/showthread.php?t=25068&page=34&highlight=%EE%F7%E5%F0%E5%E4%FC
Работает в общем как надо. Правда конечно сложная структура...
В общем хотел всё это реализовать в MS4D и встрял на операторе шифратор CD32 (преобразование позиционного кода в двоичный), так и не понял что это и как-то связано в логарифмами...
Мне казался изначально более простое решение: это считать время присутствия каждого входа и пропускать в первую очередь того кто больше, но тут нужно какое-то много канальное сравнение и пока затык.
В MS4D в библиотеке OSCAT в принципе есть оператор очереди FIFO_32 но у него вход/выход - целые числа и нужно как то это всё преобразовывать...
Правда у меня планируется более продвинутый алгоритм с выбором количества одновременного обслуживания.
Вообще весьма странно, что нет частого использования этой задачи в паблике. Этиж очереди сейчас везде и всюду)
Подскажите хотя бы направление по которому лучше пойти, хотя одно я точно конечно знаю:)
CD32 просто показывает положение старшего бита в числе. При чем у него нет понятия на выходе "не число". То есть на значения 0 и 1 на выходе он будет показывать 0.
1 = 0
2 = 1
4 = 2
8 = 3
И так далее. Введете число 12 - на выходе получите 3, так как есть старший бит (число 8).
kondor3000
31.01.2025, 12:33
Ребята приветствую, помогите с алгоритмом, кто может.
На ПЛК110-60 MS4D хочу реализовать очередь. Есть 32 входа и 32 выхода. Кто первый пришёл - тот первый и ушёл.
На OwenLogic тут нашёл готовый макрос, сделанный Сергей0308
Вообще весьма странно, что нет частого использования этой задачи в паблике. Этиж очереди сейчас везде и всюду)
Подскажите хотя бы направление по которому лучше пойти, хотя одно я точно конечно знаю:)
То же самое делается проще на ST и расширяется до 32 бит без проблем. При чём варианты могут быть разные, на IF на CASE с приоритетом и без, со сбросом и без.
Тут примеры https://owen.ru/forum/showthread.php?t=26216&page=345&p=431504#post431504
На следующей странице ещё несколько вариантов.
Вам наверное лучше поискать примеры на C#. Правда вот не знаю, что там с лицензиями в MS4D, а то может быть недоступным.
Сергей0308
31.01.2025, 13:08
Ребята приветствую, помогите с алгоритмом, кто может.
На ПЛК110-60 MS4D хочу реализовать очередь. Есть 32 входа и 32 выхода. Кто первый пришёл - тот первый и ушёл.
На OwenLogic тут нашёл готовый макрос, сделанный Сергей0308
https://owen.ru/forum/showthread.php?t=25068&page=34&highlight=%EE%F7%E5%F0%E5%E4%FC
Работает в общем как надо. Правда конечно сложная структура...
В общем хотел всё это реализовать в MS4D и встрял на операторе шифратор CD32 (преобразование позиционного кода в двоичный), так и не понял что это и как-то связано в логарифмами...
Мне казался изначально более простое решение: это считать время присутствия каждого входа и пропускать в первую очередь того кто больше, но тут нужно какое-то много канальное сравнение и пока затык.
В MS4D в библиотеке OSCAT в принципе есть оператор очереди FIFO_32 но у него вход/выход - целые числа и нужно как то это всё преобразовывать...
Правда у меня планируется более продвинутый алгоритм с выбором количества одновременного обслуживания.
Вообще весьма странно, что нет частого использования этой задачи в паблике. Этиж очереди сейчас везде и всюду)
Подскажите хотя бы направление по которому лучше пойти, хотя одно я точно конечно знаю:)
Вот здесь усовершенствовали, в смысле, можно просматривать очередь на всё глубину и делать, что захочется: https://owen.ru/forum/showthread.php?t=36452&page=4
Vadik2881
04.02.2025, 19:32
Ребята, ну вроде кое что удалось сделать. Сидел долго, даже ST пришлось немного освоить. Кстати крутая штука, но для сложных проектов...
Гляньте проект. Очередь сделал как и хотел - на принципе измерения времени ожидания, т.е. первый проходит у кого оно больше. И достаточно не сложный алгоритм.
Кому не лень, протестируйте пожалуйста на баги. Основной затык был в операторе сравнения на 3 и более входа. И получилось это только в ST!!!
Ребята, ну вроде кое что удалось сделать. Сидел долго, даже ST пришлось немного освоить. Кстати крутая штука, но для сложных проектов...
Гляньте проект. Очередь сделал как и хотел - на принципе измерения времени ожидания, т.е. первый проходит у кого оно больше. И достаточно не сложный алгоритм.
Кому не лень, протестируйте пожалуйста на баги.
Извините! Я чего-то пропустил?
А где здесь ПЛК110-60?
И конкретно FIFO-буфер?
Vadik2881
07.02.2025, 08:31
Ну ты читай между строк же :)) MS4D я только в руки взял и она достаточно громоздкая. А не простые проекты лучше делать на том, что лучше знаешь! Потом перенести алгоритм совсем не проблема. В конечном счёте, проект будет на ПЛК110-60.
Ну а с FIFO функция первый пришёл - первый ушёл - вроде как реализована. Будем считать это альтернативным вариантом исполнения. Но думаю на настоящем FIFO данную задачу тоже можно и нужно делать!
Народ, ну чё, никто не потестил?
Сейчас думаю как доработать очередь и сделать выбор для одновременного обслуживания двух и более (хотя бы двух) абонентов и пока что-то нет мыслей...
Народ, ну чё, никто не потестил? .
за народ тестировали фифо авторитетные программисты из оскат сообщества, ихним кодом и пользуемся
Ну ты читай между строк же :)) MS4D я только в руки взял и она достаточно громоздкая. А не простые проекты лучше делать на том, что лучше знаешь! Потом перенести алгоритм совсем не проблема. В конечном счёте, проект будет на ПЛК110-60.
Ну а с FIFO функция первый пришёл - первый ушёл - вроде как реализована. Будем считать это альтернативным вариантом исполнения. Но думаю на настоящем FIFO данную задачу тоже можно и нужно делать!
Народ, ну чё, никто не потестил?
Сейчас думаю как доработать очередь и сделать выбор для одновременного обслуживания двух и более (хотя бы двух) абонентов и пока что-то нет мыслей...
Ну, я потестил! Я в упор не вижу FIFO.
81823
Подсчет длительности импульсов (*0,2сек) на каждом входе и потом поиск входа с максимальной длительностью и всё!
Может надо запихивать длительность каждого импульса на одном входе в буфер?
81824
Если хочется буфер на ST?
81827
cделайте на ST
В чём проблема-то ?
function_block FIFO
var_input
in : udint;
shift : bool;
end_var
var_output
out: udint;
end_var
var
out0, out1, out2, out3, out4, out5, out6, out7, out8 : udint;
end_var
if shift then
out := out8;
out8 := out7;
out7 := out6;
out6 := out5;
out5 := out4;
out4 := out3;
out3 := out2;
out2 := out1;
out1 := out0;
out0 := in;
end_if
end_function_block
Если речь о фиксации входа с исключением, то:
81830
самый простой вариант
function_block Push
var_input
I1, I2, I3, I4, I5, I6, I7, I8 : bool;
end_var
var_output
Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8 : bool;
end_var
var
State, newState : udint;
end_var
newState.0 := I1; newState.1 := I2; newState.2 := I3; newState.3 := I4;
newState.4 := I5; newState.5 := I6; newState.6 := I7; newState.7 := I8;
if newState > 0 then
if newState <> State then
State := newState;
Q1 := I1; Q2 := I2; Q3 := I3; Q4 := I4;
Q5 := I5; Q6 := I6; Q7 := I7; Q8 := I8;
end_if
end_if
end_function_block
Тоже без ST:
81832
Фиксация следующего при условии что он единственный активный:
function_block Push
var_input
I1, I2, I3, I4, I5, I6, I7, I8 : bool;
end_var
var_output
Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8 : bool;
end_var
var
State, newState : udint;
Cnt : udint; // Кол-во активных входов
end_var
newState.0 := I1; newState.1 := I2; newState.2 := I3; newState.3 := I4;
newState.4 := I5; newState.5 := I6; newState.6 := I7; newState.7 := I8;
Cnt := 0;
if I1 then Cnt := Cnt + 1; end_if
if I2 then Cnt := Cnt + 1; end_if
if I3 then Cnt := Cnt + 1; end_if
if I4 then Cnt := Cnt + 1; end_if
if I5 then Cnt := Cnt + 1; end_if
if I6 then Cnt := Cnt + 1; end_if
if I7 then Cnt := Cnt + 1; end_if
if I8 then Cnt := Cnt + 1; end_if
if newState > 0 and Cnt = 1 and newState <> State then
State := newState;
Q1 := I1; Q2 := I2; Q3 := I3; Q4 := I4;
Q5 := I5; Q6 := I6; Q7 := I7; Q8 := I8;
end_if
end_function_block
.. но тут нужно какое-то много канальное сравнение и пока затык.
Правда у меня планируется более продвинутый алгоритм с выбором количества одновременного обслуживания.
Может ТЗ более внятное озвучить?
Vadik2881
07.02.2025, 13:43
Ух спасибо Вам много всего, буду разбираться.
ТЗ такое:
32 цифровых входа и 32 цифровых выхода. Это 32 загрузчика сырья, если физически. Но все они на одном насосе и не могут одновременно обслуживаться, поэтому очередь. Первый пришёл, обслужился, ушёл, следующий. И хаотично навалом они тоже не могут, нужна именно чётко организованная очередь, один за одним.
Тут предлагали алгоритм "кто первый встал того и тапки" но это совсем не то!
Почему считаете, что мой вариант не FIFO?! Принцип как раз такой. Мы сейчас о принципе, а не конкретном операторе FiFO32 из библиотеки OSCAT.
Мой вариант чётко отрабатывает вроде... Но нужна опция дополнительная, это количество одновременного обслуживания - до 3 абонентов или хотя бы до двух. И вот с моим вариантом это походу нереально сделать или не разобрался.
Сейчас пробую это реализовать на MS4d по цепочке: конвертор булевого в целое - оператор FIFO32 - конвертер целого в булевое.
Первый пришёл, обслужился, ушёл, следующий.
а если пока работает первый подключился второй, чтож его не обслуживать когда первый закончил или насос не будет останавливаться пока кто то есть в очереди, вернее пока очередь не пуста
Т.е. если бы насос справлялся, то можно было бы заправлять все 32 загрузчика?
А так как можно только N-загрузчика одновременно, то следующим становиться под загрузку тот, кто приехал раньше из всех ожидающих?
Предлагаю такой вариант:
81835
function_block Queue
var_input
I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, I16 : bool;
I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, I32 : bool;
N : udint; // Сколько можно загружать одновременно
end_var
var_output
Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, Q16 : bool;
Q17, Q18, Q19, Q20, Q21, Q22, Q23, Q24, Q25, Q26, Q27, Q28, Q29, Q30, Q31, Q32 : bool;
end_var
var
tr1, tr2, tr3, tr4, tr5, tr6, tr7, tr8, tr9, tr10, tr11, tr12, tr13, tr14, tr15, tr16 : SYS.RTRIG;
tr17, tr18, tr19, tr20, tr21, tr22, tr23, tr24, tr25, tr26, tr27, tr28, tr29, tr30, tr31, tr32 : SYS.RTRIG;
ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8, ts9, ts10, ts11, ts12, ts13, ts14, ts15, ts16 : dt;
ts17, ts18, ts19, ts20, ts21, ts22, ts23, ts24, ts25, ts26, ts27, ts28, ts29, ts30, ts31, ts32 : dt;
LoadCount : udint; // Текущее количество под загрузкой
nQ : udint; // Следующий в очереди и время его прибытия
minTime : dt; // .. и время его прибытия
end_var
// Фиксируем прибытие в очередь
tr1(I:=I1); tr2(I:=I2); tr3(I:=I3); tr4(I:=I4); tr5(I:=I5); tr6(I:=I6); tr7(I:=I7); tr8(I:=I8);
tr9(I:=I9); tr10(I:=I10); tr11(I:=I11); tr12(I:=I12); tr13(I:=I13); tr14(I:=I14); tr15(I:=I15); tr16(I:=I16);
tr17(I:=I17); tr18(I:=I18); tr19(I:=I19); tr20(I:=I20); tr21(I:=I21); tr22(I:=I22); tr23(I:=I23); tr24(I:=I24);
tr25(I:=I25); tr26(I:=I27); tr27(I:=I27); tr28(I:=I28); tr29(I:=I29); tr30(I:=I30); tr31(I:=I31); tr31(I:=I32);
// Фиксируем время прибытия
if tr1.Q then ts1 := get_date_time(); end_if
if tr2.Q then ts2 := get_date_time(); end_if
if tr3.Q then ts3 := get_date_time(); end_if
if tr4.Q then ts4 := get_date_time(); end_if
if tr5.Q then ts5 := get_date_time(); end_if
if tr6.Q then ts6 := get_date_time(); end_if
if tr7.Q then ts7 := get_date_time(); end_if
if tr8.Q then ts8 := get_date_time(); end_if
if tr9.Q then ts9 := get_date_time(); end_if
if tr10.Q then ts10 := get_date_time(); end_if
if tr11.Q then ts11 := get_date_time(); end_if
if tr12.Q then ts12 := get_date_time(); end_if
if tr13.Q then ts13 := get_date_time(); end_if
if tr14.Q then ts14 := get_date_time(); end_if
if tr15.Q then ts15 := get_date_time(); end_if
if tr16.Q then ts16 := get_date_time(); end_if
if tr17.Q then ts17 := get_date_time(); end_if
if tr18.Q then ts18 := get_date_time(); end_if
if tr19.Q then ts19 := get_date_time(); end_if
if tr20.Q then ts20 := get_date_time(); end_if
if tr21.Q then ts21 := get_date_time(); end_if
if tr22.Q then ts22 := get_date_time(); end_if
if tr23.Q then ts23 := get_date_time(); end_if
if tr24.Q then ts24 := get_date_time(); end_if
if tr25.Q then ts25 := get_date_time(); end_if
if tr26.Q then ts26 := get_date_time(); end_if
if tr27.Q then ts27 := get_date_time(); end_if
if tr28.Q then ts28 := get_date_time(); end_if
if tr29.Q then ts29 := get_date_time(); end_if
if tr30.Q then ts30 := get_date_time(); end_if
if tr31.Q then ts31 := get_date_time(); end_if
if tr32.Q then ts32 := get_date_time(); end_if
// Фиксируем выход из под загрузки
if not I1 then Q1 := false; end_if
if not I2 then Q2 := false; end_if
if not I3 then Q3 := false; end_if
if not I4 then Q4 := false; end_if
if not I5 then Q5 := false; end_if
if not I6 then Q6 := false; end_if
if not I7 then Q7 := false; end_if
if not I8 then Q8 := false; end_if
if not I9 then Q9 := false; end_if
if not I10 then Q10 := false; end_if
if not I11 then Q11 := false; end_if
if not I12 then Q12 := false; end_if
if not I13 then Q13 := false; end_if
if not I14 then Q14 := false; end_if
if not I15 then Q15 := false; end_if
if not I16 then Q16 := false; end_if
if not I17 then Q17 := false; end_if
if not I18 then Q18 := false; end_if
if not I19 then Q19 := false; end_if
if not I20 then Q20 := false; end_if
if not I21 then Q21 := false; end_if
if not I22 then Q22 := false; end_if
if not I23 then Q23 := false; end_if
if not I24 then Q24 := false; end_if
if not I25 then Q25 := false; end_if
if not I26 then Q26 := false; end_if
if not I27 then Q27 := false; end_if
if not I28 then Q28 := false; end_if
if not I29 then Q29 := false; end_if
if not I30 then Q30 := false; end_if
if not I31 then Q31 := false; end_if
if not I32 then Q32 := false; end_if
// Подсчитаем сколько сейчас под загрузкой
LoadCount := 0;
if Q1 then LoadCount := LoadCount + 1; end_if
if Q2 then LoadCount := LoadCount + 1; end_if
if Q3 then LoadCount := LoadCount + 1; end_if
if Q4 then LoadCount := LoadCount + 1; end_if
if Q5 then LoadCount := LoadCount + 1; end_if
if Q6 then LoadCount := LoadCount + 1; end_if
if Q7 then LoadCount := LoadCount + 1; end_if
if Q8 then LoadCount := LoadCount + 1; end_if
if Q9 then LoadCount := LoadCount + 1; end_if
if Q10 then LoadCount := LoadCount + 1; end_if
if Q11 then LoadCount := LoadCount + 1; end_if
if Q12 then LoadCount := LoadCount + 1; end_if
if Q13 then LoadCount := LoadCount + 1; end_if
if Q14 then LoadCount := LoadCount + 1; end_if
if Q15 then LoadCount := LoadCount + 1; end_if
if Q16 then LoadCount := LoadCount + 1; end_if
if Q17 then LoadCount := LoadCount + 1; end_if
if Q18 then LoadCount := LoadCount + 1; end_if
if Q19 then LoadCount := LoadCount + 1; end_if
if Q20 then LoadCount := LoadCount + 1; end_if
if Q21 then LoadCount := LoadCount + 1; end_if
if Q22 then LoadCount := LoadCount + 1; end_if
if Q23 then LoadCount := LoadCount + 1; end_if
if Q24 then LoadCount := LoadCount + 1; end_if
if Q25 then LoadCount := LoadCount + 1; end_if
if Q26 then LoadCount := LoadCount + 1; end_if
if Q28 then LoadCount := LoadCount + 1; end_if
if Q29 then LoadCount := LoadCount + 1; end_if
if Q30 then LoadCount := LoadCount + 1; end_if
if Q31 then LoadCount := LoadCount + 1; end_if
if Q32 then LoadCount := LoadCount + 1; end_if
// Если можно поставить под зашрузку еще кого-то, то ..
if LoadCount < N then
minTime := get_date_time(); nQ := 0; // Пока нет кандидата
// Но если стоишь в очереди и еще не загружаешься и с временем меньше чем у кандитата, то становишься первым кандидатом
if I1 and not Q1 and dt_to_udint(ts1) < dt_to_udint(minTime) then minTime := ts1; nQ := 1; end_if
if I2 and not Q2 and dt_to_udint(ts2) < dt_to_udint(minTime) then minTime := ts2; nQ := 2; end_if
if I3 and not Q3 and dt_to_udint(ts3) < dt_to_udint(minTime) then minTime := ts3; nQ := 3; end_if
if I4 and not Q4 and dt_to_udint(ts4) < dt_to_udint(minTime) then minTime := ts4; nQ := 4; end_if
if I5 and not Q5 and dt_to_udint(ts5) < dt_to_udint(minTime) then minTime := ts5; nQ := 5; end_if
if I6 and not Q6 and dt_to_udint(ts6) < dt_to_udint(minTime) then minTime := ts6; nQ := 6; end_if
if I7 and not Q7 and dt_to_udint(ts7) < dt_to_udint(minTime) then minTime := ts7; nQ := 7; end_if
if I8 and not Q8 and dt_to_udint(ts8) < dt_to_udint(minTime) then minTime := ts8; nQ := 8; end_if
if I9 and not Q9 and dt_to_udint(ts9) < dt_to_udint(minTime) then minTime := ts9; nQ := 9; end_if
if I10 and not Q10 and dt_to_udint(ts10) < dt_to_udint(minTime) then minTime := ts10; nQ := 10; end_if
if I11 and not Q11 and dt_to_udint(ts11) < dt_to_udint(minTime) then minTime := ts11; nQ := 11; end_if
if I12 and not Q12 and dt_to_udint(ts12) < dt_to_udint(minTime) then minTime := ts12; nQ := 12; end_if
if I13 and not Q13 and dt_to_udint(ts13) < dt_to_udint(minTime) then minTime := ts13; nQ := 13; end_if
if I14 and not Q14 and dt_to_udint(ts14) < dt_to_udint(minTime) then minTime := ts14; nQ := 14; end_if
if I15 and not Q15 and dt_to_udint(ts15) < dt_to_udint(minTime) then minTime := ts15; nQ := 15; end_if
if I16 and not Q16 and dt_to_udint(ts16) < dt_to_udint(minTime) then minTime := ts16; nQ := 16; end_if
if I17 and not Q17 and dt_to_udint(ts17) < dt_to_udint(minTime) then minTime := ts17; nQ := 17; end_if
if I18 and not Q18 and dt_to_udint(ts18) < dt_to_udint(minTime) then minTime := ts18; nQ := 18; end_if
if I19 and not Q19 and dt_to_udint(ts19) < dt_to_udint(minTime) then minTime := ts19; nQ := 19; end_if
if I20 and not Q20 and dt_to_udint(ts20) < dt_to_udint(minTime) then minTime := ts20; nQ := 20; end_if
if I21 and not Q21 and dt_to_udint(ts21) < dt_to_udint(minTime) then minTime := ts21; nQ := 21; end_if
if I22 and not Q22 and dt_to_udint(ts22) < dt_to_udint(minTime) then minTime := ts22; nQ := 22; end_if
if I23 and not Q23 and dt_to_udint(ts23) < dt_to_udint(minTime) then minTime := ts23; nQ := 23; end_if
if I24 and not Q24 and dt_to_udint(ts24) < dt_to_udint(minTime) then minTime := ts24; nQ := 24; end_if
if I25 and not Q25 and dt_to_udint(ts25) < dt_to_udint(minTime) then minTime := ts25; nQ := 25; end_if
if I26 and not Q26 and dt_to_udint(ts26) < dt_to_udint(minTime) then minTime := ts26; nQ := 26; end_if
if I27 and not Q27 and dt_to_udint(ts27) < dt_to_udint(minTime) then minTime := ts27; nQ := 27; end_if
if I28 and not Q28 and dt_to_udint(ts28) < dt_to_udint(minTime) then minTime := ts28; nQ := 28; end_if
if I29 and not Q29 and dt_to_udint(ts29) < dt_to_udint(minTime) then minTime := ts29; nQ := 29; end_if
if I30 and not Q30 and dt_to_udint(ts30) < dt_to_udint(minTime) then minTime := ts30; nQ := 30; end_if
if I31 and not Q31 and dt_to_udint(ts31) < dt_to_udint(minTime) then minTime := ts31; nQ := 31; end_if
if I32 and not Q32 and dt_to_udint(ts32) < dt_to_udint(minTime) then minTime := ts32; nQ := 32; end_if
// Если найден подходящий кандидат, то включаем его под загрузку
case nQ of
1: Q1 := true;
2: Q2 := true;
3: Q3 := true;
4: Q4 := true;
5: Q5 := true;
6: Q6 := true;
7: Q7 := true;
8: Q8 := true;
9: Q9 := true;
10: Q10 := true;
11: Q11 := true;
12: Q12 := true;
13: Q13 := true;
14: Q14 := true;
15: Q15 := true;
16: Q16 := true;
17: Q17 := true;
18: Q18 := true;
19: Q19 := true;
20: Q20 := true;
21: Q21 := true;
22: Q22 := true;
23: Q23 := true;
24: Q24 := true;
25: Q25 := true;
26: Q26 := true;
27: Q27 := true;
28: Q28 := true;
29: Q29 := true;
30: Q30 := true;
31: Q31 := true;
32: Q32 := true;
end_case
end_if
end_function_block
В вашем случае идет подсчет времени ожидания и, в принципе, вход с наибольшим накопленным временем тоже кандидат.
Только потребуется схема выборки кандидатов под загрузку. В принципе это можно реализовать и без ST.
FIFO здесь не подойдет, т.к. здесь есть возможность выйти из очереди не дождавшись загрузки.
Vadik2881 з.ы. не смотрел, но цифра 32 это всего 6 битов. Вам кто-то мешает в одной 32-х битной переменной создать "массив" до 5-ти номеров одновременно?
ой, вы тут не номерами оперируете я так понял, а битами даже. Хоть все 32-а устройства (бита) в одну очередь пихайте.
Vadik2881
07.02.2025, 16:35
Не ну EFrol конечно крут, то что надо!!! Спасибо огромное. Действительно, здесь же возможен выход из очереди досрочный и FIFO не подходит.
И самое главное не сильно сложно получилось.
FIFO здесь не подойдет, т.к. здесь есть возможность выйти из очереди не дождавшись загрузки.
Всегда можно пересобрать очередь, тут главное в основе использовать готовые блоки, а не придумывать что то свое, которое даже не представляется возможным как тестировать
Ребята, ну вроде кое что удалось сделать. Сидел долго, даже ST пришлось немного освоить. Кстати крутая штука, но для сложных проектов...
Гляньте проект. Очередь сделал как и хотел - на принципе измерения времени ожидания, т.е. первый проходит у кого оно больше. И достаточно не сложный алгоритм.
Кому не лень, протестируйте пожалуйста на баги. Основной затык был в операторе сравнения на 3 и более входа. И получилось это только в ST!!!
Я тут маленько допилил Ваш вариант.
Vadik2881
07.02.2025, 19:31
Не ну нет слов. Работает. Спасибо EFrol!!!
Единственное, я твой первый алгоритм пытаюсь в MS4d, пока со скрипом...
Второй вариант видимо проще будет.
Ответь в личном, пожалуйста.
Макрос MAX можно переписать под FBD:
81837
где MaxVN:
81838
Vadik2881
08.02.2025, 14:14
Да, наглядный пример превосходства структурированного языка, но это не для слабых умов конечно:))
Мля, с MS4D ковыряюсь, вот же раздули... и информационного материала мало.
Как видите для решения Вашей задачи вполне достаточно и самой простой ПР-ки.
Я использую ПЛК110-60 только когда в задачу соберутся несколько условий:
1. Требуется реализация нестандартного протокола обмена.
2. В системе имеются приборы с различными протоколами и разными скоростями обмена (без 2-го порта не обойтись)
3. Требуется приличное количество дискретных входов и выходов.
4. Требуются "быстрые входы".
5. Требуется объемный обмен данными через Ethernet разными протоколами.
6. Требуется подключение панелей операторов в режиме Мастер (использую RS232).
Если чего-то в задаче нет, то это - "из пушки по воробьям".
А такие задачи - большая редкость.
Чаще всего ПР110 на все про все!!!
Vadik2881 а разве в MS4D нет ST ? там точно еще есть C# правда вроде под отдельной лицензией. И сделать там программу имитирующую ПЛК вроде без проблем.
Правда не знаю архитектуры самой MS4D как она это запускает, может и нельзя. я в RapidScada сделал такое, правда программировать надо в VisualStudio в виде отдельной dll
Vadik2881
08.02.2025, 16:07
Как видите для решением Вашей задачи вполне достаточно и самой простой ПР-ки.
Я использую ПЛК110-60 только когда в задачу соберутся несколько условий:
1. Требуется реализация нестандартного протокола обмена.
2. В системе имеются приборы с различными протоколами и разными скоростями обмена (без 2-го порта не обойтись)
3. Требуется приличное количество дискретных входов и выходов.
4. Требуются "быстрые входы".
5. Требуется объемный обмен данными через Ethernet разными протоколами.
6. Требуется подключение панелей операторов в режиме Мастер (использую RS232).
Если чего-то в задаче нет, то это - "из пушки по воробьям".
А такие задачи - большая редкость.
Чаще всего ПР110 на все про все!!!
Ну я как раз согласен за оптимальность. Ну не 110пр конечно, но 205 везде работает хорошо.
Но опять же, мы ещё до сервосистем недошли, но тут видимо овену пока не светит.
Да, ПЛК110-60 это избыток в данном случае, но он валяется уже 4 года без дела и смотрю его уже сняли с производства и поддержки. Это то про что постоянно говорю. Да, сименс дорого, но он сименс и через 10 лет и через 50, а это для пром производства, где очень сложное оборудование - очень важно.
В общем надо его применить в качестве резерва у меня тут одной устающей системе управления загрузкой сырья Motan.
Но ещё мне не нравится применение панелей оператор с софтом. У Овена это СПЗхх. Это дополнительная уязвимость оборудованию ну и гляньте сколько панель в 15 дюймах стоит, аж 120 тысяч. За эти деньги можно шикарный комп промышленный с огромным монитором поставить.
Вот жду недождусь прихода ПР103 с Ethernet.
Я бы не лез во всякие полигоны, а OwenLogic развивал. Скорость, память добавить и можно на крупные объекты смотреть.
Vadik2881
08.02.2025, 16:23
Vadik2881 а разве в MS4D нет ST ? там точно еще есть C# правда вроде под отдельной лицензией. И сделать там программу имитирующую ПЛК вроде без проблем.
Правда не знаю архитектуры самой MS4D как она это запускает, может и нельзя. я в RapidScada сделал такое, правда программировать надо в VisualStudio в виде отдельной dll
Есть конечно ST в MS4D но структура и синтаксис местами отличается почему-то, название системных функций другие. Я слабый программист в ST, но думал, что он должен единым для всех устройств... Скопировать тупо не выходит... Вот пытаюсь натянуть первый алгоритм от EFrol в ST, попутно разбираясь в самой MS4D. Но у них организация дерева системы очень непонятное. То-ли специально запутать и зарабатывать на обучении, то-ли для возможностей. Работа с физическим узлом тоже какая-то не информативная. Не ну понятно, надо погружаться и осваивать...
kondor3000
08.02.2025, 18:03
Т.е. если бы насос справлялся, то можно было бы заправлять все 32 загрузчика?
А так как можно только N-загрузчика одновременно, то следующим становиться под загрузку тот, кто приехал раньше из всех ожидающих?
Предлагаю такой вариант:
81835
// Фиксируем прибытие в очередь
tr1(I:=I1); tr2(I:=I2); tr3(I:=I3); tr4(I:=I4); tr5(I:=I5); tr6(I:=I6); tr7(I:=I7); tr8(I:=I8);
tr9(I:=I9); tr10(I:=I10); tr11(I:=I11); tr12(I:=I12); tr13(I:=I13); tr14(I:=I14); tr15(I:=I15); tr16(I:=I16);
tr17(I:=I17); tr18(I:=I18); tr19(I:=I19); tr20(I:=I20); tr21(I:=I21); tr22(I:=I22); tr23(I:=I23); tr24(I:=I24);
tr25(I:=I25); tr26(I:=I27); tr27(I:=I27); tr28(I:=I28); tr29(I:=I29); tr30(I:=I30); tr31(I:=I31); tr31(I:=I32);
FIFO здесь не подойдет, т.к. здесь есть возможность выйти из очереди не дождавшись загрузки.
Нашёл ошибочку, 32 R_Trig не работает 81861 Указан 31
Vadik2881
08.02.2025, 18:20
Вот так ST выглядит в MS4D. Всё работает, радуюсь как ребёнок:) EFrol спасибо огромное, там ещё много довешивать, но это самое трудное для меня было.
Меняю своё мнение на счёт ST, думал не нужен. Хотя данная задача и решается на FBD но на грани максимума. Но осваивать полноценно ST мы конечно не будем:) на это нужно время и постоянная практика...
Нашёл ошибочку, 32 R_Trig не работает 81861 Указан 31
ОЧЕпятка!! Принято. Спасибо.
То-ли специально запутать и зарабатывать на обучении, то-ли для возможностей.
с вероятностью 99% по другому у программиста не получилось :) по себе знаю.
а вместо if not I1 then Q1:=false нельзя писать if !I1 Q1:=false ????
kondor3000
08.02.2025, 20:19
с вероятностью 99% по другому у программиста не получилось :) по себе знаю.
а вместо if not I1 then Q1:=false нельзя писать if !I1 Q1:=false ????
Нельзя, это ST, зато можно Q1:=(not I1=false);
Нельзя, это ST, зато можно Q1:=(not I1=false);
Я опять что-то пропустил? Q1 := (not I1=false); это же Q1 := I1;
if not I1 then Q1 := false; end_if - это же Импликация (https://ru.wikipedia.org/wiki/%D0%98%D0%BC%D0%BF%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D 0%B8%D1%8F)
При I1=true - Q1 не меняет своего состояния.
kondor3000
09.02.2025, 10:27
Я опять что-то пропустил? Q1 := (not I1=false); это же Q1 := I1;
if not I1 then Q1 := false; end_if - это же Импликация (https://ru.wikipedia.org/wiki/%D0%98%D0%BC%D0%BF%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D 0%B8%D1%8F)
При I1=true - Q1 не меняет своего состояния.
Я и не спорю, но в данном случае, прокатывают оба варианта, можете проверить, Скрин 81872
Я и не спорю, но в данном случае, прокатывают оба варианта, можете проверить, Скрин 81872
Проверил! Не прокатило!
81873
При 3 допустимых на погрузке.
После того как под погрузку встали Q3, Q4, Q5, I1 и I2 поставили Q1 и Q2 под погрузку без разрешения.
kondor3000
09.02.2025, 11:53
Проверил! Не прокатило!
При 3 допустимых на погрузке.
После того как под погрузку встали Q3, Q4, Q5, I1 и I2 поставили Q1 и Q2 под погрузку без разрешения.
Уговорили))) менял только 2 строки, больше не проверял)
А вот была бы очередь из оскат библиотеки, то размерностью массива можно было четко зафиксировать скольким юнитам разрешено вставить в очередь, т.ч. зря отказались
Уговорили))) менял только 2 строки, больше не проверял)
У языка Си бывают приколы. Точнее у компиляторов под различные платформы.
Например, синтаксически допустимая запись:
if(u1)
if(u2) ret = 0;
else ret = 1;
Вопрос: К какому if относится else?
А вот была бы очередь из оскат библиотеки, то размерностью массива можно было четко зафиксировать скольким юнитам разрешено вставить в очередь, т.ч. зря отказались
Я с большим уважением отношусь к библиотекам OSCAT, но создавать их самому намного интересней. Вы уж извините.
Я с большим уважением отношусь к библиотекам OSCAT, но создавать их самому намного интересней. Вы уж извините.
Ну так делать обвязку стека применительно к конкретной задаче не менее увлекательно. И отлаживать надо конкретный код, а не все подряд на несколько шагов в глубь
Ну так делать обвязку стека применительно к конкретной задаче не менее увлекательно. И отлаживать надо конкретный код, а не все подряд на несколько шагов в глубь
Я случайно попал на эту тему. С MS4D никогда не работал. Привлёк код на ST для ПР с просьбой потестить. Не смог пройти мимо.
Если бы речь шла об обычном ПЛК110-60, наверно бы использовал именно OSCAT и делал именно так, как Вы рекомендуете.
EFrol по идее ко второму если скобками не определено обратное.
EFrol по идее ко второму если скобками не определено обратное.
Логично. Именно так и по описанию. Но некоторые компиляторы считают иначе. Приходится добавлять скобки для однозначности.
странные компиляторы, учитывая что if_else это всегда пара. то есть когда скобок нет, компилятор должен определить первый к нему if и связать их.
странные компиляторы, учитывая что if_else это всегда пара. то есть когда скобок нет, компилятор должен определить первый к нему if и связать их.
https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_st_instruction_if.html
Ветви ELSIF и ветвь ELSE являются необязательными
https://content.helpme-codesys.com/en/CODESYS%20Development%20System/_cds_st_instruction_if.html
Ветви ELSIF и ветвь ELSE являются необязательными
melky имел ввиду что else относится первому if слева от этого else, а не про то что они обязательно парные.
melky имел ввиду что else относится первому if слева от этого else, а не про то что они обязательно парные.
Это как то отменяет неопределенность что предположительно второй иф может быть не парным?
если коротко - нет непределености
А если кто по разному интерпретирует, значит кто-то из двоих не следует стандарту
да, я говорю о том, что если else проставлен, то он является парой ближайшего if а не через три звезды от него.
Если форматированием (скобками) не определено иное.
Vadik2881
16.02.2025, 11:54
Привет коллеги. Ну чего, проект готов где-то на 80%. C MS4D освоился, ну точнее на нужном мне уровне... Но проект достаточно крупный. Мне она определённо нравится, несмотря кажущуюся громоздкость.
Это моя вторая скада после simple и из двух выбрал бы MS4D. Для не очень продвинутых программистов само то!
Пока всё на столе конечно, скоро потестим в полевых. Мне очень нравиться как работает всё в связке и контроллером и сам WEB доступ.
Поскольку в качестве панели оператора планируется обычный комп с тачскриновким монитором. Решил попробовать начать придерживаться такой концепции.
попозже опишусь как и что...
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot