|
|
  |
Протокол modbus. Вопросы по интерфейсу |
|
|
|
Nov 5 2009, 15:50
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(MrYuran @ Nov 5 2009, 09:17)  По ГПРС пинги по полторы секунды - не редкость. Угу. Цитата А Modbus-TCP для кого придумали? По моему скромному, самое оно для таких сетей Вот это Вы Автору, который хочет знать только RTU и видит в нем только байты, и не видит никаких проблем объясните.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Nov 6 2009, 11:21
|

Участник

Группа: Свой
Сообщений: 72
Регистрация: 10-02-05
Из: Краснодар
Пользователь №: 2 558

|
Цитата(zltigo @ Nov 4 2009, 22:17)  Ну а время, время между этими самыми байтами, как с ним дела обстоят? Огласите. Т.е. Mobus ASCII тут будет гораздо лучше ? Именно в отношении RTU vs ASCII выше было обсуждение. К тому же D&M вообще CSD пока обсуждает имхо. Цитата(MrYuran @ Nov 5 2009, 09:17)  По ГПРС пинги по полторы секунды - не редкость. и более...
|
|
|
|
|
Nov 6 2009, 12:41
|
Группа: Участник
Сообщений: 13
Регистрация: 24-10-09
Пользователь №: 53 179

|
У счетчика Modbus-RTU, а в модеме только CSD..
|
|
|
|
|
Nov 6 2009, 13:10
|

Участник

Группа: Свой
Сообщений: 72
Регистрация: 10-02-05
Из: Краснодар
Пользователь №: 2 558

|
Цитата(D&M @ Nov 6 2009, 15:41)  У счетчика Modbus-RTU, а в модеме только CSD.. Вы сначала определитесь со всей структурой системы, а затем переходите к решению отдельных пунктов. Например: 1. Что на верхнем уровне (компьютер) - какая-то готовая программа, нечто самописное, нечто на основе SCADA/OPC... Отсюда уже станет ясно, сможет ли эта программа сама всех обзванивать или иметь дополнительный функционал, и нужны ли будут нижеследующие промежуточные звенья: 2. Контроллер опроса верхнего уровня - "железка", которая сама будет обзванивать, опрашивать счетчики и преобразовывать данные в понятный формат для (п.1) программе, естественно и поддерживать обмен по протоколу который эта программа (п.1) поддерживает. 2а. модем. 3а. модем. 3. Контроллер опроса нижнего уровня - "железка" которая будет производить дополнительную обработку собранных данных до передачи в канал связи. 4. Ваши счетчик(и) В зависимости от конкретных условий - фунционала ПО п.1, канала связи и т.д., п.2 и п.3 могут отсутствовать.
|
|
|
|
|
Nov 8 2009, 00:09
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(koyodza @ Oct 18 2009, 19:51)  Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это. Стандарты порой устаревают. А сильно распространненные нарушения часто становятся частью страндарта. Грубых нарушений стандарта в упор не вижу, если CRC сошлась ложно, то пакет отбракуется по длине и прием продолжится. С другой стороны, на кой в холостую ждать 3.5 символьных интервала (это ж вагон и еще маленькая тележка времени особенно на 9600 и ниже), когда их можно потратить с пользой, например на вычитку архива из медленного eeprom'а по текущему запросу мастера. Цитата Сообщения ведь попадают в "Копилку Вечности", вдруг кто-то из начинающих когда-то забредёт сюда (даже в правилах написано - новую тему создавать после того, как ничего не нашел поиском), и подумает что так и нужно делать... Может для "Копилки Вечности" у вас найдется способ отмерить таймаут в 1.75ms под Windows?
|
|
|
|
Guest_@Ark_*
|
Nov 8 2009, 01:37
|
Guests

|
Цитата ... Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это. Сообщения ведь попадают в "Копилку Вечности".... Ну, если писать с прицелом в "Копилку Вечности", то нужно быть более точными в формулировках. Прием сообщения считается завершенным, если обнаружена пауза не менее 3.5 дительностей передачи одного символа, а правильность приема определяется по значению CRC. Начинать передачу ответа можно сразу по истечении длительности интервала ожидания конца сообщения (3,5 символа), не делая каких-либо дополнительных пауз. По этой причине, для экономии времени, правильнее сразу начинать анализ сообщения и формирование ответа, уже в процессе приема сообщения, не дожидаясь конца передачи и завершающей паузы. Естественно, что делать какие-либо критичные действия (например, запись переменных) и отправлять ответ, можно только после успешного завершения приема и проверки корректности сообщения. А вот, например, проверять код номера устройства, допустимость параметров команды, вести подсчет контрольной суммы, производить чтение данных - вполне можно уже в процессе приема сообщения. И ни каким нарушением стандарта это не является.
|
|
|
|
Guest_@Ark_*
|
Nov 8 2009, 01:56
|
Guests

