Problema con pulsadores al conectar el modulo L298N

Hola,

Tengo un proyecto para hacer que un ventilador gire a diferentes velocidades aleatoriamente con tres modos de intensidad y dos botones para subir y bajar esta. Si hago salidas en pantalla de cuando entra en cada modo parece funcionar bien, pero cuando conecto la pila al L298N y el motor empieza a girar, modo pasa a ser 0, y ya no responde a las pulsaciones de los botones.

// Práctica encender LED con botón pulsador y luego apagar LED con el mismo
//boton pulsador
const int LED = LED_BUILTIN;
const int Boton2 = 2;
const int Boton3 = 3;

const int pinENA = 6;
const int pinIN1 = 7;
const int pinIN2 = 8;
const int pinIN12 = 12;

// 100 2v en carga
// 150 3v en carga
int velo = 100;    //modo de giro 80% (200/255)
int velomin = 50;    // modo modomin

// Variable global de modo
int modo = 0;
// Constantes de modo máxima, mínima y cuanto aumento
const int modomax = 30;
const int modomin = 0;
const int aumento = 10;

volatile int intervalo = 1000;

void randomize (){
	srand(1);// Inicializa el motor aleatorio para poder usar rand
}
int random(int liminf, int limsup){ //Genera un numero aleatorio
	int Numero = (rand () % (limsup-liminf+0x1)) + liminf;  
	return Numero;
}



void setup(){  // definir si la variable es de entrada // o salida.
	Serial.begin(9600); 
  
	pinMode(LED,OUTPUT); // establecer que el pin digital es una señal de salida
	pinMode(Boton2, INPUT_PULLUP); // y Boton2 como señal de entrada
	pinMode(Boton3, INPUT_PULLUP);

	pinMode(pinIN1, OUTPUT);
	pinMode(pinIN2, OUTPUT);
	pinMode(pinENA, OUTPUT);
  
	// Configuramos los pines de interrupciones para que
	// detecten un cambio de bajo a alto
	attachInterrupt(digitalPinToInterrupt(Boton2), modoMenos, CHANGE  );
	attachInterrupt(digitalPinToInterrupt(Boton3), modoMas, CHANGE  );
 }

void loop() {       // loop = realice un lazo continuamente
	if (modo==10){
		secuencia010();
	}
	else if (modo==20){
		secuencia020();
	}
	else if (modo==30){
		secuencia030();
	}
	else{
		digitalWrite(LED,LOW); // apagar el LED
		digitalWrite(pinIN1, LOW);
		digitalWrite(pinIN2, LOW);
		analogWrite(pinENA, 0);  
	}
	//delayMicroseconds(50);
	delayMicroseconds(100);
}

// ISR pin 2, disminuye el modo
void modoMenos()
{
	// Disminuimos el valor establecido
	modo = modo - aumento;

	// Si hemos llegado a el modo mínima no disminuímos más
	if (modo < modomin)
	{
		modo = modomin;
	}
	Serial.print("El valor de modo es: "); 
	Serial.println(modo); // println imprime y crea una nueva linea
}

// ISR pin 3, aumenta el modo
void modoMas()
{
	// aumentomos el valor establecido
	modo = modo + aumento;

	// Si hemos llegado a el modo máxima no aumentomos más
	if (modo > modomax)
	{
		modo = modomax;
	}
	Serial.print("El valor de modo es: "); 
	Serial.println(modo);
}
void secuencia010(){
	while(modo==10){
		velo=random(0,125);
		if (velo<velomin){
			digitalWrite(pinIN1, LOW);
		}else{
			digitalWrite(pinIN1, HIGH);
			analogWrite(pinENA, velo);
		}
		delay(random(500,2000));  
	} 
}
void secuencia020(){
	while(modo==20){
		digitalWrite(LED, LOW);
		velo=random(50,125);
		digitalWrite(pinIN1, HIGH);
		digitalWrite(pinIN2, LOW);
		analogWrite(pinENA, velo);
		intervalo=random(500,2000);
		delayMicroseconds(intervalo);
	} 
}
void secuencia030(){
	while(modo==30){
		digitalWrite(LED, HIGH); // enciende el LED
		velo=random(50,125);
		digitalWrite(pinIN1, HIGH);
		digitalWrite(pinIN2, LOW);
		analogWrite(pinENA, velo);
		intervalo=random(500,2000);
		delayMicroseconds(intervalo);
	} 
}

