[?]: поставить паузу в WinCC перед следующим действием опера

Панели оператора PP/OP/TP/TD/MP.
Программные пакеты ProTool/WinCC flexible, SCADA система WinCC
Arthur9186
Posts: 8
Joined: Wed Aug 10, 2011 8:15 am

[?]: поставить паузу в WinCC перед следующим действием опера

Post by Arthur9186 »

Форумчане, подайте идею как решить задачу.

есть проект на winCC.
Надо на выполнении определенной операции поставить паузу,что бы выбранное решение успело вступить перед следующим изменением оператора.

Как я думаю:
есть иконка ввода с этим кодом:

Code: Select all

#include "apdefap.h"
void OnKeyDown(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nChar, UINT nRepCnt, UINT nFlags)
{
// WINCC:TAGNAME_SECTION_START
// syntax: #define TagNameInAction "DMTagName"
// next TagID : 1
// WINCC:TAGNAME_SECTION_END

// WINCC:PICNAME_SECTION_START
// syntax: #define PicNameInAction "PictureName"
// next PicID : 1
// WINCC:PICNAME_SECTION_END
char lpszTagName[128];
double dOldValue;
double dNewValue;

if (nChar == 13)
{
  sprintf(lpszTagName,"%s%s",GetText(lpszPictureName,"PositionName"),GetLinkedVariable(lpszPictureName,lpszObjectName,"OutputValue"));
  dOldValue = GetPropDouble(lpszPictureName,"FieldOldValue","OutputValue");
  dNewValue= GetPropDouble(lpszPictureName,lpszObjectName,"InputValue");
  LogValue(lpszTagName,GetText(lpszPictureName,"EUName"),dOldValue,dNewValue);
//  SubstituteValue(GetText(lpszPictureName,"ODBCName"),lpszTagName,dNewValue);
  SetPropDouble(lpszPictureName,"FieldOldValue","OutputValue",dNewValue);
}
}
и я хочу вставить sleep(3000), что бы получилось, что-то на подобии:

Code: Select all

#include "apdefap.h"
void OnKeyDown(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nChar, UINT nRepCnt, UINT nFlags)
{
// WINCC:TAGNAME_SECTION_START
// syntax: #define TagNameInAction "DMTagName"
// next TagID : 1
// WINCC:TAGNAME_SECTION_END

// WINCC:PICNAME_SECTION_START
// syntax: #define PicNameInAction "PictureName"
// next PicID : 1
// WINCC:PICNAME_SECTION_END
char lpszTagName[128];
double dOldValue;
double dNewValue;

if (nChar == 13)
{
  sprintf(lpszTagName,"%s%s",GetText(lpszPictureName,"PositionName"),GetLinkedVariable(lpszPictureName,lpszObjectName,"OutputValue"));
  dOldValue = GetPropDouble(lpszPictureName,"FieldOldValue","OutputValue");
  dNewValue= GetPropDouble(lpszPictureName,lpszObjectName,"InputValue");
  LogValue(lpszTagName,GetText(lpszPictureName,"EUName"),dOldValue,dNewValue);
//  SubstituteValue(GetText(lpszPictureName,"ODBCName"),lpszTagName,dNewValue);
  SetPropDouble(lpszPictureName,"FieldOldValue","OutputValue",dNewValue);
}
sleep(3000);
}

Но есть пара проблем:
1) как подключить библиотеку для sleep()
2) и почему-то компилятор winCC на любые изменения в программе ругается на

Code: Select all

  LogValue(lpszTagName,GetText(lpszPictureName,"EUName"),dOldValue,dNewValue);
пишет
error(0069): type mismatch in argument 3
error (006a): not enough arguments for function 'LogValue'
хотя программа уже несколько лет работает исправно.

Заранее спасибо
Linkinx64
Posts: 894
Joined: Sun Apr 11, 2010 3:00 am
Location: Russia

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Linkinx64 »

