Contar un solo clik usando Lib.Switch, con ejemplo [SOLUCIONADO] Gracias ☺!

Set up:
Arduino UNO R3
Lcd display con iC2
Este encoder

Lo que quiero hacer;
Un menu que se desplace de acuerdo a los pasos del encoder, que una vez que des clic en algun item del menu, se abra un sub-menu o la posibilidad de modificar una variable.

En lo que estoy:
El encoder funciona, me instale un sketch que permite contar la posiciones desplazadas, si es giro izquierdo o derecho todo bien.
No Puedo leer el clik!

Este es el sketch que lee el encoder;

const byte pinA = 2;      // encoder pin A to Arduino pin 2 which is also interrupt pin 0 which we will use
const byte pinB = 3;      // encoder pin B to Arduino pin 3 which is also interrupt pin 1 but we won't use it

byte state = 0;           // will store two bits for pins A & B on the encoder which we will get from the pins above

int level = 0;            // a value bumped up or down by the encoder

/* For demo purposes we will create an array of these binary digits */
String bits[] = {"00","01","10","11"};

/* A truth table of possible moves 
    1 for clockwise
   -1 for counter clockwwise
    0 for error - keybounce */
int bump[] = {0,0,-1,1};

void setup(){
  pinMode(pinA,INPUT);    // reads Pin A of the encoder
  pinMode(pinB,INPUT);    // reads Pin B of the encoder
  
  /* Writing to an Input pin turns on an internal pull up resistor */
  digitalWrite(pinA,HIGH);
  digitalWrite(pinB,HIGH);
  
  /* Set up to call our knob function any time pinA rises */
  attachInterrupt(0,knobTurned,RISING);    // calls our 'knobTurned()' function when pinA goes from LOW to HIGH
  
  level = 50;              // a value to start with
  
  /* Set up for using the on-screen monitor */
  Serial.begin(115200);    // make sure your monitor baud rate matches this
  Serial.println("Encoder Ready");
  Serial.print("level = ");
  Serial.println(level);   // to remind us where we're starting
}

void loop(){
  /* main programming will go here later
     for now we'll just do nothing until we get an interrupt */
}

void knobTurned(){
  /* AH HA! the knob was turned */
  state = 0;    // reset this value each time
  state = state + digitalRead(pinA);   // add the state of Pin A
  state <<= 1;  // shift the bit over one spot
  state = state + digitalRead(pinB);   // add the state of Pin B
  
  /* now we have a two bit binary number that holds the state of both pins
     00 - something is wrong we must have got here with a key bounce
     01 - sames as above - first bit should never be 0
     10 - knob was turned backwards
     11 - knob was turned forwards
     */
     
  /* We can pull a value out of our truth table and add it to the current level */
  level = level + bump[state];
  
  /* Let's see what happened */
  Serial.print(bits[state] + "    ");  // show us the two bits
  Serial.print(bump[state],DEC);       // show us the direction of the turn
  Serial.print("    ");
  Serial.println(level);               // show us the new value
}

La hoja de datos establece que para las terminales D y E.. existe un contacto NO.
YA LO COMPROBE CON EL MULTIMETRO...
Asi que conecto una de las terminales a 5V y la otra al pin 4 para leer su estado.

Resultado;
Comienza a contar de 0 hacia delante ta pronto como se termina el set up... ya intente poner una pulldown a tierra, pero asi no me lee nada.

Este es el código que utilizo;

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Bounce2.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

byte state = 0;           // will store two bits for pins A & B on the encoder which we will get from the pins above
int level = 0;            // a value bumped up or down by the encoder
int bump[] = {0,0,-1,1};
String bits[] = {"00","01","10","11"};

const byte pinA = 2;      // encoder pin A to Arduino pin 2 which is also interrupt pin 0 which we will use
const byte pinB = 3;      // encoder pin B to Arduino pin 3 which is also interrupt pin 1 but we won't use it
const byte pinC = 4;      //lee click 
int conteo = 0; 
int stado = 0;

//Bounce debouncer = Bounce(); // bouncer object 