Pila? de que valor, 9V? las pilas de 9V no son buena fuente para proyectos de desarrollo. Lo mejor es tener una fuente DC de 9V hacer toda la tarea y luego si quieres usar una batería de 9V entonces intentalo yo no lo aconsejo porque vivirás comprando baterias de 9V que no son baratas.

El motor estaba alimentado en origen por dos pilas de 1,5 v y le redudzco la velocidad para que no pase de 3v la corriente, en principio el consumo no será un problema porque no estará siempre enchufado. He leido por ahi tambien que los pulsadores son sensibles a interferencias, no se si podria ser el caso, si asi lo fuera siempre daria menos interferencias una pila, no?

Tambien doy por echo que las funciones attachInterrupt y digitalPinToInterrupt... ya habran tenido en cuenta las interferencias. Voy a intentar reducir el codigo a un ejemplo para que me podais ayudar mas facilmente.

Y como pretendes salir de cualquiera de estas funciones ? secuencia010(), secuencia020(), secuencia030()

void secuencia020(){
   while(modo == 20){
      digitalWrite(LED, LOW);
      velo = random(50,125);
      digitalWrite(pinIN1, HIGH);
      digitalWrite(pinIN2, LOW);
      analogWrite(pinENA, velo);
      intervalo = random(500,2000);
      delayMicroseconds(intervalo);
   } 
}

El motor estaba alimentado en origen por dos pilas de 1,5 v y le redudzco la velocidad para que no pase de 3v

3V en un puente H L298? Todo lo que veo en la hoja de datos dice que trabaja con 5V y los motores si pueden tener tensiones hasta 46V pero 3V me parece que no.

Bajando la velocidad de motor consigo 3v.

Cuando modo sea 0 deberia salir de las funciones

Bueno, he cambiado el motor y ahora va bien. Lo más curioso es que el motor que tenia antes era el que venia en el kit de inicio.

Aunque el problema esté resuelto me gustaria saber porque con algunos motores el comportamiento del programa es erratico pasando olimpicamente de los botones, poniendose en modo 0 pero quedando el motor activado.

Saludos y gracias :)

He añadido un parpadeo en el led de la placa para cada modo de mi emulador de viento racheado. Lo dejo aqui para quien le pueda servir.

// Práctica encender LED con botón pulsador y luego apagar LED con el mismo
//boton pulsador
const int LED = LED_BUILTIN;
const int Boton2 = 2;
const int Boton3 = 3;

const int pinENA = 6;
const int pinIN1 = 7;
const int pinIN2 = 8;
const int pinIN12 = 12;

// 100 2v en carga
// 150 3v en carga
int velo = 100;    //modo de giro 80% (200/255)
int velomin = 50;    // modo modomin

// Variable global de modo
int modo = 0;
// Constantes de modo máxima, mínima y cuanto aumento
const int modomax = 40;
const int modomin = 0;
const int aumento = 10;

unsigned long previousMillis = 0;        // will store last time LED was updated
volatile long intervalo = 600;
int ledState = LOW;             // ledState used to set the LED

void randomize (){
	srand(1);// Inicializa el motor aleatorio para poder usar rand
}
int random(int liminf, int limsup){ //Genera un numero aleatorio
	int Numero = (rand () % (limsup-liminf+0x1)) + liminf;  
	return Numero;
}



void setup(){  // definir si la variable es de entrada // o salida.
	Serial.begin(9600); 
  
	pinMode(LED,OUTPUT); // establecer que el pin digital es una señal de salida
	pinMode(Boton2, INPUT_PULLUP); // y Boton2 como señal de entrada
	pinMode(Boton3, INPUT_PULLUP);

	pinMode(pinIN1, OUTPUT);
	pinMode(pinIN2, OUTPUT);
	pinMode(pinENA, OUTPUT);
  
	// Configuramos los pines de interrupciones para que
	// detecten un cambio de bajo a alto
	attachInterrupt(digitalPinToInterrupt(Boton2), modoMenos, RISING  );
	attachInterrupt(digitalPinToInterrupt(Boton3), modoMas, RISING  );
 }

