yaacov / ArduinoModbusSlave

Modbus slave library for Arduino
ISC License
205 stars 75 forks source link

ModbusSlave

ModbusSlave library for Arduino

This Modbus RTU slave library uses callbacks to handle modbus requests for one or multiple slave ids. Handler functions are called on modbus a request, and the users can implement them within their sketch.

ModbusSlave is fun and easy to use

Register a handler function:

slave.cbVector[CB_READ_INPUT_REGISTERS] = ReadAnalogIn;

Implement it:

void ReadAnalogIn(uint8_t fc, uint16_t address, uint16_t length) {
    for (int i = 0; i < length; i++)
        slave.writeRegisterToBuffer(i, analogRead(address + i));
}

And thats it, your sketch is modbus enabled. (see the full examples for more detail)



Install

Download the zip package, and install it into your Arduino IDE. See the Arduino tutorial about installing 3rd party libraries: https://www.arduino.cc/en/Guide/Libraries#toc4

Compatibility

This class implements:

Serial port

Callback vector

Users register handler functions into the callback vector of the slave.

Multiple Slaves

This can be done independently for one or multiple slaves with different IDs.

Slots

The callback vector has 7 slots for request handlers:

Handler function

A handler functions must return an uint8_t code and take the following as parameters:

Usable return codes:

Function codes

Reading and writing to the request / response buffer

Examples


Handle "Force Single Coil" and write the received value to digitalWrite()
#include <ModbusSlave.h>

// Implicitly set stream to use the Serial serialport.
Modbus slave(1, 8); // [stream = Serial,] slave id = 1, rs485 control-pin = 8

void setup() {
    // Register functions to call when a certain function code is received.
    // If there is no handler assigned to the function code a valid but empty message will be replied.
    slave.cbVector[CB_WRITE_COILS] = writeDigitalOut;

    // Start the slave at a baudrate of 9600bps on the Serial port.
    Serial.begin(9600);
    slave.begin(9600);
}

void loop() {
    // Listen for modbus requests on the serial port.
    // When a request is received it's going to get validated.
    // And if there is a function registered to the received function code, this function will be executed.
    slave.poll();
}

// Handel Force Single Coil (FC=05).
uint8_t writeDigitalOut(uint8_t fc, uint16_t address, uint16_t length) {
    if (slave.readCoilFromBuffer(0) == HIGH)
    {
        digitalWrite(address, HIGH);
    }
    else
    {
        digitalWrite(address, LOW);
    }
    return STATUS_OK;
}

Handle "Read Input Registers" and return analogRead()
#include <ModbusSlave.h>

// Explicitly set a stream to use the Serial port.
Modbus slave(Serial, 1, 8); // stream = Serial, slave id = 1, rs485 control-pin = 8

void setup() {
    // Register functions to call when a certain function code is received.
    // If there is no handler assigned to the function code a valid but empty message will be replied.
    slave.cbVector[CB_WRITE_COILS] = readAnalogIn;

    // Start the slave at a baudrate of 9600bps on the Serial port.
    Serial.begin(9600);
    slave.begin(9600);
}

void loop() {
    // Listen for modbus requests on the serial port.
    // When a request is received it's going to get validated.
    // And if there is a function registered to the received function code, this function will be executed.
    slave.poll();
}

// Handle Read Input Registers (FC=04).
uint8_t readAnalogIn(uint8_t fc, uint16_t address, uint16_t length) {
    // Write the result of analogRead() into the response buffer.
    for (int i = 0; i < length; i++) {
      slave.writeRegisterToBuffer(i, analogRead(address + i));
    }
    return STATUS_OK;
}