總網頁瀏覽量

2014年10月28日 星期二

傳統伺服馬達(Servo) 改造成 可回饋位置伺服馬達(Smart Servo) Servo Hacked!


幾個月前買了幾顆二手伺服馬達  HITEC HS-311, 今天就來Hacked成可以角度回饋伺服馬達!
市售HS-311 也有新舊版之分(難道是山寨之分?)如下圖.
           

外殼拆開後可以看出電路板走線及IC也不一樣(如下圖), 不過沒關係這種類比伺服馬達原理都一樣利用VR Encoder(可變電阻)來回授位置!


只要找到Encoder回授信號(電壓值)位置,焊條電線連接出來即可以取的馬達轉動位置電壓值,
利用此電壓值可以換算馬達目前處於哪個角度位置, 焊接位置請參考下圖!


焊接線完後整理外殼出線位置,讓回饋電線容易拉出及蓋上外殼,如下圖!



接下來開始寫程式量測回饋訊號電壓及算出角度,Arduino參考程式如下,程式不難容易理解,
把回饋線路接到Arduino A0位置, 主要針對角度 0, 45, 90, 135, 和 180度取得回饋電壓值!


#include <Servo.h>

//servo object
Servo myservo;

//servo position
int pos = 0;
//positions (in degrees) to send to the servo
int positions[] = {0, 45, 90, 135, 180};
int numPositions = 5;

int numMeasurements = 1;
//increase this value to read feedback multiple times and then calculate the arithmetic average

void setup()
{
  //control servo via pin 9
  myservo.attach(3, 650, 2350);
  //start serial comm. for debugging
  Serial.begin(9600);
}

void loop()
{
  int i = 0;
  //iterate over positions
  for(i = 0; i < numPositions; i++)
  {
    pos = positions[i];
    int j = 0;
    double sum = 0;
    double sensorValue = 0;
 
    Serial.print("SETTING:");
    Serial.println(pos);
    myservo.write(pos);
 
    //wait a bit, to give the servo time to reach the requested position
    delay(800);
 
    //read the feedback via A0, once or multiple times
    for(j = 0; j<numMeasurements; j++){
      sum += analogRead(A0);
    }
 
    //calculate average if numMeasurements > 1
    sensorValue = (sum/numMeasurements);
    Serial.print("READ:");
    Serial.println(sensorValue);
 
    //wait for three seconds
    delay(3000);
  }

}


如果調整修改好程式,基本上smart motor改造完成, 可以利用下面程式換算成角度,角度多少會有誤差幾度!

#include <Servo.h>
#include <math.h>

//servo object
Servo myservo;

//servo position
int pos = 0;
//positions (in degrees) to send to the servo
int positions[] = {0, 45, 90, 135, 180};
int numPositions = 5;

int numMeasurements = 5;

//HS-311 servo parameters
int zero_degrees = 98;  // HS-311 New version: 94; Old version: 98
double one_degree = 1.5111;//HS-311 New Version: 1.4889; Old version: 1.51111;

void setup()
{
  //control servo via pin 9
  myservo.attach(3, 650, 2350);
  //start serial comm. for debugging
  Serial.begin(9600);
}

void loop()
{
  int i = 0;
  //iterate over positions
  for(i = 0; i < numPositions; i++)
  {
    pos = positions[i];
    int j = 0;
    double sum = 0;
    double sensorValue = 0;
 
    Serial.println("SETTING:");
    Serial.println(pos);
    myservo.write(pos);
 
    //wait a bit, to give the servo time to reach the requested position
    delay(800);
 
    //read the feedback via A0, once or multiple times
    for(j = 0; j<numMeasurements; j++){
      sum += analogRead(A0);
    }
 
    //calculate average if numMeasurements > 1
    sensorValue = (sum/numMeasurements);
    Serial.println("READ:");
    Serial.println(calcH311ServoPosition(sensorValue));
 
    //wait for three seconds
    delay(3000);
  }

}

double calcH311ServoPosition(double val){
  val -= zero_degrees;
  val /= one_degree;
  val = floor(val);

  return val;
}


這樣就可以DIY製作出一顆可回授位置的伺服馬達!!











4 則留言: