Git Product home page Git Product logo

modbuspp's Introduction

MODBUS++ (MODBSPP) v0.3

CMake

0 Info, Updates and Discalimer

0.0 Info

MODBUS++ (MODBUSPP) is an header-only open source c++ class/ library making an encapsulation of Modbus TCP Protocol for client.

MODBUS++ is providing a more OOP friendly syntax.

The code now is modified to extend for Windows! However, the code for running on Windows is not throughly tested.

0.1 Updates

UPDATES in v0.3 compared to V0.2:

  1. Bug Fixing
  2. Type fixing
  3. Initial Windows support (in dev, not fully tested)
  4. Logging as Option
  5. Cmake install script
  6. Pasting licensing information in file

1 Usage

To use the library, please follow the steps below. Please note current library is only compatible with Linux distributions because of the socket library dependencies.

1.1 Download

Download the MODBUS++, you can:

1.2 Include In your code

  1. Copy the "moodbus.h" to your include directory and include the code whenever appropriate:

    include "modbus.h"

  2. On Linux platform, you could also use
    mkdir build
    cd build
    cmake ..
    sudo make install
    This will install the header under usr/local/include and include the code whenever appropriate

    include "modbuspp/modbus.h"

1.3 Logging as Option

To enable logging, simply set ENABLE_MODBUSPP_LOGGING in your compile option, see CMakeLists.txt with example.

2 Getting Started with a Example

2.1 Getting the Example

Checkout example.cpp for a example usage of MODBUSPP. Please note that the code should be compiled using c++11 compilers. A sample CMakeLists.txt is included. To build example:

2.1.1 CMAKE

mkdir build
cd build
cmake ..
make

2.1.2 G++

g++ example.cpp --std=c++11 -o example

2.1.3 MSCV

Open your Visual Studio to compile the project

2.2 Tutorials

Let's break the code down, before you read this, reference to example.cpp. The example shows basic usages of how to create a modbus client connecting to a modbus server and perform modbus operations in your program.

Include the header

To start with, be sure to include the modbus.h header in your program

#include "modbus.h"

This line includes the header modbus.h from the library, this will tell the compiler to look for functions and variables in the related file.

Create and connects a mobus server

Before performing any modbus operations, a connection needed to be setup between the modbus client(your program) and a modbus server(could be a controller).

modbus mb = modbus("127.0.0.1", 502); mb.modbus_set_slave_id(1); mb.modbus_connect();

These lines creates local modbus client with target IP address at 127.0.0.1 and port at 502, a server with id 1.

Performe Mobus Operations

Modbus usually have 2 types of operations, reading and writing. Reading operations include reading a coil, reading input bits, reading holding registers, and reading input registers. Writing Operations include writing sigle coil, wirting single register, writing multiple coil, and writing multiple registers. Be sure to create a connection before performing any operations. Modbus is relatively low-level protocols. It is useful to have strong computer structure knowledge to understand it.

  1. The following line show how to read a coil (function 0x01). These lines read a bit from the coil at address 0.

bool read_coil; mb.modbus_read_coils(0, 1, &read_coil);

  1. The following lines show how to read input bits(discrete input) (function 0x02). These lines read a bit from discrete inputs at address 0.

bool read_bits; mb.modbus_read_input_bits(0, 1, &read_bits);

  1. The follwing lines show how to read holding registers (function 0x03). These lines read a word(16 bits) from holding registers starting at address 0.

uint16_t read_holding_regs[1]; mb.modbus_read_holding_registers(0, 1, read_holding_regs);

  1. The following lines show how to Read input registers (function 0x04). These lines read a word(16 bits) from input registers starting at address 0.

uint16_t read_input_regs[1]; mb.modbus_read_input_registers(0, 1, read_input_regs);

  1. The following lines show how to write single coil (function 0x05). These lines write a bit to the coil at address 0.

mb.modbus_write_coil(0, true);

  1. The following lines show how to write single register (function 0x06). These lines write a word(16 bits) to the register at address 0.

mb.modbus_write_register(0, 123);

  1. The following lines show how to write multiple coils (function 0x0F). These lines write multiple bits to the coil starting from address 0, for a length of 4.

bool write_cols[4] = {true, true, true, true}; mb.modbus_write_coils(0,4,write_cols);

  1. The following lines show how to write multiple regs (function 0x10). These lines write multiple words to the register starting from address 0, for a length of 4.

uint16_t write_regs[4] = {123, 123, 123}; mb.modbus_write_registers(0, 4, write_regs);

modbuspp's People

Contributors

fz-lyu avatar jjl772 avatar markcutler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

modbuspp's Issues

modbus_write fails to set correct size in case of WRITE_REGS (mb fn 0x10)

The length coding field in the MBAP header part of the mb/tcp ADU is wrong calculated, so enforcing mb receivers to read too few holding registers from the request.

I'm in C and C++ and Labview and Git, but i'm totally newb to the github thing. I hope to provide a new version or pull request the right way...

Wrong timeout unit on windows

From microsoft documentation SO_RCVTIMEO and SO_SNDTIMEO are expressed in ms whereas in the code the timeout seems to be targetting 20s as for linux:

#ifdef WIN32
    const DWORD timeout = 20;
#else
    struct timeval timeout
    {
    };
    timeout.tv_sec = 20; // after 20 seconds connect() will timeout
    timeout.tv_usec = 0;
#endif

the problem with 'to_send'

visual studio says that " Using uninitialized memory 'to_send' " and " potentially uninitialized local pointer variable 'to_send' used ". Because of that I can't send anything to my registers, but only read.

