Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Просмотр сообщений

В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.


Сообщения - pan2000

Страницы: [1] 2 3 ... 14
1
   Здравствуйте.

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

2
   Здравствуйте.
...записывает себе в базу данных очень маленькие значения переменных. ... Приходится удалять их вручную...
Т.е. речь идет от отбрасывании заведомо недопустимых значений.

Если найти причину образования некорректных данных поступающих в скада-систему не получится, то можно попробовать отфильтровать некорректные значения переменной... в настройках переменной включить Фильтр мин. макс.
Судя по описанию и интерактивной картинке фильтра в редакторе, "Фильтр мин. макс" не отбрасывает недопустимое значение, а конвертирует его в минимум/максимум.
На картинке зеленым цветом показано поведение переменной при условии игнорирования недопустимых значений. Хорошо видно, что площадь под кривой заметно различается для фильтра и при отбрасывании значения.
В этом случае отчет-то может и будет строится, а вот его корректность ещё придется доказать (понятно, что недопустимые значения весьма редкие, и отчет скорее всего не пострадает, но "не аккуратненько").

3
   Здравствуйте.

Для начала нужно убедиться, что от ОРС-сервера не поступают ошибочные данные. Индикация наличия ошибочных - скрипт "Изменились переменные":
Код: (delphi)
// ОТЛОВ МИНИМАЛЬНЫХ ЗНАЧЕНИЙ
begin
  with Variable do
// выбор минимального порога
//    if (Value <= LowAlarm) and (not IsFirstChange) then  // индивидуальный
    if (Value <= 5) and (not IsFirstChange) then       // общий

      AddMessage(Now, mkAlarm, Name + '=' + AsStr, True, True);
end.
При наличии ошибок желательно их ликвидировать как явление.
И как последнее средство - введение фильтра минимальных значений перед архивированием. Т.е. переменная разделяется на входную (не архивируемую), по изменению которой происходит контроль величины и выходную (архивируемую), перезаписываемую из входной при прохождении контроля.
При условии, что имена входной и выходной переменной отличаются только суффиксом у выходной переменной - скрипт по событию "Изменились переменные":
Код: (delphi)
// ФИЛЬТР МИНИМАЛЬНЫХ ЗНАЧЕНИЙ
begin
  with Variable do
// выбор минимального порога
//    if (Value > LowAlarm) and (not IsFirstChange) then
    if (Value > 5) and (not IsFirstChange) then

      GetVariableByName(Name + '_out').Value := Value;
end.
См. пример.

4
Ваши вопросы / Re: Вопрос по рассписанию.
« : 29 Апреля 2025, 02:20:35 »
   Здравствуйте.

  Поскольку нет аппаратного условия сброса управляющих сигналов, то остается формировать длительности управляющих сигналов сервером Simple-Scada.
Скрипт по событию "Текущее время вошло в установленный интервал объекта "Расписание"":
Код: (delphi)
begin
  SCI_Pusk.Value := true;
  RunDelay(3000, 1);
end.
Скрипт по событию "Текущее время вышло из установленного интервала объекта "Расписание"":
Код: (delphi)
begin
  SCI_Stop.Value := true;
  RunDelay(3000, 2);
end.
Скрипт по событию "Выполнена задержка":
Код: (delphi)
begin
  case DelayEventData.Tag of
  1: SCI_Pusk.Value := false;
  2: SCI_Stop.Value := false;
  end;
end.
Пример во вложении.

5
Ваши вопросы / Re: Границы переменных
« : 25 Апреля 2025, 00:57:48 »
   Здравствуйте.

Появление баннера при нарушении "Верхней аварийной" границы и пропадание по выходу из зоны нечувствительности:

1.Если для прочих нужд проекта не используется "Верхняя предупредительная" граница, скрипт "Нарушена граница":
Код: (delphi)
begin
  Shape5.Visible := Variable.GetValueZone = 2;
end.
, в вариациях задания зоны нечувствительности:
- "Только аварийные" границы - сама "Зона нечувствительности";
- "Аварийные и предупредительные" границы - либо нижняя граница зоны нечувствительности задается "Верхней предупредительной" границей при "Зоне нечувствительности"=0, либо "Зоной нечувствительности" при "Верхней предупредительной"="Верхней аварийной".

2. Без использования стандартной процедуры контроля границ, скрипт "Изменилась переменная":
- с нулевой зоной:
Код: (delphi)
begin
  Shape5.Visible := Variable.AsFloat >= Variable.HighAlarm;
end.
- с ненулевой зоной:
Код: (delphi)
const hist = 4.00;  // величина зоны в единицах измерения переменной
begin
  if (Variable.AsFloat >= Variable.HighAlarm) then Shape5.Visible := true;
  if Shape5.Visible and (Variable.AsFloat < (Variable.HighAlarm - hist)) then Shape5.Visible := false;
