SCSLIB - 飞特串行舵机控制库
本库提供了对飞特SMS/STS系列串行舵机的完整控制功能。
地址:
http://doc.feetech.cn/#/prodinfodownload?srcType=FTServo-emanual-ab4947a479784a71a8cb7928
功能特性
- 支持单个舵机位置、速度和加速度控制
- 支持多个舵机同步控制(最多32个)
- 支持轮式模式控制
- 提供EPROM锁定/解锁功能
- 支持参数校准
主要API说明
位置控制相关函数
- WritePosEx - 写入舵机位置
int WritePosEx(uint8_t ID, int16_t Position, uint16_t Speed, uint8_t ACC)
- ID: 舵机ID号(0-254)
- Position: 目标位置(-32768~32767)
- Speed: 运行速度(0~5000)
- ACC: 加速度(0~254)
- RegWritePosEx - 异步写入位置
int RegWritePosEx(uint8_t ID, int16_t Position, uint16_t Speed, uint8_t ACC)
- 功能同WritePosEx,但使用寄存器写入方式
- SyncWritePosEx - 多舵机同步控制
void SyncWritePosEx(uint8_t ID[], uint8_t IDN, int16_t Position[], uint16_t Speed[], uint8_t ACC[])
- ID[]: 舵机ID数组
- IDN: 舵机数量
- Position[]: 位置数组
- Speed[]: 速度数组
- ACC[]: 加速度数组
速度控制相关函数
- WheelMode - 设置轮式模式
int WheelMode(uint8_t ID)
- WriteSpe - 写入速度
int WriteSpe(uint8_t ID, int16_t Speed, uint8_t ACC)
配置相关函数
- CalibrationOfs - 校准偏移
int CalibrationOfs(uint8_t ID)
- unLockEpromEx/LockEpromEx - EPROM操作
int unLockEpromEx(uint8_t ID)
int LockEpromEx(uint8_t ID)
使用示例
- 控制单个舵机到指定位置
WritePosEx(1, 2000, 100, 50); // ID=1的舵机移动到2000位置,速度100,加速度50
- 多个舵机同步控制
uint8_t ids[3] = {1, 2, 3};
int16_t positions[3] = {1000, 2000, 3000};
uint16_t speeds[3] = {100, 100, 100};
uint8_t accs[3] = {50, 50, 50};
SyncWritePosEx(ids, 3, positions, speeds, accs);
参数详解
位置参数(Position)
- 范围: -32768 ~ 32767
- 单位: 0.02386度/单位
- 实际角度计算: Position * 0.02386°
- 示例:
// 旋转到90度位置 int pos = 90 / 0.02386; // 约等于3770 WritePosEx(1, pos, 100, 50);
速度参数(Speed)
- 范围: 0 ~ 5000
- 单位: 0.1rpm/单位
- 实际速度计算: Speed * 0.1rpm
- 特殊值: 0 = 最快速度
- 示例:
// 设置100rpm的速度 uint16_t speed = 1000; // 100rpm = 1000 * 0.1rpm WritePosEx(1, 2000, speed, 50);
加速度参数(ACC)
- 范围: 0 ~ 254
- 单值越大加速度越小
- 特殊值: 0 = 无加速度控制
- 推荐值: 50-100
- 示例:
// 设置中等加速度 uint8_t acc = 80; WritePosEx(1, 2000, 1000, acc);
高级使用案例
1. 位置模式控制案例
// 基本位置控制
WritePosEx(1, 2000, 100, 50);
// 不限速位置控制
WritePosEx(1, 2000, 0, 0);
// 多段位置控制
WritePosEx(1, 1000, 100, 50); // 先移动到1000
HAL_Delay(1000); // 等待1秒
WritePosEx(1, 2000, 200, 50); // 再移动到2000
2. 轮式模式控制案例
// 设置为轮式模式
WheelMode(1);
// 正向旋转(1000 = 100rpm)
WriteSpe(1, 1000, 50);
// 反向旋转
WriteSpe(1, -1000, 50);
// 停止
WriteSpe(1, 0, 50);
3. 多舵机同步控制案例
// 3个舵机同时到不同位置
uint8_t ids[3] = {1, 2, 3};
int16_t positions[3] = {1000, 2000, -1000}; // 支持正负位置
uint16_t speeds[3] = {100, 200, 150}; // 不同速度
uint8_t accs[3] = {50, 50, 50}; // 相同加速度
SyncWritePosEx(ids, 3, positions, speeds, accs);
// 相同参数同步控制
int16_t same_pos[3] = {2000, 2000, 2000};
uint16_t same_speed[3] = {100, 100, 100};
uint8_t same_acc[3] = {50, 50, 50};
SyncWritePosEx(ids, 3, same_pos, same_speed, same_acc);
4. EPROM操作案例
// 解锁EPROM进行参数配置
unLockEpromEx(1);
// 进行参数设置操作
// ...
// 完成后锁定EPROM
LockEpromEx(1);
注意事项
- 位置值支持负数,内部会自动转换
- 速度范围0-5000,单位为0.1rpm
- 加速度范围0-254,值越大加速度越小
- 使用同步写入时注意舵机数量不要超过32个
依赖关系
- INST.h - 指令集定义
- SCS.h - 底层通信协议
- SMS_STS.h - 舵机参数定义
错误处理
所有写入函数返回值:
- 1: 成功
- 0: 失败
建议在调用API后检查返回值以确保操作成功。
故障排除
常见问题及解决方法:
- 通信失败
- 检查波特率设置
- 确认ID是否正确
- 检查通信线序
- 舵机无响应
- 检查电源供电
- 确认舵机ID设置
- 验证通信连接
- 位置控制不准
- 校准零位: CalibrationOfs()
- 检查位置计算是否正确
- 确认机械结构无干涉
性能优化
- 提高控制效率
- 使用同步写入代替单个写入
- 合理设置速度和加速度
- 避免频繁小幅度调整
- 保护机制
// 建议的安全检查示例
if(Position > 32767 || Position < -32768) {
return 0; // 超出范围
}
if(Speed > 5000) {
Speed = 5000; // 限制最大速度
}
完整应用示例
// 初始化和配置示例
void ServoInit(uint8_t ID) {
// 解锁EPROM
unLockEpromEx(ID);
// 设置位置模式
WheelMode(ID);
// 校准零位
CalibrationOfs(ID);
// 锁定EPROM
LockEpromEx(ID);
}
// 位置控制任务示例
void ServoPositionTask(void) {
// 定义位置序列
int16_t positions[] = {1000, 2000, 3000, 0};
for(int i = 0; i < 4; i++) {
WritePosEx(1, positions[i], 200, 50);
HAL_Delay(1000); // 等待到达目标位置
}
}
用户需要实现的API
使用本库时,用户需要实现以下底层通信接口:
1. 串口发送函数
// 发送指定长度的数据
void SendData(uint8_t *data, uint8_t size) {
// 示例:使用HAL库发送数据
HAL_UART_Transmit(&huart1, data, size, 0xFFFF);
}
2. 串口接收函数
// 接收指定长度的数据,返回实际接收到的数据长度
uint8_t ReceiveData(uint8_t *data, uint8_t size) {
// 示例:使用HAL库接收数据,带超时
if(HAL_UART_Receive(&huart1, data, size, 100) == HAL_OK) {
return size;
}
return 0;
}
3. 延时函数
// 微秒级延时
void DelayUs(uint32_t us) {
// 示例1:使用定时器实现微秒延时
__HAL_TIM_SET_COUNTER(&htim1, 0);
while(__HAL_TIM_GET_COUNTER(&htim1) < us);
// 示例2:使用HAL库延时函数(不够精确)
// HAL_Delay(us/1000);
}
4. 初始化配置示例
// 串口和定时器初始化
void ServoComInit(void) {
// 配置UART
// 波特率建议:115200或1000000
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
HAL_UART_Init(&huart1);
// 配置用于延时的定时器
// 时钟配置为1MHz(1us记一次数)
htim1.Instance = TIM1;
htim1.Init.Period = 0xFFFF;
htim1.Init.Prescaler = (SystemCoreClock/1000000)-1;
HAL_TIM_Base_Init(&htim1);
HAL_TIM_Base_Start(&htim1);
}
// 舵机通信参数配置
void ServoParamInit(void) {
// 设置通信超时时间(ms)
SetTimeout(100);
// 注册通信函数
RegisterSendDataCallback(SendData);
RegisterReceiveDataCallback(ReceiveData);
RegisterDelayCallback(DelayUs);
}
5. 完整初始化流程
void SystemInit(void) {
// 1. 初始化通信接口
ServoComInit();
// 2. 配置通信参数
ServoParamInit();
// 3. 舵机初始化
uint8_t servo_id = 1;
ServoInit(servo_id);
}
注意事项
- 通信接口相关
- 波特率必须与舵机设置匹配
- 确保通信时序正确,尤其是接收超时设置
- 建议使用DMA方式进行数据收发
- 延时函数实现
- 微秒级延时推荐使用定时器实现
- HAL_Delay()精度不够,不推荐用于微秒延时
- 定时器时钟要配置正确
权限声明
本文档仅用于学习和参考目的。所有内容基于飞特串行舵机相关资料整理,如有不妥请联系删除。
版权说明
- 本文档中的示例代码和说明仅供学习交流使用
- 相关商标、专利和知识产权归飞特智能科技有限公司所有
- 如果官方认为本文档内容不当,请联系删除
注:本文档非官方文档,如有任何疑问请以官方文档为准。