diff --git a/PythonExample/AmazingHand_ChangeID.py b/PythonExample/AmazingHand_ChangeID.py new file mode 100644 index 0000000..ea8a5a5 --- /dev/null +++ b/PythonExample/AmazingHand_ChangeID.py @@ -0,0 +1,135 @@ +import time +from rustypot import Scs0009PyController + + +# Configuration +SERIAL_PORT = "COM5" # Change to your serial port +BAUDRATE = 1000000 +TIMEOUT = 2.0 +TARGET_NEW_ID = 2 # Desired new motor ID + +# EEPROM Lock values (boolean) +EEPROM_UNLOCKED = False # Unlock EEPROM to allow writes +EEPROM_LOCKED = True # Lock EEPROM to protect settings + +SCAN_RANGE = range(1, 11) + + +def main(): + print("=" * 70) + print("Permanent Motor ID Change (EEPROM Lock/Unlock)") + print("=" * 70) + print(f"Target new ID: {TARGET_NEW_ID}\n") + + # Initialize controller + print("Step 1: Initializing controller...") + try: + controller = Scs0009PyController( + serial_port=SERIAL_PORT, + baudrate=BAUDRATE, + timeout=TIMEOUT, + ) + print("✓ Controller initialized\n") + except Exception as e: + print(f"✗ Failed to initialize: {e}") + return + + # Scan for motor + print("Step 2: Scanning for motor...") + current_id = None + for motor_id in SCAN_RANGE: + try: + result = controller.ping(motor_id) + if result: + current_id = motor_id + print(f"✓ Found motor at ID {current_id}\n") + break + except Exception: + pass + + if current_id is None: + print("✗ No motor found") + return + + if current_id == TARGET_NEW_ID: + print(f"Motor already has ID {TARGET_NEW_ID}") + return + + # Change ID with EEPROM lock/unlock + print(f"Step 3: Changing ID from {current_id} to {TARGET_NEW_ID}...") + + try: + # Step 1: Disable torque (REQUIRED for EEPROM writes) + print(" a) Disabling torque...") + controller.write_torque_enable(current_id, 0) + print(" ✓ Torque disabled") + time.sleep(0.5) + + # Step 2: Unlock EEPROM + print(" b) Unlocking EEPROM...") + controller.write_lock(current_id, EEPROM_UNLOCKED) + print(" ✓ EEPROM unlocked") + time.sleep(0.5) + + # Step 3: Write new ID + print(f" c) Writing new ID {TARGET_NEW_ID} to EEPROM...") + controller.write_id(current_id, TARGET_NEW_ID) + print(" ✓ ID written to EEPROM") + time.sleep(1.0) # Wait for EEPROM write to complete + + # Step 4: Lock EEPROM to protect settings + print(" d) Locking EEPROM to protect settings...") + controller.write_lock(TARGET_NEW_ID, EEPROM_LOCKED) + print(" ✓ EEPROM locked") + time.sleep(0.5) + + # Step 5: Verify the change + print(f" e) Verifying new ID {TARGET_NEW_ID}...") + time.sleep(0.5) + result = controller.ping(TARGET_NEW_ID) + + if result: + print(f"\n✓ SUCCESS! Motor ID permanently changed to {TARGET_NEW_ID}\n") + + # Re-enable torque + print(" f) Re-enabling torque...") + controller.write_torque_enable(TARGET_NEW_ID, 1) + print(" ✓ Torque enabled") + + print("\n" + "=" * 70) + print(f"COMPLETE: Motor ID is now {TARGET_NEW_ID}") + print("EEPROM has been locked - settings are protected.") + print("This ID will persist after power cycling!") + print("=" * 70) + + print("\nVERIFICATION: Power cycle the motor to confirm") + print("1. Disconnect power from the motor") + print("2. Wait 5 seconds") + print("3. Reconnect power") + print("4. Run scanner - motor should still be at ID", TARGET_NEW_ID) + + else: + print(f"\n✗ Failed to verify new ID {TARGET_NEW_ID}") + + except Exception as e: + print(f"\n✗ Error during ID change: {e}") + print("\nTrying to re-lock EEPROM for safety...") + try: + # Try to lock with both possible IDs + try: + controller.write_lock(current_id, EEPROM_LOCKED) + except: + pass + try: + controller.write_lock(TARGET_NEW_ID, EEPROM_LOCKED) + except: + pass + print("EEPROM lock attempted") + except: + pass + import traceback + traceback.print_exc() + + +if __name__ == "__main__": + main() diff --git a/PythonExample/AmazingHand_Demo.py b/PythonExample/AmazingHand_Demo.py index ff1beb1..f4e7cef 100644 --- a/PythonExample/AmazingHand_Demo.py +++ b/PythonExample/AmazingHand_Demo.py @@ -23,8 +23,11 @@ def main(): - - c.write_torque_enable(1, 1) #1 = On / 2 = Off / 3 = Free + + # Enable torque for all 8 motors + for motor_id in range(1, 9): + c.write_torque_enable(motor_id, 1) #1 = On / 2 = Off / 3 = Free + t0 = time.time() while True: diff --git a/PythonExample/AmazingHand_FingerTest.py b/PythonExample/AmazingHand_FingerTest.py index c9081a0..bddf805 100644 --- a/PythonExample/AmazingHand_FingerTest.py +++ b/PythonExample/AmazingHand_FingerTest.py @@ -19,7 +19,8 @@ def main(): - c.write_torque_enable(1, 1) + c.write_torque_enable(ID_1, 1) + c.write_torque_enable(ID_2, 1) #1 = On / 2 = Off / 3 = Free while True: diff --git a/PythonExample/AmazingHand_ScanMotor.py b/PythonExample/AmazingHand_ScanMotor.py new file mode 100644 index 0000000..9aac039 --- /dev/null +++ b/PythonExample/AmazingHand_ScanMotor.py @@ -0,0 +1,126 @@ +import time +from rustypot import Scs0009PyController + + +# Configuration +SERIAL_PORT = "COM5" # Change to your serial port +TIMEOUT = 0.5 + +# Common baudrates for Feetech servos +BAUDRATES = [1000000, 500000, 115200, 57600, 38400, 19200, 9600] + +# Scan only a few IDs for faster testing (expand if needed) +QUICK_SCAN_RANGE = range(1, 11) # IDs 1-10 +FULL_SCAN_RANGE = range(0, 254) # All possible IDs + + +def scan_for_motors(controller, scan_range, baudrate): + """Scan for motors on the bus.""" + found_motors = [] + + for motor_id in scan_range: + try: + result = controller.ping(motor_id) + if result: + found_motors.append(motor_id) + print(f" ✓ Motor found at ID {motor_id}") + except Exception: + pass + + return found_motors + + +def main(): + """Main function to scan for motors.""" + print("=" * 70) + print("AmazingHand Motor Scanner") + print("=" * 70) + print(f"\nSerial Port: {SERIAL_PORT}") + print(f"Timeout: {TIMEOUT}s") + + print("\nAttempting to detect motors at different baudrates...") + print("This may take a moment...\n") + + all_found_motors = {} + + for baudrate in BAUDRATES: + print(f"\n{'='*70}") + print(f"Trying baudrate: {baudrate}") + print(f"{'='*70}") + + try: + controller = Scs0009PyController( + serial_port=SERIAL_PORT, + baudrate=baudrate, + timeout=TIMEOUT, + ) + print(f"Controller initialized at {baudrate} baud") + + # Quick scan first (IDs 1-10) + print(f"Quick scan (IDs {QUICK_SCAN_RANGE.start}-{QUICK_SCAN_RANGE.stop-1})...") + found_motors = scan_for_motors(controller, QUICK_SCAN_RANGE, baudrate) + + if found_motors: + all_found_motors[baudrate] = found_motors + print(f"\n✓ Found {len(found_motors)} motor(s) at {baudrate} baud: {found_motors}") + + # Get more info about the first motor + motor_id = found_motors[0] + try: + # Try to read model number + print(f"\nReading details for motor ID {motor_id}:") + position = controller.read_present_position(motor_id) + print(f" - Present Position: {position:.4f} rad ({position * 180/3.14159:.1f}°)") + + voltage = controller.read_present_voltage(motor_id) + print(f" - Present Voltage: {voltage:.2f}V") + + temperature = controller.read_present_temperature(motor_id) + print(f" - Temperature: {temperature}°C") + + except Exception as e: + print(f" - Could not read detailed info: {e}") + else: + print(f"No motors found in quick scan range") + + except Exception as e: + print(f"✗ Error at baudrate {baudrate}: {e}") + + # Summary + print("\n" + "=" * 70) + print("SCAN SUMMARY") + print("=" * 70) + + if all_found_motors: + print("\nMotors detected:") + for baudrate, motor_ids in all_found_motors.items(): + print(f" Baudrate {baudrate}: Motor IDs {motor_ids}") + + # Recommend settings + recommended_baudrate = list(all_found_motors.keys())[0] + recommended_ids = all_found_motors[recommended_baudrate] + print(f"\n✓ RECOMMENDED SETTINGS:") + print(f" Serial Port: {SERIAL_PORT}") + print(f" Baudrate: {recommended_baudrate}") + print(f" Detected Motor IDs: {recommended_ids}") + else: + print("\n⚠ No motors detected!") + print("\nTroubleshooting:") + print(" 1. Check that the motor is connected to the controller") + print(" 2. Verify the motor is powered (check power LED)") + print(" 3. Ensure the USB cable is properly connected") + print(" 4. Try connecting only ONE motor at a time") + print(" 5. Check that no other program is using the serial port") + + print("=" * 70) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + print("\n\nScan cancelled by user.") + except Exception as e: + print(f"\n\nUnexpected error: {e}") + import traceback + traceback.print_exc()