Hola chicos!
A raíz de un post reciente me he planteado escribir una clase para manejar entradas digitales.
Básicamente se trata de un objeto que encapsula un pin y lee el estado (LOW, HIGH, FALLING o RISING) y usa un debounce para evitar rebotes en la entrada. También se puede usar lógica invertida, que es útil para cuando manejamos interruptores llevados a GND y usamos la resistencia PULLUP, donde
el interruptor cerrado tiene un valor LOW pero la cabeza te dice que debe ser HIGH.
También tiene sobrecarga de operadores de igualdad, AND y OR.
El código de la librería es el siguiente:
- Archivo de cabecera input.h
#ifndef _INPUT_H_
#define _INPUT_H_
#include <Arduino.h>
// Comentar línea para no usar lógica invertida.
#define USE_INVERTED_LOGIC
// Comentar línea para no usar sobrecarga de métodos.
#define USE_OVERLOADED_METHODS
#ifndef ON
#define ON 1
#endif
#ifndef OFF
#define OFF 0
#endif
class input {
private:
uint8_t pin;
uint8_t value;
uint8_t prev;
uint8_t state;
uint32_t debounce;
uint32_t timer;
public:
input(uint8_t _pin);
void update();
uint8_t read();
void setDebounce(uint32_t _debouncd);
#ifdef USE_OVERLOADED_METHODS
bool operator==(const uint8_t v);
bool operator!=(const uint8_t v);
bool operator!();
bool operator&&(const input &a);
bool operator&&(const int &a);
bool operator||(const input &a);
bool operator||(const int &a);
#endif
};
#endif
- Archivo de implementación input.cpp
#include "input.h"
input::input(uint8_t _pin) {
pin = _pin;
pinMode(pin, INPUT_PULLUP);
value=digitalRead(pin);
prev = value;
state = value;
debounce = 50;
}
void input::update() {
if ( digitalRead(pin)==value ) {
timer=0;
}
else
if ( timer==0 ) {
timer=millis();
}
else
if ( millis()-timer>debounce ) {
value=!value;
}
#ifdef USE_INVERTED_LOGIC
if ( prev==HIGH && value==LOW ) state=RISING;
if ( prev==HIGH && value==HIGH ) state=LOW;
if ( prev==LOW && value==HIGH ) state=FALLING;
if ( prev==LOW && value==LOW ) state=HIGH;
#else
if ( prev==HIGH && value==LOW ) state=FALLING;
if ( prev==HIGH && value==HIGH ) state=HIGH;
if ( prev==LOW && value==HIGH ) state=RISING;
if ( prev==LOW && value==LOW ) state=LOW;
#endif
prev = value;
}
uint8_t input::read() {
return state;
}
void input::setDebounce(uint32_t _debounce) {
debounce = _debounce;
}
#ifdef USE_OVERLOADED_METHODS
bool input::operator==(const uint8_t v) {
return state==v;
}
bool input::operator!=(const uint8_t v) {
return state!=v;
}
bool input::operator!() {
if ( state==FALLING ) return false;
if ( state==RISING ) return true;
return !state;
}
bool input::operator&&(const input &a) {
uint8_t x, y;
x = state;
y = a.state;
(x==FALLING||x==LOW)?x=0:x=1;
(y==FALLING||y==LOW)?y=0:y=1;
return x&&y;
}
bool input::operator&&(const int &a) {
uint8_t x, y;
x = state;
a > 3 ? y = 1 : y = a;
(x==FALLING||x==LOW)?x=0:x=1;
(y==FALLING||y==LOW)?y=0:y=1;
return x&&y;
}
bool input::operator||(const input &a) {
uint8_t x, y;
x = state;
y = a.state;
(x==FALLING||x==LOW)?x=0:x=1;
(y==FALLING||y==LOW)?y=0:y=1;
return x||y;
}
bool input::operator||(const int &a) {
uint8_t x, y;
x = state;
a > 3 ? y = 1 : y = a;
(x==FALLING||x==LOW)?x=0:x=1;
(y==FALLING||y==LOW)?y=0:y=1;
return x||y;
}
#endif
Y de momento funciona, pero me he encontrado con un "problemilla", creo que me estoy oxidando como programador.
El caso es que la sobrecarga funciona, pero con limitaciones. Por ejemplo si quiero hacer el AND de tres entradas según como lo haga me da error de compilación. Ejemplo:
#include "input.h"
input i1(2);
input i2(3);
input i3(4);
void setup() {
pinMode(5, OUTPUT);
}
void loop() {
i1.update();
i2.update();
i3.update();
// Esto funciona:
if ( i1 && (i2 && i3) )
digitalWrite(5,HIGH);
else
digitalWrite(5,LOW);
}
En el código anterior hago AND de las tres entradas agrupando por paréntesis y funciona, pero si quitas el paréntesis:
#include "input.h"
input i1(2);
input i2(3);
input i3(4);
void setup() {
pinMode(5, OUTPUT);
}
void loop() {
i1.update();
i2.update();
i3.update();
// Esto NO funciona:
if ( i1 && i2 && i3 )
digitalWrite(5,HIGH);
else
digitalWrite(5,LOW);
}
Tira error de compilación:
D:\Programas\arduino-1.8.19\portable\sketchbook\pruebaInput\pruebaInput.ino: In function 'void loop()':
pruebaInput:17:17: error: no match for 'operator&&' (operand types are 'bool' and 'input')
if ( i1 && i2 && i3 )
~~~~~~~~~^~~~~
D:\Programas\arduino-1.8.19\portable\sketchbook\pruebaInput\pruebaInput.ino:17:17: note: candidate: operator&&(bool, bool) <built-in>
D:\Programas\arduino-1.8.19\portable\sketchbook\pruebaInput\pruebaInput.ino:17:17: note: no known conversion for argument 2 from 'input' to 'bool'
exit status 1
no match for 'operator&&' (operand types are 'bool' and 'input')
¿Soy yo que no sé sobrecargar los métodos && y ||, o simplemente, es que el compilador no permite realizar dicha operación con métodos
sobrecargados?