Serial Terminal Documentation: Setup and Troubleshooting

Installation

MacTools Serial Terminal is a native macOS app built with Rust and Tauri. It runs natively on Apple Silicon and Intel Macs: no Rosetta, no Parallels, no Java, no Node.js. One-time purchase, no subscription.

Download

System Requirements

RequirementMinimum
macOS13 Ventura or newer (Apple Silicon & Intel)
Serial adapterUSB-to-Serial: FTDI FT232, CH340/CH341, SiLabs CP2102, or Prolific PL2303 (RS232, RS485, or RS422 variants)
Native CDC-ACMBoards with native USB CDC (many Arduinos, ESP32-S2/S3) appear without an extra driver

First Launch

The direct download is signed and notarized by Apple, so it opens normally. If macOS still shows a warning on first launch, right-click the app, choose Open, then confirm. This is only required once.

The app installs no kernel extension. It opens the serial ports macOS exposes. If your adapter does not appear as /dev/cu.usbserial-* or /dev/cu.usbmodem*, install the chip vendor's current macOS driver first.

Quick Start

1. Talk to an RS-232 device (AT command console)

The fastest path: a cellular modem, GPS module, or any device with an AT-style command line.

  1. Plug in your USB-to-Serial adapter.
  2. Open the app and pick the port from the dropdown (/dev/cu.usbserial-*). Prefer the cu.* name. It does not require the DCD carrier line.
  3. Set framing to 115200 8N1 (most common modern default) and click Connect.
  4. With send format set to ASCII, type AT and click Send. The reply appears in the traffic table as hex bytes; 4F 4B is OK.

2. Watch hex traffic from an RS-485 device

  1. Connect to the adapter with the device's baud, parity and stop bits.
  2. Every received chunk appears in the traffic table as hex bytes (01 03 00 0A 00 02 …) with direction (RX / TX) and a millisecond timestamp.
  3. On a 2-wire bus, your own transmitted frames may echo back. That is expected.

3. Send a raw hex sequence

  1. Switch the Tx mode to Hex.
  2. Type the frame as space-separated bytes: 01 04 00 00 00 0A 70 0D (a Modbus RTU read of 10 input registers).
  3. Hit Send. The bytes go out exactly as typed, so include the CRC yourself (the example above already ends in its CRC, 70 0D).

4. Debug an Arduino firmware over USB CDC

Plug in the Arduino and select /dev/cu.usbmodem*. Set the baud to match Serial.begin(). Output appears in real time in the traffic table as hex bytes with timestamps.

5. Test without hardware

On macOS, switch to the virtual port panel and create a virtual serial port. The app shows its /dev/ttys* path; point another program at it and exchange bytes with the app, no adapter needed.

Configuration

Serial Framing

Framing must match the device exactly. A single wrong bit (e.g. 8N1 vs 8E1) turns every byte into garbage.

ParameterCommon Values
Baud ratePresets 9600 to 921600, or any custom rate
Data bits5, 6, 7, 8 (8 is the modern default)
ParityNone, Even, Odd
Stop bits1 or 2
Industrial defaults9600 8N1 (Schneider, ABB), 9600 8E1 (Siemens, many VFDs)
GPS / NMEA4800 8N1 (legacy) or 38400 8N1 (modern receivers)

Send Formats

FormatUse Case
ASCIIText protocols: AT commands, NMEA sentences, debug consoles
HexBinary protocols: Modbus RTU, proprietary frames. Type space-separated bytes.

Received data is always shown as hex in the traffic table, so control bytes and line endings (0D 0A) stay visible.

Timings & inter-byte gaps

For RS-485 with multiple slaves, set a post-Tx idle (≥3.5 character times) before releasing the bus. On 9600 8N1 that is roughly 4 ms; on 115200 it shrinks below 0.5 ms. Use the millisecond timestamps in the traffic table to check the gaps your master leaves between frames.

Key Features

Hex traffic table

Every received and sent frame is listed as hex bytes with a millisecond timestamp and direction (RX / TX). The table keeps the most recent traffic on screen.

Hex or ASCII send

Send text commands as ASCII or exact frames as space-separated hex bytes.

Virtual serial port (macOS)

Create a PTY-based virtual port and point another program at its /dev path to test serial code without an adapter.

Connection health

A live indicator shows whether data is arriving and how long the line has been idle.

Demo traffic

Built-in demo templates play back sample Modbus RTU master and slave exchanges in the traffic table, so you can see what a healthy poll cycle looks like before connecting hardware.

No kernel extensions

The app installs no kext. It opens the serial ports your adapter's driver creates, natively on Apple Silicon and Intel.

Troubleshooting

No port appears in the dropdown

Symptom: The dropdown shows no /dev/cu.usbserial-* entries.
Fix: Open Apple menu → About This Mac → More Info → System Report → USB and check the adapter enumerates. If it shows but no device node appears, the chip driver failed. Unplug/replug, try another USB port or cable (a charge-only cable is the most common cause on adapters with a USB-C breakout). Counterfeit PL2303 chips fail more often than genuine FTDI/CP2102 parts.

Port busy / Permission denied on open

Symptom: "Permission denied" or "Resource busy" when opening /dev/cu.*.
Fix: Another process holds the port: close screen, minicom, Arduino IDE's Serial Monitor, or a second instance of the app. On macOS 13+ the first time the app opens a serial port you may need to grant permission under System Settings → Privacy & Security → Files and Folders.

Garbage bytes in the traffic table

Symptom: Bytes arrive but make no sense.
Fix: Baud/parity/stop-bits mismatch. 9 out of 10 times the baud is wrong. Try 9600, 19200, 115200 first. If the first byte of every frame is fine but later bytes corrupt, drop the baud (long cable / cheap adapter can't sustain it) and add a 120 Ω termination resistor on RS-485.

RS-485: device never responds

Symptom: Tx frames go out, no Rx comes back.
Fix: Swap A and B (D+ / D−). Polarity is mislabeled on roughly half of all RS-485 adapters and is by far the most common RS-485 wiring fault. If polarity is correct, check the bus has exactly one bias resistor pair and one termination at each physical end. Over-termination loads the bus and starves signal level.

Modbus frames arrive but the CRC does not match

Symptom: Checking a received frame's last two bytes in a CRC-16/Modbus calculator shows a mismatch.
Fix: Either the framing is wrong (see "garbage bytes" above), or the issue is electrical: grounding, termination, or a baud too high for the cable length.

Support

When reporting a comms issue, include a screenshot of the traffic table (redact any sensitive payloads) and note the adapter chip (FTDI / CH340 / CP2102 / PL2303) plus the exact baud/parity/stop-bits in use.