void setup(){
  //debouncer.attach(pinC);
  //debouncer.interval(5); // interval in ms
  lcd.begin(16,2);   // initialize the lcd for 16 chars 2 lines, turn on backlight
  lcd.backlight();

  pinMode(pinA,INPUT);    // reads Pin A of the encoder
  pinMode(pinB,INPUT);    // reads Pin B of the encoder
  pinMode(pinC,INPUT);    // reads Pin B of the encoder
  
  /* Writing to an Input pin turns on an internal pull up resistor */
  digitalWrite(pinA,HIGH);
  digitalWrite(pinB,HIGH);

  attachInterrupt(0,knobTurned,RISING);    // calls our 'knobTurned()' function when pinA goes from LOW to HIGH
  level = 50;              // a value to start with
  Serial.begin(115200);    // make sure your monitor baud rate matches this
  Serial.println("Encoder Ready");
  Serial.print("level = ");
  Serial.println(level);   // to remind us where we're starting
}


void loop(){
  //debouncer.update();


  stado= digitalRead(pinC);  
  if(stado == HIGH){
     conteo++; 
     lcd.setCursor(0,0);
     lcd.print("El conteo es"); 
     lcd.setCursor(0,1); 
     lcd.print(conteo); }
     
  

}
void knobTurned(){
  /* AH HA! the knob was turned */
  state = 0;    // reset this value each time
  state = state + digitalRead(pinA);   // add the state of Pin A
  state <<= 1;  // shift the bit over one spot
  state = state + digitalRead(pinB);   // add the state of Pin B

  level = level + bump[state];
  
  /* Let's see what happened */
  Serial.print(bits[state] + "    ");  // show us the two bits
  Serial.print(bump[state],DEC);       // show us the direction of the turn
  Serial.print("    ");
  Serial.println(level);               // show us the new value
}

De momento removí el bounce, por que pensé que le habia configurado mal.

Carge un sketch de los ejemplos del arduino, donde se enciende un led cada vez que se da
clik al boton... y funciona... cada vez que doy clik al encoder se enciende el led del pin 13...

Igual algo hice mal en el codigo... han sido dias de dormir poco.

Muchas gracias de antemano!!! 8)

si entiendo bien, dices que con el multimétro se ve el cambio de estado del contacto NO.
Pero al conectarlo al arduino no ves el cambio?

Solo para entendernos te pongo esta imagen de pull-up o pull-down.
Por lo que dices lo tienes conectado como pull-down, es asi?
Aun prescindiendo de la resistencia de 100 ohms (que es opcional) cuando esta en reposo, tienes un LOW o 0V y cuando presionas tienes HIGH o 5V.
Revisa porque eso funciona.

Si quieres que las variables conserven valores cuando las modificas dentro de una funcion llamada por una
Interrupcion las debes declarar como volatile,por ejemplo
volatile int level;

Muchas gracias, aparentemente tenia un valor equivocado de resistencia y por eso pasaba demasiado ruido...
ahora funciona correctamente, o mas correctamente que antes...
pero tengo problemas para hacer que el encoder me cuente solo un clik...

Actualmente me lee los pasos, y los click, no tenia debounce, por lo que se agregaban varios.
Así que actualmente quiero agregar el debounce...
Estoy usando Debounce V2. De aqui.

En teoria deberia ser mas facil. Pero los resultados no son buenos, mientras se mantenga presionado el clik, se agrega uno a la cuenta...

Contador =1
Contador =2
Contador =3
Contador =4
Contador =5
Contador =6
Contador =7
Contador =8
Contador =9
Contador =10
Contador =11
Contador =12
Contador =13
Contador =14
Contador =15
Contador =16
Contador =17
Contador =18
Contador =19
Contador =20
Contador =21
Contador =22
Contador =23
Contador =24
Contador =25
Contador =26
Contador =27
Contador =28
Contador =29
Contador =30
Contador =31
Contador =32
Contador =33
Contador =34
Contador =35
Contador =36

Bounce v1.- Tenia un metodo llamado debounce.risingEdge que hacia precisamente eso. Ver la subida de voltaje y conseiderarlo como un clik. Pero en esta libreria no logro hacer que las cosas funcionen.

Aqui mi codigo... Nota que quizas haya metido la pata en los If, intentaba crear una condicion para incrmentar el contador solo en un tanto, ya que el metodo descrito anteriormente ya no esta.

