Duda Menu Rotary Encoder y M2tklib

Hola buenas tardes compañeros, estoy intentando hacer una especie de menu con un rotary encoder, con la libreria m2tklib he mirado ejemplos pero no consigo aclararme ya que no entiendo algunas cosas.

El metodo que habia pensado era algo mas rudo o basto... se trata de que el rotary va sumando o restando de uno en uno segun se gire, a derecha o a izquierda. Hasta ahi genial, mi idea era que si se encontraba en la posicion 2 al pulsar esa cifra se multiplicaba por 10 de manera que dejaba dentro un "submenu" que tenia del 20 - 29 para mostrar otros submenus y si se volviera a pulsar pues igual, esa posicion en la que se encuentre volver a multiplicarla por 10. Para volver atras, una pulsacion (Que no se como hacerla)de unos 2/3 segundos y asi volver al submenu o menu anterior.

Bueno pues yo he conseguido que al pulsar me multiplique la posicion por 10, pero cuando vuelvo a girar en cualquier direccion sigue por donde iba, en vez de seguir de 20 a 21,22,23 por ejemplo. No se que se me escapa ahi en ese punto, por que he intentado que pos = estadoClick para que si aumenta siga por ahi la cuenta pero no me lo hace, asi que algo estoy haciendo mal. Con respecto a la pulsacion prolongada tengo una ligera idea pero no se ponerla en marcha

#include <RotaryEncoder.h>

RotaryEncoder encoder(6, 7);

#define tiempo 200

int clickRot = 3;
int estadoClick = 0;
int newPos;
long tiempocontador = 0;
static int pos = 0;

void setup()
{
  Serial.begin(9600);
  pinMode (3, INPUT_PULLUP);
  attachInterrupt(1, pulsa, FALLING);
}

void loop() 
{
  encoder.tick();
  newPos = encoder.getPosition();
  
  if (pos != newPos)
  {
    Serial.print(newPos);
    Serial.println();    
    pos = newPos;
  }
}

void pulsa()
{
  if (millis() > tiempocontador + tiempo)
  {
   estadoClick = newPos*10;
   tiempocontador = millis();
   Serial.print(estadoClick);
   Serial.println();
  }
}

Eso es todo lo que tengo, no doy con la parte de donde tengo que almacenar el estadoClick para que cuando vuelva empiece por ahi

Por otra parte tengo esto para la pulsacion larga que cogi de otro programilla que tengo por ahi

if ((time_on != 0 ) && (millis() - time_on > 3000 && bestado))      //Si el boton esta pulsado más 3 segundo activa/desactiva el parpadeo
  {
    parpadeo = !parpadeo;
    Serial.println("Led Encendido");
    time_on = 0;                                                      //Controlamos que una vez que se activa/desactiva el parpadeo no seguir comprobando
  }

(No se como ponerlo en el nuevo)

Bueno, dar las gracias a todos los que me leais y si podeis referenciarme a algo de m2tklib os lo agradeceria bastante me parece curioso. Haber si entre todos conseguimos resolver este problema y que se quede para al proximo que le pase lo mismo en el foro.
Saludos

PD: Dejo la libreria que uso

RotaryEncoder.zip (2.09 KB)

Hola Carlitos, dime con que estas compilando M2tklib, es una librería fantástica pero puedes compilarla con los IDEs actuales?

surbyte:
Hola Carlitos, dime con que estas compilando M2tklib, es una librería fantástica pero puedes compilarla con los IDEs actuales?

Estoy usando el programa de arduino en su version 1.6.13, y me da fallo en ocasiones

C:\Users\Csf28\OneDrive\Documents\Arduino\Tutorial_1_M2tklib\Tutorial_1_M2tklib.ino:3:21: fatal error: m2ghu8g.h: No such file or directory

#include "m2ghu8g.h"

ese es uno. He seguido un tutorial de referencia que viene en github para ir aprendiendo, pero es que no me aclaro...
y en el programa de arriba que me puedes decir??
No se si e contestado a tu pregunta...

Gracias por todo Surbyte

Ese es porque m2ghu8g.h no esta donde se supone debe estar que es junto a tu ejemplo o tu código.
porque esta entre comillas. Ese error es tuyo.

Lo habras tomado de un ejemplo pero no arrastraste el archivo indicado.

surbyte:
Ese es porque m2ghu8g.h no esta donde se supone debe estar que es junto a tu ejemplo o tu código.
porque esta entre comillas. Ese error es tuyo.

Lo habras tomado de un ejemplo pero no arrastraste el archivo indicado.

Bien, con ayuda y mucha insistencia he conseguido lo que pretendia inicialmente para conseguir mi fin. Se trata de que cada pulsacion del boton del rotary multiplique por 10 y si se deja pulsado mas de un segundo se divida por 10. De esta manera crear un menu con varios submenus. Dejo el codifo de lo conseguido hasta ahora

#include <RotaryEncoder.h>
#define NIVELES 2
#define buttonPin 5
#define debounceDelay 20    // the debounce time; increase if the output flickers
int maxnivel[NIVELES]={5,40};