void loop() {       // loop = realice un lazo continuamente
	//Parpadeo(4);
	if (modo==10){
		secuencia010();
	}
	else if (modo==20){
		secuencia020();
	}
	else if (modo==30){
		secuencia030();
	}
	else if (modo==40){
		secuencia040();
	}
	else{
		digitalWrite(LED,LOW); // apagar el LED
		digitalWrite(pinIN1, LOW);
		digitalWrite(pinIN2, LOW);
		analogWrite(pinENA, 0);  
	}
	//delayMicroseconds(50);
	delay(200);
	Serial.println("Hago un looping"); 
	
  // unsigned long currentMillis = millis();

  // if (currentMillis - previousMillis >= intervalo) {
    // // save the last time you blinked the LED
    // previousMillis = currentMillis;

    // // if the LED is off turn it on and vice-versa:
    // if (ledState == LOW) {
      // ledState = HIGH;
    // } else {
      // ledState = LOW;
    // }

    // // set the LED with the ledState of the variable:
    // digitalWrite(LED, ledState);
  // }
	
	
}
void Parpadeo(int vecesparpadeo){
	for(int i=0;i<vecesparpadeo;i++){
		digitalWrite(LED, HIGH);
		delay(250);
		digitalWrite(LED, LOW);
		delay(250);

	}
	digitalWrite(LED, LOW);

}
void Parpadeosindelay(int vecesparpadeo){
	for(int i=0;i<vecesparpadeo;i++){
		unsigned long currentMillis = millis();
		if (currentMillis - previousMillis >= intervalo) {
			// save the last time you blinked the LED
			previousMillis = currentMillis;

			// if the LED is off turn it on and vice-versa:
			if (ledState == LOW) {
			  ledState = HIGH;
			} else {
			  ledState = LOW;
			}

			// set the LED with the ledState of the variable:
			digitalWrite(LED, ledState);
		}
	}
}
// ISR pin 2, disminuye el modo
void modoMenos(){	// Disminuimos el valor establecido
	modo = modo - aumento;
	// Si hemos llegado a el modo mínima no disminuímos más
	if (modo < modomin){
		modo = modomin;
	}
	Serial.print("El valor de modo es: "); 
	Serial.println(modo); // println imprime y crea una nueva linea
	delay(300);
}

// ISR pin 3, aumenta el modo
void modoMas(){
	// aumentomos el valor establecido
	modo = modo + aumento;
	// Si hemos llegado a el modo máxima no aumentomos más
	if (modo > modomax){
		modo = modomax;
	}
	Serial.print("El valor de modo es: "); 
	Serial.println(modo);
	delay(300);
}
void secuencia010(){
	Serial.println("Entrando en secuencia 10"); 
	Parpadeo(1);
	while(modo==10){
		velo=random(0,100);
		if (velo<velomin){
			digitalWrite(pinIN1, LOW);
		}else{
			digitalWrite(pinIN1, HIGH);
			digitalWrite(pinIN2, LOW);
			analogWrite(pinENA, velo);
		}
		delay(random(500,2000));  
	}
}
void secuencia020(){
	Serial.println("Entrando en secuencia 20"); 
	Parpadeo(2);
	while(modo==20){
		//digitalWrite(LED, LOW);
		velo=random(20,150);
		if (velo<velomin){
			digitalWrite(pinIN1, LOW);
		}else{
			digitalWrite(pinIN1, HIGH);
			digitalWrite(pinIN2, LOW);
			analogWrite(pinENA, velo);
		}
		delay(random(500,2000));
	}
}
void secuencia030(){
	Serial.println("Entrando en secuencia 30"); 
	Parpadeo(3);
	while(modo==30){
		//digitalWrite(LED, LOW);
		velo=random(30,180);
		if (velo<velomin){
			digitalWrite(pinIN1, LOW);
		}else{
			digitalWrite(pinIN1, HIGH);
			digitalWrite(pinIN2, LOW);
			analogWrite(pinENA, velo);
		}
		delay(random(500,2000));  
	}
}
void secuencia040(){
	Serial.println("Entrando en secuencia 40"); 
	Parpadeo(4);
	while(modo==40){
		//digitalWrite(LED, HIGH); // enciende el LED
		velo=random(100,200);
		if (velo<velomin){
			digitalWrite(pinIN1, LOW);
		}else{
			digitalWrite(pinIN1, HIGH);
			digitalWrite(pinIN2, LOW);
			analogWrite(pinENA, velo);
		}
		delay(random(500,4000));  
	}
}

Ahora creo que entiendo la pregunta de Kike_GL, sale de las funciones gracias a:

	attachInterrupt(digitalPinToInterrupt(Boton2), modoMenos, RISING  );
	attachInterrupt(digitalPinToInterrupt(Boton3), modoMas, RISING  );