#include <Bounce2.h>

int         pinC = 7; 
const byte  pinD = 13; 
int contador =0; 
Bounce encoderclik = Bounce(); 
byte stadoprevio = LOW;

void setup() {
  Serial.begin(9600);   

  pinMode(pinC, INPUT); 
  encoderclik.attach(pinC);
  encoderclik.interval(30); // interval in ms

  pinMode(pinD, OUTPUT); 
}



void loop(){

  encoderclik.update(); 
  int value = encoderclik.read(); 

  if(value== HIGH){
     if(value =! stadoprevio){
        contador= contador+1 ;
        Serial.print("Contador ="); 
        Serial.println(contador); 
        digitalWrite(pinD, HIGH); 
        stadoprevio = LOW;}}
   
  else{
    digitalWrite(pinD, LOW); }
  
}

He buscado ayuda online, encontre varios ejemplos como este, pero desgraciadamente usan la libreria vieja.

Alguien ahi que use esta libreria??? o que tenga idea como hacer lo que se requiere?

Gracias!!!

yo uso una que se llama switch.
Para tranquilidad te adjunté la librería Switch.cpp y Switch.h

Debes crear una carpeta Switch en ...\arduino\libraries

Switch.cpp (4.06 KB)

Switch.h (1.29 KB)

Como siempre gracias, Surbyte... de casualidad tendras algun ejemplo en español, me esta costando un poco entender que hacer con esto?

Gracias.
En unos minutos dejo alguno que haga yo, quizas te sea mas facil solo comentarlo.

este mismo te lo traduzco
a ver si se entiende algo mejor?

#if ARDUINO >= 100 
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif
 
#include <Streaming.h>
#include "Switch.h"
 
const byte toggleSwitchpin = 3; // (boton derecho)
const byte buttonGNDpin = 4;    // (boton izquierdo)
const byte ButtonVCCpin = 6; 
const byte Button10mspin = 8; 
int i;
 
Switch buttonGND = Switch(buttonGNDpin); // botón a GND, usa resistor interno pullup 20K
Switch toggleSwitch = Switch(toggleSwitchpin); 
Switch buttonVCC = Switch(ButtonVCCpin, INPUT, HIGH); // boton a VCC, resistencia pull-down de 10k, no pull-up interno, resistor, polaridad HIGH
Switch button10ms = Switch(Button10mspin, INPUT_PULLUP, LOW, 1); // Tiempo debounce 1ms
 
void setup() 
{ Serial.begin(9600);  
}
 
void loop() 
{ buttonGND.poll();  
  if(buttonGND.switched()) Serial << "switched ";   
  if(buttonGND.pushed()) Serial << "presionado " << ++i << " ";
  if(buttonGND.released()) Serial << "liberado\n";
  
  if(toggleSwitch.poll()) Serial << toggleSwitch.on() << endl; 
  if(toggleSwitch.longPress()) Serial << "PresionLarga1 ";
  if(toggleSwitch.longPress()) Serial << "PresionLarga2\n";
  if(toggleSwitch.doubleClick()) Serial << "double Click1 ";
  if(toggleSwitch.doubleClick()) Serial << "double Click2\n";
}

Tengo un problema aqui;

#include <Switch.h>

const byte  swEpin = 7; 
const byte  pinD = 13; 
int contador =0; 

Switch swE = Switch( swEpin, INPUT, HIGH);

Me da un error que dice no matching function for call to ´Switch::Switch(const byte &, int,int)´

??? Si le he leido... pero no entiendo bien las funciones, podrias comentarlas un poco? o poner algun ejemplo que tu tengas funcionando! Gracias.

Vaya!!!!
Ha funcionado!!!!

Muchas gracias @Surbyte...

A continuacion dejo el pequeño codigo que he usado y comentado;

#if ARDUINO >= 100      //SIN ESTAS LINEAS DE CODIGO LA LIBRERIA
  #include "Arduino.h"  //TIRA ERROR.
#else                   // AL PARECER SON MUY IMPORTANTES 
  #include "WProgram.h" // AUNQUE NI IDEA QUE HAGAM 
#endif
 
