PDA

Просмотр полной версии : Отображение данных с ПЛК210 на цифровом дисплее СП310-Р



Mikhail_NNT
05.01.2025, 12:56
Добрый день,

Есть необходимость вывести на панель заданное время таймера (уставка в программе задана в секундах) и оставшееся время до его отключения (рассчитывается в программе в секундах) в секундах.
ПЛК - Мастер, Панель - Слейв. Протокол ModBus TCP.

Панель: два цифровых дисплея с регистрами PSW типом значений WORD форматов Unsigned c разрядностью 6 знаков до запятой.

81117 81118

ПЛК: две переменных типа WORD, в которые заносятся значения в секундах. Программа работает правильно, и заносит в переменные корректные значения. Соответствующие регистры Панели привязаны к переменным ПЛК.

81119 81120 81121

На визуализации Панели получаю непонятный результат значений переменных. Перепроверял типы данных, привязку регистров к переменным, привязку регистров к цифровым дисплеям. Не понимаю, что делаю не так?

81122

kondor3000
05.01.2025, 13:31
Передаёте в секундах или минутах? Где пересчитываете?
Время TIME, надо конвертировать в DWORD, разделить на 1000, для перевода в секунды и передавать или ещё проще пересчитать в минуты разделив на 60 и тогда передавать как WORD.
Тип данных WORD, это максимальное число 65535, для передачи 6 знаков как у вас, необходимо использовать DWORD.
Типы данных давно надо было выучить)

Mikhail_NNT
05.01.2025, 14:27
Нужно будет передавать в минутах. На данный момент, пока разбираюсь, передаю в секундах.
Получается, если я ограничу разрядность до 4 знаков, то могу использовать WORD?

Пересчитываю в Main PRG:

dwSetTime:=TO_DWORD (TargetVars.tSetTactTime/1000) //заданное время счетчика
dwRemainTime:=TO_DWORD ((TargetVars.tSetTactTime-TargetVars.fbTimerTOFPause/1000) //заданное время счетчика

МихаилГл
05.01.2025, 14:46
Вы в самих регистрах плк что видите? То же, что хотите увидеть на панели, или что-то другое. Вы сразу на панель грешите, а может дело в том, что вы не то и отдаете...? Но это выше другими словами сказано. Сначала добейтесь, чтобы в плк было то число, что вам нужно. Word или Dword, а потом за панель беритесь.

PS Еще и коилы с регистрами используете...

PS2 8229 в плк и на панели... Что не так то? Где "неправильно"?

kondor3000
05.01.2025, 16:51
Нужно будет передавать в минутах. На данный момент, пока разбираюсь, передаю в секундах.
Получается, если я ограничу разрядность до 4 знаков, то могу использовать WORD?

Пересчитываю в Main PRG:

dwSetTime:=TO_DWORD (TargetVars.tSetTactTime/1000) //заданное время счетчика
dwRemainTime:=TO_DWORD ((TargetVars.tSetTactTime-TargetVars.fbTimerTOFPause/1000) //заданное время счетчика

Ошибка ваша в том, что вы до конвертации в DWORD делите на 1000, а надо делить после конвертации. И только потом, выделив минуты и секунды, конвертировать в WORD.
Передавать надо в секундах или отдельно в минутах и секундах, иначе секунды потеряете.

МихаилГл
05.01.2025, 17:48
А панель точно адекватно обрабатывает сначала 16 команду, потом 3...
Никогда СП315 как слэйв не пробовал использовать.

Может попробуете отдельно сначала без 3 для 012С области, потом без 16... Т.е. удалите сначала одну из опроса на чтение, потом другую без опроса на запись. Надо после праздников глянуть, что-то тут не так. Слэйв это та еще штука...

Mikhail_NNT
06.01.2025, 10:47
Ошибка ваша в том, что вы до конвертации в DWORD делите на 1000, а надо делить после конвертации. И только потом, выделив минуты и секунды, конвертировать в WORD.
Передавать надо в секундах или отдельно в минутах и секундах, иначе секунды потеряете.

По замечаниям, все исправил. Действительно, сейчас программа работает и выдает нужные (правильные) значения переменных.
Зеленым выделены значения, которые должны считываться из переменных ПЛК и выводятся на Панель.
Красным выделил значения, которые должны задаваться с Панели и передаваться в переменные ПЛК.

81134 81135

Mikhail_NNT
06.01.2025, 11:08
Вы в самих регистрах плк что видите? То же, что хотите увидеть на панели, или что-то другое. Вы сразу на панель грешите, а может дело в том, что вы не то и отдаете...? Но это выше другими словами сказано. Сначала добейтесь, чтобы в плк было то число, что вам нужно. Word или Dword, а потом за панель беритесь.

PS Еще и коилы с регистрами используете...

PS2 8229 в плк и на панели... Что не так то? Где "неправильно"?

По ПЛК все работает четко и выдаёт правильные значения переменных, которые должны отображаться на Панели, при условии, что правильно заданы переменные, которые должны подгружаться из Панели в ПЛК.

81136
Но даже с рабочей программой, на Панели отображаются неверные значения, и вводимые значения с Панели не передаются в ПЛК.

81137 81138
В Конфигураторе заданы настройки для элементов Ввода данных и Цифрового дисплея (разрядность 4, формат Unsigned).

81139 81140
Каналы для HMI настроены, но думаю дело в них, раз на Панели некорректное отображение. Для считывания из элемента Ввод данных нужна триггерная переменная, или данные будут циклично считываться? Использую coils, так как на элементе Панели регистр PFW (данные должны загружаться при загрузки ПЛК).
К слову, каналы №4 и №5 работают и передают значения на Панель, правда Bool, а не Word.

81141

Mikhail_NNT
06.01.2025, 11:23
При загрузке программы на ПЛК (без принудительно заданных значений) наблюдаю непонятные значения переменных. Откуда они берутся?
Интересуют переменные, выделенные красным, они задаются с Панели. На основе их значений рассчитываются и отображаются переменные, выделенные зеленым. Кстати, зеленные переменные отображаются корректно (с текущими неверными значениями красных переменных) в ПЛК, но неверно на Панели.
81142 81143 81144

МихаилГл
06.01.2025, 11:32
А разве 16 и 03 это не одна область холдинг регистров? Судя по документации СП315 это одна область PSW. А ни как не PSW и PFW, как вы подписали.

https://wiki.navtelecom.ru/ru/home/developers/protocols/modbus

kondor3000
06.01.2025, 11:35
По замечаниям, все исправил. Действительно, сейчас программа работает и выдает нужные (правильные) значения переменных.
Зеленым выделены значения, которые должны считываться из переменных ПЛК и выводятся на Панель.
Красным выделил значения, которые должны задаваться с Панели и передаваться в переменные ПЛК.

81134 81135

Тут есть проблема, отображать полученное время в панели можно в мин и сек, на одном дисплее. А вот задать вы можете только в секундах (один дисплей)
или в мин. и секундах (2 дисплея)

kondor3000
06.01.2025, 11:40
При загрузке программы на ПЛК (без принудительно заданных значений) наблюдаю непонятные значения переменных. Откуда они берутся?
Интересуют переменные, выделенные красным, они задаются с Панели. На основе их значений рассчитываются и отображаются переменные, выделенные зеленым. Кстати, зеленные переменные отображаются корректно (с текущими неверными значениями красных переменных) в ПЛК, но неверно на Панели.


Вам надо создать новый проект, добавить по 1 переменной чтения и записи и разобраться с передачей.
Либо вы пишите не туда, либо накладываются адреса регистров.

Mikhail_NNT
06.01.2025, 11:44
Тут есть проблема, отображать полученное время в панели можно в мин и сек, на одном дисплее. А вот задать вы можете только в секундах (один дисплей)
или в мин. и секундах (2 дисплея)

Все верно, отображаю в секундах на одном дисплее, и задаю в секундах на одном дисплее.

kondor3000
06.01.2025, 11:47
При загрузке программы на ПЛК (без принудительно заданных значений) наблюдаю непонятные значения переменных. Откуда они берутся? 81143


Число 8229 это 2025 год в HEX , скорее всего вы в панели выводите дату и время в эти регистры) 81146
Посмотрите в настройках панели, стоит галка вывода времени?

Mikhail_NNT
06.01.2025, 13:18
А разве 16 и 03 это не одна область холдинг регистров? Судя по документации СП315 это одна область PSW. А ни как не PSW и PFW, как вы подписали.

https://wiki.navtelecom.ru/ru/home/developers/protocols/modbus

Делал обмен "СП300 --- Мастер" по обучающему видео https://rutube.ru/video/d10dd867827a77ef9e369bffa16606d2/

В нем говориться, что PSW 256 --- Holding Registers 256, PFW256 --- Holding Registers 10256. Я думал, что ПЛК сам понимает и использует регистры 256 и 10256 соответственно.

81148

Для проверки изменил регистры у красных переменных, чтобы не пересекались. При загрузке программы во всех зелёных и красных переменных значение 0.

Mikhail_NNT
06.01.2025, 13:22
Число 8229 это 2025 год в HEX , скорее всего вы в панели выводите дату и время в эти регистры) 81146
Посмотрите в настройках панели, стоит галка вывода времени?

