A
„feedback”(visszajelzéses)
szervók négy vezetékkel vannak ellátva a sima három vezetékes szervókkal szemben, itt a negyedik
szál az analóg visszajelzést biztosítja.
A szervó kimenő tengelyéről
visszatáplált belső potméter ad egy visszajelzés a szervó
aktuális pozíciójáról, amit a szervó
vezérlőáramkörén keresztül tud elküldeni a mikrovezérlőnek.
„Open loop” rendszernél nincs
visszacsatolás, itt nem lehet ellenőrizni a kiadott utasítás
megfelelő teljesülését (nyílt hurok).
„Closed
loop” rendszer
használ
visszacsatoló jelet, hogy be állítható legyen a motor sebessége,
forgásiránya illetve elfordulása. Ilyen motor a szervó is, itt a
beépített poti leköveti a szervó kar pontos helyzetét és ezt
adja vissza.
Visszacsatolás nélkül csak egyszerűbb alkalmazásoknál használhatók megbízhatóan a szervók, bonyolultabb programoknál csak is visszacsatolással érdemes alkalmazi őket, főleg az időzítések, több szervós kapcsolások illetve elemes táplálás esetén(csökkenő tápfesz).
Kapcsolás:
szervó
fekete – GND
szervó piros – 5V
szervó sárga – vezérlő jel
kifelé D9
szervó fehér – visszajelzés a
szervótol A0
Kód
Először lássuk a visszajelzés kezelését:
void
loop()
{
val =
analogRead(potpin); // beolvassa a val változóba a
szervó pozicióját
val = map(val, 0, 1023, 0, 179); // az
analóg értéket 0-1023 átalakitja fokokká 0-179
myservo.write(val); // kiiratja a szervóra a val
változó értékét
delay(15); //
várakozás
}
kalibráljuk a szervót:
#include
<Servo.h>
Servo
myservo;
// szervó vezérlő pin d9
//szervó visszajelzését fogadó pin
A0
int servoPin = 9;
int feedbackPin = A0;
// változók
létrehozása a kalibrációs értékekhez
int
minDegrees;//elfordulás minimum
int maxDegrees;//elfordulás
max
int minFeedback;//visszajelzás min
int
maxFeedback;//visszajelzés max
int tolerance = 2; //max mérési
hiba visszacsatolásnál
/*
evvel a funkcióval
beállítjuk a szervó elmozdulásának határértékeit
*/
void calibrate(Servo servo,
int analogPin, int minPos, int maxPos)
{
// a szervót
minimális pozícióba mozgatjuk és rögzítjük az értékét
servo.write(minPos);//min pozícióba mozgatjuk a szervót
minDegrees = minPos;
delay(2000); //2mp várakozás
minFeedback = analogRead(analogPin);//beolvassuk az analóg értéket
// a szervót maximális pozícióba mozgatjuk és rögzítjük
az értékét
servo.write(maxPos);
maxDegrees = maxPos;
delay(2000); // 2mp várakozás
maxFeedback =
analogRead(analogPin);
}
void setup()
{
myservo.attach(servoPin);
calibrate(myservo, feedbackPin, 20,
160); // 20-160 fokig kalibrálja a szervó elmozdulását
}
void loop()
{
}
Pozícióra állítás:
void
Seek(Servo servo, int
analogPin,
int pos)
{
servo.write(pos);
// a
visszajelzés alapján kikalkulálja a pozíciót
int target =
map(pos, minDegrees, maxDegrees, minFeedback, maxFeedback);
// várakozik amíg pozícióba nem áll a szervónk
while(abs(analogRead(analogPin) - target) > tolerance){} //
wait...
}
Aktuális pozíció:
int
getPos(int analogPin)
{
return map(analogRead(analogPin), minFeedback, maxFeedback,
minDegrees, maxDegrees);
}
Szervó használata beviteli eszközként:
a kapcsolás
és a kód:
// http://www.adafruit.com/products/1404
#include
<Servo.h>
#include <EEPROM.h>
#define
CALIB_MAX 512
#define CALIB_MIN 100
#define SAMPLE_DELAY 25 // in ms, 50ms
seems good
uint8_t
recordButtonPin =
12;
uint8_t playButtonPin = 7;
uint8_t servoPin = 9;
uint8_t feedbackPin = A0;
uint8_t ledPin = 13;
Servo myServo;
void setup() {
Serial.begin(9600);
pinMode(recordButtonPin, INPUT);
digitalWrite(recordButtonPin, HIGH);
pinMode(playButtonPin, INPUT);
digitalWrite(playButtonPin, HIGH);
pinMode(ledPin, OUTPUT);
Serial.println("Servo
RecordPlay");
}
void loop() {
if (! digitalRead(recordButtonPin)) {
delay(10);
// wait for released
while (!
digitalRead(recordButtonPin));
delay(20);
// OK released!
recordServo(servoPin, feedbackPin,
recordButtonPin);
}
if (!
digitalRead(playButtonPin)) {
delay(10);
// wait for released
while (!
digitalRead(playButtonPin));
delay(20);
// OK released!
playServo(servoPin, playButtonPin);
}
}
void
playServo(uint8_t
servoPin,
uint8_t buttonPin) {
uint16_t addr = 0;
Serial.println("Playing");
myServo.attach(servoPin);
while (digitalRead(buttonPin)) {
uint8_t x = EEPROM.read(addr);
Serial.print("Read EE: ");
Serial.print(x);
if (x == 255) break;
// map to 0-180 degrees
x = map(x, 0, 254, 0, 180);
Serial.print(" -> ");
Serial.println(x);
myServo.write(x);
delay(SAMPLE_DELAY);
addr++;
if (addr == 512) break;
}
Serial.println("Done");
myServo.detach();
delay(250);
}
void recordServo(uint8_t servoPin,
uint8_t analogPin, uint8_t buttonPin) {
uint16_t addr = 0;
Serial.println("Recording");
digitalWrite(ledPin, HIGH);
pinMode(analogPin, INPUT);
while (digitalRead(buttonPin)) {
uint16_t a =
analogRead(analogPin);
Serial.print("Read analog:
"); Serial.print(a);
if (a < CALIB_MIN) a =
CALIB_MIN;
if (a > CALIB_MAX) a =
CALIB_MAX;
a = map(a, CALIB_MIN, CALIB_MAX,
0, 254);
Serial.print(" -> ");
Serial.println(a);
EEPROM.write(addr, a);
addr++;
if (addr == 512) break;
delay(SAMPLE_DELAY);
}
if (addr != 512) EEPROM.write(addr,
255);
digitalWrite(ledPin, LOW);
Serial.println("Done");
delay(250);
}
A sketch inditása után nyomjuk meg a
felső gombot, hogy elindítsuk a felvételt (led világít)
mozgassuk a szervót ahogy szeretnénk,
hogy mozogjon visszajátszáskor.
Nyomjuk meg ismét a felső gombot a
felvétel befejezéséhez. Az alsó gomb megnyomására elindul
a lejátszás. Minden gombnyomásra
újra lejátsza a mozgássort.
A felső gombbal új felvételeket
vehetünk fel, a minta 12,8 mp lehet (ennyi fér az eepromba) ha
elérjük a határt a felvétel
automatikusan leáll, a felvétel jelző led kialszik.
Mivel EEPROMban tárolódik a felvétel ezért még nullázás után illetve kikapcsolás után is megmarad a mozgássor.