Программирование общения двух ПК через протокол MODBUS
От: jak  
Дата: 11.08.04 08:58
Оценка:
Собственно пока 2 вопроса:
— как программировать?
— какое железо к этому надо?
ЗЫ: просьба ногами сильно не пинать т.к. в этом вопросе я абсолютный чайник
Re: Программирование общения двух ПК через протокол MODBUS
От: jak  
Дата: 12.08.04 06:32
Оценка:
просто up
очень нужно
Re: Программирование общения двух ПК через протокол MODBUS
От: Splin Беларусь  
Дата: 12.08.04 07:30
Оценка:
Здравствуйте, jak, Вы писали:

jak>Собственно пока 2 вопроса:

jak>- как программировать?
jak>- какое железо к этому надо?
jak>ЗЫ: просьба ногами сильно не пинать т.к. в этом вопросе я абсолютный чайник

Для начала Modbus может быть разный — через Ethernet (TCP/IP) или через Serial Port.
Что касается первого — не реализовывал, но думаю там нет ничего сложного.
Что касается второго — писал программу-мастер под Windows. Вообще говоря, этот протокол расчитан на работу мастера с несколькими устройствами одновременно (от 1 до 127, если не ошибаюсь), так что тут используется RS485. Если подключаться к обычному компьютеру через RS232 несколько slave-устройств, то надо иметь расширитель порта (преобразователь RS232/RS485). В принципе в случае двух PC можно и без него можно обойтись — просто соеденить через RS232. Ну а дальше — полылай запросы slave-у и получай ответы (один PC будет выступать в качестве ведущего — master, второй ведомого — slave). Могу подкинуть небольшой класс на C++ реализующий сам обмен.
Re[2]: Программирование общения двух ПК через протокол MODBU
От: jak  
Дата: 12.08.04 08:01
Оценка:
буду очень благодарен за исходник класса. Если можно пришли кусок кода для примера как организовывать общение между мастером и слэйвом.
и по поводу соединения через RS232 компы могут быть отдалены друг от друга на расстояние порятка 1500м. на сколько я понимаю просто rs232 тянет в лучшем случаем метров на 10. Правильно? и что тогда делать?

С меня

Re[3]: Программирование общения двух ПК через протокол MODBU
От: Splin Беларусь  
Дата: 12.08.04 08:35
Оценка:
Здравствуйте, jak, Вы писали:

jak>буду очень благодарен за исходник класса. Если можно пришли кусок кода для примера как организовывать общение между мастером и слэйвом.

jak>и по поводу соединения через RS232 компы могут быть отдалены друг от друга на расстояние порятка 1500м. на сколько я понимаю просто rs232 тянет в лучшем случаем метров на 10. Правильно? и что тогда делать?

