dynamixel
Version:
Node.js library for controlling DYNAMIXEL servo motors via U2D2 interface with Protocol 2.0 support
209 lines (173 loc) โข 7.71 kB
JavaScript
import { DynamixelController } from '../index.js';
/**
* Example: Separated Device Discovery
* This example demonstrates how to:
* 1. Discover communication devices (USB/Serial) without connecting
* 2. Allow user to select a device
* 3. Connect to the selected device
* 4. Discover motors on that device
*
* This pattern is ideal for Electron applications where you want to:
* - Show available devices in a UI dropdown
* - Let user select which device to use
* - Only then connect and discover motors
*/
async function main() {
console.log('๐ DYNAMIXEL Separated Discovery Example');
console.log('========================================\n');
// Step 1: Discover available communication devices WITHOUT connecting
console.log('๐ก Step 1: Discovering communication devices...');
try {
const devices = await DynamixelController.discoverCommunicationDevices();
console.log(`\n๐ Discovery Results:`);
console.log(` USB Devices: ${devices.usb.length}`);
console.log(` Serial Devices: ${devices.serial.length}`);
console.log(` Web Serial Support: ${devices.webserial}`);
// Display USB devices
if (devices.usb.length > 0) {
console.log('\n๐ USB Devices:');
devices.usb.forEach((device, index) => {
const marker = device.isU2D2 ? 'โ
' : 'โช';
console.log(` ${index + 1}. ${marker} ${device.name}`);
if (device.isU2D2) {
console.log(` โ Recommended U2D2 device`);
}
});
}
// Display Serial devices
if (devices.serial.length > 0) {
console.log('\n๐ก Serial Devices:');
devices.serial.forEach((device, index) => {
const marker = device.isU2D2 ? 'โ
' : 'โช';
console.log(` ${index + 1}. ${marker} ${device.name}`);
if (device.isU2D2) {
console.log(` โ Likely U2D2 device (FTDI chip)`);
}
});
}
// Step 2: Get U2D2-specific devices
console.log('\n๐ฏ Step 2: Finding U2D2-compatible devices...');
const u2d2Devices = await DynamixelController.discoverU2D2Devices();
if (u2d2Devices.length === 0) {
console.log('โ No U2D2-compatible devices found!');
console.log('\n๐ก Make sure:');
console.log(' - U2D2 device is connected via USB');
console.log(' - Drivers are installed');
console.log(' - Device is not being used by other software');
return;
}
console.log(`\nโ
Found ${u2d2Devices.length} U2D2-compatible device(s):`);
u2d2Devices.forEach((device, index) => {
console.log(` ${index + 1}. ${device.name}`);
if (device.type === 'serial') {
console.log(` Path: ${device.path}`);
console.log(` Manufacturer: ${device.manufacturer || 'Unknown'}`);
}
});
// Step 3: Simulate device selection (in a real app, user would select from UI)
console.log('\n๐ฏ Step 3: Selecting device...');
const selectedDevice = u2d2Devices[0]; // Select first available device
console.log(`Selected: ${selectedDevice.name}`);
// Step 4: Create controller with deferred connection
console.log('\n๐๏ธ Step 4: Creating DynamixelController with deferred connection...');
const controller = new DynamixelController({
deferConnection: true, // Don't connect immediately
timeout: 3000,
debug: false
});
// Set up event listeners
controller.on('connected', () => {
console.log('โ
Connected to selected device');
});
controller.on('disconnected', () => {
console.log('โ Disconnected from device');
});
controller.on('error', (error) => {
console.error('โ Error:', error.message);
});
// Step 5: Connect to the selected device
console.log('\n๐ Step 5: Connecting to selected device...');
const connected = await controller.connectToDevice(selectedDevice);
if (!connected) {
console.error('โ Failed to connect to selected device');
return;
}
console.log('โ
Successfully connected!');
// Step 6: Now discover motors on the connected device
console.log('\n๐ค Step 6: Discovering DYNAMIXEL motors...');
console.log('Scanning for motors on the connected bus...\n');
let discoveredMotors = [];
// Quick motor discovery
try {
discoveredMotors = await controller.quickDiscovery((progress) => {
process.stdout.write(`\r Scanning motor ID ${progress.id}... (${progress.current}/${progress.total})`);
});
console.log(`\n Found ${discoveredMotors.length} motors in quick scan`);
} catch (error) {
console.log(`\n Motor discovery failed: ${error.message}`);
}
// Display discovered motors
if (discoveredMotors.length > 0) {
console.log('\n๐ค Discovered Motors:');
const devices = controller.getAllDevices();
devices.forEach(device => {
const info = device.getDeviceInfo();
const modelName = DynamixelController.getModelName(info.modelNumber);
console.log(` Motor ID ${info.id}: ${modelName} (Model: ${info.modelNumber}), FW: ${info.firmwareVersion}`);
});
// Test first motor
console.log('\n๐งช Testing first motor...');
const firstMotor = devices[0];
// Add a small delay to allow motor to settle after discovery
await new Promise(resolve => setTimeout(resolve, 500));
try {
console.log(` Pinging motor ${firstMotor.id}...`);
await firstMotor.ping();
console.log(` โ
Motor ${firstMotor.id} is responding`);
// Get status
const temperature = await firstMotor.getPresentTemperature();
const voltage = await firstMotor.getPresentVoltage();
const position = await firstMotor.getPresentPosition();
console.log(` Status for Motor ${firstMotor.id}:`);
console.log(` Temperature: ${temperature}ยฐC`);
console.log(` Voltage: ${firstMotor.voltageToVolts(voltage).toFixed(1)}V`);
console.log(` Position: ${position} (${firstMotor.positionToDegrees(position).toFixed(1)}ยฐ)`);
} catch (error) {
console.log(` โ Error testing motor: ${error.message}`);
}
} else {
console.log('\nโ No motors found on the bus');
console.log('\n๐ก Make sure:');
console.log(' - DYNAMIXEL motors are connected to the bus');
console.log(' - Motors are powered');
console.log(' - Baud rate matches (default: 57600)');
console.log(' - Motor IDs are in range 1-20 (or run full discovery)');
}
// Step 7: Cleanup
console.log('\n๐งน Step 7: Disconnecting...');
await controller.disconnect();
console.log('โ
Disconnected successfully');
} catch (error) {
console.error('\nโ Discovery process failed:', error.message);
}
console.log('\n๐ Separated discovery example complete!');
console.log('\n๐ก In an Electron app, you would:');
console.log(' 1. Run discoverCommunicationDevices() on app start');
console.log(' 2. Show devices in a dropdown/list UI');
console.log(' 3. Let user select a device');
console.log(' 4. Create controller with { deferConnection: true }');
console.log(' 5. Call connectToDevice(selectedDevice)');
console.log(' 6. Run motor discovery after connection');
}
// Handle process termination
process.on('SIGINT', async () => {
console.log('\n\nโ ๏ธ Received SIGINT, shutting down gracefully...');
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('\n\nโ ๏ธ Received SIGTERM, shutting down gracefully...');
process.exit(0);
});
// Run the example
main().catch(console.error);