Skip to content

Getting started

This library speaks MELSEC serial MC Protocol from host tools and MCU firmware. The core client is transport-agnostic, so you can drive it from a blocking host serial port or from your board UART layer.

Prerequisites

Requirement Notes
C++ standard Strict ISO C++17 for PlatformIO packages, the repository CMake build, tests, CLI, and examples.
Build system PlatformIO for MCU projects, or CMake for host examples and local integration.
Supported MCU targets ESP32 and RP2040. Arduino Mega 2560 and other AVR/8-bit targets are not supported.
Serial interface RS-232C or RS-485 hardware that matches your PLC serial module.
PLC settings Baud rate, parity, stop bits, frame type, and station number must match the PLC module settings.

Install

For PlatformIO, add the library package:

[env:your-board]
lib_deps =
    fa-yoshinobu/mcprotocol-serial-cpp
build_unflags =
    -std=gnu++11
    -std=gnu++14
build_flags =
    -std=c++17

This package is the MCU-oriented, transport-agnostic core. It compiles client.cpp and codec.cpp; it does not compile host_sync.cpp or a Windows/POSIX serial backend. Use MelsecSerialClient with your UART or simulated transport in PlatformIO.

For the host-only PosixSyncClient, vendor the source repository in a CMake project and link the host-enabled target:

add_subdirectory(external/plc-comm-mcprotocol-serial-cpp)
target_link_libraries(your_app PRIVATE mcprotocol_serial)

PlatformIO examples

Run the maintained PlatformIO environments with pio run -e <env>.

Purpose Environments
Host / simulated examples native-example, native-example-ultra-minimal
RP2040 / Raspberry Pi Pico rpipico-arduino-example, rpipico-arduino-uart-example, rpipico-arduino-example-ultra-minimal
ESP32-C3 DevKitM-1 esp32-c3-devkitm-1-example, esp32-c3-devkitm-1-uart-example, esp32-c3-devkitm-1-example-ultra-minimal

The normal MCU examples use a reduced footprint profile. The ultra-minimal examples keep only the smallest batch read/write path and reduce fixed buffers for small firmware builds. Existing Mega/AVR projects must migrate to a supported ESP32 target or carry an unsupported downstream port; the distributed package and CI do not validate AVR builds.

Choose your PLC profile

PlcProfile is required. There is no default profile for live communication. Use plc_profile_display_name(profile) when you need a UI label.

Canonical profile Display name Hardware API selector
melsec:iq-r MELSEC iQ-R MELSEC iQ-R serial modules PlcProfile::MelsecIqR
melsec:iq-l MELSEC iQ-L MELSEC iQ-L serial modules PlcProfile::MelsecIqL
melsec:iq-f MELSEC iQ-F MELSEC iQ-F / FX5 serial paths PlcProfile::MelsecIqF
melsec:qcpu MELSEC-Q MELSEC-Q serial modules PlcProfile::MelsecQ
melsec:lcpu MELSEC-L MELSEC-L serial modules PlcProfile::MelsecL
melsec:qna MELSEC QnA MELSEC QnA-compatible targets PlcProfile::MelsecQnA
melsec:ana-anu MELSEC AnA/AnU MELSEC AnA / AnU-compatible targets PlcProfile::MelsecAnAAnU
melsec:a MELSEC-A MELSEC-A-compatible targets PlcProfile::MelsecA
auto protocol = mcprotocol::serial::highlevel::make_c4_ascii_format4_protocol(
    mcprotocol::serial::PlcProfile::MelsecQ,
    mcprotocol::serial::SumCheckMode::Disabled,
    mcprotocol::serial::RouteConfig {mcprotocol::serial::HostStationRoute {}});

First read on a host

This CMake/source-tree example uses PosixSyncClient, explicit serial settings, make_c4_ascii_format4_protocol(..., RouteConfig {HostStationRoute {}}), and read_words("D100", words). The PlatformIO package does not contain the host facade implementation.

#include <array>
#include <cstdint>
#include <cstdio>

#include "mcprotocol_serial.hpp"

int main() {
  using mcprotocol::serial::HardwareFlowControl;
  using mcprotocol::serial::PlcProfile;
  using mcprotocol::serial::PosixSerialConfig;
  using mcprotocol::serial::PosixSyncClient;
  using mcprotocol::serial::SerialParity;
  using mcprotocol::serial::Status;
  using mcprotocol::serial::SumCheckMode;
  using mcprotocol::serial::highlevel::make_c4_ascii_format4_protocol;

  const PosixSerialConfig serial(
#if defined(_WIN32)
      "COM3",
#else
      "/dev/ttyUSB0",
#endif
      19200,
      8,
      1,
      SerialParity::Even,
      HardwareFlowControl::None);

  auto protocol = make_c4_ascii_format4_protocol(
      PlcProfile::MelsecQ,
      SumCheckMode::Disabled,
      mcprotocol::serial::RouteConfig {mcprotocol::serial::HostStationRoute {}});

  PosixSyncClient plc;
  Status status = plc.open(serial, protocol);
  if (!status.ok()) {
    std::fprintf(stderr, "open failed: %s\n", status.message);
    return 1;
  }

  std::array<std::uint16_t, 1> words {};
  status = plc.read_words("D100", words);
  if (!status.ok()) {
    std::fprintf(stderr, "read_words failed: %s\n", status.message);
    return 1;
  }

  std::printf("D100=0x%04X\n", words[0]);
  return 0;
}

Expected output shape:

D100=0x0000

The value depends on your PLC memory.

First read on an MCU

Start from the real-UART PlatformIO examples:

Board Example Default PLC UART
RP2040 / Raspberry Pi Pico platformio_rpipico_arduino_uart Serial1, TX 0, RX 1, 19200 / 8E1
ESP32-C3 DevKitM-1 platformio_esp32c3_arduino_uart Serial1, TX 7, RX 6, 19200 / 8E1

The pin numbers are sample defaults. Change them to match your actual board wiring and level shifter. The serial values in examples are also sample defaults. Match the actual PLC serial-module frame, baud rate, parity, stop bits, and station number before using them as validation settings.

Confirm success

  1. Your PLC serial module settings match the host or MCU serial settings exactly.
  2. The profile selected in code matches the target PLC family.
  3. The frame type configured in the PLC matches the helper you selected.
  4. The first read returns a Status where status.ok() is true.
  5. The returned word values match a memory range you can safely inspect.

If it does not work

Symptom Check
No response from the PLC Baud rate, parity, and stop bits must all match the PLC serial module DIP switch or parameter settings.
PLC error or framing error Check that the PLC module is configured for the same frame type and code mode.
RS-485 multi-drop does not answer Select the frame-specific route and the actual topology. Use a *StandardMultidropRoute for normal/1:n or a *MnMultidropRoute with the assigned SelfStationNo for m:n. Ensure station—and for 3C/4C, network and PC target—matches the serial module. For 4C, also verify the mandatory destination-module target. Use the explicit 1E PC target when 1E is selected.
MCU sample prints zeros or no values Verify the UART TX/RX pins and the TTL-to-RS-232C or RS-485 interface.
Wiring uncertainty See the shared MC Protocol Serial setup guide before changing software settings.