Step 6: Hands-On: Demo Run
Now that your basic communication is working, let's run the full OpenArm demo program to test complete system functionality. More details for control can be found here.
Prerequisites
Before running the demo, verify these prerequisites are complete:
- ✅ Motor IDs configured and tested (Steps 1, 3)
- ✅ CAN interface configured (Step 2)
- ✅ OpenArm CAN library built (Step 4)
- ✅ Motor zero position set to safe values, baudrate matches CAN interface configuration (Step 5)
- ZERO POSITION: Ensure you have set safe zero positions for all motors
- EMERGENCY STOP: Keep emergency stop button within immediate reach at ALL times
- CLEAR WORKSPACE: Remove ALL obstacles, tools, and personnel from arm movement area
- POWER DISCONNECT: Know how to quickly disconnect power if needed
Failure to follow these safety requirements may result in serious injury or equipment damage.
Connect the motors in a daisy-chain using XT30 2+2 cables. See detailed wiring instructions →
The default demo uses motors 0x01, 0x02, 0x07 (DM4310) on CAN0 with CANFD. If your setup matches, run directly:
./build/openarm-demo
Configure the Demo
Configured with your specific motor setup by editing openarm_can/examples
and rebuild if needed.
Find and update these sections to match your motor setup:
// Initialize arm motors
std::vector<openarm::damiao_motor::MotorType> motor_types = {
openarm::damiao_motor::MotorType::DM4310,
openarm::damiao_motor::MotorType::DM4310
};
std::vector<uint32_t> send_can_ids = {0x01, 0x02}; // Your motor send IDs
std::vector<uint32_t> recv_can_ids = {0x11, 0x12}; // Your motor receive IDs
Example configurations:
7-motor arm:
std::vector<openarm::damiao_motor::MotorType> motor_types = {
openarm::damiao_motor::MotorType::DM8009,
openarm::damiao_motor::MotorType::DM8009,
openarm::damiao_motor::MotorType::DM4340,
openarm::damiao_motor::MotorType::DM4340,
openarm::damiao_motor::MotorType::DM4310,
openarm::damiao_motor::MotorType::DM4310,
openarm::damiao_motor::MotorType::DM4310
};
std::vector<uint32_t> send_can_ids = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
std::vector<uint32_t> recv_can_ids = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
Ensure all three vectors (motor_types, send_can_ids, recv_can_ids) have the same length to avoid undefined behavior.
gripper
If you have a gripper, update the gripper configuration. Otherwise, remove all code using the gripper.
// Initialize gripper
openarm.init_gripper_motor(openarm::damiao_motor::MotorType::DM4310, 0x08, 0x18);
What the Demo Does
The demo program performs these operations:
- Initialization: Sets up CAN interface and motor communication
- Motor Query: Reads and displays motor IDs to verify configuration
- Motor Control:
- Enables all motors
- Performs position control tests
- Performs torque control tests
- Gripper Control: Opens and closes the gripper (if configured)
- Status Monitoring: Displays motor positions for 10 cycles
- Cleanup: Safely disables all motors
Modify the configuration as needed for your setup.
Rebuild the Demo
After modifying the configuration, rebuild the demo:
cmake --build build --target openarm-demo
Run the Demo
cd build
./openarm-demo
Expected Output
You should see output similar to:
=== OpenArm CAN Example ===
This example demonstrates the OpenArm API functionality
Initializing OpenArm CAN...
Initializing gripper...
=== Enabling Motors ===
=== Querying Motor Recv IDs ===
Arm Motor: 1 ID: 17
Arm Motor: 2 ID: 18
Gripper Motor: 8 ID: 24
=== Controlling Motors ===
Closing gripper...
Arm Motor: 1 position: 0.123
Arm Motor: 2 position: 0.456
Gripper Motor: 8 position: 0.789
...
Troubleshooting
- Use
candump
to monitor CAN communication - Verify motor power supply (24V)
- Check cable connections (especially for daisy-chained setups)
What's Next
Congrats! You have completed the basic setup. If the demo runs successfully, you can now develop custom applications using the OpenArm API or try ROS2 integration.