Proyecto de robot con guante

Hola muy buenas a todos, os comento, estoy finalizando un grado superior de electrónica y tengo que presentar ya mismo el proyecto final.
Opte por realizar uno de fuente abierta que vi en Internet que era un robot de 2 ruedas capaz de mantenerse de pie por si solo, ademas de poder controlarlo desde el móvil por la app pero finalmente le realice algunos cambios ya que de programación ando muy verde y no lo conseguí.

Finalmente mi proyecto se basaba en el mismo robot pero con unos soportes en los lados para que no se pueda caer y le fabrique un guante con un sensor MPU6050, un arduino nano y un pulsador en el dedo, con el objetivo de que la persona que quiera controlar el robot se coloque el guante y a través del movimiento que realice con la mano el robot avance, gire o retroceda, y al darle al pulsador del dedo, el robot que tiene una pequeña hacha con un servomotor de un pequeño “hachazo” jajaja.

Todo eso lo he conseguido y tengo el robot funcionando aunque si coloco la programación seguro que mas de uno se echara las manos a la cabeza, ademas de que no la tengo terminada del todo :roll_eyes: ahora mi único problema es que, por ejemplo yo muevo la mano hacia delante o el lado que quiera mover el robot y si dejo la mano en esa posición esta continuamente enviándole la orden y el robot va a tirones. En cambio si inclino la mano hacia delante y nuevamente la pongo recta el robot se queda avanzando sin problema hasta que le de una nueva orden.

Me gustaría poder solucionar el tema de que vaya a tirones ya que es como que se le envía la orden todo el rato y va dando tirones, y si acciono el hacha con el pulsador pasa lo mismo, se queda pegando hachazos todo el rato como pillado hasta que le de una nueva orden.

Por cierto tengo que mencionar que el guante con el robot están conectados mediante bluetooth, uno como maestro y otro como esclavo.

A continuación dejo el código del robot y del guante:

Robot:

/*
Al configurar los motores, el primer numero indicara el numero de pasos y con FORWARD indicamos la direccion hacia adelante y BACKWARD hacia atras.
Los metodos de exitacion de bobinas pueden ser:

(Single = solo se excita una bobina, tiene un par motor bajo pero consume menos.)
(Double = Excitan 2 bobinas y se tiene par motor maximo pero doble de consumo.)
(Interleave = Se excitan pares de bobinas, lo que permite doble resolucion, con un par motor y un consumo intermedios, pero al tener doble de posiciones la velocidad es la mitad.
(Microstepping: En ligar de alimentar las bobinas con todo o nada, usamos tensiones PWM con una ciertas relaciones entre la alimentación de las dos bobinas, con lo que la transición entre pasos es más suave.
*/


#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
#include <Servo.h> 
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1); // Configuracion del motor paso a paso 1, con 200 pasos y selecionando el puerto 1 (M1 y M2)
Adafruit_StepperMotor *motor2 = AFMS.getStepper(200, 2); // Configuracion del motor paso a paso 2, con 200 pasos y selecionando el puerto 2 (M3 y M4)
Servo servoMotor;
char inforecibida; 


void controlmotores() // podria hacer falta una funcion de interrupcion, que cuando este inclinandose demasiado corte la aceleracion
   {
     // Si se envia algun dato, se leera.
    if (Serial.available() > 0)
    {
      inforecibida = Serial.read();
      delay(20);
    }
    
    // Si se recibe un "A" desde el bluetooth, los motores avanzaran un paso.
    if (inforecibida == 'A')
    {
      motor1->step(1, BACKWARD, DOUBLE); // Se indica el numero de pasos a avanzar, la direccion y el metodo de excitacion de bobinas 
      motor2->step(1, FORWARD, DOUBLE);
    }

    // Si se recibe un "B" desde el bluetooth, los motores retrocederan un paso.
    
    if (inforecibida == 'B')
    {
      motor1->step(1, FORWARD, DOUBLE); 
      motor2->step(1, BACKWARD, DOUBLE);  
    }

    // Si se recibe un "C" desde el bluetooth, el robot girara a la derecha.
    
    if (inforecibida == 'C')
    {
      motor1->step(1, FORWARD, DOUBLE); // motor1 da un paso hacia DELANTE
      motor2->step(1, FORWARD, DOUBLE);  // motor2 da un paso hacia ATRAS
    }

    // Si se recibe un "D" desde el bluetooth, el robot girara a la izquierda.
    
    if (inforecibida == 'D')
    {
      motor1->step(1, BACKWARD, DOUBLE);  // motor1 da un paso hacia ATRAS 
      motor2->step(1, BACKWARD, DOUBLE);   // motor2 da un paso hacia DELANTE
    }

    // Si se recibe un "E" desde el bluetooth, el robot accionara el servomotor.
    if (inforecibida == 'E')
    {
      servoMotor.write(175); // Se le ordena la posicion de 175º al servomotor
      delay(300);
      servoMotor.write(75);  // El servo motor regresa a la posicion de origen.

    }
    
   }

   

