说在前面:
如果你看到/想要购买如图所示的舵机,那么恭喜你可以看这篇帖子来跟我一起使(cai)用(keng)了
一些总线舵机的优点:
- 只需要一根总线就可以连接所有总线舵机,大大减少了接线时的麻烦,同时对于连接结构的灵活性也得到了提升(不会被很多线卡住,,)而且写代码的时候不用在意哪个口接哪个(x2.
- 扭力相对pwm舵机较大,市面上有15,20,30,45kg等可供选择
亿些缺点:
- 贵。一个总线舵机是50-100+不等,而一个SG90舵机大约是7元
- 控制必须要使用格式恒定的字符串指令,在需要多次输入时在交互方面比较头疼
如果你觉得可以忍受上述缺点,请继续往下看:
一、硬件准备
-
一块主控板,我这里用的是arduino uno核心板2.
-
一块24路舵机接线板
*1处为普通舵机接线处,可见满满当当 -
一个可以稳定输出5-8.4v直流的电源,总线舵机需要通过电源额外供电,不然直接用电脑供电控制板可能会烧(
二、一些其他准备
- 需要安装串口工具(需要的串口工具及代码都附在最后链接
- 准备一个arduino
- 看一下链接里的总线舵机使用手册,通读一遍
三、代码编写
- 调试各个舵机,使其的控制模式、波特率、初始值达到设定的目标,这里我修改官方程序使其便于调整,完整程序见链接,部分代码如下:
/*******全局变量宏定义*******/
#define UART_RECEIVE_BUF_SIZE 100
/*******全局变量定义*******/
u8 i=0;
u8 uart_receive_buf[UART_RECEIVE_BUF_SIZE]={0}, uart_receive_buf_index, uart_get_ok;
void setup(void) { //ZL
setup_led(); //初始化LED信号灯
setup_uart(); //初始化串口
/**********************************************
* @总线设备基本控制指令表:
* 1. #000PID! //读取ID指令
* 2. #000PID001! //设置ID指令
* 3. #000PVER! //读取版本
* 4. #000PBD1! //设置波特率 默认115200 1:9600 , 2:19200 , 3:38400 , 4:57600 , 5:115200 , 6:128000 7:256000 8:1000000
* 5. #000PCLE! //恢复出厂设置包括ID
* @总线舵机ZServo控制指令表:
* 1. #000P1500T1000! //舵机角度控制
* 2. #000PDST! //停止
* 3. #000PDPT! //暂停
* 4. #000PDCT! //继续
* 5. #000PCSD! //设置当前值为开机值
* 6. #000PCSM! //开机释放扭力
* 7. #000PRAD! //读取角度
* 8. #000PULK! //释力
* 9. #000PULR! //恢复扭力
* 10. #000PSCK! //设置当前值为1500的偏差值
* 11. #000PSCK+050! //把1500+50作为1500的中间值
* 12. #000PSCK-050! //把1500-50作为1500的中间值
* 13. #000PMOD! //读取模式
* 14. #000PMOD1! //设置模式 舵机模式:2 270 逆时针 1:270 顺 4 180 逆时针 3:180 顺 马达模式:6 360 逆时针 5:360 顺圈 8 360 逆时针 7:360 顺时
* 15. #000PRTV! //读取电压和温度
* 16. #000PSTB! //读取保护值
* 17. #000PSTB=60! //设置保护值 默认60 范围25-80
* 18. #000PPAAAIBBB! //设置KP = AAA, KI = BBB
* 19. #000PMIN! //设置最小值
* 20. #000PMAX! //设置最大值
* 21. #000PULM! //释力 不带阻力
* 22. #000PLN! //RGB灯开启
* 23. #000PLF! //RGB灯关闭
**********************************************/
// uart_send_str((u8 *)"#255PCLE!"); //恢复出厂设置
// uart_send_str((u8 *)"#000PID001!"); //设置ID指令
// uart_send_str((u8 *)"#001PID!"); //读取ID指令
// delay(500);
// uart_send_str((u8 *)"#255PBD1!");
// delay(500);
// uart_send_str((u8 *)"#002PMOD4!"); //设置舵机模式
// delay(500);
// uart_send_str((u8 *)"#001PCSD!"); //设置当前值为开机值
// delay(500);
// uart_send_str((u8 *)"#002PSCK!"); //设置当前值为中间值
// delay(500);
// uart_send_str((u8 *)"#001P1500T1000!");
// uart_send_str((u8 *)"#002P1500T1000!");
// uart_send_str((u8 *)"#003P1500T1000!");
// uart_send_str((u8 *)"#004P1500T1000!");
// delay(1500);
}
总之是按需取用(都被我注释掉了可见一斑),踩坑点在于:
(a)控制多个舵机时如果需要控制每个舵机的转动角度,那么需要给它们一个个编号,切记改ID时总线上只能连你想改的那个舵机,使用#255PID001!改动。如果连着多个舵机那么这条指令会让所有ID都变成001
(b)每个舵机在开始设定的中值是一样的,但是由于舵机连着的齿轮有精度差异,可能需要一个一个调试中值,可以看下一个代码
- 看到上面那个官方例程就会发现:除了初始化一切控制都很不方便,因为它使用了字符串进行控制,在交互方面会出现许多意想不到的bug,万幸的是还有第二个官方例程,于是我就按照第二个程序的思路进行修改
#include <Servo.h>
#include <SoftwareSerial.h> //包含软串口头文件,硬串口通信文件库系统自带String uart1_receive_buf = "";
/*******************************一些宏定义****************************************/
SoftwareSerial mySerial(A4,A5); //创建一个软串口的类,模拟引脚4,5分别代表 RX, TX引脚 AR多功能板
Servo myServo;
int angle;
int myId, myPwm, myTime, destination;
char cmd_return[100];//这里的cmd_return的字符长度要足够的大,根据舵机个数定,大小 = 15*个数+10
String inputString = "";
boolean stringComplete = false;
void setup() {
Serial.begin(9600); //硬件串口
mySerial.begin(9600); //设置软串口波特率 <--原装波特率默认为115200,这里是使用initialize修改后的波特率
Serial.println("请输入舵机ID和角度(格式:ID,角度):");
}
void loop() {
while (Serial.available()>0) {
char inChar = (char)Serial.read();
if (inChar == '\n') {
stringComplete = true;
} else {
inputString += inChar;
}
}
if (stringComplete){
int comma_index = inputString.indexOf(',');
if (comma_index > 0){
String id_string = inputString.substring(0, comma_index);
String angle_string = inputString.substring(comma_index + 1);
myId = id_string.toInt();
angle = angle_string.toInt();
if (angle >= 40 && angle <= 140) {
destination = angle/9.0*100 + 500;
Serial.print("舵机");
Serial.print(myId);
Serial.print("旋转到角度:");
Serial.println(angle);
sprintf(cmd_return, "#%03dP%04dT%04d!", myId, destination, 1000);
Serial.print(cmd_return);
mySerial.print(cmd_return);
} else if(angle<40){
angle = 40;
destination = angle/9.0*100 + 500;
sprintf(cmd_return, "#%03dP%04dT%04d!", myId, destination, 1000);
Serial.print(cmd_return);
mySerial.print(cmd_return);
} else {
angle = 140;
destination = angle/9.0*100 + 500; //由于我设置的是0-180度范围,而舵机控制是0500-2500,这里是把角度转换为舵机可接受的信号
sprintf(cmd_return, "#%03dP%04dT%04d!", myId, destination, 1000);
Serial.print(cmd_return);
mySerial.print(cmd_return);
}
}else{
Serial.println("输入格式无效,请使用格式:ID,角度");
}
inputString = "";
stringComplete = false;
Serial.println("请输入舵机ID和角度(格式:ID,角度):");
while (Serial.available() > 0) { //用于清除串口输入,在没有加这个while循环之前有可能无法进行输入,导致舵机无法驱动
Serial.read();
}
}
}
控制程序到这里就基本结束,除了交互还有一些意想不到的bug:
例如:写完程序已正常运行过,但是没有修改过程序舵机突然不会转了
解决方法:
1.看看舵机接口蓝灯有没有闪烁,如果没有拔掉线重新接上试试。我遇到了上一个灭了不能动下一个灯亮还能动的情况
2.让它休息休息,第二天来保不准能动了,,(真实情况
3.实在解决不了怎么办?call 客服
希望对看到这里的你有所帮助
所需材料链接:GitHub - Chaos1009/Servo: Learning and programming materials for beginners
全部材料链接(有一些已经写好的图形化调试程序):
链接: 百度网盘 请输入提取码 提取码: 5485