使用Arduino控制大疆GM6020无刷电机:
话不多说直接上代码
#include <Servo.h>
Servo myservo; //创建一个舵机控制对象
// Arduino自带的Servo函数库只可以同时控制两个模拟舵机;
//且最好使用D9 D10脚;
//若需要控制多个舵机则需要用pwm功能;
//使用Servo类最多可以控制8个舵机
int pos = 1840; // 该变量(pos)用于存储舵机角度位置
char num;
int i = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~朴实的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~ */
void setup()
{
Serial.begin(19200);
myservo.attach(9); // 该舵机由arduino第九脚控制
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~朴实的分割线 ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
void loop()
{
num = Serial.read();
switch(num){
case '1':
pos = 1840;
myservo.writeMicroseconds(pos);
delay(20);
break; /* 可选的 */
case '3':
pos = 1210;
myservo.writeMicroseconds(pos);
delay(20);
break; /* 可选的 */
case '4':
pos = 1425;
myservo.writeMicroseconds(pos);
delay(20);
break; /* 可选的 */
case '0':
pos = 1635;
myservo.write(pos);
delay(20);
break; /* 可选的 */
/* 您可以有任意数量的 case 语句 */
default : /* 可选的 */
myservo.writeMicroseconds(pos);
delay(20);
break;
}
}
具体的编程思想是模拟50HZ的PWM波来完成对GM6020电机的控制,笔者的代码并不是非常好,建议大家使用定时器Timer来完成模拟这样Arduino就可以做更多事了,而非将全部的资源都用来模拟PWM波
如果大家觉得有帮助的话可以点个赞!
2021.9.9
由于项目需要,又用了一下GM6020,更新一下代码,可以不用模拟PWM波直接用它自带的Servo库即可(Servo库本身就是用的定时器实现的控制),但是需要设置一下占空比的范围,我用的是ESP32,用Arduino的话改一下就行了
#include <ESP32Servo.h>
#define OUT_X 17 // 伺服馬達X的輸出腳
Servo servoX;
int pos = 0, temp = 0;
void setup() {
// put your setup code here, to run once:
servoX.attach(OUT_X, 1000, 2000); // 設定伺服馬達的接腳
Serial.begin(115200); //设置串口波特率9600
}
void loop() {
// put your main code here, to run repeatedly:
while(!Serial)//检测是否有串口接通
{}
if(Serial.available()>0) //判断是否具有输入
{
pos=Serial.parseInt(); //接收数据
if (pos != 0)
{
Serial.println(pos);
servoX.write(pos); //定义舵机的转动角度
}
}
}
如果GM6020没反应的话,可以拨一下电机底座上决定ID号的拨码开关就行了
2022.2.9
最近经过测试,使用3508电机时我发现上面那个使用ESP32Servo库的程序时好时坏,经过思考我发现,问题出在了串口通讯上面,库本身是能够发出正确的PWM波的,但是由于我们使用串口控制的缘故,导致程序需要的等待我们发出串口的指令,这样ESP32Servo库发出PWM波的周期就不正确了,这也是为什么我最开始第一次更新的那个程序可以正常工作而后面这个有的时候可以而有的时候不可以,最前面的那个Arduino的那个程序,因为在无论何时都是满足50HZ的发布频率,因为我们使用了delay去模拟,所以电调才能一直接收到正确频率的PWM波信号,这个3508很娇贵,你必须先按照他的要求发送给PWM波把他骗过去,后面就是你想咋发就咋发了,程序代码如下:
#include <ESP32Servo.h>
// #include <SPI.h>
// #include <Wire.h>
#define OUT_X 15 // 3508的輸出腳
Servo servoX;
int pos = 1500, temp = 0, flag = 2000;
void setup() {
// put your setup code here, to run once:
servoX.attach(OUT_X, 1000, 2000); // 設定3508的接腳
Serial.begin(115200); //设置串口波特率115200
// 3508初始化
while(flag > 1430) // 我使用的这个3508是1430的脉宽的时候静止,这一段的意义是按照C620要求的发布速率发布
{ // pwm波先把电调给骗过去,然后后面你给他发什么他就会干什么
servoX.write(flag--);
Serial.println(flag);
delay(20);
}
}
void loop() {
while(!Serial)//检测是否有串口接通
{}
if(Serial.available()>0) //判断是否具有输入
{
temp=Serial.parseInt(); //接收数据
if (temp != 0)
{
pos = temp;
Serial.println(pos);
servoX.write(pos); //定义3508的转动速度的PWM脉宽
}
}
}
另附测试代码,不是串口控制,是直接控制,建议这样做比较合适
#include <ESP32Servo.h>
#define OUT_X 15 // 3508的輸出腳
Servo servoX;
int pos = 90, temp = 0;
void setup() {
// put your setup code here, to run once:
servoX.attach(OUT_X, 1000, 2000); // 設定3508的接腳
servoX.setTimerWidth(20);
Serial.begin(115200); //设置串口波特率115200
}
uint16_t flag=1500;
void loop() {
// put your main code here, to run repeatedly:
while(flag < 2000){
servoX.write(flag++); // 理论上1500停止 1000顺时针最大速度 2000逆时针最大速度中间是线性的
delay(10);
}
while(flag > 1000){
servoX.write(flag--);
delay(10);
}
}
使用ESP32的话为了不阻塞性延时loop函数,建议使用FreeRTOS创建一个task来专门处理此事