Control de 5 servos con 4 pulsadores por etapas

Hola a todos.

Estoy realizando un proyecto para clase que consiste en una mano robotizada y cada dedo lo actúa un servomotor. La programación simple para que cada servomotor funcione lo tengo correcto.

El problema es que ahora me piden que le incluya 4 pulsadores para hacer como un selector de programa, los pulsadores haciendo como si fueran un código binario me permite hacer hasta 15 programas + el 0 que lo reservo para la posición inicial. Entonces lo que he pensado es hacerlo por etapas como si fuera un PLC, la etapa 0 la inicial y de aquí según la combinación de botones que pulse va a otra etapa y regresa a la 0.

Cuando tengo todo ya conectado, he probado con 5 etapas, del 1 al 4 una por dedo y el 5º dedo con los 4 botones pulsados. Esto me funcionaba bien hasta que vi que el 4º botón aunque no lo pulsara me saltaba a la etapa 4, y cuando miraba por que al desconectar los pines me hacia las acciones de la etapa 1 y 2.

Espero a ver si alguien me puede ayudar, soy bastante novato con arduino y no se por donde me equivoco, o si tienen alguna idea mejor.

Gracias de antemano. :wink:

Dejo el código y el esquema eléctrico de las conexiones.

#include <Servo.h>
//Servos
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;

//Pulsadores
int puls1 = 2;
int puls2 = 4;
int puls3 = 7;
int puls4 = 8;

//Etapas
boolean e_0 = true, e_1 = false, e_2 = false, e_3 = false;
boolean e_4 = false, e_5 = false, e_6 = false, e_7 = false;
boolean e_8 = false, e_9 = false, e_10 = false, e_11 = false;
boolean e_12 = false, e_13 = false, e_14 = false, e_15 = false;

void setup() {
//Servos
  servo1.attach(3);
  servo2.attach(5);
  servo3.attach(6);
  servo4.attach(9);
  servo5.attach(10);
//Pulsadores
  pinMode(puls1, INPUT);
  pinMode(puls2, INPUT);
  pinMode(puls3, INPUT);
  pinMode(puls4, INPUT);
}

void loop() {

  //TRANSICIONES ETAPA 0
  if (e_0 == true && digitalRead(puls4) == LOW && digitalRead(puls3) == LOW && digitalRead(puls2) == LOW && digitalRead(puls1) == HIGH)  {
    e_1 = true; e_0 = false;
  }
  if (e_0 == true && digitalRead(puls4) == LOW && digitalRead(puls3) == LOW && digitalRead(puls2) == HIGH && digitalRead(puls1) == LOW)  {
    e_2 = true; e_0 = false;
  }
  if (e_0 == true && digitalRead(puls4) == LOW && digitalRead(puls3) == HIGH && digitalRead(puls2) == LOW && digitalRead(puls1) == LOW)  {
    e_3 = true; e_0 = false;
  }
  if (e_0 == true && digitalRead(puls4) == HIGH && digitalRead(puls3) == LOW && digitalRead(puls2) == LOW && digitalRead(puls1) == LOW)  {
    e_4 = true; e_0 = false;
  }
  if (e_0 == true && digitalRead(puls4) == HIGH && digitalRead(puls3) == HIGH && digitalRead(puls2) == HIGH && digitalRead(puls1) == HIGH)  {
    e_5 = true; e_0 = false;
  }


  //ACCIONS ETAPAS

  //ETAPA 0 - INICIAL

  if (e_0 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(0);
    delay(1000);
  }

  //ETAPA 1
  if (e_1 == true) {
    servo1.write(100);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_1 = false;
  }

  //ETAPA 2
  if (e_2 == true) {
    servo1.write(0);
    servo2.write(100);
    servo3.write(0);
    servo4.write(0);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_2 = false;
  }

  //ETAPA 3
  if (e_3 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(100);
    servo4.write(0);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_3 = false;
  }

  //ETAPA 4
  if (e_4 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(100);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_4 = false;
  }

  //ETAPA 5
  if (e_5 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_5 = false;
  }

}

Lo primero que veo es que no haces nada con el pulsador si éste tiene rebotes.
una de dos: o miras las transición del pulsador o botón o bien agregas un debounce para confirmar que se ha presionado el mismo.
Yo uso una librería que se llama Switch que evita agregar tanto código para confirmar cada boton.

Luego que confirmes que el boton esta realmente en un estado, entonces si haces tu lógica pero intenta agrupar los 4 bits en un nible o medio byte para trabajar mas cómodo (al menos para mi)

#include <Switch.h>

// los defines asi. solo agrego el tema de los pulsadores

