初出茅廬的小李第6篇博客之arduino控制兩路舵機

arduino控制兩路舵機

爲什麼想要用arduino控制舵機呢,說來話長,其實最直接原因就是因爲它比較簡單易上手吧。

網傳控制原理還要看一看

舵機是一種位置伺服的驅動器,主要是由外殼、電路板、無核心馬達、齒輪與位置檢測器所構成。其工作原理是由接收機或者單片機發出信號給舵機,其內部有一個基準電路,產生週期爲 20ms,寬度爲 1.5ms 的基準信號,將獲得的直流偏置電壓與電位器的電壓比較,獲得電壓差輸出。經由電路板上的 IC 判斷轉動方向,再驅動無核心馬達開始轉動,透過減速齒輪將動力傳至擺臂,同時由位置檢測器送回信號,判斷是否已經到達定位。適用於那些需要角度不斷變化並可以保持的控制系統。當電機轉速一定時,通過級聯減速齒輪帶動電位器旋轉,使得電壓差爲 0,電機停止轉動。一般舵機旋轉的角度範圍是 0 度到 180 度。

其實我也不知道我買的舵機是不是一般的舵機,反正手裏的舵機是幾個小舵機我看了一下型號 Micro Servo 9g 應該就是江湖上說的SG90舵機記得買的時候是90度舵機,後來實驗發現180度也可以轉,姑且認爲它是180度舵機了。
在這裏插入圖片描述
以上都不重要,重要的是如何接線…
舵機有很多規格,但所有的舵機都有外接三根線,分別用棕、 紅、 橙三種顏色進區分,由於舵機品牌不同,顏色也會有所差異, 色爲接地線, 色爲電源正極線,色爲信號線。其實我個人感覺知道這些就差不多了,不過鑑於第一次使用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);//引用脈衝函數
    }
  }
}

測試效果如圖
在這裏插入圖片描述
這段代碼可以實現串口發送1到9舵機轉動不同的角度,但是我發現了一個問題沒法回到0度,而且程序已經設定好了,於是我就看看了作者是如何實現的對應(菜雞就是這樣踩坑的),我把這裏進行了修改把0也包括進去了就是把>號換成了>=號
val=Serial.read();//讀取串行端口的值
if(val>=‘0’&&val<=‘9’)

在這裏插入圖片描述
註釋裏說的是0到9對應180度,估計是手誤大家都是複製粘貼就導致了將錯就錯,正確的版本可能就應該帶上等於號吧,不管了問題找到了,可是還有一個問題就是我發送10的時候出現了一個奇怪的現象,就是舵機先移動了到了20度後來又移動到了0度,肯定是串口讀取把10當成了1和0了,這下我就明白了爲啥程序上不設計成0到18對應0度到180度了,那樣程序可能就要重新來設計了。這應該是arduino串口的坑,稍後再去探個究竟,先不管,繼續改程序,我要控制舵機。

控制兩路舵機實現同步的0度到180度連續擺動

參考網上的代碼進行了如下修改

#include <Servo.h>
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串口的坑了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章