soligen2010 / encoder Goto Github PK
View Code? Open in Web Editor NEWThis project forked from 0xpit/encoder
Atmel AVR C++ RotaryEncoder Implementation
This project forked from 0xpit/encoder
Atmel AVR C++ RotaryEncoder Implementation
Hi, just testing your library on a ESP32 using your ESP8266Example.
The encoder itself seems to work well, and responsive. However it takes a fairly long time before I get a "Button: ClickEncoder::Clicked" message. Im guessing on the order of ~500ms or so, too long for responsive menu's. I tried changing ENC_BUTTONINTERVAL , but that seems to make no difference?
Also, Im a little confused about the difference between ClickEncoder::Pressed and ClickEncoder::Clicked. The former never seems to trigger?
thanks!
I've tried two different encoders, one being an Alps and the other a Panasonic. They both "sort of" work. Right now the Panasonic works nearly correct in one direction, but when turning in the other it only bounces between two values. Have tried various permutation of wiring and code changes.
Would like to know try encoders were tested with the library and go from there.
I'm using this fork of ClickEncoder to read from two encoders/buttons. After extensive tests, I'm still having trouble reading clicks of the 2nd encoder (I'm calling it "2nd" because it is the second instantiation). A test program shows I can get accurate and expected results (encoders register 1 increment for each click, and button clicks--double-clicked, held, released, etc.--return their expected values) when both encoders are handled in the loop() function.
In my actual application, the 1st encoder/button works perfectly as expected (in loop()), and the button of the 2nd encoder/button also works as expected--to call another function which I will use for a menu. Once inside that menu function, however, I cannot get the 2nd rotary to encode reliably. Sometimes a single indent will properly be registered, sometimes not. If it's turned several indents at a time, it will sometimes register, but only if I turn fast enough. Thinking it may be the problem, I've disabled acceleration for both encoder/buttons (I don't want it anyway). That has not solved the problem. By the way, the button of the 2nd encoder/button does work as expected to exit the menu function with a press-and-release (that is, the menu function closes when it receives the "release" code (4) is returned.
Because of the erratic behavior, I'm guessing there may be an issue with the timer-based interrupt, but I'm not knowledgeable enough in the library to know--and certainly not enough to fix it. Is anyone else aware of 1) problems related to use of ClickEncoder in separate functions, and 2) what can be done about them?
Thanks!
Hey there!
This is my favorite encoder library so far but it's driving me crazy ๐คฆ
Even though I'm quite new to all of this, I believe to understand the logic behind that library but still struggle to implement...
I am trying to read the time the button is held. My approach so far is to get the millis() when the button is pressed and released, to calculate the "button hold" time.
Problem seems to be that I don't understand where to grab the two millis() values.
millisReleased is read in case ClickEncoder::Released:
and it works so far.
But for millisPressed I'm lost ๐ wherever I try to read, it doesn't make any sense since it's constantly setting millisPressed to the current millis(), not the first time the button was pressed.
Hope that makes some sense ๐
If not, maybe this explains it...
When holding the button down I get something like this nonsense:
- Button: 3 held
millisPressed: 7174
- Button: 3 held
millisPressed: 7213
- Button: 4 released
millisReleased: 7246
- time held = 33
millisPressed is updated while the button is pressed, but I need to get the "timestamp" when it is first pressed and ignore the rest.
I'm starting to think that I did not understand what I'm doing...
If anyone could shove me in the right direction, this project might have an end ๐
maybe not really relevant but here's the whole sketch:
#include <ClickEncoder.h>
#include <TimerOne.h>
int16_t oldEncPos, encPos;
uint8_t buttonState;
uint8_t lastButtonState;
#define pinA 3
#define pinB 2
#define pinSw 4 //switch
#define STEPS 4
unsigned long millisPressed;
unsigned long millisReleased;
ClickEncoder encoder(pinA, pinB, pinSw, STEPS);
void setup() {
Serial.begin(9600);
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);
encoder.setAccelerationEnabled(true);
Serial.print("Acceleration is ");
Serial.println((encoder.getAccelerationEnabled()) ? "enabled" : "disabled");
oldEncPos = -1;
}
void loop() {
encPos += encoder.getValue();
if (encPos != oldEncPos) {
oldEncPos = encPos;
Serial.print("Encoder Value: ");
Serial.println(encPos);
}
buttonState = encoder.getButton();
if (buttonState != 0) {
// if (buttonState != lastButtonState) {
// millisPressed = millis();
// lastButtonState = buttonState;
// }
Serial.print("Button: "); Serial.println(buttonState);
switch (buttonState) {
case ClickEncoder::Open: //0
break;
case ClickEncoder::Closed: //1
break;
case ClickEncoder::Pressed: //2
break;
case ClickEncoder::Held: //3
Serial.println("held");
millisPressed = millis();
Serial.print("millisPressed: "); Serial.println(millisPressed);
break;
case ClickEncoder::Released: //4
millisReleased = millis();
Serial.print("millisReleased: "); Serial.println(millisReleased);
Serial.print("time held = "); Serial.println(millisReleased - millisPressed);
break;
case ClickEncoder::Clicked: //5
break;
case ClickEncoder::DoubleClicked: //6
break;
}
}
}
void timerIsr() {
encoder.service();
}
Hello,
and thanks for this fork (I was using the main github repository and - successfully - hacked the library in order to get it to work with STM32duino, until I discovered your fork...). Very bad referencement !
There's a problem I'd like to solve. To figure out, turn the encoder quickly, CW and CCW, and then click it. You will see a couple of "turn events" before the "click" event is taken into account. This is really annoying for menus !
I read this thread : https://www.mikrocontroller.net/articles/Drehgeber (with Google translate) ; it seems the encoder stops on an "unstable" position between 2 notches or not really on a steady one, and issues some events while clicking (I get up to 2 or 3 events).
These tests were done with debounced contacts : RC + Schmitt triggers, tested and validated (too large RC can kill the Gray code, spent some time on this !)
Before I reinvent the wheel, is there a software solution to this issue, already integrated in the library (I can't see it...)
Otherwise, I was thinking of an "event queue" (ring buffer), with timestamps, and a getButton() function discarding the very new "rotate" envents. But this could'nt work in interrupts routines : no micros() ! (on my side I prefer interrupts than "spaghetti coding" in the loop function)
Some thoughts ?
(sorry for my bad english)
Hi,
i have a strange behavior with my Rotary Encoders. I used two different types, to be sure. But both show the same:
Setup:
I can rotate left or right, it has the same effect:
The Logic Analyser looks ok, or at least sufficient.
But the output of the Serial Monitor is
Mon Oct 14 13:49:05 (master)> platformio.exe device monitor
Miniterm on COM4 115200,8,N,1
Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Encoder Value: 0
Encoder Value: -1
Encoder Value: 0
Encoder Value: -1
Encoder Value: 0
Encoder Value: -1
Encoder Value: 0
Encoder Value: -1
Encoder Value: 0
Encoder Value: -1
Encoder Value: 0
Encoder Value: -1
and the Code of the Arduino is your example:
using ENC_HALFSTEP or ENC_DECODER makes no difference.
#include <ClickEncoder.h>
#include <TimerOne.h>
ClickEncoder *encoder;
int16_t last, value;
#define ENCODER_PIN_A 5
#define ENCODER_PIN_B 6
#define WITHOUT_BUTTON 1
/* #define ENCODER_PUSH_BUTTON A3 */
#define ENC_HALFSTEP 1
void timerIsr() {
encoder->service();
}
void setup() {
Serial.begin(115200);
/* encoder = new ClickEncoder(ENCODER_PIN_A, ENCODER_PIN_B, ENCODER_PUSH_BUTTON,1); */
encoder = new ClickEncoder(ENCODER_PIN_A, ENCODER_PIN_B,-1);
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);
last = -1;
}
void loop() {
value += encoder->getValue();
if (value != last) {
last = value;
Serial.print("Encoder Value: ");
Serial.println(value);
}
ClickEncoder::Button b = encoder->getButton();
if (b != ClickEncoder::Open) {
Serial.print("Button: ");
#define VERBOSECASE(label) case label: Serial.println(#label); break;
switch (b) {
VERBOSECASE(ClickEncoder::Pressed);
VERBOSECASE(ClickEncoder::Held)
VERBOSECASE(ClickEncoder::Released)
VERBOSECASE(ClickEncoder::Clicked)
case ClickEncoder::DoubleClicked:
Serial.println("ClickEncoder::DoubleClicked");
encoder->setAccelerationEnabled(!encoder->getAccelerationEnabled());
Serial.print(" Acceleration is ");
Serial.println((encoder->getAccelerationEnabled()) ? "enabled" : "disabled");
break;
}
}
}
Build Process looks OK, here the Output to verify the Version Numbers. (Windows Workstation)
Mon Oct 14 13:48:19 (master)> platformio run -e uno --target upload
Processing uno (platform: atmelavr; board: nanoatmega328; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/nanoatmega328.html
PLATFORM: Atmel AVR 1.15.0 > Arduino Nano ATmega328
HARDWARE: ATMEGA328P 16MHz, 2KB RAM, 30KB Flash
PACKAGES: toolchain-atmelavr 1.50400.190710 (5.4.0), framework-arduinoavr 4.1.2, tool-avrdude 1.60300.190424 (6.3.0)
Converting encoder.ino
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 11 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <ClickEncoder>
|-- <TimerOne>
Compiling .pio\build\uno\src\encoder.ino.cpp.o
C:/Users/Marco/work/TonUINO/src/encoder.ino: In function 'void loop()':
C:/Users/Marco/work/TonUINO/src/encoder.ino:40:12: warning: enumeration value 'Open' not handled in switch [-Wswitch]
switch (b) {
^
C:/Users/Marco/work/TonUINO/src/encoder.ino:40:12: warning: enumeration value 'Closed' not handled in switch [-Wswitch]
Linking .pio\build\uno\firmware.elf
Checking size .pio\build\uno\firmware.elf
Building .pio\build\uno\firmware.hex
Memory Usage -> http://bit.ly/pio-memory-usage
DATA: [== ] 18.6% (used 380 bytes from 2048 bytes)
PROGRAM: [= ] 13.6% (used 4174 bytes from 30720 bytes)
Configuring upload protocol...
AVAILABLE: arduino
CURRENT: upload_protocol = arduino
Looking for upload port...
Use manually specified: COM4
Uploading .pio\build\uno\firmware.hex
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file ".pio\build\uno\firmware.hex"
avrdude: writing flash (4174 bytes):
Writing | ################################################## | 100% 1.19s
avrdude: 4174 bytes of flash written
avrdude: verifying flash memory against .pio\build\uno\firmware.hex:
avrdude: load data flash data from input file .pio\build\uno\firmware.hex:
avrdude: input file .pio\build\uno\firmware.hex contains 4174 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.91s
avrdude: verifying ...
avrdude: 4174 bytes of flash verified
avrdude: safemode: Fuses OK (E:00, H:00, L:00)
avrdude done. Thank you.
=============================================================== [SUCCESS] Took 8.94 seconds ===============================================================
If you need more Information, please do not hesitate to drop me a mail.
I've run out of ideas of troubleshooting.
I will appreciate your help with this situation.
Cheers, bye
Marco
In some occasions, it is necessary to prohibit response to encoder rotation, and only allow buttons. Is there a way to achieve it?
To be recognised by Arduino IDE, the library needs a library.properties file, much like library.json for platformio.
The recommended structure for the library (for both arduino and pio) is to put the source files in a "src" sub-folder.
I have no idea how to fix this or what it means, never seen this compiler error before.
Esp32, platformio
tried disabling with build flags and it didn't work.
??
cc1: warning: command line option '-Wno-reorder' is valid for C++/ObjC++ but not for C
^
In file included from /Users/shawn/projects/microcontrollers/dev/libraries/encoder/ClickEncoder.cpp:12:0:
/Users/shawn/projects/microcontrollers/dev/libraries/encoder/ClickEncoder.h: In constructor 'ClickEncoder::ClickEncoder(int8_t, int8_t, int8_t, uint8_t, bool)':
/Users/shawn/projects/microcontrollers/dev/libraries/encoder/ClickEncoder.h:88:8: error: 'ClickEncoder::buttonHeldEnabled' will be initialized after [-Werror=reorder]
bool buttonHeldEnabled;
^
/Users/shawn/projects/microcontrollers/dev/libraries/encoder/ClickEncoder.h:81:8: error: 'bool ClickEncoder::accelerationEnabled' [-Werror=reorder]
bool accelerationEnabled;
^
/Users/shawn/projects/microcontrollers/dev/libraries/encoder/ClickEncoder.cpp:44:1: error: when initialized here [-Werror=reorder]
ClickEncoder::ClickEncoder(int8_t A, int8_t B, int8_t BTN, uint8_t stepsPerNotch, bool active)
^
Hey,
If I run the example, the values don't change at all and button presses are not detected.
The strange thing is that everything works perfect if I add #define WITHOUT_BUTTON 1 to the start.
Obviously the button does not work then, whats going on? how can I get the button to work also.
Thanks.
I have a rotatory encoder with pushbutton. I am using this library to read the values from the encoder. Each time I move the encoder one indent, 4 events get triggered advancing the counter by 4. Not sure if this is normal or my encoder is different than the usual expected behavior. I have tried adding #define ENC_DECODER (1 << 2) before including the .h file. I have also tried #define ENC_HALFSTEP with different values with 2 or 3 events getting triggered instead. When I set the 4th parameter of the constructor to 2, only 2 events get triggered but if I change it to the default of 1, 3 events get triggered.
Is there a problem with my encoder? Is there a way to ensure that only one event is triggered per encoder indent so that it only advances the position counter by 1 per indent?
Thanks for any help!
Hi Guys and Gals,
I am trying to 'squeeze' this onto a Arduino Nano (limited variable space) along with all the other code...
is there any way of calling just the rotary acceleration via an interrupt then the <TimerOne.h>
would not be needed?
Encoder pinA = connected to = Arduino pin3 (being an interrupt pin)
Encoder pinB = connected to = Arduino pin4
const byte pinA = 3; // Pin on encoder, CLK
const byte pinB = 4; // Pin on encoder, DT
void setup(){
// Encoder setup
pinMode(pinA, INPUT);
pinMode(pinB, INPUT);
attachInterrupt(digitalPinToInterrupt(pinA), InterruptEncoder, LOW); // Attach the routine to service the interrupts
...
}
void InterruptEncoder(){ // Encoder interrupt
???
}
this code is currently working great but takes an age to wind to the top/bottom of the scale, enter acceleration...
Thanks
The example for the esp doesnt use a timer interrupt because of the potential interference with wifi; the AVR example does, but doesnt compile on ESP because the timer library seems incompatible.
Thing is, I dont need wifi, but I do need a timer interrupt because the graphics library Im using is blocking. If anyone could provide me with an example how to use encoder.h with a timer interrupt on ESP, I would be most grateful.
Hi,
I've been using your fork in an Adafruit Huzzah ESP8266 with a rotary encoder and it has been working fine so far. But I noticed that the rotary encoder stops responding after a while...
Looking at the code, I think the problem is in this section from the loop function:
static uint32_t lastService = 0;
if (lastService + 1000 < micros()) {
lastService = micros();
encoder.service();
}
At some point, micros() will overflow (after 70 minutes or so) and then start over again. At that point lastService + 1000 is always going to be greater than micros(), so encoder.service() will not be called anymore.
I modified my code using the following:
if (micros() < encoderLastService) { // micros() has gone back to zero
encoderLastService = micros();
} else if (micros() > (encoderLastService + 1000)) { // Update only once every 1 ms
encoderLastService = micros();
encoder.service();
}
It seems to work for now!
Oscar.
Hi. Thanks for fixing the lib. I use the original a lot on Arduino but now are starting with ESP8266 and 32.
I have hooked up the encoder. It does pick up the click but does not see the encode values/ I can see a led flash on the ESP8266 when I turn the encoder but the value stays 0.
The click is also missed sometimes.
Here is the code. What am I doing wrong ?
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <RunningMedian.h>
#include <SHT1x.h>
#include<CountUpDownTimer.h>
#include <Adafruit_SSD1306.h>
#include <ClickEncoder.h>
#define ENCODER_PINA 16 //D0
#define ENCODER_PINB 12 //D6
#define ENCODER_BTN 0 //D3
#define ENCODER_STEPS_PER_NOTCH 4 // Change this depending on which encoder is used
ClickEncoder encoder = ClickEncoder(ENCODER_PINA,ENCODER_PINB,ENCODER_BTN,ENCODER_STEPS_PER_NOTCH);
static int16_t last, value;
#define OLED_RESET LED_BUILTIN //4
Adafruit_SSD1306 display(OLED_RESET);
// Specify data and clock connections and instantiate SHT1x object
#define dataPin 2
#define clockPin 14
SHT1x sht1x(dataPin, clockPin);
float temp_c , wbt;
float humidity;
char payload[8];
String send_data;
char attributes[100];
CountUpDownTimer sensor_timer(UP, HIGH);
CountUpDownTimer send_data_timer(UP, HIGH);
#define TOKEN "123"
const char* ssid = "Pandora-LR";
const char* password = "123";
const char* mqtt_server = "demo.thingsboard.io";
const char* esp_hostname = "esptest";
// Static IP's
IPAddress arduino_ip ( 10, 64, 9, 229);
IPAddress dns_ip ( 10, 64, 9, 20);
IPAddress gateway_ip ( 10, 64, 9, 20);
IPAddress subnet_mask(255, 255, 255, 0);
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
const char* outTopic = "espout";
const char* inTopic = "espin";
//d7 (13) en d8 (15) is ok op reboot.
int feeder_relay_pin = 15;
int stoker_relay_pin = 13;
bool relayState = LOW;
// RH Smoothing vars
RunningMedian s_rh = RunningMedian(10); //Smooth RH probe 1
RunningMedian s_temp = RunningMedian(10); //Smooth Stoker Temp probe 1
//RH Constants
float svp_0 = 610.7; // saturated vapour pressure [Pa], water, at 0 Celcius
float aa = 7.5;
float bb = 237.3; // [K]
float Gamma = 66; // [Pa/K]
void setup_wifi() {
delay(10);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.println("Connecting to ");
display.println(ssid);
display.display();
while (WiFi.status() != WL_CONNECTED) {
for (int i = 0; i < 500; i++) {
delay(1);
}
Serial.print(".");
display.print(".");
display.display();
}
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.hostname(esp_hostname);
WiFi.config(arduino_ip, gateway_ip, subnet_mask);
WiFi.begin(ssid, password);
display.println("WiFi connected");
display.display();
//delay(10000);
}
void on_message(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '0') {
digitalWrite(feeder_relay_pin, LOW); // Turn the LED on (Note that LOW is the voltage level
Serial.println("relay_pin -> LOW");
client.publish(outTopic, "OFF");
digitalWrite(2, HIGH);
relayState = LOW;
//EEPROM.write(0, relayState); // Write state to EEPROM
//EEPROM.commit();
} else if ((char)payload[0] == '1') {
digitalWrite(feeder_relay_pin, HIGH); // Turn the LED off by making the voltage HIGH
Serial.println("ON");
client.publish(outTopic, "ON");
digitalWrite(2, LOW);
relayState = HIGH;
delay(3500);
digitalWrite(feeder_relay_pin, LOW);
client.publish(outTopic, "OFF");
digitalWrite(2, HIGH);
} else if ((char)payload[0] == '2') {
relayState = !relayState;
digitalWrite(feeder_relay_pin, relayState); // Turn the LED off by making the voltage HIGH
digitalWrite(2, !relayState);
Serial.print("relay_pin -> switched to ");
client.publish(outTopic, "relay_pin -> switched to");
Serial.println(relayState);
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Connecting to ThingsBoard node ...");
// Attempt to connect (clientId, username, password)
if ( client.connect("ESP8266Client", TOKEN, NULL) ) {
Serial.println( "[DONE]" );
} else {
Serial.print( "[FAILED] [ rc = " );
Serial.print( client.state() );
Serial.println( " : retrying in 5 seconds]" );
// Wait 5 seconds before retrying
delay( 5000 );
}
}
}
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("RH Control");
display.display();
delay(1000);
pinMode(feeder_relay_pin, OUTPUT); // Initialize the relay pin as an output
pinMode(stoker_relay_pin, OUTPUT); // Initialize the relay pin as an output
pinMode(16, INPUT);
pinMode(12, INPUT);
pinMode(0, INPUT);
encoder.setButtonHeldEnabled(true);
encoder.setDoubleClickEnabled(true);
// Enable the button to be on pin 0. Normally pin 0 is not recognized as a valid pin for a button,
// this is to maintain backward compatibility with an old version of the library
// This version can have the button on pin zero, and this call enables the feature.
// in this version best to use pin -1 instead of 0 to disable button functions
encoder.setButtonOnPinZeroEnabled(true);
Serial.begin(115200);
setup_wifi(); // Connect to wifi
client.setServer(mqtt_server, 1883);
client.setCallback(on_message);
sensor_timer.StartTimer();
send_data_timer.StartTimer();
}
void loop() {
sensor_timer.Timer();
send_data_timer.Timer();
if (!client.connected()) {
reconnect();
}
client.loop();
if (sensor_timer.TimeHasChanged() ) // this prevents the time from being constantly shown.
{
if(sensor_timer.ShowSeconds() >= 2) {
//digitalWrite(2, HIGH);
// Read values from the sensor
humidity = sht1x.readHumidity();
temp_c = sht1x.retrieveTemperatureC();
if(temp_c <= 0){
humidity = sht1x.readHumidity();
temp_c = sht1x.retrieveTemperatureC();
}
s_rh.add(humidity);
humidity = s_rh.getMedian();
s_temp.add(temp_c);
temp_c = s_temp.getMedian();
//Calculate the Wet Bulb
wbt = CalcWetBulb(temp_c , humidity);
Serial.print("RH :");
Serial.println(humidity , 2);
Serial.print("Temp :");
Serial.println(temp_c , 2);
Serial.print("Wet Bulb :");
Serial.println(wbt , 2);
sensor_timer.ResetTimer();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("RH % :" + String(humidity));
display.setCursor(0,10);
display.print("DB Temp :" + String(temp_c));
display.setCursor(0,20);
display.print("WB Temp :" + String(wbt));
display.display();
//digitalWrite(2, LOW);
}
}
//Send the data every 20 seconds
if(send_data_timer.ShowSeconds() >= 20) {
//Send all the values via MQTT
// Prepare a JSON payload string
String payload1 = "{";
payload1 += "\"temperature\":"; payload1 += temp_c; payload1 += ",";
payload1 += "\"humidity\":"; payload1+= humidity; payload1 += ",";
payload1 += "\"wbt\":"; payload1+= wbt;
payload1 += "}";
// Send payload
char attributes1[100];
payload1.toCharArray( attributes1, 100 );
client.publish( "v1/devices/me/telemetry", attributes1 );
Serial.println( attributes1 );
send_data_timer.ResetTimer();
}
//Switch the relay
if(wbt <= 18){
digitalWrite(feeder_relay_pin, HIGH);
digitalWrite(stoker_relay_pin, HIGH);
//client.publish(outTopic, "ON");
}
else{
digitalWrite(feeder_relay_pin, LOW);
digitalWrite(stoker_relay_pin, LOW);
//client.publish(outTopic, "OFF");
}
//Encoder Code
//Call Service in loop becasue using timer interrupts may affect ESP8266 WIFI
//however call no more than 1 time per millisecond to reduce encoder bounce
static uint32_t lastService = 0;
if (lastService + 1000 < micros()) {
lastService = micros();
encoder.service();
}
value += encoder.getValue();
if (value != last) {
last = value;
Serial.print("Encoder Value: ");
Serial.println(value);
display.setCursor(0,30);
display.print("Value :" + String(value));
display.display();
}
ClickEncoder::Button b = encoder.getButton();
if (b != ClickEncoder::Open) {
Serial.print("Button: ");
#define VERBOSECASE(label) case label: Serial.println(#label); break;
switch (b) {
VERBOSECASE(ClickEncoder::Pressed);
VERBOSECASE(ClickEncoder::Held)
VERBOSECASE(ClickEncoder::Released)
VERBOSECASE(ClickEncoder::Clicked)
VERBOSECASE(ClickEncoder::DoubleClicked)
}
}
}
//Calculate the wet bulb temperature
float CalcWetBulb(float DB , float RH){
float Tw;
Tw = DB * atan(0.151977 * sqrt(RH + 8.313659))
+ atan(DB + RH) - atan(RH - 1.676331)
+ 0.00391838 * pow(RH , 3./2.) * atan(0.023101 * RH)
- 4.686035;
return Tw;
}
// calc saturated vapour pressure at Celcius-temp T:
float CalcSVP(float T) {
float tmp = aa * T / (bb+T);
return svp_0 * pow(10,tmp);
}
// calc partial vapour pressure at Celcius-temp T, given wet-bulb Tw:
float CalcVapPress(float T,float Tw) {
float A = 66.87 * (1+0.00115 * Tw); // at 1 atm!!
return CalcSVP(Tw) - A * (T-Tw);
}
// calc relative humidity at Celcius-temp T, given wet-bulb Tw:
float CalcRH(float T,float Tw) {
float tmp = (CalcVapPress(T,Tw)/CalcSVP(T)*1000+0.5)/10;
if (tmp<0) {
return 0;
}
else {
return tmp;
}
}
I am having a heck of a time trying to get this to work properly, these are the keyes ebay modules pretty standard.
It seems to work but it actually does not work correctly.
If I rotate CW I get value change on detent.
If I rotate CCW I get value change immediately! well before detent maybe half step.
I have tried several settings and see no improvement, is it possible this code is not checking properly?
Ill try to scope it and see what is going on, tested several encoders I have.
Using esp8266 example
Ill make a video also to better explain, I am not sure I fully understand the flaky option and the half step modifiers, but I have tried them all.
hello,
this lib is great, thak you to have continued the good work of the first author
but i was wandering if it would be possible to make it more user friendly, for example, instead of:
ClickEncoder::Button buttonState = encoder->getButton();
i would like to use (as all the library that are around):
ClickEncoder myRE;
buttonState = myRE.getButton();
i know it would need some work of class changes but then the library would be perfect
cheers
Can a detent detect as a click?
Some kind of reorder error is showing up with building with Platformio.
src/main.cpp:57:12: warning: enumeration value 'Closed' not handled in switch [-Wswitch] In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h: In constructor 'ClickEncoder::ClickEncoder(int8_t, int8_t, int8_t, uint8_t, bool)': .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:165:8: error: 'ClickEncoder::buttonHeldEnabled' will be initialized after [-Werror=reorder] bool buttonHeldEnabled; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:158:8: error: 'bool ClickEncoder::accelerationEnabled' [-Werror=reorder] bool accelerationEnabled; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:44:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t A, int8_t B, int8_t BTN, uint8_t stepsPerNotch, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:158:8: error: 'ClickEncoder::accelerationEnabled' will be initialized after [-Werror=reorder] bool accelerationEnabled; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:154:20: error: 'volatile int16_t ClickEncoder::delta' [-Werror=reorder] volatile int16_t delta; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:44:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t A, int8_t B, int8_t BTN, uint8_t stepsPerNotch, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:163:19: error: 'ClickEncoder::button' will be initialized after [-Werror=reorder] volatile Button button; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:156:20: error: 'volatile uint8_t ClickEncoder::steps' [-Werror=reorder] volatile uint8_t steps; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:44:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t A, int8_t B, int8_t BTN, uint8_t stepsPerNotch, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:156:20: error: 'ClickEncoder::steps' will be initialized after [-Werror=reorder] volatile uint8_t steps; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:150:10: error: 'int8_t ClickEncoder::pinA' [-Werror=reorder] int8_t pinA; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:44:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t A, int8_t B, int8_t BTN, uint8_t stepsPerNotch, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h: In constructor 'ClickEncoder::ClickEncoder(int8_t, bool)': .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:165:8: error: 'ClickEncoder::buttonHeldEnabled' will be initialized after [-Werror=reorder] bool buttonHeldEnabled; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:158:8: error: 'bool ClickEncoder::accelerationEnabled' [-Werror=reorder] bool accelerationEnabled; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:74:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t BTN, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:158:8: error: 'ClickEncoder::accelerationEnabled' will be initialized after [-Werror=reorder] bool accelerationEnabled; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:154:20: error: 'volatile int16_t ClickEncoder::delta' [-Werror=reorder] volatile int16_t delta; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:74:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t BTN, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:163:19: error: 'ClickEncoder::button' will be initialized after [-Werror=reorder] volatile Button button; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:156:20: error: 'volatile uint8_t ClickEncoder::steps' [-Werror=reorder] volatile uint8_t steps; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:74:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t BTN, bool active) ^ In file included from .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:12:0: .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:167:22: error: 'ClickEncoder::analogInput' will be initialized after [-Werror=reorder] bool analogInput = false; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.h:150:10: error: 'int8_t ClickEncoder::pinA' [-Werror=reorder] int8_t pinA; ^ .pio/libdeps/featheresp32/ClickEncoder/ClickEncoder.cpp:74:1: error: when initialized here [-Werror=reorder] ClickEncoder::ClickEncoder(int8_t BTN, bool active) ^ cc1plus: some warnings being treated as errors *** [.pio/build/featheresp32/lib82b/ClickEncoder/ClickEncoder.cpp.o] Error 1
Hello , i am using your click encoder program and find it the fastest i tested lately.
In the serial i get my values and button chances ,so that is perfect.
But ,due to my lack of skills , i can't figure out how i can implement it in my sketch.
I only want to use if encodervalue increases to get "right = TRUE " or UP and when the value decreases a "left = TRUE".
Can you please give me a hint how to implement this , i want to use it to steer an steppenmotor.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.