Skip to content

Commit

Permalink
add modbus.Master
Browse files Browse the repository at this point in the history
  • Loading branch information
MK16kawai committed Nov 11, 2024
1 parent 0e9b937 commit b665263
Show file tree
Hide file tree
Showing 10 changed files with 1,102 additions and 318 deletions.
607 changes: 536 additions & 71 deletions components/comm/include/maix_modbus.hpp

Large diffs are not rendered by default.

522 changes: 341 additions & 181 deletions components/comm/src/maix_modbus.cpp

Large diffs are not rendered by default.

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
maix_modbus_master Project based on MaixCDK
maix_modbus_loopback Project based on MaixCDK
====


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
id: maix_modbus_master
name: maix_modbus_master
id: maix_modbus_loopback
name: maix_modbus_loopback
name[zh]:
version: 1.0.0
#icon: assets/hello.png
Expand Down
File renamed without changes.
222 changes: 222 additions & 0 deletions examples/maix_modbus_loopback/main/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@

#include "maix_basic.hpp"
#include "main.h"
#include "maix_modbus.hpp"
#include "maix_pinmap.hpp"
#include <iomanip> // std::setw and std::setfill
#include <sstream> // std::stringstream
#include <thread> // std::thread

using namespace maix;
using namespace maix::comm;

/** MODE: RTU/TCP
* NOTE: RTU UART0(Slave) <--> UART1(Master)
*/
constexpr modbus::Mode MODE = modbus::Mode::RTU;
// constexpr modbus::Mode MODE = modbus::Mode::TCP;

/* slave cfg */
constexpr uint8_t REGISTERS_START_ADDRESS = 0x00;
constexpr uint32_t REGISTERS_NUMBER = 10;

/* rtu cfg */
constexpr uint32_t RTU_SLAVE_ID = 1;
constexpr int RTU_BAUDRATE = 115200;

/* tcp cfg */
constexpr int TCP_PORT = 5020;

int master_rtu_thread()
{
if(peripheral::pinmap::set_pin_function("A19", "UART1_TX") != err::Err::ERR_NONE) {
log::error("init uart1 failed!");
return -1;
}
if (peripheral::pinmap::set_pin_function("A18", "UART1_RX") != err::Err::ERR_NONE) {
log::error("init uart failed!");
return -1;
}

// modbus::set_master_debug(true);

modbus::MasterRTU master("/dev/ttyS1", RTU_BAUDRATE);

while (!app::need_exit()) {
// log::info("master thread running...");

std::vector<uint16_t> rt = master.read_holding_registers(RTU_SLAVE_ID, REGISTERS_NUMBER, REGISTERS_START_ADDRESS, 2000);
if (rt.empty())
continue;

std::stringstream ss;
ss << "Master read: ";
for (const auto& value : rt) {
ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << value << " ";
}
log::info(ss.str().c_str());
time::sleep(1);
}

return 0;
}

int slave_rtu_thread()
{
modbus::Registers cfg;
cfg.coils.start_address = REGISTERS_START_ADDRESS;
cfg.coils.size = REGISTERS_NUMBER;
cfg.discrete_inputs.start_address = REGISTERS_START_ADDRESS;
cfg.discrete_inputs.size = REGISTERS_NUMBER;
cfg.holding_registers.start_address = REGISTERS_START_ADDRESS;
cfg.holding_registers.size = REGISTERS_NUMBER;
cfg.input_registers.start_address = REGISTERS_START_ADDRESS;
cfg.input_registers.size = REGISTERS_NUMBER;

modbus::Slave slave(
modbus::Mode::RTU,
"/dev/ttyS0",
cfg,
RTU_BAUDRATE,
RTU_SLAVE_ID
);

while (!app::need_exit()) {
// log::info("slave thread running...");

auto rt = slave.receive(2000);
if (rt != err::Err::ERR_NONE)
continue;

modbus::RequestType type = slave.request_type();
if (type == modbus::RequestType::READ_HOLDING_REGISTERS) {
std::stringstream ss;
ss << "Slave update: ";
for (int i = 0; i < slave->nb_registers; ++i) {
slave->tab_registers[i]++;
ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << slave->tab_registers[i] << " ";
}
log::info(ss.str().c_str());
}

slave.reply();
}

return 0;
}

void rtu_loopback()
{
std::thread slave_th(slave_rtu_thread);
time::sleep_ms(500);
std::thread master_th(master_rtu_thread);

slave_th.join();
master_th.join();
}

int slave_tcp_thread()
{
modbus::Registers cfg;
cfg.coils.start_address = REGISTERS_START_ADDRESS;
cfg.coils.size = REGISTERS_NUMBER;
cfg.discrete_inputs.start_address = REGISTERS_START_ADDRESS;
cfg.discrete_inputs.size = REGISTERS_NUMBER;
cfg.holding_registers.start_address = REGISTERS_START_ADDRESS;
cfg.holding_registers.size = REGISTERS_NUMBER;
cfg.input_registers.start_address = REGISTERS_START_ADDRESS;
cfg.input_registers.size = REGISTERS_NUMBER;

modbus::Slave slave(
modbus::Mode::TCP,
"",
cfg,
0,
0,
TCP_PORT
);

while (!app::need_exit()) {
// log::info("slave thread running...");

auto rt = slave.receive(2000);
if (rt != err::Err::ERR_NONE)
continue;

modbus::RequestType type = slave.request_type();
if (type == modbus::RequestType::READ_HOLDING_REGISTERS) {
std::stringstream ss;
ss << "Slave update: ";
for (int i = 0; i < slave->nb_registers; ++i) {
slave->tab_registers[i]++;
ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << slave->tab_registers[i] << " ";
}
log::info(ss.str().c_str());
}

slave.reply();
}

return 0;
}

int master_tcp_thread()
{
// modbus::set_master_debug(true);

modbus::MasterTCP master(TCP_PORT);

while (!app::need_exit()) {
// log::info("master thread running...");

std::vector<uint16_t> rt = master.read_holding_registers("127.0.0.1", REGISTERS_NUMBER, REGISTERS_START_ADDRESS, 2000);
if (rt.empty())
continue;

std::stringstream ss;
ss << "Master read: ";
for (const auto& value : rt) {
ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << value << " ";
}
log::info(ss.str().c_str());
time::sleep(1);
}

return 0;
}


void tcp_loopback()
{
std::thread slave_th(slave_tcp_thread);
time::sleep_ms(500);
std::thread master_th(master_tcp_thread);

slave_th.join();
master_th.join();
}

int _main(int argc, char* argv[])
{

if constexpr (MODE == modbus::Mode::RTU) {
rtu_loopback();
} else {
tcp_loopback();
}

return 0;
}

int main(int argc, char* argv[])
{
// Catch signal and process
sys::register_default_signal_handle();

// Use CATCH_EXCEPTION_RUN_RETURN to catch exception,
// if we don't catch exception, when program throw exception, the objects will not be destructed.
// So we catch exception here to let resources be released(call objects' destructor) before exit.
CATCH_EXCEPTION_RUN_RETURN(_main, -1, argc, argv);
}


63 changes: 0 additions & 63 deletions examples/maix_modbus_master/main/src/main.cpp

This file was deleted.

0 comments on commit b665263

Please sign in to comment.