Metadata-Version: 2.4
Name: sts-suite
Version: 0.1.2
Summary: Terminal debugger for Feetech STS3215 smart serial bus servos
Project-URL: Homepage, https://github.com/pham-tuan-binh/sts-suite
Project-URL: Repository, https://github.com/pham-tuan-binh/sts-suite
Project-URL: Issues, https://github.com/pham-tuan-binh/sts-suite/issues
Author-email: Binh Pham <binh.pham@livekit.io>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: debugger,feetech,robotics,serial,servo,sts3215,tui
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Topic :: Terminals
Requires-Python: >=3.10
Requires-Dist: pyserial>=3.5
Requires-Dist: questionary>=2.0.1
Requires-Dist: rich>=13.7.0
Requires-Dist: rustypot>=1.4.2
Requires-Dist: textual-plotext>=0.2.1
Requires-Dist: textual>=0.50.0
Requires-Dist: typer>=0.12.0
Description-Content-Type: text/markdown

# sts-suite

![Python](https://img.shields.io/badge/python-3.10%2B-3776AB?logo=python&logoColor=white)
![License](https://img.shields.io/badge/license-Apache_2.0-4CAF50)
![TUI](https://img.shields.io/badge/TUI-Textual-5A1BCC)
![Serial](https://img.shields.io/badge/serial-rustypot-DE3B26)
![Platform](https://img.shields.io/badge/platform-macOS_|_Linux-555)

Terminal debugger for Feetech STS3215 smart serial bus servos.

<!-- Screenshot goes here -->
![screenshot](https://raw.githubusercontent.com/pham-tuan-binh/sts-suite/main/docs/screenshot.png)

## Requirements

- Python 3.10 or newer
- A USB-to-TTL adapter wired to the servo bus

## Install

With [uv](https://docs.astral.sh/uv/):

```bash
uv tool install sts-suite
```

Or with pip:

```bash
pip install sts-suite
```

## Run

```bash
sts
```

Pick a serial port and baud rate. The debugger opens. The last choice is saved to `~/.cache/sts-suite/last.json`.

If no motors respond, hit `Baud sweep` in the port picker and it will try every preset and pick the one with the most motors.

## Main screen

Left sidebar: motors on the bus. Toggle multi-select with `ctrl+space`; goal and nudge then drive the whole selection via `sync_write` in one packet.

Right side: a watch strip with the always-visible vitals, then the full register table. `Enter` on any RW row pops an edit modal with a description, range, units, and a dropdown for enum registers.

## Screens

| Key      | Screen                                              |
| -------- | --------------------------------------------------- |
| `?`      | Help overlay                                        |
| `o`      | Oscilloscope: live plot of position / speed / load / current |
| `w`      | Waveform generator: sine, square, triangle, step    |
| `v`      | Grid view: every motor on one screen                |
| `d`      | Diff against a saved state snapshot                 |
| `Ctrl+L` | Preset loader: apply a JSON of register values      |

## Keybindings

| Key          | Action                                          |
| ------------ | ----------------------------------------------- |
| `q`          | Quit                                            |
| `r`          | Rescan bus                                      |
| `t`          | Toggle torque on selected (or all selected)     |
| `!`          | E-STOP: broadcast torque off to every motor     |
| `space`      | Full refresh                                    |
| `Ctrl+Space` | Toggle multi-select on highlighted motor        |
| `g`          | Focus goal / speed input                        |
| `k` / `j`    | Nudge +5 / -5 (auto-scales per mode)            |
| `l` / `h`    | Nudge +50 / -50                                 |
| `c`          | Center: goal to 2048 or speed to 0              |
| `Enter`      | Edit selected register (RW only)                |
| `x`          | Movement test on selected motor                 |
| `s`          | Save JSON snapshot of every motor               |
| `Ctrl+R`     | Reboot selected motor                           |

## Modes

The control bar adapts to the selected motor's `mode` register.

| Mode | Name                   | Target        | Range            | Nudge scale |
| ---- | ---------------------- | ------------- | ---------------- | ----------- |
| 0    | position (servo)       | goal_position | 0 to 4095        | 1           |
| 1    | wheel (continuous)     | goal_speed    | -4000 to 4000    | 10          |
| 2    | PWM (open-loop)        | goal_speed    | -1000 to 1000    | 5           |
| 3    | step                   | goal_position | -32768 to 32767  | 20          |

## Status register

Bit flags decoded in the register table and watch strip.

| Tag     | Meaning                  |
| ------- | ------------------------ |
| `VOLT`  | voltage out of range     |
| `ANGLE` | angle limit exceeded     |
| `HOT`   | overheat                 |
| `CURR`  | overcurrent              |
| `OVLD`  | overload                 |

## Snapshot file

`s` writes `sts-state-YYYYMMDD-HHMMSS.json` in the current directory with every register value for every motor on the bus. Load one with `d` to diff against the current live readings.

## Preset file

Presets live in any JSON file with a top-level `registers` map:

```json
{
  "registers": {
    "p_coefficient": 32,
    "i_coefficient": 0,
    "d_coefficient": 0,
    "torque_limit": 800,
    "acceleration": 30,
    "max_temperature_limit": 70
  }
}
```

`Ctrl+L` applies every RW field to the selected motor; EEPROM fields are unlocked and re-locked automatically.

## Performance

- Live tick reads SRAM 40-70 in one `read_raw_data` call (single round trip per refresh).
- Full refresh reads EEPROM 0-39 plus SRAM 40-70 as two bulk reads instead of 26.
- Serial I/O runs in a worker thread; a stuck motor can't freeze the UI.
- Multi-motor writes use `sync_write_raw_data` so N motors update in one packet.

## Stack

- [Textual](https://github.com/Textualize/textual) and [textual-plotext](https://github.com/Textualize/textual-plotext) for the UI
- [rustypot](https://github.com/pollen-robotics/rustypot) for the Feetech protocol over serial

## License

Apache License 2.0. See [LICENSE](LICENSE).