end.
.
Вариант 1 более предпочтительный, т.к. и скрипт проще, и событий меньше. Примеры для некоторых вариантов во вложении.

6
Ваши вопросы / Re: Работа с таблицами
« : 16 Апреля 2025, 22:12:31 »
    Здравствуйте.

Красный лучше оставь белым.
(Если время пребывания меньше - время сушки - красный, если время пребывания больше - время сушки - зеленый.)
Раскраска строк в два цвета (красный-зеленый) не соответствует Вашему первому сообщению - там красный цвет (предупреждающий/аварийный) означает что сушка закончилась преждевременно, и лучше не использовать его для нормально идущего процесса. Должна быть явная индикация (в общей таблице или в отдельной). Это позволяет визуально контролировать ошибки (сейчас выкатил тележку раньше времени и концы в воду) операторов тележки. Да и то только если таблицы видит начальник.
Цитировать
... корректно записываются и удаляются данные.
На мой взгляд более правильно использовать БД именно как БД, а не как некоторый сохраняемый массив данных. Т.е. по хорошему в БД при заезде тележки должно фиксироваться дата-время заезда и некоторая идентифицирующая информация о загрузке тележки (доски, брус, ... кирпич и т.д.)
При выезде тележки БД дополняется временем сушки, текущем интервалом контроля и идентификатором выкатившего тележку оператора/бригады. В этом случае начальник может контролировать многие очень интересные вещи.

Замечание по скрипту обработки SQL-запроса - к сожалению окончание скрипта не видно, но если у условия "if DataSet.IsEmpty = false then" нет альтернативы "else" с очисткой таблицы, то группа тележек, умудрившаяся выкатиться, полностью освободив помещение в течение последней минуты, может и не удалиться из таблиц формы.
Можно обрезать "жирок" со скриптов:
Код: (delphi)
begin
  // запрашиваем первые до 20 строк
  RunSQL('SELECT numberCart,timeCart1,timeCart2 FROM cart1 LIMIT 20;', Table1, 3);
  // запрашиваем остаток строк
  RunSQL('SELECT numberCart,timeCart1,timeCart2 FROM cart1 LIMIT 20 OFFSET 20;', Table2, 3);
end.
Код: (delphi)
var aRow, i: integer;
    aColor: cardinal;
begin
  if DataSet.Tag = 3 then
    with DataSet.Sender as TM_Table do
      for aRow := 0 to 19 do
        if not DataSet.EOF then
        begin
          if DataSet.Fields[2].AsInt > dryingTime1.AsInt then aColor := clGreen
          else aColor := clRed;
          for i := 0 to DataSet.FieldCount - 1 do
          begin
            GetCell(i, aRow).Text := DataSet.Fields[i].AsStr;
            GetCell(i, aRow).Color := aColor;
          end;
          DataSet.Next;
        end
        else
          for i := 0 to 2 do
          begin
            GetCell(i, aRow).Text := '';
            GetCell(i, aRow).Color := clNone;
          end;
end.

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

С проблемой считывателя меток нужно разбираться по его документации. Без этого пытаться городить всевозможные фильтры и логику бесполезно, т.к. доподлинно не известно всегда ли это будет работать или перестанет по изменению погоды, скоростью движения тележки и т.д.
В качестве шаманства с бубном, можно изменить фронт срабатывания TagRead (в предположении что один фронт индицирует начало считывания, а другой собственно завершение).

7
Ваши вопросы / Re: Работа с таблицами
« : 12 Апреля 2025, 06:23:56 »
 Здравствуйте.

И есть ли возможность заполнения таблицы из БД полностью на всю форму без прокручивания (на картинке). В таблице количество строк равно 40.
Заполнить таблицу, состоящую из нескольких групп однотипных столбцов, "змейкой" можно (по крайней мере в MySQL версии 8.0) с использованием оконной функции LEAD.
Так для таблицы my_table из БД со столбцами col1, col2, col3 запрос на заполнение таблицы в Simple-Scada из двух групп не более чем в 20 строк:
SELECT *, LEAD(col1,20) OVER(),LEAD(col2,20) OVER(),LEAD(col3,20) OVER() FROM my_table LIMIT 20; 
Реальный запрос может быть усложнен за счёт замены NULL на пустую строку, форматирования данных, добавления вычисляемых столбцов. Скрин показывает результаты работы запроса по таблице из предыдущих примеров. Запрос для левой половины таблицы включает замену NULL, вычисление и форматирование столбца, правая - только вычисления.


8
Ваши вопросы / Re: Работа с таблицами
« : 10 Апреля 2025, 12:27:28 »
   Здравствуйте.
