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

Тема: Чтение с помощью библиотеки UNM

  1. #1

    По умолчанию Чтение с помощью библиотеки UNM

    Возможно, глупый вопрос: как читать данные из последовательного порта с помощью библоитеки UNM?
    Гляжу пример - там читают по одному байту за цикл программы, и сразу же анализируют:
    код примера:
    Код:
    	(*Ïðèåì îòâåòà*)
    		t1;
    		otvet_RB:=GetByte(DeviceNumber);
    		(*Åñëè ïîëó÷èëè íîâûé áàéò, òî ñîáèðàåì åãî â ðåçóëüòàò*)
    		(*è âåäåì ïîäñ÷åò ïðèíÿòûõ áàéò*)
    		IF otvet_RB>0 THEN
    			p:=ADR(otvet)+count;
    			p^:=otvet_RB^.data;
    			count:=count+1;
    		END_IF
    
    		(*Åñëè ïîëó÷èëè ïåðâûé áàéò, ïðîâåðÿåì àäðåñ óñòðîéñòâà*)
    		IF count=1 AND otvet[0]<>DeviceAdr AND t1.Q=FALSE THEN
    			error:=1;
    			t1(IN:=FALSE);
    			t1;
    			stat:=6;
    			ready:=TRUE;
    		END_IF
    
    		(*&#197;&#241;&#235;&#232; &#239;&#238;&#235;&#243;&#247;&#232;&#235;&#232; &#226;&#242;&#238;&#240;&#238;&#233; &#225;&#224;&#233;&#242;, &#242;&#238; &#239;&#240;&#238;&#226;&#229;&#240;&#255;&#229;&#236; &#240;&#224;&#231;&#236;&#229;&#240; &#239;&#238;&#241;&#251;&#235;&#234;&#232;*)
    		(*&#200;&#235;&#232; &#239;&#240;&#238;&#226;&#229;&#240;&#255;&#229;&#236; &#234;&#238;&#228; &#238;&#248;&#232;&#225;&#234;&#232;*)
    		IF count=2  AND t1.Q=FALSE THEN
    			IF otvet[1]<>16#03 AND otvet[1]<>16#83 THEN
    				error:=2;
    				t1(IN:=FALSE);
    				t1;
    				stat:=6;
    				ready:=TRUE;
    			ELSIF otvet[1]=16#83 THEN
    				modbus_error:=TRUE;
    			END_IF
    		END_IF
    
    		(*&#197;&#241;&#235;&#232; &#239;&#238;&#235;&#243;&#247;&#232;&#235;&#232; &#242;&#240;&#229;&#242;&#232;&#233; &#225;&#224;&#233;&#242;, &#242;&#238; &#239;&#240;&#238;&#226;&#229;&#240;&#255;&#229;&#236; &#240;&#224;&#231;&#236;&#229;&#240; &#239;&#238;&#241;&#251;&#235;&#234;&#232;*)
    		IF count=3 AND  modbus_error=FALSE AND otvet[2]<>Quantity*2 AND t1.Q=FALSE THEN
    			error:=3;
    			t1(IN:=FALSE);
    			t1;
    			stat:=6;
    			ready:=TRUE;
    		END_IF
    
    		(*&#197;&#241;&#235;&#232; &#226; &#238;&#242;&#226;&#229;&#242;&#229; &#225;&#251;&#235; &#234;&#238;&#228; &#238;&#248;&#232;&#225;&#234;&#232;, &#242;&#238; &#226; &#242;&#240;&#229;&#242;&#252;&#229;&#236; &#225;&#224;&#233;&#242;&#229; &#247;&#232;&#242;&#224;&#229;&#236; &#232;&#241;&#234;&#235;&#254;&#247;&#229;&#237;&#232;&#229;*)
    		IF count=3 AND modbus_error=TRUE  AND t1.Q=FALSE THEN
    			IF otvet[2]=1 THEN
    				error:=4;
    			ELSIF otvet[2]=2 THEN
    				error:=5;
    			ELSIF otvet[2]=3 THEN
    				error:=6;
    			ELSIF otvet[2]=4 THEN
    				error:=7;
    			ELSE
    				error:=8;
    			END_IF
    		END_IF
    
    		(*&#197;&#241;&#235;&#232; &#239;&#238;&#235;&#237;&#238;&#241;&#242;&#252;&#254; &#239;&#240;&#232;&#248;&#229;&#235; &#238;&#248;&#232;&#225;&#238;&#247;&#237;&#251;&#233; &#238;&#242;&#226;&#229;&#242; &#231;&#224; &#228;&#238;&#239;&#243;&#241;&#242;&#232;&#236;&#238;&#229; &#226;&#240;&#229;&#236;&#255;, &#239;&#240;&#238;&#226;&#229;&#240;&#255;&#229;&#236; CRC*)
    		IF count=otvet_len_error AND modbus_error=TRUE AND t1.Q=FALSE  THEN
    			(*&#208;&#224;&#241;&#247;&#229;&#242; CRC*)
    			p:=ADR(otvet);
    			CRC:=MB_CRC(p, otvet_len_error-2);
    			p:=ADR(CRC);
    			crc1:=p^;
    			p:=ADR(CRC)+1;
    			crc2:=p^;
    			(*&#209;&#226;&#229;&#240;&#255;&#229;&#236; CRC*)
    			IF crc1=otvet[otvet_len_error-2] AND crc2=otvet[otvet_len_error-1] THEN
    				error:=error;
    			ELSE
    				error:=9;
    			END_IF
    			t1(IN:=FALSE);
    			t1;
    			stat:=6;
    			ready:=TRUE;
    			modbus_error:=FALSE;
    		END_IF
    
    		(*&#197;&#241;&#235;&#232; &#239;&#238;&#235;&#243;&#247;&#229;&#237; &#238;&#242;&#226;&#229;&#242; &#231;&#224; &#228;&#238;&#239;&#243;&#241;&#242;&#232;&#236;&#238;&#229; &#226;&#240;&#229;&#236;&#255; &#238;&#230;&#232;&#228;&#224;&#237;&#232;&#255;, &#242;&#238; &#239;&#240;&#238;&#226;&#229;&#240;&#255;&#229;&#236; CRC *)
    		(*&#200; &#244;&#238;&#240;&#236;&#232;&#240;&#243;&#229;&#236; &#240;&#229;&#231;&#243;&#235;&#252;&#242;&#224;&#242;*)
    		IF count=otvet_len  AND t1.Q=FALSE  THEN
    			(*&#208;&#224;&#241;&#247;&#229;&#242; CRC*)
    			p:=ADR(otvet);
    			CRC:=MB_CRC(p, otvet_len-2);
    			p:=ADR(CRC);
    			crc1:=p^;
    			p:=ADR(CRC)+1;
    			crc2:=p^;
    			(*&#209;&#226;&#229;&#240;&#255;&#229;&#236; CRC*)
    			IF crc1=otvet[otvet_len-2] AND crc2=otvet[otvet_len-1] THEN
    				error:=0;
    				(*&#194;&#251;&#228;&#224;&#229;&#236; &#240;&#229;&#231;&#243;&#235;&#252;&#242;&#224;&#242;*)
    				FOR i:=0 TO Quantity*2-1 DO
    					out[i]:=otvet[3+i];
    				END_FOR
    
    				FOR i:=Quantity*2 TO 127 DO
    					out[i]:=0;
    				END_FOR
    				(*&#194;&#251;&#228;&#224;&#229;&#236; &#247;&#232;&#241;&#235;&#238; &#225;&#224;&#233;&#242; &#226; &#238;&#242;&#226;&#229;&#242;&#229;*)
    				ByteCount:=Quantity*2;
    			ELSE
    				error:=10;
    			END_IF
    			t1(IN:=FALSE);
    			t1;
    			stat:=6;
    			ready:=TRUE;
    		END_IF
    
    		IF t1.IN AND t1.Q THEN
    			error:=11;
    			t1(IN:=FALSE);
    			t1;
    			stat:=6;
    			ready:=TRUE;
    		END_IF

    Для сравнения, с помощью библиотеки SysLibCom читают буфер в цикле целиком, не дожидаясь следующего вызова программы:
    код примера:
    Код:
    	(*&#215;&#242;&#229;&#237;&#232;&#229; &#225;&#243;&#244;&#229;&#240;&#224; &#239;&#240;&#232;&#229;&#236;&#224;*)
    	0:
    		(*&#194;&#251;&#231;&#251;&#226;&#224;&#229;&#236; &#242;&#224;&#233;&#236;&#229;&#240; &#238;&#230;&#232;&#228;&#224;&#237;&#232;&#255; &#238;&#242;&#226;&#229;&#242;&#224;*)
    		T1();
    		(*&#194; &#239;&#229;&#240;&#229;&#236;&#229;&#237;&#237;&#243;&#254; byte_read &#236;&#251; &#239;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#247;&#232;&#241;&#235;&#238; &#239;&#240;&#232;&#237;&#255;&#242;&#251;&#245; &#225;&#224;&#233;&#242; &#239;&#240;&#232; &#247;&#242;&#229;&#237;&#232;&#232; &#239;&#238;&#240;&#242;&#224;*)
    		byte_read:=SysComRead(port_number, ADR(buf_otvet), 8, 0);
    		(*&#197;&#241;&#235;&#232; &#236;&#251; &#239;&#238;&#235;&#243;&#247;&#232;&#235;&#232; &#238;&#242;&#226;&#229;&#242; &#238;&#242; &#243;&#241;&#242;&#240;&#238;&#233;&#241;&#242;&#226;&#224;, &#242;&#238; &#239;&#240;&#232;&#237;&#255;&#242;&#243;&#254; &#232;&#237;&#244;&#238;&#240;&#236;&#224;&#246;&#232;&#254; &#241;&#238;&#225;&#232;&#240;&#224;&#229;&#236; &#226; &#225;&#238;&#235;&#229;&#229; &#225;&#238;&#235;&#252;&#248;&#238;&#233; &#225;&#243;&#244;&#229;&#240; &#238;&#242;&#226;&#229;&#242;&#224;
    		&#242;&#238; &#229;&#241;&#242;&#252; &#241;&#238;&#225;&#232;&#240;&#224;&#229;&#236; &#238;&#242;&#226;&#229;&#242; &#226; &#243;&#228;&#238;&#225;&#237;&#251;&#233; &#228;&#235;&#255; &#238;&#225;&#240;&#224;&#225;&#238;&#242;&#234;&#232; &#244;&#238;&#240;&#236;&#224;&#242;*)
    		IF byte_read>0 THEN
    			FOR i:=0 TO byte_read-1 DO
    				otvet[l+i]:=buf_otvet[i];
    			END_FOR
    			l:=l+byte_read;
    
    			(*&#194; &#228;&#224;&#237;&#237;&#238;&#236; &#236;&#229;&#241;&#242;&#229; &#239;&#240;&#238;&#227;&#240;&#224;&#236;&#236;&#251; &#237;&#229;&#238;&#225;&#245;&#238;&#228;&#232;&#236;&#238; &#240;&#229;&#224;&#235;&#232;&#231;&#238;&#226;&#224;&#242;&#252; &#238;&#225;&#240;&#224;&#225;&#238;&#242;&#234;&#243; &#239;&#240;&#232;&#237;&#255;&#242;&#238;&#233; &#232;&#231; &#239;&#238;&#240;&#242;&#224; &#232;&#237;&#244;&#238;&#240;&#236;&#224;&#246;&#232;&#232;*)
    			(*&#196;&#224;&#225;&#251; &#241;&#232;&#235;&#252;&#237;&#238; &#237;&#229; &#239;&#229;&#240;&#229;&#227;&#240;&#243;&#230;&#224;&#242;&#252; &#239;&#240;&#232;&#236;&#229;&#240; &#232;&#237;&#244;&#238;&#240;&#236;&#224;&#246;&#232;&#232; &#237;&#232;&#230;&#229; &#232;&#241;&#239;&#238;&#235;&#252;&#231;&#243;&#229;&#242;&#241;&#255; &#239;&#238;&#228;&#238;&#225;&#232;&#229; &#231;&#224;&#227;&#235;&#243;&#248;&#234;&#232;*)
    			(*&#200;&#231;&#226;&#229;&#241;&#242;&#237;&#238; &#247;&#242;&#238; &#228;&#235;&#232;&#237;&#224; &#238;&#242;&#226;&#229;&#242;&#224; &#237;&#224; &#232;&#241;&#239;&#238;&#235;&#252;&#231;&#243;&#229;&#236;&#251;&#229; &#226; &#239;&#240;&#238;&#227;&#240;&#224;&#236;&#236;&#229; &#231;&#224;&#239;&#240;&#238;&#241;&#251; &#241;&#242;&#238;&#240;&#238;&#227;&#238; 8 &#225;&#224;&#233;&#242;*)
    			(*&#207;&#238;&#253;&#242;&#238;&#236;&#243; &#237;&#232;&#230;&#229; &#239;&#240;&#238;&#232;&#231;&#226;&#238;&#228;&#232;&#242;&#241;&#255; &#224;&#237;&#224;&#235;&#232;&#231; &#240;&#224;&#231;&#236;&#229;&#240;&#224; &#239;&#240;&#232;&#237;&#255;&#242;&#238;&#227;&#238; &#238;&#242;&#226;&#229;&#242;&#224;*)
    			(*&#202;&#224;&#234; &#242;&#238;&#235;&#252;&#234;&#238; &#239;&#240;&#232;&#245;&#238;&#228;&#232;&#242; &#231;&#224; &#238;&#242;&#226;&#229;&#228;&#229;&#237;&#237;&#251;&#233; &#232;&#237;&#242;&#229;&#240;&#226;&#224;&#235; &#226;&#240;&#229;&#236;&#229;&#237;&#232; &#237;&#243;&#230;&#237;&#238;&#229; &#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#238; &#225;&#224;&#233;&#242;, &#237;&#224;&#247;&#232;&#237;&#224;&#229;&#236; &#238;&#225;&#240;&#224;&#225;&#238;&#242;&#234;&#243; &#239;&#240;&#232;&#237;&#255;&#242;&#238;&#233; &#234;&#238;&#236;&#224;&#237;&#228;&#251;*)
    			IF ( l=7) THEN
    				(*&#207;&#238;&#235;&#243;&#247;&#232;&#235;&#232; &#237;&#243;&#230;&#237;&#238;&#229; &#234;&#238;&#235;&#232;&#247;&#229;&#241;&#242;&#226;&#238; &#225;&#224;&#233;&#242;*)
    				(*&#207;&#240;&#238;&#232;&#231;&#226;&#238;&#228;&#232;&#236; &#240;&#224;&#241;&#239;&#224;&#234;&#238;&#226;&#234;&#243; &#238;&#242;&#226;&#229;&#242;&#224; &#232; &#231;&#224;&#239;&#232;&#241;&#251;&#226;&#224;&#229;&#236; &#229;&#227;&#238; &#237;&#224; &#226;&#251;&#245;&#238;&#228; &#225;&#235;&#238;&#234;&#224;*)
    				p1:=ADR(otvet[4]);
    				p:=ADR(rez);
    				p^:=p1^;
    				p1:=ADR(otvet[3]);
    				p:=p+1;
    				p^:=p1^;
    				(*&#206;&#241;&#242;&#224;&#237;&#224;&#226;&#235;&#232;&#226;&#224;&#229;&#236; &#242;&#224;&#233;&#236;&#229;&#240; &#238;&#230;&#232;&#228;&#224;&#237;&#232;&#255; &#238;&#242;&#226;&#229;&#242;&#224;*)
    				T1(IN:=FALSE, PT:=T#0s );
    				(*&#206;&#248;&#232;&#225;&#238;&#234; &#237;&#229;&#242;*)
    				errors:=0;
    				(*&#199;&#237;&#224;&#247;&#232;&#237;&#232;&#255; &#237;&#224; &#226;&#251;&#245;&#238;&#228;&#229; &#225;&#235;&#238;&#234;&#224; &#241;&#244;&#238;&#240;&#236;&#232;&#240;&#238;&#226;&#224;&#237;&#251;, &#232;&#245; &#236;&#238;&#230;&#237;&#238; &#232;&#241;&#239;&#238;&#235;&#252;&#231;&#238;&#226;&#224;&#242;&#252; &#226; &#239;&#240;&#238;&#227;&#240;&#224;&#236;&#236;&#229;*)
    				ready:=TRUE;
    				(*&#207;&#229;&#240;&#229;&#226;&#238;&#228;&#232;&#236; &#225;&#235;&#238;&#234; &#226; &#240;&#229;&#230;&#232;&#236; &#238;&#242;&#239;&#240;&#224;&#226;&#234;&#232; &#231;&#224;&#239;&#240;&#238;&#241;&#224;*)
    				status:=1;
    			END_IF
    		END_IF

    Нельзя ли и с помощью функции из библиотеки UNM так же по байту читать буфер в цикле целиком? И, кстати, какова длина входного буфера у ПЛК110?

  2. #2
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,224

    По умолчанию

    а Вы для разнообразия засеките время от момента начала слушанья порта до приема нужных данных через SysLibCom, возможно усредненно так же выйдет байт в цикл, все зависит конечно от времени устанавливаемого мин.цикла
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  3. #3

    По умолчанию

    У меня нет пока железа, так что померить не могу.
    Мне нужно читать положение по энкодеру, подключенному к RS485, расчетно весь цикл его опроса должен занимать около 3 мс, а в ответе может быть до 7 байт, так что читать ответ побайтно при каждом вызове программы, мягко говоря, нерационально.
    Последний раз редактировалось baritone; 19.12.2014 в 15:06.

  4. #4
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,224

    По умолчанию

    контроллеры любого бренда для работы с энкодерами используют аппаратные "быстрые" входа, ни кто по последовательному порту не ловит сигналы энкодера, если это отдельный модуль, то в любом случае Вы будете считывать уже результируещее значение
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  5. #5
    Пользователь
    Регистрация
    11.01.2009
    Адрес
    Кострома
    Сообщений
    3,144

    По умолчанию

    там похоже речь про энкодер с интерфейсом.
    модель напишите и что с ним хотите делать.

  6. #6

    По умолчанию

    Прошу прощения, не заметил ответа.
    Мне надо считывать положение по относительному энкодеру с TTL-выходом для позиционирования поршней и заливных трубок машины по разливке продукта. Варианта рассматриваются два:
    - использовать встроенные энкодеры ПЛК110 (новый) с модулем согласования уровня сигнала (например, ЛИР-901);
    - использовать модули СКБ ИС ЛИР-915, передающий данные по RS485. Последний вариант приходится рассматривать, потому что нет гарантии, что частота сигнала от энкодера не будет превышать 100 кГц.

    Если использовать модуль ЛИР-915, то я могу гонять трубки и поршня на высокой скорости, а перед остановкой снижать скорость в разы, чтобы получить требуемую точность, несмотря на задержку с ответом. Я собираюсь организовать запрос данных с модуля ЛИР-915, ожидание, получение ответа, да еще и задание скорости с помощью отдельной короткой программы, вызываемой с периодом в 1 мс. Если я смогу считывать ответ с модуля сопряжения с энкодером в течение одного цикла работы программы, то полный цикл управления позиционированием (опрос-считывание энкодера-задание скорости) не превысит 8-10 вызовов для 2-х осей, что, с учетом замедления, вполне приемлемо. Если не смогу, а придется читать по одному байту ответа за каждый вызов - это удлинит цикл управления позиционированием в три раза, и система уже не будет поспевать. Сначала я стал писать программу с использованием библиотеки UNM, а когда стал смотреть, как организовано считывание данных из порта, немного испугался.

  7. #7
    Пользователь
    Регистрация
    13.10.2011
    Адрес
    Златоуст
    Сообщений
    1,021

    По умолчанию

    Столкнулся с ЛИР-915. Вот код чтения относительной координаты:
    Код:
    VAR    step, _step, count: DINT;
        timeout: TON := (PT := T#300ms);
    	request: ARRAY [0..1] OF BYTE := 51, 1;
    	rsp: ARRAY [0..5] OF BYTE;
    	pos: DINT;
    	rpt: BOOL;
    END_VAR
    VAR CONSTANT
        port: COMSETTINGS := (Port := COM1, dwBaudRate := 115200, dwBufferSize := 1);
    END_VAR
    
    REPEAT
    	rpt := FALSE;
    
    
    	CASE step OF
    
    
    	    0:
    	        IF SysComOpen(port.Port) = 0 = SysComSetSettings(port.Port, ADR(port)) THEN
    	            step := step + 1;
    	        END_IF
    		1:
    			step := step + 1;
    
    
    		2:
    			count := count + SysComWrite(port.Port, ADR(request) + count, SIZEOF(request) - count, 0);
    			IF count >= 2 THEN
    				step := step + 1;
    				rpt := TRUE;
    			END_IF
    
    
    		3:
    			count := count + SysComRead(port.Port, ADR(rsp) + count, SIZEOF(rsp) - count, 0);
    			IF count >= 6 THEN
    				IF rsp[0] = 10 AND rsp[5] = 11 THEN
    
    
    					pos :=
    						SHR(rsp[4], 4) * 10000000 + (rsp[4] AND 15) * 1000000 +
    						SHR(rsp[3], 4) * 100000 + (rsp[3] AND 15) * 10000 +
    						SHR(rsp[2], 4) * 1000 + (rsp[2] AND 15) * 100 +
    						SHR(rsp[1], 4) * 10 + (rsp[1] AND 15);
    
    
    
    
    					IF SHR(rsp[4], 4) = 9 THEN
    						pos := pos - 100000000;
    
    
    					END_IF
    
    
    					step := 2;
    					rpt := TRUE;
    				END_IF
    			END_IF
    
    
    	END_CASE
    
    
    	timeout(IN := step = _step);
    	IF timeout.Q THEN
    		(* Discard input to resync *)
    		SysComRead(port.Port, ADR(rsp), SIZEOF(rsp), 0);
    		step := 1;
    	END_IF
    
    
    	IF step <> _step THEN
    		count := 0;
    		_step := step;
    	END_IF
    
    
    UNTIL NOT rpt END_REPEAT
    И вот картина по времени (ПЛК160, RS232, 115200, ЛИР в «двоично-десятичном» режиме); D0 — запросы:

    lir915_loaded.png

    Любопытно, что ЛИР отвечает гораздо быстрее, если датчик стоит примерно на нуле:

    lir915_idle.png

Похожие темы

  1. UNM
    от Fudz в разделе ПЛК1хх
    Ответов: 7
    Последнее сообщение: 28.09.2012, 22:27
  2. Библиотека UNM
    от Сергей71 в разделе ПЛК1хх
    Ответов: 10
    Последнее сообщение: 19.01.2012, 18:15
  3. Вопрос по применению библиотеки UNM
    от nestor в разделе Эксплуатация
    Ответов: 9
    Последнее сообщение: 24.10.2011, 10:26
  4. Вопрос по использованию библиотеки UNM
    от SergeyNG в разделе ПЛК1хх
    Ответов: 3
    Последнее сообщение: 21.03.2007, 10:49
  5. ПЛК и UNM
    от Dio в разделе ПЛК1хх
    Ответов: 2
    Последнее сообщение: 19.01.2007, 13:02

Ваши права

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