A C# port of the Feetech SCServo SDK for controlling SC series servo motors on Windows. This library provides a complete C# implementation for Windows that maintains compatibility with the original protocol while leveraging C#'s type safety and modern language features.
- Complete Protocol Implementation: Full support for SCServo communication protocol
- Windows Native: Built using
System.IO.Ports.SerialPortfor reliable Windows serial communication - Type Safety: Leverages C#'s strong typing system for safer servo control
- Modern API: Clean, idiomatic C# interface with proper error handling
- Sync Operations: Support for synchronized read/write operations with multiple servos
- Easy to Use: Simple, intuitive API with comprehensive examples
- .NET 8.0 or later
- Windows OS
- USB to TTL serial converter (compatible with 3.3V or 5V logic)
- SCServo with serial communication capability
dotnet add package FeetechServoSDK- Clone this repository
- Build the project:
dotnet build FeetechServoSDK/FeetechServoSDK.csproj
- Add a project reference to your application
using Feetech.ServoSDK;
// Initialize components
var portHandler = new PortHandler("COM3"); // Change to your COM port
var packetHandler = PacketHandlerFactory.CreatePacketHandler(0);
try
{
// Open port and set baudrate
portHandler.OpenPort();
portHandler.SetBaudRate(1000000);
// Ping servo
var (modelNumber, result, error) = packetHandler.Ping(portHandler, 1);
if (result == CommResult.Success && error.IsEmpty())
{
Console.WriteLine($"Servo found! Model number: {modelNumber}");
}
portHandler.ClosePort();
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}// Write goal position
var (writeResult, writeError) = packetHandler.Write2ByteTxRx(
portHandler,
servoId: 1,
address: ControlTableAddress.GoalPosition,
data: 2048
);
// Read present position
var (position, readResult, readError) = packetHandler.Read2ByteTxRx(
portHandler,
servoId: 1,
address: ControlTableAddress.PresentPosition
);
Console.WriteLine($"Current position: {position}");// Create sync write group
var syncWrite = new GroupSyncWrite(
portHandler,
packetHandler,
ControlTableAddress.GoalPosition,
dataLength: 2
);
// Add multiple servos
syncWrite.AddParam2Byte(servoId: 1, data: 1000);
syncWrite.AddParam2Byte(servoId: 2, data: 2000);
syncWrite.AddParam2Byte(servoId: 3, data: 3000);
// Execute synchronized write
var result = syncWrite.TxPacket();Manages serial port communication with the servo controller.
public class PortHandler : IPortHandler, IDisposable
{
public PortHandler(string portName);
public void OpenPort();
public void ClosePort();
public void SetBaudRate(uint baudRate);
public byte[] ReadPort(int length);
public int WritePort(byte[] data);
public static string[] GetAvailablePorts();
}Handles SCServo protocol packet communication.
public interface IPacketHandler
{
(ushort modelNumber, CommResult result, ProtocolError error) Ping(IPortHandler port, byte servoId);
(byte data, CommResult result, ProtocolError error) Read1ByteTxRx(IPortHandler port, byte servoId, byte address);
(CommResult result, ProtocolError error) Write1ByteTxRx(IPortHandler port, byte servoId, byte address, byte data);
// ... more methods for 2-byte and 4-byte operations
}Performs synchronized write operations to multiple servos.
public class GroupSyncWrite
{
public GroupSyncWrite(IPortHandler port, IPacketHandler packetHandler, byte startAddress, byte dataLength);
public bool AddParam(byte servoId, byte[] data);
public bool AddParam2Byte(byte servoId, ushort data);
public CommResult TxPacket();
}Performs synchronized read operations from multiple servos.
public class GroupSyncRead
{
public GroupSyncRead(IPortHandler port, IPacketHandler packetHandler, byte startAddress, byte dataLength);
public bool AddParam(byte servoId);
public CommResult TxRxPacket();
public ushort GetData2Byte(byte servoId, byte address);
}public enum CommResult : int
{
Success = 0,
PortBusy = -1,
TxFail = -2,
RxFail = -3,
TxError = -4,
RxTimeout = -6,
RxCorrupt = -7,
NotAvailable = -9
}public static class ControlTableAddress
{
public const byte TorqueEnable = 40;
public const byte GoalPosition = 42;
public const byte GoalSpeed = 46;
public const byte PresentPosition = 56;
}[Flags]
public enum ProtocolError : byte
{
None = 0,
Voltage = 1,
Angle = 2,
Overheat = 4,
Overload = 32
}The library includes several example applications in the Examples folder:
- Basic servo detection and communication test
- Demonstrates connection setup and basic ping operation
- Run:
dotnet run --project Examples/PingExample
- Individual servo position control
- Shows reading present position and setting goal position
- Includes motion monitoring and error handling
- Run:
dotnet run --project Examples/ReadWriteExample
- Multi-servo coordinated control
- Demonstrates synchronized operations
- Shows how to control multiple servos simultaneously
- Run:
dotnet run --project Examples/SyncReadWriteExample
// List available COM ports
var ports = PortHandler.GetAvailablePorts();
foreach (var port in ports)
{
Console.WriteLine(port);
}Set the correct protocol endianness for your servo series:
// For STS/SMS series (most common)
var packetHandler = PacketHandlerFactory.CreatePacketHandler(0);
// For SCS series
var packetHandler = PacketHandlerFactory.CreatePacketHandler(1);Common baudrates for SCServos:
portHandler.SetBaudRate(1000000); // Most common
portHandler.SetBaudRate(115200); // Alternative
portHandler.SetBaudRate(57600); // Lower speedThe library uses C#'s native exception handling and tuple return types:
try
{
portHandler.OpenPort();
portHandler.SetBaudRate(1000000);
var (data, result, error) = packetHandler.Read2ByteTxRx(portHandler, 1, 42);
switch (result)
{
case CommResult.Success:
if (error.IsEmpty())
Console.WriteLine($"Data: {data}");
else
Console.WriteLine($"Protocol error: {error.GetDescription()}");
break;
case CommResult.RxTimeout:
Console.WriteLine("Communication timeout - check connections");
break;
default:
Console.WriteLine($"Communication error: {result.GetDescription()}");
break;
}
}
catch (SerialPortException ex)
{
Console.WriteLine($"Port error: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
}The library is designed for single-threaded use. If you need to access servos from multiple threads:
- Use a single dedicated thread for all servo communication
- Implement your own synchronization mechanisms (e.g.,
lockstatements) - Create separate
PortHandlerinstances for each thread (not recommended)
- Batch Operations: Use sync read/write for multiple servos to reduce communication overhead
- Timeout Settings: Adjust packet timeouts based on your communication requirements
- Baudrate: Higher baudrates provide faster communication but may be less reliable over long distances
-
Access Denied to COM Port
- Close other applications using the port
- Check Windows Device Manager for port conflicts
- Run your application with appropriate permissions
-
No Response from Servo
- Check power supply
- Verify baudrate settings
- Ensure correct servo ID
- Check cable connections
-
Communication Errors
- Reduce baudrate
- Check for electromagnetic interference
- Verify protocol endianness setting
- Ensure USB drivers are installed
Enable detailed logging:
#if DEBUG
Console.WriteLine($"Communication result: {result.GetDescription()}");
Console.WriteLine($"Protocol error: {error.GetDescription()}");
#endif- STS Series: Smart Serial Servo (most common)
- SMS Series: Smart Serial Servo with magnetic encoder
- SCS Series: Smart Serial Servo with different protocol endianness
- Windows 10 or later
- .NET 8.0 or later
- USB to TTL serial converter (compatible with 3.3V or 5V logic)
- SCServo with serial communication capability
- Appropriate power supply for your servo model
# Clone the repository
git clone https://github.com/yourusername/feetech-servo-sdk-csharp.git
cd feetech-servo-sdk-csharp
# Build the library
dotnet build FeetechServoSDK/FeetechServoSDK.csproj
# Build and run an example
dotnet run --project Examples/PingExampleThis C# port maintains compatibility with the original Feetech library licensing terms.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all examples still work
- Submit a pull request
This is a C# port of the Swift library by FyrbyAdditive, which itself is based on the original Feetech Python library. Special thanks to the original authors for their excellent work.
For issues specific to this C# port, please open an issue on the repository. For general SCServo questions, refer to the original Feetech documentation.