Files
dragon-q6a/docs/uart.md
T
ykcheungab c970272361 修复 UART 命令处理并支持 1–4 路传感器
增加只读启动和可调用采集 API,保留单路数据协议。通过 28 项模拟回归测试、Ruff 和文档检查;实机限制见 docs/uart.md。
2026-10-14 14:17:27 +08:00

6.7 KiB
Raw Blame History

UART finger service

serial/example_uart.py processes 1–4 finger cameras or recorded videos and publishes the SDK's normal and shear values over a separate data UART. Python 3.10+, the board's installed orisys SDK and pyserial are required. Run inside the board environment prepared by setup/sdk_setup.sh; install pyserial there with python -m pip install pyserial if needed.

Launch from the login console

The TTL login console and data UART must use different device ports. Start the script in the login shell; connect the data receiver to the port selected by --port. A shell/getty or another serial program must not own that data port. The default is /dev/ttyHS1, 115200 baud, 8N1, with no flow control. This service does not configure pin multiplexing or enable the board's UART hardware.

From the board's dragon-q6a checkout:

# Host commands control connection and streaming (default: one camera).
python serial/example_uart.py --port /dev/ttyHS1 --config finger

# Four configured sources; use 1, 2, 3 or 4 entries as required.
python serial/example_uart.py --port /dev/ttyHS1 --sources 0 2 4 6

# A passive receiver needs only to read: connection and streaming start automatically.
python serial/example_uart.py --port /dev/ttyHS1 --sources 0 2 --read-only

# Start streaming immediately, while still accepting UART commands.
python serial/example_uart.py --port /dev/ttyHS1 --sources 0 2 --autostart

Use actual camera indices/device paths discovered on the board; 0 2 4 6 is only an example. Slot IDs are fixed by --sources order, not camera index. Repeat --config once per source for different sensor configurations, or supply one shared configuration. Existing --camera-id and --video remain available for a single source. --sources replaces those options. --show requires a local GUI and is off by default. Logs go to the login console, replies to the data UART.

In --read-only mode, all incoming UART commands are ignored. End the process with Ctrl-C in the login shell. Startup still emits OK/ERR records; the receiver should select force, lines. Without --autostart or --read-only, a passive reader receives only OK ready until a host sends connect and run.

Command protocol

Commands are UTF-8, case-insensitive, terminated by LF, CR or CRLF. Incomplete lines remain buffered across serial timeouts. Lines exceeding 1024 bytes are discarded through their terminator and produce ERR command ... in control mode. Quote file paths containing spaces. Linux device paths are recommended on Q6A.

Command Behavior
search List cameras, then OK search N; use before connecting. Rejected while streaming.
connect Connect slot 1 using its configured source; in single-source mode, prefer the latest search result for a camera.
connect SOURCE Legacy form: connect slot 1 to this camera index, device path or file.
connect ID SOURCE Connect/replace one slot; stop streaming that slot. Other slots keep their connections.
connect all Connect all configured slots; report each success/failure independently.
run [ID|all] Stream the selected slot, or all connected slots when omitted. Requires a connection.
read [ID|all] Publish one newly processed measurement per selected slot; defaults to all configured slots. Does not start streaming.
stop [ID|all] Stop selected streaming, or all when omitted; keep cameras connected.
quit / exit Exit and release all camera and UART resources.

connect 2 means camera index 2 on slot 1, preserving the old protocol. To connect slot 2, send connect 2 /dev/video2 or use connect all. There are no motor-control commands; these commands control acquisition only.

Single-source measurements retain the original format:

force,1.250000,-2.500000,3.750000

When configured with multiple sources, measurements include the slot ID even if only one source connected successfully:

OK connect 2 /dev/video2 (camera)
OK run 1 2
force,1,1.250000,-2.500000,3.750000
force,2,0.500000,0.100000,-0.200000
ERR run 2 processing failed
OK eof 1

Force fields are FNORMAL, FSHEARX, FSHEARY in SDK axes. They may be raw or calibrated; do not assume Newtons. The Python API exposes SDK units per reading, using unknown if an older SDK does not expose them. CSV preserves the original fields and carries no units, timestamps or cross-sensor synchronization.

Each processing failure or EOF stops only the affected slot. Processing exceptions produce ERR, never fabricated zero force. --no-loop-video stops files at EOF; the default tries one rewind, resets the tracker and retries one frame. Failed preparation releases the newly opened runtime; replacing a connection releases the old one before opening the replacement. A failed replacement requires retrying connect. Startup continues with any successfully connected slots and fails if none connect. Reconnect and run explicitly after a camera failure.

Callable acquisition API

serial/finger_api.py owns acquisition and runtime cleanup; importing it opens no UART or camera. Place that directory on the caller's module search path:

from finger_api import FingerSensorBank

bank = FingerSensorBank([0, 2], configs=["finger"])
try:
    bank.connect(1)
    bank.connect(2)
    reading = bank.read(1)
    if reading is not None:
        print(reading.normal, reading.shear_x, reading.shear_y, reading.units)
finally:
    bank.close()

The caller owns one thread and must close the bank. read() returns None on capture failure/EOF and raises on processing failure. It returns an image and three scalar forces from the same processed frame. One file or camera is read at a time; the API introduces no workers beyond those owned by the SDK.

Verification and limits

Hardware-free regression tests cover command fragmentation, CR/LF, legacy output, 1–4 slot identities, selective control, failure isolation, read-only startup and cleanup. They use in-memory serial and runtime fakes, not physical devices:

python -m unittest discover -s tests -v

Q6A UART wiring, installed ARM SDK compatibility, camera bandwidth, sustained frame rates and latency remain unverified. The shipped ARM wheel is compiled orisys 0.5.0; local tests do not execute it. SDK capture and processing remain synchronous from this service's perspective. Commands are checked before each round; a slow grab, processing call, connection or camera scan can delay them. Serial writes have a finite timeout (default 1 second), and transport failure terminates the service with cleanup. At 115200 baud/8N1, the data budget is 11,520 bytes/s, shared by all measurements and replies. Measure actual frame rates and stop latency on the board before choosing a higher baud rate.