C++ SDK - Revo2 灵巧手
系统要求
- Linux: Ubuntu 20.04/22.04 LTS (x86_64/aarch64), glibc ≥ 2.31
- macOS: 10.15+
- Windows: 10/11
快速开始
克隆仓库
shell
# 使用 HTTPS 方式
git clone https://github.com/BrainCoTech/stark-serialport-example.git
# 或使用 SSH 方式
git clone git@github.com:BrainCoTech/stark-serialport-example.git安装与配置
shell
# 安装依赖
# 需要: build-essential, cmake, make, gcc, g++ 等
# 安装 SDK 依赖库
./download-lib.sh
# 配置设备权限
# Linux 系统中,串口设备(如 /dev/ttyUSB0)通常归属于 dialout 或 tty 用户组
# 只有该组成员才能访问设备,例如:
# crw-rw---- 1 root dialout 188, 0 Aug 14 12:00 /dev/ttyUSB0
# 将当前用户添加到 dialout 组
sudo usermod -aG dialout $USER
# 注意:添加后需要重新登录才能生效
# 编译并运行示例(跨平台统一目录)
cd c && make
cd demo && ./hand_demo.exe # 自动检测设备并运行shell
# 安装 Xcode 或 Xcode Command Line Tools
xcode-select --install
# 安装 SDK 依赖库
./download-lib.sh
# 编译并运行示例(跨平台统一目录)
cd c && make
cd demo && ./hand_demo.exe # 自动检测设备并运行shell
# 需要 MinGW 或 MSVC 编译环境
# 安装 SDK 依赖库
./download-lib.sh
# 编译并运行示例(跨平台统一目录)
cd c && make
cd demo && hand_demo.exe # 自动检测设备并运行示例代码
SDK 提供了丰富的示例代码,涵盖不同通信协议和应用场景。
跨平台示例(推荐)⭐
统一的跨平台示例,支持自动检测设备和多种通信协议。
shell
cd c
make
cd demo
./hand_demo.exe # 自动检测设备并运行演示| 示例 | 说明 |
|---|---|
| hand_demo.cpp | 综合演示(8种模式:位置/速度/电流控制、动作序列、触觉传感器等) |
| hand_monitor.cpp | 实时数据监控(电机状态、触觉数据) |
| hand_dfu.cpp | 固件升级 |
| auto_detect.cpp | 设备自动检测 |
支持的初始化方式:
shell
./hand_demo.exe # 自动检测(推荐)
./hand_demo.exe -m /dev/ttyUSB0 460800 127 # Modbus
./hand_demo.exe -c /dev/cu.usbmodem14201 1000000 1 # CAN 2.0 (ZQWL)
./hand_demo.exe -f /dev/cu.usbmodem14201 1000000 5000000 127 # CANFD (ZQWL)
./hand_demo.exe -s can0 1 # SocketCAN (Linux)Modbus-RTU 协议
单手/双手控制
触觉传感器
固件升级
CANFD 协议
单手控制示例
- 自定义 CANFD 设备 - C++ 示例
- ZLG USBCANFD 设备 - C++ 示例
- ZQWL USBCANFD 设备 - C++ 示例
固件升级
EtherCAT 协议
API 参考
初始化配置
c
#ifndef SETUP_H
#define SETUP_H
#include <stdint.h>
/**
* @brief Log level enumeration
* Defines supported log output levels, higher levels show more detailed log information
*/
enum LogLevel : uint8_t {
LOG_LEVEL_ERROR = 0, ///< Error level: only shows error messages
LOG_LEVEL_WARN = 1, ///< Warning level: shows warning and above level messages
LOG_LEVEL_INFO = 2, ///< Info level: shows general information and above levels
LOG_LEVEL_DEBUG = 3, ///< Debug level: shows debug information and above levels
LOG_LEVEL_TRACE = 4, ///< Trace level: shows all levels of detailed trace information
};
/**
* @brief Communication protocol type enumeration
* Defines supported communication protocol types
*/
enum StarkProtocolType : uint8_t {
STARK_PROTOCOL_TYPE_MODBUS = 1, ///< Modbus protocol: serial communication protocol
STARK_PROTOCOL_TYPE_CAN = 2, ///< CAN 2.0 protocol: Controller Area Network (1Mbps)
STARK_PROTOCOL_TYPE_CAN_FD = 3, ///< CAN FD protocol: CAN with Flexible Data-Rate (1Mbps arb, 5Mbps data)
STARK_PROTOCOL_TYPE_ETHER_CAT = 4, ///< EtherCAT protocol: Ethernet fieldbus (Linux only)
STARK_PROTOCOL_TYPE_PROTOBUF = 5, ///< Protobuf protocol: Legacy protocol (Revo1 only)
};
/**
* @brief Initialize SDK logging
* Sets log output level for SDK operations
* @param log_level Log output level, default is LOG_LEVEL_INFO
* @note Call this function before using other APIs to enable logging
* @example
* init_logging(LOG_LEVEL_INFO);
*/
void init_logging(LogLevel log_level);
/**
* @brief List all available serial ports
* Prints available serial ports to stdout
*/
void list_available_ports();
#endif // SETUP_H自动检测设备
c
#ifndef AUTO_DETECT_H
#define AUTO_DETECT_H
#include <stdint.h>
#include <stdbool.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
typedef struct CDeviceConfig CDeviceConfig;
typedef struct CDetectedDevice CDetectedDevice;
typedef struct CDetectedDeviceList CDetectedDeviceList;
typedef struct ZqwlDeviceList ZqwlDeviceList;
typedef struct CZqwlDeviceInfo CZqwlDeviceInfo;
enum StarkProtocolType : uint8_t {
STARK_PROTOCOL_TYPE_MODBUS = 1,
STARK_PROTOCOL_TYPE_CAN = 2,
STARK_PROTOCOL_TYPE_CAN_FD = 3,
STARK_PROTOCOL_TYPE_ETHER_CAT = 4,
STARK_PROTOCOL_TYPE_PROTOBUF = 5,
};
enum StarkHardwareType : uint8_t {
STARK_HARDWARE_TYPE_REVO1_PROTOBUF = 0,
STARK_HARDWARE_TYPE_REVO1_BASIC = 1,
STARK_HARDWARE_TYPE_REVO1_TOUCH = 2,
STARK_HARDWARE_TYPE_REVO1_ADVANCED = 3,
STARK_HARDWARE_TYPE_REVO1_ADVANCED_TOUCH = 4,
STARK_HARDWARE_TYPE_REVO2_BASIC = 5,
STARK_HARDWARE_TYPE_REVO2_TOUCH = 6,
STARK_HARDWARE_TYPE_REVO2_TOUCH_PRESSURE = 7,
};
enum SkuType : uint8_t {
SKU_TYPE_MEDIUM_RIGHT = 1,
SKU_TYPE_MEDIUM_LEFT = 2,
SKU_TYPE_SMALL_RIGHT = 3,
SKU_TYPE_SMALL_LEFT = 4,
};
/**
* @brief Detected device information (C interface)
*/
struct CDetectedDevice {
StarkProtocolType protocol; ///< Protocol type
char *port_name; ///< Port name (serial port or CAN adapter port)
uint8_t slave_id; ///< Slave ID on the bus
uint32_t baudrate; ///< Baudrate (for Modbus/serial, or CAN arbitration)
uint32_t data_baudrate; ///< Data baudrate (for CANFD only, 0 for others)
StarkHardwareType hardware_type; ///< Hardware type
SkuType sku_type; ///< SKU type
char *serial_number; ///< Serial number (NULL if not detected)
char *firmware_version; ///< Firmware version (NULL if not detected)
};
/**
* @brief Detected device list (C interface)
*/
struct CDetectedDeviceList {
CDetectedDevice *devices; ///< Device array pointer
size_t count; ///< Device count
};
/**
* @brief ZQWL device info struct (C interface)
*/
struct CZqwlDeviceInfo {
uint16_t device_type; ///< Device type
char *port_name; ///< Serial port name
uint16_t vid; ///< USB VID
uint16_t pid; ///< USB PID
bool supports_canfd; ///< Whether CANFD is supported
uint8_t channel_count; ///< Number of channels
};
/**
* @brief ZQWL device list struct (C interface)
*/
struct ZqwlDeviceList {
CZqwlDeviceInfo *devices; ///< Device array pointer
size_t count; ///< Device count
};
// ============================================================================
// Recommended: High-Level Auto-Detect API (Supports All Protocols)
// ============================================================================
/**
* @brief Auto-detect Stark devices across all protocols (Recommended)
*
* Scans for devices in priority order:
* 1. ZQWL CANFD (Revo2: IDs 0x7E, 0x7F)
* 2. ZQWL CAN 2.0 (Revo1/Revo2: IDs 1, 2)
* 3. Modbus/RS485 (IDs 0x7E, 0x7F, 1, 2, 10)
*
* @param scan_all If true, scan for all devices. If false, stop at first found.
* @param port Optional port name to scan. If NULL, scans all available ports.
* @param protocol Protocol to use (0=auto, 1=Modbus, 2=Can, 3=CanFd)
* @return Pointer to CDetectedDeviceList. Call free_detected_device_list to free.
* @retval Empty list (count=0) if no devices found.
*
* @example
* // Simple auto-detect (recommended)
* CDetectedDeviceList *list = stark_auto_detect(false, NULL, 0);
* if (list && list->count > 0) {
* CDetectedDevice *dev = &list->devices[0];
* printf("Found: %s on %s, ID: %d\n",
* dev->protocol == STARK_PROTOCOL_TYPE_CAN_FD ? "CANFD" : "Modbus",
* dev->port_name, dev->slave_id);
*
* // Initialize from detected device
* DeviceHandler *handle = init_from_detected(dev);
* // ... use handle ...
* close_device_handler(handle, dev->protocol);
* }
* free_detected_device_list(list);
*/
CDetectedDeviceList *stark_auto_detect(bool scan_all, const char *port, uint8_t protocol);
/**
* @brief Initialize device handler from detected device info (Recommended)
*
* This function initializes the appropriate transport (Modbus, CAN, CANFD)
* based on the detected device's protocol and returns a ready-to-use handler.
*
* @param device Pointer to CDetectedDevice from stark_auto_detect()
* @return Pointer to DeviceHandler on success, NULL on failure
*
* @note For CAN/CANFD: Initializes ZQWL adapter automatically
* @note For Modbus: Opens serial port with detected baudrate
* @note Call close_device_handler() to cleanup
*/
DeviceHandler *init_from_detected(const CDetectedDevice *device);
/**
* @brief Close device handler based on protocol type
*
* Convenience function that handles cleanup for any protocol type.
* Automatically closes ZQWL adapter for CAN/CANFD protocols.
*
* @param handle Device handler to close
* @param protocol Protocol type (from CDetectedDevice.protocol)
*/
void close_device_handler(DeviceHandler *handle, uint8_t protocol);
/**
* @brief Free detected device list memory
* @param list CDetectedDeviceList pointer returned by stark_auto_detect
*/
void free_detected_device_list(CDetectedDeviceList *list);
// ============================================================================
// ZQWL CAN/CANFD Adapter API
// ============================================================================
/**
* @brief List all ZQWL USB CAN/CANFD devices
*
* @return Device list pointer. Call free_zqwl_device_list to free.
* @retval List with count=0 if no devices found.
*
* @note This is a low-level API. Recommend using stark_auto_detect + init_from_detected.
*/
ZqwlDeviceList *list_zqwl_devices(void);
/**
* @brief Free ZQWL device list memory
* @param list ZqwlDeviceList pointer
*/
void free_zqwl_device_list(ZqwlDeviceList *list);
/**
* @brief Initialize ZQWL CAN device (CAN 2.0 mode)
*
* @param port_name Serial port name (e.g., "/dev/cu.usbmodem*" or "COM3")
* @param arb_baudrate Arbitration baudrate (bps), typically 1000000
* @return 0 on success, -1 on failure
*
* @note This is a low-level API. Recommend using stark_auto_detect + init_from_detected.
*/
int init_zqwl_can(const char *port_name, uint32_t arb_baudrate);
/**
* @brief Initialize ZQWL CANFD device
*
* @param port_name Serial port name
* @param arb_baudrate Arbitration baudrate (bps), typically 1000000
* @param data_baudrate Data baudrate (bps), typically 5000000
* @return 0 on success, -1 on failure
*
* @note This is a low-level API. Recommend using stark_auto_detect + init_from_detected.
*/
int init_zqwl_canfd(const char *port_name, uint32_t arb_baudrate, uint32_t data_baudrate);
/**
* @brief Close ZQWL CAN/CANFD device
*
* @note If device was initialized with init_from_detected, use close_device_handler instead.
*/
void close_zqwl(void);
/**
* @brief Scan CAN bus for devices
*
* @param candidate_ids Pointer to array of candidate device IDs
* @param candidate_count Number of candidate device IDs
* @param timeout_ms Timeout in milliseconds
* @return Found device ID (1-255), or 0 if no device found
*/
uint8_t scan_can_devices(const uint8_t *candidate_ids, size_t candidate_count, uint64_t timeout_ms);
// ============================================================================
// Legacy Auto-Detect API (Modbus Only)
// ============================================================================
/**
* @brief Legacy device configuration structure
* @deprecated Use CDetectedDevice instead
*/
struct CDeviceConfig {
StarkProtocolType protocol; ///< Protocol type
const char *port_name; ///< Port name
uint32_t baudrate; ///< Baud rate
uint8_t slave_id; ///< Slave device ID
};
/**
* @brief Automatically detect a Stark device on a serial port
*
* @deprecated Use stark_auto_detect + init_from_detected instead for multi-protocol support.
*
* @param port Serial port name; when NULL, auto-detect ports
* @param quick Whether to use quick detection
* @return Pointer to CDeviceConfig; call free_device_config to free
* @retval NULL Detection failed
*
* @note IMPORTANT: Only supports Modbus-RTU protocol detection
*/
CDeviceConfig *auto_detect_device(const char *port, bool quick);
/**
* @brief Automatically detect a Revo1 hand over Modbus-RTU
* @deprecated Use stark_auto_detect + init_from_detected instead.
*/
CDeviceConfig *auto_detect_modbus_revo1(const char *port, bool quick);
/**
* @brief Automatically detect a Revo2 hand over Modbus-RTU
* @deprecated Use stark_auto_detect + init_from_detected instead.
*/
CDeviceConfig *auto_detect_modbus_revo2(const char *port, bool quick);
/**
* @brief Free device configuration structure
* @param config CDeviceConfig pointer
*/
void free_device_config(CDeviceConfig *config);
#endif // AUTO_DETECT_H设备设置
c
#ifndef DEVICE_SETTINGS_H
#define DEVICE_SETTINGS_H
#include <stdint.h>
#include <stdbool.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Set device slave ID
*
* Changes the slave ID of the device. This is useful when controlling multiple
* devices on the same bus.
*
* @param handle Device handler
* @param slave_id Current slave device ID
* @param new_id New slave device ID to set
* @note Default is 1, valid range 1~247; 0 is the broadcast address
* @note Revo1 default ID is 1; Revo2 default left/right IDs are 0x7E and 0x7F
* @note When controlling multiple devices on the same bus, assign different IDs,
* e.g. left=1, right=2
* @warning Using broadcast ID 0 controls all devices on the bus; per Modbus spec,
* broadcast commands do not receive responses
* @example
* // Set left hand to ID 1, right hand to ID 2
* stark_set_slave_id(handle, 0x7E, 1); // Left hand
* stark_set_slave_id(handle, 0x7F, 2); // Right hand
*/
void stark_set_slave_id(DeviceHandler *handle, uint8_t slave_id, uint8_t new_id);
/**
* @brief Get LED enabled state
* @param handle Device handler
* @param slave_id Device ID
* @return true if LED is enabled, false otherwise
*/
bool get_led_enabled(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Get buzzer enabled state
* @param handle Device handler
* @param slave_id Device ID
* @return true if buzzer is enabled, false otherwise
*/
bool get_buzzer_enabled(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Get vibration enabled state
* @param handle Device handler
* @param slave_id Device ID
* @return true if vibration is enabled, false otherwise
*/
bool get_vibration_enabled(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Set LED enabled state
* @param handle Device handler
* @param slave_id Device ID
* @param enabled true to enable LED, false to disable
*/
void set_led_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);
/**
* @brief Set buzzer enabled state
* @param handle Device handler
* @param slave_id Device ID
* @param enabled true to enable buzzer, false to disable
*/
void set_buzzer_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);
/**
* @brief Set vibration enabled state
* @param handle Device handler
* @param slave_id Device ID
* @param enabled true to enable vibration, false to disable
*/
void set_vibration_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);
/**
* @brief Query whether automatic position calibration on power-up is enabled
* @param handle Device handler
* @param slave_id Device ID
* @return true if auto-calibration is enabled, false otherwise
*/
bool stark_get_auto_calibration(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Enable or disable automatic position calibration on power-up
* @param handle Device handler
* @param slave_id Device ID
* @param enabled true to enable auto-calibration, false to disable
*/
void stark_set_auto_calibration(DeviceHandler *handle, uint8_t slave_id, bool enabled);
/**
* @brief Send manual position-calibration command
*
* Triggers a manual calibration of finger positions.
*
* @param handle Device handler
* @param slave_id Device ID
* @note Ensure fingers are in a known position before calibrating
*/
void stark_send_calibrate_position(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Reset default gestures to factory settings
*
* Restores all built-in gestures (open, fist, pinch, etc.) to their
* factory default configurations.
*
* @param handle Device handler
* @param slave_id Device ID
*/
void stark_reset_default_gesture(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Reset all settings to factory defaults
*
* Resets all device settings including:
* - Default IDs: left hand → 0x7E (126); right hand → 0x7F (127)
* - RS485 baud rate: 460800 bps
* - CAN FD baud rate: 5 Mbps
*
* @param handle Device handler
* @param slave_id Device ID
* @warning This will reset ALL device settings. Use with caution.
*/
void stark_reset_default_settings(DeviceHandler *handle, uint8_t slave_id);
#endif // DEVICE_SETTINGS_H通信协议
Modbus-RTU
c
#ifndef MODBUS_REVO2_H
#define MODBUS_REVO2_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Open serial connection (Revo2 only)
* Initializes and establishes high-speed serial communication connection with Revo2 device
* @param port Serial port device name, e.g., "/dev/ttyUSB0" (Linux), "COM1" (Windows)
* @param baudrate Serial baud rate, Revo2 supports: 460800 (default), 1M, 2M, 5M
* @return DeviceHandler structure pointer (must be freed with modbus_close)
* @retval NULL Connection failed or invalid parameters
* @note The returned pointer points to dynamically allocated memory and must be freed
* @note Revo2 supports higher baud rates, suitable for high-speed data transfer scenarios
* @warning Using unsupported baud rate may cause communication failure
*/
DeviceHandler *modbus_open(const char *port, uint32_t baudrate);
/**
* @brief Close serial connection
* Disconnects serial connection and releases memory allocated by modbus_open
* @param handle DeviceHandler structure pointer returned by modbus_open
* @note Passing NULL is safe, the function will return directly
* @note After calling this function, the handle pointer becomes invalid and should not be used
*/
void modbus_close(DeviceHandler *handle);
#endif // MODBUS_REVO2_HCANFD
c
#ifndef CANFD_H
#define CANFD_H
#include <stdint.h>
#include <stdbool.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
// ============================================================================
// Recommended: Use stark_auto_detect + init_from_detected (see auto_detect.h)
// ============================================================================
/**
* @brief Create a new CANFD DeviceHandler
*
* @param protocol_type Protocol type (STARK_PROTOCOL_TYPE_CAN_FD or STARK_PROTOCOL_TYPE_CAN)
* @param master_id Master device ID (usually 0)
* @return Pointer to DeviceHandler (must be freed with close_device_handler)
*
* @note Before calling this, you must either:
* 1. Call init_zqwl_canfd() for ZQWL adapter, or
* 2. Set custom CAN callbacks with set_can_tx_callback/set_can_rx_callback
*
* @example
* // Using ZQWL adapter
* init_zqwl_canfd("/dev/cu.usbmodem12345", 1000000, 5000000);
* DeviceHandler *handle = init_device_handler(STARK_PROTOCOL_TYPE_CAN_FD, 0);
* // ... use handle ...
* close_device_handler(handle, STARK_PROTOCOL_TYPE_CAN_FD);
*/
DeviceHandler *init_device_handler(uint8_t protocol_type, uint8_t master_id);
/**
* @brief Create a DeviceHandler with hardware type pre-set
*
* Useful when you already know the hardware type (e.g., from auto_detect)
* and want to avoid an extra get_device_info call.
*
* @param protocol_type Protocol type
* @param master_id Master device ID
* @param slave_id Slave ID to set hardware type for
* @param hw_type Hardware type (StarkHardwareType enum value)
* @return Pointer to DeviceHandler
*/
DeviceHandler *init_device_handler_with_hw_type(uint8_t protocol_type,
uint8_t master_id,
uint8_t slave_id,
uint8_t hw_type);
// ============================================================================
// CAN/CANFD Communication Callbacks (for custom adapters like ZLG)
// ============================================================================
/**
* @brief CAN/CANFD TX callback type
*
* @param slave_id Slave ID
* @param can_id CAN ID
* @param data Data buffer
* @param data_len Data length
* @return 0 on success, non-zero on failure
*/
typedef int32_t (*CanTxCallback)(uint8_t slave_id,
uint32_t can_id,
const uint8_t *data,
size_t data_len);
/**
* @brief CAN/CANFD RX callback type
*
* @param slave_id Slave ID
* @param expected_can_id Expected CAN ID to filter responses
* @param expected_frames Expected frame count (0=auto-detect)
* @param can_id_out Output CAN ID
* @param data_out Output data buffer (must be at least 512 bytes)
* @param data_len_out Output data length
* @return 0 on success, non-zero on failure
*/
typedef int32_t (*CanRxCallback)(uint8_t slave_id,
uint32_t expected_can_id,
uint8_t expected_frames,
uint32_t *can_id_out,
uint8_t *data_out,
size_t *data_len_out);
/**
* @brief Set CAN/CANFD TX callback
* @param cb TX callback function
*/
void set_can_tx_callback(CanTxCallback cb);
/**
* @brief Set CAN/CANFD RX callback
* @param cb RX callback function
*/
void set_can_rx_callback(CanRxCallback cb);
#endif // CANFD_HEtherCAT
c
#ifndef ETHERCAT_H
#define ETHERCAT_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief EtherCAT FoE (File over EtherCAT) firmware type
*/
enum EtherCATFoeType : uint8_t {
ETHER_CAT_FOE_TYPE_WRIST = 1, ///< Wrist module firmware
ETHER_CAT_FOE_TYPE_CONTROL = 2, ///< Main controller firmware
};
// ================================
// EtherCAT Connection (Linux only)
// ================================
/**
* @brief Open the EtherCAT IgH Master
* @param master_pos Master position (typically 0)
* @return Pointer to DeviceHandler, NULL on failure
* @note Requires IgH EtherCAT Master installed on Linux
*/
DeviceHandler *ethercat_open_master(uint32_t master_pos);
/**
* @brief Close the EtherCAT IgH Master
* @param handle DeviceHandler from ethercat_open_master
*/
void ethercat_close(DeviceHandler *handle);
/**
* @brief Reserve the EtherCAT master for exclusive use
* Prevents other processes from accessing the master.
* @param handle DeviceHandler
*/
void ethercat_reserve_master(DeviceHandler *handle);
/**
* @brief Configure SDO for an EtherCAT slave device
* @param handle DeviceHandler
* @param slave_pos Slave position on the bus
*/
void ethercat_setup_sdo(DeviceHandler *handle, uint16_t slave_pos);
/**
* @brief Start EtherCAT cyclic loop with PDO communication
*
* @param handle DeviceHandler
* @param slave_positions Array of slave positions
* @param count Number of slaves
* @param dc_assign_activate DC flags (0x0000 = DC disabled, 0x0300 = typical)
* @param sync0_cycle_time SYNC0 cycle time in nanoseconds (loop period)
* @param sync0_shift_time SYNC0 phase shift in nanoseconds
* @param sync1_cycle_time SYNC1 cycle time in nanoseconds
* @param sync1_shift_time SYNC1 phase shift in nanoseconds
*/
void ethercat_start_loop(DeviceHandler *handle,
const uint16_t *slave_positions,
int count,
uint16_t dc_assign_activate,
uint32_t sync0_cycle_time,
int32_t sync0_shift_time,
uint32_t sync1_cycle_time,
int32_t sync1_shift_time);
/**
* @brief Stop the EtherCAT cyclic loop
* @param handle DeviceHandler
*/
void ethercat_stop_loop(DeviceHandler *handle);
/**
* @brief EtherCAT DFU: upgrade firmware via FoE protocol
*
* @param handle DeviceHandler
* @param slave_pos Slave position
* @param dfu_type DFU type (WRIST or CONTROL)
* @param file_path Firmware file path
*
* @note Revo2 EtherCAT requires two firmware files:
* - Wrist: revo2_ec_wrist_*.bin
* - Control: revo2_ec_ctrl_*.bin
*/
void ethercat_start_dfu(DeviceHandler *handle,
uint16_t slave_pos,
EtherCATFoeType dfu_type,
const char *file_path);
#endif // ETHERCAT_H设备信息
c
#ifndef DEVICE_INFO_H
#define DEVICE_INFO_H
#include <stdint.h>
#include <stdbool.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
typedef struct CDeviceInfo CDeviceInfo;
/**
* @brief Hardware type enumeration
* Defines supported hardware version types
*/
enum StarkHardwareType : uint8_t {
STARK_HARDWARE_TYPE_REVO1_PROTOBUF = 0, ///< Revo1 with legacy Protobuf protocol
STARK_HARDWARE_TYPE_REVO1_BASIC = 1, ///< Revo1 basic version (no touch)
STARK_HARDWARE_TYPE_REVO1_TOUCH = 2, ///< Revo1 with capacitive touch
STARK_HARDWARE_TYPE_REVO1_ADVANCED = 3, ///< Revo1 Advanced (Revo2 motor API)
STARK_HARDWARE_TYPE_REVO1_ADVANCED_TOUCH = 4,///< Revo1 Advanced with capacitive touch
STARK_HARDWARE_TYPE_REVO2_BASIC = 5, ///< Revo2 basic version (no touch)
STARK_HARDWARE_TYPE_REVO2_TOUCH = 6, ///< Revo2 with capacitive touch
STARK_HARDWARE_TYPE_REVO2_TOUCH_PRESSURE = 7,///< Revo2 with pressure/modulus touch
};
/**
* @brief SKU type enumeration
* Defines device hand type (left/right)
*/
enum SkuType : uint8_t {
SKU_TYPE_MEDIUM_RIGHT = 1, ///< Medium size right hand
SKU_TYPE_MEDIUM_LEFT = 2, ///< Medium size left hand
SKU_TYPE_SMALL_RIGHT = 3, ///< Small size right hand (reserved)
SKU_TYPE_SMALL_LEFT = 4, ///< Small size left hand (reserved)
};
/**
* @brief Device information structure
* Contains hardware type, SKU type, serial number, and firmware version
*/
struct CDeviceInfo {
SkuType sku_type; ///< SKU type (1: right hand, 2: left hand)
StarkHardwareType hardware_type; ///< Hardware type enum
const char *serial_number; ///< Device serial number
const char *firmware_version; ///< Firmware version string
};
/**
* @brief Get device information
* @param handle Device handler
* @param slave_id Device ID
* @return CDeviceInfo* - Device information (must be freed with free_device_info)
* @retval NULL Failed to get device info
*
* @example
* auto info = stark_get_device_info(handle, slave_id);
* if (info != NULL) {
* printf("SN: %s, FW: %s\n", info->serial_number, info->firmware_version);
*
* // Check device capabilities
* if (stark_is_touch_device(info->hardware_type)) {
* printf("Touch-enabled device\n");
* if (stark_uses_pressure_touch_api(info->hardware_type)) {
* printf("Using pressure/modulus touch sensors\n");
* }
* }
* free_device_info(info);
* }
*/
CDeviceInfo *stark_get_device_info(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Free device information structure
* @param info CDeviceInfo pointer
*/
void free_device_info(CDeviceInfo *info);
// ============================================================================
// Device Type Helper Functions
// ============================================================================
/**
* @brief Check if hardware type has touch sensor
* @param hw_type Hardware type enum value
* @return true if device has touch sensor
*/
bool stark_is_touch_device(uint8_t hw_type);
/**
* @brief Check if hardware type uses Revo1 Motor API
*
* Revo1 Basic/Touch use Revo1 Motor API.
* Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
*
* @param hw_type Hardware type enum value
* @return true if uses Revo1 Motor API
* @note To check Revo2 Motor API, use: !stark_uses_revo1_motor_api(hw_type)
*/
bool stark_uses_revo1_motor_api(uint8_t hw_type);
/**
* @brief Check if hardware type uses Revo1 Touch API
*
* Revo1 Touch API has different sensor counts per finger (capacitive).
* Includes Revo1Touch and Revo1AdvancedTouch.
*
* @param hw_type Hardware type enum value
* @return true if uses Revo1 Touch API
*/
bool stark_uses_revo1_touch_api(uint8_t hw_type);
/**
* @brief Check if hardware type uses Revo2 Touch API
*
* Revo2 Touch API has uniform sensor counts per finger (capacitive).
*
* @param hw_type Hardware type enum value
* @return true if uses Revo2 Touch API
*/
bool stark_uses_revo2_touch_api(uint8_t hw_type);
/**
* @brief Check if hardware type uses Pressure/Modulus Touch API
*
* Pressure Touch API uses completely different data structure.
* Only Revo2TouchPressure uses this API.
*
* @param hw_type Hardware type enum value
* @return true if uses Pressure Touch API
*/
bool stark_uses_pressure_touch_api(uint8_t hw_type);
/**
* @brief Get touch sensor type from hardware type
* @param hw_type Hardware type enum value
* @return 0=None, 1=Capacitive, 2=Pressure
*/
uint8_t stark_get_touch_sensor_type(uint8_t hw_type);
/**
* @brief Get touch sensor vendor type by reading register
* @param handle Device handler
* @param slave_id Device ID
* @return 0=Unknown, 1=Capacitive, 2=Pressure
* @note Call this for Revo2 Touch devices to determine actual sensor type
*/
uint8_t stark_get_touch_vendor(DeviceHandler *handle, uint8_t slave_id);
// ============================================================================
// CDeviceInfo Helper Functions
// ============================================================================
/**
* @brief Check if device uses Revo1 Motor API (from CDeviceInfo)
*/
bool device_info_uses_revo1_motor_api(const CDeviceInfo *info);
/**
* @brief Check if device uses Revo1 Touch API (from CDeviceInfo)
*/
bool device_info_uses_revo1_touch_api(const CDeviceInfo *info);
/**
* @brief Check if device uses Revo2 Touch API (from CDeviceInfo)
*/
bool device_info_uses_revo2_touch_api(const CDeviceInfo *info);
/**
* @brief Check if device has any touch sensor (from CDeviceInfo)
*/
bool device_info_is_touch(const CDeviceInfo *info);
// ============================================================================
// Device Configuration
// ============================================================================
/**
* @brief Get device battery voltage in mV
* @param handle Device handler
* @param slave_id Device ID
* @return Voltage in millivolts
*/
uint16_t stark_get_voltage(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Get RS-485 baud rate
* @param handle Device handler
* @param slave_id Device ID
* @return Baud rate value
* @note Revo1: 115200, 57600, 19200, 460800 (default: 115200)
* @note Revo2: 460800, 1M, 2M, 5M (default: 460800)
*/
uint32_t stark_get_rs485_baudrate(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Set RS-485 baud rate
* @param handle Device handler
* @param slave_id Device ID
* @param baudrate Baud rate to set
*/
void stark_set_rs485_baudrate(DeviceHandler *handle, uint8_t slave_id, uint32_t baudrate);
/**
* @brief Get CANFD data baud rate
* @param handle Device handler
* @param slave_id Device ID
* @return Baud rate value (1M, 2M, 4M, 5M)
*/
uint32_t stark_get_canfd_baudrate(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Set CANFD data baud rate
* @param handle Device handler
* @param slave_id Device ID
* @param baudrate Baud rate to set (1M, 2M, 4M, 5M)
*/
void stark_set_canfd_baudrate(DeviceHandler *handle, uint8_t slave_id, uint32_t baudrate);
/**
* @brief Set device slave ID
* @param handle Device handler
* @param slave_id Current slave ID
* @param new_id New slave ID to set
* @note Revo1 default: 1, Revo2 default: 0x7E (left), 0x7F (right)
*/
void stark_set_slave_id(DeviceHandler *handle, uint8_t slave_id, uint8_t new_id);
#endif // DEVICE_INFO_H关节控制
位置/速度/电流控制
c
#ifndef FINGER_POSITION_REVO2_H
#define FINGER_POSITION_REVO2_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Finger unit mode enumeration
*/
enum FingerUnitMode : uint8_t {
FINGER_UNIT_MODE_NORMALIZED = 0, ///< Normalized mode
FINGER_UNIT_MODE_PHYSICAL = 1, ///< Physical units mode
};
/**
* @brief Finger ID enumeration
* Defines unique identifiers for each finger of the dexterous hand
*/
enum StarkFingerId : uint8_t {
STARK_FINGER_ID_THUMB = 1, ///< Thumb
STARK_FINGER_ID_THUMB_AUX = 2, ///< Thumb Auxiliary
STARK_FINGER_ID_INDEX = 3, ///< Index Finger
STARK_FINGER_ID_MIDDLE = 4, ///< Middle Finger
STARK_FINGER_ID_RING = 5, ///< Ring Finger
STARK_FINGER_ID_PINKY = 6, ///< Pinky Finger
};
/**
* @brief Set finger control unit mode (Revo2 only)
* Configures the unit mode for finger control, resets to default after power-on
* @param handle Device handler
* @param slave_id Device ID
* @param mode Unit mode, supports normalized mode and physical units mode
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_unit_mode(DeviceHandler *handle, uint8_t slave_id, FingerUnitMode mode);
/**
* @brief Get finger control unit mode (Revo2 only)
* Retrieves the currently set finger control unit mode
* @param handle Device handler
* @param slave_id Device ID
* @return Current unit mode
* @retval FINGER_UNIT_MODE_NORMALIZED Default return value on read failure
* @note Only applicable to Revo2 devices
*/
FingerUnitMode stark_get_finger_unit_mode(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Set finger maximum position (Revo2 only)
* Configures the maximum position limit for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param max_pos Maximum position value, unit: degrees (°)
* @note Default values: [75, 94, 88, 88, 88, 88] for [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_max_position(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t max_pos);
/**
* @brief Get finger maximum position (Revo2 only)
* Retrieves the maximum position limit setting for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @return Maximum position value, unit: degrees (°)
* @retval 0 Returns 0 on read failure
* @note Only applicable to Revo2 devices
*/
uint16_t stark_get_finger_max_position(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id);
/**
* @brief Set finger minimum position (Revo2 only)
* Configures the minimum position limit for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param min_pos Minimum position value, unit: degrees (°)
* @note Default values: [0, 0, 0, 0, 0, 0] for all fingers
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_min_position(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t min_pos);
/**
* @brief Get finger minimum position (Revo2 only)
* Retrieves the minimum position limit setting for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @return Minimum position value, unit: degrees (°)
* @note Default values: [0, 0, 0, 0, 0, 0] for all fingers
* @retval 0 Returns 0 on read failure (note: normal minimum value can also be 0)
* @note Only applicable to Revo2 devices
*/
uint16_t stark_get_finger_min_position(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id);
/**
* @brief Set finger maximum speed (Revo2 only)
* Configures the maximum movement speed limit for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param max_speed Maximum speed value, unit: degrees per second (°/s)
* @note Default values: [145, 150, 130, 130, 130, 130] for [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_max_speed(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t max_speed);
/**
* @brief Get finger maximum speed (Revo2 only)
* Retrieves the maximum speed limit for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @return Maximum speed value, unit: degrees per second (°/s)
* @retval 0 Returns 0 on read failure
* @note Only applicable to Revo2 devices
*/
uint16_t stark_get_finger_max_speed(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id);
/**
* @brief Set finger maximum current (Revo2 only)
* Configures the maximum drive current limit for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param max_current Maximum current value, unit: milliamps (mA)
* @note Default value: 1000 mA (all fingers)
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_max_current(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t max_current);
/**
* @brief Get finger maximum current (Revo2 only)
* Retrieves the maximum current limit for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @return Maximum current value, unit: milliamps (mA)
* @retval 0 Returns 0 on read failure
* @note Only applicable to Revo2 devices
*/
uint16_t stark_get_finger_max_current(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id);
/**
* @brief Set finger protection current (Revo2 only)
* Configures the protection current threshold for a specified finger to prevent overload damage
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param protected_current Protection current value, unit: milliamps (mA), range 100~1500
* @note Default values: [500, 500, 500, 500, 500, 500] for all fingers
* @note When current exceeds this value, the system triggers protection mechanism
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_protected_current(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t protected_current);
/**
* @brief Get finger protection current (Revo2 only)
* Retrieves the protection current threshold for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @return Protection current value, unit: milliamps (mA), range 100~1500
* @retval 0 Returns 0 on read failure
* @note Only applicable to Revo2 devices
*/
uint16_t stark_get_finger_protected_current(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id);
/**
* @brief Set thumb auxiliary joint lock current (Revo2 only)
* Configures the lock current for thumb auxiliary joint to maintain joint position
* @param handle Device handler
* @param slave_id Device ID
* @param aux_lock_current Lock current value, unit: milliamps (mA), range 100~500
* @note Default value: 200 mA
* @note Only applicable to Revo2 devices
* @note This function is specifically for thumb auxiliary joint position holding
*/
void stark_set_thumb_aux_lock_current(DeviceHandler *handle,
uint8_t slave_id,
uint16_t aux_lock_current);
/**
* @brief Get thumb auxiliary joint lock current (Revo2 only)
* Retrieves the lock current setting for thumb auxiliary joint
* @param handle Device handler
* @param slave_id Device ID
* @return Lock current value, unit: milliamps (mA)
* @note Only applicable to Revo2 devices
*/
uint16_t stark_get_thumb_aux_lock_current(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Set single finger position (Revo2 only)
* Controls specified finger to move to target position
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param position Position value
* @note Revo1: range 0~100 (percentage)
* @note Revo2: range 0~1000 (normalized mode) or min-max position angle (physical mode, unit: degrees)
* @note Position control is the most basic finger control method
*/
void stark_set_finger_position(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t position);
/**
* @brief Set single finger position with duration (Revo2 only)
* Controls specified finger to move to target position within specified time
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param position Position value, range 0~1000 (normalized mode) or min-max position angle (physical mode)
* @param millis Expected duration, unit: milliseconds, range 1~2000ms
* @note Only applicable to Revo2 devices
* @note System automatically calculates appropriate movement speed based on expected duration
* @example
* stark_set_finger_position_with_millis(handle, slave_id,
* STARK_FINGER_ID_THUMB, 1000, 1000);
*/
void stark_set_finger_position_with_millis(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t position,
uint16_t millis);
/**
* @brief Set single finger position with speed (Revo2 only)
* Controls specified finger to move to target position at specified speed
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param position Position value, range 0~1000 (normalized mode) or min-max position angle (physical mode)
* @param speed Speed value, range 1~1000 (normalized mode) or min~max speed (°/s) (physical mode)
* @note Only applicable to Revo2 devices
* @note Provides more precise speed control
* @example
* stark_set_finger_position_with_speed(handle, slave_id,
* STARK_FINGER_ID_MIDDLE, 1000, 50);
*/
void stark_set_finger_position_with_speed(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
uint16_t position,
uint16_t speed);
/**
* @brief Set multiple finger positions
* Batch sets positions for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param positions Position value array, length 6, range 0~1000
* @param len Array length, must be 6
* @note Array order: [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
*/
void stark_set_finger_positions(DeviceHandler *handle,
uint8_t slave_id,
const uint16_t *positions,
uintptr_t len);
/**
* @brief Set multiple finger positions with durations (Revo2 only)
* Batch sets positions and expected durations for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param positions Position value array, length 6, range 0~1000 or min~max position (°)
* @param millis Expected duration array, length 6, range 1~2000ms
* @param len Array length, must be 6
* @note Position values and duration values correspond one-to-one
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_positions_and_durations(DeviceHandler *handle,
uint8_t slave_id,
const uint16_t *positions,
const uint16_t *millis,
uintptr_t len);
/**
* @brief Set multiple finger positions with speeds (Revo2 only)
* Batch sets positions and expected speeds for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param positions Position value array, length 6, range 0~1000 or min-max position (°)
* @param speeds Speed value array, length 6, range 1~1000 or min~max speed (°/s)
* @param len Array length, must be 6
* @note Position values and speed values correspond one-to-one
* @note Only applicable to Revo2 devices
* @example
* uint16_t positions[] = {300, 300, 500, 500, 500, 500};
* uint16_t speeds[] = {500, 500, 500, 500, 500, 500};
* stark_set_finger_positions_and_speeds(handle, slave_id, positions, speeds, 6);
*/
void stark_set_finger_positions_and_speeds(DeviceHandler *handle,
uint8_t slave_id,
const uint16_t *positions,
const uint16_t *speeds,
uintptr_t len);
/**
* @brief Set single finger speed (Revo2 only)
* Sets movement speed for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param speed Speed value, Revo1 range -100~100, Revo2 range -1000~1000 or -max speed~max speed (°/s)
* @note Sign indicates direction, positive for close direction, negative for open direction
* @example
* stark_set_finger_speed(handle, slave_id, STARK_FINGER_ID_MIDDLE, 500);
*/
void stark_set_finger_speed(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
int16_t speed);
/**
* @brief Set single finger current (Revo2 only)
* Sets current for a specified finger (current control mode)
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param current Current value, range -1000~1000 or -max current~max current (mA)
* @note Sign indicates direction, positive for close direction, negative for open direction
* @note Only applicable to Revo2 devices
* @example
* stark_set_finger_current(handle, slave_id, STARK_FINGER_ID_INDEX, -300);
*/
void stark_set_finger_current(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
int16_t current);
/**
* @brief Set single finger PWM (Revo2 only)
* Sets PWM for a specified finger (PWM control mode)
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID
* @param pwm PWM value, range -1000~1000
* @note Sign indicates direction, positive for close direction, negative for open direction
* @note Only applicable to Revo2 devices
*/
void stark_set_finger_pwm(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
int16_t pwm);
/**
* @brief Set multiple finger speeds
* Batch sets movement speeds for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param speeds Speed value array, length 6, Revo1 range -100~100, Revo2 range -1000~1000 or -max speed~max speed (°/s)
* @param len Array length, must be 6
* @note Sign indicates direction, positive for close direction, negative for open direction
*/
void stark_set_finger_speeds(DeviceHandler *handle,
uint8_t slave_id,
const int16_t *speeds,
uintptr_t len);
/**
* @brief Set multiple finger currents (Revo2 only)
* Batch sets currents for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param currents Current value array, length 6, range -1000~1000 or -max current~max current (mA)
* @param len Array length, must be 6
* @note Sign indicates direction, positive for close direction, negative for open direction
* @note Only applicable to Revo2 devices
* @example
* int16_t currents[] = {-300, -300, -300, -300, -300, -300};
* stark_set_finger_currents(handle, slave_id, currents, 6);
*/
void stark_set_finger_currents(DeviceHandler *handle,
uint8_t slave_id,
const int16_t *currents,
uintptr_t len);
/**
* @brief Set multiple finger PWMs (Revo2 only)
* Directly controls PWM output values for multiple fingers
* @param handle Device handler
* @param slave_id Device ID
* @param pwms PWM value array, length 6, range -1000~1000
* @param len Array length, must be 6
* @note Positive values indicate close direction, negative values indicate open direction
* @note Array order: [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
* @note Only applicable to Revo2 devices
* @warning PWM control is low-level control and should be used with caution
*/
void stark_set_finger_pwms(DeviceHandler *handle,
uint8_t slave_id,
const int16_t *pwms,
uintptr_t len);
#endif // FINGER_POSITION_REVO2_H电机状态
c
#ifndef MOTOR_STATUS_H
#define MOTOR_STATUS_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Motor status data structure
* Contains current positions, speeds, currents, and states for all motors
*/
struct MotorStatusData {
uint16_t positions[6]; ///< Current positions [0-1000]
int16_t speeds[6]; ///< Current speeds
int16_t currents[6]; ///< Current values
uint8_t states[6]; ///< Motor state flags
};
/**
* @brief Get motor status
* Retrieves current motor status including positions, speeds, currents, and states
* @param handle Device handler
* @param slave_id Device ID
* @return MotorStatusData* - Motor status structure (must be freed with free_motor_status_data)
* @retval NULL Failed to get status or invalid parameters
* @note The returned pointer points to dynamically allocated memory and must be freed
* @example
* auto status = stark_get_motor_status(handle, slave_id);
* if (status != NULL) {
* printf("Positions: %hu, %hu, %hu, %hu, %hu, %hu\n",
* status->positions[0], status->positions[1],
* status->positions[2], status->positions[3],
* status->positions[4], status->positions[5]);
* free_motor_status_data(status);
* }
*/
MotorStatusData *stark_get_motor_status(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Free motor status data structure
* Releases memory allocated by stark_get_motor_status
* @param status MotorStatusData structure pointer returned by stark_get_motor_status
* @note Passing NULL is safe, the function will return directly
*/
void free_motor_status_data(MotorStatusData *status);
#endif // MOTOR_STATUS_H传感器
触觉信息
c
#ifndef TOUCH_H
#define TOUCH_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Touch sensor raw data structure
* Contains raw channel data from tactile sensors
*/
struct TouchRawData {
uint32_t thumb[7]; ///< Thumb raw data (7 channels)
uint32_t index[11]; ///< Index finger raw data (11 channels)
uint32_t middle[11]; ///< Middle finger raw data (11 channels)
uint32_t ring[11]; ///< Ring finger raw data (11 channels)
uint32_t pinky[7]; ///< Pinky finger raw data (7 channels)
};
/**
* @brief Enable touch sensor function
* Enables specified touch sensors, all sensors are disabled by default after power-on
* @param handle Device handler
* @param slave_id Device ID
* @param mask Enabled touch sensor bitmask, range 0~31
* @note Uses bitmask representation, each bit corresponds to one sensor
* @example 0x01 enables only sensor 1 (thumb position)
* @example 0x1F enables all 5 sensors
* @note Only applicable to touch-enabled devices
* @example
* // Enable all touch sensors
* stark_enable_touch_sensor(handle, slave_id, 0x1F);
*/
void stark_enable_touch_sensor(DeviceHandler *handle, uint8_t slave_id, uint8_t mask);
/**
* @brief Get raw channel data from the tactile sensors
*
* Retrieves raw capacitance channel data from all tactile sensors.
*
* @param handle Device handler
* @param slave_id Device ID
* @return TouchRawData* - Raw data structure (must be freed with free_touch_raw_data)
* @retval NULL Failed to get data or device does not support touch function
* @note The returned pointer points to dynamically allocated memory and must be freed
* @note Only applicable to touch-enabled devices
*/
TouchRawData *stark_get_touch_raw_data(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Read 3D force, proximity and status for a single finger
*
* Retrieves tactile sensor data for one specific finger.
*
* @param handle Device handler
* @param slave_id Device ID
* @param index Finger index: 0~4 for thumb, index, middle, ring, pinky
* @return TouchFingerItem* - Single finger data (must be freed with free_touch_finger_item)
* @retval NULL Failed to get data or invalid index
* @note The returned pointer points to dynamically allocated memory and must be freed
* @note Only applicable to touch-enabled devices
*/
TouchFingerItem *stark_get_single_touch_status(DeviceHandler *handle,
uint8_t slave_id,
uint8_t index);
/**
* @brief Reset touch sensor acquisition channels
* Reinitializes specified touch sensor acquisition channels, clearing possible error states
* @param handle Device handler
* @param slave_id Device ID
* @param mask Reset touch sensor bitmask, range 0~31
* @note When executing this command, finger sensors should avoid force to ensure reset effectiveness
* @example 0x01 resets sensor 1
* @example 0xFF resets all 8 sensors
* @warning Sensor data may be inaccurate during reset process
*/
void stark_reset_touch_sensor(DeviceHandler *handle, uint8_t slave_id, uint8_t mask);
/**
* @brief Touch sensor parameter calibration
* Calibrates specified touch sensors, eliminating static offset errors
* @param handle Device handler
* @param slave_id Device ID
* @param mask Calibration touch sensor bitmask, range 0~31
* @note When 3D force values are not zero in idle state, use this method for calibration
* @note Ensure sensors are in force-free state during calibration
* @example 0x01 calibrates sensor 1
* @warning Do not touch sensors during calibration to avoid affecting calibration results
*/
void stark_calibrate_touch_sensor(DeviceHandler *handle, uint8_t slave_id, uint8_t mask);
/**
* @brief Touch sensor data structure
* Contains complete tactile information for a single sensor, including 3D force, capacitance values, and status
*
* @note Revo1 Touch: Contains complete 3D force data and capacitance values
* @note Revo2 Touch: Only contains normal force, tangential force, tangential direction, and proximity values; other values are 0
*/
struct TouchFingerItem {
// Normal force data (pressure perpendicular to contact surface)
uint16_t normal_force1; ///< Normal force 1, unit: 100×N (e.g., 1000 = 10N), measurement range: 0~25N
uint16_t normal_force2; ///< Normal force 2, unit: 100×N, measurement range: 0~25N
uint16_t normal_force3; ///< Normal force 3, unit: 100×N, invalid for thumb and pinky
// Tangential force data (friction force parallel to contact surface)
uint16_t tangential_force1; ///< Tangential force 1, unit: 100×N (e.g., 1000 = 10N), measurement range: 0~25N
uint16_t tangential_force2; ///< Tangential force 2, unit: 100×N, measurement range: 0~25N
uint16_t tangential_force3; ///< Tangential force 3, unit: 100×N, invalid for thumb and pinky
// Tangential force direction data
uint16_t tangential_direction1; ///< Tangential direction 1, unit: degrees, range: 0~359°, 0xFFFF = invalid
uint16_t tangential_direction2; ///< Tangential direction 2, unit: degrees, 0° toward fingertip, increases clockwise
uint16_t tangential_direction3; ///< Tangential direction 3, unit: degrees, invalid for thumb and pinky
// Proximity sensor data (capacitance values)
uint32_t self_proximity1; ///< Self-proximity capacitance 1, used to detect object approach
uint32_t self_proximity2; ///< Self-proximity capacitance 2, invalid for thumb and pinky
uint32_t mutual_proximity; ///< Mutual-proximity capacitance, invalid for thumb and pinky
uint16_t status; ///< Sensor status: 0=data normal, 1=data abnormal, 2=communication abnormal
};
/**
* @brief Touch sensor status data collection
* Contains tactile sensor data for all fingers
*/
struct TouchFingerData {
TouchFingerItem items[5]; ///< Tactile data array for 5 fingers: [Thumb, Index, Middle, Ring, Pinky]
};
/**
* @brief Get touch sensor status
* Retrieves tactile sensor data for all fingers, including 3D force, capacitance values, and status information
* @param handle Device handler
* @param slave_id Device ID
* @return TouchFingerData* - Structure pointer containing tactile data for 5 fingers (must be freed with free_touch_finger_data)
* @retval NULL Failed to get data or device does not support touch function
* @note The returned pointer points to dynamically allocated memory and must be freed
* @note Only applicable to touch-enabled devices
* @note Data order: [Thumb, Index, Middle, Ring, Pinky]
*/
TouchFingerData *stark_get_touch_status(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Free touch sensor status data
* Releases memory allocated by stark_get_touch_status
* @param status TouchFingerData structure pointer returned by stark_get_touch_status
* @note Passing NULL is safe, the function will return directly
* @note Do not use the pointer after freeing to avoid accessing freed memory
*/
void free_touch_finger_data(TouchFingerData *status);
/**
* @brief Free single touch finger item
* Releases memory allocated by stark_get_single_touch_status
* @param item TouchFingerItem structure pointer returned by stark_get_single_touch_status
* @note Passing NULL is safe, the function will return directly
*/
void free_touch_finger_item(TouchFingerItem *item);
/**
* @brief Free touch raw data
* Releases memory allocated by stark_get_touch_raw_data
* @param data TouchRawData structure pointer returned by stark_get_touch_raw_data
* @note Passing NULL is safe, the function will return directly
*/
void free_touch_raw_data(TouchRawData *data);
#endif // TOUCH_H高性能数据采集 ⭐
DataCollector(数据采集器)
c
#ifndef DATA_COLLECTOR_H
#define DATA_COLLECTOR_H
#include <stdint.h>
#include <stdbool.h>
// Forward declarations
typedef struct DeviceHandler DeviceHandler;
typedef struct CDataCollector CDataCollector;
typedef struct CMotorStatusBuffer CMotorStatusBuffer;
typedef struct CTouchStatusBuffer CTouchStatusBuffer;
typedef struct CPressureSummaryBuffer CPressureSummaryBuffer;
typedef struct CPressureDetailedBuffer CPressureDetailedBuffer;
// ============================================================================
// Motor Status Data
// ============================================================================
/**
* @brief Motor status data for all 6 finger joints
* Array order: [Thumb, ThumbAux, Index, Middle, Ring, Pinky]
*/
typedef struct CMotorStatusData {
uint16_t positions[6]; ///< Position values (0-1000)
int16_t speeds[6]; ///< Speed values (-1000 to +1000)
int16_t currents[6]; ///< Current values (-1000 to +1000)
uint8_t states[6]; ///< Motor states (MotorState enum)
} CMotorStatusData;
/**
* @brief Touch sensor data for a single finger
*/
typedef struct CTouchFingerItem {
uint16_t normal_force1;
uint16_t normal_force2;
uint16_t normal_force3;
uint16_t tangential_force1;
uint16_t tangential_force2;
uint16_t tangential_force3;
uint16_t tangential_direction1;
uint16_t tangential_direction2;
uint16_t tangential_direction3;
uint32_t self_proximity1;
uint32_t self_proximity2;
uint32_t mutual_proximity;
uint16_t status;
} CTouchFingerItem;
/**
* @brief Pressure sensor detailed data
*/
typedef struct PressureDetailedItem {
uint8_t sensor_count; ///< Number of sensors (fingers: 9, palm: 46)
uint16_t sensors_data[46]; ///< Sensor data array
} PressureDetailedItem;
// ============================================================================
// Buffer Creation and Management
// ============================================================================
/**
* @brief Create a new motor status buffer
* @param max_size Maximum buffer capacity (default 1000)
* @return Pointer to buffer, or NULL on failure
*/
CMotorStatusBuffer *motor_buffer_new(size_t max_size);
/**
* @brief Free a motor status buffer
* @param buffer Buffer pointer
*/
void motor_buffer_free(CMotorStatusBuffer *buffer);
/**
* @brief Get all motor status data from buffer
* @param buffer Buffer pointer
* @param out_data Output array (caller must allocate)
* @param max_count Maximum items to return
* @param out_count Actual items returned
* @return 0 on success, -1 on failure
*/
int motor_buffer_pop_all(CMotorStatusBuffer *buffer,
CMotorStatusData *out_data,
size_t max_count,
size_t *out_count);
/**
* @brief Get buffer length
* @param buffer Buffer pointer
* @return Number of items in buffer
*/
size_t motor_buffer_len(const CMotorStatusBuffer *buffer);
/**
* @brief Check if buffer is empty
* @param buffer Buffer pointer
* @return 1 if empty, 0 if not, -1 on error
*/
int motor_buffer_is_empty(const CMotorStatusBuffer *buffer);
/**
* @brief Clear all data from buffer
* @param buffer Buffer pointer
*/
void motor_buffer_clear(CMotorStatusBuffer *buffer);
/**
* @brief Create a new touch status buffer
* @param max_size Maximum buffer capacity per finger
* @return Pointer to buffer, or NULL on failure
*/
CTouchStatusBuffer *touch_buffer_new(size_t max_size);
/**
* @brief Free a touch status buffer
* @param buffer Buffer pointer
*/
void touch_buffer_free(CTouchStatusBuffer *buffer);
/**
* @brief Create a new pressure summary buffer
* @param max_size Maximum buffer capacity per part
* @return Pointer to buffer, or NULL on failure
*/
CPressureSummaryBuffer *pressure_summary_buffer_new(size_t max_size);
/**
* @brief Free a pressure summary buffer
* @param buffer Buffer pointer
*/
void pressure_summary_buffer_free(CPressureSummaryBuffer *buffer);
/**
* @brief Create a new pressure detailed buffer
* @param max_size Maximum buffer capacity per part
* @return Pointer to buffer, or NULL on failure
*/
CPressureDetailedBuffer *pressure_detailed_buffer_new(size_t max_size);
/**
* @brief Free a pressure detailed buffer
* @param buffer Buffer pointer
*/
void pressure_detailed_buffer_free(CPressureDetailedBuffer *buffer);
// ============================================================================
// DataCollector Creation
// ============================================================================
/**
* @brief Create a basic data collector (motor only)
* @param handle Device handler
* @param motor_buffer Motor status buffer
* @param slave_id Slave ID (default 1)
* @param motor_frequency Motor sampling frequency in Hz (default 1000)
* @param enable_stats Whether to print statistics (1=true, 0=false)
* @return Pointer to collector, or NULL on failure
*/
CDataCollector *data_collector_new_basic(DeviceHandler *handle,
CMotorStatusBuffer *motor_buffer,
uint8_t slave_id,
uint32_t motor_frequency,
int enable_stats);
/**
* @brief Create a capacitive touch data collector
* @param handle Device handler
* @param motor_buffer Motor status buffer
* @param touch_buffer Touch status buffer
* @param slave_id Slave ID
* @param motor_frequency Motor sampling frequency in Hz
* @param touch_frequency Touch sampling frequency in Hz
* @param enable_stats Whether to print statistics
* @return Pointer to collector, or NULL on failure
*/
CDataCollector *data_collector_new_capacitive(DeviceHandler *handle,
CMotorStatusBuffer *motor_buffer,
CTouchStatusBuffer *touch_buffer,
uint8_t slave_id,
uint32_t motor_frequency,
uint32_t touch_frequency,
int enable_stats);
/**
* @brief Create a pressure summary data collector
* @param handle Device handler
* @param motor_buffer Motor status buffer
* @param pressure_summary_buffer Pressure summary buffer
* @param slave_id Slave ID
* @param motor_frequency Motor sampling frequency in Hz
* @param touch_frequency Touch sampling frequency in Hz
* @param enable_stats Whether to print statistics
* @return Pointer to collector, or NULL on failure
*/
CDataCollector *data_collector_new_pressure_summary(DeviceHandler *handle,
CMotorStatusBuffer *motor_buffer,
CPressureSummaryBuffer *pressure_summary_buffer,
uint8_t slave_id,
uint32_t motor_frequency,
uint32_t touch_frequency,
int enable_stats);
/**
* @brief Create a pressure detailed data collector
* @param handle Device handler
* @param motor_buffer Motor status buffer
* @param pressure_detailed_buffer Pressure detailed buffer
* @param slave_id Slave ID
* @param motor_frequency Motor sampling frequency in Hz
* @param touch_frequency Touch sampling frequency in Hz (default 10)
* @param enable_stats Whether to print statistics
* @return Pointer to collector, or NULL on failure
*/
CDataCollector *data_collector_new_pressure_detailed(DeviceHandler *handle,
CMotorStatusBuffer *motor_buffer,
CPressureDetailedBuffer *pressure_detailed_buffer,
uint8_t slave_id,
uint32_t motor_frequency,
uint32_t touch_frequency,
int enable_stats);
/**
* @brief Create a pressure hybrid data collector (summary + detailed)
* @param handle Device handler
* @param motor_buffer Motor status buffer
* @param pressure_summary_buffer Pressure summary buffer
* @param pressure_detailed_buffer Pressure detailed buffer
* @param slave_id Slave ID
* @param motor_frequency Motor sampling frequency in Hz
* @param summary_frequency Summary sampling frequency in Hz
* @param detailed_frequency Detailed sampling frequency in Hz
* @param enable_stats Whether to print statistics
* @return Pointer to collector, or NULL on failure
*/
CDataCollector *data_collector_new_pressure_hybrid(DeviceHandler *handle,
CMotorStatusBuffer *motor_buffer,
CPressureSummaryBuffer *pressure_summary_buffer,
CPressureDetailedBuffer *pressure_detailed_buffer,
uint8_t slave_id,
uint32_t motor_frequency,
uint32_t summary_frequency,
uint32_t detailed_frequency,
int enable_stats);
// ============================================================================
// DataCollector Control
// ============================================================================
/**
* @brief Start data collection
* @param collector Collector pointer
* @return 0 on success, -1 on failure
*/
int data_collector_start(CDataCollector *collector);
/**
* @brief Stop data collection (non-blocking)
* @param collector Collector pointer
* @return 0 on success, -1 on failure
*/
int data_collector_stop(CDataCollector *collector);
/**
* @brief Wait for data collection thread to finish
* @param collector Collector pointer
* @return 0 on success, -1 on failure
*/
int data_collector_wait(CDataCollector *collector);
/**
* @brief Check if data collector is running
* @param collector Collector pointer
* @return 1 if running, 0 if not, -1 on error
*/
int data_collector_is_running(const CDataCollector *collector);
/**
* @brief Free a data collector
* @param collector Collector pointer
*/
void data_collector_free(CDataCollector *collector);
#endif // DATA_COLLECTOR_H交互功能
动作序列(手势)
c
#ifndef ACTION_SEQUENCE_H
#define ACTION_SEQUENCE_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Action sequence ID enumeration
* Defines IDs for built-in gestures and custom action sequences
*
* Built-in gestures (ID 1-6):
* - Open hand, fist, two-finger pinch, three-finger pinch, side pinch, single-finger point
*
* Custom action sequences:
* - Revo1: Supports up to 6 custom action sequences (ID 10-15)
* - Revo2: Supports up to 24 custom action sequences (ID 7-30)
*/
enum ActionSequenceId : uint8_t {
ACTION_SEQUENCE_ID_DEFAULT_GESTURE_OPEN = 1, ///< Built-in gesture: open hand
ACTION_SEQUENCE_ID_DEFAULT_GESTURE_FIST = 2, ///< Built-in gesture: fist
ACTION_SEQUENCE_ID_DEFAULT_GESTURE_PINCH_TWO = 3, ///< Built-in gesture: two-finger pinch
ACTION_SEQUENCE_ID_DEFAULT_GESTURE_PINCH_THREE = 4,///< Built-in gesture: three-finger pinch
ACTION_SEQUENCE_ID_DEFAULT_GESTURE_PINCH_SIDE = 5, ///< Built-in gesture: side pinch
ACTION_SEQUENCE_ID_DEFAULT_GESTURE_POINT = 6, ///< Built-in gesture: single-finger point
ACTION_SEQUENCE_ID_CUSTOM_GESTURE22 = 7, ///< Custom gesture 22 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE23 = 8, ///< Custom gesture 23 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE24 = 9, ///< Custom gesture 24 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE1 = 10, ///< Custom gesture 1
ACTION_SEQUENCE_ID_CUSTOM_GESTURE2 = 11, ///< Custom gesture 2
ACTION_SEQUENCE_ID_CUSTOM_GESTURE3 = 12, ///< Custom gesture 3
ACTION_SEQUENCE_ID_CUSTOM_GESTURE4 = 13, ///< Custom gesture 4
ACTION_SEQUENCE_ID_CUSTOM_GESTURE5 = 14, ///< Custom gesture 5
ACTION_SEQUENCE_ID_CUSTOM_GESTURE6 = 15, ///< Custom gesture 6
ACTION_SEQUENCE_ID_CUSTOM_GESTURE7 = 16, ///< Custom gesture 7 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE8 = 17, ///< Custom gesture 8 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE9 = 18, ///< Custom gesture 9 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE10 = 19, ///< Custom gesture 10 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE11 = 20, ///< Custom gesture 11 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE12 = 21, ///< Custom gesture 12 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE13 = 22, ///< Custom gesture 13 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE14 = 23, ///< Custom gesture 14 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE15 = 24, ///< Custom gesture 15 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE16 = 25, ///< Custom gesture 16 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE17 = 26, ///< Custom gesture 17 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE18 = 27, ///< Custom gesture 18 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE19 = 28, ///< Custom gesture 19 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE20 = 29, ///< Custom gesture 20 (Revo2 only)
ACTION_SEQUENCE_ID_CUSTOM_GESTURE21 = 30, ///< Custom gesture 21 (Revo2 only)
};
/**
* @brief Run an action sequence
* Executes a predefined or custom action sequence by ID
* @param handle Device handler
* @param slave_id Device ID
* @param action_id Action sequence ID, see ActionSequenceId enumeration
* @note Custom action sequences must be set via stark_set_action_sequence before execution
* @note Built-in gestures (ID 1-6) can be executed directly without prior setup
*/
void stark_run_action_sequence(DeviceHandler *handle, uint8_t slave_id, ActionSequenceId action_id);
/**
* @brief Transfer action sequences to the device
*
* This function sends multiple action sequences. Each sequence is represented
* by a fixed-length array of u16 parameters.
*
* @param handle Device handler
* @param slave_id Device ID
* @param is_revo2 Whether the device is Revo2
* @param action_id Action sequence ID that uniquely identifies the sequence
* @param sequences Flattened parameter array containing multiple sequences
* @param len Number of sequences (number of rows in the flattened array)
*
* @section revo1_format Revo1 Action Sequence Format
* Each action sequence contains 20 uint16_t elements:
* - [0] Sequence index: position in the queue
* - [1] Duration: execution time in milliseconds
* - [2-7] Finger positions: 6 finger position values (0-100)
* - [8-13] Finger speeds: 6 finger speed values (0-100)
* - [14-19] Finger forces: 6 finger force values (0-100)
*
* @section revo2_format Revo2 Action Sequence Format
* Each action sequence contains 27 uint16_t elements:
* - [0] Sequence index: position in the queue
* - [1] Duration: execution time in milliseconds
* - [2] Control mode: 1=position+time, 2=position+speed, 3=current, 4=speed
* - [3-8] Finger positions: 6 finger positions in degrees (°), 0xFFFF=keep current angle
* - [9-14] Finger speeds: 6 finger rotational speeds (°/s)
* - [15-20] Finger currents: 6 finger current values (mA)
*
* @example
* Revo1 action sequence example:
* @code
* uint16_t sequence[20] = {
* 0, // Sequence index
* 2000, // Duration: 2 seconds
* 0, 0, 100, 100, 100, 100, // 6 finger positions
* 10, 20, 30, 40, 50, 60, // 6 finger speeds
* 5, 10, 15, 20, 25, 30 // 6 finger forces
* };
* @endcode
*
* @note Revo1 supports maximum 32 action sequences, Revo2 supports maximum 8
* @warning If handle or sequences is NULL, the function returns immediately
* @warning If len exceeds the maximum limit, a warning is logged and the function returns
*/
void stark_set_action_sequence(DeviceHandler *handle,
uint8_t slave_id,
bool is_revo2,
ActionSequenceId action_id,
const uint16_t *sequences,
uintptr_t len);
#endif // ACTION_SEQUENCE_HLED 控制
c
#ifndef LED_H
#define LED_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief LED color enumeration
* Defines supported LED color combinations based on RGB
*/
typedef enum {
LED_COLOR_UNCHANGED = 0, ///< Color unchanged (Note: not equivalent to off, mainly controlled by LedMode)
LED_COLOR_R = 1, ///< Red
LED_COLOR_G = 2, ///< Green
LED_COLOR_RG = 3, ///< Red-Green (Yellow)
LED_COLOR_B = 4, ///< Blue
LED_COLOR_RB = 5, ///< Red-Blue (Purple)
LED_COLOR_GB = 6, ///< Green-Blue (Cyan)
LED_COLOR_RGB = 7 ///< Red-Green-Blue (White)
} LedColor;
/**
* @brief LED mode enumeration
* Defines LED operating modes including blink frequency and duration control
*/
typedef enum {
LED_MODE_NONE = 0, ///< No mode / undefined
LED_MODE_SHUTDOWN = 1, ///< Turn off LED
LED_MODE_KEEP = 2, ///< Keep LED on
LED_MODE_BLINK = 3, ///< Standard blink: 1Hz frequency, 50% duty cycle
LED_MODE_ONE_SHOT = 4, ///< Single pulse: on for 100ms then off, repeated commands reset timer
LED_MODE_BLINK0_5HZ = 5, ///< Slow blink: 0.5Hz frequency, 50% duty cycle
LED_MODE_BLINK2_HZ = 6 ///< Fast blink: 2Hz frequency, 50% duty cycle
} LedMode;
/**
* @brief LED information structure
* Contains LED color and operating mode
*/
struct LedInfo {
LedColor color; ///< LED color
LedMode mode; ///< LED operating mode
};
/**
* @brief Get LED information
* Retrieves LED status information including color and operating mode
* @param handle Device handler
* @param slave_id Device ID
* @return LedInfo* - LED information structure (must be freed with free_led_info)
* @retval NULL Failed to get LED info or invalid parameters
* @note The returned pointer points to dynamically allocated memory and must be freed
*/
LedInfo *stark_get_led_info(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Free LED information structure
* Releases memory allocated by stark_get_led_info
* @param info LedInfo structure pointer returned by stark_get_led_info
* @note Passing NULL is safe, the function will return directly
*/
void free_led_info(LedInfo *info);
#endif // LED_H按键
c
#ifndef BUTTON_H
#define BUTTON_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Button press state enumeration
* Defines three button states: none, pressed, released
*/
enum PressState : uint8_t {
PRESS_STATE_NONE = 0, ///< No button state
PRESS_STATE_DOWN = 1, ///< Button pressed state
PRESS_STATE_UP = 2, ///< Button released state
};
/**
* @brief Button event structure
* Contains button event timestamp, button ID, and press state
*/
struct ButtonPressEvent {
int32_t timestamp; ///< Event timestamp (milliseconds)
int32_t button_id; ///< Button identifier
PressState press_state; ///< Press state
};
/**
* @brief Get button event
* Retrieves button event information including timestamp, button ID, and state
* @param handle Device handler
* @param slave_id Device ID
* @return ButtonPressEvent* - Button event structure (must be freed with free_button_event)
* @retval NULL Failed to get event, no event available, or invalid parameters
* @note The returned pointer points to dynamically allocated memory and must be freed
* @note May return NULL if no new button events are available
*/
ButtonPressEvent *stark_get_button_event(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Free button event structure
* Releases memory allocated by stark_get_button_event
* @param event ButtonPressEvent structure pointer returned by stark_get_button_event
* @note Passing NULL is safe, the function will return directly
*/
void free_button_event(ButtonPressEvent *event);
#endif // BUTTON_H固件升级
c
/// DFU state callback, `state` corresponds to `DfuState`.
using DfuStateCallback = void(*)(uint8_t slave_id, uint8_t state);
/// DFU progress callback.
using DfuProgressCallback = void(*)(uint8_t slave_id, float progress);
/// Set DFU state callback.
void set_dfu_state_callback(DfuStateCallback cb);
/// Set DFU progress callback.
void set_dfu_progress_callback(DfuProgressCallback cb);
/// Start the DFU (Device Firmware Update) process.
/// - `handle`: Device handler pointer.
/// - `slave_id`: Slave device ID.
/// - `dfu_file_path`: DFU file path, as a C string.
/// - `wait_secs`: Timeout for entering DFU mode, in seconds (default 5).
void start_dfu(DeviceHandler *handle,
uint8_t slave_id,
const char *dfu_file_path,
uintptr_t wait_secs);
/// Stop the DFU process.
/// - `slave_id`: Slave device ID.
/// This stops an ongoing DFU session.
/// Note: If DFU has not started or has already completed, this function has no effect.
void stop_dfu(uint8_t slave_id);高级功能
设备辅助函数
c
#ifndef DEVICE_HELPERS_H
#define DEVICE_HELPERS_H
#include <stdbool.h>
/**
* @brief Determine whether the hand is a touch hand by serial number
*
* Checks if the device is a touch-enabled version based on its serial number.
*
* @param sn_ptr Pointer to serial number string
* @return true if the device is a touch hand, false otherwise
* @note This is a helper function that parses the serial number format
* @example
* auto info = stark_get_device_info(handle, slave_id);
* if (is_touch_hand_by_sn(info->serial_number)) {
* printf("Touch-enabled device detected\n");
* }
*/
bool is_touch_hand_by_sn(const char *sn_ptr);
/**
* @brief Determine whether the hand is Revo2 by serial number
*
* Checks if the device is a Revo2 version based on its serial number.
*
* @param sn_ptr Pointer to serial number string
* @return true if the device is Revo2, false if Revo1
* @note This is a helper function that parses the serial number format
* @example
* auto info = stark_get_device_info(handle, slave_id);
* if (is_revo2_hand_by_sn(info->serial_number)) {
* printf("Revo2 device detected\n");
* } else {
* printf("Revo1 device detected\n");
* }
*/
bool is_revo2_hand_by_sn(const char *sn_ptr);
#endif // DEVICE_HELPERS_HTurbo 模式
c
#ifndef TURBO_MODE_H
#define TURBO_MODE_H
#include <stdint.h>
#include <stdbool.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Turbo mode configuration structure
*
* Turbo mode allows the hand to continuously squeeze with specified
* interval and duration parameters.
*/
struct TurboConfig {
uint16_t interval; ///< Interval time in milliseconds
uint16_t duration; ///< Duration time in milliseconds
};
/**
* @brief Check whether Turbo mode is enabled
*
* When Turbo mode is enabled, the hand will keep squeezing continuously
* according to the configured interval and duration.
*
* @param handle Device handler
* @param slave_id Device ID
* @return true if Turbo mode is enabled, false otherwise
*/
bool stark_get_turbo_mode_enabled(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Enable or disable Turbo mode
*
* @param handle Device handler
* @param slave_id Device ID
* @param enabled true to enable Turbo mode, false to disable
* @note When enabled, the hand will continuously squeeze based on TurboConfig settings
*/
void stark_set_turbo_mode_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);
/**
* @brief Get Turbo mode configuration
*
* Retrieves the current Turbo mode interval and duration settings.
*
* @param handle Device handler
* @param slave_id Device ID
* @return Pointer to TurboConfig structure (must be freed with free_turbo_config)
* @retval NULL Failed to get configuration or invalid parameters
* @note The returned pointer points to dynamically allocated memory and must be freed
*/
TurboConfig *stark_get_turbo_config(DeviceHandler *handle, uint8_t slave_id);
/**
* @brief Free Turbo mode configuration structure
*
* Releases memory allocated by stark_get_turbo_config.
*
* @param config TurboConfig structure pointer returned by stark_get_turbo_config
* @note Passing NULL is safe, the function will return directly
*/
void free_turbo_config(TurboConfig *config);
#endif // TURBO_MODE_H自定义回调
c
#ifndef CALLBACKS_H
#define CALLBACKS_H
#include <stdint.h>
/**
* @brief Modbus async read/write result callback type
*
* This callback processes results of asynchronous Modbus operations.
*
* @param data Pointer to data buffer
* @param len Length of data
* @param error_code Error code (0 on success, non-zero on failure)
* @param user_data User-defined data pointer
*/
using ModbusOperationResultCallback = void(*)(uint8_t* data,
int len,
int error_code,
void* user_data);
/**
* @brief Modbus async read/write callback type
*
* @param values Pointer to values array
* @param len Length of values array
* @param callback Result callback function
* @param user_data User-defined data pointer
* @return 0 on success, non-zero on failure
*/
using ModbusOperationCallback = int32_t(*)(const uint8_t *values,
int len,
ModbusOperationResultCallback callback,
void *user_data);
/**
* @brief Custom Modbus RX callback
*
* Callback for reading Modbus registers.
*
* @param slave_id Slave device ID
* @param register_address Starting register address
* @param data_out Output data buffer
* @param count Number of registers to read
* @return 0 on success, non-zero on failure
*/
using ModbusRxCallback = int32_t(*)(uint8_t slave_id,
uint16_t register_address,
uint16_t *data_out,
uint16_t count);
/**
* @brief Custom Modbus TX callback
*
* Callback for writing Modbus registers.
*
* @param slave_id Slave device ID
* @param register_address Starting register address
* @param data Input data buffer
* @param count Number of registers to write
* @return 0 on success, non-zero on failure
*/
using ModbusTxCallback = int32_t(*)(uint8_t slave_id,
uint16_t register_address,
const uint16_t *data,
uint16_t count);
/**
* @brief CAN/CANFD RX callback
*
* Callback for receiving CAN/CANFD messages.
*
* @param slave_id Slave device ID
* @param can_id_out Output CAN ID
* @param data_out Output data buffer (max 64 bytes)
* @param data_len_out Output data length
* @return 0 on success, non-zero on failure
* @note data_out length must be at most 64 bytes
*/
using CanRxCallback = int32_t(*)(uint8_t slave_id,
uint32_t *can_id_out,
uint8_t *data_out,
uintptr_t *data_len_out);
/**
* @brief CAN/CANFD TX callback
*
* Callback for transmitting CAN/CANFD messages.
*
* @param slave_id Slave device ID
* @param can_id CAN ID
* @param data Input data buffer
* @param data_len Data length
* @return 0 on success, non-zero on failure
*/
using CanTxCallback = int32_t(*)(uint8_t slave_id,
uint32_t can_id,
const uint8_t *data,
uintptr_t data_len);
/**
* @brief Set Modbus async read/write callback
*
* Registers a callback for asynchronous Modbus operations.
*
* @param cb Callback function pointer
*/
void set_modbus_operation_callback(ModbusOperationCallback cb);
/**
* @brief Set Modbus read callback for input registers
*
* Registers a callback for reading Modbus input registers.
*
* @param cb Callback function pointer
*/
void set_modbus_read_input_callback(ModbusRxCallback cb);
/**
* @brief Set Modbus read callback for holding registers
*
* Registers a callback for reading Modbus holding registers.
*
* @param cb Callback function pointer
*/
void set_modbus_read_holding_callback(ModbusRxCallback cb);
/**
* @brief Set Modbus write callback
*
* Registers a callback for writing Modbus registers.
*
* @param cb Callback function pointer
*/
void set_modbus_write_callback(ModbusTxCallback cb);
/**
* @brief Set CAN/CANFD RX callback
*
* Registers a callback for receiving CAN/CANFD messages.
*
* @param cb Callback function pointer
*/
void set_can_rx_callback(CanRxCallback cb);
/**
* @brief Set CAN/CANFD TX callback
*
* Registers a callback for transmitting CAN/CANFD messages.
*
* @param cb Callback function pointer
*/
void set_can_tx_callback(CanTxCallback cb);
#endif // CALLBACKS_HAPI 快速参考
初始化与配置
| API | 说明 |
|---|---|
init_logging() | 初始化 SDK 日志 |
连接管理(推荐)
| API | 说明 |
|---|---|
stark_auto_detect() | 自动检测设备(支持所有协议)⭐ |
init_from_detected() | 从检测结果初始化设备 ⭐ |
close_device_handler() | 关闭设备连接(统一接口)⭐ |
list_zqwl_devices() | 列出 ZQWL CAN/CANFD 设备 ⭐ |
init_zqwl_canfd() | 初始化 ZQWL CANFD 设备 |
init_zqwl_can() | 初始化 ZQWL CAN 2.0 设备 |
close_zqwl() | 关闭 ZQWL 设备 |
scan_can_devices() | 扫描 CAN 总线设备 |
连接管理(传统)
| API | 说明 |
|---|---|
modbus_open() | 打开 Modbus 连接 |
modbus_close() | 关闭 Modbus 连接 |
init_device_handler() | 创建设备处理器(CAN/CANFD/EtherCAT,需手动管理适配器) |
init_device_handler_with_hw_type() | 创建设备处理器并预设硬件类型(跳过 get_device_info)⭐ |
auto_detect_device() | 自动检测设备(仅 Modbus) |
auto_detect_modbus_revo2() | 自动检测 Revo2 设备(仅 Modbus) |
list_available_ports() | 列出可用串口 |
设备信息
| API | 说明 |
|---|---|
stark_get_device_info() | 获取设备完整信息 |
stark_is_touch_device() | 判断是否支持触觉 ⭐ |
stark_uses_revo1_motor_api() | 判断是否使用 Revo1 电机 API ⭐ |
stark_uses_pressure_touch_api() | 判断是否使用压力触觉 API ⭐ |
stark_get_touch_vendor() | 获取触觉传感器类型 ⭐ |
stark_get_voltage() | 获取设备电压 |
stark_get_rs485_baudrate() | 获取 RS485 波特率 |
stark_set_rs485_baudrate() | 设置 RS485 波特率 |
stark_get_canfd_baudrate() | 获取 CANFD 波特率 |
stark_set_canfd_baudrate() | 设置 CANFD 波特率 |
stark_set_slave_id() | 设置从站 ID |
电机控制 - 位置(统一范围 0-1000)
| API | 说明 |
|---|---|
stark_set_finger_position() | 设置单个手指位置 |
stark_set_finger_position_with_millis() | 设置位置(指定时间)⭐ |
stark_set_finger_position_with_speed() | 设置位置(指定速度)⭐ |
stark_set_finger_positions() | 设置所有手指位置 |
stark_set_finger_positions_and_durations() | 设置位置和时间 ⭐ |
stark_set_finger_positions_and_speeds() | 设置位置和速度 ⭐ |
stark_get_finger_positions() | 获取所有手指位置 |
电机控制 - 速度(统一范围 -1000~+1000)
| API | 说明 |
|---|---|
stark_set_finger_speed() | 设置单个手指速度 |
stark_set_finger_speeds() | 设置所有手指速度 |
stark_get_finger_speeds() | 获取所有手指速度 |
电机控制 - 电流(统一范围 -1000~+1000)
| API | 说明 |
|---|---|
stark_set_finger_current() | 设置单个手指电流 |
stark_set_finger_currents() | 设置所有手指电流 |
stark_get_finger_currents() | 获取所有手指电流 |
电机控制 - PWM(统一范围 -1000~+1000)⭐
| API | 说明 |
|---|---|
stark_set_finger_pwm() | 设置单个手指 PWM |
stark_set_finger_pwms() | 设置所有手指 PWM |
电机状态
| API | 说明 |
|---|---|
stark_get_motor_status() | 获取电机综合状态 |
stark_get_motor_state() | 获取电机运行状态 |
电机设置 ⭐
| API | 说明 |
|---|---|
stark_get_finger_unit_mode() | 获取单位模式 |
stark_set_finger_unit_mode() | 设置单位模式 |
stark_get_finger_min_position() | 获取最小位置限制 |
stark_set_finger_min_position() | 设置最小位置限制 |
stark_get_finger_max_position() | 获取最大位置限制 |
stark_set_finger_max_position() | 设置最大位置限制 |
stark_get_finger_max_speed() | 获取最大速度限制 |
stark_set_finger_max_speed() | 设置最大速度限制 |
stark_get_finger_max_current() | 获取最大电流限制 |
stark_set_finger_max_current() | 设置最大电流限制 |
stark_get_finger_protected_current() | 获取保护电流 |
stark_set_finger_protected_current() | 设置保护电流 |
stark_get_thumb_aux_lock_current() | 获取拇指辅助锁定电流 |
stark_set_thumb_aux_lock_current() | 设置拇指辅助锁定电流 |
触觉传感器
| API | 说明 |
|---|---|
stark_get_touch_sensor_enabled() | 获取触觉传感器启用状态 |
stark_get_touch_sensor_fw_versions() | 获取触觉传感器固件版本 |
stark_get_touch_sensor_raw_data() | 获取触觉原始数据 |
stark_get_touch_sensor_status() | 获取触觉传感器状态 |
stark_touch_sensor_setup() | 设置触觉传感器 |
stark_touch_sensor_reset() | 重置触觉传感器 |
stark_touch_sensor_calibrate() | 校准触觉传感器 |
高性能数据采集 ⭐
| API | 说明 |
|---|---|
motor_buffer_new() | 创建电机状态缓冲区 |
motor_buffer_free() | 释放电机状态缓冲区 |
motor_buffer_pop_all() | 获取所有电机数据 |
touch_buffer_new() | 创建触觉状态缓冲区 |
touch_buffer_free() | 释放触觉状态缓冲区 |
pressure_summary_buffer_new() | 创建压力摘要缓冲区 |
pressure_detailed_buffer_new() | 创建压力详细缓冲区 |
data_collector_new_basic() | 创建基础采集器 |
data_collector_new_capacitive() | 创建电容触觉采集器 |
data_collector_new_pressure_summary() | 创建压力摘要采集器 |
data_collector_new_pressure_detailed() | 创建压力详细采集器 |
data_collector_new_pressure_hybrid() | 创建混合模式采集器 |
data_collector_start() | 启动数据采集 |
data_collector_stop() | 停止数据采集 |
data_collector_wait() | 等待采集线程结束 |
data_collector_free() | 释放数据采集器 |
LED、蜂鸣器、震动 ⭐
| API | 说明 |
|---|---|
stark_get_led_enabled() | 获取 LED 启用状态 |
stark_set_led_enabled() | 设置 LED 启用状态 |
stark_get_buzzer_enabled() | 获取蜂鸣器启用状态 |
stark_set_buzzer_enabled() | 设置蜂鸣器启用状态 |
stark_get_vibration_enabled() | 获取震动启用状态 |
stark_set_vibration_enabled() | 设置震动启用状态 |
动作序列
| API | 说明 |
|---|---|
stark_get_action_sequence() | 获取动作序列 |
stark_transfer_action_sequence() | 上传动作序列 |
stark_run_action_sequence() | 执行动作序列 |
设备配置
| API | 说明 |
|---|---|
stark_get_force_level() | 获取力度等级 |
stark_set_force_level() | 设置力度等级 |
stark_get_auto_calibration_enabled() | 获取自动校准状态 |
stark_set_auto_calibration() | 设置自动校准 |
stark_calibrate_position() | 手动校准位置 |
stark_get_turbo_mode_enabled() | 获取 Turbo 模式状态 |
stark_set_turbo_mode_enabled() | 设置 Turbo 模式 |
stark_get_turbo_config() | 获取 Turbo 配置 |
stark_set_turbo_config() | 设置 Turbo 配置 |
stark_reboot() | 重启设备 |
EtherCAT 专用 ⭐
| API | 说明 |
|---|---|
stark_ec_setup_sdo() | 设置 SDO |
stark_ec_start_loop() | 启动循环 |
stark_ec_stop_loop() | 停止循环 |
stark_ec_start_dfu() | 启动固件升级 |
固件升级
| API | 说明 |
|---|---|
stark_start_dfu() | 启动固件升级 |
⭐ 标记表示 Revo2 专有或增强功能