Перейти к содержанию
    

Протокол modbus. Вопросы по интерфейсу

По ГПРС пинги по полторы секунды - не редкость.

Угу.

А Modbus-TCP для кого придумали? По моему скромному, самое оно для таких сетей

Вот это Вы Автору, который хочет знать только RTU и видит в нем только байты, и не видит никаких проблем объясните.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну а время, время между этими самыми байтами, как с ним дела обстоят? Огласите.

 

Т.е. Mobus ASCII тут будет гораздо лучше ? Именно в отношении RTU vs ASCII выше было обсуждение.

К тому же D&M вообще CSD пока обсуждает имхо.

 

По ГПРС пинги по полторы секунды - не редкость.

 

и более... :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У счетчика Modbus-RTU, а в модеме только CSD..

 

Вы сначала определитесь со всей структурой системы, а затем переходите к решению отдельных пунктов.

 

Например:

1. Что на верхнем уровне (компьютер) - какая-то готовая программа, нечто самописное, нечто на основе SCADA/OPC...

Отсюда уже станет ясно, сможет ли эта программа сама всех обзванивать или иметь дополнительный функционал, и нужны ли будут нижеследующие промежуточные звенья:

2. Контроллер опроса верхнего уровня - "железка", которая сама будет обзванивать, опрашивать счетчики и преобразовывать данные в понятный формат для (п.1) программе, естественно и поддерживать обмен по протоколу который эта программа (п.1) поддерживает.

2а. модем.

3а. модем.

3. Контроллер опроса нижнего уровня - "железка" которая будет производить дополнительную обработку собранных данных до передачи в канал связи.

4. Ваши счетчик(и)

 

В зависимости от конкретных условий - фунционала ПО п.1, канала связи и т.д., п.2 и п.3 могут отсутствовать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это.

Стандарты порой устаревают. А сильно распространненные нарушения часто становятся частью страндарта.

Грубых нарушений стандарта в упор не вижу, если CRC сошлась ложно, то пакет отбракуется по длине и прием продолжится.

С другой стороны, на кой в холостую ждать 3.5 символьных интервала (это ж вагон и еще маленькая тележка времени особенно на 9600 и ниже), когда их можно потратить с пользой, например на вычитку архива из медленного eeprom'а по текущему запросу мастера.

 

Сообщения ведь попадают в "Копилку Вечности", вдруг кто-то из начинающих когда-то забредёт сюда (даже в правилах написано - новую тему создавать после того, как ничего не нашел поиском), и подумает что так и нужно делать...

Может для "Копилки Вечности" у вас найдется способ отмерить таймаут в 1.75ms под Windows?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
... Я ответил скорее не топикпастеру, а на фразу defunct по поводу того что "По приему CRC слейв может сразу же приступить к формированию ответа". Поскольку это грубое, но очень сильно распространенное нарушение стандарта, решил указать на это. Сообщения ведь попадают в "Копилку Вечности"....

Ну, если писать с прицелом в "Копилку Вечности", то нужно быть более точными в формулировках.

Прием сообщения считается завершенным, если обнаружена пауза не менее 3.5 дительностей передачи одного символа, а правильность приема определяется по значению CRC. Начинать передачу ответа можно сразу по истечении длительности интервала ожидания конца сообщения (3,5 символа), не делая каких-либо дополнительных пауз. По этой причине, для экономии времени, правильнее сразу начинать анализ сообщения и формирование ответа, уже в процессе приема сообщения, не дожидаясь конца передачи и завершающей паузы. Естественно, что делать какие-либо критичные действия (например, запись переменных) и отправлять ответ, можно только после успешного завершения приема и проверки корректности сообщения. А вот, например, проверять код номера устройства, допустимость параметров команды, вести подсчет контрольной суммы, производить чтение данных - вполне можно уже в процессе приема сообщения. И ни каким нарушением стандарта это не является.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот, например, проверять код номера устройства, допустимость параметров команды, вести подсчет контрольной суммы, производить чтение данных - вполне можно уже в процессе приема сообщения. И ни каким нарушением стандарта это не является.

Из всего перечисленного какой-то практический смысл имеет только проверка адреса. Все остальное - это просто создание себе вороха проблем ради весьма сомнительной экономии. Пусть и в рамках стандарта.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
Из всего перечисленного какой-то практический смысл имеет только проверка адреса. Все остальное - это просто создание себе вороха проблем ради весьма сомнительной экономии.