Да, вы правы, галка стояла - убрал. Теперь выводятся нули, так как значения заданных переменных нули. Думаю, сейчас с отображением значений все верно.

Почему при вводе значений с панели они не записываются в переменные? Нужна триггерная переменная?
При перезагрузке ПЛК значения введенных переменных остаются на Панели, но не передаются в ПЛК.
При попытке присвоить значения в Codesys, они не присваиваются - остаются нули.

81149

МихаилГл
06.01.2025, 13:40
10256 и 256
Ххххх и 012С
Найдите 16ричный код с 10256... Это не 012С

012С это даже 300 регистр, а 10300 тогда 283С

kondor3000
06.01.2025, 13:54
Почему при вводе значений с панели они не записываются в переменные? Нужна триггерная переменная?
При перезагрузке ПЛК значения введенных переменных остаются на Панели, но не передаются в ПЛК.
При попытке присвоить значения в Codesys, они не присваиваются - остаются нули.

Теперь про адреса, какие вы используете в панели и какие в ПЛК? Как читаете и как записываете?
Чтение то у вас правильно было, а записывать из ПЛК надо по триггеру. В панели для записи триггер не нужен.

МихаилГл
06.01.2025, 13:56
Теперь про адреса, какие вы используете в панели и какие в ПЛК? Как читаете и как записываете?

Да у него там не понятно, читает и записывает с 300 (16х012С), а в панели прописаны с 256го... Напутал походу... :)

PS Не тот скрин глянул. Это пример похоже к 256 обращается, а ТС с 300 по 309. Но PFW это 10300-10309. В первом сообщении скрин карты регистров.

Mikhail_NNT
06.01.2025, 14:43
Еще раз опишу, чтобы понять, что я напутал.

Панель СП310-Р --- Слейв, ПЛК 210 --- Мастер, протокол ModBus TCP ( вывод значений с ПЛК на Панель с каналов №4 и №5 работает как надо).

Использую канал №6 для вывода значения 2-х переменных (PSW 300, PSW 302) ПЛК на Панель, канал №7 для записи введенных значений 3-х переменных (PFW310, PFW 312, PFW314) Панели на ПЛК.
81152 81153

В Конфигураторе два цифровых дисплея PSW 300 и PSW 302 (Word, Unsigned, 4 знака), три ввода данных PFW310, PFW 312, PFW314 (Word, Unsigned, 4 знака).
81154 81155

Ниже код Main программы ПЛК, где обрабатываются все переменные.
81156

Нужно, чтобы при вводе значений на Панели и после выключения/перезагрузки ПЛК, они присваивались переменным ПЛК.

Сейчас наблюдаю следующее, при включении ПЛК, в Codesys во всех переменных нули, на Панели раннее введенные значения (но не переданные в переменные ПЛК).
При попытке задать значения в Codesys, сразу сбрасываются на нули.

Пересмотрел еще раз вышеуказанное видео, перепроверил элементы, переменные и каналы. С регистрами PSW и PFW на видео одна информация, по факту все не так.
Сам уже запутался, не пойму в чем ошибся.

МихаилГл
06.01.2025, 14:50
В плк210 для pfw области адресация должно быть не для 300 регистра, а для 10300. А в СП315 это будут PFW 300 регистры и далее. Вроде так.

А у вас все регистры в плк обозначены для PSW области панели.

kondor3000
06.01.2025, 16:01
Для регистра PFW310, адрес должен быть 10310 или в HEX 16#2846, а у вас адрес 310 или 16#0136. 81159

Чтобы не путаться забивайте адрес в DEC, в в HEX комп сам переведёт

МихаилГл
07.01.2025, 10:34
Для регистра PFW310, адрес должен быть 10310 или в HEX 16#2846, а у вас адрес 310 или 16#0136. 81159

Чтобы не путаться забивайте адрес в DEC, в в HEX комп сам переведёт

Согласно руководства это зона холдинг регистров, просто энергонезависимая...

Ну да ладно. Что-то не видно "начальника транспортного цеха". Хотелось бы услышать получилось или нет... А то не напишет больше, а мы тут 2 дня все что-то обдумываем...

Mikhail_NNT
08.01.2025, 09:13
Доброе утро! Рождество же было, отдыхали)

Все верно, напутал с адресами для регистров! На Панели и в ПЛК появилось отображение верных значений, вводимых с Панели.


kondor3000 и МихаилГл спасибо большое за помощь в решении проблемы! И за объяснения принципов работы обмена Панель - ПЛК)

Mikhail_NNT
08.01.2025, 12:00
Вопрос может не в тему, но как к опытным товарищам:

Есть простейшая часть программы - Если нажата кнопка с фиксацией загорается лампа и издается звуковой сигнал 2 секунды, если кнопка с фиксацией отжата, то лампа гаснет.
81188

Переменные, привязанные к входам/выходам модулей на вкладке Соотнесения входов/выходов меняют свои значения, при выполнении программы, т.е. при нажатии кнопки с фиксацией лампа загорается, при отжатии - гаснет.
81189 81190

