Brazo Robótico Sencillo

Hola a todos, estoy construyendo un brazo robótico sencillo utilizando 4 servomotores, es un proyecto bastante dificil para mi que me llevará tiempo, pero me apetece intentarlo, y no tengo ninguna prisa.

Por ahora, estoy con la programación y con el circuito eléctrico, pero he caído en un pequeño detalle. Poseo servos pequeños, TowerPro MG90s, y servos más grandes como el MG 996R. A parte de la enorme diferencia de torque entre ambos, resulta que el más pequeño es analógico, y el grande es digital, asi que a la hora de moverlo con un potenciómetro, el grande no me hace ni caso. He estado googleando e investigando, pero la única manera de mover un servo digital que he encontrado es mediante 2 botones, lo cual me parece bastante molesto. Por ahora, mi única pregunta sería si sería posible mover también los digitales con potenciómetros o con joysticks, utilizando otro código, mas pines, etc…

En cuánto a Hardware, uso:

Arduino Mega 2560 (oficial)

4 potenciometros de 4,7 k

3 TowerPro MG 90S (2.2 kg de torque cada uno)

1TowerPro MG996R (10kg de torque)

Fuente alimentación regulable SOLO para el Arduino (le meto 7,5v)

4 pilas Varta 1.2 voltios recargables de 2700 miliamperios cada una (No dan 4.8 entre las 4 dan 5.4, porque están nuevas, cuando deje de colarme asi, usare 5 en vez de 4)

Próximamente, contare con 2 MG 946R de 12 kg de torque, también digitales, que reemplazaran al MG996R y a uno de los MG90S, para darle asi más fuerza y resistencia al brazo. Si necesitáis que pase el código que estoy usando para mover los servos analógicos con el potenciómetro, decídmelo y lo subiré lo más rápido que pueda.

Muchas gracias a todos por vuestras respuestas, atención y tiempo.

Hola danielr8, este es tu proyecto y tu evaluarás que hace falta mostrar y que no.
En general todos los proyectos intentan mostrar todo y compartir cosas para sacar lo mejor para todos.
En tu caso mi primer pregunta es: como vas a alimentar los servos. Hablas de una fuente para el arduino pero no entendí como alimentaras los servos.

Respondiendo tu pregunta: puedes mover los servos como gustes. Pero primero sería mas interesante saber, mas alla de hacer el brazo robótico, que intentas hacer con el, porque eso cambia la interfaz a usar para darle movimiento al brazo.
Si solo quieres moverlo usas botones o potenciometros.
tambien puedes darle movimientos predeterminados para cumplir una tarea X. Asi que eso se podria hacer con una secuencia de pasos que el brazo ejecutaria. COmo si fuera un robot soldador en una cadena de fabricación de autos por ejemplo.
Podrias hacer que tu robot moviera un cubo rubic y lo resolviera… pero es mas complejo.
O podrias hacer que gracias a algun sensor tomara una figura que pasa por una cinta transportadora y la depositara en una caja determinada.

Primero que todo, no tengo ningún problema en compartirlo todo, y ahora mismo os paso el código que uso para mover los servo analógicos el cual no me está funcionando con los digitales, a ver si encontráis el fallo, o si me podríais explicar como adaptarlo a algún servo digital ( sin usar botones, prefiero potenciómetros, por que luego los reemplazaré por joysticks)

#include <Servo.h>

Servo TowerProBase;//Servos pesados
Servo TowerPro;

Servo MG90s;//Microservos
Servo MG90sPinza;

int pot1 = 1;//potenciometros para servos pesados (analogicos)
int pot2 = 2;

int pot3 = 3;//Potenciometros para microservos (analogicos)
int pot4 = 4;

void setup(){

Serial.begin(9600);

TowerProBase.attach(3);//Pines digitales servos pesados 
TowerPro.attach(5);

MG90s.attach(7);//Pines digitales microservos
MG90sPinza.attach(9);

}

void loop(){

int valpot1 = analogRead(pot1);
int val1 = map(valpot1,0, 1023, 0, 180); //Giro TowerProBase
TowerProBase.write(val1);
delay(20);

int valpot2 = analogRead(pot2);
int val2 = map(valpot2,0, 1023, 0, 180); //Giro TowerPro
TowerPro.write(val2);
delay(20);

int valpot3 = analogRead(pot3);
int val3 = map(valpot3,0, 1023, 0, 180); //Giro MG90s
MG90s.write(val3);
delay(20);

int valpot4 = analogRead(pot4);
int val4 = map(valpot4,0, 1023, 0, 180); //Abrir y cerrar pinza con MG90sPinza
MG90sPinza.write(val4);
delay(20);


}

