Debounce

<< Regresar

Los problemas mecánicos y físicos de un interruptor o pulsador son detectados por el programa como múltiples pulsaciones en un corto tiempo. Son falsas pulsaciones producido por falsos contactos (ruido).

El objetivo de Debounce es comprobar el cambio de estado en el interruptor dos veces en un corto período de tiempo para asegurar la pulsación del interruptor.

/ *
  La licencia MIT (MIT)

  Copyright (c) 2013 thomasfredericks

  Por la presente se otorga el permiso, sin cargo, a cualquier persona que obtenga una copia de este software y los archivos de documentación asociados (el "Software"), para tratar en el Software sin restricciones, incluidos, entre otros, los derechos de usar, copiar, modificar, fusionar, publicar, distribuir, sublicenciar y / o vender copias del Software, y para permitir que las personas a quienes se suministra el Software lo hagan, sujeto a las siguientes condiciones:

El aviso de copyright anterior y este aviso de permiso se incluirán en todas las Copias o partes sustanciales del Software.

EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITAS, INCLUIDAS, PERO NO LIMITADAS A LAS GARANTÍAS DE COMERCIABILIDAD, APTITUD PARA UN PROPÓSITO PARTICULAR Y NO INCUMPLIMIENTO. EN NINGÚN CASO LOS AUTORES O LOS TITULARES DEL DERECHO DE AUTOR SERÁN RESPONSABLES POR CUALQUIER RECLAMACIÓN, DAÑOS U OTRAS RESPONSABILIDADES, SI EN UNA ACCIÓN DE CONTRATO, CORTE O DE OTRA MANERA, DERIVADO DE, FUERA DE O EN CONEXIÓN CON EL SOFTWARE O EL USO U OTRAS REPARACIONES EN EL SOFTWARE.
* /

/ * * * * * * * * * * * * * * * * * * * * * * * * * *
  Modificado para Particle por David Washington (@dwcares)
  Código principal por Thomas O Fredericks (tof@t-o-f.info)
  Contribuciones anteriores de Eric Lowry, Jim Schimpf y Tom Harkaway
  * * * * * * * * * * * * * * * * * * * * * * * * * * *

#include "Debounce.h"

#define DEBOUNCED_STATE 0
#define UNSTABLE_STATE  1
#define STATE_CHANGED   3


Debounce::Debounce()
    : previous_millis(0)
    , interval_millis(10)
    , state(0)
    , pin(0)
{}

void Debounce::attach(int pin) {
    this->pin = pin;
    state = 0;
    if (digitalRead(pin)) {
        state = _BV(DEBOUNCED_STATE) | _BV(UNSTABLE_STATE);
    }
#ifdef BOUNCE_LOCK_OUT
    previous_millis = 0;
#else
    previous_millis = millis();
#endif
}

void Debounce::attach(int pin, PinMode mode){
  pinMode(pin, mode);
  
  this->attach(pin);
}

void Debounce::interval(uint16_t interval_millis)
{
    this->interval_millis = interval_millis;
}

bool Debounce::update()
{
#ifdef BOUNCE_LOCK_OUT
    state &= ~_BV(STATE_CHANGED);
    // Ignorar todo si estamos bloqueados
    if (millis() - previous_millis >= interval_millis) {
        bool currentState = digitalRead(pin);
        if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) {
            previous_millis = millis();
            state ^= _BV(DEBOUNCED_STATE);
            state |= _BV(STATE_CHANGED);
        }
    }
    return state & _BV(STATE_CHANGED);

#elif defined BOUNCE_WITH_PROMPT_DETECTION
    // Lee el estado del puerto del switch en una variable temporal.
    bool readState = digitalRead(pin);
    // Borrar el indicador de estado modificado: se restablecerá si confirmamos un cambio de estado del botón.
    state &= ~_BV(STATE_CHANGED);

    if ( readState != (bool)(state & _BV(DEBOUNCED_STATE))) {
      // Hemos visto un cambio desde el estado actual del botón.

      if ( millis() - previous_millis >= interval_millis ) {
	// Hemos pasado el umbral de tiempo, por lo que se permite un nuevo cambio de estado.
        // establece el indicador STATE_CHANGED y el nuevo DEBOUNCED_STATE.
        // Esto será puntual siempre y cuando haya habido más que interval_misllis ms desde el último cambio de entrada.
        // De lo contrario, el estado de rebote no volverá a cambiar hasta que el rebote sea estable durante el período de tiempo de espera.
	state ^= _BV(DEBOUNCED_STATE);
	state |= _BV(STATE_CHANGED);
      }
    }

    // Si readState es diferente de readState anterior, reinicie el temporizador de rebote, ya que la entrada aún es inestable
    // y queremos evitar nuevos cambios en el estado del botón hasta que el anterior se haya mantenido estable durante el tiempo de espera.
    if ( readState != (bool)(state & _BV(UNSTABLE_STATE)) ) {
	// Actualizar Bit inestable a macth readState
        state ^= _BV(UNSTABLE_STATE);
        previous_millis = millis();
    }
    // devuelve solo el estado cambiado bit
    return state & _BV(STATE_CHANGED);
#else
    // Leer el estado del switch en una variable temporal.
    bool currentState = digitalRead(pin);
    state &= ~_BV(STATE_CHANGED);

    // Si la lectura es diferente de la última lectura, reinicie el contador de rebote
    if ( currentState != (bool)(state & _BV(UNSTABLE_STATE)) ) {
        previous_millis = millis();
        state ^= _BV(UNSTABLE_STATE);
    } else
        if ( millis() - previous_millis >= interval_millis ) {
            // Hemos pasado el tiempo límite, por lo que la entrada ahora es estable
            // Si es diferente del último estado, establece el indicador
            if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) {
                previous_millis = millis();
                state ^= _BV(DEBOUNCED_STATE);
                state |= _BV(STATE_CHANGED);
            }
        }

    return state & _BV(STATE_CHANGED);
#endif
}

bool Debounce::read()
{
    return state & _BV(DEBOUNCED_STATE);
}

bool Debounce::rose()
{
    return ( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));
}

bool Debounce::fell()
{
    return !( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));
}

Temas Relacionados

 

Última actualización: octubre 26, 2018

Deja un comentario

Facebook
Facebook
Twitter
Visit Us
LinkedIn
YOUTUBE
YOUTUBE