estas interrumpen el while y al cambiar de modo, si se llega a 0, se para el motor segun el else de loop()

A veces salta dos modos con una pulsación, aun no se porque. Lei por ahi que era mejor usar el delaymicrosec con las funciones de interrupción pero no he notado nada al probar.

¿Alguna idea de porque salta dos modos en algunas ocasiones?

Porque no debes usar interrupciones para leer botones, algo que ha sido muchas veces dicho en este foro pero claro que no lo sabes, porque recién llegas y seguramente no has buscado estos temas ya comentados.

La web esta llena de personas que programan mal y no digo que sea palabra santa programando pero no se usan interrupciones con pulsadores!!! Eso es bien sabido, porque un pulsador rebota o puede hacerlo. Además se puede leer un pulsador sin usar interrupciones y no te darás cuenta.

También esta mas que comentado como hacerlo en el foro.

Basicamente lees el estado de un pulsador y lo comparas con el estado anterior del mismo pulsador. Antes de leerlo. Entonces comparas el flanco, cuando el flanco o sea el cambio de 0 a 1 o 1 a 0 es el que buscas entonces llevas adelante la acción de control como sumar un contador o decrementarlo. Es muy simple, no usa interrupciones y casi siempre funciona bien aún con los pulsadores que las interrupciones al ser tan rápidas muestras defectos.

En la misma página he dado el mismo comentario para dos personas, solo búscalo. Lee otros hilos y verás la respueta.

Gracias. Si, la información que busque en este foro fué referente al problema que me daba al conectar el motor al modulo. Sobre los botones con interrupciones la encontre en otras páginas. Buscaré otra manera de hacerlo aquí. Muchas gracias :)

Mira la manera es asi

Las variables son todas del tipo bool

  p = digitalRead(BOTON);
  if (!p && p_Ant) {   // flanco de 1 a 0?
      pulsado = !pulsado;
  }
  p_Ant = p;

Si en tu caso el botón esta siempre en LOW entonces invierte el flanco que vas a usar o sea será de 0 a 1

  if (p && !p_Ant) {   // flanco de 0 a 1?

Con esto resuelves el tema de como leer los pulsadores o botones.

Muchas gracias por simplificarmelo tanto. De esa forma por lo que veo tendria que meter el codigo de cada boton dentro de los while de cada funcion secuenciaXXX, pero no obstante segun entiendo tendria que dejar de usar delay ya que tengo que esperar con el boton pulsado hasta que termina el delay aleatorio, que es el motivo por el que busque otras opciones como la interrupción

Lo primero que debes haces es DESTERRAR (y mira como lo escribí) el uso de delay() de tus alternativas para programar y menos que menos si en un código usas milllis() en otro usar delay() porque es incoherente.

Modificarlo es todo un trabajo y no tengo tanto tiempo para hacerlo
He quitado las interrupciones y agregué lo sugerido

// Práctica encender LED con botón pulsador y luego apagar LED con el mismo
// boton pulsador
const byte LED     = LED_BUILTIN;
const byte Boton2  = 2;
const byte Boton3  = 3;

const byte pinENA  = 6;
const byte pinIN1  = 7;
const byte pinIN2  = 8;
const byte pinIN12 = 12;

// 100 2v en carga
// 150 3v en carga
int velo    = 100;    //modo de giro 80% (200/255)
int velomin = 50;    // modo modomin

// Variable global de modo
int modo = 0;
// Constantes de modo máxima, mínima y cuanto aumento
const int modomax = 40;
const int modomin =  0;
const int aumento = 10;

unsigned long previousMillis = 0;        // will store last time LED was updated
volatile long intervalo = 600;
int ledState = LOW;             // ledState used to set the LED

bool mMas, mMas_Ant = false;
bool mMenos, mMenos_Ant = false;

void randomize (){
  srand(1);// Inicializa el motor aleatorio para poder usar rand
}

int random(int liminf, int limsup){ //Genera un numero aleatorio
  int Numero = (rand () % (limsup-liminf+0x1)) + liminf;  
  return Numero;
}

void setup(){  // definir si la variable es de entrada // o salida.
  Serial.begin(9600); 
  
  pinMode(LED,OUTPUT); // establecer que el pin digital es una señal de salida
  pinMode(Boton2, INPUT_PULLUP); // y Boton2 como señal de entrada
  pinMode(Boton3, INPUT_PULLUP);

  pinMode(pinIN1, OUTPUT);
  pinMode(pinIN2, OUTPUT);
  pinMode(pinENA, OUTPUT);
  
  // Configuramos los pines de interrupciones para que
  // detecten un cambio de bajo a alto
  // attachInterrupt(digitalPinToInterrupt(Boton2), modoMenos, RISING  );
  // attachInterrupt(digitalPinToInterrupt(Boton3), modoMas, RISING  );
 }

void loop() {       // loop = realice un lazo continuamente

  mMas = digitalRead(BOTON2);
  if (mMas && !mMas_Ant) {   // flanco de 0 a 1?
      modoMas();
  }
  mMas_Ant = mMas;
  

  mMenos = digitalRead(BOTON3);
  if (mMenos && !mMenos_Ant) {   // flanco de 0 a 1?
      modoMas();
  }
  mMenos_Ant = mMenos;

  //Parpadeo(4);
  switch (modo) {
    case 10: secuencia010;
             break;
    case 20: secuencia020;
             break;
    case 30: secuencia030;
             break;      
    case 40: secuencia040;
             break;  
    default: 
              digitalWrite(LED,LOW); // apagar el LED
              digitalWrite(pinIN1, LOW);
              digitalWrite(pinIN2, LOW);
              analogWrite(pinENA, 0);  
              break;
  }

  //delayMicroseconds(50);
  delay(200);
  Serial.println("Hago un looping"); 
}


void Parpadeo(int vecesparpadeo){
  for (int i=0;i<vecesparpadeo;i++){
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
      delay(250);
  }
  digitalWrite(LED, LOW);

}

void Parpadeosindelay(int vecesparpadeo){
  for(int i=0;i<vecesparpadeo;i++){
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= intervalo) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;

      // if the LED is off turn it on and vice-versa:
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }

      // set the LED with the ledState of the variable:
      digitalWrite(LED, ledState);
    }
  }
}

