### Arduino Example: Control Mode Source: https://github.com/project-sternbergia/cybergear_m5/blob/main/README.md An Arduino sketch demonstrating control modes (Position, Speed, Current) for the cybergear_m5. It utilizes M5 stack buttons for mode changes and value adjustments. Users can switch between ESP32_CAN library by commenting specific lines. ```arduino // Check cybergear behaviour using M5 stack. // Middle Button - Change Control Mode (Position Mode -> Speed Mode -> Current Mode) // Right Button - Increase control value // Left Button - Decrease control value // If you want to use ESP32_CAN library, please commentin [this lines](https://github.com/project-sternbergia/cybergear_m5/blob/bca92165be36318d6ae63f8e38ba0b4d76887dc3/examples/control_mode_example/control_mode_example.ino#L6-L7). // #include // #include // Example usage (actual code not provided in the text, this is a placeholder): void setup() { // Initialization code } void loop() { // Main loop code } ``` -------------------------------- ### Arduino Example: Bilateral Control Source: https://github.com/project-sternbergia/cybergear_m5/blob/main/README.md An Arduino sketch for controlling two cybergears in a leader-follower configuration. Before running, the CAN IDs for the leader (0x7F) and follower (0x7E) cybergears must be set. This example requires flashing the sketch to the M5 stack via Arduino IDE. ```arduino // This example use two cybergears for leader and follower. // Before you test this example, please change cybergear can id as follows. // After that write [cybergear_m5/examples/cybergear_bilateral.ino](https://github.com/project-sternbergia/cybergear_m5/blob/main/examples/cybergear_bilateral.ino) to m5 stack throughout Arduino IDE. // * leader cybergear : 0x7F // * follower cybergear : 0x7E // Example usage (actual code not provided in the text, this is a placeholder): void setup() { // Initialization code } void loop() { // Main loop code } ``` -------------------------------- ### CybergearDriver - Single Motor Control Example Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Demonstrates how to use the `CybergearDriver` class for direct control of a single Xiaomi CyberGear motor. It covers initialization, setting motor mode, enabling the motor, and processing real-time status feedback including position, velocity, torque, and temperature. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" uint8_t MASTER_CAN_ID = 0x00; uint8_t MOTOR_CAN_ID = 0x7F; // Default CyberGear CAN ID CybergearDriver driver(MASTER_CAN_ID, MOTOR_CAN_ID); CybergearCanInterfaceMcp interface; MotorStatus status; void setup() { M5.begin(); interface.init(); // Initialize driver with CAN interface driver.init(&interface); // Initialize motor in position mode (MODE_POSITION=1, MODE_SPEED=2, MODE_CURRENT=3, MODE_MOTION=0) driver.init_motor(MODE_POSITION); // Set speed limit for position control (0-30 rad/s) driver.set_limit_speed(2.0f); // Enable the motor driver.enable_motor(); } void loop() { // Set target position (radians) driver.set_position_ref(1.57f); // ~90 degrees // Process incoming CAN packets and update motor status if (driver.process_packet()) { status = driver.get_motor_status(); // Access motor feedback Serial.printf("Position: %.2f rad\n", status.position); // -4pi to 4pi Serial.printf("Velocity: %.2f rad/s\n", status.velocity); // -30 to 30 Serial.printf("Torque: %.2f Nm\n", status.effort); // -12 to 12 Serial.printf("Temperature: %.1f C\n", status.temperature); } delay(10); } ``` -------------------------------- ### cybergear_m5 Position Control Mode Configuration Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Configures and utilizes the position control mode for a CyberGear motor. This example shows how to set target positions, speed limits, current limits, and PID gains, responding to M5Stack button presses to change the motor's target angle. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" CybergearDriver driver(0x00, 0x7F); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); driver.init(&interface); // Initialize in position mode driver.init_motor(MODE_POSITION); // Configure position control parameters driver.set_limit_speed(5.0f); // Max speed during positioning (rad/s) driver.set_limit_current(10.0f); // Current limit (A) driver.set_position_kp(30.0f); // Position control proportional gain driver.enable_motor(); } void loop() { M5.update(); // Move to different positions based on button input if (M5.BtnA.wasPressed()) { driver.set_position_ref(-3.14f); // Move to -180 degrees } if (M5.BtnB.wasPressed()) { driver.set_position_ref(0.0f); // Move to origin } if (M5.BtnC.wasPressed()) { driver.set_position_ref(3.14f); // Move to +180 degrees } driver.process_packet(); delay(10); } ``` -------------------------------- ### Bilateral Leader-Follower Control with CyberGear Motors (C++) Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Implements a leader-follower control system where one motor (follower) mirrors the position of another (leader) using current control mode. This setup requires two motors and a CAN interface. The follower attempts to match the leader's position, and the leader experiences resistance if the follower cannot keep up. ```cpp #include #include "cybergear_controller.hh" #include "cybergear_can_interface_mcp.hh" uint8_t MASTER_CAN_ID = 0x00; uint8_t LEADER_ID = 0x7F; uint8_t FOLLOWER_ID = 0x7E; std::vector motor_ids = {LEADER_ID, FOLLOWER_ID}; std::vector currents = {0.0f, 0.0f}; CybergearController controller(MASTER_CAN_ID); CybergearCanInterfaceMcp interface; const float MAX_CURRENT = 1.0f; // Safety limit (A) const float BILATERAL_GAIN = 30.0f; // Position error to current gain void setup() { M5.begin(); interface.init(); // First, move both motors to origin in position mode controller.init(motor_ids, MODE_POSITION, &interface); controller.enable_motors(); controller.send_position_command(motor_ids, {0.0f, 0.0f}); delay(1000); // Switch to current mode for bilateral control controller.init(motor_ids, MODE_CURRENT, &interface); controller.enable_motors(); } void loop() { M5.update(); // Send current commands controller.send_current_command(motor_ids, currents); // Get motor status std::vector status; if (controller.process_packet()) { controller.get_motor_status(status); // Calculate bilateral control currents // Leader feels resistance when follower can't keep up // Follower tries to match leader position float pos_error = status[1].position - status[0].position; currents[0] = pos_error * BILATERAL_GAIN; // Leader current currents[1] = -pos_error * BILATERAL_GAIN; // Follower current // Clamp currents for safety currents[0] = constrain(currents[0], -MAX_CURRENT, MAX_CURRENT); currents[1] = constrain(currents[1], -MAX_CURRENT, MAX_CURRENT); } } ``` -------------------------------- ### Configure CyberGear Motor Limits and Gains (C++) Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Demonstrates how to configure hardware and software limits, control gains, and other parameters for a CyberGear motor. This includes setting position limits, speed, current, and torque limits, as well as tuning PID control gains for position and velocity. These configurations are crucial for safe and effective motor operation. ```cpp #include #include "cybergear_controller.hh" #include "cybergear_can_interface_mcp.hh" CybergearController controller(0x00); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); std::vector motor_ids = {0x7F}; // Software configuration for position limits and offsets std::vector sw_configs = { CybergearSoftwareConfig( 0x7F, // motor id CW, // direction (CW=1, CCW=-1) 10.0f, // limit_speed (rad/s) 15.0f, // limit_current (A) 8.0f, // limit_torque (Nm) 3.14f, // upper_position_limit (rad) -3.14f, // lower_position_limit (rad) CW, // calibration direction 0.0f // position_offset (rad) ) }; controller.init(motor_ids, sw_configs, MODE_POSITION, &interface); // Hardware configuration (written to motor RAM) CybergearHardwareConfig hw_config; hw_config.id = 0x7F; hw_config.limit_speed = 10.0f; hw_config.limit_current = 15.0f; hw_config.limit_torque = 8.0f; hw_config.current_kp = 0.125f; hw_config.current_ki = 0.0158f; hw_config.current_filter_gain = 0.1f; controller.set_motor_config(hw_config); // Or set individual parameters controller.set_speed_limit(0x7F, 10.0f); controller.set_torque_limit(0x7F, 8.0f); controller.set_current_limit(0x7F, 15.0f); controller.set_position_control_gain(0x7F, 30.0f); controller.set_velocity_control_gain(0x7F, 2.0f, 0.002f); controller.enable_motors(); } ``` -------------------------------- ### Clone Arduino Libraries for cybergear_m5 Source: https://github.com/project-sternbergia/cybergear_m5/blob/main/README.md Clones necessary libraries for the cybergear_m5 project into the Arduino libraries directory. This includes MCP_CAN_LIB, RingBuffer, arduino-CAN, and cybergear_m5 itself. ```bash cd ~/Arduino/libraries git clone https://github.com/coryjfowler/MCP_CAN_lib.git git clone https://github.com/Locoduino/RingBuffer.git git clone git@github.com:project-sternbergia/arduino-CAN.git git clone https://github.com/project-sternbergia/cybergear_m5.git ``` -------------------------------- ### Initialize CAN Interface for cybergear_m5 Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Initializes the CAN interface for the cybergear_m5 library. Supports both MCP2515-based CAN modules (via SPI) and native ESP32 CAN transceivers. This step is crucial before creating a driver instance. ```cpp #include #include "cybergear_driver.hh" // Option 1: MCP2515-based CAN (M5Stack Commu module) #include "cybergear_can_interface_mcp.hh" CybergearCanInterfaceMcp interface; void setup() { M5.begin(); // Default pins: CS=12, INT=15 for M5Stack Commu module interface.init(); // Or specify custom pins // interface.init(12, 15); } // Option 2: ESP32 native CAN (PWRCAN or CAN Transceiver Unit) #include "cybergear_can_interface_esp32.hh" CybergearCanInterfaceEsp32 interface; void setup() { M5.begin(); // Default pins for CAN Transceiver Unit: RX=5, TX=15 interface.init(); // For PWRCAN module, specify pins // interface.init(16, 17); } ``` -------------------------------- ### Read Motor Parameters with Cybergear Driver (C++) Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Reads and displays all motor parameters for debugging and monitoring using the CybergearDriver. It initializes the M5Stack, CAN interface, and driver, then enters a loop to continuously fetch and print motor status including position, velocity, bus voltage, and various control parameters. Requires M5Stack and cybergear_driver libraries. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_esp32.hh" CybergearDriver driver(0x00, 0x7F); CybergearCanInterfaceEsp32 interface; void setup() { M5.begin(true, false, true); // LCD, SD, Serial interface.init(); driver.init(&interface); driver.init_motor(MODE_POSITION); delay(500); driver.enable_motor(); } void loop() { M5.update(); // Request individual parameters driver.get_mech_position(); driver.get_mech_velocity(); driver.get_vbus(); driver.get_rotation(); // Or dump all parameters at once (slower, ~1ms per parameter) driver.dump_motor_param(); driver.process_packet(); MotorParameter param = driver.get_motor_param(); M5.Lcd.fillScreen(BLACK); M5.Lcd.setCursor(0, 0); M5.Lcd.printf("Motor Parameters:\n"); M5.Lcd.printf(" Run Mode: %d\n", param.run_mode); M5.Lcd.printf(" Mech Pos: %.3f rad\n", param.mech_pos); M5.Lcd.printf(" Mech Vel: %.3f rad/s\n", param.mech_vel); M5.Lcd.printf(" VBus: %.2f V\n", param.vbus); M5.Lcd.printf(" Rotation: %d\n", param.rotation); M5.Lcd.printf(" Limit Speed: %.1f rad/s\n", param.limit_spd); M5.Lcd.printf(" Limit Torque: %.1f Nm\n", param.limit_torque); M5.Lcd.printf(" Limit Current: %.1f A\n", param.limit_cur); M5.Lcd.printf(" Loc KP: %.3f\n", param.loc_kp); M5.Lcd.printf(" Spd KP: %.3f\n", param.spd_kp); M5.Lcd.printf(" Spd KI: %.5f\n", param.spd_ki); delay(1000); } ``` -------------------------------- ### Zero Motor Position with Cybergear Driver (C++) Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Sets the current mechanical position of the motor as the zero reference point. This function is useful for establishing a home position in robotic applications. It initializes the M5Stack, CAN interface, and driver, then waits for a button press to trigger the zeroing operation. Requires M5Stack and cybergear_driver libraries. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" CybergearDriver driver(0x00, 0x7F); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); driver.init(&interface); driver.init_motor(MODE_POSITION); driver.enable_motor(); M5.Lcd.println("Press Button A to zero position"); } void loop() { M5.update(); if (M5.BtnA.wasPressed()) { // Set current position as zero driver.set_mech_position_to_zero(); M5.Lcd.println("Position zeroed!"); } if (driver.process_packet()) { MotorStatus status = driver.get_motor_status(); M5.Lcd.setCursor(0, 50); M5.Lcd.printf("Position: %.3f rad ", status.position); } delay(10); } ``` -------------------------------- ### Multi-Motor Control with CyberGearController Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Manages multiple CyberGear motors simultaneously for synchronized control in multi-axis applications. Initializes motors with specified IDs and control mode, then sends commands. Requires `cybergear_controller.hh` and `cybergear_can_interface_mcp.hh`. ```cpp #include #include "cybergear_controller.hh" #include "cybergear_can_interface_mcp.hh" uint8_t MASTER_CAN_ID = 0x00; std::vector motor_ids = {0x7F, 0x7E, 0x7D}; // Three motors CybergearController controller(MASTER_CAN_ID); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); // Initialize controller with motor IDs and control mode controller.init(motor_ids, MODE_POSITION, &interface); // Enable all motors controller.enable_motors(); } void loop() { // Send position commands to all motors std::vector positions = {0.0f, 1.57f, 3.14f}; controller.send_position_command(motor_ids, positions); // Process packets and get status if (controller.process_packet()) { std::vector status_list; controller.get_motor_status(status_list); for (size_t i = 0; i < status_list.size(); i++) { Serial.printf("Motor %d: pos=%.2f vel=%.2f\n", motor_ids[i], status_list[i].position, status_list[i].velocity); } } delay(10); } ``` -------------------------------- ### Motion Control Mode with CyberGear Driver Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Enables simultaneous position, velocity, and torque control for a single motor. Configures impedance parameters (kp, kd) for desired stiffness and damping. Requires `cybergear_driver.hh` and `cybergear_can_interface_mcp.hh`. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" CybergearDriver driver(0x00, 0x7F); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); driver.init(&interface); // Initialize in motion mode driver.init_motor(MODE_MOTION); driver.enable_motor(); } void loop() { static float target_position = 0.0f; static float direction = 1.0f; // Oscillate position between limits target_position += direction * 0.05f; if (target_position > 12.5f) { direction = -1.0f; target_position = 12.5f; } if (target_position < -12.5f) { direction = 1.0f; target_position = -12.5f; } // motor_control(position, velocity, torque, kp, kd) // position: -12.5 to 12.5 rad (P_MIN to P_MAX) // velocity: -30 to 30 rad/s // torque: -12 to 12 Nm // kp: 0 to 500 (position stiffness) // kd: 0 to 5 (velocity damping) driver.motor_control( target_position, // target position 0.0f, // target velocity 0.0f, // feedforward torque 50.0f, // kp - position gain 1.0f // kd - damping gain ); driver.process_packet(); delay(10); } ``` -------------------------------- ### Current (Torque) Control Mode with CyberGear Driver Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Directly controls motor current for torque applications using the CyberGear driver. Configures current PID gains and a low-pass filter. Requires `cybergear_driver.hh` and `cybergear_can_interface_mcp.hh`. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" CybergearDriver driver(0x00, 0x7F); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); driver.init(&interface); // Initialize in current mode driver.init_motor(MODE_CURRENT); // Configure current control parameters driver.set_current_kp(0.125f); // Current proportional gain driver.set_current_ki(0.0158f); // Current integral gain driver.set_current_filter_gain(0.1f); // Low-pass filter gain (0-1) driver.enable_motor(); } void loop() { M5.update(); // Set target current (-23A to 27A range) // Positive = clockwise torque, Negative = counter-clockwise float target_current = 0.5f; // 0.5A for gentle torque driver.set_current_ref(target_current); if (driver.process_packet()) { MotorStatus status = driver.get_motor_status(); M5.Lcd.setCursor(0, 0); M5.Lcd.printf("Current: %.2f A\n", target_current); M5.Lcd.printf("Torque: %.2f Nm\n", status.effort); } delay(10); } ``` -------------------------------- ### Speed Control Mode with CyberGear Driver Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Maintains a target velocity for a single motor using the CyberGear driver. Configures velocity PID gains and current limits. Requires the `cybergear_driver.hh` and `cybergear_can_interface_mcp.hh` headers. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" CybergearDriver driver(0x00, 0x7F); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); interface.init(); driver.init(&interface); // Initialize in speed mode driver.init_motor(MODE_SPEED); // Configure velocity control parameters driver.set_velocity_kp(2.0f); // Velocity proportional gain driver.set_velocity_ki(0.002f); // Velocity integral gain driver.set_limit_current(15.0f); // Current limit (A) driver.enable_motor(); } void loop() { M5.update(); MotorStatus status; // Set target velocity (-30 to 30 rad/s) float target_speed = 5.0f; // 5 rad/s clockwise driver.set_speed_ref(target_speed); if (driver.process_packet()) { status = driver.get_motor_status(); M5.Lcd.setCursor(0, 0); M5.Lcd.printf("Target: %.1f rad/s\n", target_speed); M5.Lcd.printf("Actual: %.1f rad/s\n", status.velocity); } delay(10); } ``` -------------------------------- ### Change CyberGear Motor CAN ID (C++) Source: https://context7.com/project-sternbergia/cybergear_m5/llms.txt Provides a code snippet to change the CAN ID of a CyberGear motor. This is essential when setting up multi-motor systems to ensure each motor has a unique identifier on the CAN bus. The new ID is stored in the motor's flash memory and requires a power cycle to take effect. ```cpp #include #include "cybergear_driver.hh" #include "cybergear_can_interface_mcp.hh" uint8_t MASTER_CAN_ID = 0x00; uint8_t CURRENT_CAN_ID = 0x7F; // Default CyberGear ID uint8_t NEW_CAN_ID = 0x7E; // Desired new ID CybergearDriver driver(MASTER_CAN_ID, CURRENT_CAN_ID); CybergearCanInterfaceMcp interface; void setup() { M5.begin(); M5.Lcd.printf("Changing CAN ID from 0x%02X to 0x%02X\n", CURRENT_CAN_ID, NEW_CAN_ID); interface.init(); driver.init(&interface); driver.init_motor(MODE_POSITION); // Change the motor's CAN ID (stored in motor flash) driver.change_motor_can_id(NEW_CAN_ID); M5.Lcd.println("CAN ID changed. Power cycle motor to apply."); } void loop() { M5.update(); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.