Если это связано с WinAPI:
1. Ф-ция Sleep() (Sleep(__in DWORD dwMilliseconds)) определена в библиотеке kernel32.dll. Как подключать в WinCC - #include kernel32.dll, кури документацию на сайте сименса.
2. Попробуй сначала присвоить значение GetText переменной (тип char*), затем передай эту переменную в качестве 2-го аргумента ф-ции LogValue. И ещё попробуй поменять "EUName" на L"EUName". Как-то перекомпилирывал прогу сделанную в VC++ 6.0 на VS2008, компилятор всё возгудал пока я "L" перед всеми строками не понаставил.

P.S. Постановка задачи непонятна: какое решение должно вступать? зачем для этого блокировать доступ оператору на 3 секунды? Ну и пусть он выполняет операции дальше, они все будут обработанны одна за одной.. Он что, вводит новые данные быстрее, чем винсс обрабатывает старые? Ну так от этого уже предусмотрена защита - буфер ввода называется. Он не бесконечен, и при переполнении компьютер запищит о невозможности буферизации очередной команды. Думается мне, вот так просто впихнув Sleep в конец функции на паузу встанет не только текущая операция, но и всё winCC. Попробуй решить свою задачу (хотя я не понимаю её сути) с помощью таймера. Экземпл использования таймеров здесь - http://msdn.microsoft.com/en-us/library ... s.85).aspx. Библиотека : user32.dll. Как подключать к винсс и куда совать WM_TIMER - см.п.1. Но идея, надеюсь, ясна.
dmitry_79
Posts: 149
Joined: Sun Dec 20, 2009 1:30 pm
Location: Russia

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by dmitry_79 »

Не забываем что скриптовая подсистема WinCC онднозадачная! Такая "пауза" запретит выполнение всех скриптов, пока время не истечет, что может привести к падению подсистемы. Решайте данную задачу средствами PLC - безопасней и надежней.
Arthur9186
Posts: 8
Joined: Wed Aug 10, 2011 8:15 am

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Arthur9186 »

Спасибо за пояснения.
Функция Sleep() я решил вообще не ставить. Везде на нее ругаются. Поставил другие ограничения на ввод(чисел) для оператора.

А вот с
2. Попробуй сначала присвоить значение GetText переменной (тип char*), затем передай эту переменную в качестве 2-го аргумента ф-ции LogValue. И ещё попробуй поменять "EUName" на L"EUName". Как-то перекомпилирывал прогу сделанную в VC++ 6.0 на VS2008, компилятор всё возгудал пока я "L" перед всеми строками не понаставил.
если я не ошибаюсь, то L ставится VC++ если косяк с кодировкой(перевод в русскую). И кстати после записи L"EUName" появляется ошибка
undefined identifier 'L'
Linkinx64
Posts: 894
Joined: Sun Apr 11, 2010 3:00 am
Location: Russia

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Linkinx64 »

Arthur9186 wrote:если я не ошибаюсь, то L ставится VC++ если косяк с кодировкой(перевод в русскую). И кстати после записи L"EUName" появляется ошибка
Да, это из-за очередных нововведений от лукавого. То перед стрингами L надо ставить, то cout переименовывать в std::cout, то в include несуществующая библиотека... Скомпилировать старый код в новой среде без ошибок редко когда получается.
А без L всё равно ругается на аргумент?
Arthur9186
Posts: 8
Joined: Wed Aug 10, 2011 8:15 am

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Arthur9186 »

А еще не подскажите как можно установить зависимость старого значения относительно нового?
К примеру разность dOldValue(который на момент ввода находится в памяти контроллера) и dNewValue должна быть меньше 3-х. И где это прописать можно? т.к. раздел keyboard -> Press, в котором находился вышеописанный текст, совсем не реагирует на какие-либо изменения в ручном режиме..........
Linkinx64
Posts: 894
Joined: Sun Apr 11, 2010 3:00 am
Location: Russia

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Linkinx64 »

Не совсем понятно..
Если требуется выравнивать dNewValue относительно dOldValue, то это можно сделать в цикле, например :

Code: Select all

while((dOldValue - dNewValue) > 3)
{
   dNewValue += 0.1; /* чем меньше шаг и чем больше дельта dOldValue-dNewValue - тем дольше время выполнения цикла. */
}
Вот и будет тебе зависимость.
Если же требуется что-то выполнить, когда дельта меньше 3, то вставь это условие в if...else.
Arthur9186
Posts: 8
Joined: Wed Aug 10, 2011 8:15 am

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Arthur9186 »

