— Human-Readable Communication for Noisy & Low-Bandwidth Links

(Module 2 · Modbus Serial Protocols — The Original Workhorses)


Reading roadmap

§TopicBread-and-ButterDeep-Dive Nuggets
6.1Why Modbus ASCII was inventedDial-up modems, radio, teletypeHow 1970-era acoustic couplers shaped the frame
6.2Frame anatomyStart “:”, ASCII hex, CR LF, LRCByte-by-byte with ASCII→binary mapping
6.3Longitudinal Redundancy Check (LRC)8-bit two’s-complement checksumManual example + table-less C & Python code
6.4Timing & throughput1-second inter-frame vs RTU’s 3.5-charBandwidth model & optimisation levers
6.5ASCII vs RTU head-to-headPros, cons, mixed networksWhen to tunnel RTU vs convert in gateway
6.6Worked examplesRead & write frames with live decodeWireshark TCP-over-serial capture, RealTerm log
6.7Implementation patternsUART config, buffers, error handlingConverting ASCII↔RTU inside microcontroller
6.8Troubleshooting cookbookClassic field failures & fixes“Ghost colon”, CR LF polarity, HEX typo traps

(diagram & listing placeholders appear as [Fig-6-x] / Listing x)


6.1 Why Modbus ASCII Exists

  1. Human readability
    Every data byte is transmitted as two high-ASCII characters (0‥9 A‥F). A technician armed with only a dumb serial terminal in 1984 could read frames and type commands by hand.
  2. Character-oriented framing
    Start sentinel : and terminator CR LF remove dependence on inter-byte silence. Perfect for:
    • acoustic-coupler modems (300 Bd)
    • half-duplex UHF/VHF radios with unknown turn-around delay
    • RS-232 links that insert variable gaps (UART FIFOs, SCADA pollers)
  3. Noise resilience on mutilated channels
    ASCII hex doubles the byte length but halves the probability that a single flipped bit converts one legal byte into another legal byte.

6.2 Frame Anatomy — Byte-for-Byte Breakdown

Mnemonic “S A F D … D LRC E
Start : Address Function Data … Data Checksum End(CR LF)

OrderElementLength (ASCII chars)Purpose
Start: (3A h)Marks absolute frame start
Slave Addr2Hex of 0–247 (00–F7)
Function Code2Hex of FC (01–06, 0F, 10…)
DataN×2Parameters or payload
LRC28-bit checksum (two’s complement)
End0D 0A (CR LF)Frame terminator

[Fig-6-1] Colour-coded ASCII frame -> binary field map.

6.2.1 ASCII → Binary Mapping

Every ASCII pair (3F) == one binary byte (0x3F).
Total binary data per register = 2 (bytes) × 2 = 4 ASCII characters.

BinaryASCII HighASCII LowComment
0x11'1' '1'Slave address 17
0x03'0' '3'Function 03

6.3 Longitudinal Redundancy Check (LRC)

6.3.1 Definition

LRC = Two’s-complement (negated sum) of every binary byte from Slave Addr → Data inclusive. LRC=[−∑i=1nbytei]8 bit\text{LRC} = \left[ -\sum_{i=1}^{n} \text{byte}_i \right]_{8\,\text{bit}}

6.3.2 Hand Calculation Walk-Through

Assume request :110300000006 (Addr 17, FC03, Start 0000, Qty 0006).

ByteHexRunning sum (8-bit)
Addr110x11
FC030x14
Hi000x14
Lo000x14
QtyH000x14
QtyL060x1A

Negate: -0x1A = 0xE6 (two’s complement).
ASCII E6 appended before CR LF ⇒ full frame:

:110300000006E6␍␊

6.3.3 Table-less Code (C) – Listing 1

uint8_t calc_lrc(const uint8_t *buf, size_t len) {
    uint8_t lrc = 0;
    while (len--) lrc += *buf++;   // 8-bit add (auto wraps)
    return (uint8_t)(-lrc);        // two's complement
}

6.4 Timing & Throughput

6.4.1 Framing Rules

ParameterRecommendedNotes
Inter-char timeout≤ 1 sLonger aborts frame
Inter-frame gap≥ 1 sGives slave parse window
Baud rate range300 Bd … 38 400 BdASCII decoding overhead becomes dominant above 19 200 Bd

Unlike RTU, ASCII framing does not depend on character time; start/stop chars govern the parser.

6.4.2 Efficiency Equation

η=NdataNascii=(1+D+2)(1+D)×2+5\eta = \frac{N_\text{data}}{N_\text{ascii}} = \frac{(1 + D + 2)}{(1 + D) \times 2 + 5}

(where 1=Addr, 2=LRC, D=Data bytes, 5 = Start+CRLF)

Example read of 60 regs (binary 125 B data):
ASCII size = (1+1+4+2) × 2 + 3 = 232 chars (1.28× bigger than RTU).
At 9600 Bd = 232 × 11 / 9600 ≈ 266 ms vs 91 ms for RTU.

