Показано с 1 по 5 из 5

Тема: Отдельная задача для опроса COM порта. Нужно ли?

  1. #1

    По умолчанию Отдельная задача для опроса COM порта от весового модуля CAS CI-1560. Нужно ли?

    Здравствуйте. Осваиваю CodeSys (3.5 SP5.5). Имею СПК207 и весовой модуль CAS CI-1560.
    За день разобрался, как их подружить, научился парсить то, что рассказывает мне весовой модуль.
    Далее эта связка будет использоваться в узле смешивания компонентов - будет работа с модулями дискретного ввода-вывода, отображение на дисплее всякого.
    Возникли вопросы, на которые я уже часа 4 честно ищу ответы. Посмотрел несколько вебинаров, поискал по форуму по словам "задача"...

    Есть много примеров реализации общения по нестандартным протоколам. Есть целый мануал про это. Но там вся реализация пишется в PLC_PRG.
    У меня же есть смутное подозрение, что общение с COM портом лучше вынести в отдельную задачу - и для отладки, и вообще для порядка в коде.
    Не могу найти какое-то внятное описание лучших практик по этому поводу. В CDSv3.5_FirstStart_v3.0 настоятельно НЕ рекомендуют новичкам связываться с задачами: "Это связано с тем, что принцип обработки в CODESYS достаточно сложен (используется механизм вытесняющей многозадачности) и мало документирован".
    С другой стороны - для общения по Модбасу, вроде бы, задачи чуть ли не автоматически создаются. Значит, это всё же имеет большой смысл...

    Отсюда вопросы:
    1) стоит ли вообще связываться с задачами для общения с COM портом? (постоянное циклическое считывание веса по 232).

    2) У меня уже есть рабочий функциональный блок общения с портом с двумя вложенными методами. Попробовал сделать из него задачу - но к задаче можно привязать только программу. А у программы нет понятия "метод"... Есть "действие", но в руководстве сказано, что это рудимент, да и действию не передать параметры. В CodesysTaskManagment.pdf описано, как можно к задаче прикрутить именно ФБ. Но опять же вопрос - если для этого нужно костыльно прописывать (имя ФБ) что-то руками - может, это не лучший способ, и сокрытие функционала привязки к задаче именно ФБ чем-то оправдано?
    Как лучше поступить в данном случае?
    2.а) создать COM_PRG, в нём просто создать экземпляр уже готового ФБ, вызвать его и успокоиться на этом?
    2.б) создать COM_PRG и переписать весь функционал в него, а вместо методов всё же использовать "действия", как-то накостылив обработку нужных мне данных без передачи параметров?
    2.в) по примеру из Приложение Г CodesysTaskManagment.pdf всё же прикрутить к задаче экземпляр ФБ? Но нужно ли для его объявления создавать отдельный от PLC_PRG файл, или в этом нет большого смысла, и можно объявить экземпляр в PLC_PRG?

    3) Если я всё же свяжусь с отдельной задачей - есть ли какие-то методики подбора оптимального периода её вызова исходя из скорости работы протокола 232 и длины передаваемого пакета байт?
    Я некоторое время программировал (для себя) Arduino и STM32, и после них осталось понимание, что не нужно лишний раз запускать процесс, если это приведёт лишь к бесполезной перезаписи ячеек памяти.
    Например, сейчас у меня настроена скорость передачи 19200 (максимальная для весового модуля). Количество передаваемых им байт: 22 штуки в пакете. Есть ли смысл заморочиться и подогнать периодичность вызова задачи прослушивания порта так, чтоб не было холостых вызовов? Или как у всех - просто выставить примерно 20 милисекунд, и не морочить голову?)


    Спасибо заранее за ответы и советы
    Последний раз редактировалось Нидвораич; 18.02.2025 в 00:01. Причина: вынес в название темы название прибора, так как приложил код работы с ним для будущих поколений

  2. #2

    По умолчанию

    Даже не парьтесь, совсем не обязательно использовать задачи, достаточно вызвать в основной программе, доп. программу или ФБ (в вашем случае). Всё будет работать.
    Мало того, так желательно делать и в дальнейшем, разбивать программу на части и без нужды задачи не трогать.

    И кстати проект опроса модуля CAS CI-1560, тоже можно выложить, если не жалко и код проверен.
    Последний раз редактировалось kondor3000; 17.02.2025 в 22:38.

  3. #3

    По умолчанию

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

    Насчёт кода - попробую тут прикрепить основные моменты, но не гарантирую полную работоспособность. Я ещё не до конца разобрался с обработкой ошибок. Грубо говоря - пока всё штатно - значения считываются. Но что будет, если весовой модуль уйдёт в ошибку, или ещё при каких-то условиях - тут уже сам не знаю. Но кому-то как отправная точка для начала общения с прибором - может пригодиться
    Например - если выдернуть шнур подключения тензоатчика - модуль успевает послать рандомное значение массы (которое в сотни раз может превышать реальное), и только потом падает в ошибку, прекращая вещание в порт.
    Опять же - не уверен, что моя реализация максимально оптимальна в плане грамотного кода, выделения памяти под переменные и прочего.
    Перечислю минусы на всякий случай и в название темы вынесу название прибора, чтоб проще было найти кому-то.
    Пример основан на видео уважаемого товарища с канала КодесисВанЛав. Там был пример работы с нестандартным протоколом.
    Минусы моей реализации:
    1) пока что нормально не обработаны ошибки связи и чтения
    2) пока что НЕ реализован сдвиг по накопительному буферу (в идеале - если пакет пришёл частями - нужно слепить всё это в одном буфере, обработать, и не сразу обнулять буфер, а просто сдвинуть указатель на необработанную часть, потому что там тоже может быть начальная часть следующего пакета, ИМХО). А сам накопительный буфер я планирую не обнулять при близости переполнения, а просто сдвигать необработанную часть в начало буфера. Мне кажется - так правильнее
    3) этот весовой модуль помимо веса и статуса выплёвывает ещё "байт состояния ламп". У него есть 7 ламп: ST, TARE, NET, HOLD, ZERO, kg, t. Почему-то при изменении свечения ламп HOLD, kg и t ни один бит в этом байте не меняется. Либо эти состояния вообще не передаются по каким-то причинам, либо я чего-то не догнал. Состояние остальных ламп я прекрасно считываю и отображаю у себя на отладочной странице визуализации. А эти три не могу. В поддержке мне сказали, что лампы kg и t вообще особо ни на что не влияют (я так и не понял - при одной и той же нагрузке прибор показывает 4.0 и в режиме kg, и в режиме t, хотя в режиме t я ожидал деления на 1000 как бы).


    Итак, полученные и распарсенные данные я собираю в структуру, объявленную в PLC_PRG, и передаваемую в ФБ чтения как IN_OUT (скорее всего, это тоже не очень верно)
    Из PLC_PRG я вызываю ФБ чтения, у ФБ чтения есть два метода - парсинг и очистка буферов. Помимо этого в проекте есть несколько перечислений (отвечающих за шаг выполнения процесса чтения порта и за состояния, передаваемые прибором).

    Библиотека для работы с ком портом: CAA SerialCom 3.5.3.0,
    CodeSys 3.5 SP5 patch 5
    Результат выводится вот на такой отладочный экран
    Monosnap Otladko - Google Chrome 2025-02-18 00.16..png


    boobs.png

    код по порядку из скрина:

    Код:
    TYPE CAS_NetBrut :
    (
    	HZ_beleberda :=0,
    	GS_Brutto := 1,
    	NT_Netto :=2
    );
    END_TYPE
    Код:
    TYPE CAS_Status :
    (
    	HZ_beleberda :=0,
    	US_unstable := 1,
    	ST_stable :=2,
    	OL_overload :=3
    	
    );
    END_TYPE
    Код:
    TYPE COM_CAS_STATE :
    (
    	//INITIALIZE := 00,
    	OPEN_PORT := 0,
    	READ_FROM_PORT :=30,
    	WRITE_TO_PORT :=40,
    	CLOSE_PORT := 50
    );
    END_TYPE
    Код:
    TYPE S_fromCAS :
    	STRUCT
    	
    	DATUS_CORRECTUS: BOOL;
    	s_Pri4inaOstanovki :WSTRING;
    	s_ChoDelaetsaYoMoyo :WSTRING;
    	status: CAS_Status;
    	itiBrut: CAS_NetBrut;
    	DevID: 	USINT;
    	Lamp_Zero: BOOL;
    	Lamp_Tare: BOOL;
    	Lamp_Net: BOOL;
    	Lamp_Stable: BOOL;
    	Lamp_Hold: BOOL;
    	Lamp4: BOOL; // непонятно, за что отвечает этот бит
    	Lamp5: BOOL; // непонятно, за что отвечает этот бит
    	Lamp7: BOOL; // непонятно, за что отвечает этот бит
    	VES: REAL;
    END_STRUCT
    END_TYPE

    Код:
    FUNCTION_BLOCK fb_CAS_CI_1560
    VAR_INPUT
    	
    END_VAR
    VAR_OUTPUT
    	
    END_VAR
    VAR
    	
    
    eState:				COM_CAS_STATE:=COM_CAS_STATE.OPEN_PORT;
    	//xAllreadyOpened:	BOOL :=false;
    	aCom232Params : ARRAY [1..7] OF COM.PARAMETER;
    //sComSet:			COM.COM_Settings;
        fb_ComOpen:			COM.Open;
    	
    	fb_ComRead:			COM.Read;
    	fb_ComSend:			COM.Write;
    	
    	//буфер для одного фрагмента пакета
    	abyResponseBuffer: 	ARRAY[0..255] OF BYTE;
    	
    	//буфер для хранения полного пакета
    	abyPaket_S_Paketami:		ARRAY[0..255] OF BYTE;
    	
    	//полный пакет в строковом виде
    	//sPaket_S_Paketami:			STRING(1024);
    	
    	//размер заполненности пакета с пакетами
    	uiCurrentPSP_size: 			UINT;
    	
    	//таймер ожидания полного пакета
    	fbWaitingOfPosylkaTimer:		TON;
    
    	//таймер терпения отсутствия пакетов
    	fbWaitingAnyPosylkaTimer:		TON;
    	
    	
    	//флаг "Программа в процессе получения полного пакета" (взодится после получения первого фрагмента пакета) 
    	xRecieveInProgress:	BOOL;
    	
    	//тестовая строка для посылки на модуль
    	sTestingSlovoToCas:		STRING := '1';
    	
    	rVes: REAL;
    	
    	udiDlinaPaketa:	UDINT :=22;
    	tTimeToWaitBeforeError:		TIME := T#1000MS;
    			
    	//fb_SET_CAS:				SET_CAS;		
    
    	//i:						INT;			
    	
    	//xOpen:					BOOL;			
    	//xClose:					BOOL;	
    END_VAR
    VAR_IN_OUT
        s_ShoTam: S_fromCAS;
    END_VAR
    
    CASE eState OF
    	COM_CAS_STATE.OPEN_PORT:
    								s_ShoTam.s_ChoDelaetsaYoMoyo:="пробуем открыть порт";
    										aCom232Params[1].udiParameterId := COM.CAA_Parameter_Constants.udiPort;
    										aCom232Params[1].udiValue := 2; // the correct Port should be adapted
    										aCom232Params[2].udiParameterId := COM.CAA_Parameter_Constants.udiBaudrate;
    										aCom232Params[2].udiValue := 19200;
    										aCom232Params[3].udiParameterId := COM.CAA_Parameter_Constants.udiParity;
    										aCom232Params[3].udiValue := INT_TO_UDINT(COM.PARITY.NONE);
    										aCom232Params[4].udiParameterId := COM.CAA_Parameter_Constants.udiStopBits;
    										aCom232Params[4].udiValue := INT_TO_UDINT(COM.STOPBIT.ONESTOPBIT);
    										aCom232Params[5].udiParameterId := COM.CAA_Parameter_Constants.udiTimeout;
    										aCom232Params[5].udiValue := 0;
    										aCom232Params[6].udiParameterId := COM.CAA_Parameter_Constants.udiByteSize;
    										aCom232Params[6].udiValue := 8;
    										aCom232Params[7].udiParameterId := COM.CAA_Parameter_Constants.udiBinary;
    										aCom232Params[7].udiValue := 0;
    								fb_ComOpen(xExecute:=TRUE, usiListLength:=SIZEOF(aCom232Params)/SIZEOF(COM.PARAMETER),pParameterList:= ADR(aCom232Params));
    								IF fb_ComOpen.xError THEN
    									s_ShoTam.DATUS_CORRECTUS:=FALSE;
    									s_ShoTam.s_Pri4inaOstanovki:="ошибка соединения с весовым модулем";
    								END_IF	
    								
    								IF fb_ComOpen.xDone THEN
    									eState:= COM_CAS_STATE.READ_FROM_PORT;
    								ELSE
    									s_ShoTam.DATUS_CORRECTUS:=FALSE;
    									s_ShoTam.s_Pri4inaOstanovki:="ожидание соединения с весовым модулем";
    									
    								END_IF
    	
    	
    	COM_CAS_STATE.READ_FROM_PORT:
    								s_ShoTam.s_ChoDelaetsaYoMoyo:="пробуем читать из порта";
    								fb_ComRead(xExecute:=TRUE, hCom:= fb_ComOpen.hCom, pBuffer:=ADR(abyResponseBuffer), szBuffer:= SIZEOF(abyResponseBuffer));
    								fbWaitingOfPosylkaTimer(IN:=xRecieveInProgress, PT:=tTimeToWaitBeforeError);
    								fbWaitingAnyPosylkaTimer(IN:=TRUE, pt:=tTimeToWaitBeforeError);
    								// получен пакет или его обрывок
    								IF fb_ComRead.xDone THEN
    									IF fb_ComRead.szSize >0 THEN
    										xRecieveInProgress:= TRUE;
    										//пихаем обрывок в пакет с пакетами, если там ещё есть место
    										{warning 'Разобраться, что делать при переполнении'}			
    										
    										IF (uiCurrentPSP_size + fb_ComRead.szSize) <= SIZEOF(abyPaket_S_Paketami) THEN
    											Mem.MemMove(ADR(abyResponseBuffer), ADR(abyPaket_S_Paketami) + uiCurrentPSP_size, TO_UINT(fb_ComRead.szSize));
    											uiCurrentPSP_size := uiCurrentPSP_size + TO_UINT(fb_ComRead.szSize);
    											
    										END_IF
    										ParsinH();	
    									END_IF //считана не пустота
    								
    									// сброс блока для последующего перезапуска - даже если в буфере нет данных
    									fb_ComRead(xExecute := FALSE);
    									
    									
    								// при вызове ФБ произошла ошибка
    								ELSIF fb_ComRead.xError THEN
    									
    									fb_ComRead(xExecute := FALSE);			
    									xRecieveInProgress:= FALSE;
    									s_ShoTam.DATUS_CORRECTUS:=FALSE;
    									s_ShoTam.s_Pri4inaOstanovki:="ошибка чтения порта";
    									
    									//eState:= COM_CAS_STATE.OPEN_PORT;
    									
    								END_IF //окончание чтения
    								//MEM.MemMove(ADR(abyPaket_S_Paketami), ADR(sPaket_S_Paketami), TO_UINT(udiCurrentPSP_size) );
    								
    								
    								IF uiCurrentPSP_size > 200 THEN
    									prvClear();	
    								END_IF
    								// если за заданное время не получили полного пакета - то начинаем всё заново
    									IF fbWaitingOfPosylkaTimer.Q THEN
    										
    										// чистим буферы и сбрасываем переменные
    										prvClear();
    										eState:= COM_CAS_STATE.OPEN_PORT;
    										s_ShoTam.DATUS_CORRECTUS:=FALSE;
    										s_ShoTam.s_Pri4inaOstanovki:="истекло время ожидания пакета от весового модуля";
    									END_IF
    								
    		
    END_CASE


    Код:
    METHOD ParsinH
    VAR_INPUT
    END_VAR
    VAR
    	i: UINT;
    	y: USINT;
    	ui_NACHALO: UINT;
    	sTempVes: STRING(8);
    	
    	
    	usiFirstCifra: USINT;
    	rWeightValue: REAL;
    END_VAR
    VAR CONSTANT
    	c_PROBEL: 	USINT:=32;
    	c_ZPT:		USINT:=44;
    	c_CR:		USINT:=13;
    	c_LF:		USINT:=10;
    	 
    END_VAR
    
    
    
    
    {region “Описание протокола”}
    	// 'ST,GS,A»,-    0.2 kg$R$N-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-    0.2 kg$R$N   0.2 kg$R$NST,GS,A»,-    0.2 kg$R$NST,GS,A»,-  '
    	(*
    	00	S  (стаб)  U (нестаб)   пусто (хз)   O (перегруз)   
    	01  T  (стаб)  S (нестаб)	пусто (хз)	 L (перегруз)
    	02	, = 44
    	03	G (брутто)	N (нетто)
    	04	S (брутто)	T (нетто)
    	05	, = 44
    	06	ID
    	07  ламповая статусность: 
    		7	1
    		6	состояние стабильности
    		5	0
    		4	взвешивание нестабильных грузов (чот не меняется бит, когда лампочка вроде мигает)
    		3	передача данных
    		2	масса нетто
    		1	выборка массы тары
    		0	обнуление
    	08	, = 44
    	09	данные о массе
    	10	данные о массе
    	11	данные о массе
    	12	данные о массе
    	13	данные о массе
    	14	данные о массе
    	15	данные о массе
    	16	данные о массе
    	17	пусто
    	18	k (единица измерения)
    	19	g (единица измерения)
    	20	CR 0x0D = 13
    	21	LF 0x0A = 10
    	*)
    {endregion}
    //предполагаю, что посылка получена с самого начала. Соответвтенно - её конец находится на 20-21 байте
    //n:=INT_TO_BYTE(SIZEOF(abyPaket_S_Paketami))-1;
    FOR i:=20 TO uiCurrentPSP_size DO
    	//ищем конец пакета из CR LF
    	IF abyPaket_S_Paketami[i] = c_CR AND abyPaket_S_Paketami[i+1] = c_LF  THEN
     		// если найден конец пакета - есть смысл поискать весь пакет в предыдущих байтах
    		IF abyPaket_S_Paketami[i-3]=c_PROBEL AND abyPaket_S_Paketami[i-12]=c_ZPT AND abyPaket_S_Paketami[i-15]=c_ZPT AND abyPaket_S_Paketami[i-18]=c_ZPT THEN
    			ui_NACHALO:=i-20;
    			s_ShoTam.DATUS_CORRECTUS:=TRUE;
    			
    			//определение передаваемого статуса. СТабильно, нестабильно, перегруз
    			IF abyPaket_S_Paketami[ui_NACHALO] = 83 AND abyPaket_S_Paketami[ui_NACHALO+1] = 84 THEN 
    				s_ShoTam.status:=CAS_Status.ST_stable;
    			ELSIF abyPaket_S_Paketami[ui_NACHALO] = 85 AND abyPaket_S_Paketami[ui_NACHALO+1] = 83 THEN 
    				s_ShoTam.status:=CAS_Status.US_unstable;
    			ELSIF abyPaket_S_Paketami[ui_NACHALO] = 79 AND abyPaket_S_Paketami[ui_NACHALO+1] = 76 THEN 
    				s_ShoTam.status:=CAS_Status.OL_overload;
    				s_ShoTam.DATUS_CORRECTUS:=FALSE;
    				s_ShoTam.s_Pri4inaOstanovki:="ПЕРЕГРУЗ";
    			ELSE
    				s_ShoTam.DATUS_CORRECTUS:=FALSE;
    				s_ShoTam.s_Pri4inaOstanovki:="битый статус";
    				s_ShoTam.status:=CAS_Status.HZ_beleberda;
    			END_IF
    			
    			//определение иты брута
    			IF abyPaket_S_Paketami[ui_NACHALO+3] = 71 AND abyPaket_S_Paketami[ui_NACHALO+4] = 83 THEN 
    				s_ShoTam.itiBrut:=CAS_NetBrut.GS_Brutto;
    			ELSIF abyPaket_S_Paketami[ui_NACHALO+3] = 78 AND abyPaket_S_Paketami[ui_NACHALO+4] = 84 THEN 
    				s_ShoTam.itiBrut:=CAS_NetBrut.NT_Netto;
    			ELSE
    				s_ShoTam.DATUS_CORRECTUS:=FALSE;
    				s_ShoTam.s_Pri4inaOstanovki:="битое нетто\брутто";
    				s_ShoTam.itiBrut:=CAS_NetBrut.HZ_beleberda;
    			END_IF
    			
    							s_ShoTam.Lamp_Zero:=NOT(abyPaket_S_Paketami[ui_NACHALO+7].0);
    							s_ShoTam.Lamp_Tare:=NOT(abyPaket_S_Paketami[ui_NACHALO+7].1);
    							s_ShoTam.Lamp_Net:=abyPaket_S_Paketami[ui_NACHALO+7].2;
    							s_ShoTam.Lamp_Hold:=NOT(abyPaket_S_Paketami[ui_NACHALO+7].3);
    							s_ShoTam.Lamp_Stable:=NOT(abyPaket_S_Paketami[ui_NACHALO+7].6);
    							
    							
    			s_ShoTam.Lamp4:=abyPaket_S_Paketami[ui_NACHALO+7].4;
    			s_ShoTam.Lamp5:=abyPaket_S_Paketami[ui_NACHALO+7].5; //типа всегда 0
    			s_ShoTam.Lamp7:=abyPaket_S_Paketami[ui_NACHALO+7].7; // типа всегда 1
    							
    							
    
    			//MEM.MemMove(ADR(abyPaket_S_Paketami[ui_NACHALO+8]), ADR(sTempVes),9 );
    			sTempVes:='HUIPIZDA';
    			usiFirstCifra:=0;
    			FOR y:=0 TO 7 DO
    				sTempVes[y]:=abyPaket_S_Paketami[y+ui_NACHALO+8+1];
    				IF usiFirstCifra=0 AND y>0 AND sTempVes[y]<>32 THEN
    					usiFirstCifra:=y;
    				END_IF
    			END_FOR
    			IF sTempVes[0]=45 THEN
    				sTempVes[0]:=32;
    				sTempVes[usiFirstCifra-1]:=45;
    			END_IF
    			
    			s_ShoTam.VES := -9999;
    			s_ShoTam.VES := TO_REAL(sTempVes);
    //IF abyPaket_S_Paketami[ui_NACHALO] = 83 AND abyPaket_S_Paketami[ui_NACHALO+1] = 84 THEN s_ShoTam.status:=CAS_Status.ST_stable;
    			//IF abyPaket_S_Paketami[ui_NACHALO] = 83 AND abyPaket_S_Paketami[ui_NACHALO+1] = 84 THEN s_ShoTam.status:=CAS_Status.ST_stable;
    		
    		
    		END_IF
    	END_IF
    END_FOR


    Код:
    // метод очистки буферов и сброса переменных после получения запроса или в случае ошибки
    METHOD prvClear
    
    VAR_INPUT
    END_VAR
    
    VAR
    	ci:	S_fromCAS;
    	
    END_VAR
    
    
    // чистим буферы
    Mem.MemFill(ADR(abyResponseBuffer), SIZEOF(abyResponseBuffer), 0);
    Mem.MemFill(ADR(abyPaket_S_Paketami), 	    SIZEOF(abyPaket_S_Paketami), 0);
    				
    // сбрасывем флаг "Программа в процессе получения пакета" и позицию в буфере
    xRecieveInProgress := FALSE;
    uiCurrentPSP_size := 0;

    ну и в PLC_PRG:

    Код:
    fbCAS: fb_CAS_CI_1560;
    s_ShoTamUcas: S_fromCAS;
    
    fbCAS(s_ShoTam:=s_ShoTamUcas);
    Последний раз редактировалось Нидвораич; 18.02.2025 в 09:25. Причина: исправил время ожидания таймера. Проект в разработке. Экспериментировал...

  4. #4

    По умолчанию

    Так как прибор у Вас один и он является определяющим в системе, то смысла в отдельной задаче нет. Смысл есть, когда система имеет много распределённых точек ввода-вывода. Так, установлено, что уже при наличии 30 серверов modbusTCP возникают тормоза в веб-визуализации (особенно если в сети что-то отвалилось). И вот здесь помогают задачи с их приоритетами и вытесняющей многозадачностью. Tоже самое можно реализовать самостоятельно в рамках одной задачи. Вопрос только зачем, когда есть готовый механизм.

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

  5. #5

    По умолчанию

    Цитата Сообщение от Емельянов Кирилл Посмотреть сообщение
    установлено, что уже при наличии 30 серверов modbusTCP возникают тормоза в веб-визуализации (особенно если в сети что-то отвалилось). И вот здесь помогают задачи с их приоритетами и вытесняющей многозадачностью.
    спасибо стало понятнее, зачем для модбаса создаются задачи, соответственно - энтузиазма городить задачу для одного устройства поубавилось

Похожие темы

  1. Задача об АР
    от Нока в разделе Трёп (Курилка)
    Ответов: 0
    Последнее сообщение: 13.02.2021, 21:36
  2. Ответов: 1
    Последнее сообщение: 05.03.2020, 08:38
  3. Ответов: 7
    Последнее сообщение: 30.05.2011, 08:33
  4. МВА8 нужно примеры програмирования (опроса) на delphi
    от Aleksey Myasnikov в разделе Помощь Разработчикам
    Ответов: 0
    Последнее сообщение: 20.01.2011, 10:22
  5. задача
    от Дмитрий Донской в разделе Помощь Разработчикам
    Ответов: 2
    Последнее сообщение: 15.11.2007, 10:13

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •