¿Cómo puedo conseguir que este botón sea más confiable para mi programa arduino?

2

He estado trabajando en este programa para un controlador simple. Tengo un prototipo completamente conectado y funcionando, sin embargo, el pulsador momentáneo no es muy confiable. A veces lo lee y otras veces lo ignora.

Aquí está mi código.

/*
 * Valve Purge Control/heater control
 */
#include <math.h>

int feedValve = 12;                              // feed valve is connected to pin 12
int returnValve = 11;                            // return valve is connected to pin 11
int heater = 10;                               // heater is connected to pin 10
//int loopValves = 9                             // loop valves are connected to pin 9
//int pump = 8                                   // pump is connected to pin 8
int button = 2;                                  // button is connected to pin 2

int val;                                         // variable for reading the pin status
int val2;                                        // variable for reading the delayed/debounced status
int buttonState;                                 // variable to hold the button state

int buttonMode = 0;                               // Is valve on or off?

void setup() {
  pinMode(feedValve, OUTPUT);                    // Set the Feed Valve pin as output
  pinMode(returnValve, OUTPUT);                  // Set the Return Valve pin as output
  pinMode(heater, OUTPUT);                       // Set the Heater Valve pin as output
  //pinMode(loopValves, OUTPUT);                 // Set the Loop Valves pin as output
  //pinMode(pump, OUTPUT):                       // Set Pump pin as output
  pinMode(button, INPUT);                        // Set the switch pin as input
  Serial.begin(9600);                            // Set up serial communication at 9600bps
  buttonState = digitalRead(button);             // read the initial state
}

double Thermister(int RawADC) {
  double Temp;
  Temp = log(((10240000/RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
  Temp = Temp - 273.15;           // Convert Kelvin to Celcius
  Temp = (Temp * 1.8) + 32.0;    // Convert to F
  return Temp;
}

void loop(){
  val = digitalRead(button);                     // read input value and store it in val
  delay(10);
  val2 = digitalRead(button);                    // read the input again to check for bounces
  if (val == val2) {                             // make sure we got 2 consistant readings!
    if (val != buttonState) {                    // the button state has changed!
      if (val == LOW) {                          // check if the button is pressed
        if (buttonMode == 0) {                   // is the button off?
           buttonMode = 1;                       // turn buttonMode to 1
          } else {
            if (buttonMode == 1){
            buttonMode = 0;                      // turn buttonMode to 0
          }
        }
      }  
     buttonState = val;
    }
    if (buttonMode == 1) {
      double Temp = Thermister(analogRead(0));   // read Thermistor
      //Serial.println(Temp);
      if (Temp > 90){
        digitalWrite(feedValve, HIGH);           // turn on feed valve
        delay(5000);                             
        digitalWrite(returnValve, HIGH);         // turn on return valve
      }
      if (Temp < 100)digitalWrite(heater, HIGH);      // turn heater on
      else if (Temp > 105)digitalWrite(heater, LOW);  // turn heater off
    }

    if (buttonMode == 0) {
      digitalWrite(heater, LOW);                 // turn heater off
      digitalWrite(feedValve, LOW);              // turn feed valve off    
      delay(5000);
      digitalWrite(returnValve, LOW);            // turn return valve off
    }
  }
}
    
pregunta D.W.

3 respuestas

5

EDITAR: El botón está conectado de esta manera:

Sinohubieraunpull-up,unopondríalosiguienteensetup()

pinMode(button,INPUT);digitalWrite(button,HIGH);

Unainterrupciónesuneventoque"detiene" el programa principal, ejecuta una función (llamada rutina de servicio de interrupción o ISR, por sus siglas en inglés), luego regresa al programa principal donde se fue. Los pines 2 y 3 tienen interrupciones activadas por nivel y borde. Puede usarlos para establecer un indicador que indica que se presionó el botón. p.ej. agregando este código a la configuración ()

attachInterrupt(0, pin2_isr, FALLING);

ejecutará la función pin2_isr cuando el botón traiga el pin 2 bajo. Añadir una variable de marca al inicio,

volatile boolean pin2_flag = 0;

luego la función isr,

void pin2_isr() {
    pin2_flag = 1;
}

EDITAR: agrega una variable de estado de válvula para que no sigas activándolas cuando ya están encendidas.

boolean valve_state = 0;

Tu bucle principal podría convertirse en

void loop() 
{
    if(pin2_flag == 1) 
    { 
        detachInterrupt(0);      //Interrupt received, turn ISR off
        pin2_flag = 0;           //Interrupt received, clear flag
        //Debounce
        delay(250);
        //Check button still down
        if(digitalRead(2) == 0) {
          if (buttonMode == 0) buttonMode = 1;   //Change mode
          else buttonMode = 0;
          Serial.println("button press");
        }
        //Little delay for debounce
        digitalWrite(13,LOW);
        attachInterrupt(0,pin2_isr,FALLING);   //Re-enable interrupt
    }

    if (buttonMode == 1) {
        double Temp = Thermister(analogRead(0));   // read Thermistor
        //Serial.println(Temp);
        if (Temp > 90 && valve_state == 0) {
            digitalWrite(feedValve, HIGH);           // turn on feed valve
            delay(5000);                             
            digitalWrite(returnValve, HIGH);         // turn on return valve
            valve_state = 1;
        }
        if (Temp < 100) digitalWrite(heater, HIGH);      // turn heater on
        else if (Temp > 105) digitalWrite(heater, LOW);  // turn heater off
    }

    else if (buttonMode == 0) {
        digitalWrite(heater, LOW);                 // turn heater off
        if (valve_state == 1) {
            digitalWrite(feedValve, LOW);          // turn feed valve off
            delay(5000);
            digitalWrite(returnValve, LOW);        // turn return valve off
            valve_state = 0;
        }
    }
}

Note el cambio del segundo 'if' a un 'else if' y la adición de las líneas de modo de botón.

Por cierto, lo que tienes ahora es una máquina de estados. Agrega más botones de modo para hacer más cosas.

editar: se modificó la interrupción a la caída para evitar que se establezca una marca cuando el botón se mantiene presionado durante demasiado tiempo.

edición 2: modificada según la sugerencia de daves

edición 3: se ha añadido mejor rebote

edición 4: el número de interrupción debe ser 0 no 2

    
respondido por el geometrikal
3

La forma en que se escribe tu código, está gastando un lote de tiempo en delay(5000) llamadas. Esto podría explicar fácilmente las pulsaciones de botón perdidas.

Cada vez que el sistema operativo Arduino llame a su función loop() , siempre que el estado del botón sea estable, ingresará al bloque if (val == val2) { ... } . Dentro de este bloque hay tres declaraciones if() más; if (val != buttonState) detecta y maneja nuevos botones presionando y solo se ejecuta ocasionalmente. Pero uno de los otros dos bloques siempre se ejecutará, dependiendo del estado actual de buttonMode . Cada uno de estos bloques contiene un delay(5000) ; el que está en el bloque if (buttonMode == 1) se ejecuta cuando la temperatura es superior a 90, y el que está en el bloque if (buttonMode == 0) siempre se ejecuta.

Querrás encontrar una forma diferente de implementar esos retrasos que no bloqueen tu bucle principal, pero no sé cuál es el lenguaje Arduino adecuado para hacerlo.

    
respondido por el Dave Tweed
0

Bueno, no es que no pueda deshacer el rebote en el software, pero el lado del hardware de mí simplemente se lanzó en algún pequeño desautorizador de interruptor .

Además, pondría el botón pulsador en una línea de interrupción en lugar de sondeo, pero ese es solo yo, no tienes que hacer eso.

¿Ha intentado aumentar su tiempo de retardo a 250 ms o menos?

    
respondido por el Some Hardware Guy

Lea otras preguntas en las etiquetas