(Siento si he usado mal el icono del código, no estoy muy seguro de como se usa)

Respecto a tu pregunta, los servos van alimentados a parte, como dije en el post (creo que no quedó muy claro). Van alimentados con 4 pilas de 1.2 v y 2700 miliamperio cada una, osea, 9800 miliamperios en total. El voltaje por ahora, no es problema, por que al estar completamente nuevas, no suman 4.8 voltios, si no más de 5 voltios,(5.3 o asi) pero de todos modos no habría problema, por que dispongo de 8 pilas en total, y son todas recargables, sería cuestión de poner 1 pila máś en un portapilas más grande.

Por último, respecto al funcionamiento del brazo, si consigo que se mueva, me doy por contento. Luego, ya intentaré pensar algo más si lo consigo, aunque lo del cubo de rubik, es imposible para alguien con mi nivel (tengo 16 años y estoy en 1º de bachillerato, aun no tengo edad para ir a la universidad)

Inicialmente, lo que me gustaría hacer sería un brazo sencillo, en contrachapado, acabado en una pinza, que coja cosas controlado de manera humana (un poco como una grúa). Si consigo esto, ya se me abrirían muchas puertas para darle funciones al brazo o más autonomía.

Brazo_Rob_tico.ino (999 Bytes)

Tras un tiempo, el brazo avanza satisfactoriamente, y ya he conseguido hacer funcionar 2 de los 4 servos que irán en el. Estos 2 servos,son digitales, y son los dos que forman la base y el hombro del brazo. EL problema ha llegado cuando he puesto el analógico del codo, el cual no obedece las ordenes del potenciómetro, y no para de repetir un movimiento que no he programado (creo que es alguna interferencia de algún tipo, o ruido, no estoy seguro)

Este, es el código de ambos digitales, que funcionan bien, lo dejo aqui, y abajo, por si alguien lo quiere descargar.

#include <Servo.h>

Servo MG995base;
Servo MG995hombro;

int right1 = 7;
int right2 = 12;

int left1 = 8;
int left2 = 13;

int right_state1;
int left_state1;

int right_state2;
int left_state2;




int servo_val1;
int servo_val2;


void setup()
{
  Serial.begin(9600);
  pinMode(right1, INPUT);
  pinMode(left1, INPUT);
  pinMode(right2, INPUT);
  pinMode(left2, INPUT);
  
  MG995base.attach(6);
  MG995hombro.attach(11);
  
  servo_val1 = MG995base.read();
  servo_val2 = MG995hombro.read();
}

void loop()
{
  right_state1 = digitalRead(right1);
  left_state1 = digitalRead(left1);
  right_state2 = digitalRead(right2);
  left_state2 = digitalRead(left2);
 
 
  if(right_state1 == HIGH)
  {
    MG995base.write(servo_val1 - 1);
    delay(14);
    servo_val1 = MG995base.read();
    Serial.println("Right1 HIGH");
  }
 
  if(left_state1 == HIGH)
  {
  MG995base.write(servo_val1 + 1);
  delay(14);
  servo_val1 = MG995base.read();
  Serial.println("Left1 HIGH");
  }
  
  if(left_state1 == HIGH)
  {
  MG995base.write(servo_val1 + 1);
  delay(14);
  servo_val1 = MG995base.read();
  Serial.println("Left1 HIGH");
  }
  
  if(right_state2 == HIGH)
  {
    MG995hombro.write(servo_val2 - 1);
    delay(14);
    servo_val2 = MG995hombro.read();
    Serial.println("Right2 HIGH");
  }
    
   if(left_state2 == HIGH)
  {
  MG995hombro.write(servo_val2 + 1);
  delay(14);
  servo_val2 = MG995hombro.read();
  Serial.println("Left2 HIGH");
  }
}

A su vez, los digitales me presentan un problema. Dan movimientos bruscos tremendos cuando enciendo el brazo, supongo que por algún pico de tensión o amperaje. No tengo muy claro como puede solucionarse, agradecería cualquier tipo de directriz. Las conexiones de estos servos son muy sencillas, simplemente los conecto a una protoboard, directamente, positivo y negativo, y el pin de la señal al arduino. Los servos van alimentados aparte del Arduino con 4 pilas AA, de 2700 miliamperios cada una (son servos MG995, dato)

Este sería el ejemplo de programa del brazo, que no me funciona, que causa la interferencia con el servo analógico Mg90s

#include <Servo.h>

Servo MG995base;
Servo MG995hombro;
Servo MG90scodo;

int right1 = 7;
int right2 = 12;

int left1 = 8;
int left2 = 13;