void setup()

   { 
     Serial.begin(9600);
     Serial.println("En espera de ordenes!");
     AFMS.begin(); // Inicia los motores
     servoMotor.attach(10);  // Seleccionar puerto para el servomotor
     servoMotor.write(75); // Se le asigna la posicion de 75º al servomotor al iniciar el robot
     motor1->setSpeed(300); // rpm del motor 1
     motor2->setSpeed(300); // rpm del motor 2
   }


void loop()
   
   {
    
    controlmotores(); // Se carga la funcion encargada del control de los motores por bluetooth segun la informacion recibida avanzara, retrocedera o girara a un lado o otro
   

   }

Guante:

#include <MPU6050_tockn.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#define DedoIndice 7
int estadoindice;

SoftwareSerial Bluetooth(4,3); // RX, TX

MPU6050 mpu6050(Wire);

void setup() {
  pinMode(DedoIndice, INPUT);
  Bluetooth.begin(9600);
  Serial.begin(9600);
  Wire.begin();
  mpu6050.begin();
}

void lectura()
{
  mpu6050.update();
  delay(10);
  
}
void loop() {
    estadoindice = digitalRead(DedoIndice);
    lectura();
    Serial.print("accX : ");Serial.print(mpu6050.getAccX());
    Serial.print("\taccY : ");Serial.print(mpu6050.getAccY());
    Serial.print("\taccZ : ");Serial.println(mpu6050.getAccZ());

  if (estadoindice == 0) 
  {
    Bluetooth.write('E'); // Accionar el hacha
    Serial.print("Hachazo");
    delay(300);
  }

   if (mpu6050.getAccX() >= 0.70){  
    Bluetooth.write('D');    
    Serial.print("Izquierda ");
  }
  
  else if(mpu6050.getAccX() <= -0.60){
    Bluetooth.write('C');    
    Serial.print("Derecha");
  }
  
  else if(mpu6050.getAccY() >= 0.60){  
    Bluetooth.write('B'); 
    Serial.print("Atras ");
    
  }
  else if(mpu6050.getAccY() <= -0.60){
    Bluetooth.write('A'); 
    Serial.print("Adelante ");
  }
  
  else
  {
   
  }
  

  
  
}

Espero haberme explicado bien y que me podáis ayudar, muchas gracias.

Vaya lo que has hecho y no te has dadocuenta que tu problema de TIRONES como lo llamas se debe al uso de delay()!!!

En el foro (al que recién llegas) el 99% de las veces el responsable de todo lo que se comporta como lo que tu describes es el uso de delay().
Debes reemplazarlo por millis() y máquinas de estados.
Ve a documentación => indice de temas tutoriales y lee lo relacionado con millis() y máquina de estados. Eso te dara la base para modficar tu código.

Al margen cuando publiques algo no lo hagas con lo que a ti te parece que tiene responsabilidad en el problema. Siempre publica todo porque nosotros no conocemos todo el contexto del proyecto. Y debemos entenderlo.

El reemplazo de delay por millis() no es simple pero para alguien que ha hecho lo que describes no será muy complicado.
De esta forma tu código será fluido y no tendra esos tirones.

Cuando publiques el código completo del robot y guante te daré otra visión.

Hola primeramente muchas gracias por la ayuda :). Me ha ayudado otro compañero también y he reemplazado el delay por millis() y ya funciona perfectamente sin ningún tirón, pero tengo alguna duda.

La primera es sobre si habría alguna manera de hacer que el robot se quede quieto al no estar recibiendo ninguna orden de movimiento.

Y la segunda y ultima duda es sobre el código del guante, el tema de poner else if varias veces cuando se lo mostré a mi profesor recuerdo que no le hizo mucha gracia, se podría poner con un switch también o alguna otra forma que quede mas “bonita”?

A continuación te dejo el código nuevo del robot:

