¿Qué encontraremos en este blog?
En este blog veremos cómo usar las funciones Modbus más utilizadas y encontraremos ejemplos de uso de los protocolos Modbus RTU y Modbus TCP en diferentes lenguajes de programación con un Raspberry PLC de Industrial Shields.
Requisitos
Hardware
- M-DUINO 21+ (Esclavo)
- Raspberry PLC 21+ (Maestro)
Software
+ M-DUINO 21+
+ Raspberry PLC 21+
- Imagen del RPI PLC de Industrial Shields (Cómo instalar)
- NODE-RED (instalado con la imagen)
- Modbus Pack (Información)
- Modpoll
- Para descargar el programa, podemos hacerlo con: wget https://www.modbusdriver.com/downloads/modpoll.tgz
- Después debemos descomprimirlo: tar xzf modpoll.tgz
- Y podemos ejecutar el ejecutable que hay dentro de la carpeta que acabamos de descomprimir o añadirlo al $PATH de esta manera:
- Abrimos el archivo .bashrc: nano ~/.bashrc
- Añadimos la siguiente línea al final del archivo: export PATH=$PWD/modpoll/armv6-rpi-linux-gnueabihf:$PATH
- Guardamos y salimos con Ctrl + S (guardar) y Ctrl + X (salir) y ejecutamos: source ~/.bashrc
- En este punto, tendremos listo para usar nuestro probador de maestro Modbus.
- Python
- Biblioteca PyModbus: pip install pymodbus
- Biblioteca para C++ y C
- libmodbus: sudo apt install libmodbus-dev
Funciones Modbus usadas en este blog
LECTURA | ESCRITURA |
FC1: Read Coil Status (lectura de 5 bobinas o salidas digitales) FC2: Read Input Status (lectura de 7 entradas digitales) FC3: Read Holding Registers (lectura de 3 registros o salidas analógicas) FC4: Read Input Registers (lectura de 6 entradas analógicas) | FC5: Write Single Coil (escritura de un valor digital en una salida digital) FC6: Write Single Register (escritura de un valor analógico en una salida analógica) FC15: Write Multiple (escritura de varios valores digitales en varias salidas digitales) FC16: Write Multiple Registers (escritura de varios valores analógicos en varias salidas analógicas) |
ÍNDICE DE CÓDIGOS
NODE-RED
| BASH + MODPOLL
| PYTHON
| C++
| C
|
| MODBUS RTU MODBUS TCP | MODBUS RTU MODBUS TCP | MODBUS RTU MODBUS TCP | MODBUS RTU MODBUS TCP | MODBUS RTU MODBUS TCP |
Conceptos de cada protocolo
En estos ejemplos se ha usado un M-Duino 21+ como ESCLAVO (con los códigos de ejemplo de la biblioteca Modbus de Industrial Shields, tanto para ESCLAVO RTU como para ESCLAVO TCP) y un Raspberry PLC 21+ como MAESTRO, es decir, el maestro envía los comandos al esclavo y este responde con las acciones o los datos solicitados.
Modbus RTU
Hemos usado el protocolo Modbus RTU sobre la interfaz de conexión RS485, lo que significa usar dos cables conectados a los pines A+ y B- de ambos dispositivos.
En estos ejemplos hemos usado /dev/ttySC0 como puerto de salida del Raspberry PLC. La dirección del esclavo es 31 y hemos configurado la conexión con una velocidad de 38400 baudios, 8 bits de datos, paridad par y 1 bit de parada.
Estos datos son muy importantes para el uso de este protocolo, ya que son los que hemos definido en los ejemplos de la biblioteca MODBUS y, si son diferentes, no funcionará con los ejemplos realizados
Modbus TCP
Hemos usado el protocolo TCP sobre la interfaz de conexión ETHERNET, lo que significa usar los conectores Ethernet de ambos dispositivos.
En este caso solo tenemos que tener en cuenta la IP del esclavo, que es 10.10.10.4
Código fuente
NODE-RED
Tras ejecutar node-red-start, copia e importa este código JSON:
Se importará algo como esto:

Después, despliega el flujo y, con los botones de inserción, podrás probar este protocolo.
BASH + MODPOLL
FC1: Read Coil Status
modpoll -m rtu -b 38400 -a 31 -d 8 -p even -s 1 -c 5 -t 0 /dev/ttySC0
FC2: Read Input Status
modpoll -m rtu -b 38400 -a 31 -d 8 -p even -s 1 -c 7 -t 1 /dev/ttySC0
FC3: Read Holding Registers
modpoll -m rtu -b 38400 -a 31 -d 8 -p even -s 1 -c 3 -t 4 /dev/ttySC0
FC4: Read Input Registers
modpoll -m rtu -b 38400 -a 31 -d 8 -p even -s 1 -c 6 -t 3 /dev/ttySC0
FC5: Write Single Coil
modpoll -m rtu -b 38400 -a 31 -r 6 -c 1 -p even -t 0 /dev/ttySC0 1
modpoll -m rtu -b 38400 -a 31 -r 6 -c 1 -p even -t 0 /dev/ttySC0 0
FC6: Write Single Register
modpoll -m rtu -b 38400 -a 31 -r 3 -c 1 -p even -t 4 /dev/ttySC0 1000
modpoll -m rtu -b 38400 -a 31 -r 3 -c 1 -p even -t 4 /dev/ttySC0 200
modpoll -m rtu -b 38400 -a 31 -r 3 -c 1 -p even -t 4 /dev/ttySC0 0
FC15: Write Multiple
modpoll -m rtu -b 38400 -a 31 -p even -t 0 /dev/ttySC0 1 1 1 1 1
modpoll -m rtu -b 38400 -a 31 -p even -t 0 /dev/ttySC0 0 0 0 0 0
FC16: Write Multiple Registers
modpoll -m rtu -b 38400 -a 31 -p even -t 4 /dev/ttySC0 255 500 300
modpoll -m rtu -b 38400 -a 31 -p even -t 4 /dev/ttySC0 0 0 0
PYTHON
Código:
from pymodbus.client import ModbusSerialClient
# Client
serial_port = '/dev/ttySC0'
baud_rate = 38400
unit_id = 31
# FC1: Read Coil Status
def read_coil(client, address, quantity):
result = client.read_coils(address, quantity, unit_id)
if not result.isError():
print(f"Successfully FC1 read coils: %s" % result.bits)
else:
print(f"Failed FC1 to read coils from address {address}")
# FC2: Read Input Status
def read_input_status(client, address, quantity):
result = client.read_discrete_inputs(address, quantity, unit_id)
if not result.isError():
print(f"Successfully FC2 read: %s" % result.bits)
else:
print(f"Failed FC2 to read from address {address}")
# FC3: Read Holding Registers
def read_holding_register(client, address, quantity):
result = client.read_holding_registers(address, quantity, unit_id)
if not result.isError():
print(f"Successfully FC3 read: %s" % result.registers)
else:
print(f"Failed FC3 to read from address {address}")
# FC4: Read Input Registers
def read_input_register(client, address, quantity):
result = client.read_input_registers(address, quantity, unit_id)
if not result.isError():
print(f"Successfully FC4 read: %s" % result.registers)
else:
print(f"Failed FC4 to read from address {address}")
# FC5: Write Single Coil
def write_coil(client, address, value):
result = client.write_coil(address, value, unit_id)
if not result.isError():
print(f"Successfully FC5 wrote value {value} to coil address {address}")
else:
print(f"Failed FC5 to write value to coil address {address}")
# FC6: Write Single Register
def write_register(client, address, value):
result = client.write_register(address, value, unit_id)
if not result.isError():
print(f"Successfully FC6 wrote value {value} to coil address {address}")
else:
print(f"Failed FC6 to write value to coil address {address}")
# FC15: Write Multiple
def write_multiple_coils(client, address, value):
result = client.write_coils(address, value, unit_id)
if not result.isError():
print(f"Successfully FC15 wrote value {value} to coil address {address}")
else:
print(f"Failed FC15 to write value to coil address {address}")
# FC16: Write Multiple Registers
def write_multiple_registers(client, address, value):
result = client.write_registers(address, value, unit_id)
if not result.isError():
print(f"Successfully FC16 wrote value {value} to coil address {address}")
else:
print(f"Failed FC16 to write value to coil address {address}")
client = ModbusSerialClient(method='rtu', port=serial_port, baudrate=baud_rate, stopbits=1, bytesize=8, parity='E')
if client.connect():
# FC1: Read Coil Status
read_coil(client, 0, 5)
# FC2: Read Input Status
read_input_status(client, 0, 7)
# FC3: Read Holding Registers
read_holding_register(client, 0, 3)
# FC4: Read Input Registers
read_input_register(client, 0, 6)
# FC5: Write Single Coil
write_coil(client, 5, True)
write_coil(client, 5, False)
# FC6: Write Single Register
write_register(client, 2, 200)
write_register(client, 2, 0)
# FC15: Write Multiple
write_multiple_coils(client, 0, [True,True,True,True,True])
write_multiple_coils(client, 0, [False,False,False,False,False])
# FC16: Write Multiple Registers
write_multiple_registers(client, 0, [255,500,300])
write_multiple_registers(client, 0, [0,0,0])
client.close()
else:
print(f"Failed to connect to Modbus RTU on {serial_port}")
Ejecución: python3 modbus_example.py
C++
Código:
#include <iostream>
#include <modbus/modbus.h>
// FC1: Read Coil Status
void read_coil(modbus_t *ctx, int address, int quantity) {
uint8_t *bits = new uint8_t[quantity];
int rc = modbus_read_bits(ctx, address, quantity, bits);
if (rc >= 0) {
std::cout << "Successfully FC1 read coils:";
for (int i = 0; i < quantity; ++i) {
std::cout << " " << (int)bits[i];
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC1 to read coils from address " << address << std::endl;
}
delete[] bits;
}
// FC2: Read Input Status
void read_input_status(modbus_t *ctx, int address, int quantity) {
uint8_t *bits = new uint8_t[quantity];
int rc = modbus_read_input_bits(ctx, address, quantity, bits);
if (rc >= 0) {
std::cout << "Successfully FC2 read:";
for (int i = 0; i < quantity; ++i) {
std::cout << " " << (int)bits[i];
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC2 to read from address " << address << std::endl;
}
delete[] bits;
}
// FC3: Read Holding Registers
void read_holding_register(modbus_t *ctx, int address, int quantity) {
uint16_t *registers = new uint16_t[quantity];
int rc = modbus_read_registers(ctx, address, quantity, registers);
if (rc >= 0) {
std::cout << "Successfully FC3 read:";
for (int i = 0; i < quantity; ++i) {
std::cout << " " << registers[i];
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC3 to read from address " << address << std::endl;
}
delete[] registers;
}
// FC4: Read Input Registers
void read_input_register(modbus_t *ctx, int address, int quantity) {
uint16_t *registers = new uint16_t[quantity];
int rc = modbus_read_input_registers(ctx, address, quantity, registers);
if (rc >= 0) {
std::cout << "Successfully FC4 read:";
for (int i = 0; i < quantity; ++i) {
std::cout << " " << registers[i];
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC4 to read from address " << address << std::endl;
}
delete[] registers;
}
// FC5: Write Single Coil
void write_coil(modbus_t *ctx, int address, int value) {
int rc = modbus_write_bit(ctx, address, value);
if (rc >= 0) {
std::cout << "Successfully FC5 wrote value " << value << " to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC5 to write value to coil address " << address << std::endl;
}
}
// FC6: Write Single Register
void write_register(modbus_t *ctx, int address, int value) {
int rc = modbus_write_register(ctx, address, value);
if (rc >= 0) {
std::cout << "Successfully FC6 wrote value " << value << " to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC6 to write value to coil address " << address << std::endl;
}
}
// FC15: Write Multiple
void write_multiple_coils(modbus_t *ctx, int address, int quantity, uint8_t *values) {
int rc = modbus_write_bits(ctx, address, quantity, values);
if (rc >= 0) {
std::cout << "Successfully FC15 wrote values to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC15 to write values to coil address " << address << std::endl;
}
}
// FC16: Write Multiple Registers
void write_multiple_registers(modbus_t *ctx, int address, int quantity, uint16_t *values) {
int rc = modbus_write_registers(ctx, address, quantity, values);
if (rc >= 0) {
std::cout << "Successfully FC16 wrote values to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC16 to write values to coil address " << address << std::endl;
}
}
int main() {
const char *serial_port = "/dev/ttySC0";
int baud_rate = 38400;
int unit_id = 31;
modbus_t *ctx = modbus_new_rtu(serial_port, baud_rate, 'E', 8, 1);
if (ctx == NULL) {
std::cerr << "Failed to create Modbus context." << std::endl;
return 1;
}
modbus_set_slave(ctx, unit_id); // Establecer el identificador del esclavo
if (modbus_connect(ctx) == -1) {
std::cerr << "Failed to connect to Modbus RTU on " << serial_port << std::endl;
modbus_free(ctx);
return 1;
}
// FC1: Read Coil Status
read_coil(ctx, 0, 5);
// FC2: Read Input Status
read_input_status(ctx, 0, 7);
// FC3: Read Holding Registers
read_holding_register(ctx, 0, 3);
// FC4: Read Input Registers
read_input_register(ctx, 0, 6);
// FC5: Write Single Coil
write_coil(ctx, 5, 1);
write_coil(ctx, 5, 0);
// FC6: Write Single Register
write_register(ctx, 2, 200);
write_register(ctx, 2, 0);
// FC15: Write Multiple
uint8_t multiple_coils[] = {1, 1, 1, 1, 1};
write_multiple_coils(ctx, 0, 5, multiple_coils);
uint8_t multiple_coils_off[] = {0, 0, 0, 0, 0};
write_multiple_coils(ctx, 0, 5, multiple_coils_off);
// FC16: Write Multiple Registers
uint16_t multiple_registers[] = {255, 500, 300};
write_multiple_registers(ctx, 0, 3, multiple_registers);
uint16_t multiple_registers_off[] = {0, 0, 0};
write_multiple_registers(ctx, 0, 3, multiple_registers_off);
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
Compilación: g++ -o modbus_example modbus_example.cpp -lmodbus
Ejecución: ./modbus_example
C
Código:
#include <stdio.h>
#include <stdlib.h>
#include <modbus/modbus.h>
#include <errno.h>
#define SERIAL_PORT "/dev/ttySC0"
#define BAUD_RATE 38400
#define UNIT_ID 31
void read_coil(modbus_t *ctx, int address, int quantity) {
uint8_t tab_rq_bits[quantity];
int rc;
rc = modbus_read_bits(ctx, address, quantity, tab_rq_bits);
if (rc != -1) {
printf("Successfully FC1 read coils: ");
for (int i = 0; i < quantity; i++) {
printf("%d ", tab_rq_bits[i]);
}
printf("\n");
} else {
printf("Failed FC1 to read coils from address %d\n", address);
}
}
void read_input_status(modbus_t *ctx, int address, int quantity) {
uint8_t tab_rq_bits[quantity];
int rc;
rc = modbus_read_input_bits(ctx, address, quantity, tab_rq_bits);
if (rc != -1) {
printf("Successfully FC2 read: ");
for (int i = 0; i < quantity; i++) {
printf("%d ", tab_rq_bits[i]);
}
printf("\n");
} else {
printf("Failed FC2 to read from address %d\n", address);
}
}
void read_holding_register(modbus_t *ctx, int address, int quantity) {
uint16_t tab_reg[quantity];
int rc;
rc = modbus_read_registers(ctx, address, quantity, tab_reg);
if (rc != -1) {
printf("Successfully FC3 read: ");
for (int i = 0; i < quantity; i++) {
printf("%d ", tab_reg[i]);
}
printf("\n");
} else {
printf("Failed FC3 to read from address %d\n", address);
}
}
void read_input_register(modbus_t *ctx, int address, int quantity) {
uint16_t tab_reg[quantity];
int rc;
rc = modbus_read_input_registers(ctx, address, quantity, tab_reg);
if (rc != -1) {
printf("Successfully FC4 read: ");
for (int i = 0; i < quantity; i++) {
printf("%d ", tab_reg[i]);
}
printf("\n");
} else {
printf("Failed FC4 to read from address %d\n", address);
}
}
void write_coil(modbus_t *ctx, int address, int value) {
int rc;
rc = modbus_write_bit(ctx, address, value);
if (rc != -1) {
printf("Successfully FC5 wrote value %d to coil address %d\n", value, address);
} else {
printf("Failed FC5 to write value to coil address %d\n", address);
}
}
void write_register(modbus_t *ctx, int address, int value) {
int rc;
rc = modbus_write_register(ctx, address, value);
if (rc != -1) {
printf("Successfully FC6 wrote value %d to coil address %d\n", value, address);
} else {
printf("Failed FC6 to write value to coil address %d\n", address);
}
}
void write_multiple_coils(modbus_t *ctx, int address, int quantity, uint8_t *values) {
int rc;
rc = modbus_write_bits(ctx, address, quantity, values);
if (rc != -1) {
printf("Successfully FC15 wrote values to coil address %d\n", address);
} else {
printf("Failed FC15 to write values to coil address %d\n", address);
}
}
void write_multiple_registers(modbus_t *ctx, int address, int quantity, uint16_t *values) {
int rc;
rc = modbus_write_registers(ctx, address, quantity, values);
if (rc != -1) {
printf("Successfully FC16 wrote values to coil address %d\n", address);
} else {
printf("Failed FC16 to write values to coil address %d\n", address);
}
}
int main() {
modbus_t *ctx;
int rc;
ctx = modbus_new_rtu(SERIAL_PORT, BAUD_RATE, 'E', 8, 1);
if (ctx == NULL) {
fprintf(stderr, "Unable to create the libmodbus context\n");
return 1;
}
modbus_set_slave(ctx, UNIT_ID);
rc = modbus_connect(ctx);
if (rc == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return 1;
}
// FC1: Read Coil Status
read_coil(ctx, 0, 5);
// FC2: Read Input Status
read_input_status(ctx, 0, 7);
// FC3: Read Holding Registers
read_holding_register(ctx, 0, 3);
// FC4: Read Input Registers
read_input_register(ctx, 0, 6);
// FC5: Write Single Coil
write_coil(ctx, 5, 1);
write_coil(ctx, 5, 0);
// FC6: Write Single Register
write_register(ctx, 2, 200);
write_register(ctx, 2, 0);
// FC15: Write Multiple
uint8_t coil_values[] = {1, 1, 1, 1, 1};
write_multiple_coils(ctx, 0, 5, coil_values);
uint8_t coil_values_off[] = {0, 0, 0, 0, 0};
write_multiple_coils(ctx, 0, 5, coil_values_off);
// FC16: Write Multiple Registers
uint16_t reg_values[] = {255, 500, 300};
write_multiple_registers(ctx, 0, 3, reg_values);
uint16_t reg_values_off[] = {0, 0, 0};
write_multiple_registers(ctx, 0, 3, reg_values_off);
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
Compilación: gcc -o modbus_example modbus_example.c -lmodbus
Ejecución: ./modbus_example
NODE-RED
Tras ejecutar node-red-start, copia e importa este código JSON:
Se importará algo como esto:

Después, despliega el flujo y, con los botones de inserción, podrás probar este protocolo.
BASH + MODPOLL
FC1: Read Coil Status
modpoll -m tcp -c 5 -t 0 10.10.10.4
FC2: Read Input Status
modpoll -m tcp -c 7 -t 1 10.10.10.4
FC3: Read Holding Registers
modpoll -c 3 -t 4 10.10.10.4
FC4: Read Input Registers
modpoll -c 6 -t 3 10.10.10.4
FC5: Write Single Coil
modpoll -t 0 10.10.10.4 1
modpoll -t 0 10.10.10.4 0
FC6: Write Single Register
modpoll -t 4 10.10.10.4 1000
modpoll -t 4 10.10.10.4 200
modpoll -t 4 10.10.10.4 0
FC15: Write Multiple
modpoll -t 0 10.10.10.4 1 1 1 1 1
modpoll -t 0 10.10.10.4 0 0 0 0 0
FC16: Write Multiple Registers
modpoll -t 4 10.10.10.4 255 500 300
modpoll -t 4 10.10.10.4 0 0 0
PYTHON
Código:
from pymodbus.client import ModbusTcpClient
# Client
tcp_host = '10.10.10.4'
tcp_port = 502
# FC1: Read Coil Status
def read_coil(client, address, quantity):
result = client.read_coils(address, quantity)
if not result.isError():
print(f"Successfully FC1 read coils: %s" % result.bits)
else:
print(f"Failed FC1 to read coils from address {address}")
# FC2: Read Input Status
def read_input_status(client, address, quantity):
result = client.read_discrete_inputs(address, quantity)
if not result.isError():
print(f"Successfully FC2 read: %s" % result.bits)
else:
print(f"Failed FC2 to read from address {address}")
# FC3: Read Holding Registers
def read_holding_register(client, address, quantity):
result = client.read_holding_registers(address, quantity)
if not result.isError():
print(f"Successfully FC3 read: %s" % result.registers)
else:
print(f"Failed FC3 to read from address {address}")
# FC4: Read Input Registers
def read_input_register(client, address, quantity):
result = client.read_input_registers(address, quantity)
if not result.isError():
print(f"Successfully FC4 read: %s" % result.registers)
else:
print(f"Failed FC4 to read from address {address}")
# FC5: Write Single Coil
def write_coil(client, address, value):
result = client.write_coil(address, value)
if not result.isError():
print(f"Successfully FC5 wrote value {value} to coil address {address}")
else:
print(f"Failed FC5 to write value to coil address {address}")
# FC6: Write Single Register
def write_register(client, address, value):
result = client.write_register(address, value)
if not result.isError():
print(f"Successfully FC6 wrote value {value} to coil address {address}")
else:
print(f"Failed FC6 to write value to coil address {address}")
# FC15: Write Multiple
def write_multiple_coils(client, address, value):
result = client.write_coils(address, value)
if not result.isError():
print(f"Successfully FC15 wrote value {value} to coil address {address}")
else:
print(f"Failed FC15 to write value to coil address {address}")
# FC16: Write Multiple Registers
def write_multiple_registers(client, address, value):
result = client.write_registers(address, value)
if not result.isError():
print(f"Successfully FC16 wrote value {value} to coil address {address}")
else:
print(f"Failed FC16 to write value to coil address {address}")
client = ModbusTcpClient(host=tcp_host, port=tcp_port)
if client.connect():
# FC1: Read Coil Status
read_coil(client, 0, 5)
# FC2: Read Input Status
read_input_status(client, 0, 7)
# FC3: Read Holding Registers
read_holding_register(client, 0, 3)
# FC4: Read Input Registers
read_input_register(client, 0, 6)
# FC5: Write Single Coil
write_coil(client, 5, True)
write_coil(client, 5, False)
# FC6: Write Single Register
write_register(client, 2, 200)
write_register(client, 2, 0)
# FC15: Write Multiple
write_multiple_coils(client, 0, [True,True,True,True,True])
write_multiple_coils(client, 0, [False,False,False,False,False])
# FC16: Write Multiple Registers
write_multiple_registers(client, 0, [255,500,300])
write_multiple_registers(client, 0, [0,0,0])
client.close()
else:
print(f"Failed to connect to Modbus TCP on {tcp_host}")
Ejecución: python exemple_modbus.py
C++
Código:
#include <iostream>
#include <modbus/modbus.h>
// Modbus context
modbus_t *ctx;
// TCP connection parameters
const char *tcp_host = "10.10.10.4";
const int tcp_port = 502;
// Function to read coil status
void read_coil(int address, int quantity) {
uint8_t tab_coils[quantity];
if (modbus_read_bits(ctx, address, quantity, tab_coils) == quantity) {
std::cout << "Successfully FC1 read coils: ";
for (int i = 0; i < quantity; ++i) {
std::cout << static_cast<int>(tab_coils[i]) << " ";
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC1 to read coils from address " << address << std::endl;
}
}
// Function to read input status
void read_input_status(int address, int quantity) {
uint8_t tab_input[quantity];
if (modbus_read_input_bits(ctx, address, quantity, tab_input) == quantity) {
std::cout << "Successfully FC2 read: ";
for (int i = 0; i < quantity; ++i) {
std::cout << static_cast<int>(tab_input[i]) << " ";
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC2 to read from address " << address << std::endl;
}
}
// Function to read holding registers
void read_holding_register(int address, int quantity) {
uint16_t tab_registers[quantity];
if (modbus_read_registers(ctx, address, quantity, tab_registers) == quantity) {
std::cout << "Successfully FC3 read: ";
for (int i = 0; i < quantity; ++i) {
std::cout << tab_registers[i] << " ";
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC3 to read from address " << address << std::endl;
}
}
// Function to read input registers
void read_input_register(int address, int quantity) {
uint16_t tab_input_registers[quantity];
if (modbus_read_input_registers(ctx, address, quantity, tab_input_registers) == quantity) {
std::cout << "Successfully FC4 read: ";
for (int i = 0; i < quantity; ++i) {
std::cout << tab_input_registers[i] << " ";
}
std::cout << std::endl;
} else {
std::cerr << "Failed FC4 to read from address " << address << std::endl;
}
}
// Function to write single coil
void write_coil(int address, int value) {
if (modbus_write_bit(ctx, address, value) != -1) {
std::cout << "Successfully FC5 wrote value " << value << " to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC5 to write value to coil address " << address << std::endl;
}
}
// Function to write single register
void write_register(int address, int value) {
if (modbus_write_register(ctx, address, value) != -1) {
std::cout << "Successfully FC6 wrote value " << value << " to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC6 to write value to coil address " << address << std::endl;
}
}
// Function to write multiple coils
void write_multiple_coils(int address, int quantity, uint8_t *value) {
if (modbus_write_bits(ctx, address, quantity, value) != -1) {
std::cout << "Successfully FC15 wrote value to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC15 to write value to coil address " << address << std::endl;
}
}
// Function to write multiple registers
void write_multiple_registers(int address, int quantity, uint16_t *value) {
if (modbus_write_registers(ctx, address, quantity, value) != -1) {
std::cout << "Successfully FC16 wrote value to coil address " << address << std::endl;
} else {
std::cerr << "Failed FC16 to write value to coil address " << address << std::endl;
}
}
int main() {
// Create a Modbus context
ctx = modbus_new_tcp(tcp_host, tcp_port);
if (ctx == nullptr) {
std::cerr << "Failed to create the Modbus context" << std::endl;
return 1;
}
// Connect to the Modbus server
if (modbus_connect(ctx) == -1) {
std::cerr << "Failed to connect to Modbus TCP on " << tcp_host << std::endl;
modbus_free(ctx);
return 1;
}
// Perform Modbus operations
read_coil(0, 5);
read_input_status(0, 7);
read_holding_register(0, 3);
read_input_register(0, 6);
write_coil(5, 1);
write_coil(5, 0);
write_register(2, 200);
write_register(2, 0);
uint8_t value_coils[] = {1, 1, 1, 1, 1};
write_multiple_coils(0, 5, value_coils);
uint16_t value_registers[] = {255, 500, 300};
write_multiple_registers(0, 3, value_registers);
// Close the Modbus connection and free the context
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
Compilación: g++ -o modbus_example modbus_example.cpp -lmodbus
Ejecución: ./modbus_example
C
Código:
#include <stdio.h>
#include <stdlib.h>
#include <modbus/modbus.h>
#include <errno.h>
#define SERVER_ID 1
#define ADDR_COILS 0
#define ADDR_DISCRETE_INPUTS 0
#define ADDR_HOLDING_REGISTERS 0
#define ADDR_INPUT_REGISTERS 0
int main() {
modbus_t *ctx;
uint16_t tab_reg[32];
int rc;
ctx = modbus_new_tcp("10.10.10.4", 502);
if (ctx == NULL) {
fprintf(stderr, "Unable to allocate libmodbus context\n");
return -1;
}
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
// FC1: Read Coil Status
rc = modbus_read_bits(ctx, ADDR_COILS, 5, tab_reg);
if (rc >= 0) {
printf("Successfully FC1 read coils: ");
for (int i = 0; i < 5; i++)
printf("%d ", tab_reg[i]);
printf("\n");
} else {
fprintf(stderr, "Failed FC1 to read coils: %s\n", modbus_strerror(errno));
}
// FC2: Read Input Status
rc = modbus_read_input_bits(ctx, ADDR_DISCRETE_INPUTS, 7, tab_reg);
if (rc >= 0) {
printf("Successfully FC2 read: ");
for (int i = 0; i < 7; i++)
printf("%d ", tab_reg[i]);
printf("\n");
} else {
fprintf(stderr, "Failed FC2 to read: %s\n", modbus_strerror(errno));
}
// FC3: Read Holding Registers
rc = modbus_read_registers(ctx, ADDR_HOLDING_REGISTERS, 3, tab_reg);
if (rc >= 0) {
printf("Successfully FC3 read: ");
for (int i = 0; i < 3; i++)
printf("%d ", tab_reg[i]);
printf("\n");
} else {
fprintf(stderr, "Failed FC3 to read: %s\n", modbus_strerror(errno));
}
// FC4: Read Input Registers
rc = modbus_read_input_registers(ctx, ADDR_INPUT_REGISTERS, 6, tab_reg);
if (rc >= 0) {
printf("Successfully FC4 read: ");
for (int i = 0; i < 6; i++)
printf("%d ", tab_reg[i]);
printf("\n");
} else {
fprintf(stderr, "Failed FC4 to read: %s\n", modbus_strerror(errno));
}
// FC5: Write Single Coil
rc = modbus_write_bit(ctx, 5, 1);
if (rc >= 0) {
printf("Successfully FC5 wrote value 1 to coil address 5\n");
} else {
fprintf(stderr, "Failed FC5 to write: %s\n", modbus_strerror(errno));
}
rc = modbus_write_bit(ctx, 5, 0);
if (rc >= 0) {
printf("Successfully FC5 wrote value 0 to coil address 5\n");
} else {
fprintf(stderr, "Failed FC5 to write: %s\n", modbus_strerror(errno));
}
// FC6: Write Single Register
rc = modbus_write_register(ctx, 2, 200);
if (rc >= 0) {
printf("Successfully FC6 wrote value 200 to register address 2\n");
} else {
fprintf(stderr, "Failed FC6 to write: %s\n", modbus_strerror(errno));
}
rc = modbus_write_register(ctx, 2, 0);
if (rc >= 0) {
printf("Successfully FC6 wrote value 0 to register address 2\n");
} else {
fprintf(stderr, "Failed FC6 to write: %s\n", modbus_strerror(errno));
}
// FC15: Write Multiple
uint8_t tab_bits[5] = {1, 1, 1, 1, 1};
rc = modbus_write_bits(ctx, 0, 5, tab_bits);
if (rc >= 0) {
printf("Successfully FC15 wrote value 1 to coil address 0-4\n");
} else {
fprintf(stderr, "Failed FC15 to write: %s\n", modbus_strerror(errno));
}
uint8_t tab_bits_off[5] = {0, 0, 0, 0, 0};
rc = modbus_write_bits(ctx, 0, 5, tab_bits_off);
if (rc >= 0) {
printf("Successfully FC15 wrote value 0 to coil address 0-4\n");
} else {
fprintf(stderr, "Failed FC15 to write: %s\n", modbus_strerror(errno));
}
// FC16: Write Multiple Registers
uint16_t tab_registers[3] = {255, 500, 300};
rc = modbus_write_registers(ctx, 0, 3, tab_registers);
if (rc >= 0) {
printf("Successfully FC16 wrote values to register address 0-2\n");
} else {
fprintf(stderr, "Failed FC16 to write: %s\n", modbus_strerror(errno));
}
uint16_t tab_registers_off[3] = {0, 0, 0};
rc = modbus_write_registers(ctx, 0, 3, tab_registers_off);
if (rc >= 0) {
printf("Successfully FC16 wrote values 0 to register address 0-2\n");
} else {
fprintf(stderr, "Failed FC16 to write: %s\n", modbus_strerror(errno));
}
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
Compilación: gcc -o modbus_example modbus_example.c -lmodbus
Ejecución: ./modbus_example




