necesito ayuda para evitar zig zag en un robot con brujula

hola, pues hace un tiempo que voy haciendo cosillas con robots y ahora mismo estoy intentando que un robot ande recto con la ayuda de una brújula , el tema es que recto se puede decir que si que va pero haciendo zig zags bastante fuertes .

la idea seria reducir o eliminar el zig zag que se debe a que cuando el robot gira solo con una rueda y cuando esta a cero de desviacion esta se desactiva a la vez que se activa la otra , provocando una sacudida y la activación de la otra rueda.

el robot tiene 2 motores DC con un puente L298N H bridge y una brujula gy-271 , como "cerebro" cuenta con un arduino mega.

el error se muestra como negativo o positivo , he pensado que esto podría servir para modificar la velocidad de los motores y reducir las sacudidas pero no se como.

y ya esta , no se que mas datos poner, alguna idea?

gracias.

grados = 89  destino = 90 error =  1

 grados = 90  destino = 90 error =  0
 grados = 90  destino = 90 error =  0

 grados = 90  destino = 90 error =  0
 grados = 90  destino = 90 error =  0

 grados = 91  destino = 90 error =  -1

 grados = 91  destino = 90 error =  -1

 grados = 91  destino = 90 error =  -1

 grados = 91  destino = 90 error =  -1

 grados = 91  destino = 90 error =  -1

 grados = 91  destino = 90 error =  -1

 grados = 92  destino = 90 error =  -2

lo que se me pasa por la cabeza es lo siguiente;

   if(error>=0)
{
  error = positivo;
  }
  
velocidad = 150;

 total = velocidad + positvo;
  
  analogWrite(ENA,total);
  digitalWrite(IN2,HIGH);

algo así podría funcionar??

Porque no comienzas poniendo todo el codigo como para ver a ciencia cierta que haces y si le envias comandos bruscos a los motores en lugar de una versión digamos lineal en función de cuan corrido este de la linea deseada.

Yo haria eso, estableceria una variación proporcional al error positivo o negativo para volver a la ruta deseada. un enfoque simple creo.

esto es lo que hay ahora, una chapuza para ver que tal va y a partir de ahi ir puliendo la cosa.

soloiz y solod es que mueve solo la derecha o la izquierda , por que como le haga girar usando las 2 parece un lobo intentando matar un conejo , hasta se le cae el ultrasonidos del servo.

void ir() 
  {
  if(error <= 10 or error == 0)
  {
  soloiz();
  }

  else if(error >= -10 or error == 0)
  {
  solod();
  }

entonces con lo de mi segundo post iria por buen camino??

vas bien pero no se que lel pides a soloiz() y solod() que haga
para ti da lo mismo que este a -2 que a -9 para ir a la derecha y idem con +2 o +9 para ir a izq.
Lo que te pido es que con -2 lo haga a una velocidad y con -9 a mayor velocidad

Traducido, la correcciòn de la ruta es suave si estoy en el entorno del error y mas brusca si estoy mas lejos

Peroooo a medida que voy de -9 a 0 que ocurre que sucesivas lecturas hacen que baje la velocidad de aproximaciòn.

Entonces el camino sera mas suave.

Ahora lo estoy pensando en el aire, no he hecho nada ni parecido asi que hay que ver como se comporte el robot.

soloiz lo que hace es mover solo la rueda izquierda , esta se mueve a un pulso pwm de 150 mas el valor del error , el error va de 0 a 180 , siendo 180 el máximo y 0 el mínimo.

180+150= 330 y el pulso maximo es 255, supongo que hay interesa hacer un if total >= 255 total = 255;

es la unica manera que se me ocurre para un movimiento suave, no se si sera la mejor.

bueno pues ahora va suave sin sacudidas ni derrapes extraños, aun no es perfecto pero poco a poco.
edito, si veis alguna manera de mejorarlo o simplificarlo os estaré agradecido.

grados = headingDegrees;
   destino = 0;
   error = destino - grados;

  if ( error > 180 ) 
  {
  error -= 360;
  } 
  else if ( error < -180 )
  {
  error += 360;
  }
   
   Serial.println("");
   Serial.print(" grados = ");
   Serial.print(grados);
   Serial.print("  destino = ");
   Serial.print(destino);
   Serial.print(" error =  ");
   Serial.print(error);
   
   ir();

}
  
   void ir() 
   {
    if(error>=1)                   
{
  izquierda = velocidad - error*-1;
  derecha = velocidad + error*-1;
  analogWrite(ENA,derecha);
  digitalWrite(IN2,HIGH);
  analogWrite(ENB,izquierda);
  digitalWrite(IN4,HIGH);
  Serial.print(" izquierda = ");
  Serial.print(izquierda);
  Serial.print(" derecha = ");
  Serial.print(derecha);
}
  if(izquierda >=255)
 {
   izquierda = 255;
  
}
   
 if(error <= -0)
{
  derecha = velocidad + error*-1;
  izquierda = velocidad - error*-1;
  
 // negativo = velocidad + error;
 // derecha = negativo*-1;
  analogWrite(ENA,derecha);
  digitalWrite(IN2,HIGH);
  analogWrite(ENB,izquierda);
  digitalWrite(IN4,HIGH);
  Serial.print(" izquierda = ");
  Serial.print(izquierda);
  Serial.print(" derecha = ");
  Serial.print(derecha);
}
if(derecha >= 255)
{
 derecha = 255;
 } 
   }

bueno, salió la cosa pero con error incluido, si pasabas de 105 grados el robot andaba recto , así que para corregir ahora para una rueda, derecha o izquierda según el lado del que sea la desviación

grados = headingDegrees;
   destino = 0;
   error = destino - grados;

  if ( error > 180 ) 
  {
  error -= 360;
  } 
  else if ( error < -180 )
  {
  error += 360;
  }
   Serial.println("");
   Serial.print(" grados = ");
   Serial.print(grados);
   Serial.print("  destino = ");
   Serial.print(destino);
   Serial.print(" error =  ");
   Serial.print(error);
   
   ir();

}
  
   void ir() 
   {
    if(error > 1 && error <= 105)
{
  izquierda = velocidad - error*-1;
  derecha = velocidad + error*-1;
  if(izquierda >=255)
 {
  izquierda = 255;
 }
  analogWrite(ENA,derecha);
  digitalWrite(IN2,HIGH);
  analogWrite(ENB,izquierda);
  digitalWrite(IN4,HIGH);
  Serial.print(" izquierda = ");
  Serial.print(izquierda);
  Serial.print(" derecha = ");
  Serial.print(derecha);
} 
  else if( error > 105 && error < 180)
  {
  
  derecha = 0;
  
  }
    
   
 if(error <= -0 && error >= -105)
{
  
  derecha = velocidad + error*-1;
  izquierda = velocidad - error*-1;
  if(derecha >= 255)
 {
 derecha = 255;
 } 
  analogWrite(ENA,derecha);
  digitalWrite(IN2,HIGH);
  analogWrite(ENB,izquierda);
  digitalWrite(IN4,HIGH);
  Serial.print(" izquierda = ");
  Serial.print(izquierda);
  Serial.print(" derecha = ");
  Serial.print(derecha);
}

   
   else if(error > 180 && error < 105)
   {
     izquierda = 0;
   }
   }

Lo arreglas agregando un tiempo de estabilización, en la lectura de la brujula y la correccion de la ruta. Recuerda que va a 16mhz, siempre un delay ayuda, empieza con 1 segundo y lo vas bajando hasta que quede lo mas rapido y mas estable.

Tengo una buena idea pero me va a llevar tiempo. Si me esperas 1 dia lo hago.

Bueno a ver que te parece esta rutina
Esto es lo que tenía en la mente y no podía plasmarlo.

void DireccionRueda (int compValue) {
  int velocidad = 255;
  int diff = compValue - destino;    // diff es tu error
  if (diff > 180) {
    diff = -360 + diff;
  }
  else if (diff < -180 ) {
    diff = 360 + diff;
  }
  diff = map(diff, -180, 180, -speedy, speedy);
  if (diff > 0) {
    speedLeft = velocidad - diff;
    speedRight = velocidad;
  }
  else {
    speedLeft = velocidad;
    speedRight = velocidad + diff;
  }
  //Serial.println(speedLeft);
  //Serial.println(speedRight);
}

Sigo pensando en como integrar mas cosas.

si usas la librería #include <Adafruit_Sensor.h>

El compas podemos leerlo de este modo (sacado de la web Adafruit)

float CompassSensor() {
  sensors_event_t event;
  mag.getEvent(&event);

// Se calcula la cabezera con el nivel del magnetómetro, luego se corrije el signo según los ejes.

  float heading = atan2(event.magnetic.y, event.magnetic.x);
// Una vez que tienes la cabecera, se debe agregar el "Angulo de Declinación" que es el error del campo magnético terrestre según su locación.
// Encontrá el tuyo acá: http://www.magnetic-declination.com/
  
  float declinationAngle = 0.2045;
  heading += declinationAngle;
  if (heading < 0) {
    heading += 2 * PI;  
  }
  if (heading > 2 * PI) {
    heading -= 2 * PI;
  }
  float headingDegrees = (heading * 180) / M_PI;
  //Serial.println(headingDegrees);
  return headingDegrees;
}

hola surbyte , lo mirare a ver que tal , la verdad es que pensaba que el hilo estaba muerto, la verdad es que esa librería si funciona con mi brújula puede simplificar mucho las cosas .

El tema es que respondo muchas consultas y me esta consumiendo mucho tiempo de MI CPU, jajaja.

Pero me mantiene hiper estimulado ver cosas tan diversas y me da gusto como mi cerebro empieza a encontrar mejores maneras de resolverlas.