Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added scservo_sdk/__pycache__/__init__.cpython-313.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added scservo_sdk/__pycache__/hls.cpython-313.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added scservo_sdk/__pycache__/scscl.cpython-313.pyc
Binary file not shown.
Binary file added scservo_sdk/__pycache__/scservo_def.cpython-313.pyc
Binary file not shown.
Binary file added scservo_sdk/__pycache__/sms_sts.cpython-313.pyc
Binary file not shown.
15 changes: 13 additions & 2 deletions scservo_sdk/port_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ def closePort(self):
self.is_open = False

def clearPort(self):
# Clear both input AND output buffers
self.ser.reset_output_buffer()
self.ser.reset_input_buffer()
self.ser.flush()
time.sleep(0.001)

def setPortName(self, port_name):
self.port_name = port_name
Expand Down Expand Up @@ -60,11 +64,15 @@ def readPort(self, length):
return [ord(ch) for ch in self.ser.read(length)]

def writePort(self, packet):
return self.ser.write(packet)
written_bytes = self.ser.write(packet)
self.ser.flush() # Wait for TX to finish
self.ser.reset_input_buffer() # Wipe the "echo" of your own message
return written_bytes
# return self.ser.write(packet)

def setPacketTimeout(self, packet_length):
self.packet_start_time = self.getCurrentTime()
self.packet_timeout = (self.tx_time_per_byte * packet_length) + (self.tx_time_per_byte * 3.0) + LATENCY_TIMER
self.packet_timeout = (self.tx_time_per_byte * (packet_length + 3.0)) + LATENCY_TIMER + 20.0

def setPacketTimeoutMillis(self, msec):
self.packet_start_time = self.getCurrentTime()
Expand Down Expand Up @@ -102,7 +110,10 @@ def setupPort(self, cflag_baud):

self.is_open = True

# Wait for port to stabilize before use
time.sleep(0.1)
self.ser.reset_input_buffer()
self.ser.reset_output_buffer()

self.tx_time_per_byte = (1000.0 / self.baudrate) * 10.0

Expand Down
16 changes: 15 additions & 1 deletion sms_sts/ping.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,28 @@
import sys
import os


import subprocess

# ... after portHandler.openPort() ...

# Use the setserial command to force low latency mode
try:
subprocess.run(['sudo', 'setserial', '/dev/serial0', 'low_latency'], check=True)
print("Low latency mode enabled")
except:
print("Could not set low latency (ensure 'setserial' is installed)")



sys.path.append("..")
from scservo_sdk import * # Uses FTServo SDK library


# Initialize PortHandler instance
# Set the port path
# Get methods and members of PortHandlerLinux or PortHandlerWindows
portHandler = PortHandler('/dev/ttyUSB0') #ex) Windows: "COM1" Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"
portHandler = PortHandler('/dev/ttyAMA0') #ex) Windows: "COM1" Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"

# Initialize PacketHandler instance
# Get methods and members of Protocol
Expand Down
2 changes: 1 addition & 1 deletion sms_sts/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# Initialize PortHandler instance
# Set the port path
# Get methods and members of PortHandlerLinux or PortHandlerWindows
portHandler = PortHandler('/dev/ttyUSB0')# ex) Windows: "COM1" Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"
portHandler = PortHandler('/dev/ttyAMA0')# ex) Windows: "COM1" Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"

# Initialize PacketHandler instance
# Get methods and members of Protocol
Expand Down
65 changes: 65 additions & 0 deletions sms_sts/test_servo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import serial
import time
import subprocess

# 1. Force Low Latency at the OS level for the Pi 5's ttyAMA10
try:
# On Pi 5, serial0 usually points to ttyAMA10
subprocess.run(['sudo', 'setserial', '/dev/serial0', 'low_latency'], check=True)
print("SUCCESS: Low latency mode enabled")
except Exception as e:
print(f"WARNING: Could not set low latency (check if setserial is installed): {e}")

# 2. Configure the Serial Port
try:
ser = serial.Serial(
port='/dev/serial0',
baudrate=1000000,
timeout=0.1,
write_timeout=0.5
)
except Exception as e:
print(f"ERROR: Could not open port: {e}")
exit()

def send_ping(servo_id):
# STS/SCS Ping Packet: FF FF [ID] [Len] [Instr] [Checksum]
# Checksum = ~(ID + Length + Instruction) & 0xFF
checksum = (~(servo_id + 0x02 + 0x01)) & 0xFF
packet = bytearray([0xFF, 0xFF, servo_id, 0x02, 0x01, checksum])

print(f"\n--- Testing ID: {servo_id} ---")
print(f"Sending: {packet.hex().upper()}")

ser.reset_input_buffer() # Clear anything sitting in the buffer
ser.write(packet)
ser.flush() # Ensure data physically leaves the TX pin

# Tiny pause for the automatic directional circuit on your board
time.sleep(0.05)

if ser.in_waiting > 0:
response = ser.read(ser.in_waiting)
print(f"RECEIVED: {response.hex().upper()}")
if len(response) >= 6:
# A valid response usually starts with FF FF
print("RESULT: Servo responded! Hardware communication is working.")
else:
print("RESULT: Received data, but it's too short (potentially an echo).")
else:
print("RESULT: Total silence. No response.")

try:
if ser.is_open:
print("Serial port opened at 1,000,000 baud")

# Test ID 1 (Standard default)
for servo_id in range(1, 6):
send_ping(servo_id)

# Test ID 254 (Broadcast - every servo should answer)
send_ping(254)

finally:
ser.close()
print("\nPort closed.")