Bugg en arduino

Hola gente del foro.

Estoy construyendo un robot basado en arduino el cual tiene que leer un grupo de sensores y actuar ante eso sobre la velocidad de motores.

El problema esta en que a un tiempo (variable) de estar ejecutando correctamente el programa este envia el maximo valor de pwm (255 en este caso) a una de las ruedas y la otra la deja en 0, generando asi que gire hacia una direccion a toda velocidad sin tener registro de los valores de los sensores ni nada, la unica respuesta es la tension maxima a la entrada de PWM.

La placa arduino se conecta bien a la pc y puedo subir programas sin problemas. A que se le puede atribuir este bugg repentino en el funcionamiento?

Gracias! ...

Coloca el código por favor usando tags </>

surbyte, Adjunto el codigo, pero antes querria decir algo que estuve probando...

Subi el ejemplo de "blink" para ver si el bugg era producido por el hardware del arduino y este no dio este resultado siendo alimentado tanto del Vin como por USB.

Mi conclusion es que puede llegar a ser un problema de la parte de potencia (motores) porque al estar en giro constante sucede esto, pero, la placa paso muchas pruebas y funciona como debe.

Al crear un programa especificamente para los motores estos generan el mismo problema:

Giran en un sentido y lo cambian correctamente pero al repetir el proceso unas dos veces aceleran a su maxima velocidad haciendo que haya que reiniciar o desconectar la alimentacion.

El codigo:

#include <QTRSensors.h>

#define STANDBY          3  // pin STANDBY del Motor Driver
#define MOTORLEFT_DIR_A  5  // pin 1 de dirección del Motor Izquierdo
#define MOTORLEFT_DIR_B  4  // pin 2 de dirección del Motor Izquierdo
#define MOTORLEFT_PWM    6  // pin PWM del Motor Izquierdo
#define MOTORRIGHT_DIR_A  11  // pin 1 de dirección del Motor Derecho
#define MOTORRIGHT_DIR_B  10  // pin 2 de dirección del Motor Derecho
#define MOTORRIGHT_PWM    9  // pin PWM del Motor Derecho

#define NUM_SENSORS             8    // número de sensores usados


// cant. lecturas analógicas que serán leídas por sensor

#define NUM_SAMPLES_PER_SENSOR  4    
#define EMITTER_PIN             12   // pin emisor del QTR

#define ENCODERPIN 12               // pin del encoder
#define LEDPIN     13                // número del pin de test
#define BUTTONPIN  2                 // boton externo

// función para pulsar el botón y esperar que deje de pulsarlo
#define esperarBoton() while(!digitalRead(BUTTONPIN)); while(digitalRead(BUTTONPIN))

// estructura para los sensores
QTRSensorsAnalog qtra((unsigned char[]) 
 { A7, A6, A5, A4, A3, A2, A1, A0 }
, NUM_SENSORS, NUM_SAMPLES_PER_SENSOR, EMITTER_PIN);

// arreglo para almacenamiento de valores por sensor
unsigned int sensorValues[NUM_SENSORS];

// función Velocidad Motor Izquierdo
void setMotorLeft(int value)
{
 if ( value >= 0 )
 {
   // si valor positivo vamos hacia adelante
   digitalWrite(MOTORRIGHT_DIR_A,HIGH);
   digitalWrite(MOTORRIGHT_DIR_B,LOW);
 }
 else
 {
   // si valor negativo vamos hacia atras
   digitalWrite(MOTORRIGHT_DIR_A,LOW);
   digitalWrite(MOTORRIGHT_DIR_B,HIGH);
   value *= -1;
 }

 // Setea Velocidad
 analogWrite(MOTORRIGHT_PWM,value);
}

// función Velocidad Motor Derecho
void setMotorRight(int value)
{  
 if ( value >= 0 )
 {
   // si valor positivo vamos hacia adelante
   digitalWrite(MOTORLEFT_DIR_A,HIGH);
   digitalWrite(MOTORLEFT_DIR_B,LOW);
 }
 else
 {
   // si valor negativo vamos hacia atras
   digitalWrite(MOTORLEFT_DIR_A,LOW);
   digitalWrite(MOTORLEFT_DIR_B,HIGH);
   value *= -1;
 }    

 // Setea Velocidad
 analogWrite(MOTORLEFT_PWM,value);
}

// función Velocidad Motores
void setMotors(int left, int right)
{
 digitalWrite(STANDBY,HIGH);
 setMotorLeft(left);
 setMotorRight(right);
}

// función Freno en Motores
void setBrake(boolean left, boolean right, int value)
{
 // pin STAND BY
 digitalWrite(STANDBY,HIGH);

 if ( left )
 {
   // pines LEFT motor
   digitalWrite(MOTORRIGHT_DIR_A,HIGH);
   digitalWrite(MOTORRIGHT_DIR_B,LOW);
   analogWrite (MOTORRIGHT_PWM, value);
 }

 if ( right )
 {
   // pines RIGHT motor
   digitalWrite(MOTORLEFT_DIR_A,HIGH);
   digitalWrite(MOTORLEFT_DIR_B,LOW);
   analogWrite (MOTORLEFT_PWM, value);
 }
}

