Страница 53 из 85 ПерваяПервая ... 343515253545563 ... ПоследняяПоследняя
Показано с 521 по 530 из 931

Тема: Панели оператора СП270. Вопросы и ответы

Комбинированный просмотр

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1

    По умолчанию

    Насколько я понимаю, соответствие RS-485 будет обеспечено терминалом при передаче (если порт правильно настроен), а соответствие стандарту Modbus и правильность ответа проверяет уже скрипт.
    Вот новая функция, проверить по-прежнему нет возможности
    Код:
    const BYTES_PER_REG = 2;
    const N_RETRIES = 3;
    const RETRY_TIMEOUT = 1000; //ms
    BOOL MWrites(int comID, int staID, int objType, int add1, int regs, void* pRegs) {
    	BYTE bSend[256], bRecieve[256], i;
    	WORD bBytesToSend = 0, bBytesRecieved = 65535;
    	BYTE nRetry = N_RETRIES; //Количество попыток повтора
    	BYTE offset_PSW_log;
    	int CrcSum;
    	
    	switch (comID) {
    	case DOWNLOAD:
    		offset_PSW_log = 60;
    		break;
    	case PLC:
    		offset_PSW_log = 70;
    		break;
    	default:
    		return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do
    	}
    	
    	bSend[0] = staID;
    	switch (objType) {
    	case MODBUS_RTU_REGS_4X:
    		bSend[1] = 0x10;
    		break;
    	default:
    		return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do
    	}
    	bSend[2] = HIBYTE(add1);
    	bSend[3] = LOBYTE(add1);
    	bSend[4] = HIBYTE(regs);
    	bSend[5] = LOBYTE(regs);
    	bSend[6] = regs * BYTES_PER_REG;
    	bBytesToSend = 7;
    	
    	for (i=0; i<regs*2; i++) {
    		bSend[bBytesToSend] = ((BYTE*)pRegs)[i];
    		bBytesToSend++;
    	}
    	
    	CrcSum = Crc(bSend, bBytesToSend);
    	bSend[bBytesToSend] = LOBYTE(CrcSum);
    	bSend[bBytesToSend + 1] = HIBYTE(CrcSum);
    	bBytesToSend += 2;
    	
    	if (bBytesToSend > 256)
    		return FALSE;
    	
    	Enter(comID);//Захватить порт PLC
    	do {
    		if (bBytesRecieved != 65535) { //Была ошибка связи
    			PSW[offset_PSW_log+1]++;
    			if (bBytesRecieved != 0) // Ошибка данных
    				PSW[offset_PSW_log+3]++;
    			//else //Таймаут
    			//	PSW[offset_PSW_log+2]++;
    		}
    		
    		Send(comID, bSend, bBytesToSend);//Отправить команду
    		bBytesRecieved = Receive(comID, bRecieve, 256, RETRY_TIMEOUT, 6);//Получить ответ (тайм-аут 1000мс)
    	} while ((bBytesRecieved == 0 || //Если данные получены
    		bRecieve[0] != staID || //От правильного устройства
    		bRecieve[1] != bSend[1] || //Правильной функцией
    		MAKEWORD(bRecieve[3], bRecieve[2]) != add1 || // По правильному адресу
    		MAKEWORD(bRecieve[5], bRecieve[4]) != regs || // Правильное количество регистров
    		Crc(bRecieve, bBytesRecieved) != 0 //Контрольная сумма в порядке 
    	) && (nRetry--)>0); //... то всё ок, иначе отнимаем попытку и, если они остались, пытаемся ещё
    	Leave(comID);//Освободить порт
    	
    	if (nRetry>0) { //Если попытки остались, значит, последняя попытка связи была успешной
    		PSW[offset_PSW_log]++;
    		return TRUE;
    	} else
    		return FALSE;
    }
    Последний раз редактировалось SokolovS; 03.11.2014 в 11:40.

  2. #2

    По умолчанию

    Цитата Сообщение от SokolovS Посмотреть сообщение
    Насколько я понимаю, соответствие RS-485 будет обеспечено терминалом при передаче (если порт правильно настроен), а соответствие стандарту Modbus и правильность ответа проверяет уже скрипт.
    Вот новая функция, проверить по-прежнему нет возможности
    Код:
    Код:
    const BYTES_PER_REG = 2;
    const N_RETRIES = 3;
    const RETRY_TIMEOUT = 1000; //ms
    BOOL MWrites(int comID, int staID, int objType, int add1, int regs, void* pRegs) {
    	BYTE bSend[256], bRecieve[256], i;
    	WORD bBytesToSend = 0, bBytesRecieved = 65535;
    	BYTE nRetry = N_RETRIES; //Количество попыток повтора
    	BYTE offset_PSW_log;
    	int CrcSum;
    	
    	switch (comID) {
    	case DOWNLOAD:
    		offset_PSW_log = 60;
    		break;
    	case PLC:
    		offset_PSW_log = 70;
    		break;
    	default:
    		return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do
    	}
    	
    	bSend[0] = staID;
    	switch (objType) {
    	case MODBUS_RTU_REGS_4X:
    		bSend[1] = 0x10;
    		break;
    	default:
    		return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do
    	}
    	bSend[2] = HIBYTE(add1);
    	bSend[3] = LOBYTE(add1);
    	bSend[4] = HIBYTE(regs);
    	bSend[5] = LOBYTE(regs);
    	bSend[6] = regs * BYTES_PER_REG;
    	bBytesToSend = 7;
    	
    	for (i=0; i<regs*2; i++) {
    		bSend[bBytesToSend] = ((BYTE*)pRegs)[i];
    		bBytesToSend++;
    	}
    	
    	CrcSum = Crc(bSend, bBytesToSend);
    	bSend[bBytesToSend] = LOBYTE(CrcSum);
    	bSend[bBytesToSend + 1] = HIBYTE(CrcSum);
    	bBytesToSend += 2;
    	
    	if (bBytesToSend > 256)
    		return FALSE;
    	
    	Enter(comID);//Захватить порт PLC
    	do {
    		if (bBytesRecieved != 65535) { //Была ошибка связи
    			PSW[offset_PSW_log+1]++;
    			if (bBytesRecieved != 0) // Ошибка данных
    				PSW[offset_PSW_log+3]++;
    			//else //Таймаут
    			//	PSW[offset_PSW_log+2]++;
    		}
    		
    		Send(comID, bSend, bBytesToSend);//Отправить команду
    		bBytesRecieved = Receive(comID, bRecieve, 256, RETRY_TIMEOUT, 6);//Получить ответ (тайм-аут 1000мс)
    	} while ((bBytesRecieved == 0 || //Если данные получены
    		bRecieve[0] != staID || //От правильного устройства
    		bRecieve[1] != bSend[1] || //Правильной функцией
    		MAKEWORD(bRecieve[3], bRecieve[2]) != add1 || // По правильному адресу
    		MAKEWORD(bRecieve[5], bRecieve[4]) != regs || // Правильное количество регистров
    		Crc(bRecieve, bBytesRecieved) != 0 //Контрольная сумма в порядке 
    	) && (nRetry--)>0); //... то всё ок, иначе отнимаем попытку и, если они остались, пытаемся ещё
    	Leave(comID);//Освободить порт
    	
    	if (nRetry>0) { //Если попытки остались, значит, последняя попытка связи была успешной
    		PSW[offset_PSW_log]++;
    		return TRUE;
    	} else
    		return FALSE;
    }
    Добрался потестить. Отправляет запрос с неправильным порядком байт
    Исправил, вот эта штука работоспособна (полный цикл тестирования не проводился):
    Код:
    const BYTES_PER_REG = 2;
    const N_RETRIES = 3;
    const RETRY_TIMEOUT = 1000; //ms
    BOOL MWrites(int comID, int staID, int objType, int add1, int regs, void* pRegs) {
    	BYTE bSend[256], bRecieve[256], i;
    	WORD bBytesToSend = 0, bBytesRecieved = 65535;
    	BYTE nRetry = N_RETRIES; //Количество попыток повтора
    	BYTE offset_PSW_log;
    	int CrcSum;
    	
    	switch (comID) {
    	case DOWNLOAD:
    		offset_PSW_log = 60;
    		break;
    	case PLC:
    		offset_PSW_log = 70;
    		break;
    	default:
    		return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do
    	}
    	
    	bSend[0] = staID;
    	switch (objType) {
    	case MODBUS_RTU_REGS_4X:
    		bSend[1] = 0x10;
    		break;
    	default:
    		return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do
    	}
    	bSend[2] = HIBYTE(add1);
    	bSend[3] = LOBYTE(add1);
    	bSend[4] = HIBYTE(regs);
    	bSend[5] = LOBYTE(regs);
    	bSend[6] = regs * BYTES_PER_REG;
    	bBytesToSend = 7;
    	
    	for (i=0; i<regs; i++) {
    		bSend[bBytesToSend] = HIBYTE(((WORD*)pRegs)[i]);
    		bBytesToSend++;
    		bSend[bBytesToSend] = LOBYTE(((WORD*)pRegs)[i]);
    		bBytesToSend++;
    	}
    	
    	CrcSum = Crc(bSend, bBytesToSend);
    	bSend[bBytesToSend] = HIBYTE(CrcSum);
    	bSend[bBytesToSend + 1] = LOBYTE(CrcSum);
    	bBytesToSend += 2;
    	
    	if (bBytesToSend > 256)
    		return FALSE;
    	
    	Enter(comID);//Захватить порт PLC
    	do {
    		if (bBytesRecieved != 65535) { //Была ошибка связи
    			PSW[offset_PSW_log+1]++;
    			if (bBytesRecieved != 0) // Ошибка данных
    				PSW[offset_PSW_log+2]++;
    			//else //Таймаут
    			//	PSW[offset_PSW_log+3]++;
    		}
    		
    		Send(comID, bSend, bBytesToSend);//Отправить команду
    		bBytesRecieved = Receive(comID, bRecieve, 256, RETRY_TIMEOUT, 6);//Получить ответ (тайм-аут 1000мс)
    	} while ((bBytesRecieved == 0 || //Если данные получены
    		bRecieve[0] != staID || //От правильного устройства
    		bRecieve[1] != bSend[1] || //Правильной функцией
    		MAKEWORD(bRecieve[3], bRecieve[2]) != add1 || // По правильному адресу
    		MAKEWORD(bRecieve[5], bRecieve[4]) != regs || // Правильное количество регистров
    		Crc(bRecieve, bBytesRecieved) != 0 //Контрольная сумма в порядке 
    	) && (--nRetry)>0); //... то всё ок, иначе отнимаем попытку и, если они остались, пытаемся ещё
    	Leave(comID);//Освободить порт
    	
    	if (nRetry>0) { //Если попытки остались, значит, последняя попытка связи была успешной
    		PSW[offset_PSW_log]++;
    		return TRUE;
    	} else
    		return FALSE;
    }
    Последний раз редактировалось SokolovS; 13.04.2015 в 12:11. Причина: порядок байт контрольной суммы тоже поправил и ещё одну ошибочку тоже

  3. #3

    По умолчанию

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

  4. #4
    Пользователь Аватар для petera
    Регистрация
    06.05.2011
    Адрес
    Минск
    Сообщений
    3,851

    По умолчанию

    Цитата Сообщение от SokolovS Посмотреть сообщение
    Увеличить таймаут до десяти секунд, подключить вместо нормального устройства просто терминал и любой ответ заслать
    Любой ответ нельзя.
    Захват-1.png

    ЗЫ. Во вложении описание протокола
    Вложения Вложения
    Последний раз редактировалось petera; 28.10.2014 в 15:04.
    Мой канал на ютубе
    https://www.youtube.com/c/ПетрАртюков
    Библиотека ГМ для СП300
    https://disk.yandex.com/d/gHLMhLi8x1_HBg

  5. #5
    Пользователь Аватар для petera
    Регистрация
    06.05.2011
    Адрес
    Минск
    Сообщений
    3,851
    Последний раз редактировалось petera; 28.10.2014 в 15:11.
    Мой канал на ютубе
    https://www.youtube.com/c/ПетрАртюков
    Библиотека ГМ для СП300
    https://disk.yandex.com/d/gHLMhLi8x1_HBg

  6. #6
    Пользователь Аватар для petera
    Регистрация
    06.05.2011
    Адрес
    Минск
    Сообщений
    3,851

    По умолчанию

    Скрипт не проверяет ситуацию ошибок второго типа, например если мастер пытается записать регистр в слейв по несуществующему адресу регистра, то в ответ будет послан пакет из 5 байт, а не из 8.
    //[0]-адрес устройства
    //[1]-Код функции ModbusRTU с индикацией ошибки-запись нескольких регистров 0x90
    //[2]-код ошибки (0x02)
    //[3]-ст.байт CRC
    //[4]-мл.байт CRC
    см пост#620

    ЗЫ. Стандартые процедуры обмена при ошибках записывают в регистре PSW61(PSW71) число не успешных попыток обмена без учета повторных попыток, а в PSW62(PSW72) и PSW64(PSW73) с учетом повторных попыток, т.е. если число повторов задано 3, то при тайм-ауте PSW61(PSW71)=N, а PSW62(PSW72)=3хN, где N-число команд записи
    Последний раз редактировалось petera; 28.10.2014 в 16:01.
    Мой канал на ютубе
    https://www.youtube.com/c/ПетрАртюков
    Библиотека ГМ для СП300
    https://disk.yandex.com/d/gHLMhLi8x1_HBg

  7. #7

    По умолчанию

    А теперь?
    Код:
    		bRecieve[1] != bSend[1] || //Правильной функцией
    По задумке эта строка проверяет чего там вернуло устройство, и в случае возвращённой ошибки там будет не 0х10, а 0х90. Скрипт ещё несколько раз помучает устройство и отстанет, записав всё в ошибки. По задумке.

  8. #8
    Пользователь Аватар для petera
    Регистрация
    06.05.2011
    Адрес
    Минск
    Сообщений
    3,851

    По умолчанию

    Если нам не важна причина ошибок, тот же неверный адрес регистра, для дальнейшего принятия решений, то тогда можно ограничится и просто констатацией ошибки.
    Мой канал на ютубе
    https://www.youtube.com/c/ПетрАртюков
    Библиотека ГМ для СП300
    https://disk.yandex.com/d/gHLMhLi8x1_HBg

  9. #9

    По умолчанию

    Я не вижу других вариантов
    Штатные функции не поддерживают такого и смысла расширять возможности нет

  10. #10
    Пользователь Аватар для petera
    Регистрация
    06.05.2011
    Адрес
    Минск
    Сообщений
    3,851

    По умолчанию

    Самое интересное, что похоже без наших усилий в регистры PSW62(PSW72) панель и так сама пишет даже для команд Send() и Receive()
    Регистры
    PSW63(PSW73) проверяю.

    ЗЫ
    PSW60(PSW70) (Успешные попытки) автоматически не обновляются
    Мой канал на ютубе
    https://www.youtube.com/c/ПетрАртюков
    Библиотека ГМ для СП300
    https://disk.yandex.com/d/gHLMhLi8x1_HBg

Страница 53 из 85 ПерваяПервая ... 343515253545563 ... ПоследняяПоследняя

Похожие темы

  1. Панели оператора СП3xx. Вопросы и ответы
    от Мурат Ахриев в разделе Панели оператора (HMI)
    Ответов: 3302
    Последнее сообщение: Вчера, 14:06
  2. Индикатор ИП120 , вопросы- ответы
    от rovki в разделе Программируемые реле
    Ответов: 56
    Последнее сообщение: 03.11.2017, 15:58
  3. СПК 110 в качестве Панели оператора
    от GSM73 в разделе СПК1хх
    Ответов: 3
    Последнее сообщение: 14.03.2017, 00:42
  4. СПК 107 в качестве панели оператора
    от Леонид в разделе СПК1хх
    Ответов: 15
    Последнее сообщение: 20.11.2015, 08:17
  5. Ответов: 4
    Последнее сообщение: 27.10.2012, 23:12

Метки этой темы

Ваши права

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