/*
Al configurar los motores, el primer numero indicara el numero de pasos y con FORWARD indicamos la direccion hacia adelante y BACKWARD hacia atras.
Los metodos de exitacion de bobinas pueden ser:

(Single = solo se excita una bobina, tiene un par motor bajo pero consume menos.)
(Double = Excitan 2 bobinas y se tiene par motor maximo pero doble de consumo.)
(Interleave = Se excitan pares de bobinas, lo que permite doble resolucion, con un par motor y un consumo intermedios, pero al tener doble de posiciones la velocidad es la mitad.
(Microstepping: En ligar de alimentar las bobinas con todo o nada, usamos tensiones PWM con una ciertas relaciones entre la alimentación de las dos bobinas, con lo que la transición entre pasos es más suave.
*/

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
#include <Servo.h> 
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1); // Configuracion del motor paso a paso 1, con 200 pasos y seleccionando el puerto 1 (M1 y M2)
Adafruit_StepperMotor *motor2 = AFMS.getStepper(200, 2); // Configuracion del motor paso a paso 2, con 200 pasos y seleccionando el puerto 2 (M3 y M4)

Servo servoMotor;
char inforecibida; 
unsigned marcaTiempoLectura = 0;
unsigned marcaTiempoServo = 0;
bool servoActivo = false;

void setup() { 
  Serial.begin(9600);
  Serial.println("En espera de ordenes!");
  AFMS.begin(); // Inicia los motores
  servoMotor.attach(10); // Seleccionar puerto para el servomotor
  servoMotor.write(75); // Se le asigna la posición de 75º al servomotor al iniciar el robot
  motor1->setSpeed(300); // rpm del motor 1
  motor2->setSpeed(300); // rpm del motor 2
}

void loop() {
  int motor1Direc;
  int motor2Direc;
  
  if (millis() > marcaTiempoLectura + 20 && Serial.available() > 0) { 
    inforecibida = Serial.read();
    marcaTiempoLectura = millis();
    
    switch(inforecibida) {
      
    case 'A': // Si se recibe un "A" desde el bluetooth, los motores avanzaran.
      motor1Direc = BACKWARD; 
      motor2Direc = FORWARD;
      break;
      
    case 'B': // Si se recibe un "B" desde el bluetooth, los motores retrocederán.
      motor1Direc = FORWARD;
      motor2Direc = BACKWARD; 
      break;
      
    case 'C': // Si se recibe un "C" desde el bluetooth, el robot girara a la derecha.
      motor1Direc = FORWARD; // motor1 da un paso hacia DELANTE
      motor2Direc = FORWARD; // motor2 da un paso hacia ATRÁS
      break; 
      
    case 'D': // Si se recibe un "D" desde el bluetooth, el robot girara a la izquierda.
      motor1Direc = BACKWARD; // motor1 da un paso hacia ATRÁS 
      motor2Direc = BACKWARD; // motor2 da un paso hacia DELANTE 
      break;
      
    case 'E': // Si se recibe un "E" desde el bluetooth, el robot accionara el servomotor.
      if(!servoActivo) {
          servoActivo = true;
          marcaTiempoServo = millis();
      }
        break;
        
    default:
      motor1Direc = RELEASE;
      motor2Direc = RELEASE;
      break;
    }
  }
  
  motor1->step(1, motor1Direc, DOUBLE); // Se indica el numero de pasos a avanzar, la direccion y el metodo de excitación de bobinas 
  motor2->step(1, motor2Direc, DOUBLE);
  
  accionarServo(); 
}

void accionarServo() {
  if(servoActivo) {
    if(millis() > marcaTiempoServo + 300) {
          servoMotor.write(75);
          servoActivo = false;
        }
        else {
          servoMotor.write(175);
        }
  }
}

else if varias veces

No veo la manera de usar switch en el guante reemplazando esto.

Primero para mi esta mal usando el if else if y todo lo que veo y expico porque.

  if (mpu6050.getAccX() >= 0.70){  
    Bluetooth.write('D');    
    Serial.print("Izquierda ");
  }
  else if (mpu6050.getAccX() <= -0.60){
           Bluetooth.write('C');    
           Serial.print("Derecha");
          }

Esta parte del código son condicionales x encima de 0.7 y por debajo de -0.6
Conclusión un if x un lado y otro if por el otro son suficientes de este modo ya que no existe un else… porque que hace si getAccX() vale 0.69 pues nada y que hace si vale -0.59 nada y en todo ese rango NADA entonces?

yo lo usaría asi

  if (mpu6050.getAccX() >= 0.70){  
      Bluetooth.write('D');    
      Serial.print("Izquierda ");
  }
  if (mpu6050.getAccX() <= -0.60){
      Bluetooth.write('C');    
      Serial.print("Derecha");
 }

Y hago lo mismo. para getAccY() pasa lo mismo y el ultimo else esta gratis.

  else
  {

  }