void setup()
{
 // inicializar pines de salida
 pinMode(LEDPIN          ,OUTPUT);
 pinMode(STANDBY         ,OUTPUT);
 pinMode(MOTORRIGHT_DIR_A ,OUTPUT);
 pinMode(MOTORRIGHT_DIR_B ,OUTPUT);
 pinMode(MOTORRIGHT_PWM   ,OUTPUT);
 pinMode(MOTORLEFT_DIR_A ,OUTPUT);
 pinMode(MOTORLEFT_DIR_B ,OUTPUT);
 pinMode(MOTORLEFT_PWM   ,OUTPUT);
 pinMode(BUTTONPIN       ,INPUT);
 Serial.begin(9600);

 // presiona botón para activar calibración
 while ( !digitalRead(BUTTONPIN) );

 // calibrar sensores QTRA, titilando LED como guía
 for ( int i=0; i<70; i++)
 {
   digitalWrite(LEDPIN, HIGH); delay(20);
   qtra.calibrate();
   digitalWrite(LEDPIN, LOW);  delay(20);
 }

 // apagar LED
 digitalWrite(LEDPIN, LOW);

 // presionar botón para correr el robot
 while ( !digitalRead(BUTTONPIN) );

 // esperar 5 segundos 
 delay(1000);
 
 // mover el robot suave para ganar inercia
 setMotors(10, 10);
 
 // durante 0.3 segundos
 delay(300);
}

unsigned int position = 0; // posición actual de los sensores
int derivative = 0;        // derivada
int proportional = 0;      // proporcional
int power_difference = 0;  // velocidad diferencial

// Máxima velocidad en el poder diferencial
int max = 120;

// Ultima Proporcional
int last_proportional;

// Constantes Proporcional y Derivativa
float KP = 0.17;
float KD = 2.2;

// Constante para Rango de Freno (Range Brake)
#define RANGEBRAKE 3500

void loop()
{   
 // Obtiene la posición de la linea
 // Aquí no estamos interesados en los valores 
 // individuales de cada sensor
 position = qtra.readLine(sensorValues);

 // El término proporcional debe ser 0 cuando estamos en línea
 proportional = ((int)position) - 3500;

 // Si entra en el rango de freno, aplicarlo en la 
 // direccion de la curva
 if ( proportional <= -RANGEBRAKE )
 {
   setMotorRight(0);
   setBrake(true,false,255);
   delay(1);
 }
 else if ( proportional >= RANGEBRAKE )
 {
   setMotorLeft(0);
   setBrake(false,true,255);
   delay(1);
 }

 // Calcula el término derivativo (cambio) de la posición
 derivative = proportional - last_proportional;

 // Recordando la última posición
 last_proportional = proportional;

 // Calcula la diferencia entre la potencia de los dos motores [ m1 - m2 ]. 
 // Si es un número positivo, el robot gira a la [ derecha ] 
 // Si es un número negativo, el robot gira a la [ izquierda ]
 //  y la magnitud del número determina el ángulo de giro.
 int power_difference = ( proportional * KP ) + ( derivative * KD );

 // Si velocidad diferencial es mayor a la posible tanto positiva como negativa,
 // asignar la máxima permitida
 if ( power_difference > max ) power_difference = max; 
 else if ( power_difference < -max ) power_difference = -max;

 // Asignar velocidad calculada en el poder diferencial de los motores
 ( power_difference < 0 ) ? 
   setMotors(max+power_difference, max) : setMotors(max, max-power_difference);
   
}

y el codigo que cree para los motores individualmente es:

int direca = 11;
int direcb = 10;
int pwm1 = 9;
int direca2 = 5;
int direcb2 = 4;
int pwm2 = 6;

void setup() {

 pinMode(direca, OUTPUT);
 pinMode(direcb, OUTPUT);
 pinMode(pwm1, OUTPUT);
 pinMode(direca2, OUTPUT);
 pinMode(direcb2, OUTPUT);
 pinMode(pwm2, OUTPUT);

}

void loop() {
 
digitalWrite(direca, HIGH);
digitalWrite(direcb, LOW);
digitalWrite(pwm1, HIGH);
digitalWrite(direca2, HIGH);
digitalWrite(direcb2, LOW);
digitalWrite(pwm2, HIGH);
delay(2000);
digitalWrite(direca, LOW);
digitalWrite(direcb, HIGH);
digitalWrite(pwm1,HIGH);
digitalWrite(direca2, LOW);
digitalWrite(direcb2, HIGH);
digitalWrite(pwm2, HIGH);
delay(4000);

}

Y si alimentas los motores desde el Arduino eso puede ocurrir.
Monta o compra una fuente para los motores y comparte GND entre ambas fuentes para que los comandos del arduino al driver de los motores siga funcionando.

Alimento los motores desde una fuente externa, el arduino no soportaria los 400mA que demanda cada motor.

Estoy realizando multiples pruebas para llegar el problema puntual y quiero consultarte algo para ver si estoy dando con lo justo.

Al programa que genere para controlar los motores le borre algunas partes para que solamente funcione uno y luego le borre otras para que funcione el otro y dar con el puente H que esta reiniciando el arduino... Por suerte di con el que esta mal.

Si defino como salida los puertos de PWM y direccion y por X motivo se genera una tension en el puerto que proviene del puente H, el arduino se reiniciaria para protegerlo? o tal vez se queda en un bucle al no saber que hacer con esta tension.

Es posible? como protege ante esto?

Gracias