RotaryEncoder encoder(6, 7);
int ledState = HIGH; 
unsigned long int LowTime = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  menuEncoder();
}

void menuEncoder()
{
  static long int pos = 0;
  encoder.tick();

  long int newPos = encoder.getPosition();
  if (pos != newPos) {
    Serial.print(newPos);
    Serial.println();
    pos = newPos;
  }
  int reading = digitalRead(buttonPin);
  if (reading == LOW)
  {
    delay(debounceDelay);
    LowTime = millis();
    while(!digitalRead(buttonPin));
    LowTime = millis() - LowTime;
    if (LowTime > 1000) encoder.setPosition(encoder.getPosition()/10);
    else if (LowTime > 0 && LowTime < 1000) encoder.setPosition(encoder.getPosition()*10);
    long int newPos = encoder.getPosition();
  }
}

Hasta ahi todo correcto. Ahora lo que estoy intentando es limitar el rotary y hacerlo "redundante", es decir, mi intencion es que el nivel 1 de menu vaya de 0 a 6 y que cuando sea mayor que 6 regrese al inicio, y viceversa, aundo sea menor que 0 vaya a 6. Lo he intentado y lo consigo, pero claro, si pulso el boton, como se multiplica x 10 en numero en el que me encuentre, por ejempolo el 5 pasa a ser 50 y como 50 es mayor que 6 pues lo que se muestra es un 0. Ahi no le encuentro el punto a esto. y es donde me quedo.
Gracias por tu tiempo, aun asi seguire investigando.
Saludos

Porque estas haciendo eso si creo que la librería soporta encoders y sus variantes de submenús.

Esto lo has visto? Tutorial 9: Incremental Rotary Encoder

Incluso es muy actual, del 2016, hacía tiempo que no veía actualizacion de esta librería.
Tienes mucho para estudiar me parece!!

surbyte:
Porque estas haciendo eso si creo que la librería soporta encoders y sus variantes de submenús.

Esto lo has visto? Tutorial 9: Incremental Rotary Encoder

Incluso es muy actual, del 2016, hacía tiempo que no veía actualizacion de esta librería.
Tienes mucho para estudiar me parece!!

Si lo he visto, pero como tampoco manejo mucho el tema de programacion (Se lo sencillo, en clases, objetos, punteros y eso me pierdo, estoy buscando documentacion o algunos libros del mercado para aclararme y practicar ejercicios) he preferido empezar por lo sencillo. Por eso lo de hacerlo a grandes rasgos en vez de meterme con m2tklib que me pondrea estudiar una vez que consiga este. Para lo que quiero usarlo es para mostar una serie de pantallas que hagan referencia a los datos de una estacion meteorologicapor ejemplo el 1 temperatura, dentro del 1 como se multiplica por 10, pues el 10 la del sensor dht22 y el 11 el sensor bmp280, dentro de cada uno de ellos la temperatura actual, la temperatura max la minima.

Voy a volver a mirar ese tutorial, lo unico que el rotary tenia que hacer dos click (En el mismo sentido) para que se moviese la seleccion en el menu, y por eso uso esta libreria que subi en el primer comentario.
Gracias

De todas las librerías te metiste con la peor pero también una de las mas completas. De ti depende.
Tienes herramientas para resolverlo, como te puse hay eventos y todo tipo de controles para ir de un lado a otro sin hacerlo como tu propones porque en definitiva propones una nueva forma que ya esta hecha.

Yo dejé de usarla porque no tenia actualizacion pero ahora que veo una mas o menos actual la tendré en cuenta pero no significa que miraré tu caso porque te aseguro que requiere de buen tiempo entenderla, pero una vez que lo hagas, vale la pena porque muy pocas tienen el nivel profesional de ésta.

surbyte:
De todas las librerías te metiste con la peor pero también una de las mas completas. De ti depende.
Tienes herramientas para resolverlo, como te puse hay eventos y todo tipo de controles para ir de un lado a otro sin hacerlo como tu propones porque en definitiva propones una nueva forma que ya esta hecha.

Yo dejé de usarla porque no tenia actualizacion pero ahora que veo una mas o menos actual la tendré en cuenta pero no significa que miraré tu caso porque te aseguro que requiere de buen tiempo entenderla, pero una vez que lo hagas, vale la pena porque muy pocas tienen el nivel profesional de ésta.

Hoa surbyte, te escribo de nuevo por que no consigo solucionar ese defectillo con lo del rotary encoder y no se que hacer, por que no se me ocurre otra manera ni otra libreria que usar que sea mas sencilla de usar que esta, hay parametros que no entiendo pero bueno no pasa nada. Por eso te pregunto que puedo hacer para solucionar lo del ratary. Gracias

#include <stdlib.h>		// for itoa
#include "U8glib.h"
#include "M2tk.h"
#include "utility/m2ghu8g.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);	// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)

// DOGM132, DOGM128 and DOGXL160 shield
uint8_t uiKeyUpPin = 7;         
uint8_t uiKeyDownPin = 6;
uint8_t uiKeySelectPin = 5;
uint8_t uiKeyExitPin = 5;


