C++ SDK - Revo1 Dexterous Hand
System Requirements
- Linux: Ubuntu 20.04/22.04 LTS (x86_64/aarch64), glibc ≥ 2.31
- macOS: 10.15+
- Windows: 10/11
Quick Start
Clone Repository
shell
git clone git@github.com:BrainCoTech/stark-serialport-example.gitInstallation & Configuration
shell
# Install dependencies
# Required: build-essential, cmake, make, gcc, g++, etc.
# Install SDK dependencies
./download-lib.sh
# Configure device permissions
# In Linux, serial devices (e.g., /dev/ttyUSB0) typically belong to dialout or tty group
# Only group members can access the device, for example:
# crw-rw---- 1 root dialout 188, 0 Aug 14 12:00 /dev/ttyUSB0
# Add current user to dialout group
sudo usermod -aG dialout $USER
# Note: You need to log out and log back in for this to take effect
# Build and run example (unified cross-platform directory)
cd c && make
cd demo && ./hand_demo.exe # Auto-detect device and runshell
# Install Xcode or Xcode Command Line Tools
xcode-select --install
# Install SDK dependencies
./download-lib.sh
# Build and run example (unified cross-platform directory)
cd c && make
cd demo && ./hand_demo.exe # Auto-detect device and runshell
# Requires MinGW or MSVC build environment
# Install SDK dependencies
./download-lib.sh
# Build and run example (unified cross-platform directory)
cd c && make
cd demo && hand_demo.exe # Auto-detect device and runExample Code
The SDK provides comprehensive example code covering different communication protocols and application scenarios.
Cross-Platform Examples (Recommended) ⭐
Unified cross-platform examples with auto-detection and multi-protocol support.
shell
cd c
make
cd demo
./hand_demo.exe # Auto-detect device and run demo| Example | Description |
|---|---|
| hand_demo.cpp | Comprehensive demo (8 modes: position/speed/current control, action sequences, touch sensors, etc.) |
| hand_monitor.cpp | Real-time data monitor (motor status, touch data) |
| hand_dfu.cpp | Firmware upgrade |
| auto_detect.cpp | Device auto-detection |
Supported initialization methods:
shell
./hand_demo.exe # Auto-detect (recommended)
./hand_demo.exe -m /dev/ttyUSB0 115200 1 # Modbus
./hand_demo.exe -c /dev/cu.usbmodem14201 1000000 1 # CAN 2.0 (ZQWL)
./hand_demo.exe -s can0 1 # SocketCAN (Linux)Modbus-RTU Protocol
Single/Dual Hand Control
- Single Hand Control
- Dual Hand Control - Connect left and right hands via single serial port with different device IDs
Tactile Sensor
Firmware Upgrade
CAN 2.0 Protocol
Single Hand Control Examples
- Custom CAN Device - C++ Example
- ZLG USBCAN Device - C++ Example
- ZQWL USBCAN Device - C++ Example
API Reference
Initialize Configuration
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_HAuto-Detect Device
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_HDevice Settings
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_HCommunication Protocols
Modbus-RTU
c
#ifndef MODBUS_REVO1_H
#define MODBUS_REVO1_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @brief Open Modbus serial connection (Revo1 only)
* Initializes and establishes Modbus serial communication connection with Revo1 device
* @param port Serial port device name, e.g., "/dev/ttyUSB0" (Linux), "COM1" (Windows)
* @param baudrate Serial baud rate, Revo1 supports: 115200, 57600, 19200, 460800 (default: 115200)
* @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
* @warning Using unsupported baud rate may cause communication failure
* @example
* auto handle = modbus_open("/dev/ttyUSB0", 115200);
*/
DeviceHandler *modbus_open(const char *port, uint32_t baudrate);
/**
* @brief Close Modbus 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_REVO1_HCAN 2.0
c
#ifndef DEVICE_HANDLER_H
#define DEVICE_HANDLER_H
#include <stdint.h>
#include <stdbool.h>
// Forward declarations
typedef struct DeviceHandler DeviceHandler;
typedef struct CDetectedDevice CDetectedDevice;
typedef struct CDetectedDeviceList CDetectedDeviceList;
// ================================
// Recommended: Auto-Detect Flow
// ================================
/**
* @brief Auto-detect Stark devices across all protocols
*
* 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.
* Returns empty list (count=0) if no devices found.
*/
CDetectedDeviceList *stark_auto_detect(bool scan_all, const char *port, uint8_t protocol);
/**
* @brief Initialize device handler from detected device info
*
* Automatically initializes the appropriate transport (Modbus, CAN, CANFD)
* based on the detected device's protocol.
*
* @param device Pointer to CDetectedDevice from stark_auto_detect()
* @return Pointer to DeviceHandler on success, NULL on failure
* @note Call close_device_handler to cleanup
*/
DeviceHandler *init_from_detected(const CDetectedDevice *device);
/**
* @brief Close device handler and release resources
*
* Counterpart to init_from_detected() and init_device_handler().
* Automatically handles cleanup based on protocol type:
* - For CAN/CANFD: Closes ZQWL device
* - For Modbus: Closes serial port
*
* @param handle DeviceHandler to close
*/
void close_device_handler(DeviceHandler *handle);
/**
* @brief Free detected device list memory
* @param list Pointer to CDetectedDeviceList
*/
void free_detected_device_list(CDetectedDeviceList *list);
// ================================
// Manual Initialization
// ================================
/**
* @brief Open Modbus serial port
* @param port Serial port name, e.g. "/dev/ttyUSB0" or "COM1"
* @param baudrate Baud rate (115200, 460800, 1000000, 2000000, 5000000)
* Revo1 default: 115200, Revo2 default: 460800
* @return Pointer to DeviceHandler, NULL on failure
* @note Call modbus_close to free
*/
DeviceHandler *modbus_open(const char *port, uint32_t baudrate);
/**
* @brief Close Modbus serial port
* @param handle DeviceHandler from modbus_open
*/
void modbus_close(DeviceHandler *handle);
/**
* @brief Create device handler with specified protocol
* @param protocol_type Protocol type (Modbus, CAN, CanFd, EtherCAT)
* @param master_id Master ID (required for CanFd and EtherCAT, 0 for others)
* @return Pointer to DeviceHandler. Call close_device_handler to release.
*/
DeviceHandler *init_device_handler(StarkProtocolType protocol_type, uint8_t master_id);
/**
* @brief Create device handler with hardware type pre-set
*
* Useful when hardware type is known (e.g., from auto_detect) to avoid
* extra get_device_info call.
*
* @param protocol_type Protocol type
* @param master_id Master ID
* @param slave_id Slave ID to set hardware type for
* @param hw_type Hardware type (StarkHardwareType enum value)
* @return Pointer to DeviceHandler. Call close_device_handler to release.
*/
DeviceHandler *init_device_handler_with_hw_type(StarkProtocolType protocol_type,
uint8_t master_id,
uint8_t slave_id,
StarkHardwareType hw_type);
#endif // DEVICE_HANDLER_HDevice Information
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_HJoint Control
Position/Speed/Current Control
c
#ifndef FINGER_POSITION_H
#define FINGER_POSITION_H
#include <stdint.h>
// Forward declaration
typedef struct DeviceHandler DeviceHandler;
/**
* @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 Control single finger position
* Sets the position parameter for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID, see StarkFingerId enumeration
* @param position Position value, range 0~1000 (0=fully open, 1000=fully closed)
* @note Position control is the basic finger control mode, suitable for most applications
*/
void stark_set_finger_position(DeviceHandler *handle, uint8_t slave_id, StarkFingerId finger_id, uint16_t position);
/**
* @brief Control all finger positions
* Batch sets position parameters for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param positions Position value array pointer, contains position values for 6 fingers, range 0~1000
* @param len Array length, must be 6 (corresponding to 6 fingers)
* @note Array order: [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
* @warning len parameter must equal 6, otherwise may cause unpredictable behavior
* @example
* // Close grip
* uint16_t positions_fist[] = {600, 600, 1000, 1000, 1000, 1000};
* stark_set_finger_positions(handle, slave_id, positions_fist, 6);
*
* // Open all fingers
* uint16_t positions_open[] = {0, 0, 0, 0, 0, 0};
* stark_set_finger_positions(handle, slave_id, positions_open, 6);
*/
void stark_set_finger_positions(DeviceHandler *handle, uint8_t slave_id, const uint16_t *positions, uintptr_t len);
/**
* @brief Control single finger speed (Revo1)
* Sets the movement speed for a specified finger
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID, see StarkFingerId enumeration
* @param speed Speed value, range -1000~1000 (negative=open direction, positive=close direction, 0=stop)
* @note Speed control allows real-time adjustment of finger movement speed and direction
*/
void stark_set_finger_speed(DeviceHandler *handle, uint8_t slave_id, StarkFingerId finger_id, int16_t speed);
/**
* @brief Control all finger speeds (Revo1)
* Batch sets movement speeds for all fingers
* @param handle Device handler
* @param slave_id Device ID
* @param speeds Speed value array pointer, contains speed values for 6 fingers, range -1000~1000
* @param len Array length, must be 6 (corresponding to 6 fingers)
* @note Array order: [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
* @note Negative values indicate open direction, positive values indicate close direction, 0 means stop
* @warning len parameter must equal 6, otherwise may cause unpredictable behavior
* @example
* int16_t speeds[] = {100, 100, 100, 100, 100, 100};
* stark_set_finger_speeds(handle, slave_id, speeds, 6);
*/
void stark_set_finger_speeds(DeviceHandler *handle, uint8_t slave_id, const int16_t *speeds, uintptr_t len);
/**
* @brief Set single finger current (Revo1 Touch only)
* Directly controls finger motor drive current for precise force control
* @param handle Device handler
* @param slave_id Device ID
* @param finger_id Finger ID, see StarkFingerId enumeration
* @param current Current value, range -1000~1000
* @note Positive values indicate close direction current, negative values indicate open direction current
* @warning Only applicable to Revo1 Touch devices, use corresponding control functions for other versions
*/
void stark_set_finger_current(DeviceHandler *handle,
uint8_t slave_id,
StarkFingerId finger_id,
int16_t current);
/**
* @brief Set multiple finger currents (Revo1 Touch only)
* Batch controls drive currents for multiple finger motors
* @param handle Device handler
* @param slave_id Device ID
* @param currents Current value array pointer, contains current values for multiple fingers, range -1000~1000
* @param len Array length, typically 6 (corresponding to 6 fingers)
* @note Positive values indicate close direction current, negative values indicate open direction current
* @note Array order: [Thumb, Thumb Aux, Index, Middle, Ring, Pinky]
* @warning Only applicable to Revo1 Touch devices, use corresponding control functions for other versions
*/
void stark_set_finger_currents(DeviceHandler *handle,
uint8_t slave_id,
const int16_t *currents,
uintptr_t len);
#endif // FINGER_POSITION_HMotor Status
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_HSensors
Tactile Information
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_HInteractive Features
Action Sequences (Gestures)
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 Control
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_HButton
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_HFirmware Upgrade
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);Advanced Features
Device Helper Functions
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 Mode
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_HCustom Callbacks
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 Quick Reference
Initialization and Configuration
| API | Description |
|---|---|
init_logging() | Initialize SDK logging |
Connection Management
| API | Description |
|---|---|
stark_auto_detect() | Auto-detect devices (recommended, all protocols) |
init_from_detected() | Initialize device from detection result |
close_device_handler() | Close device connection (recommended) |
list_zqwl_devices() | List ZQWL CAN adapters |
init_zqwl_can() | Initialize ZQWL CAN adapter |
close_zqwl() | Close ZQWL adapter |
modbus_open() | Open Modbus connection |
modbus_close() | Close Modbus connection |
init_device_handler() | Create device handler (CAN/CANFD, manual adapter management) |
init_device_handler_with_hw_type() | Create device handler with pre-set hardware type (skip get_device_info) ⭐ |
auto_detect_device() | Auto-detect device (deprecated) |
auto_detect_modbus_revo1() | Auto-detect Revo1 device (deprecated) |
list_available_ports() | List available serial ports |
Device Information
| API | Description |
|---|---|
stark_get_device_info() | Get complete device information |
stark_get_device_sn() | Get device serial number |
stark_get_device_fw_version() | Get firmware version |
stark_get_sku_type() | Get SKU type |
stark_get_voltage() | Get battery voltage |
stark_get_serialport_cfg() | Get serial port configuration |
stark_set_serialport_baudrate() | Set baud rate |
stark_set_slave_id() | Set slave ID |
Device Type Checking
| API | Description |
|---|---|
stark_is_touch_device() | Check if device has touch sensors |
stark_uses_revo1_motor_api() | Check if uses Revo1 Motor API |
stark_uses_revo1_touch_api() | Check if uses Revo1 Touch API |
stark_uses_revo2_touch_api() | Check if uses Revo2 Touch API |
stark_uses_pressure_touch_api() | Check if uses Pressure Touch API |
stark_get_touch_sensor_type() | Get touch sensor type |
Motor Control - Position
| API | Description |
|---|---|
stark_set_finger_position() | Set single finger position (0~1000) |
stark_set_finger_positions() | Set all finger positions |
stark_get_finger_positions() | Get all finger positions |
Motor Control - Speed
| API | Description |
|---|---|
stark_set_finger_speed() | Set single finger speed (-1000~+1000) |
stark_set_finger_speeds() | Set all finger speeds |
stark_get_finger_speeds() | Get all finger speeds |
Motor Control - Current
| API | Description |
|---|---|
stark_set_finger_current() | Set single finger current (-1000~+1000) |
stark_set_finger_currents() | Set all finger currents |
stark_get_finger_currents() | Get all finger currents |
Motor Status
| API | Description |
|---|---|
stark_get_motor_status() | Get comprehensive motor status |
stark_get_motor_state() | Get motor running state |
Touch Sensors
| API | Description |
|---|---|
stark_get_touch_sensor_enabled() | Get touch sensor enabled status |
stark_get_touch_sensor_fw_versions() | Get touch sensor firmware versions |
stark_get_touch_sensor_raw_data() | Get touch raw data |
stark_get_touch_sensor_status() | Get touch sensor status |
stark_touch_sensor_setup() | Setup touch sensors |
stark_touch_sensor_reset() | Reset touch sensors |
stark_touch_sensor_calibrate() | Calibrate touch sensors |
LED and Button
| API | Description |
|---|---|
stark_get_led_info() | Get LED status |
stark_set_led_info() | Set LED status |
stark_get_button_event() | Get button event |
Action Sequences
| API | Description |
|---|---|
stark_get_action_sequence() | Get action sequence |
stark_transfer_action_sequence() | Upload action sequence |
stark_run_action_sequence() | Execute action sequence |
Device Configuration
| API | Description |
|---|---|
stark_get_force_level() | Get force level |
stark_set_force_level() | Set force level |
stark_get_auto_calibration_enabled() | Get auto-calibration status |
stark_set_auto_calibration() | Set auto-calibration |
stark_calibrate_position() | Manual position calibration |
stark_get_turbo_mode_enabled() | Get turbo mode status |
stark_set_turbo_mode_enabled() | Set turbo mode |
stark_get_turbo_config() | Get turbo configuration |
stark_set_turbo_config() | Set turbo configuration |
stark_reboot() | Reboot device |
Firmware Upgrade
| API | Description |
|---|---|
stark_start_dfu() | Start firmware upgrade |