в разделе раздел keyboard -> Press, где был текст

Code: Select all

 char lpszTagName[128];
 double dOldValue;
 double dNewValue;

 sscanf (lpszTagName,"%s%s",GetText(lpszPictureName,"PositionName"),GetLinkedVariable(lpszPictureName,lpszObjectName,"OutputValue"));
 dOldValue = GetPropDouble(lpszPictureName,"FieldOldValue","OutputValue");
 dNewValue= GetPropDouble(lpszPictureName,lpszObjectName,"InputValue");
  LogValue(lpszTagName,GetText(lpszPictureName,"EUName"),dOldValue,dNewValue);
 //  SubstituteValue(GetText(lpszPictureName,"ODBCName"),lpszTagName,dNewValue);
   SetPropDouble(lpszPictureName,"FieldOldValue","OutputValue",dNewValue);
 sprintf (lpszTagName,"%s%s",GetText(lpszPictureName,"PositionName"),GetLinkedVariable(lpszPictureName,lpszObjectName,"OutputValue"));
}
я сделал так:

Code: Select all

 char lpszTagName[128];
 double dOldValue;
 double dNewValue;

 sscanf (lpszTagName,"%s%s",GetText(lpszPictureName,"PositionName"),GetLinkedVariable(lpszPictureName,lpszObjectName,"OutputValue"));
 dOldValue = GetPropDouble(lpszPictureName,"FieldOldValue","OutputValue");
 dNewValue= GetPropDouble(lpszPictureName,lpszObjectName,"InputValue");

if((dOldValue-dNewValue>3)||(dNewValue-dOldValue>3))
{
     if(dOldValue-dNewValue>3)
 	{dNewValue=dOldValue+3;
 	}
      else
 	{dNewValue=dOldValue-3;
 	}
} 

 //  LogValue(lpszTagName,GetText(lpszPictureName,"EUName"),dOldValue,dNewValue);
 //  SubstituteValue(GetText(lpszPictureName,"ODBCName"),lpszTagName,dNewValue);
   SetPropDouble(lpszPictureName,"FieldOldValue","OutputValue",dNewValue);
 sprintf (lpszTagName,"%s%s",GetText(lpszPictureName,"PositionName"),GetLinkedVariable(lpszPictureName,lpszObjectName,"OutputValue"));
}
но изменений никаких нет. Вводимое с клавиатуры число не изменяется в зависимости от предыдущего значения
Linkinx64
Posts: 894
Joined: Sun Apr 11, 2010 3:00 am
Location: Russia

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Linkinx64 »

А что в данном случае означает "3" и каких изменений ты ждёшь?
Допустим

Code: Select all

dOldValue = 100 
а dNewValue = 2.
if 100-2=98 > 3 => true, а раз true dNewValue = 100 + 3 = 103.
Вся калькуляция заняла тактов 10 или меньше...это, не дай бох соврать, 2-3 микросекунды времени современных процессоров, а может и меньше
Программа пошла выполняться далее, и к сравнению больше не вернётся, если не вызывать... Устраивает задержка в 2-3 микросекунды? Если да- задача худо-бедно решена.
Говорю - юзай таймеры. Будет чёткая привязка по времени.
Arthur9186
Posts: 8
Joined: Wed Aug 10, 2011 8:15 am

Re: [?]: поставить паузу в WinCC перед следующим действием о

Post by Arthur9186 »

Code: Select all

Код:
dOldValue = 100
а dNewValue = 2.
if 100-2=98 > 3 => true, а раз true dNewValue = 100 + 3 = 103.
Сорри ступил малость........
Мне надо :

Code: Select all

dOldValue=100           //взятое из памяти
/*вводим*/dNewValue=2
if ((dOldValue>dNewValue)&&(dOldValue-dNewValue>3))
{dNewValue=dOldValue-3;
}
 
Но вопрос в каком разделе это прописывать???

P.S.: таймеры мне уже не нужны.