Switch buttonPuls1 = Switch(puls1, INPUT, HIGH); // boton a +5V, 10k pull-down resistor, no internal pull-up resistor, HIGH polarity
Switch buttonPuls2 = Switch(puls2, INPUT, HIGH);
Switch buttonPuls3 = Switch(puls3, INPUT, HIGH);
Switch buttonPuls4 = Switch(puls4, INPUT, HIGH);
byte estado;

// En setup nada

//en el loop
 
void loop() {

 buttonPuls1.poll();  
 buttonPuls2.poll();
 buttonPuls3.poll();
 buttonPuls4.poll();

 estado = buttonPuls4.switched()<<3+buttonPuls3.switched()<<2+buttonPuls2.switched()<<1+buttonPuls1.switched();

luego tus consultas seran en lugar de

if (e_0 == true && digitalRead(puls4) == LOW && digitalRead(puls3) == LOW && digitalRead(puls2) == LOW && digitalRead(puls1) == HIGH)  {
    e_1 = true; e_0 = false;
  }

estado a comparar = 0001 = 0x01 hexa

  if (e_0 == true && estado == 0x01)  {
    e_1 = true; e_0 = false;
  }

tambien armaría un switch case que tal vez ayude a leer mejor el código, falta incorporar e_0 pero como siempre debe estar en 1 entonces

if (e_0) {
   switch(estado) {
     case 0x01: // tarea 1
                      break;
     case 0x02: // tarea 2
                      break;
    ..............
     case 0x0f:  // tarea 15
                      break;
     case 0x00: // lo que corresponda
                      break;
    }
}

Muchas gracias, ahora probaré si me funciona.

Espero lo hayas entendido porque tal vez esté algo entrecruzada la explicación

Basicamente la librería sirve para eliminar los rebotes.

el procedimiento objeto.poll() es el que lee el estado del pulsador.
el procedimiento objeto.switched() te devuelve 1 o 0 de acuerdo si esta o no switcheado o pulsado.

Luego cree un nibble o sea medio byte con el peso a cada pulsador.

Y es mas facil para compararlo dentro de un switch case. y como lo que vi de tu código siempre preguntas por e_0 en 1 simplifacamos asi

if (e_0) {
  switch(estado) {

   // todos los case: break

  }
}

tal vez esta explicación sea reiterativa pero se comprenda mejor x resumida

Si creo que lo he entendido bastante bien y veo que me quedara mucho mas limpio el código. No conocía la librería switch ni los case, he trabajado muy poco con arduino aun jeje.

Tengo una duda.
En el código que yo puse lo que tendría que quitar los pulsadores del void setup, ya que le digo que son inputs arriba.

Gracias por todo, cuando lo tenga hecho lo volveré a poner.

Si. quitalos porque la definición de los objetos como esta

Switch buttonPuls3 = Switch(puls3, INPUT, HIGH);

ya lo hace.

Adapta tu definición del objeto a como tengas cableado el pulsador.

Creo que he hecho todo como me dijiste surbyte pero no me responde al menos ahora no me hace el loco sino que parece que se queda en la etapa 0 y no avanza.

Creo que puede ser que la resistencia que tengo puesta en cada pulsador debe ser demasiado grande es de 820K.

Sino no se por donde puede venir el problema.

Dejo el código que tengo de momento

#include <Servo.h>

Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;

int puls1 = 2;
int puls2 = 4;
int puls3 = 7;
int puls4 = 8;

#include <Switch.h>
Switch buttonPuls1 = Switch(puls1, INPUT, HIGH); 
Switch buttonPuls2 = Switch(puls2, INPUT, HIGH);
Switch buttonPuls3 = Switch(puls3, INPUT, HIGH);
Switch buttonPuls4 = Switch(puls4, INPUT, HIGH);

byte estado;

boolean e_0 = true, e_1 = false, e_2 = false, e_3 = false;
boolean e_4 = false, e_5 = false, e_6 = false, e_7 = false;
boolean e_8 = false, e_9 = false, e_10 = false, e_11 = false;
boolean e_12 = false, e_13 = false, e_14 = false, e_15 = false;



void setup() {
  servo1.attach(3);
  servo2.attach(5);
  servo3.attach(6);
  servo4.attach(9);
  servo5.attach(10);
}

void loop() {
   buttonPuls1.poll();  
   buttonPuls2.poll();
   buttonPuls3.poll();
   buttonPuls4.poll();
   
   estado = buttonPuls4.switched()<<3+buttonPuls3.switched()<<2+buttonPuls2.switched()<<1+buttonPuls1.switched();

  //TRANSICIONES ETAPA 0

  //ETAPA 0
   if (e_0) {
   switch(estado) {
    
     case 0x01: e_1 = true; e_0 = false;
                      break;
     case 0x02: e_2 = true; e_0 = false;
                      break;
     case 0x03: e_3 = true; e_0 = false;
                      break;
     case 0x04: e_4 = true; e_0 = false;
                      break;
     case 0x05: e_5 = true; e_0 = false;
                      break;
     case 0x06: e_6 = true; e_0 = false;
                      break;
     case 0x07: e_7 = true; e_0 = false;
                      break;
     case 0x08: e_8 = true; e_0 = false;
                      break;
     case 0x09: e_9 = true; e_0 = false;
                      break;
     case 0x0a: e_10 = true; e_0 = false;
                      break;
     case 0x0b: e_11 = true; e_0 = false;
                      break;
     case 0x0c: e_12 = true; e_0 = false;
                      break;
     case 0x0d: e_13 = true; e_0 = false;
                      break;
     case 0x0e: e_14 = true; e_0 = false;
                      break;
     case 0x0f: e_15 = true; e_0 = false;
                      break;
     case 0x00: //No quiero que haga nada
                      break;
    }
  }
  
  
  //ACCIONES ETAPAS
  //ETAPA 0
  if (e_0 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(0);
    delay(1000);
  }

  //ETAPA 1
  if (e_1 == true) {
    servo1.write(100);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_1 = false;
  }

  //ETAPA 2
  if (e_2 == true) {
    servo1.write(0);
    servo2.write(100);
    servo3.write(0);
    servo4.write(0);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_2 = false;
  }

  //ETAPA 3
  if (e_3 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(100);
    servo4.write(0);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_3 = false;
  }

  //ETAPA 4
  if (e_4 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(100);
    servo5.write(0);
    delay(2000);
    e_0 = true;
    e_4 = false;
  }

  //ETAPA 5
  if (e_5 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_5 = false;
  }
  
    //ETAPA 6
  if (e_6 == true) {
    servo1.write(100);
    servo2.write(0);
    servo3.write(0);
    servo4.write(0);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_6 = false;
  }
  
    //ETAPA 7
  if (e_7 == true) {
    servo1.write(0);
    servo2.write(100);
    servo3.write(0);
    servo4.write(0);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_7 = false;
  }
  
    //ETAPA 8
  if (e_8 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(100);
    servo4.write(0);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_8 = false;
  }
  
    //ETAPA 9
  if (e_9 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(0);
    servo4.write(100);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_9 = false;
  }
  
    //ETAPA 10
  if (e_10 == true) {
    servo1.write(100);
    servo2.write(0);
    servo3.write(0);
    servo4.write(100);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_10 = false;
  }
  
    //ETAPA 11
  if (e_11 == true) {
    servo1.write(0);
    servo2.write(100);
    servo3.write(0);
    servo4.write(100);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_11 = false;
  }
  
    //ETAPA 12
  if (e_12 == true) {
    servo1.write(0);
    servo2.write(0);
    servo3.write(100);
    servo4.write(100);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_12 = false;
  }
  
    //ETAPA 13
  if (e_13 == true) {
    servo1.write(100);
    servo2.write(0);
    servo3.write(100);
    servo4.write(100);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_13 = false;
  }
  
    //ETAPA 14
  if (e_14 == true) {
    servo1.write(0);
    servo2.write(100);
    servo3.write(100);
    servo4.write(100);
    servo5.write(100);
    delay(2000);
    e_0 = true;
    e_14 = false;
  }
  
    //ETAPA 15
  if (e_15 == true) {
    servo1.write(50);
    servo2.write(50);
    servo3.write(50);
    servo4.write(50);
    servo5.write(50);
    delay(2000);
    e_0 = true;
    e_15 = false;
  }

}

Jajaja las resistencias que tienes deben ser de 10 o 20k máximo.
Dime como las tienes conectadas? son pull-up o down?

Ya he cambiado las resistencias de 10k aunque no me da tiempo a probar ahora mismo y tengo que cambiar un cable que he detectado un corte interno en el 4º pulsador, son pull-down.

Con la etapa 0 si en el case lo pongo:

switch(estado) {
    
     case 0x00: e_0 = true;
                      break;

Esto no me provocara un bucle y que cuando no pulse pueda no hacer la transición a otra etapa? o sino como había pensado en dejar ese case sin poner nada o borrarlo.

Bien, esta es mi versión, pero debes verificar que pasa con el estado e_0 cuando vale 0 y ademas verifica que pasa si no presionas nada.
Tengo dudas de que este bien.

Un cambio que hice, saque los delays que bloquean todo comportamiento del sistema porque todos agregan 2 segundos que no se lee nada.
Ahora debemos asegurarnos de que se sigue en el estado en el que estamos.
Si no es asi se como arreglarlo

#include <Servo.h>

#include "Arduino.h"
#include "Switch.h"



Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;

const byte puls1 = 2;
const byte puls2 = 4;
const byte puls3 = 7;
const byte puls4 = 8;

Switch buttonGND = Switch(3); 
Switch buttonPuls1 = Switch(puls1, INPUT, HIGH);
Switch buttonPuls2 = Switch(puls2, INPUT, HIGH);
Switch buttonPuls3 = Switch(puls3, INPUT, HIGH);
Switch buttonPuls4 = Switch(puls4, INPUT, HIGH);

byte estado;

//enum (E0 = 0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15);

bool e_0 = true;
unsigned long start = 0;


void setup() {
  servo1.attach(3);
  servo2.attach(5);
  servo3.attach(6);
  servo4.attach(9);
  servo5.attach(10);
  start = millis();
}

void loop() {
   buttonPuls1.poll();  
   buttonPuls2.poll();
   buttonPuls3.poll();
   buttonPuls4.poll();
   
   estado = buttonPuls4.switched()<<3+buttonPuls3.switched()<<2+buttonPuls2.switched()<<1+buttonPuls1.switched();

  //TRANSICIONES ETAPA 0

  //ETAPA 0
   if (e_0) {
   switch(estado) {
    
     case 0x01: //ETAPA 1
     			ControlServo(100, 0, 0, 0, 0);
                break;

     case 0x02:   //ETAPA 2
     			ControlServo(0, 100, 0, 0, 0);
                break;

     case 0x03: //ETAPA 3
				ControlServo(0, 0, 100, 0, 0);
                break;

     case 0x04: //ETAPA 4
				ControlServo(0, 0, 0, 100, 0);
                break;

     case 0x05: //ETAPA 5
				ControlServo(0, 0, 0, 0, 100);
                break;

     case 0x06: //ETAPA 6
				ControlServo(100, 0, 0, 0, 100);
                break;

     case 0x07: //ETAPA 7
				ControlServo(0, 100, 0, 0, 100);
                break;
     
     case 0x08: //ETAPA 8
				ControlServo(0, 0, 100, 0, 100);     
                break;
     
     case 0x09: //ETAPA 9
				ControlServo(0, 0, 0, 100, 100);     
                break;
     
     case 0x0a: //ETAPA 10
				ControlServo(100, 0, 0, 100, 100);     
                break;
     
     case 0x0b: //ETAPA 11
				ControlServo(0, 100, 0, 100, 100);     
                break;
     
     case 0x0c: //ETAPA 12
				ControlServo(0, 0, 100, 100, 100);     
                break;
     
     case 0x0d: //ETAPA 13
				ControlServo(100, 0, 100, 100, 100);     
                break;
     
     case 0x0e: //ETAPA 14
				ControlServo(0, 100, 100, 100, 100);     
                break;
     
     case 0x0f: //ETAPA 15
				ControlServo(50, 50, 50, 50, 50);     
                break;
     
     case 0x00: //ETAPA 00
     default:
				ControlServo(0, 0, 0, 0, 0);     
                break;
    }
    if (millis()-start > 2000) {
    	start = millis();
    	e_0 = true;
    } else 
    	e_0 = false;
  }
}  
  
void  ControlServo(byte v1, byte v2, byte v3, byte v4, byte v5)
{
	servo1.write(v1);
	servo2.write(v2);
	servo3.write(v3);
	servo4.write(v4);
	servo5.write(v5);
}

sigue sin actuar al pulsar cualquier botón, se queda como si fuera la etapa 0 con todos los servos a 0, si modifico las posiciones de esta etapa se mueven a estas posiciones, supongo que eso significa que de la etapa 0 no consigue salir. Si pulsas o no hace lo mismo los servos en la posición de etapa 0.

No se si hay otra forma para poder verificar mejor si pasa de etapa o si recibe señal de los botones,etc...

El tiempo de entrega del proyecto se me agota :confused: en fin acabo de probar la programación que puse al inicio con pequeñas variaciones y algo mas "sucio y rustico" pero me ha funcionado para que haga lo que quiero hacer. Usare esta programación para el proyecto.

De todas formas me gustaría seguir investigando con la programación que me estas mostrando, por aprender mas y porque en día de la presentación si ocurriese algún problema con el primer código, podría demostrar el segundo y cubrirme las espaldas.

Mas tarde pongo el código que presentaré. Y si puedo alguna foto o vídeo.

Hola estoy en el tema de tu proyecto sabes que queria saber la fuente de Alimentacion que utilizas :frowning:

No revivas hilos de mas de 4 meses y menos algo del 2015
Crea uno nuevo y lee las normas del foro