Но в коде программы значения не меняются с Истины на Ложь и обратно. При этом физически все работает: при нажатии кнопки загорается соответствующий вход, далее загорается соответствующий выход на лампу и она горит.
И таймер ТР также работает некорректно: должен при нажатии кнопки с фиксацией (по ее заднему фронту) запуститься на 2 секунды и все. В реальности запускается при нажатии кнопки на бесконечный цикл 2 секунды, при отжатии кнопки - отключается после отработки заданного времени.

Именно эта часть кода так себя ведет, остальная программа работает как положено. С чем это может быть связано?

1exan
08.01.2025, 12:27
Вопрос может не в тему, но как к опытным товарищам:

Есть простейшая часть программы - Если нажата кнопка с фиксацией загорается лампа и издается звуковой сигнал 2 секунды, если кнопка с фиксацией отжата, то лампа гаснет.


Переменные, привязанные к входам/выходам модулей на вкладке Соотнесения входов/выходов меняют свои значения, при выполнении программы, т.е. при нажатии кнопки с фиксацией лампа загорается, при отжатии - гаснет.


Но в коде программы значения не меняются с Истины на Ложь и обратно. При этом физически все работает: при нажатии кнопки загорается соответствующий вход, далее загорается соответствующий выход на лампу и она горит.
И таймер ТР также работает некорректно: должен при нажатии кнопки с фиксацией (по ее заднему фронту) запуститься на 2 секунды и все. В реальности запускается при нажатии кнопки на бесконечный цикл 2 секунды, при отжатии кнопки - отключается после отработки заданного времени.

Именно эта часть кода так себя ведет, остальная программа работает как положено. С чем это может быть связано?

Таймер ТР - где он на скринах?

melky
08.01.2025, 12:28
как может быть цикл в 2 сек бесконечным ? :)

вероятно у вас через цикл таймер перезапускается. Не силен в ST, но скорее всего, если есть запустить эмуляцию по шагам это будет видно.

Mikhail_NNT
08.01.2025, 12:36
Таймер ТР - где он на скринах?

Выделил красным
81193

Mikhail_NNT
08.01.2025, 12:39
как может быть цикл в 2 сек бесконечным ? :)

вероятно у вас через цикл таймер перезапускается. Не силен в ST, но скорее всего, если есть запустить эмуляцию по шагам это будет видно.

Да, таймер запускается на 2 секунды, после отработки снова на 2 секунды и так далее. Может быть этот как-то связано с переменными, которые не меняют свое значение?

1exan
08.01.2025, 12:42
Выделил красным


А куда его выход привязан?

Вообще это
81194
Можно заменить на


xRedLamp := xRedButton;
tpRedBuzzer(IN := rtClickRedButton.Q, PT :- t#2s);

Mikhail_NNT
08.01.2025, 13:10
А куда его выход привязан?

Вообще это
81194
Можно заменить на


xRedLamp := xRedButton;
tpRedBuzzer(IN := rtClickRedButton.Q, PT :- t#2s);


Да, код намного компактнее) Заменил.

Привязку выхода таймера к переменной пока убрал, чтобы над ухом зуммер не шумел. А так переменная привязана к выходу модуля (выделил зеленым).
81195

МихаилГл
08.01.2025, 13:34
Тоже хотел про код где кнопка и лампа написать... Но уже направили...
Кстати, условие ниже тоже можно сократить:
Альфа:= Бета ЭНД Гамма...

melky
08.01.2025, 13:53
так если у вас 2 сек работа, 2 сек пауза, опять 2 сек работа и т.д. Зачем там ТР ? ну BLINK поставьте и все. Если это для работы зуммера.

1exan
08.01.2025, 14:27
Да, таймер запускается на 2 секунды, после отработки снова на 2 секунды и так далее. Может быть этот как-то связано с переменными, которые не меняют свое значение?

Наверное связано и скорее всего, проблема не в приведённом участке программы

Mikhail_NNT
08.01.2025, 14:29
так если у вас 2 сек работа, 2 сек пауза, опять 2 сек работа и т.д. Зачем там ТР ? ну BLINK поставьте и все. Если это для работы зуммера.

Нужно, чтобы при нажатии на кнопку зуммер пропищал 2 секунды и на этом все. Blink не требуется.

melky
08.01.2025, 15:19
ну тогда ищите, почему у вас таймер постоянно перезапускается. ТР работает просто, по стартовому импульсу на входе отрабатывает свою задержку и все.
Даже если на входе выставить 0 до истечения задержки. Если он у вас перезапускается, значит вы дергаете его вход IN где-то в коде.

Наверное самая примитивная ошибка Авария И НОТ ТР.Кью - запустить таймер. Вот он и будет стартовать каждый раз, когда будет сам выключаться

Mikhail_NNT
16.01.2025, 10:37
Заметил не понятное для меня поведение Slave HMI:
На вкладке Каналов указаны 10 каналов с определенными регистрами и длинами (все по 10 раз перепроверил, привязка правильная).
81343
На вкладке Соотнесения входов/выходов ситуация непонятная. Присутствуют нужные мне каналы, а также сторонние каналы (то ли дублирующие, то ли еще какие). Удалить их не получается.
81344
В процессе отладки менял параметры каналов по нескольку раз. Могло это произойти из-за этого?

Вижу только один выход - удалить канал и заново создать. НО! К некоторым каналам привязаны по 200-300 переменных, не хотелось бы заново этим заниматься.

kondor3000
16.01.2025, 12:58
В процессе отладки менял параметры каналов по нескольку раз. Могло это произойти из-за этого?

Вижу только один выход - удалить канал и заново создать. НО! К некоторым каналам привязаны по 200-300 переменных, не хотелось бы заново этим заниматься.

Проверять обмен надо было до написания проекта на 3-5 переменных.
Теперь лучше будет всё удалить и сделать заново, учитывая все ошибки и возможно исправив последовательность регистров.
Заодно и повторите пройденный материал))

Mikhail_NNT
18.01.2025, 15:03
Проверять обмен надо было до написания проекта на 3-5 переменных.
Теперь лучше будет всё удалить и сделать заново, учитывая все ошибки и возможно исправив последовательность регистров.
Заодно и повторите пройденный материал))

С каналами разобрался, все переделал - работает:o


ну тогда ищите, почему у вас таймер постоянно перезапускается. ТР работает просто, по стартовому импульсу на входе отрабатывает свою задержку и все.
Даже если на входе выставить 0 до истечения задержки. Если он у вас перезапускается, значит вы дергаете его вход IN где-то в коде.

Наверное самая примитивная ошибка Авария И НОТ ТР.Кью - запустить таймер. Вот он и будет стартовать каждый раз, когда будет сам выключаться

Наблюдал за поведением переменных при наступлении события (при нажатии кнопки, должна загореться лампа и пропищать 2 секунды зуммер; при отключении кнопки, лампа гаснет):
При нажатии кнопки на модуле входов загорается соответствующий вход и переменная, привязанная к этому входу, меняет свое значение с Ложь на Истина.
81395
Но почему-то это значение не передается в локальные переменные двух ФБ.
81401
Из Списка перекрестных ссылок видно, что переменная объявляется один раз в Главной программе, и два раза читается ее значение при вызове двух ФБ. Что означают остальные записи IoConfig_ErrorPou? В одной из них также идет запись. Может в этом дело?
81397
В обеих ФБ, код завязанный на этой переменной работает некорректно, так как внутри ФБ значения привязанных переменных не меняются.
81398 81399