Я это воспринял как автоматическое с датчика, а если заносится ручками, то смотрите пример @pan2000.
Наличие раздельных переменных для меток заезда и выезда не обязательно указывает на "ручки" :-\, равно как и ввод значения метки в поле. Достаточно изменить события на "Изменилась основная переменная" и это будет вариант для помещения с раздельным заездом и выездом (например, туннельная печь).
Для единственного поля ввода метки (считывателя) - заезд/выезд определяется по наличию тележки в помещении. Пример во вложении.

9
Ваши вопросы / Re: Работа с таблицами
« : 09 Апреля 2025, 20:44:07 »
   Здравствуйте.

  Размер таблицы ограничен 40 строками, резонно предположить что больше тележек просто-напросто не входит в помещение или в наличии не больше 40 меток тележек.
  В примере (для БД MySQL, не более 40 меток) используется пара совмещенных таблиц: верхняя - прозрачная, содержащая собственно данные о тележках (метки событий урезаны только до времени), нижняя - с широкими колонками, перекрывающими набор колонок верхней, и полным значением времени заезда (дата-время).
Такое решение позволяет избежать нудных перекрашиваний группы ячеек из верхней таблицы и получать правильное значение времени нахождения в помещении (независимо от перезапусков сервера), как разность текущего времени и времени заезда.

Таблица содержит все последние завершенные (в том числе удачные) и все текущие переезды тележек. Можно исключить из таблицы удачно завершенные переезды, однако гарантировано увеличить количество меток (при условии что в помещении одновременно не более 40 тележек) не получится, т.к. в таблице могут присутствовать красные строки для тележек вне помещения.
При новом заезде тележки информация о предыдущем заезде удаляется из таблицы посредством смены знака у идентификатора тележки, что позволяет сохранять предысторию.
При запуске проекта и по событиям "Заезд тележки №№", "Выезд тележки №№", "Удаление из таблицы тележки №№" происходит заполнение таблицы из БД с раскладкой данных из набора данных DataSet.
Вычисление текущего времени нахождения в помещении  тележек и "раскраска" нижней таблицы осуществляются по таймеру 1 сек.

P.S. Для уменьшения скрипта раскладки данных используется более сложная форма запроса, при желании можно свести запрос к минимальному и усложнить обработку в скрипте (это по поводу смены БД).
Пример только для иллюстрации: задание интервала контроля ограничено 23:59:59, длительность нахождения в помещении ограничена ~ 800 часами, нет контроля общего числа тележек в помещении.
При условии не более 40 тележек в помещении, было бы правильно отображать в таблице состояния присутствующих в помещении тележек, а преждевременный выезд тележек перенести в отдельную таблицу.

10
   Здравствуйте.

По видимому, объекты формы используются только для задания части начальных значений перед работой с окном-формой, и не предполагают изменения свойств входящих в форму объектов.
Для исключения возможных ошибок/конфликтов в скрипте обработки формы следует использовать данные только из FormData. Пример ошибки подобного сорта:
- в моём предыдущем примере обнаружен КОНФЛИКТ при работе нескольких клиентов - способ передачи выбранной переменной в скрипт обработки формы посредством основной переменной поля-формы ввода значения переменной, которая не локализуется в форме и является общей для всех клиентов. При отправки формы изменялись свойства переменной из последнего открытого окна-формы.
Исправление: имя выбранной переменной передается через дополнительное невидимое поле, локализуемое в форме.

Пример с исправлениями и возможностью изменения типа границ во вложении.

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

11
Ваши вопросы / Re: Ввод данных типа Single
« : 26 Марта 2025, 15:15:41 »
   Здравствуйте.

  Для ограниченного набора возможных значений переменной ввода (в Вашем случае 10001 значение) можно использовать целочисленную переменную PositionTC со сдвигом запятой -1.
Код: (delphi)
begin
   case PositionTC.AsVariant of
        0..160      : wNumberPlace.Value := 1;
        161..1000   : wNumberPlace.Value := 2;
        1001..5000  : wNumberPlace.Value := 3;
        5001..7000  : wNumberPlace.Value := 4;
        7001..10000 : wNumberPlace.Value := 5;
      end;
end.

Для вещественной переменной можно использовать округление до ближайшего целого:
Код: (delphi)
...
  case Round(PositionTC_1.AsSingle * 10) of
...

12
Ваши вопросы / Re: Страница трендов
« : 18 Марта 2025, 10:31:11 »
   Здравствуйте.

