Open array81 opened 6 years ago
I'm observing the same on ESP32. I thought it was my encoder, because even simple encoder test sketch shows increment or decrement by 2 instead of one. I'm waiting now for the several encoder models from Ali to test it.
what encoder driver is in use? menuIO/clickEncoderIn.h menuIO/encoderIn.h
i'm using clickEncoderIn on esp8266 also be sure to remove main loop delay used on most examples...
I use (un demo IC2) menuIO/encoderIn.h (with menuIO/clickEncoderIn.h I get error about ClickEncoder.h not found), and I have remove delay(100); from demo.
thanks for the feedback, i have an esp32 around will give it a try
@array81 missing file is from encoder driver https://github.com/0xPIT/encoder , must install it you will also have to use some esp timer, the example is using timerOne (i think) and it was not compatible with esp last time i checked... please let me know if you need esp timer setup, i have some working code
If you send me your code, you'll do me a favor. timerOne doesn't seem to work on NodeMCU.
using clickEncoder (0XPIT encoder) with esp
extern "C" {//esp8266 stuff
#include "user_interface.h"
}
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Wire.h>//oled+? bus
#include <U8g2lib.h>//oled driver
// #include <ClickEncoder.h>//from https://github.com/0xPIT/encoder
#define I2C_ADDRESS 0x3C
// #include "SSD1306Ascii.h"
// #include "SSD1306AsciiWire.h"
#include <menu.h>
// #include <menuIO/SSD1306AsciiOut.h>
#include <ClickEncoder.h>
#include <menuIO/clickEncoderIn.h>
#include <menuIO/keyIn.h>
#include <menuIO/chainStream.h>
#include <menuIO/u8g2Out.h>
using namespace Menu;
//monocrome colors
const colorDef<uint8_t> colors[]={
{{0,0},{0,1,1}},//bgColor
{{1,1},{1,0,0}},//fgColor
{{1,1},{1,0,0}},//valColor
{{1,1},{1,0,0}},//unitColor
{{0,1},{0,0,1}},//cursorColor
{{1,1},{1,0,0}},//titleColor
};
#define menuFont u8g2_font_7x13_mf
constexpr int fontX=7;
constexpr int fontY=16;
// SSD1306AsciiWire oled;
#define OLED_ROT U8G2_R2
constexpr int OLED_SDA=0;
constexpr int OLED_SDC=2;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C oled(OLED_ROT, U8X8_PIN_NONE, OLED_SDC, OLED_SDA);
#define encA 5
#define encB 4
#define encBtn 10
#define encSteps 4
ClickEncoder clickEncoder = ClickEncoder(encA,encB,encBtn,encSteps);
ClickEncoderStream encStream(clickEncoder,1);
//----------------------------------------------------------
result doAlert(eventMask e, prompt &item);
result showEvent(eventMask e,navNode& nav,prompt& item) {
Serial.print("event: ");
Serial.println(e);
return proceed;
}
int test=55;
result action1(eventMask e) {
Serial.print(e);
Serial.println(" action1 executed, proceed menu");
Serial.flush();
return proceed;
}
result action2(eventMask e,navNode& nav, prompt &item) {
Serial.print(e);
Serial.println(" action2 executed, quiting menu");
return quit;
}
int ledCtrl=LOW;
result myLedOn() {
ledCtrl=HIGH;
return proceed;
}
result myLedOff() {
ledCtrl=LOW;
return proceed;
}
TOGGLE(ledCtrl,setLed,"Led: ",doNothing,noEvent,noStyle //,doExit,enterEvent,noStyle
,VALUE("On",HIGH,doNothing,noEvent)
,VALUE("Off",LOW,doNothing,noEvent)
);
int selTest=0;
SELECT(selTest,selMenu,"Select",doNothing,noEvent,noStyle
,VALUE("Zero",0,doNothing,noEvent)
,VALUE("One",1,doNothing,noEvent)
,VALUE("Two",2,doNothing,noEvent)
);
int chooseTest=-1;
CHOOSE(chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle
,VALUE("First",1,doNothing,noEvent)
,VALUE("Second",2,doNothing,noEvent)
,VALUE("Third",3,doNothing,noEvent)
,VALUE("Last",-1,doNothing,noEvent)
);
//customizing a prompt look!
//by extending the prompt class
class altPrompt:public prompt {
public:
altPrompt(constMEM promptShadow& p):prompt(p) {}
Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t) override {
return out.printRaw("special prompt!",len);
}
};
MENU(subMenu,"Sub-Menu",showEvent,anyEvent,noStyle
,OP("Sub1",showEvent,anyEvent)
,OP("Sub2",showEvent,anyEvent)
,OP("Sub3",showEvent,anyEvent)
,altOP(altPrompt,"",showEvent,anyEvent)
,EXIT("<Back")
);
MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
,OP("Op1",action1,anyEvent)
,OP("Op2",action2,enterEvent)
,FIELD(test,"Test","%",0,100,10,1,doNothing,noEvent,wrapStyle)
,SUBMENU(subMenu)
,SUBMENU(setLed)
,OP("LED On",myLedOn,enterEvent)
,OP("LED Off",myLedOff,enterEvent)
,SUBMENU(selMenu)
,SUBMENU(chooseMenu)
,OP("Alert test",doAlert,enterEvent)
,EXIT("<Back")
);
#define MAX_DEPTH 2
constMEM panel panels[] MEMMODE{{0,0,128/fontX,64/fontY}};
navNode* nodes[sizeof(panels)/sizeof(panel)];//navNodes to store navigation status
panelsList pList(panels,nodes,1);//a list of panels and nodes
idx_t tops[MAX_DEPTH]={0,0};//store cursor positions for each level
//define outputs controller
u8g2Out outOLED(oled,colors,tops,pList,fontX,fontY,0,0,3);//,1,3);
// SSD1306AsciiOut outOLED(&oled,tops,pList);//oled output device menu driver
menuOut* outputs[]={&outOLED};//list of output devices
outputsList out(outputs,1);//outputs list
MENU_INPUTS(in,&encStream);
NAVROOT(nav,mainMenu,MAX_DEPTH,in,out);
result alert(menuOut& o,idleEvent e) {
if (e==idling) {
o.setCursor(0,0);
o.print("alert test");
o.setCursor(0,1);
o.print("press [select]");
o.setCursor(0,2);
o.print("to continue...");
}
return proceed;
}
result doAlert(eventMask e, prompt &item) {
nav.idleOn(alert);
return proceed;
}
//when menu is suspended
result idle(menuOut &o, idleEvent e) {
//o.clear();
switch(e) {
case idleStart:o.println("suspending menu!");break;
case idling:o.println("suspended...");break;
case idleEnd:o.println("resuming menu.");break;
}
return proceed;
}
//esp8266 timer
os_timer_t myTimer;
void timerCallback(void *) {clickEncoder.service();}
void setup() {
Serial.begin(115200);
while (!Serial) {
/* code */
}
Serial.println();
delay(3000);
pinMode(encBtn,INPUT_PULLUP);
while(!Serial);
Serial.println("menu 4.x test");
Serial.flush();
Wire.begin();
oled.begin();
oled.setFont(menuFont);
// oled.begin(&Adafruit128x64, I2C_ADDRESS);
// oled.setFont(System5x7);
// oled.clear();
// oled.print("Hello world!");
nav.idleTask=idle;//point a function to be used when menu is suspended
mainMenu[1].enabled=disabledStatus;
nav.showTitle=false;
//encoder timer!
os_timer_setfn(&myTimer, timerCallback, NULL);//set the callback funtion
os_timer_arm(&myTimer, 1, true);//setup the timer tick
}
void loop() {
// static uint32_t lastService = 0;
// please use timer
// if (lastService + 1000 < micros()) {
// lastService = micros();
// clickEncoder.service();
//
// }
//--------------------Menu:------------------------
constexpr int menuFPS=1000/30;
static unsigned long lastMenuFrame=-menuFPS;
unsigned long now=millis();
if (now-lastMenuFrame>=menuFPS) {
lastMenuFrame=millis();
// Serial.write('.');
Serial.print(digitalRead(encA));
Serial.print(digitalRead(encB));
Serial.println(digitalRead(encBtn));
nav.doInput();
if (nav.changed(0)||(nav.sleepTask&&nav.idleChanged)) {//gfx device [0] changed?
oled.setFont(menuFont);
oled.firstPage();
do nav.doOutput(); while(oled.nextPage());
}
}
}
I get this error:
ClickEncoder.h:18:20: fatal error: avr/io.h: No such file or directory
Where can I find AVR?
OK. I have comment this lines on ClickEncoder.h
//#include <avr/io.h> //#include <avr/interrupt.h> //#include <avr/pgmspace.h>
I can compile and upload the code and encoder NOT seems work. CW rotation works but CCW rotation NOT works besides CLICK works only sometimes.
I don't know if can help you but this demo seems works well with NodeMCU: https://arduino.stackexchange.com/questions/30012/how-to-use-a-rotary-encoder-on-nodemcu-with-arduino-code
Any news?
Sorry for close it. I have wrong.
I'd like know if there are new
sorry, not yet, been away hope to return to this soon thanks
News?
HI, no, not yet (shame :disappointed: )
Some information about problem. I hope this can help you to solve it.
I hope this can help you because I choose select a menu library for my project and I'd like choose your library but I cannot use it with this problem.
I have used ClickEncoder for my test.
This is the code used for test:
#include <Arduino.h>
/********************
Arduino generic menu system
Arduino menu on I2C LCD example
http://www.r-site.net/?at=//op%5B%40id=%273090%27%5D
Sep.2014 Rui Azevedo - ruihfazevedo(@rrob@)gmail.com
LCD library:
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home
http://playground.arduino.cc/Code/LCD3wires
LCD SCL -> D1
LCD SDA -> D2
ENCODER CLK -> D3
ENCODER DT -> D4
ENCODER SW -> D5
*/
extern "C" {
#include "user_interface.h"
}
#ifndef ARDUINO_SAM_DUE
#include <Wire.h>
#include <LiquidCrystal_I2C.h>//F. Malpartida LCD's driver
#include <menu.h>//menu macros and objects
#include <menuIO/lcdOut.h>//malpartidas lcd menu output
#include <menuIO/serialIn.h>//Serial input
#include <ClickEncoder.h>
#include <menuIO/clickEncoderIn.h>
//#include <menuIO/encoderIn.h>//quadrature encoder driver and fake stream
#include <menuIO/keyIn.h>//keyboard driver and fake stream (for the encoder button)
#include <menuIO/chainStream.h>// concatenate multiple input streams (this allows adding a button to the encoder)
using namespace Menu;
//LiquidCrystal_I2C lcd(0x27);//, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address and pinout
// Encoder /////////////////////////////////////
#define encA D3
#define encB D4
//this encoder has a button here
#define encBtn D5
//encoderIn<encA,encB> encoder;//simple quad encoder driver
//#define ENC_SENSIVITY 4
//encoderInStream<encA,encB> encStream(encoder,ENC_SENSIVITY);// simple quad encoder fake Stream
#define encSteps 4
ClickEncoder clickEncoder = ClickEncoder(encA,encB,encBtn,encSteps);
ClickEncoderStream encStream(clickEncoder,1);
//esp8266 timer
os_timer_t myTimer;
void timerCallback(void *) {clickEncoder.service();}
//a keyboard with only one key as the encoder button
keyMap encBtn_map[]={{-encBtn,defaultNavCodes[enterCmd].ch}};//negative pin numbers use internal pull-up, this is on when low
keyIn<1> encButton(encBtn_map);//1 is the number of keys
serialIn serial(Serial);
//input from the encoder + encoder button + serial
menuIn* inputsList[]={&encStream,&encButton,&serial};
chainStream<3> in(inputsList);//3 is the number of inputs
#define LEDPIN A0
result doAlert(eventMask e, prompt &item);
result showEvent(eventMask e,navNode& nav,prompt& item) {
Serial.print("event: ");
Serial.println(e);
return proceed;
}
int test=55;
result action1(eventMask e,navNode& nav, prompt &item) {
Serial.print("action1 event: ");
Serial.print(e);
Serial.println(", proceed menu");
Serial.flush();
return proceed;
}
result action2(eventMask e,navNode& nav, prompt &item) {
Serial.print("action2 event: ");
Serial.print(e);
Serial.println(", quiting menu.");
Serial.flush();
return quit;
}
int ledCtrl=LOW;
result myLedOn() {
ledCtrl=HIGH;
return proceed;
}
result myLedOff() {
ledCtrl=LOW;
return proceed;
}
TOGGLE(ledCtrl,setLed,"Led: ",doNothing,noEvent,noStyle//,doExit,enterEvent,noStyle
,VALUE("On",HIGH,doNothing,noEvent)
,VALUE("Off",LOW,doNothing,noEvent)
);
int selTest=0;
SELECT(selTest,selMenu,"Select",doNothing,noEvent,noStyle
,VALUE("Zero",0,doNothing,noEvent)
,VALUE("One",1,doNothing,noEvent)
,VALUE("Two",2,doNothing,noEvent)
);
int chooseTest=-1;
CHOOSE(chooseTest,chooseMenu,"Choose",doNothing,noEvent,noStyle
,VALUE("First",1,doNothing,noEvent)
,VALUE("Second",2,doNothing,noEvent)
,VALUE("Third",3,doNothing,noEvent)
,VALUE("Last",-1,doNothing,noEvent)
);
//customizing a prompt look!
//by extending the prompt class
class altPrompt:public prompt {
public:
altPrompt(constMEM promptShadow& p):prompt(p) {}
Used printTo(navRoot &root,bool sel,menuOut& out, idx_t idx,idx_t len,idx_t) override {
return out.printRaw(F("special prompt!"),len);;
}
};
MENU(subMenu,"Sub-Menu",showEvent,anyEvent,noStyle
,OP("Sub1",showEvent,anyEvent)
,OP("Sub2",showEvent,anyEvent)
,OP("Sub3",showEvent,anyEvent)
,altOP(altPrompt,"",showEvent,anyEvent)
,EXIT("<Back")
);
/*extern menu mainMenu;
TOGGLE((mainMenu[1].enabled),togOp,"Op 2:",doNothing,noEvent,noStyle
,VALUE("Enabled",enabledStatus,doNothing,noEvent)
,VALUE("disabled",disabledStatus,doNothing,noEvent)
);*/
char* constMEM hexDigit MEMMODE="0123456789ABCDEF";
char* constMEM hexNr[] MEMMODE={"0","x",hexDigit,hexDigit};
char buf1[]="0x11";
MENU(mainMenu,"Main menu",doNothing,noEvent,wrapStyle
,OP("Op1",action1,anyEvent)
,OP("Op2",action2,enterEvent)
//,SUBMENU(togOp)
,FIELD(test,"Test","%",0,100,10,1,doNothing,noEvent,wrapStyle)
,SUBMENU(subMenu)
,SUBMENU(setLed)
,OP("LED On",myLedOn,enterEvent)
,OP("LED Off",myLedOff,enterEvent)
,SUBMENU(selMenu)
,SUBMENU(chooseMenu)
,OP("Alert test",doAlert,enterEvent)
,EDIT("Hex",buf1,hexNr,doNothing,noEvent,noStyle)
,EXIT("<Back")
);
#define MAX_DEPTH 4
/*const panel panels[] MEMMODE={{0,0,16,2}};
navNode* nodes[sizeof(panels)/sizeof(panel)];
panelsList pList(panels,nodes,1);
idx_t tops[MAX_DEPTH];
lcdOut outLCD(&lcd,tops,pList);//output device for LCD
menuOut* constMEM outputs[] MEMMODE={&outLCD};//list of output devices
outputsList out(outputs,1);//outputs list with 2 outputs
*/
MENU_OUTPUTS(out,MAX_DEPTH
,LCD_OUT(lcd,{0,0,20,4})
,NONE
);
NAVROOT(nav,mainMenu,MAX_DEPTH,in,out);//the navigation root object
result alert(menuOut& o,idleEvent e) {
if (e==idling) {
o.setCursor(0,0);
o.print("alert test");
o.setCursor(0,1);
o.print("[select] to continue...");
}
return proceed;
}
result doAlert(eventMask e, prompt &item) {
nav.idleOn(alert);
return proceed;
}
result idle(menuOut& o,idleEvent e) {
switch(e) {
case idleStart:o.print("suspending menu!");break;
case idling:o.print("suspended...");break;
case idleEnd:o.print("resuming menu.");break;
}
return proceed;
}
void setup() {
pinMode(encBtn,INPUT_PULLUP);
pinMode(LEDPIN,OUTPUT);
Serial.begin(115200);
while(!Serial);
Serial.println("Arduino Menu Library");Serial.flush();
//encoder.begin();
lcd.begin(20,4);
nav.idleTask=idle;//point a function to be used when menu is suspended
mainMenu[1].enabled=disabledStatus;
nav.showTitle=false;
lcd.setCursor(0, 0);
lcd.print("Menu 4.x LCD");
lcd.setCursor(0, 1);
lcd.print("r-site.net");
delay(2000);
//encoder timer!
os_timer_setfn(&myTimer, timerCallback, NULL);//set the callback funtion
os_timer_arm(&myTimer, 1, true);//setup the timer tick
}
void loop() {
nav.poll();
digitalWrite(LEDPIN, ledCtrl);
//delay(100);//simulate a delay as if other tasks are running
}
#endif
Hi @array81 I noticed your encoder signals are like this:
ENCODER CLK -> D3 ??? ENCODER DT -> D4 ??? ENCODER SW -> D5
So what kind of encoder device you are using? The library (I believe) expects simply de-phased square pulses at both encoder inputs A and B: Clockwise turns А:__П_П_П B: __П_П_П Counter Clockwise turns А: __П_П_П B:__П_П_П
Also, you may need to add pull-up resistors.
What your encoder' CLK and DT signals look like?
hi! I'm using an quad-encoder with 1 button, so 2 pins are for encoder (out of phase as mentioned) and another for the button, there together for convenience but the driver for encoder is independent from the button, if using the internal encoder driver. However there is an alternative driver, click-encoder that can also be used.
internal encoder driver, uses PCINT library to handle pin-change interrupts, can use all atmega pins... but might not go well with all mcus.
click-encoder driver uses a timer to handle the encoder
Hi, I'm using a KY-040, please see here for details: http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/
These are the connections on NodeMCU: ENCODER CLK -> D3 ENCODER DT -> D4 ENCODER SW -> D5
These are the connections on Arduino Nano: ENCODER CLK -> D2 ENCODER DT -> D3 ENCODER SW -> D4
As said with Arduino it works correctly but with NodeMCU there are many problems:
Hi @neu-rah First, thank you for the great piece of work - the ArduinoMenu!
Yes I understood the driver difference. My only point was to check the hardware. ESP8266 has few IO pins, some are used for programming, some have pull-ups or not, depending of the board. If both encoder signals are not well formed (example missing pull-up) - it may cause inconsistency.
I am not very clear of the situation - is your (@neu-rah ) setup working as expected and only @array81 experiences problems or the issue was found by both of you ?
@array81 Hi, I think NodeMCU D5 (GPIO14) has no pull-up resistor on board.
I am not very clear of the situation - is your (@neu-rah ) setup working as expected and only @array81 experiences problems or the issue was found by both of you ?
I think @neu-rah don't have a NodeMCU so he did not test.
Hi, I think NodeMCU D5 (GPIO14) has no pull-up resistor on board.
In this moment I cannot show the image (I'm not at home). But if you're right I should change pin then test it.
I'm using clickencoder (timer driven) for mcu and internal from atmegas, and yes i didn't gave a try for internal driver on mcu (yet) :smile: thanks for the interest, there is also the chat room about ArduinoMenu https://gitter.im/ArduinoMenu/Lobby
Hi, I managed to run the example by timer-driven ClickEncoder on NodeMCU. You need a good rotary encoder and make sure pull-up resistors present on your board or externally on encA, encB and button lines.
See this for ESP8266 HW quick reference: https://tttapa.github.io/ESP8266/Chap04%20-%20Microcontroller.html
My encoder was old and inconsistent and finally broke so I had to build and encoder from mouse wheel to finish my tests :) I observed a button reaction delay when using ClickEncoder library for it. Better to use the separate "keyboard" alternative with one key for button. (clickencoder only for +/- UP/DOWN functionality)
So ... here are the hints for ESP8266 timer:
// add this at beginning
extern "C" {
#include "user_interface.h"
}
...
// create timer and callback
os_timer_t myTimer;
void timerCallback(void *)
{
clickEncoder.service();
}
...
void setup() {
...
//initialize & run the Timer
os_timer_setfn(&myTimer, timerCallback, NULL);//set the callback function for the encoder
os_timer_arm(&myTimer, 2, true);//setup the timer tick to call it every 2 ms
//clickEncoder.setAccelerationEnabled(true);
So ... here are the hints for ESP8266 timer: I don't understand, with this hints and pull-up resistors it should work on NodeMCU?
I'll have a few tests as soon as possible, these days I do not have much time unfortunately.
@array81 Hi Martin, Yes, with these hints, pull-ups and good encoder NodeMCU runs smooth with code based on U8G2.ino Here are the pins of my test, in (L/H) are the levels required by NodeMCU to boot properly: I have *4 x free DIO pins 3V logic remaining to use to control my external devices + one analog A0 input. RX and TX are reserved for serial and programming, but it can be used too (with caution).
D0 (L) has a pull-down on NodeMCU PCB D1 SCL of SSD1306 128x64 I2C OLED D2 SDA of SSD1306 128x64 I2C OLED D3 (H) has a pull-up on NodeMCU PCB D4 (H) enc SW has a pull-up on NodeMCU PCB D5 D6 encA I added external 10k pull-up D7 encB I added external 10k pull-up D8 has pull-down on NodeMCU PCB D9 (RX) D10 (TX) *A0 analog input
I have try to use you suggestion on IC2 (see post 9 Nov) so I have change pin and add pull-up (timer code is just ok) but the result is the same counterclockwise works always but clockwise and click button no. I am sincerely thinking of abandoning NodeMCU, my problem is Arduino Nano have very small memory and using ArduinoMenu little space remains.
you can use code driven menu, by handling the encoder with the driver of your choice and issuing menu commands to the navigation root. I've been using wemos D1 mini with clickencoder quite well... and yes atmegas are short on memory when using the menu, even reducing numeric field to be all of the same time (ie: int)
note: every usage of field with a different type instantiates the fields code for that type (or part of them).
I have the same issue on the ESP32 and the rotary encoder (https://www.az-delivery.de/products/drehimpulsgeber-modul?ls=de) which has pullup resistors preinstalled.
@Ulli2k what driver are you using? the internal driver (using interrupts) or the clickEncoder driver (using timer)
also make sure that internal MCU pull-ups are not messing the signals and that pins are ok, swaping an encoder pin with the button pins will have undesirable results
I've used clickencoder with esp8266, let me know if you need help setting up the timer.
the internal driver does not do software debounce, so it should be used with hw debounce (a couple of small capacitors between the encoder pins and ground)
Hello, @neu-rah how did you manage to use ClickEncoder on ESP8622? Fails to compile for me because I lack the /avr/* includes in this lib. I commented them and could compile and upload my sketch (adapted TFT_eSPI example), but the encoder seams not to work. I use the ESP8622-timer like array81 and lorol suggested above and a KY-040 encoder. I have to use different pins (D6/D1 for the encoder, D4 for the button) because of the TFT display and D2 and D0 will be consumed by other hardware in my project.
I forgot to say -- I use a WEMOS D1 mini, so I name the pins in my sketch the way above -- they are the GPIOs 12/5 for the encoder and 2 for the button.
@orlo11 just comment out or delete those lines, the functionality is already included on esp8266
Same issue with my ESP32 WROOM(The button work but both CW and CCW are jumping around or sometimes, simply no action) and on Arduino MEGA it works. It try another library and the encoder work fine: https://github.com/igorantolic/ai-esp32-rotary-encoder on my ESP32. So I guess, it's software issue.
Any suggestion or how to integrate ai-esp32 library into this library?
yes, you can check your encoder state and issue menu commands as required, see the codectrl example here https://github.com/neu-rah/ArduinoMenu/blob/master/examples/codeCtrl/codeCtrl/codeCtrl.ino#L168
ok, this codeCtrl sample works, but it is only one direction CW and its library is different from the LCD i2c sample. so how can i merge it with the crystal lcd i2c sample? thanks
code control allows any input, you must handle your input and do your encoder reading and decide what menu command to call
here is an enumeration of commands: https://github.com/neu-rah/ArduinoMenu/blob/master/src/menuBase.h#L89
Sorry, I am new to this thing.
Since codeCtrl have only 1 directional button and a click button, i add another NAV_BTN2 which point to another PIN. but it always call the NAV_BTN for both up and down rotation.
Please note that I use rotary encoder.
(!digitalRead(SEL_BTN)) {
delay(SOFT_DEBOUNCE_MS);
while(!digitalRead(SEL_BTN));
nav.doNav(enterCmd);
delay(SOFT_DEBOUNCE_MS);
}
if (!digitalRead(NAV_BTN)) {
delay(SOFT_DEBOUNCE_MS);
while(!digitalRead(NAV_BTN));//wait for button release
nav.doNav(upCmd);
delay(SOFT_DEBOUNCE_MS);
Serial.println("UP");
}
/**I add this this function and bind it to another PIN of my rotary encoder**/
if (!digitalRead(NAV_BTN2)) {
delay(SOFT_DEBOUNCE_MS);
while(!digitalRead(NAV_BTN2));//wait for button release
nav.doNav(downCmd);
delay(SOFT_DEBOUNCE_MS);
Serial.println("DOWN");
}
here is the wiki section about it. https://github.com/neu-rah/ArduinoMenu/wiki/Navigation#enum-navcmds
when using commands the menu system wont read you encoder and you should NOT configure the encoder as an input. you must read the encoder using its own drive and issue menu commands to the nav root according to you encoder readings... so you will be 100% responsible for the relation between the encoder and the menu.
the code section you pasted above is just a demo using software debounce on some pins. Because the menu key driver has no debounce we are reading the pins and doing the debounce and eventually send menu commands to do some menu action.
the thing is i cannot find any working rotary encoder driver that work with my esp32 from your sample yet.
this git work https://github.com/igorantolic/ai-esp32-rotary-encoder but i have no idea how to integrate with your menu
if you have any encoder driver that work without the menu, then you can use a menu (without input) and read your working driver then issue menu commands to your intended encoder action.
I have a low accuracy for encoder button when use NodeMCU. On Arduino Nano it work well but on NodeMCU (same configuration: LCD, encoder) when rotate the encoder sometimes I get the right result for example the cursor is moved to next o before item but sometimes the cursor is moved to many items. Click button works well.