kondor3000
18.01.2025, 15:13
С каналами разобрался, все переделал - работает:o



Наблюдал за поведением переменных при наступлении события (при нажатии кнопки, должна загореться лампа и пропищать 2 секунды зуммер; при отключении кнопки, лампа гаснет):
При нажатии кнопки на модуле входов загорается соответствующий вход и переменная, привязанная к этому входу, меняет свое значение с Ложь на Истина.


У вас i=21 в цикле FOR, а смотрите вы переменную [17] в массиве. Поставьте после цикла i:=17;

melky
18.01.2025, 15:16
https://owen.ru/forum/attachment.php?attachmentid=81401&d=1737201431

Ну не понимаю я ST, отстаньте от меня :) - все, что я вижу и могу предположить, что в True у вас 17-й индекс регистра. А в цикле FOR у вас последний индекс регистра, который false.

И далее по программе у вас все перетирается по несколько раз.

МихаилГл
18.01.2025, 15:18
Все передается. Вы мониторите (17) бит, а в онлайне отображается последний для (21) структуры.

PS Пока изучал скрины и писал ответ, уже прилетело 2 ответа выше...

PS2 А еще столько много лишнего кода даже в этих нескольких скринах, аж кровь из глаз.

Mikhail_NNT
20.01.2025, 08:16
Все передается. Вы мониторите (17) бит, а в онлайне отображается последний для (21) структуры.

PS Пока изучал скрины и писал ответ, уже прилетело 2 ответа выше...

PS2 А еще столько много лишнего кода даже в этих нескольких скринах, аж кровь из глаз.

Это моя первая программа в CODESYS и на ST) Изучаю среду программирования, осваиваю новый язык и параллельно пишу код. До этого иногда приходилось писать простецкие программы на LAD под контроллеры AB.

МихаилГл
20.01.2025, 08:21
Это моя первая программа в CODESYS и на ST) Изучаю среду программирования, осваиваю новый язык и параллельно пишу код. До этого иногда приходилось писать простецкие программы на LAD под контроллеры AB.

Даже на LD в ален брэдли (AB) есть вложенные циклы for ..., где вы также увидите только последние значения, если не сделаете "финт ушами") Похоже ваши программы были очень очень очень простецкими...

Mikhail_NNT
20.01.2025, 08:25
Даже на LD в ален брэдли (AB) есть вложенные циклы for ..., где вы также увидите только последние значения, если не сделаете "финт ушами") Похоже ваши программы были очень очень очень простецкими...

Так оно и есть, программы типа "Если нажата кнопка, то горит лампа" и приходилось это делать очень не часто) Получается сейчас с нуля все познаю.

МихаилГл
20.01.2025, 08:31
Так оно и есть, программы типа "Если нажата кнопка, то горит лампа" и приходилось это делать очень не часто) Получается сейчас с нуля все познаю.

Тогда все If ... Then ... Else ... , где логика в Then и Else противоположна, просто делайте как: А:= В (в В условие If, в А параметр из Then ... или Else ...).
И Q=> тоже лишние, можно удалить.



If B=true (Можно написать так: If B)
then A:=true
else A:=false

Меняете на:

A:=B

Mikhail_NNT
20.01.2025, 08:53
Тогда все If ... Then ... Else ... , где логика в Then и Else противоположна, просто делайте как: А:= В (в В условие If, в А параметр из Then ... или Else ...).
И Q=> тоже лишние, можно удалить.



If B=true (Можно написать так: If B)
then A:=true
else A:=false

Меняете на:

A:=B


Спасибо!)

Понял почему таймер циклически перезапускается. У меня кнопка с фиксацией (Emergency stop), я ловлю ее фронт, а так как она с фиксацией, то выход фронта всегда Истина.
81425
Не могу понять как мне это обойти? Пробовал использовать TOF вместо TP, вообще не запускается.
Как запускать таймер на 2 секунды с кнопки с фиксацией?

МихаилГл
20.01.2025, 09:13
Спасибо!)

Понял почему таймер циклически перезапускается. У меня кнопка с фиксацией (Emergency stop), я ловлю ее фронт, а так как она с фиксацией, то выход фронта всегда Истина.
81425
Не могу понять как мне это обойти? Пробовал использовать TOF вместо TP, вообще не запускается.
Как запускать таймер на 2 секунды с кнопки с фиксацией?

81426
как то так

добавил кнопку сброса (не квитирования, это немного по другому работает)... можно просто из последнего условия его убрать, но это уже неправильный подход...

PS Там отсечка на выключение сирены... А не лампы.

PS2: Неправильный по моему мнению вариант

//IF alarm_button THEN //взвели сигнал аварии
// alarm_lamp:= TRUE;
//END_IF
alarm_lamp:= alarm_button;
alarm_TON(IN:= alarm_lamp, PT:= T#2S); //отсечка на выключение сирены Х секунд
alarm_beep:= (alarm_lamp AND NOT alarm_TON.Q);
//IF alarm_reset AND NOT alarm_button THEN //сбросили сигнал аварии - квитирование
// alarm_lamp:= FALSE;
//END_IF

melky
20.01.2025, 09:49
Ну если кнопка с фиксацией а для ТП нужен импульс с проверкой выхода таймера. То типа Кнопа - Rtrig - переменнаяХ и уже эту переменную использовать для запуска.

ПеременнаяХ И !TP.Q --- старт TP
А когда вы используете просто сигнал кнопки тут, то таймер сам себя будет перезапускать, как выше писал. Просто потому, что TP так работает.

МихаилГл
20.01.2025, 09:51
Ну если кнопка с фиксацией а для ТП нужен импульс с проверкой выхода таймера. То типа Кнопа - Rtrig - переменнаяХ и уже эту переменную использовать для запуска.

ПеременнаяХ И !TP.Q --- старт TP
А когда вы используете просто сигнал кнопки тут, то таймер сам себя будет перезапускать, как выше писал. Просто потому, что TP так работает.

Вот поэтому я всегда только TON использую)

