幾個月前買了幾顆二手伺服馬達 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製作出一顆可回授位置的伺服馬達!!