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
- Free download: dl-serial-monitor.voltrus.id: notarized DMG, free to use
- Pro licence: $4.99 one-time from the Voltrus Console. Enter the key in the app to unlock the Pro features.
- Product page: /serial-terminal/
System Requirements
| Requirement | Minimum |
|---|---|
| macOS | 13 Ventura or newer (Apple Silicon & Intel) |
| Serial adapter | USB-to-Serial: FTDI FT232, CH340/CH341, SiLabs CP2102, or Prolific PL2303 (RS232, RS485, or RS422 variants) |
| Native CDC-ACM | Boards 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.
/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.
- Plug in your USB-to-Serial adapter.
- Open the app and pick the port from the dropdown (
/dev/cu.usbserial-*). Prefer thecu.*name. It does not require the DCD carrier line. - Set framing to
115200 8N1(most common modern default) and click Connect. - With send format set to ASCII, type
ATand click Send. The reply appears in the traffic table as hex bytes;4F 4BisOK.
2. Watch hex traffic from an RS-485 device
- Connect to the adapter with the device's baud, parity and stop bits.
- 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. - On a 2-wire bus, your own transmitted frames may echo back. That is expected.
3. Send a raw hex sequence
- Switch the Tx mode to Hex.
- Type the frame as space-separated bytes:
01 04 00 00 00 0A 70 0D(a Modbus RTU read of 10 input registers). - 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.
| Parameter | Common Values |
|---|---|
| Baud rate | Presets 9600 to 921600, or any custom rate |
| Data bits | 5, 6, 7, 8 (8 is the modern default) |
| Parity | None, Even, Odd |
| Stop bits | 1 or 2 |
| Industrial defaults | 9600 8N1 (Schneider, ABB), 9600 8E1 (Siemens, many VFDs) |
| GPS / NMEA | 4800 8N1 (legacy) or 38400 8N1 (modern receivers) |
Send Formats
| Format | Use Case |
|---|---|
| ASCII | Text protocols: AT commands, NMEA sentences, debug consoles |
| Hex | Binary 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
- Email: [email protected]
- Product page: /serial-terminal/
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.