Эта "сомнительная экономия" требуется, когда необходимо сократить время ответа устройства до минимально возможного, и, тем самым, повысить быстродействие всей системы. Если для Вас это не критично - можете не экономить, никто не заставляет. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, сколько удалось наносекунд сэкономить, а? Серьезно спрашиваю.

Если такое аж требуется, значит что-то не так с выбором протоколов и интерфейсов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
... значит что-то не так с выбором протоколов и интерфейсов.

Конечно. Самое простое решение - взять канал побыстрее, а "камень по-больше", чего там экономить! :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ради справедливости хотелось бы заметить, что не всегда есть возможность разбирать пакет "на лету" по причине многоуровневой организации связи. Вообще говоря, ModBus это довольно высокий уровень в сетевой модели OSI. Когда у устройства только один коммуникационный интерфейс и только один поддерживаемый протокол, то там можно конечно наоптимзировать. Но в общем случае формирование и разбор пакетов не связаны напрямую с их приемом/отправкой и тем более с отслеживанием пауз. Прием/отправка чаще всего привязаны к прерываниям UART. Но в прерывании UART не желательно еще и паузы отслеживать (в крайнем случае можно лишь каждый байт сопровождать меткой времени, интерлив этих меток анализировать не его задача) и за сетевыми адресами следить и CRC считать. Там потоковые буферы работают. А у буфера только три параметра: указатель на его начало, индекс текущего элемента и счетчик кол-ва байт. Все! Больше ничего буферу не нужно. И что там именно принимается или передается функции прерываний уже не интересует. Есть что-то в буфере передачи - передаем (если передача разрешена) пока не закончится это что-то. На приеме: если что-то пришло, без ошибок, фиксируемых аппаратурой UART, и есть место в буфере приема, то принимаем. Только такая организация физического уровня позволяет его использовать вне зависимости от вышестоящего протокола.

P.S. вдогонку, а кроме UART есть (существуют) еще и другие интерфейсы :)

P.P.S. вообще лично я отношусь отрицательно, когда в реализации связи не предусмотрены настраиваемые задержки. Не нужны тебе задержки - занули их, но пускай они будут. Самому же потом будет проще адаптировать свою аппаратуру к чужим сетям.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, как и следовало ожидать, конкретные цифры озвучены не были.

 

Конечно. Самое простое решение - взять канал побыстрее, а "камень по-больше", чего там экономить! :biggrin:

Считаете, простое решение менее разумно? А я вот полагаю, что куда менее разумно доводить до абсурда "оптимизацию".

 

Пусть сэкономим 5ms на пакет. Много это или мало... хм.. на тысяче пакетов сэкономим 5 секунд, на 10K - 50 секунд уже существенно.

Ну, 5ms сэкономим разве что при скорости 9600 (два байта CRC и 3.5 паузы). И сколько секунд в этом случае займут 10К пакетов?

Экономия получается на уровне единиц процентов в самом лучшем случае.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но в общем случае формирование и разбор пакетов не связаны напрямую с их приемом/отправкой и тем более с отслеживанием пауз. Прием/отправка чаще всего привязаны к прерываниям 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 байт принятого пакета. Она не противоречит и Вашей организации. Можно из буфера приема (если есть память под этот отдельный буфер приема) читать символы побайтово, и скармливать байт-обработчику, только это будет двойная работа, и нет ясности как быть с таймаутами (не думаю что Вы всерьез предложили наградить каждый принятый байт довеском их одно-, двух-, трех-, четырех- байтой метки времени).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость @Ark
Ну, как и следовало ожидать, конкретные цифры озвучены не были...

А какие могут быть конкретные цифры, без указания конкретной задачи?

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

Считаете, простое решение менее разумно?....

Для приведенного примера - более простое решение просто не приемлемо. Считать 100 значений АЦП и передать по каналу усредненный результат, или 100 раз передать по MODBUS "сырые" значения - разницу трудно не заметить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пример из пальца высосан: вдруг, по команде извне, начинаем АЦПировать и накапливать 100 значений, вместо того, чтобы делать это постоянно и спокойно отдавать при необходимости готовый результат. Ах, ну да, у нас ведь ресурсов нет на такие сложности.

А можно еще какой-нибудь 1-wire термометр так опрашивать - огромная экономия выйдет, если запустить преобразование с опережением в 5.5 символов UART'а.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...