В этом случае можно протянуть кабель и установить обычные модемы, которые будут обеспечивать связь (можно использовать радио-модемы). Я не очень вкурсе конкретных устройств, т.к. я программист. Могу лишь сказать, что мы когда-то использовали некое устройство "удлинитель порта" позволяющие передавать данные по RS232 на большие растояния (точно не скажу насколько . Что касается кода — это вот такой класс (реализацию могу тоже предоставить после небольшой правки, если интересно, конечно...):

class CModbusConnection  
{
public:
    enum
    {
        RtuFrameMaxSize = 256,
        RtuFrameMinSize = 4,
        
        fExceptionMask = 0x80,

        // Bit access
        fReadDiscreteInputs = 1,
        fReadCoils = 2,
        fWriteSingleCoil = 5,
        fWriteMultipleCoils = 15,
        // 16 bits access
        fReadInputRegisters = 4,
        fReadHoldingRegisters = 3,
        fWriteSingleRegister = 6,
        fWriteMultipleRegisters = 16,
        // Diagnostics
        fReadExceptionStatus = 7
    };

public:
    CModbusConnection();
    ~CModbusConnection();

    // Open comm port
    bool Open(
        /* [in] */ LPCTSTR lpszPortName,
        /* [in] */ DWORD dwPortBaudRate,
        /* [in] */ BYTE byPortByteSize,
        /* [in] */ BYTE byPortParity,
        /* [in] */ BYTE byPortStopBits,
        /* [in] */ DWORD dwTimeoutRead,
        /* [in] */ DWORD dwTimeoutWrite);
    
    // Is openned comm port?
    bool IsOpened();
    
    // Close comm port
    void Close();

    // Sets the retry options
    void SetRetryOptions(DWORD dwRetryCount, DWORD dwRetryDelay);
    // Returnes the retry options
    void GetRetryOptions(DWORD& dwRetryCount, DWORD& dwRetryDelay) const;

public:
    // Sends read request (functions 1, 2, 3, 4)
    bool ReadRequest(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ BYTE byFunction,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [out] */ BYTE* pbyData,
        /* [in] */ BYTE byDataSize,
        /* [out] */ BYTE& byDataRealSize);

public:
    // #01 - Read Discrete Inputs
    bool ReadDiscreteInputs(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [out] */ BYTE* pbyData,
        /* [in] */ BYTE byDataSize,
        /* [out] */ BYTE& byDataRealSize);
    
    // #02 - Read Coils
    bool ReadCoils(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [out] */ BYTE* pbyData,
        /* [in] */ BYTE byDataSize,
        /* [out] */ BYTE& byDataRealSize);

    // #03 - Read Holding Registers
    bool ReadHoldingRegisters(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [out] */ BYTE* pbyData,
        /* [in] */ BYTE byDataSize,
        /* [out] */ BYTE& byDataRealSize);
    
    // #04 - Read Input Registers
    bool ReadInputRegisters(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [out] */ BYTE* pbyData,
        /* [in] */ BYTE byDataSize,
        /* [out] */ BYTE& byDataRealSize);

    // #05 - Write Single Coil
    bool WriteSingleCoil(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wAddres,
        /* [in] */ WORD wData);
    
    // #06 - Write Single Register
    bool WriteSingleRegister(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wAddres,
        /* [in] */ WORD wData);

    // #07 - Read Exception Status
    bool ReadExceptionStatus(
        /* [in] */ BYTE bySlaveAddres,
        /* [out] */ BYTE& byStatus);

    // #15 - Write Multiple Coils
    bool WriteMultipleCoils(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [in] */ const BYTE* pbyData,
        /* [in] */ BYTE byDataSize);
    
    // #16 - Write Multiple Registers
    bool WriteMultipleRegisters(
        /* [in] */ BYTE bySlaveAddres,
        /* [in] */ WORD wStartingAddres,
        /* [in] */ WORD wQuantity,
        /* [in] */ const WORD* pwData,
        /* [in] */ BYTE byDataSize);

protected:    
    bool SendQueryWithRetry(
        /* [in] */ const BYTE* pbyQuery,
        /* [in] */ WORD wQuerySize,
        /* [out] */ BYTE* pbyResponse,
        /* [in] */ WORD wResponseSize,
        /* [out] */ WORD* pwResponseRealSize);

    bool SendQuery(
        /* [in] */ const BYTE* pbyQuery,
        /* [in] */ WORD wQuerySize,
        /* [out] */ BYTE* pbyResponse,
        /* [in] */ WORD wResponseSize,
        /* [out] */ WORD* pwResponseRealSize);

    bool ValidateResponse(
        /* [in] */ const BYTE* pbyQuery,
        /* [in] */ WORD wQuerySize,
        /* [in] */ const BYTE* pbyResponse,
        /* [in] */ WORD wResponseSize,
        /* [in] */ WORD wResponseRealSize);

protected:
    void TraceModbusError(LPCTSTR lpszPortName, BYTE byError, LPCTSTR lpszMessage);

    void TraceCommError(LPCTSTR lpszPortName, DWORD dwError, LPCTSTR lpszMessage);
    void TraceCommError(LPCTSTR lpszPortName, LPCTSTR lpszMessage);
    void TraceCommInfo(LPCTSTR lpszPortName, LPCTSTR lpszMessage);
    void TraceCommDebug(LPCTSTR lpszPortName, LPCTSTR lpszMessage);
    
    void TraceFrame(const BYTE* pbyFrame, const WORD wFrameSize, bool bQuery);
    
    bool ClearAndTraceCommError(HRESULT hrError, LPCTSTR lpszMessage);

protected:
    CString m_strPortName;
    HANDLE m_hCommPort;

protected:
    DWORD m_dwRetryCount;
    DWORD m_dwRetryDelay;
};
Re[4]: Программирование общения двух ПК через протокол MODBU
От: jak  
Дата: 12.08.04 09:44
Оценка:
S>В этом случае можно протянуть кабель и установить обычные модемы, которые будут обеспечивать связь (можно использовать радио-модемы). Я не очень вкурсе конкретных устройств, т.к. я программист. Могу лишь сказать, что мы когда-то использовали некое устройство "удлинитель порта" позволяющие передавать данные по RS232 на большие растояния (точно не скажу насколько .

ну я полгода назад занимался такой же проблемой и нашел вариант конвертации из rs232 в rs485 (вроде бы) и обратно что позволило в априоре доставить сигнал на 1000м, но не смог тогда разобраться как это все корректно установить, и по сему закинул, (да и клиент отказался от этой идеи).

S>Что касается кода — это вот такой класс (реализацию могу тоже предоставить после небольшой правки, если интересно, конечно...):


S>
S>class CModbusConnection  
S>{
S>...
S>};

S>


Это я так опнимаю идет обращение на сом-порт к которому подключена линия с используемым протоколом MODBUS ?
Re[5]: Программирование общения двух ПК через протокол MODBU
От: Splin Беларусь  
Дата: 12.08.04 11:27
Оценка:
Здравствуйте, jak, Вы писали:

jak>ну я полгода назад занимался такой же проблемой и нашел вариант конвертации из rs232 в rs485 (вроде бы) и обратно что позволило в априоре доставить сигнал на 1000м, но не смог тогда разобраться как это все корректно установить, и по сему закинул, (да и клиент отказался от этой идеи).


А нет там ничего сложного — все довольно просто — в описании устройства можно прочитать как подключать. В моем случае использовалась структура в виде (если я точно помню):
Slaves <-(несколько десятков метров)-> Адаптер RS485/RS232 (производства ADAM, кажеться) <-> Модем Zyxel <- 4W Line (несколько км.) -> Модем Zyxel <-> PC (RS232)
Для отладкия я использовал такую схему:
Slaves <-(несколько десятков метров)-> Адаптер RS485/RS232 (производства ADAM, кажеться) <-> PC (RS232)
Все это работало без проблем. Разница межну нижней схемой и верхней лишь в увеличении задержек на прием передачу.
Основная проблема была лишь в том, сколько slave устройст можно подключить, т.к. каждое "подсаживает" линию. Это зависит от конкретных устройств (как правило производитили это записывают в документации).

В Вашем случае я не совсем понимаю зачем обмениваться 2-м PC через Modbus. Этот протокол предназначен для обмена сразу со многими устройствами. Если надо организовать обмен 2-х PC через COM-порт, то есть много других вариантов.

jak>Это я так опнимаю идет обращение на сом-порт к которому подключена линия с используемым протоколом MODBUS ?


Обмен происходит по принципу запрос-ответ. Этот класс занимается тем что получает запрос, формирует Modbus frame, отправляет его в линию и дожидается ответа (который и возвращается в out параметрах). Т.е. реализует протокол (формирование пакетов, проверки и пр.). В качестве линии используется serial line (т.е. последовательный порт). Хочу отметить, что преобразователи RS232/RS485 могут быть как внешними (отдельное уст-во, так и внутренними — спец. карта в PC).
Re[6]: Программирование общения двух ПК через протокол MODBU
От: jak  
Дата: 13.08.04 06:23
Оценка:
2 Splin
Спасибо за консультацию
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.