//=================================================
// Forward declaration of the toplevel element
M2_EXTERN_ALIGN(top_el_x2l_menu);


//=================================================
// Define three user menus, just for demonstration. 

M2_ROOT(el_mnu1_sel, "t1", "Menu 1 selected", &top_el_x2l_menu);
M2_ALIGN(top_el_mnu1_sel, "-1|1W64H64", &el_mnu1_sel);

M2_ROOT(el_mnu2_sel, "t1", "Menu 2 selected", &top_el_x2l_menu);
M2_ALIGN(top_el_mnu2_sel, "-1|1W64H64", &el_mnu2_sel);

M2_ROOT(el_mnu3_sel, "t1", "Menu 3 selected", &top_el_x2l_menu);
M2_ALIGN(top_el_mnu3_sel, "-1|1W64H64", &el_mnu3_sel);


//=================================================
uint8_t value = 0;
char buf[20];

// define callback procedure, which returns a menu entry with a value
const char *xmenu_value(uint8_t idx, uint8_t msg)
{  
  if ( msg == M2_STRLIST_MSG_GET_STR ) {
    strcpy(buf, " Value: ");
    itoa((int)value, buf+strlen(buf), 10);
    return buf;
  }
  return "";
}

// define callback procedures which increment and decrement a value
const char *xmenu_inc(uint8_t idx, uint8_t msg) {
  if ( msg == M2_STRLIST_MSG_SELECT  ) {
      value++;
  }
  return "";
}

const char *xmenu_dec(uint8_t idx, uint8_t msg) {
  if ( msg == M2_STRLIST_MSG_SELECT  ) {
      value--;
  }
  return "";
}

//=================================================
// this is the overall menu structure for the X2L Menu

m2_xmenu_entry xmenu_data[] = 
{
  { "Menu 1", NULL, NULL },		/* expandable main menu entry */
  { ".", NULL, xmenu_value },		/* The label of this menu line is returned by the callback procedure */
  { ". Inc", NULL, xmenu_inc },		/* This callback increments the value */
  { ". Dec", NULL, xmenu_dec },		/* This callback decrements the value */
  { "Menu 2", NULL, NULL },
  { ". Sub 2-1", &top_el_mnu1_sel, NULL },
  { ". Sub 2-2", &top_el_mnu2_sel, NULL},
  { ". Sub 2-3", &top_el_mnu3_sel, NULL },
  { NULL, NULL, NULL },
};

//=================================================
// This is the main menu dialog box

// The first visible line and the total number of visible lines.
// Both values are written by M2_X2LMENU and read by M2_VSB
uint8_t el_x2l_first = 0;
uint8_t el_x2l_cnt = 3;

// M2_X2LMENU definition
// Option l4 = four visible lines
// Option e15 = first column has a width of 15 pixel
// Option W43 = second column has a width of 43/64 of the display width
// Option F3 = select font 3 for the extra column (icons)

M2_X2LMENU(el_x2l_strlist, "l4e15W43F3", &el_x2l_first, &el_x2l_cnt, xmenu_data, 65,102,'\0');
M2_SPACE(el_x2l_space, "W1h1");
M2_VSB(el_x2l_vsb, "l4W2r1", &el_x2l_first, &el_x2l_cnt);
M2_LIST(list_x2l) = { &el_x2l_strlist, &el_x2l_space, &el_x2l_vsb };
M2_HLIST(el_x2l_hlist, NULL, list_x2l);
M2_ALIGN(top_el_x2l_menu, "-1|1W64H64", &el_x2l_hlist);


//=================================================
// m2 object and constructor
M2tk m2(&top_el_x2l_menu, m2_es_arduino, m2_eh_4bs, m2_gh_u8g_ffs);

//=================================================
// Draw procedure, Arduino Setup & Loop


void draw(void) {
  m2.draw();
}

void setup(void) {
  // Connect u8glib with m2tklib
  m2_SetU8g(u8g.getU8g(), m2_u8g_box_icon);

  // Assign u8g font to index 0
  m2.setFont(0, u8g_font_6x13r);

  // Assign icon font to index 3
  m2.setFont(3, u8g_font_m2icon_7);

  // Setup keys
  m2.setPin(M2_KEY_SELECT, uiKeySelectPin);
  m2.setPin(M2_KEY_PREV, uiKeyUpPin);
  m2.setPin(M2_KEY_NEXT, uiKeyDownPin);
  m2.setPin(M2_KEY_EXIT, uiKeyExitPin);    
  
  /*
  m2.setPin(M2_KEY_SELECT, 7);
  m2.setPin(M2_KEY_ROT_ENC_A, 3);
  m2.setPin(M2_KEY_ROT_ENC_B, 4);
  */
  
}

void loop() {
  // menu management
  m2.checkKey();
  if ( m2.handleKey() != 0 ) {
    u8g.firstPage();  
    do {
      m2.checkKey();
      draw();
    } while( u8g.nextPage() );
  }
}

Alguien saba como puedo solucionar lo del giro del rotary encoder??
Aparte le he echado un ojo a la libreria y no me aclaro mucho...
Gracias