Servo con retroalimentación

Podemos controlar un servo y situarlo en la posición que queramos, pero no tenemos forma de saber en que posición esta.
Para ello, necesitamos un servo con retroalimentación.
Se puede modificar un servo (Futaba S3003) para que nos indique en que ángulo se encuentra.

El sentido de este montaje es que podemos leer la posición del servo moviéndolo a mano y guardarlas en memoria para una posterior ejecución en cadena.
Esto, con un solo servo tiene poco sentido, pero si tenemos, por ejemplo, un brazo articulado con 3-4 servos podemos mover "a mano" cada una de las "articulaciones" e ir grabando sus posiciones hasta lograr que el brazo haga movimientos complejos sin necesidad de programarlos.
Incluso si tenemos dos brazos iguales puede hacerse que al mover un brazo, el otro replique los movimientos del primero a distancia. Los movimientos de uno son leidos por el microprocesador y replicados en el otro.
Son solo dos ejemplos.
Solo necesitamos soldar un cable al conector central del potenciómetro que hay en el servo, como vemos en la imagen superior (cable verde).
Con ello, tendremos una tensión proporcional al giro del potenciómetro y que podremos leer en una entrada analógica del Arduino.

A la derecha vemos un montaje de ejemplo. Control del servo típica con una salida digital y lectura del cable de retroalimentación verde en una entrada analógica. Hay tres botones, borrar la EEPROM, ejecutar lo grabado y el tercero para ir grabando en la EEPROM del Arduino cada una de las posiciones del servo. En Arduino Uno se pueden grabar 512 posiciones. Si se usa más de un servo, habría que reservar segmentos de memoria para cada uno de ellos.




//Programa para grabar movimientos de un servo modificado con feedback
//Movemos a servo a diferentes posiciones que son grabadas pulsando un botón
//Después se ejecutan todas seguidas
//Joaquín Paredes 01/2014  www.jopapa.me

#include <Servo.h>
#include <EEPROM.h>
#define Max 487     //Valores max y min del potenciometro mi servo Futaba S3003
#define Min 135     //Pueden ser diferentes para otros servos.
int grabaBotPin = 2;
int ejecBotPin = 5;
int servoPin = 9;
int resetPin = 6;
int feedbackPin = A0;
int ledPin = 13;
int addr;
Servo myServo;

void setup() {
  Serial.begin(9600);
  pinMode(grabaBotPin, INPUT); digitalWrite(grabaBotPin, HIGH);
  pinMode(ejecBotPin, INPUT); digitalWrite(ejecBotPin, HIGH);
  pinMode(resetPin, INPUT); digitalWrite(resetPin, HIGH);
  pinMode(ledPin, OUTPUT);
  pinMode(feedbackPin, INPUT);
}

void loop() {
if(digitalRead(resetPin) == LOW){          //pone a 255 toda la memoria EEPROM
  Serial.println("Borrando EEPROM, espere...");
  for(addr=0; addr<=512; addr++){ EEPROM.write(addr, 255); }   
  addr = 0;
  Serial.println("EEPROM borrada");
}  
if (digitalRead(grabaBotPin)==LOW) {       //Graba posiciones del servo
   delay(100);
   grabaServo(servoPin, feedbackPin);
}
  if (digitalRead(ejecBotPin)==LOW) {       //Ejecuta en el servo lo grabado en la EEPROM
   delay(400);
   ejecutaServo(servoPin, ejecBotPin);
}
}

void ejecutaServo(int servoPin, int botonPin) {
  addr = 0;
  Serial.println("Activando Servo");
  myServo.attach(servoPin);
  while (digitalRead(botonPin)) {  
    int dato = EEPROM.read(addr);
    Serial.print("Lee EE: "); Serial.print(dato);
    if (dato == 255) break;                       //Detecta final de datos y termina
    dato = map(dato, 0, 254, 0, 180);             //Ajusta a valores posibles en servo
    Serial.print(" -> "); Serial.println(dato);
    myServo.write(dato);
    delay(1500);
    addr++;
    if (addr == 512) break;
  }
  Serial.println(" y termina");
  myServo.detach();
  delay(300);
}

void grabaServo(int servoPin, int analogPin) {
  Serial.println("Grabando posicion");
  digitalWrite(ledPin, HIGH);
  int dato = analogRead(feedbackPin);
  Serial.print("Valor analogico: "); Serial.print(dato);
  if (dato < Min) dato = Min; if (dato > Max) dato = Max;  //Limita valores
  dato = map(dato, Min, Max, 0, 254);                      //Ajusta a valores posibles en EEPROM
  Serial.print(" -> "); Serial.println(dato);
  EEPROM.write(addr, dato);
  addr++;
  digitalWrite(ledPin, LOW);
  Serial.println("Grabada posicion");
  delay(300);
}

Menu