int right_state1;
int left_state1;

int right_state2;
int left_state2;

int pot1 = 1;


int servo_val1;
int servo_val2;


void setup()
{
  Serial.begin(9600);
  pinMode(right1, INPUT);
  pinMode(left1, INPUT);
  pinMode(right2, INPUT);
  pinMode(left2, INPUT);
  
  MG995base.attach(6);
  MG995hombro.attach(11);
  MG90scodo.attach(22);
  
  
  servo_val1 = MG995base.read();
  servo_val2 = MG995hombro.read();
}

void loop()
{
  right_state1 = digitalRead(right1);
  left_state1 = digitalRead(left1);
  right_state2 = digitalRead(right2);
  left_state2 = digitalRead(left2);
 
 
  if(right_state1 == HIGH)
  {
    MG995base.write(servo_val1 - 1);
    delay(14);
    servo_val1 = MG995base.read();
    Serial.println("Right1 HIGH");
  }
 
  if(left_state1 == HIGH)
  {
  MG995base.write(servo_val1 + 1);
  delay(14);
  servo_val1 = MG995base.read();
  Serial.println("Left1 HIGH");
  }
  
  if(left_state1 == HIGH)
  {
  MG995base.write(servo_val1 + 1);
  delay(14);
  servo_val1 = MG995base.read();
  Serial.println("Left1 HIGH");
  }
  
  if(right_state2 == HIGH)
  {
    MG995hombro.write(servo_val2 - 1);
    delay(14);
    servo_val2 = MG995hombro.read();
    Serial.println("Right2 HIGH");
  }
    
   if(left_state2 == HIGH)
  {
  MG995hombro.write(servo_val2 + 1);
  delay(14);
  servo_val2 = MG995hombro.read();
  Serial.println("Left2 HIGH");
  }
  
  {
    int valpot = analogRead(pot1);
    int val = map(valpot,0, 1023, 0, 180); //Giro MG90s
    MG90scodo.write(val);
    delay(20);
  }
}

Si encontráis el fallo, por favor, decídmelo. En breve pasaré un diagrama con las conexiones que supongo que os facilitará el trabajo y algún video. Muchas gracias por vuestra atención y respuestas.

_2_servos_digi_y_analog_error.ino (1.6 KB)

_2_servos_digi_def.ino (1.41 KB)

Hola, hace mucho tiempo que no posteo, pero no he abandonado el proyecto. Es más el brazo ya casi está acabado, pero tengo un problema. No consigo que los servomotores me hagan caso, y no acabo de entender que es lo que está mal, si el programa, o la electrónica.

Os explico, estoy usando 4 servomotores digitales, y moviéndo cada uno con 2 pulsadores pcb. Uno de los pulsadores le da la orden"+1" y otro “-1” haciendo así que los servomotores giren, pero a veces se vuelven locos, y se ponen a vibrar y a girar en todas direcciones, sin obedecer los pulsadores. A parte, los servos, giran más rápido hacia un lado, que hacia el otro, y no encuentro ninguna razón para ello.

Dejo aqui el código, a ver si encontráis algún error que explique que está mal. En breves pasaré un diagrama del circuito.

Gracias por vuestras respuestas.

#include <Servo.h>

Servo MG995base;
Servo MG995hombro;
Servo Emaxcodo;
Servo Emaxpinza;

int right1 = 7;
int right2 = 12;
int right3 = 22;
int right4 = 26;

int left1 = 8;
int left2 = 13;
int left3 = 24;
int left4 = 28;


int right_state1;
int left_state1;
int right_state2;
int left_state2;

int right_state3;
int left_state3;

int right_state4;
int left_state4;



int servo_val1;
int servo_val2;
int servo_val3;
int servo_val4;

void setup()
{
  Serial.begin(9600);
  pinMode(right1, INPUT);
  pinMode(left1, INPUT);
  pinMode(right2, INPUT);
  pinMode(left2, INPUT);
  pinMode(right3, INPUT);
  pinMode(left3, INPUT);
  pinMode(right4, INPUT);
  pinMode(left4, INPUT);
  
  MG995base.attach(6);
  MG995hombro.attach(11);
  Emaxcodo.attach(3);
  Emaxpinza.attach(5);
  
  
  servo_val1 = MG995base.read();
  servo_val2 = MG995hombro.read();
  servo_val3 = Emaxcodo.read();
  servo_val4 = Emaxpinza.read();
}

