宁天道/FeelECH
01-介绍
串口总线舵机,可以通过一根线将多个舵机串联在一起,一个串口线片可以控制所有的舵机。
内带闭环,可以自定义舵机移动的最大速度,加速度,
可以修改各种模式,满足各种各样的需求,步进模式,
可控最多7.5圈稳定闭环转动
需要USB/TTL调试版
通过入手教程学习
数据单位和指令内容等在内存表中可以看
其他长相的也行
默认波特率1000000
电压6-8.4
02-上位机调试内容
0-连接上位机
使用USB与调试版连接时,然后和舵机通信时,需要将ZX和USB引脚短接,其他调试版应该也有类似的需求,注意一点
1-设计扭矩
仅限夹取相同物品(相同质量的物品)且需提前设定好“扭矩限制”百分比,如果是多次夹取质量体积不固定的物品,无法判定舵机需要输出的扭矩值,可能会损坏物体或舵机出现过载卸力等情况。
以串口舵机为例,串口舵机具备“扭矩限制”百分比输出可控。当物体的重量需要舵机输出 1kg 的力且能维持物品夹取不掉落又不损伤物体。
我们可以通过以下操作实现:假设堵转扭矩为 10kg.cm,在 16 地址“扭矩限制”中输入 100(表示 10kg 的 10%即 1kg 输出),即可实现 1kg 的力去夹取物品,但同时速度也会变慢。
舵机输出轴是按照公斤每厘米计算的,如 20kg.cm 就是输出轴中心 1CM 处最大负重 20kg,如装上摆臂后,摆臂长度是 10CM,那么摆臂末端所能负重最大是 2kg,舵机在最大负载下寿命及短,需保证在额定负载下,会延长舵机使用寿命,一般堵转的三分一是额定扭矩,那么上述说的 20kg.cm,额定就是约为 6.5kg 以下,2kg 就是 0.65kg 以下。
2-观察最大速度
3-修改舵机ID
4-修改波特率
还有一部分,看上手手册去吧
03-基本调度(无DMA)(自行移植版本v0.1)
1-写逻辑
这是一个发送指令的函数
int syncReadPacketTx(uint8_t ID[], uint8_t IDN, uint8_t MemAddr, uint8_t nLen)
{
uint8_t checkSum;
uint8_t i;
rFlushSCS();
syncReadRxPacketLen = nLen;
checkSum = (4+0xfe)+IDN+MemAddr+nLen+INST_SYNC_READ;
writeByteSCS(0xff);
writeByteSCS(0xff);
writeByteSCS(0xfe);
writeByteSCS(IDN+4);
writeByteSCS(INST_SYNC_READ);
writeByteSCS(MemAddr);
writeByteSCS(nLen);
for(i=0; i<IDN; i++){
writeByteSCS(ID[i]);
checkSum += ID[i];
}
checkSum = ~checkSum;
writeByteSCS(checkSum);
wFlushSCS();
syncReadRxBuffLen = readSCS(syncReadRxBuff, syncReadRxBuffMax);
return syncReadRxBuffLen;
}
int writeByteSCS(unsigned char bDat)
{
if(wLen<sizeof(wBuf)){
wBuf[wLen] = bDat;
wLen++;
}
return wLen;
}//将数据指令逐个写入缓冲区
//写缓冲区结束,将其阻塞发送
void wFlushSCS()
{
if(wLen){
Uart_Send(wBuf, wLen);
wLen = 0;
}
}
void Uart_Send(uint8_t *buf , uint16_t len)
{
HAL_UART_Transmit(UART_InitStructure, buf, len, HAL_MAX_DELAY);
}
2-读逻辑
先发送指令,之后立刻进入阻塞式接收方式(那我DMA是不是也可以仿照这种模式)
int readSCS(unsigned char *nDat, int nLen)
{
return Uart_Read(nDat, nLen, IOTimeOut);
}
int16_t Uart_Read(uint8_t *buf , uint16_t len, uint32_t timeout)
{
if(HAL_UART_Receive(UART_InitStructure, buf, len, timeout)==HAL_OK){
return len;
}else{
return 0;
}
}
接收到数据后,直接下一步进入结算
for(i=0; i<sizeof(ID); i++){
//接收ID[i]同步读返回包
if(!syncReadPacketRx(ID[i], rxPacket)){
continue;//接收解码失败
}
STS_Group[i]->position = syncReadRxPacketToWrod(15);//解码两个字节 bit15为方向位,参数=0表示无方向位
STS_Group[i]->speed = syncReadRxPacketToWrod(15);//解码两个字节 bit15为方向位,参数=0表示无方向位
HAL_Delay(10);
}
04-DMA版本(v1.1)
有些缺陷,在scan和set间最少间隔一毫秒
在sts_api.h中有详细的调用方案
1-写逻辑
在开始发送的时候关闭DMA传输,在结束发送的时候重新开启,此时的效果和缓冲区模式类似
//只在内部
void Uart_DMA_Send_Stop(void)//开始写缓冲区时,关闭,并清空缓冲区
{
HAL_UART_DMAStop(&UART_InitStructure);
//直接关闭串口全部DMA,可能有问题,
// 或许可以通过全局变量加个保护
}
//只在内部
void Uart_DMA_Send_Start(uint8_t *buf , uint16_t len){//写完缓冲区后,打开发送DMA
HAL_UART_Transmit_DMA(&UART_InitStructure, buf, len);//使用DMA发送数据
}
2-读逻辑
开启串口空闲中断
在完成指令的发送后,立刻打开DMA接收,之后读函数就结束,在串口空闲中断进入的时候,进行数据的计算
问题:
01-串口空闲中断只在接收完一帧数据后,没有继续接收数据时才会进入,发送结束不会激活。
02-一开始这个逻辑时不能用的,但在给malloc前加入了(uint8_t*)后就可以用了,不知道为什么,观察到没有的时候,其数据一直是0且只有一位。加入后,也只有一位,但数据为ff