void modoMenos(){ // Disminuimos el valor establecido
  modo -= aumento;
  // Si hemos llegado a el modo mínima no disminuímos más
  if (modo < modomin) modo = modomin;
  
  Serial.print("El valor de modo es: "); 
  Serial.println(modo); // println imprime y crea una nueva linea
  delay(300);
}

void modoMas(){
  // aumentomos el valor establecido
  modo += aumento;
  // Si hemos llegado a el modo máxima no aumentomos más
  if (modo > modomax)
      modo = modomax;
  Serial.print("El valor de modo es: "); 
  Serial.println(modo);
  delay(300);
}

void secuencia010(){
  Serial.println("Entrando en secuencia 10"); 
  Parpadeo(1);
  while (modo==10){
    velo=random(0,100);
    if (velo<velomin){
      digitalWrite(pinIN1, LOW);
    }else{
      digitalWrite(pinIN1, HIGH);
      digitalWrite(pinIN2, LOW);
      analogWrite(pinENA, velo);
    }
    delay(random(500,2000));  
  }
}
void secuencia020(){
  Serial.println("Entrando en secuencia 20"); 
  Parpadeo(2);
  while(modo==20){
    //digitalWrite(LED, LOW);
    velo=random(20,150);
    if (velo<velomin){
      digitalWrite(pinIN1, LOW);
    }else{
      digitalWrite(pinIN1, HIGH);
      digitalWrite(pinIN2, LOW);
      analogWrite(pinENA, velo);
    }
    delay(random(500,2000));
  }
}
void secuencia030(){
  Serial.println("Entrando en secuencia 30"); 
  Parpadeo(3);
  while(modo==30){
    //digitalWrite(LED, LOW);
    velo=random(30,180);
    if (velo<velomin){
      digitalWrite(pinIN1, LOW);
    }else{
      digitalWrite(pinIN1, HIGH);
      digitalWrite(pinIN2, LOW);
      analogWrite(pinENA, velo);
    }
    delay(random(500,2000));  
  }
}
void secuencia040(){
  Serial.println("Entrando en secuencia 40"); 
  Parpadeo(4);
  while(modo==40){
    //digitalWrite(LED, HIGH); // enciende el LED
    velo=random(100,200);
    if (velo<velomin){
      digitalWrite(pinIN1, LOW);
    }else{
      digitalWrite(pinIN1, HIGH);
      digitalWrite(pinIN2, LOW);
      analogWrite(pinENA, velo);
    }
    delay(random(500,4000));  
  }
}