samples: add Modbus RTU client sample

Add Modbus RTU client sample.

Signed-off-by: Johann Fischer <j.fischer@phytec.de>
This commit is contained in:
Johann Fischer 2020-08-27 14:30:51 +02:00 committed by Carles Cufí
commit fef70aa494
6 changed files with 202 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(modbus-rtu-client)
target_sources(app PRIVATE src/main.c)

View file

@ -0,0 +1,58 @@
.. _modbus-rtu-client-sample:
Modbus RTU Client Sample
########################
Overview
********
This is a simple application demonstrating a Modbus RTU client implementation
in Zephyr RTOS.
Requirements
************
This sample has been tested with the nRF52840-DK and FRDM-K64F boards,
but it should work with any board that has a free UART interface.
RTU client example is running on an evaluation board and communicates
with another board that has been prepared according to the description
`modbus-rtu-server-sample`.
In addition to the evaluation board, an USB to RS-485 bus adapter and
a RS-485 shield are required. Shield converts the UART TX, RX signals to
RS-485 and does not need a specific overlay, an Arduino header compatible
shield like `joy-it RS-485 shield for Arduino`_ can be used.
The A+, B- lines of the RS-485 shield should be connected together.
Alternatively UART RX,TX signals of two boards can be connected crosswise.
Building and Running
********************
This sample can be found under
:zephyr_file:`samples/subsys/modbus/rtu_client` in the Zephyr tree.
The following commands build and flash RTU client sample.
.. zephyr-app-commands::
:zephyr-app: samples/subsys/modbus/rtu_client
:board: frdm_k64f
:goals: build flash
:compact:
The example communicates with the RTU server and lets the LEDs light up
one after the other.
.. code-block:: console
*** Booting Zephyr OS build zephyr-v2.3.0-1993-g07e8d80ae028 ***
[00:00:00.005,000] <inf> mb_rtu: RTU timeout 2005 us
[00:00:00.050,000] <inf> mbc_sample: WR|RD holding register:
48 00 65 00 6c 00 6c 00 6f 00 00 00 00 00 00 00 |H.e.l.l. o.......
[00:00:00.062,000] <inf> mbc_sample: Coils state 0x00
[00:00:00.864,000] <inf> mbc_sample: Coils state 0x07
.. _`joy-it RS-485 shield for Arduino`: https://joy-it.net/en/products/ARD-RS485

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2020 Phytec Messtechnik GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
&arduino_serial {
status = "okay";
modbus0 {
compatible = "zephyr,modbus-serial";
label = "MODBUS";
status = "okay";
};
};

View file

@ -0,0 +1,8 @@
CONFIG_LOG=y
CONFIG_GPIO=y
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=n
CONFIG_MODBUS_RTU=y
CONFIG_MODBUS_RTU_ROLE_CLIENT=y

View file

@ -0,0 +1,6 @@
sample:
name: Modbus RTU Client Sample
tests:
sample.modbus.rtu_client:
tags: uart modbus
depends_on: gpio, arduino_serial

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2020 PHYTEC Messtechnik GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <sys/util.h>
#include <drivers/gpio.h>
#include <modbus/modbus_rtu.h>
#include <logging/log.h>
LOG_MODULE_REGISTER(mbc_sample, LOG_LEVEL_INF);
#define RTU_IFACE 0
static int init_modbus_client(void)
{
const uint32_t mb_rtu_br = 19200;
const uint32_t rsp_timeout = 50000;
return mb_rtu_cfg_client(RTU_IFACE, mb_rtu_br, UART_CFG_PARITY_NONE,
rsp_timeout, false);
}
void main(void)
{
uint16_t holding_reg[8] = {'H', 'e', 'l', 'l', 'o'};
const uint8_t coil_qty = 3;
uint8_t coil[1] = {0};
const int32_t sleep = 250;
static uint8_t node = 1;
int err;
if (init_modbus_client()) {
LOG_ERR("Modbus RTU client initialization failed");
return;
}
err = mb_rtu_write_holding_regs(RTU_IFACE, node, 0, holding_reg,
ARRAY_SIZE(holding_reg));
if (err != 0) {
LOG_ERR("FC16 failed");
return;
}
err = mb_rtu_read_holding_regs(RTU_IFACE, node, 0, holding_reg,
ARRAY_SIZE(holding_reg));
if (err != 0) {
LOG_ERR("FC03 failed with %d", err);
return;
}
LOG_HEXDUMP_INF(holding_reg, sizeof(holding_reg),
"WR|RD holding register:");
while (true) {
uint16_t addr = 0;
err = mb_rtu_read_coils(RTU_IFACE, node, 0, coil, coil_qty);
if (err != 0) {
LOG_ERR("FC01 failed with %d", err);
return;
}
LOG_INF("Coils state 0x%02x", coil[0]);
err = mb_rtu_write_coil(RTU_IFACE, node, addr++, true);
if (err != 0) {
LOG_ERR("FC05 failed with %d", err);
return;
}
k_msleep(sleep);
err = mb_rtu_write_coil(RTU_IFACE, node, addr++, true);
if (err != 0) {
LOG_ERR("FC05 failed with %d", err);
return;
}
k_msleep(sleep);
err = mb_rtu_write_coil(RTU_IFACE, node, addr++, true);
if (err != 0) {
LOG_ERR("FC05 failed with %d", err);
return;
}
k_msleep(sleep);
err = mb_rtu_read_coils(RTU_IFACE, node, 0, coil, coil_qty);
if (err != 0) {
LOG_ERR("FC01 failed with %d", err);
return;
}
LOG_INF("Coils state 0x%02x", coil[0]);
coil[0] = 0;
err = mb_rtu_write_coils(RTU_IFACE, node, 0, coil, coil_qty);
if (err != 0) {
LOG_ERR("FC15 failed with %d", err);
return;
}
k_msleep(sleep);
}
}