void loop()
{
  right_state1 = digitalRead(right1);
  left_state1 = digitalRead(left1);
  
  right_state2 = digitalRead(right2);
  left_state2 = digitalRead(left2);
  
  right_state3 = digitalRead(right3);
  left_state3 = digitalRead(left3);
  
  right_state4 = digitalRead(right4);
  left_state4 = digitalRead(left4);
  
  

 
  if(right_state1 == HIGH)
  {
    MG995base.write(servo_val1 - 1);
      delay(14);
    servo_val1 = MG995base.read();
    Serial.println("Right1 HIGH");
  }
  if(left_state1 == HIGH)
  {
  MG995base.write(servo_val1 + 1);
  delay(14);
  servo_val1 = MG995base.read();
  Serial.println("Left1 HIGH");
  }
  
  
  
  if(right_state2 == HIGH)
  {
    MG995hombro.write(servo_val2 - 1);
    delay(14);
    servo_val2 = MG995hombro.read();
    Serial.println("Right2 HIGH");
  }
    
   if(left_state2 == HIGH)
  {
  MG995hombro.write(servo_val2 + 1);
  delay(14);
  servo_val2 = MG995hombro.read();
  Serial.println("Left2 HIGH");
  }
  
  
  
  if(right_state3 == HIGH)
  {
    Emaxcodo.write(servo_val3 - 1);
    delay(14);
    servo_val3 = Emaxcodo.read();
    Serial.println("Right3 HIGH");
  }
    
   if(left_state3 == HIGH)
  {
  Emaxcodo.write(servo_val3 + 1);
  delay(14);
  servo_val3 = Emaxcodo.read();
  Serial.println("Left3 HIGH");
  }
  
  
  if(right_state4 == HIGH)
  {
    Emaxpinza.write(servo_val4 - 1);
    delay(14);
    servo_val4 = Emaxpinza.read();
    Serial.println("Right4 HIGH");
  }
    
   if(left_state4 == HIGH)
  {
  Emaxpinza.write(servo_val4 + 1);
  delay(14);
  servo_val4 = Emaxpinza.read();
  Serial.println("Left4 HIGH");
  }
  
  
}

4_servos_digi.ino|attachment (2.45 KB)

Tendrias que tener una condicion que limitara el movimiento del servo en caso de rebasar los limites del servo que son 0° y180° (en algunos servos me encontrado que hay que poner algun grado mas de 0° y menos de 180° porque hacian tope) .por ejemplo antes de hacer el write cuando restas ,comprobar si el resultado va ser menor que 0 y cuando sumas que no pase de 180:

If (valor - 1 >= 0) {
      //entonces puedes restar 1 y hacer el write.esto para
     // boton de restar 
}
If (valor + 1 <= 180){
   //entonces puedes sumar y hacer el write.esto para 
   //boton sumar
}

Donde valor es la posicion que le vas a dar al servo.
En cuanto a que se vuelvan locos pinta a interferencias.has comunicado todos los gnd de los servos,fuente alimentacion y arduino?

Hola jose, muchas gracias por tu atención y tu tiempo, primero que todo.

Respeto a lo que dices del código, pinta bien, y lo probaré en cuánto pueda, pero mis servos giran 210º (no se por que, tecnicamente son de 180º, pero yo el tope se lo veo en 210º). Tendría que poner la limitación del programa en 180º o en 210º, entonces?

Y respecto a lo que dices del circuito, no entiendo muy bien la pregunta, pero ahora te paso un diagrama hecho con Fritzing, que espero que responda a lo que necesitas saber para ayudarme. Debo aclarar, que no todos los componentes son los que uso, en Fritzing faltan muchas cosas. Para empezar, donde hay una batería de 9v, en realidad yo uso una pequeña fuente que va a la pared de 7.5 v, y se la enchufo en la alimentación del arduno ( no en el USB, en el de al lado). Y el paquete de baterías, tampoco lo uso, uso una fuente regulable que va de 0 a 30 v y que me da de 0 a 3 Amperios, lo cual considero más que suficiente para los 4 servos.

Ah, y las resistencias, son todas de 10k.

Como puedes ver, por una parte alimento la Arduino Mega, a la cual van los pines de señal de lo servos, y los pines de los botones, y por otra parte, con la fuente grande, alimento los servos. Espero que esto te sirva de esquema, te lo dejo en la descripción.

De nuevo, muchas gracias por tu ayuda.

No has adjuntado ningun esquema......Si el servo te da mas grados de movimiento ,pues aprovechalos si te hacen falta,cuando hace tope se nota porque se queda haciendo ruido y vibrando.Lo otro es simplemente conectar entre si los negativos o gnd de los elementos que estas usando.Tal como lo tienes ahora mismo supongo que bastaria con unir con un cable los negativos o gnd de las dos fuentes que usas.Las resistencias supongo que las usas como pulldown para los pulsadores.