modbus_write has a problem when func == WRITE_COILS

When multiple coils are written the modbus_write writes wrongfully the low byte of the requested coil
Requested Number of Coil Low Byte should be:
to_send[11] = (uint8_t) (amount);
instead of :
to_send[11] = (uint8_t) (amount>>8);

Emulate Modbus Server

Is there any way to emulate a MODBUS Server too using modbuspp?

So I can use my own PC (or 2 PCs + Ethernet comm) to run the modbus datagram transfer?

Bug when breaking a line

When you successfully connect and send data, receive data, this is normal.
Unplugging the network cable and sending data again will return an error, which is normal.
However, when you plug the network cable back in, no error will be returned because "err_no" is 0,
This bug occurs in -> If (err) {return err_no; }

Another problem is that when the wire is broken and reconnected, there is no check to see if the content of the protocol frame returned is correct

default value of error variable on modbuserror_handle

currently the variables below are defined and the end of the function, overwriting the error on the variable "msg" identified previously by the switch.
err = false;
error_msg = "NO ERR";

Moving the definition at before the switch will show the error properly

/**
 * Error Code Handler
 * @param msg   Message Received from the Server
 * @param func  Modbus Functional Code
 */
void modbus::modbuserror_handle(const uint8_t *msg, int func) {
    err = false;
    error_msg = "NO ERR";
    if(msg[7] == func + 0x80) {
        err = true;
        switch(msg[8]){
            case EX_ILLEGAL_FUNCTION:
                error_msg = "1 Illegal Function";
                break;
            case EX_ILLEGAL_ADDRESS:
                error_msg = "2 Illegal Address";
                break;
            case EX_ILLEGAL_VALUE:
                error_msg = "3 Illegal Value";
                break;
            case EX_SERVER_FAILURE:
                error_msg = "4 Server Failure";
                break;
            case EX_ACKNOWLEDGE:
                error_msg = "5 Acknowledge";
                break;
            case EX_SERVER_BUSY:
                error_msg = "6 Server Busy";
                break;
            case EX_NEGATIVE_ACK:
                error_msg = "7 Negative Acknowledge";
                break;
            case EX_MEM_PARITY_PROB:
                error_msg = "8 Memory Parity Problem";
                break;
            case EX_GATEWAY_PROBLEMP:
                error_msg = "10 Gateway Path Unavailable";
                break;
            case EX_GATEWYA_PROBLEMF:
                error_msg = "11 Gateway Target Device Failed to Respond";
                break;
            default:
                error_msg = "UNK";
                break;
        }
    }
    // err = false;
    // error_msg = "NO ERR";
}

illegal data values

when "modbus_write_coil"s function calls it gives me "illegal data values" error. i do to_send[11] = (uint8_t)(amount); in func == WRITE_COILS of "modbus_write" function butt it did not write multiple coils coils

The problem used in Windows

I saw you said this code could also be used in Windows, but when I used it in Windows, firstly it need to compile with -lwsock32. But when I get the executable file, it could only connect with the Modbus Slaver, could not read or write, only can connect this IP with the correct port, but it can not read or write.

modbus_write_coils not working

void modbus::modbus_write(int address, int amount, int func, uint16_t value) {
if (func == WRITE_COIL || func == WRITE_REG) {
uint8_t to_send[12];
modbus_build_request(to_send, address, func);
to_send[5] = 6;
to_send[10] = (uint8_t)(value[0] >> 8);
to_send[11] = (uint8_t)(value[0] & 0x00FF);
modbus_send(to_send, 12);
}
else if (func == WRITE_REGS) {
uint8_t
to_send = new uint8_t[13 + 2 * amount];
modbus_build_request(to_send, address, func);
to_send[5] = (uint8_t)(5 + 2 * amount);
to_send[10] = (uint8_t)(amount >> 8);
to_send[11] = (uint8_t)(amount & 0x00FF);
to_send[12] = (uint8_t)(2 * amount);
for (int i = 0; i < amount; i++) {
to_send[13 + 2 * i] = (uint8_t)(value[i] >> 8);
to_send[14 + 2 * i] = (uint8_t)(value[i] & 0x00FF);
}
cout << to_send << endl;
modbus_send(to_send, 13 + 2 * amount);
}
else if (func == WRITE_COILS) {

	uint8_t* to_send = new uint8_t[14 + (amount - 1) / 8];
	modbus_build_request(to_send, address, func);
	to_send[5] = (uint8_t)(7 + (amount - 1) / 8);
	to_send[10] = (uint8_t)(amount >> 8);
	to_send[11] = (uint8_t)(amount>>8);
	to_send[12] = (uint8_t)((amount + 7) / 8);
	for (int i = 0; i < amount; i++) {
		to_send[13 + (i - 1) / 8] += (uint8_t)(value[i] << (i % 8));
	}
	cout << to_send << endl;
	modbus_send(to_send, 14 + (amount - 1) / 8);
}

}

Exception on exit

Hello,

i just started using your library but I found an issue.

When I instantiate the class, the code works but I get an exception when the program exits. See below and attached screenshot.

Output :

address : 192.168.1.21 port : 502
reg #1 : 1 reg #2 : 2
Found Proper Host 192.168.1.21 and Port 502
Socket Opened Successfully
Connected
Register #0 holds : 0x7fff360f17ae
Socket Closed
*** Error in `./modbus_retriever': munmap_chunk(): invalid pointer: 0x00007fff360f1800 ***
Abandon (core dumped)

@fanzhe98 Thanks you for helping

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.