|
Цитата Из всего перечисленного какой-то практический смысл имеет только проверка адреса. Все остальное - это просто создание себе вороха проблем ради весьма сомнительной экономии. Эта "сомнительная экономия" требуется, когда необходимо сократить время ответа устройства до минимально возможного, и, тем самым, повысить быстродействие всей системы. Если для Вас это не критично - можете не экономить, никто не заставляет.
|
|
|
|
Guest_@Ark_*
|
Nov 8 2009, 02:21
|
Guests

|
Цитата ... значит что-то не так с выбором протоколов и интерфейсов. Конечно. Самое простое решение - взять канал побыстрее, а "камень по-больше", чего там экономить!
|
|
|
|
|
Nov 8 2009, 02:32
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Ради справедливости хотелось бы заметить, что не всегда есть возможность разбирать пакет "на лету" по причине многоуровневой организации связи. Вообще говоря, ModBus это довольно высокий уровень в сетевой модели OSI. Когда у устройства только один коммуникационный интерфейс и только один поддерживаемый протокол, то там можно конечно наоптимзировать. Но в общем случае формирование и разбор пакетов не связаны напрямую с их приемом/отправкой и тем более с отслеживанием пауз. Прием/отправка чаще всего привязаны к прерываниям UART. Но в прерывании UART не желательно еще и паузы отслеживать (в крайнем случае можно лишь каждый байт сопровождать меткой времени, интерлив этих меток анализировать не его задача) и за сетевыми адресами следить и CRC считать. Там потоковые буферы работают. А у буфера только три параметра: указатель на его начало, индекс текущего элемента и счетчик кол-ва байт. Все! Больше ничего буферу не нужно. И что там именно принимается или передается функции прерываний уже не интересует. Есть что-то в буфере передачи - передаем (если передача разрешена) пока не закончится это что-то. На приеме: если что-то пришло, без ошибок, фиксируемых аппаратурой UART, и есть место в буфере приема, то принимаем. Только такая организация физического уровня позволяет его использовать вне зависимости от вышестоящего протокола. P.S. вдогонку, а кроме UART есть (существуют) еще и другие интерфейсы  P.P.S. вообще лично я отношусь отрицательно, когда в реализации связи не предусмотрены настраиваемые задержки. Не нужны тебе задержки - занули их, но пускай они будут. Самому же потом будет проще адаптировать свою аппаратуру к чужим сетям.
|
|
|
|
|
Nov 8 2009, 02:55
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Ну, как и следовало ожидать, конкретные цифры озвучены не были. Цитата(@Ark @ Nov 8 2009, 05:21)  Конечно. Самое простое решение - взять канал побыстрее, а "камень по-больше", чего там экономить!  Считаете, простое решение менее разумно? А я вот полагаю, что куда менее разумно доводить до абсурда "оптимизацию". Цитата(defunct @ Nov 8 2009, 05:47)  Пусть сэкономим 5ms на пакет. Много это или мало... хм.. на тысяче пакетов сэкономим 5 секунд, на 10K - 50 секунд уже существенно. Ну, 5ms сэкономим разве что при скорости 9600 (два байта CRC и 3.5 паузы). И сколько секунд в этом случае займут 10К пакетов? Экономия получается на уровне единиц процентов в самом лучшем случае.
|
|
|
|
|
Nov 8 2009, 03:27
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(rezident @ Nov 8 2009, 04:32)  Но в общем случае формирование и разбор пакетов не связаны напрямую с их приемом/отправкой и тем более с отслеживанием пауз. Прием/отправка чаще всего привязаны к прерываниям UART. Но в прерывании UART не желательно еще и паузы отслеживать (в крайнем случае можно лишь каждый байт сопровождать меткой времени, интерлив этих меток анализировать не его задача) и за сетевыми адресами следить и CRC считать. Насчет приемной части пожалуй позволю себе с Вами не согласиться. При использовании последовательных интерфейсов, определением границ пакета удобнее всего заниматься там, где идет посимвольный поток. А где такой поток идет нативно? - Как раз в RX прерывании UARTa. Смену протокола, не меняя (не нарушая) структуру драйвера UART'a тоже элементарно сделать - предусмотрев подмену потоковой функции-обработчика. Крайне желательно чтобы эта функция-обработчик занималась определением сетевого адреса, отбрасывая мусор нам непредназначенный, тем самым экономя и время, и память. Пусть есть сл. обработчик прерывания (упрощенно): Код __interrupt void uart_RxExtHandler(void) { U8 status = UART_STATUS_REG; U8 ch = UART_DATA_REG;
if (status != OK ) { DoHandleError(); return; }
if (rx_cb) // Есть спец-функция обработки потока? rx_cb( ch ); // пользуем ее else // нет, тогда... { ... положить в generic uart буфер или сделать что-то еще } } Смена протокола сведется к смене обработчика потока: rx_cb = MEK_RxCharHandler; rx_cb = Modbus_RxCharHandler; rx_cb = hc_RxCharHandler; rx_cb = ppp_RxCharHandler; rx_cb = slip_RxCharHandler; ... и т.д. и т.п. Пример возможного обработчика потока: Код /***************************************** * ppp_RxCharHandler() * * Attached when lower layer is UP * * using byte staffing (flag sequence) * * to extract packets * * ---> val - current char from the link * * <--- returns nothing * *****************************************/ static void ppp_RxCharHandler(U8 val) { PPACKET_BUF pInPkt = linkContext.pInPkt; #if (AUTO_ESCAPE) static U8 prevch = 0; U8 esc_val = (prevch == PPP_ESCAPE) ? val ^ 0x20 : val; #else #define esc_val val #endif
if (!pInPkt) // return if no storage return;
linkContext.pppRxOctetCnt += 1; linkContext.pppRxTimeSinceLastOctet = 0; if (val == PPP_FLAG) // new packet / end of packet { ppp_NewPacket( pInPkt ); } else { // receiving packet #if (AUTO_ESCAPE) if (!ppp_IsEscaped( linkContext.inACCM, val)) { pInPkt->payload[ pInPkt->Length++ ] = esc_val; pInPkt->fcs = ppp_fcs16( pInPkt->fcs, &esc_val, 1); if (pInPkt->fcs == PPPGOODFCS16) ppp_NewPacket( pInPkt ); } #else pInPkt->payload[ pInPkt->Length++ ] = esc_val; #endif if (pInPkt->Length >= MAX_LINK_PACKET_SIZE) { // break receving (exceed max len) linkContext.pppRxDiscardMaxLen += 1; pInPkt->Length = 0; } }
#if (AUTO_ESCAPE) prevch = val; #endif } То что в этом обработчике делается весьма просто и без лишних затрат памяти - escaped characters, нативное определение границ пакета, - делать в аппликейшине накладнее. Кроме того например Microsoft не утруждает себя посылкой закрывающего флага 0x7E в конце пакета, MS считает что достаточно одного 0x7E флага в начале пакета. Поэтому, чтобы не терять время в ожидании таймаута <хрен знает какой длины> или следующего пакета с разделительным флагом - FCS (CRC) текущего пакета считается на лету, при совпадении пакет сразу же отцепляется. Цитата На приеме: если что-то пришло, без ошибок, фиксируемых аппаратурой UART, и есть место в буфере приема, то принимаем. Только такая организация физического уровня позволяет его использовать вне зависимости от вышестоящего протокола. Ну мы говорим не про физ уровень, а про канальный уровень. Приведенная выше организация решает обратную задачу, - как сделать протокол пригодным к использованию с любым каналом и экономить память занимаемую канальным уровнем. Байт-обработчики можно использовать и для пакетных интерфесов, т.к. никто не мешает вызвать их n раз для n байт принятого пакета. Она не противоречит и Вашей организации. Можно из буфера приема (если есть память под этот отдельный буфер приема) читать символы побайтово, и скармливать байт-обработчику, только это будет двойная работа, и нет ясности как быть с таймаутами (не думаю что Вы всерьез предложили наградить каждый принятый байт довеском их одно-, двух-, трех-, четырех- байтой метки времени).
|
|
|
|
Guest_@Ark_*
|
Nov 8 2009, 06:30
|
Guests

|
Цитата Ну, как и следовало ожидать, конкретные цифры озвучены не были... А какие могут быть конкретные цифры, без указания конкретной задачи? Пример могу привести. При реализации операции чтения по MODBUS (например, значений АЦП), часто требуется первичную обработку данных делать в самом устройстве (получение и усреднение нескольких значений, масштабирование результата, пересчет и приведение к нужному виду). А не гнать поток "сырой информации" мастеру, перекладывая на него их обработку, и загружая канал. В этом случае формирование ответа может занимать значительное время - сравнимое со временем приема сообщения... Цитата Считаете, простое решение менее разумно?.... Для приведенного примера - более простое решение просто не приемлемо. Считать 100 значений АЦП и передать по каналу усредненный результат, или 100 раз передать по MODBUS "сырые" значения - разницу трудно не заметить.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|