Если достаточно просмотра тренда с момента клика по ячейке, то можно использовать временной тренд с одном трендом и переключением переменной.
В противном случае (поскольку данные накапливаются) необходим индивидуальный тренд для каждой переменной. В зависимости от общего количества трендов это может быть один временной тренд или несколько. Нужный тренд выбирается управлением видимостью тренда/временного тренда.
Наиболее простой вариант это единственный временной тренд (в предположении, что количество трендов не превысит максимального для временного тренда ?) и следующие правила:
- тренд выбирается по клику по строке таблицы;
- для выбора тренда используется поиск по их переменным до совпадения с дополнительной переменной ячейки;
- шкала устанавливается по минимуму-максимуму переменной;
- количество меток шкалы и линий по Y определяются шкалой переменной в свойстве "Единица измерения". Если это свойство используется в проекте, то простых решений, кроме фиксированного значения в редакторе, нет.
Пример с двумя просто переменными и одной с генератором пилы во вложении. 

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

13
    Здравствуйте.

  Для просмотра/редактирования одиночной переменной и её свойств можно создать обычное (или модальное) окно-форму.
При открывании окна в форму передаются переменная с набором просматриваемых/редактируемых свойств.
По заполнении данные из формы переписываются в свойства переменной.
Пример во вложении.

14
  Здравствуйте.

...наверное, можно как то автоматически их обнулять...

  Кнопка/кнопки изменяют состояния по действиям оператора и изменению состояния установки. Пример для некоторой модели установки во вложении.
Модель установки на основе реверсивного счетчика, по значениям переменных SCi_pusk и SCi_stop формирует временные диаграммы сигналов состояния системы в переменной SCo_Kod__Sostoyanie_:
- бит 0: 1 - система стоит, 0 - работает;
- бит 5: 32 - жалюзи открываются/закрываются, 0 - в покое;
- бит 10: 1024 - двигатель включен, 0 - выключен.

1. Кнопка имеет четыре состояния: ПУСК, ОТКР., СТОП, ЗАКР. Основная переменная связана с вспомогательной переменной состояния кнопки, дополнительная с переменной состояния системы.
В состояниях ОТКР. и ЗАКР. кнопка недоступна, а переход к следующему состоянию определяется значением переменной состояния системы.
Скрипты по изменению основной и дополнительной переменных:
Код: (delphi)
begin
  with Sender as TM_Object do
  begin
    Enabled := not GetBit(AsInt, 0);  // недоступна в нечетных состояниях кнопки (ОТКР. и ЗАКР.)
// конверсия состояний кнопки в состояние управляющих переменных
    case AsInt of
    0: begin SCi_pusk.Value := false; SCi_stop.Value := false; end;
    1: begin SCi_pusk.Value := true; SCi_stop.Value := false; end;
//    2: begin SCi_pusk.Value := true; SCi_stop.Value := false; end;
    3: begin SCi_pusk.Value := false; SCi_stop.Value := true; end;
    end;
  end;
end.
Код: (delphi)
// обратная связь от установки
begin
  with Sender as TM_Object do
  begin
    case AsInt of
    1: if GetBit(VariableEx.AsInt, 10) then value := 2;       // от включения двигателя
//    3: if not GetBit(VariableEx.AsInt, 5) then value := 0;    // от закрытых жалюзи
    3: if GetBit(VariableEx.AsInt, 0) then value := 0;        // от состояния системы
    end;
  end;
end.

2. Пара двоичных кнопок с общим вектором состояния, Однако в этом случае скрипты становятся сложнее, а информативность ниже, т.к. допустимы только три состояния вектора (запрещено - доступны одновременно ПУСК и СТОП). 

15
   Здравствуйте.
Условие:
по сути, притенять кнопку нужно от момента нажатия, до значения переменной 1024. после этого она должная стать активной и перейти в состояние 2
предполагает наличие трёх состояний и, соответственно трех графических образов, причем собственно нажатие кнопки переведет её в следующее состояние.
Возможные варианты создания третьего притемненного состояние:
- при нажатии кнопка становится невидимой, графический объект (Текст, Кнопка или ...) размещенный непосредственно под кнопкой изображает притемненное состояние. По достижении условия кнопка вновь становится видимой;
- добавление третьего (притемненного) состояния к кнопке. в котором кнопка становится "Недоступной". По достижении условия кнопка переходит в состояние "Стоп" и вновь становится доступной;
- аналогично предыдущему варианту, но с использованием автомата состояний. Кнопка прикрыта сверху прозрачным объектом, управляющим автоматом с переходами по нажатию: "Пуск"->"Притемнение", "Притемнение"->"Притемнение", "Стоп"->"Пуск". По достижении условия автомат переходит в состояние "Стоп".
Притемненное состояние кнопки может использоваться для индикации промежуточных состояний (разумеется если они могут быть выделены):
ПУСК -> двигатель запускается -> жалюзи открывается -> что-то ещё случается -> СТОП
Примеры вариантов во вложении.

Страницы: [1] 2 3 ... 14