melky
20.01.2025, 09:57
Ну TP тоже нужен. для Ton потребуется дополнительный сброс чтобы получить Pulse Timer. А тут просто дополнительный флаг после RTrig.
Вообще в "бумажных" языках (ST, C#, других) с таймерами легко намудрить. В FBD это выглядит все проще, так как запуск таймера вынесен в другие FDB в качестве условий.

Mikhail_NNT
20.01.2025, 12:27
81426
как то так

добавил кнопку сброса (не квитирования, это немного по другому работает)... можно просто из последнего условия его убрать, но это уже неправильный подход...

PS Там отсечка на выключение сирены... А не лампы.

PS2: Неправильный по моему мнению вариант

//IF alarm_button THEN //взвели сигнал аварии
// alarm_lamp:= TRUE;
//END_IF
alarm_lamp:= alarm_button;
alarm_TON(IN:= alarm_lamp, PT:= T#2S); //отсечка на выключение сирены Х секунд
alarm_beep:= (alarm_lamp AND NOT alarm_TON.Q);
//IF alarm_reset AND NOT alarm_button THEN //сбросили сигнал аварии - квитирование
// alarm_lamp:= FALSE;
//END_IF


Использовал код по второму варианту, так как сброс мне не нужен, таймер не запускается вообще.

МихаилГл
20.01.2025, 12:30
Использовал код по второму варианту, так как сброс мне не нужен, таймер не запускается вообще.

Скрин давайте переменных и того, что вы написали. У меня все работает. При нажатии кнопки загорается лампа, и горит до отпускания. А звуковой сигнал после нажатия работает 2 секунды. Таймер TON.

Mikhail_NNT
20.01.2025, 12:44
Скрин давайте переменных и того, что вы написали. У меня все работает. При нажатии кнопки загорается лампа, и горит до отпускания. А звуковой сигнал после нажатия работает 2 секунды. Таймер TON.

81433 81434

При нажатии кнопки лампа загорается, зуммер пищит постоянно. При отжатии - лампа гаснет, зуммер перестает пищать.
При этом Timer.ET всегда равен 0.

МихаилГл
20.01.2025, 12:50
А программа специально остановлена?

И у вас это FB? С особенностями FB и переменными типа var_in, var_out могут быть косяки. Я все переменные делаю глобальными и никогда FB не использую. Сделайте это в чистом основном коде программы, там все будет работать.

PS Где то, что до FB...?

Mikhail_NNT
20.01.2025, 13:22
А программа специально остановлена?

И у вас это FB? С особенностями FB и переменными типа var_in, var_out могут быть косяки. Я все переменные делаю глобальными и никогда FB не использую. Сделайте это в чистом основном коде программы, там все будет работать.

PS Где то, что до FB...?

Программа остановлена, т.к. зуммер пищит рядом.
Да, это универсальный ФБ, который в Главной программе в цикле вызывается 20 раз.
81436

МихаилГл
20.01.2025, 13:26
Программа остановлена, т.к. зуммер пищит рядом.
Да, это универсальный ФБ, который в Главной программе в цикле вызывается 20 раз.
81436

Вы конечно молодец... Тока начали и полезли туда, куда рано... Таймер у вас поди внутренний, и он 1 на все блоки, его тупо затирают другие вызовы. Вы бы не онлайн режим скринили, а офлайн с описанием переменных в какую зону вы их запихали. Таймер один, это 100%... И как вы с ним работать хотите?

PS Сделайте от i:=1 до 1, т.е. для одного i. Может и заработает...

Mikhail_NNT
20.01.2025, 13:38
Вы конечно молодец... Тока начали и полезли туда, куда рано... Таймер у вас поди внутренний, и он 1 на все блоки, его тупо затирают другие вызовы. Вы бы не онлайн режим скринили, а офлайн с описанием переменных в какую зону вы их запихали. Таймер один, это 100%... И как вы с ним работать хотите?

PS Сделайте от i:=1 до 1, т.е. для одного i. Может и заработает...

Таймер внутренний, для конкретного ФБ. Из Списка глобальных перекрестных ссылок видно, что таймер по одному разу объявляется, вызывается и читается. Нигде более не используется.
81437

У меня есть еще пару подобных ФБ, в которых применяются не по одному таймеру и они прекрасно работают, вызываясь в Главной программе в цикле 20 раз. Именно с этим таймером засада какая-то.

melky
20.01.2025, 13:51
Mikhail_NNT не важно, сколько циклов. важно количество экземпляров таймера на одну сущность.
Блин, как объяснить то. Вы объявили один таймер, а пытаетесь его применить к 5-ти кнопкам. Откель таймеру знать, что надо начинать считать с нуля на второй, третьей, пятой сработавшей кнопке, когда он уже считает от нажатия 1-й?
У таймера есть внутренняя переменная состояния и времени его работы

Mikhail_NNT
20.01.2025, 14:25
Mikhail_NNT не важно, сколько циклов. важно количество экземпляров таймера на одну сущность.
Блин, как объяснить то. Вы объявили один таймер, а пытаетесь его применить к 5-ти кнопкам. Откель таймеру знать, что надо начинать считать с нуля на второй, третьей, пятой сработавшей кнопке, когда он уже считает от нажатия 1-й?
У таймера есть внутренняя переменная состояния и времени его работы

Суть вроде ясна. Как этот момент можно реализовать в таком случае? Неужели выход только создавать 20 ФБ с разными таймерами, а если бы их было 100?

Пробовал разные варианты таймеров, по разному запускать, с разными условиями, принудительно выключать. Результата два: либо вообще не включаются таймеры, либо циклически перезапускаются.
Как вы предлагали с ТР также не будет рабочей схемой?

kondor3000
20.01.2025, 14:33
Суть вроде ясна. Как этот момент можно реализовать в таком случае? Неужели выход только создавать 20 ФБ с разными таймерами, а если бы их было 100?

Пробовал разные варианты таймеров, по разному запускать, с разными условиями, принудительно выключать. Результата два: либо вообще не включаются таймеры, либо циклически перезапускаются.
Как вы предлагали с ТР также не будет рабочей схемой?

2 варианта:
1) встроить таймер прямо в ФБ, тогда у каждого экземпляра будет по своему таймеру.
2) использовать массив таймеров, и вызывать нужный как вызываете переменные массива.

Mikhail_NNT
20.01.2025, 14:40
2 варианта:
1) встроить таймер прямо в ФБ, тогда у каждого экземпляра будет по своему таймеру.
2) использовать массив таймеров, и вызывать нужный как вызываете переменные массива.

У меня сделано по первому варианту. Таймер находится (объявляется и вызывается) внутри ФБ, далее ФБ вызывается в Главной программе в цикле N раз. Таймер объявлен в VAR, т.е. внутренний.
81438 81439

МихаилГл
20.01.2025, 14:59
Как вариант-костыль, сделайте в фб 20 таймеров, и передавайте в него i как входную переменную номера таймера. Но это все равно неправильный костыль и возможно не проканает, хотя... (Это как раз 2ой вариант кондора)

PS Скрины объявленных переменных делайте в оффлайне, это более информативно.

МихаилГл
20.01.2025, 15:05
У меня сделано по первому варианту. Таймер находится (объявляется и вызывается) внутри ФБ, далее ФБ вызывается в Главной программе в цикле N раз. Таймер объявлен в VAR, т.е. внутренний.
81438 81439

Нет, тут о том, что таймер должен быть входной-выходной переменной, чтоб было где сохранять. А он у вас просто один. Как Solo в сериале Бункер.

Я даже не знаю как с таким объявлением работать, если честно...

kondor3000
20.01.2025, 15:20
У меня сделано по первому варианту. Таймер находится (объявляется и вызывается) внутри ФБ, далее ФБ вызывается в Главной программе в цикле N раз. Таймер объявлен в VAR, т.е. внутренний.
81438 81439

Тогда я не понимаю, зачем вам цикл FOR в ФБ, если вы 20 раз вызываете ФБ то и цикл внутри не нужен.

Цикл надо было использовать в основной программе, массив из 20 переменных и массив из 20 таймеров.

МихаилГл
20.01.2025, 15:24
Тогда я не понимаю, зачем вам цикл FOR в ФБ, если вы 20 раз вызываете ФБ то и цикл внутри не нужен.

