Рейтинг:
17
0x01AA
После всех обсуждений я бы попробовал что-то вроде приведенного ниже в разделе кода вашего приемника, чтобы ускорить связь.
Я надеюсь, что это поможет и что я не сделал слишком много ошибок.
// The following expects that serialPort.ReadTimeout is setup
// for "message timeout" which is usually much bigger than character
// timeout after the first byte has been received
//
var tmp = new byte[0x2000];
int dataLength = 0;
try
{
while(true)
{
byte receiveByte= (byte)serialPort.ReadByte();
// We received one byte. Check buffer size
if (dataLength >= tmp.Length)
{
// Buffer to small
result.ErrorCode = 1; // Appropriate ErrorCode
result.ErrorText = "Buffer Overrun";
return result;
}
// Add it to receive buffer
tmp[dataLength++] = receiveByte;
// Set character Timeout after we received the first byte of the answer
if (dataLength == 1)
{
// Set new character timeout according to Modbus spec.
// At least 3.5 characters silence but here we take about
// 5 times more chars to be on the safe side
//
// 10Bit/Byte mS ca. 5x3.5
serialPort.ReadTimeout= (10 * 1000 * 18) / serialPort.Baudrate;
}
// Don't eat CPU too aggressive (has to be proofed whether it really helps)
Thread.Sleep(0);
}
}
catch (TimeoutException ex)
{
// Expected exception. No more character received in the specified
// character timeout period
}
catch (Exception ex)
{
// Other than (TimeoutException is an error condition
result.ErrorCode = 1; // Appropriate ErrorCode
result.ErrorText = ex.Message;
return result;
}
Demuter
Хороший день. Я хотел бы поблагодарить вас за вашу помощь с моей прошлой проблемой, если есть возможность, не могли бы вы взглянуть еще на один из моих вопросов. Он говорит на подобную тему ... Я не могу понять, в чем проблема ...
Рейтинг:
1
OriginalGriff
Начните с того, чтобы выяснить, где он проводит свое время: поперчите его Секундомер Класса (Система.Диагностика) | Microsoft Docs[^] экземпляры и протоколировать различные части операции в файл в конце. Затем сосредоточьтесь на самой длинной части и добавьте больше секундомеров, чтобы попытаться сузить область, где он тратит свое время.
Когда у вас есть это, вы можете начать смотреть на ускорение, но пока у вас нет реальных цифр, это все догадки. Когда вы знаете, вы можете сосредоточиться на "почему это медленно?" - но не до тех пор, пока у вас нет данных и ссылки, чтобы проверить свои улучшения.
Demuter
Этот код работает дольше всего. Я попытался уменьшить размер буфера, но время не изменилось ...
var tmp = new byte[0x2000];
//var tmp = new byte[0x11];
int dataLength = 0;
try
{
for (int i = 0; i < tmp.Length; i++)
tmp[dataLength++] = (byte)serialPort.ReadByte();
}
catch (Exception ex)
{
}
0x01AA
В чем ценность для это соответственно, последовательный порт.ReadTimeout?
Кроме того, я бы предложил регистрировать время для первого полученного байта. Это покажет вам, как долго другая часть должна отвечать на ваш запрос.
OriginalGriff
разумный Совет. :большой палец вверх:
0x01AA
Спасибо :счастливо:
Demuter
Значение для serialPort.ReadTimeout = 1000.
Я сделал вывод, как вы и предлагали - первый ответ за 0,033 секунды.
0x01AA
Итак, я бы сказал, что вы тратите/теряете 1000 мс, пока не остановите свой цикл ;)
Что я помню из Modbus, так это то, что конец передачи-это когда нет символа, полученного для "по крайней мере 3½ символьных времен молчания"
Demuter
Может быть, это поможет, при настройке модема, с помощью которого я пингую устройство, у меня есть: тайм-аут бездействия=30 секунд...
0x01AA
Но я говорю от serialPort.ReadTimeout
Установите его, например, на 10, это означает тайм-аут 10 мс (около 20 символов молчат при 19'200), после чего ваш цикл останавливается.
[Edit] забыл упомянуть, что эти 10 мс должны быть установлены после получения первого символа.
Кстати. Я бы поймал TimeoutException
явно потому, что это ожидаемое исключение. Все остальные исключения должны обрабатываться особым образом, поскольку они являются условием ошибки.
Demuter
Это работает! Большое спасибо.
Но не могли бы вы сказать мне, как обойти новую ошибку?.. =))
Теперь, когда я читаю несколько регистров в цикле, вероятно, у программы нет времени, чтобы получить ответ, и данные не поступают.
Возможно ли решить только увеличение времени? Или есть еще варианты?
Еще раз спасибо!
Я не видел вашего кода. Сейчас я попробую, а потом напишу, как идут дела.
0x01AA
:большой палец вверх:
Мы всегда рады вам. С нетерпением жду результатов вашего теста.
Demuter
Ваш код работает, но первый улов(TimeoutException ex) иногда выдает ошибку: время ожидания операции истекло.
И тогда возникает проблема, как в моем комментарии выше ...
0x01AA
Убедитесь, что в начале ReadTimeout большой, что-то вроде 1000 мс, как вы делали это раньше.
OriginalGriff
Так... это другой конец.
Ваш код сидит там, ожидая поступления данных - вы не можете ускорить это, это в значительной степени полностью зависит от устройства на другом конце связи.
Подумайте об этом: предполагая, что вы общаетесь по каналу связи 9600 бод, это в лучшем случае ~1000 символов в секунду, поэтому ваши 17 символов займут менее двух сотен секунд, чтобы быть физически принятыми и переданными в ваше приложение. Если этот код принимает лучшую часть в 100 раз больше, то задержка происходит с поставщиком данных, а не с получателем.
Вы не можете кодировать вокруг этого!
Garth J Lancaster
Я повторяю вывод OriginalGriff - я много работал с Modbus, и последнее конкретное устройство (например) было небольшой микропроцессорной платой, работающей по протоколу Modbus, но контролирующей множество датчиков-у него могли быть моменты, когда он просто не мог ответить на запрос показаний регистра
Demuter
Я бы не беспокоился, если бы не было нормальной скорости на tcp. Скорость отклика по tcp составляет около 0,15 сек. Поэтому я думаю, что это где-то проблема в моем коде...
Может быть, где-то еще в коде ...