RS485 Controller

RS485 Controller hardware 0.5

A programmable ESP32-S3-MINI-1U controller with a half-duplex RS485 interface for Gearotons servomotors and other compatible RS485 devices. Includes an external antenna. Write your own control application on the ESP32-S3; USB bridging and wireless behavior depend on the firmware you install. The datasheet covers wiring, power, pinouts and Arduino setup.

Start here

Let your coding agent write it

Copy the prompt below into your preferred AI coding agent, then describe what you want to build. It points your agent to the official product documentation for commands, units, wiring details and error codes, so it can look them up instead of guessing.

The prompt — paste it into your agent, then describe your project
I am writing code to control a Gearotons RS485 Controller (product code RS2, hardware version 0.5).
A programmable ESP32-S3-MINI-1U controller with a half-duplex RS485 interface for Gearotons servomotors and other compatible RS485 devices. Includes an external antenna. Write your own control application on the ESP32-S3; USB bridging and wireless behavior depend on the firmware you install. The datasheet covers wiring, power, pinouts and Arduino setup.

All of the official documentation is machine-readable. Read what you need from these before writing any code:

- https://9o.at/products/rs2/0.5.md
  This product: what it is, the datasheet, the schematic, every firmware release and how to flash one.
- https://9o.at/docs/arduino.md
  The Arduino library reference: commands, arguments, units, wiring, examples and error codes.
- https://9o.at/llms.txt
  An index of everything else, including the other Gearotons products.

Use only commands, units and error codes that appear in those documents. If something I ask for is not covered there, tell me instead of guessing.

Here is what I want to build:

Nothing to install and no account: the documentation is plain Markdown at a stable address. Point an agent straight at it if you prefer — this product, Arduino, documentation index.

Schematic

Open the PDF in a new tab ↗ · Download · Click the drawing, then scroll to zoom and drag to pan. Full screen for reading part numbers.

Loading the schematic viewer…

Firmware

No firmware files are published for this hardware version.

Get coding

Arduino

Library Manager → search Servomotor → Install.

Arduino example
// Minimal Arduino example: Trapezoid move using built-in unit conversions
// Goal: spin the motor exactly 1 rotation in 1 second, then stop.
// Sequence:
//  system reset -> enable MOSFETs -> trapezoidMove(1.0 rotations, 1.0 seconds)
//  -> wait 1.1s -> disable MOSFETs.
//
// Notes:
// - This uses the library's unit conversion (no raw counts/timesteps).
// - Configure Serial1 pins for your board (ESP32 example pins below).
// - Motor is created AFTER Serial1.begin(...) so hardware UART pins are set first.
// - Every command is checked with getError(). No command method returns a success
//   flag, and a motor that has latched a fatal error silently ignores everything
//   afterwards, so an unchecked sketch just stops moving with no symptom at all.
//   See "Checking for errors" in the API documentation.

#include <Servomotor.h>

#define ALIAS 'X'                   // Device alias
#define BAUD 230400                 // RS485 UART baud rate
#define DISPLACEMENT_ROTATIONS 1.0f // 1 rotation
#define DURATION_SECONDS 1.0f       // 1 second
#define TOLERANCE_PERCENT 10        // +10% wait margin because the motor's clock is not
                                    //  perfectly accurate
#define WAIT_MS ((unsigned long)(DURATION_SECONDS * 1000.0f * (100 + TOLERANCE_PERCENT) / 100))
#define POST_RESET_WAIT_MS 1500     // Keep the bus SILENT this long after a reset: the motor
                                    //  boots through a bootloader window, and any packet that
                                    //  arrives during it pins the motor in the bootloader.

// Example RS485 pins for ESP32 DevKit (change as needed for your board)
#if defined(ESP32)
#define RS485_TXD 4              // TX pin to RS485 transceiver
#define RS485_RXD 5              // RX pin from RS485 transceiver
#endif

// Returns true (and explains itself) if the previous command did not succeed.
// getError() is 0 on success, positive for a fatal error reported by the motor
// (look the number up in the Error Codes section of the documentation), and
// negative for a communication failure such as -1 = no reply within 1 second.
bool failed(Servomotor &motor, const char *what) {
  int e = motor.getError();
  if (e == 0) return false;
  Serial.print("[FAIL] ");
  Serial.print(what);
  Serial.print(" -> getError() = ");
  Serial.print(e);
  Serial.println(e > 0 ? "  (motor fatal error - see the Error Codes section)"
                       : "  (communication failure - check wiring, alias and power)");
  return true;
}

void setup() {
  Serial.begin(115200); // Console serial for debugging
                        // On ESP32-S3, set Tools > USB CDC On Boot > Enabled or this
                        // output never reaches the USB serial monitor.

  // Create the motor; serial port opens on first instantiation.
#if defined(ESP32)
  Servomotor motor(ALIAS, Serial1, RS485_RXD, RS485_TXD);
#else
  Servomotor motor(ALIAS, Serial1);
#endif

  // Use units: rotations for position, seconds for time.
  // These are host-side only - they send nothing to the motor.
  motor.setPositionUnit(PositionUnit::SHAFT_ROTATIONS);
  motor.setTimeUnit(TimeUnit::SECONDS);

  // Start from a known-clean state: this also clears any fatal error left over
  // from a previous run, which is the usual reason a motor "stops working".
  motor.systemReset();
  if (failed(motor, "systemReset")) return;
  delay(POST_RESET_WAIT_MS);

  motor.enableMosfets();
  if (failed(motor, "enableMosfets")) return;

  motor.trapezoidMove(DISPLACEMENT_ROTATIONS, DURATION_SECONDS);
  if (failed(motor, "trapezoidMove")) return;

  delay(WAIT_MS);

  // A successful move command only means the move was accepted and queued. Faults
  // such as a stall or a position-deviation trip happen later, while it executes,
  // so check the motor's own status once the motion should be finished.
  getStatusResponse status = motor.getStatus();
  if (failed(motor, "getStatus")) return;
  if (status.fatalErrorCode != 0) {
    Serial.print("[FAIL] motor faulted during the move, error code ");
    Serial.println(status.fatalErrorCode);
    return;
  }

  motor.disableMosfets();
  if (failed(motor, "disableMosfets")) return;

  Serial.println("Move completed successfully.");
}

void loop() {
}

Getting started · Full Arduino reference · Library on GitHub ↗