Цикл надо было использовать в основной программе, массив из 20 переменных и массив из 20 таймеров.

Этот цикл у ТС вне фб... А таймер внутри 1. Я уже сам путаюсь. Я возможно тоже не так понимаю ваш 1ый способ...

melky
20.01.2025, 15:34
Mikhail_NNT вы один FB вызываете или создаете циклом 20 FB ? если вызов одного FB 20 раз, то его экземпляр всего один, соответственно и таймер 1.

Экземпляр FB создает набор переменных под себя. Вызов одного и того же в цикле работает с одним экземпляром переменных. Так как экземпляр создастся всего один.

МихаилГл
20.01.2025, 15:44
Короче, ТС, покажите описание переменных в офлайне, народ хочет знать, у вас fb или array () of fb :)

PS Квадратных скобок в цикле нет... Это не массив...

МихаилГл
20.01.2025, 15:54
https://owen.ru/forum/attachment.php?attachmentid=81439&d=1737367589&thumb=1
разве не очевидно что он гоняет один ФБ подставляя в него входящие значения входных данных из 20 мест?
И ни какой таймер туда не входит
даже если он объявил несколько экземпляров этого ФБ

Да все уже поняли, кроме ТС. А вдруг)

kondor3000
20.01.2025, 18:09
Вот скрины работы 20 экземпляров ФБ, со встроенным таймером внутри ФБ. В примере Таймер на 20 секунд.
Сама программа, таймер встроен в ФБ 81440 Вызов 20 экземпляров в цикле FOR 81441
Просмотр работы 17 и 18 экземпляра, включены не одновременно и время на таймерах разное !!! 81442
То есть они работают, каждый в своём экземпляре ФБ.

Для просмотра работы, не открывая экземпляры, после цикла поставлена i:=17; и 17 экземпляр виден прямо в PLC_PRG.

МихаилГл
20.01.2025, 18:15
У вас FB это массив, а у ТС нет, он это никак не хочет понять...

Mikhail_NNT
22.01.2025, 11:04
https://owen.ru/forum/attachment.php?attachmentid=81439&d=1737367589&thumb=1
разве не очевидно что он гоняет один ФБ подставляя в него входящие значения входных данных из 20 мест?
И ни какой таймер туда не входит
даже если он объявил несколько экземпляров этого ФБ

Да, так оно и есть.

ФБ с обработкой событий с таймером вызываю в цикле 20 раз в Основной программе, соответственно меняются только входящие переменные.
81484 81485 81486

Mikhail_NNT
22.01.2025, 11:06
Вот скрины работы 20 экземпляров ФБ, со встроенным таймером внутри ФБ. В примере Таймер на 20 секунд.
Сама программа, таймер встроен в ФБ 81440 Вызов 20 экземпляров в цикле FOR 81441
Просмотр работы 17 и 18 экземпляра, включены не одновременно и время на таймерах разное !!! 81442
То есть они работают, каждый в своём экземпляре ФБ.

Для просмотра работы, не открывая экземпляры, после цикла поставлена i:=17; и 17 экземпляр виден прямо в PLC_PRG.

Спасибо, буду разбираться!

capzap
22.01.2025, 11:24
Да, так оно и есть.

ФБ с обработкой событий с таймером вызываю в цикле 20 раз в Основной программе, соответственно меняются только входящие переменные.

Вы вызываете двадцать раз один экземпляр с внутренним таймером, а надо вызывать 20 экземпляров, чтоб обеспечить 20 независимых внутренних таймеров

Mikhail_NNT
22.01.2025, 14:49
Всем спасибо за помощь, разобрался, все поправил, работает. Верная причина указана постом выше.

Еще такой вопрос, как правильно организовать программу, если события в разных ФБ должны влиять на одно физическое устройство?

Например, есть 1 лампа и 2 ФБ.
При событии в первом ФБ лампа горит, иначе не горит.
При событии во втором ФБ лампа моргает, иначе не моргает.

Программа с подобными задачами у меня выстроена так (например, ФБ, обрабатывающий событие теста всех ламп световой колонны, и ФБ, обрабатывающий события нажатия кнопок и работы ламп световой колонны):
В каждом ФБ создается своя выходная логическая переменная, которые привязываются к 2-м выходам на модуле DO. Далее физически 2 выхода подключаются через перемычку и на лампу.
Такой способ слишком много свободных DO съедает.

Знаю, что при присвоении значений в одну и ту же переменную в разных ФБ программы, ничего хорошего не выйдет. Но может есть еще варианты, чтобы в конечном итоге был задействован 1 выход модуля DO для лампы?

kondor3000
22.01.2025, 14:57
Пересмотрите подход, пока не поздно, сделайте один ФБ, и управляйте всем чем надо, не будет проблем и геморроя.
Два выхода на 1 лампу тоже не нужны, одного за глаза. Выше пример уже дал.
Blink для моргания, тоже можно встроить прямо в ФБ. Пример моргания лампы от Аварии 81499
Порядок не выставлял, это пример.

melky
22.01.2025, 15:10
При событии в первом ФБ лампа горит, иначе не горит.
При событии во втором ФБ лампа моргает, иначе не моргает.

События никогда не происходят вместе? - тогда их выходы через OR на DO
События происходят вместе но одно из них главнее? - тогда выход DO подключать через Селектор.

Mikhail_NNT
23.01.2025, 09:41
Понял, спасибо, перепишу код, чтобы все события были в одном условии и ссылались на один DO

Mikhail_NNT
24.01.2025, 12:31
Подскажите еще по системному времени. Программа считает простои сборочной линии: кнопка нажата таймер запустился, кнопка отжата таймер остановился и сохранилось значение таймера ЕТ.
Все работает отлично, все считает заносит данные в таблицу в панели, но делает это в миллисекундах, никак не пойму почему?
81541
В выделенном фрагменте построчно:
Системное время TIME перевожу в DWORD
Перевожу миллисекунды в секунды разделив DWORD на 1000
Перевожу DWORD в WORD
Записываю значение в переменную- старое значение переменной + текущий WORD
81542
В таблице на HMI столбцы данных тип-WORD, всего знаков-4, формат-unsigned

МихаилГл
24.01.2025, 12:44
У вас dword в word влазит? Интересно интересно...

PS А в чем проблема? Таймеры в миллисекундах и работают...

Mikhail_NNT
24.01.2025, 13:12
У вас dword в word влазит? Интересно интересно...

PS А в чем проблема? Таймеры в миллисекундах и работают...

Да, таймеры работают в миллисекундах, мне нужен вывод в секундах.

Получается нужно сделать что-то типа WORD + WORD:= TO_WORD (DWORD)?

МихаилГл
24.01.2025, 13:17
Да, таймеры работают в миллисекундах, мне нужен вывод в секундах.

Получается нужно сделать что-то типа WORD + WORD:= TO_WORD (DWORD)?

Вопрос не понятен... 509 это как раз секунды (8 минут 29 секунд). Что именно не правильно?

PS WORD это максимум 65536 секунд...

Mikhail_NNT
24.01.2025, 13:20
Вопрос не понятен... 509 это как раз секунды (8 минут 29 секунд). Что именно не правильно?