Optimisation tip If you must stick with ASCII, crank baud to 19 200 or 38 400 to regain cycle time.


6.5 ASCII vs RTU — Choosing Wisely

FeatureASCIIRTU
Human readable
Works through ASCII-only media (GPRS SMS, e-mail tunnelling)
Bandwidth efficiency❌ (≈½)
Parser complexity✅ (no timing)⚠ Gap-aware
Interoperability with hobby tools (PuTTY)
Field popularity (2020s)5 % of new builds95 %

Decision matrix

Choose ASCII if:

  1. Communication traverses text-only channels (ASY-000 AT-modem, radio telemetry, SMS).
  2. A human will type configuration frames (legacy drive commissioning).
  3. Debugging takes place via simple terminal without protocol plug-ins.

Choose RTU otherwise; wrap RTU inside an ASCII-capable modem or tunnel over TCP if needed.


6.6 Worked Examples

6.6.1 Request — Write Single Coil (ON) to Slave 07

:0705 0013 FF00  79␍␊

Spaces added for clarity.

FieldASCIIBinMeaning
Start:
Addr070x07Slave 7
FC050x05Write Single Coil
Addr00 1319Coil 19
ValueFF 00On
LRC79Checksum

Slave response echoes same PDU → :07050013FF0079\r\n

6.6.2 Terminal Capture [Fig-6-2]

Screenshot of RealTerm log, highlighting Start → LRC, colourising TX vs RX.


6.7 Implementation Patterns & Gateways

6.7.1 UART Configuration

SettingRecommended
Data bits7 (ASCII) or 8 (if parity used for 7E1)
ParityEven (7E1) — optional
Stop bits1

Why 7E1? Each ASCII char is 7 bits; parity gives simple per-char error check.

6.7.2 Buffer Strategy

  • Scan for :; when found, switch to collect mode.
  • Store until LF; verify LRC before parsing.
  • Reject frames > 513 chars (spec safety guard).

6.7.3 ASCII ↔ RTU Conversion

Many modern gateways (e.g., Moxa, Anybus) transparently convert:

  1. Strips : and CR LF.
  2. Converts ASCII pairs → binary bytes.
  3. Re-computes CRC-16 to send onto RS-485 RTU slaves.

Latency cost ≈ 1 ms + (ASCII length/baud). Ensure gateway FIFO can buffer full ASCII frame.

6.7.4 In-Microcontroller Conversion (bare metal)

Listing 2 Minimal C routine (STM32) to accept ASCII on UART 1, forward RTU on UART 2; includes interrupt state machine.

(full listing trimmed for brevity but complete in downloadable repo)


6.8 Troubleshooting Cookbook

SymptomPossible CauseFix
Slave never respondsStart char missing (:)Verify terminal sends 0x3A; some GUIs strip
“LRC error” only on long framesAdmin typed wrong HEX pairEcho input, visual diff
CRC errors after gatewayASCII→RTU converter double-byte swappedUpdate firmware / set little-endian CRC flag
Frame splits across two TCP packetsTelnet/SSH path inserts CR onlyRequire full CR LF; enable binary mode

Ghost colon Noise flips a line from 0→1 that equals ASCII ‘:’ (0x3A). Install EMI ferrite, verify shield ground.


Key Takeaways

  1. Modbus ASCII is text-mode RTU: same 6-byte PDU, human-visible hex envelope.
  2. Start : + End CR LF provide timing-agnostic framing perfect for modems & radios.
  3. LRC = –Σ(bytes) (two’s complement); send as ASCII high-low nibbles.
  4. ASCII costs ~2× bandwidth; mitigate with higher baud or migrate to RTU/TCP.
  5. Gateways make ASCII ↔ RTU conversion painless but watch latency & endian flags.

Assets to produce before publication

IDVisual / AssetPurpose
Fig-6-1Colour-coded ASCII frameTeach field order
Fig-6-2RealTerm TX/RX capturePractical reference
Fig-6-3LRC calc flowchartReinforce algorithm
Fig-6-4ASCII vs RTU efficiency graphDecision making

Coming Up Next

With both serial variants under your belt, Module 3 catapults us onto Ethernet: Chapter 7 – Introduction to Modbus TCP/IP & the MBAP Header. You’ll learn how the same PDU sails through IP networks, what Transaction-ID means, and how Unit-IDs let one gateway feed 50 serial loops. Keep Wireshark open.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Chapter 9 – Modbus Gateways

— Bridging Serial & TCP/IP Worlds (Module 3 · Modbus TCP/IP) Ambition for this chapter: Build the best single source on earth for everything that happens inside a Modbus gateway—PCB…

Chapter 30 – Modbus vs. The Rest

— A Definitive, Metrics-Driven Guide to Choosing (or Replacing) an Industrial Protocol *(Module 9 · Advanced & Specialised Topics — FINAL) How to use this chapter Print it, laminate it, and pin…