#include <Streaming.h>  //INCLUYE LA LIBRERIA, ME SUPONGO QUE ES PARA HACER
                        //ALGO COMO Serial << "longPress1 ";
#include "Switch.h"     //INCLUYE LA LIBRERIA SWITCH

const byte  swEpin = 7;  //PIN EN EL CONECTAREMOS EL SWITCH 
const byte  pinD = 13;   //PIN PARA HACER BRILLAR EL LED DEL PIN13 DE ARDUINO
int contador =0;         //VARIABLE PARA ALMACENAR EL CONTADOR 


     Switch swE        =   Switch(  swEpin,   INPUT, HIGH); //CONSTRUCTOR, QUE CREA UN OBJETO SWITCH
//     ↑     ↑                 ↑      ↑          ↑      ↑
//  FUNCION NOMBRE DEL      FUNCION  PIN DEL   ESTO ES IGUAL QUE DIGITAL
//            SWITCH                 SWITCH    DIGITAL.READ(INPUT), ENABLE PULL DOWN RESISTOR

void setup() {

  Serial.begin(9600);   
  pinMode(pinD, OUTPUT); 
}

void loop(){
swE.poll(); 
//↑ FUNCION NECESARIA PARA REFRESCAR EL ESTADO DEL BOTON. 

  if(swE.released()== HIGH){
//   ↑N.SW   ↑ ESTA FUNCION SOLO DEVUELVE HIGH CUANDO EL BOTON HA SIDO SOLTADO 
//    POR LO QUE ES PERFECTA PARA ESTE TRABAJO.
        contador= contador+1 ;
        Serial.print("Contador ="); 
        Serial.println(contador); 
        digitalWrite(pinD, HIGH); }

   
  else{
    digitalWrite(pinD, LOW); }
  
}

De momento solo necesito esta funcion, pero las demas suenan bastante bien, quizas luego comente
mas afondo lo que encuentre.

Y aqui... los resultados;

Contador =1
Contador =2
Contador =3
Contador =4
Contador =5
Contador =6
Contador =7
Contador =8
Contador =9
Contador =10
Contador =11
Contador =12
Contador =13
Contador =14
Contador =15
Contador =16

es como si hubieras usado esto

if(buttonGND.released()) Serial << "presionado " << ++i << " ";

La librería Streaming es para tener este manejo estilo C++ si no la vas a usar comentala o quitala.
Todo consume espacio sea RAM o FLASH. Cuando los programas creces después no sabes por donde quitar cosas.

Repito esto es debido a Streaming Serial << "presionado " << ++i << " ";

Las lineas precedidas por # son para el compilador .en ese caso le esta diciendo que segun la version del ide se cargue una libreria u otra.las primeras versiones del ide usan la libreria WProgram.h y las mas nuevas Arduino.h
Con esas lineas se consigue que el sketch sea compatible con todos los ide

@jose

Osea que se pueden eleminar el if... si intento a cargar una libreria u otra, y la que me funcione mejor?

Lo digo por que gustaria tener un codigo un poco mas limpio, y como ya menciono @Surbyte, tampoco necesito la libreria Streaming.h

Gracias!...
Todos los dias se aprende algo nuevo por aqui!!!

AlexLPD:
@jose

Osea que se pueden eleminar el if... si intento a cargar una libreria u otra, y la que me funcione mejor?

Lo digo por que gustaria tener un codigo un poco mas limpio, y como ya menciono @Surbyte, tampoco necesito la libreria Streaming.h

Gracias!...
Todos los dias se aprende algo nuevo por aqui!!!

Si tu ide es 1.0 o superior usa #include<Arduino.h> si es anterior #include<WProgram.h> y puedes borrar
lo demas.Si vas a subir tus sketch a alguna web o blog dejalo por si el que lo usa tiene instalado un ide anterior no le falle.

Hola surbyte seria bueno una pequeña clase
del uso de de liberia switch.

Hace mucho me ayudaste con la libreria debounce v2
hoy quisiera no molestar mucho
y solo un pequeño ejemplo en español del uso
de todas la funciones de la libreria.

En el ejemplo de creador de la libreria no entendi
lo del ButtonVCC
me gustaria una explicacion extendida
si no es mucha molestia
Se te agradece de antemano