В переменной wDownTimeS1Hx нужно записать секунды, как раз 509, а записываются миллисекунды.

Из-за неправильного преобразования типов такая история?

kondor3000
24.01.2025, 13:22
Подскажите еще по системному времени. Программа считает простои сборочной линии: кнопка нажата таймер запустился, кнопка отжата таймер остановился и сохранилось значение таймера ЕТ.
Все работает отлично, все считает заносит данные в таблицу в панели, но делает это в миллисекундах, никак не пойму почему?
В выделенном фрагменте построчно:
Системное время TIME перевожу в DWORD
Перевожу миллисекунды в секунды разделив DWORD на 1000
Перевожу DWORD в WORD
Записываю значение в переменную- старое значение переменной + текущий WORD

В таблице на HMI столбцы данных тип-WORD, всего знаков-4, формат-unsigned

Для начала определитесь, какое максимальное время у вас будет?
У вас на скрине уже 37098 +509 =37607, а WORD максимум 65 535 (это максимум 18 часов, если в секундах).
Если больше, то конвертация DWORD_TO_ WORD уже не нужна. DWORD это максимум 49 дней (в мс), это тоже надо помнить.

Потом зачем скрадывать конвертированное время WORD, если проще складывать само время TIME, а конвертировать только результат.
У вас на 10 строках несколько раз конвертация туда и обратно. Не мудрено, что всё считает криво.

Сначала надо составить алгоритм, прикинуть, хватает ли вам диапазона переменных и только потом писать программу.

МихаилГл
24.01.2025, 13:23
В переменной wDownTimeS1Hx нужно записать секунды, как раз 509, а записываются миллисекунды.

Из-за неправильного преобразования типов такая история?

wDownTimeS1Hx это что за тип? Откуда вы решили что у вас неправильно? До каких пор вы будете скринить непойми что? Люди скоро вас материть начнут. Если что то не работает, скидывайте исходники...

Mikhail_NNT
24.01.2025, 13:33
Простои считаются и сохраняются по одному часу, например с 6:30 до 7:30, далее сохраняются в другой час, и так далее в течении смены, так что WORD мне достаточно.
Код ФБ:
FUNCTION_BLOCK Downtime_Chassis_line
VAR_INPUT
xRedButton: BOOL; //Красная кнопка "Авария"
END_VAR
VAR_OUTPUT
wDownTimeS1H1: WORD; //Простой в минутах I смены 1-ый час
wDownTimeS1H2: WORD; //Простой в минутах I смены 2-ой час
wDownTimeS1H3: WORD; //Простой в минутах I смены 3-ий час
wDownTimeS1H4: WORD; //Простой в минутах I смены 4-ый час
wDownTimeS1H5: WORD; //Простой в минутах I смены 5-ый час
wDownTimeS1H6: WORD; //Простой в минутах I смены 6-ой час
wDownTimeS1H7: WORD; //Простой в минутах I смены 7-ой час
wDownTimeS1H8: WORD; //Простой в минутах I смены 8-ой час

wDownTimeS2H1: WORD; //Простой в минутах II смены 1-ый час
wDownTimeS2H2: WORD; //Простой в минутах II смены 2-ой час
wDownTimeS2H3: WORD; //Простой в минутах II смены 3-ий час
wDownTimeS2H4: WORD; //Простой в минутах II смены 4-ый час
wDownTimeS2H5: WORD; //Простой в минутах II смены 5-ый час
wDownTimeS2H6: WORD; //Простой в минутах II смены 6-ой час
wDownTimeS2H7: WORD; //Простой в минутах II смены 7-ой час
wDownTimeS2H8: WORD; //Простой в минутах II смены 8-ой час

wTotalDownTimeS1: WORD; //Всего простоев за I смену
wTotalDownTimeS2: WORD; //Всего простоев за II смену
END_VAR
VAR
tonDowntime: TON; //Таймер времени простоя

tDowntime: TIME; //Время работы таймера простоя в секундах
dwDowntime: DWORD;
wDowntime: WORD;
END_VAR



//Присвоение значения селектору количества часов в I смене
IF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sStartShift1) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH1_H2Shift1))
THEN TargetVars.iHourShift1:=1; //1-ый час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH1_H2Shift1) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sStartBreak11))
THEN TargetVars.iHourShift1:=2; //2-ой час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sEndBreak11) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH3_H4Shift1))
THEN TargetVars.iHourShift1:=3; //3-ий час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH3_H4Shift1) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sStartLunch1))
THEN TargetVars.iHourShift1:=4; //4-ый час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sEndLunch1) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH5_H6Shift1))
THEN TargetVars.iHourShift1:=5; //5-ый час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH5_H6Shift1) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sStartBreak12))
THEN TargetVars.iHourShift1:=6; //6-ой час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sEndBreak12) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH7_H8Shift1))
THEN TargetVars.iHourShift1:=7; //7-ой час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH7_H8Shift1) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sEndShift1))
THEN TargetVars.iHourShift1:=8; //8-ой час
END_IF

//Присвоение значения селектору количества часов во II смене
IF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sStartShift2) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH1_H2Shift2))
THEN TargetVars.iHourShift2:=1; //1-ый час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH1_H2Shift2) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sStartBreak21))
THEN TargetVars.iHourShift2:=2; //2-ой час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sEndBreak21) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH3_H4Shift2))
THEN TargetVars.iHourShift2:=3; //3-ий час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH3_H4Shift2) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sStartLunch2))
THEN TargetVars.iHourShift2:=4; //4-ый час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sEndLunch2) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH5_H6Shift2))
THEN TargetVars.iHourShift2:=5; //5-ый час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH5_H6Shift2) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sStartBreak22))
THEN TargetVars.iHourShift2:=6; //6-ой час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sEndBreak22) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sH7_H8Shift2))
THEN TargetVars.iHourShift2:=7; //7-ой час
ELSIF ((TargetVars.stRTC.sGetFormatTime>=TargetVars.sH7_H8Shift2) AND (TargetVars.stRTC.sGetFormatTime<TargetVars.sEndShift2))
THEN TargetVars.iHourShift2:=8; //8-ой час
END_IF

//Сброс данных о простоях I и II смены
IF TargetVars.stRTC.sGetFormatTime=TargetVars.sDataRe set OR TargetVars.stRTC.sGetFormatTime='12:08:00'
THEN wDownTimeS1H1:=0;
wDownTimeS1H2:=0;
wDownTimeS1H3:=0;
wDownTimeS1H4:=0;
wDownTimeS1H5:=0;
wDownTimeS1H6:=0;
wDownTimeS1H7:=0;
wDownTimeS1H8:=0;

wDownTimeS2H1:=0;
wDownTimeS2H2:=0;
wDownTimeS2H3:=0;
wDownTimeS2H4:=0;
wDownTimeS2H5:=0;
wDownTimeS2H6:=0;
wDownTimeS2H7:=0;
wDownTimeS2H8:=0;
END_IF

