初出茅庐的小李第6篇博客之arduino控制两路舵机

arduino控制两路舵机

为什么想要用arduino控制舵机呢,说来话长,其实最直接原因就是因为它比较简单易上手吧。

网传控制原理还要看一看

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

其实我也不知道我买的舵机是不是一般的舵机,反正手里的舵机是几个小舵机我看了一下型号 Micro Servo 9g 应该就是江湖上说的SG90舵机记得买的时候是90度舵机,后来实验发现180度也可以转,姑且认为它是180度舵机了。
初出茅庐的小李第6篇博客之arduino控制两路舵机_第1张图片
以上都不重要,重要的是如何接线…
舵机有很多规格,但所有的舵机都有外接三根线,分别用棕、 红、 橙三种颜色进区分,由于舵机品牌不同,颜色也会有所差异, 色为接地线, 色为电源正极线,色为信号线。其实我个人感觉知道这些就差不多了,不过鉴于第一次使用arduino驱动舵机我还是决定网上参考一下。

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

由于我有四个舵机,其实原本打算做天猫精灵模拟垃圾分类开垃圾箱的,所以决定先尝试第一种方法,毕竟第二种只能驱动两个舵机,太少了。

前人踩过的坑还是要再踩一遍

int servopin=9;//定义数字接口 9 连接伺服舵机信号线
int myangle;//定义角度变量
int pulsewidth;//定义脉宽变量
int val;
void servopulse(int servopin,int myangle)//定义一个脉冲函数
{
  pulsewidth=(myangle*11)+500;//将角度转化为 500-2480 的脉宽值
  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" ) ;
}
void loop()//将 0 到 9 的数转化为 0 到 180 角度,并让 LED 闪烁相应数的次数
{
  val=Serial.read();//读取串行端口的值
  if(val>'0'&&val<='9')
  {
  val=val-'0';//将特征量转化为数值变量
  val=val*(180/9);//将数字转化为角度
  Serial.print("moving servo to ");
  Serial.print(val,DEC);
  Serial.println();
    for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
    {
      servopulse(servopin,val);//引用脉冲函数
    }
  }
}

测试效果如图
初出茅庐的小李第6篇博客之arduino控制两路舵机_第2张图片
这段代码可以实现串口发送1到9舵机转动不同的角度,但是我发现了一个问题没法回到0度,而且程序已经设定好了,于是我就看看了作者是如何实现的对应(菜鸡就是这样踩坑的),我把这里进行了修改把0也包括进去了就是把>号换成了>=号
val=Serial.read();//读取串行端口的值
if(val>=‘0’&&val<=‘9’)

初出茅庐的小李第6篇博客之arduino控制两路舵机_第3张图片
注释里说的是0到9对应180度,估计是手误大家都是复制粘贴就导致了将错就错,正确的版本可能就应该带上等于号吧,不管了问题找到了,可是还有一个问题就是我发送10的时候出现了一个奇怪的现象,就是舵机先移动了到了20度后来又移动到了0度,肯定是串口读取把10当成了1和0了,这下我就明白了为啥程序上不设计成0到18对应0度到180度了,那样程序可能就要重新来设计了。这应该是arduino串口的坑,稍后再去探个究竟,先不管,继续改程序,我要控制舵机。

控制两路舵机实现同步的0度到180度连续摆动

参考网上的代码进行了如下修改

#include 
int servopin_1=9;//定义数字接口 9 连接伺服舵机信号线
int servopin_2=10;//定义数字接口 10 连接伺服舵机信号线

//int myangle_1;//定义角度变量
//int myangle_2;//定义角度变量

int pulsewidth;//定义脉宽变量
int val=0;//初始值

void servopulse(int servopin,int myangle)//定义一个脉冲函数,参数是舵机信号线和角度
{
  pulsewidth=(myangle*11)+500;//将角度转化为 500-2480 的脉宽值
  digitalWrite(servopin,HIGH);//将舵机接口电平至高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(servopin,LOW);//将舵机接口电平至低
  delay(20-pulsewidth/1000);//延时周期内剩余时间
}
void setup()
{
  pinMode(servopin_1,OUTPUT);//设定舵机1接口为输出接口
  pinMode(servopin_2,OUTPUT);//设定舵机2接口为输出接口
  
  Serial.begin(9600);//连接到串行端口,波特率为 9600
  Serial.println("servo=o_seral_simple ready" );//串口打印的提示
}
void loop()
{
  for(val=0;val<=180;val=val+30)
    {
      Serial.print("moving servo to ");
      Serial.print(val,DEC);//十进制输出
      Serial.println();//回车换行
      servopulse(servopin_1,val);//1引用脉冲函数
      servopulse(servopin_2,val);//2引用脉冲函数
     if(val==180)//如果移动到了180度
     delay(2000);//暂停两秒钟
    }  
  for(val=180;val>=0;val=val-10)
   {
      Serial.print("moving servo to ");
      Serial.print(val,DEC);//十进制输出
      Serial.println();//回车换行
      servopulse(servopin_1,val);//1引用脉冲函数
      servopulse(servopin_2,val);//2引用脉冲函数
      if(val==0)//如果移动到了0度
      delay(2000);//暂停两秒钟
    }
  }

小破站的视频
https://www.bilibili.com/video/av88852837/

实现了想要的效果,为了使效果更加明显,我就加了两个大延时(delay大法好)
看人家的程序舵机移动的感觉很迅速,自己的for循环发现舵机跟傻了一样,龟速移动后来修改了for循环的步进值发现速度确实变化了不少,如果想要舵机响应的快一点就可以把步进值30调的更大一些。就这样吧,接下来可能要去填一下arduino串口的坑了。

你可能感兴趣的:(初出茅庐的小李第6篇博客之arduino控制两路舵机)