Arduino控制舵机和无刷电机(ESC)

1.Arduino控制舵机

    舵机是一种位置伺服的驱动器,主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号(给舵机1.5ms脉宽、周期为20ms的PWM信号,舵机应该处在中位)将获得的直流偏置电压与电位器的电压比较,获得电压差输出。经由电路板上的IC判断转动方向,再驱动无核心马达开始转动,透过减速齿轮将动力传至摆臂,同时由位置检测器送回信号,判断是否已经到达定位。适用于那些需要角度不断变化并可以保持的控制系统。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。一般舵机旋转的角度范围 是0 度到180 度。

    所有的舵机都有外接三根线,一般用棕、红、橙三种颜色进行区分,棕色为接地线,红色为电源正极线,橙色为信号线。

    舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的,标准PWM(脉冲宽度调制)信号的周期固定为20ms (50Hz),理论上脉宽分布应在1ms到2ms 之间,但是,事实上脉宽 可由0.5ms 到2.5ms 之间,脉宽和舵机的转角0°~180°相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。

    用Arduino 控制舵机的方法有两种,一种是通过Arduino的普通数字传感器接口产生占空比不同的方波,模拟产生PWM信号进行舵机定位,第二种是直接利用Arduino 自带的Servo函数进行舵机的控制, 这种控制方法的优点在于程序编写,缺点是只能控制2路舵机,因为 Arduino 自带函数只能利用数字9、10 接口。Arduino 的驱动能力有限,所以当需要控制1 个以上的舵机时需要外接电源。

1.1方法一:模拟产生PWM信号

       将舵机接数字12接口上(这种方法不是使用analogwrite产生PWM,因此不必使用PWM口)。编写一个程序让舵机转动到用户输入数字所对应的角度数的位置,并将角度打印显示到屏幕上。

int servopin = 12; // 定义数字接口12连接伺服舵机信号线
int myangle; // 定义角度变量
int pulsewidth; // 定义脉宽变量
int val;
void servopulse(int servopin, int myangle) // 定义一个(伺服)脉冲函数
{
  pulsewidth = (myangle*11)+500; // 将角度转化为500-2480的脉宽值(0.5ms~2.5ms的脉宽)
  digitalWrite(servopin, HIGH); // 将舵机接口电平至高
  delayMicroseconds(pulsewidth); // 延时脉宽值的微妙数
  digitalWrite(servopin,LOW); // 将舵机接口电平至低
  delay(20-pulsewidth/1000); // 至低的时间远长于至高的时间
}
void setup() {
  pinMode(servopin, OUTPUT); // 设定舵机接口为输出接口
  Serial.begin(9600); // 连接到串行端口,波特率为9600
  Serial.println("servo=o_seral_simple ready");
}
// 将0到9的数转化为0到180角度,并让LED闪烁相应数的次数
void loop() {
  val = Serial.read(); // 读取串行端口的值(读取char型数据返回int类型)
  if (val>'0'&&val<='9')
  {
    val = val - '0'; // 将特征量转化为数值变量()
    val = val*(180/9); //  将数字转化为角度
    Serial.print("moving servo to ");
    Serial.print(val, DEC); // print as an ASCII-encoded decimal
    Serial.println();
    for (int i=0; i<=50; i++) // 给予舵机足够的时间让它转到指定角度
    {
      servopulse(servopin, val); // 引用脉冲函数
    }
  }
}

1.2方法二:自带的Servo函数

       使用时必须#include  

       Servo也是一个Class,可以创建自己的Servo,例如:Servo myservo;

       1、attach(接口)——设定舵机的接口(数字9或10)

       2、write(角度)——设定旋转角度(0°~180°)

       3、read()读取舵机角度

#include 
Servo myservo;  // create servo object to control a servo
int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(9600);
}

void loop() {
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  Serial.println(val);
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}

1.3关于 -'0' 

int val;
void setup() {
  Serial.begin(9600);
}

void loop() {
  /*if(Serial.available()>0)
  {
    val = Serial.read();    // Serial.read() 读取char型数据,返回的类型根据变量绑定的类型自动转换
    Serial.println(val);
  }*/
  while(Serial.available())
  {
    val = Serial.read();
    Serial.println(val);
    if (val > '0'&& val <='9')
    {
      val = val - '0';
      Serial.println(val-'0');
    }
  }
}


2. Arduino控制无刷电机

       关于电调的控制信号:电调信号是pwm信号,信号频率为50Hz,一个周期为20ms。对于电调来讲,高电平脉宽为1ms表示停转,高电平脉宽为2ms表示满油门运转;对于舵机来说1.5ms是归中,1ms和2ms分别为左右满舵。(因此下面才直接用Servo库来给实现ESC信号的输出)。

Arduino控制舵机和无刷电机(ESC)_第1张图片

关于Servo.write()和Servo.writeMicroseconds()

0.Servo.writeMicroseconds(): Writes a value in microseconds (uS) to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft. On standard servos a parameter value of 1000 is fully counter-clockwise, 2000 is fully clockwise, and 1500 is in the middle.

1.servo.write() allows a maximum of 180 servo positions

  servo.writeMicroseconds() allows a maximum of 1000 servo positions

2.The "write" method simply maps the "degrees" to microseconds and calls the "writeMicroseconds" method anyway.

   The "degree" of turn is simply a convenient abstraction, and few bother to calibrate it.

 

控制程序:

#include  // Using servo library to control ESC
Servo esc; // Creating a servo class with name as esc
int val; // Creating a variable val
void setup()
{
esc.attach(9); // Specify the esc signal pin,Here as D9
esc.writeMicroseconds(1000); // initialize the signal to 1000
Serial.begin(9600);
}
void loop()
{
val= analogRead(A0); // Read input from analog pin a0 and store in val
val= map(val, 0, 1023,1000,2000); // mapping val to minimum and maximum(Change if needed)
Serial.println(val);
esc.writeMicroseconds(val); // using val as the signal to esc
}

补充:电调1ms停转,2ms满油门运转,是指的单向电调,且是方波脉冲。而一般双向电调,1ms反转最大油门,1.5油门中点,2ms满油门正转。


 

你可能感兴趣的:(Embedded,system)