//Включение/отключение/сохранение времени Таймера времени простоя
tonDowntime (IN:=xRedButton, PT:= T#28800S); // Таймер на 8 часов

IF NOT tonDowntime.Q
THEN tDowntime:=tonDowntime.ET;
END_IF

CASE TargetVars.iHourShift1 OF
1:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H1:= wDownTimeS1H1 + wDowntime;
2:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H2:= wDownTimeS1H2 + wDowntime;
3:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H3:= wDownTimeS1H3 + wDowntime;
4:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H4:= wDownTimeS1H4 + wDowntime;
5:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H5:= wDownTimeS1H5 + wDowntime;
6:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H6:= wDownTimeS1H6 + wDowntime;
7:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H7:= wDownTimeS1H7 + wDowntime;
8:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS1H8:= wDownTimeS1H8 + wDowntime;
END_CASE

wTotalDownTimeS1:= wDownTimeS1H1+wDownTimeS1H2+wDownTimeS1H3+wDownTim eS1H4+wDownTimeS1H5+wDownTimeS1H6+wDownTimeS1H7+wD ownTimeS1H8;

CASE TargetVars.iHourShift2 OF
1:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H1:= wDownTimeS2H1 + wDowntime;
2:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H2:= wDownTimeS2H2 + wDowntime;
3:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H3:= wDownTimeS2H3 + wDowntime;
4:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H4:= wDownTimeS2H4 + wDowntime;
5:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H5:= wDownTimeS2H5 + wDowntime;
6:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H6:= wDownTimeS2H6 + wDowntime;
7:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H7:= wDownTimeS2H7 + wDowntime;
8:
dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
wDowntime:= TO_WORD (dwDowntime);
wDownTimeS2H8:= wDownTimeS2H8 + wDowntime;
END_CASE

wTotalDownTimeS2:= wDownTimeS2H1+wDownTimeS2H2+wDownTimeS2H3+wDownTim eS2H4+wDownTimeS2H5+wDownTimeS2H6+wDownTimeS2H7+wD ownTimeS2H8;

kondor3000
24.01.2025, 14:09
Подскажите еще по системному времени. Программа считает простои сборочной линии: кнопка нажата таймер запустился, кнопка отжата таймер остановился и сохранилось значение таймера ЕТ.
Все работает отлично, все считает заносит данные в таблицу в панели, но делает это в миллисекундах, никак не пойму почему?


У вас насчитало 509 секунд, с чего вы решили, что в таблице мс, у вас там 509 000 ?
Такого не может быть, максимум 65535

Mikhail_NNT
24.01.2025, 14:14
У вас насчитало 509, с чего вы решили, что в таблице мс, у вас там 509 000 ?
Такого не может быть, максимум 65535

В таблице, и соответственно в переменной wDownTimeS2Hх, вместо 509 отображается 37098 и 29851.

Значение доходит до 9999 (так как в таблице ограничено 4 знаками) и начинается отсчет сначала, и именно это значение записывается в wDownTimeS2Hх, а нужно чтобы 509.
81545

capzap
24.01.2025, 14:19
В таблице, и соответственно в переменной wDownTimeS2Hх, вместо 509 отображается 37098 и 29851. Нужно чтобы было именно 509.
Не понимаю, что тогда записывается в переменную wDownTimeS2Hх?
81545

ну так если Вы замените wDownTimeS2H8:= wDownTimeS2H8 + wDowntime; на wDownTimeS2H8:= wDowntime; будет отображаться 509, но Вам же не это нужно?

Mikhail_NNT
24.01.2025, 14:26
ну так если Вы замените wDownTimeS2H8:= wDownTimeS2H8 + wDowntime; на wDownTimeS2H8:= wDowntime; будет отображаться 509, но Вам же не это нужно?

Все верно, нужно, чтобы к старому значению wDownTimeS2H8 прибавлялось текущее значение wDowntime

kondor3000
24.01.2025, 14:27
В таблице, и соответственно в переменной wDownTimeS2Hх, вместо 509 отображается 37098 и 29851.

Значение доходит до 9999 (так как в таблице ограничено 4 знаками) и начинается отсчет сначала, и именно это значение записывается в wDownTimeS2Hх, а нужно чтобы 509.
81545

Думаю у вас сложение происходит несколько раз, а должно происходить однократно, по R_Trig, или просто присваивайте 509 на выход без сложения.
Получается вы отравляете в панель не ту переменную, вместо 509 у вас 37 тысяч

МихаилГл
24.01.2025, 14:30
Я ТС уже не понимаю. То ему надо суммировать, то не надо. Походу щас ожидаю вопросы по правильности работы case, типа он не те числа складывает.. Вы определитесь как элементарные функции работают.

Скрины разрисовывать время есть, а приложить исходник в виде файла проекта совесть не позволяет. Тогда уж код отдклите служебными словами кода...

МихаилГл
24.01.2025, 14:33
Думаю у вас сложение происходит несколько раз, а должно происходить однократно, по R_Trig, или просто присваивайте 509 на выход без сложения.

По времени цикла программы...)
Ниче, и так сойдет.

PS Сейчас опять новый вопрос предвижу: какое такое время цикла... Что за 20 мс по умолчанию... Мне так не надо...

Ваш функциональный блок, кстати, не информативен без кода, его вызывающего. Триггер нужен или вне, или внутри блока.

capzap
24.01.2025, 14:38
Все верно, нужно, чтобы к старому значению wDownTimeS2H8 прибавлялось текущее значение wDowntime

ну тогда значения 37098 и 29851 это результат сложения старого с текущим, что не так? Где тогда должно отображаться текущее?
И главное чтоб не "выкатывать" такие "портянки" напишите функцию, например


function Solver: WORD;
var_input
OLD_TIK : WORD;
tDowntime: TIME;
end_var
var_
dwDowntime: DWORD;
end_var

dwDowntime:= TO_DWORD (tDowntime);
dwDowntime:= dwDowntime / 1000; //Перевод миллисекунд в секунды
Solver := OLD_TIK + TO_WORD (dwDowntime);
end_function


и тогда заметно код сократится, если в каждом кейсе написать wDownTimeSXHX:= Solver(wDownTimeSXHX,tDowntime);

МихаилГл
24.01.2025, 14:43
А может ТС смущает:
12345:= 12345 + 123

И он хочет узнать почему отображается не:
12345:= 12222 + 123

Ну думаю это не так, и все же он спрашивает о том, о чем мы все говорим...

PS Включил ПК, щас набросаю код...

МихаилГл
24.01.2025, 15:27
.....

81552

Не благодарите...

У ТС там арифметическая прогрессия была. Задолбался переменные прописывать начала-конца часов. Ну мы же не можем проект приложить, мы выше этого...

PS Но ваш алгоритм все равно будет работать неправильно, вернее моя корректировка. Т.к. если кнопка стоп будет отжата после перехода часовки, то данные наработки в предыдущем часе присвоятся следующему часу. Так что внедряйте другой механизм, тут я показал просто вашу ошибку в коде, и костыль для ее решения малой кровью...

PS2 Создайте цикл на 1000 мс, перенесите туда ваш код, и просто прибавляйте в вашем старом алгоритме не время, а 1. Это кстати так и надо делать. Таймер можно вообще убрать. Тогда и часовки будут правильными.



If not кнопка-стоп then
Case...
1: часовка1:= часовка1 + 1
2: часовка2:= часовка2 + 1
...

И никаких преобразования таймеров...