Siento mucho lo del esquema, tuve problemas con el tamaño del archivo, pero ahora ya le he bajado la calidad y ya se ha subido.

danielr8:
Siento mucho lo del esquema, tuve problemas con el tamaño del archivo, pero ahora ya le he bajado la calidad y ya se ha subido.

Prueba lo que te comento arriba ,conecta con un cable el negativo de la fuente regulable a un pin gnd del arduino para compartir los negativos y vigila con el voltaje que le das a la fuente porque segun el esquema los botones tambien los alimentas de ahi,no deberias superar los 5v ya que van a las entradas del Arduino .Los botones si quieres los puedes alimentar del pin de 5v del arduino y asi elevar la fuente a 6v que es como dan la maxima velocidad y torque tus servos:
http://www.servodatabase.com/servo/towerpro/mg90
http://www.servodatabase.com/servo/towerpro/mg996r

Muchas gracias por responder tan rápido. Actualmente estoy en examenes y no voy a poder probar en un tiempo, pero en cuánto lo haga te comentaré los resultados, pero una pregunta. ¿Puedes explicarme el por qué?

Está bien probar y ver que funciona, pero me gustaría saber por que el hecho de conectarlo a la tierra del arduino "estabiliza" los servomotores. Pura curiosidad científica, nada más.

no se la explicacion cientifica ,hay gente mas puesta por aqui que te lo explicara,pero supongo que es un tema de referencias ,por ejemplo ,los botones los conectas de la fuente a las entradas de arduino ,pero solo has conectado el positivo, y no tienes una referencia para saber respecto a que tienes esos 5v si no compartes tambien el negativo de donde vienen esos 5v.con los servos me imagino que algo parecido ,dan problemas si la señal y la alimentacion provienen de fuentes diferentes.

Ok, muchas gracias de todas maneras. Te tendré al tanto.

Básicamente es porque al unir las tierras haces que todo el circuito funcione eléctricamente a una misma referencia, por lo tanto todos los voltajes van a estar referenciados hacia un punto de tierra común. Esto finalmente estabiliza los circuitos eléctricos... Si las tierras no se conectan siempre existe la posibilidad que los 5v que entrega un circuito sean vistos como 4v (a modo de ejemplo) en el otro y por lo tanto se obtengan resultados no esperados. En estos casos la tierra es independiente en cada circuito por lo tanto cada uno mide en base de su propia referencia...

Eso en palabras simples ...

Bueno, tras bastante tiempo ocupado hoy he tenido ocasión de probar y ha funcionado a la perfección poner las tierras en común. Gracias a vosotros la parte electrónica e informática del brazo ya están acabadas,ya solo falta acoplarle la pinza al brazo y hacer un par de pruebas.

Muchas gracias, os tendré al tanto y os pasaré alguna foto.

No te olvides de editar el titulo del post para añadir al final SOLUCIONADO

Básicamente es porque al unir las tierras haces que todo el circuito funcione eléctricamente a una misma referencia, por lo tanto todos los voltajes van a estar referenciados hacia un punto de tierra común. Esto finalmente estabiliza los circuitos eléctricos... Si las tierras no se conectan siempre existe la posibilidad que los 5v que entrega un circuito sean vistos como 4v (a modo de ejemplo) en el otro y por lo tanto se obtengan resultados no esperados. En estos casos la tierra es independiente en cada circuito por lo tanto cada uno mide en base de su propia referencia...

Creo que esta es tu duda Pues es muy simple. imagina varios circuitos con pilas Tienes una pila/batería que alimenta una lámpara. Otra en un circuito 2 alimenta un motor. Un tercero alimenta un pulsador en serie con una Resistencia. Si vienes con un tester/multimetro/polímetro (lo escribo asi para que alguna acepción sea la que entiendas en tu país), y lees mides sobre la lámpara leeras supongamos 6V si asi la alimenté. Ahora dejo una punta la negativa en ese circuito y llevo la roja (positiva al positivo del segundo circuito y dime que lees... pues cualquier cosa, porque es una tensión NO REFERENCIADA al primer circuito, y en cuanto unes el negativo del primero con el negativo del segundo, leeras que la pila del segundo supongamos es de 9V y en tu polimetro leerás 9V.

Esa es la explicación y no es científica. Es Electricidad básica.

Por cierto el tercer circuito dejalo solo..jaja

Muchas gracias por la explicación Surbyte, ahora me ha quedado todo más claro. Y respecto a lo de SOLUCIONADO, preferiría no hacerlo aún si es posible, por que el proyecto aún no ha sido acabado y puede que vuelva a necesitar ayuda.

Saludos