Wow, thanks so much Brainy. Just tested with some very cheap KY040 style encoders, your code works way better than much of the libraries available via the Lib manager, incl. Paul Stoffregen's Encoder library, him of Teensy fame. His code goes up by 2 every time I make a single detent step - not sure why as didn't hang around to see why it was so bad. Goes to show properly analysing and breaking down the true output of the encoder is always the best option. Great work!
Isn't it simpler to do a bitwise XOR of the pin values? A clockwise move would generate either1,0 or 0,1. XORing these two sets of values would always give a 1. A counterclockwise move would generate a 1,1 or a 0,0. XORing these two sets of values would always give you a 0. You only need to keep track of previous clock to do debounce checking. E.g: void check_rotary() { static int oldClock = -1; // Initialize to an impossible value. int clockVal = digitalRead(PinCLK); int dataVal = digitalRead(PinDT); if(clockVal == oldClock) return; // was a bounce. Don't count this. if(clockVal ^ dataVal) { // clockwise move displaycounter++ } else { // counterclockwise move displaycounter--; } oldClock = clockVal; // store clock state for debounce check. p.print(displaycounter); }
Any suggestions for when your values are all over the place and don't really fit said formula ? Or even worse, they f*ckin intersect with one another (same transition exists in both clockwise and counterclockwise moves).
Thank you very much. This saved me. Was getting crazy from the "official" sample code. The bouncing was limiting any serious usage of this encoder. I made just a small modification, I increase/decrease the counter only in stages, where value on CLK is 1. That allows me to copy with the counter the full clicks only, not the intermediate states.
Thank you for sharing your knowledge and experience my friend. I picked up a KY-040 & an Arduino Uno for a rotary arcade joystick project. I plan to use it to make a controller that functions like the classic SNK LS-30 8-position rotary joystick used on Ikari Warriors arcade machines. Absolutely NOBODY makes a rotary joystick anymore so DIY is the only solution. Great tutorial, thank you again!
The test code worked well for my bench test. I'm planning on using an Arduino micro with a rotary encoder to control under vehicle programmable LED lighting on my truck. I'll have multiple light patterns (PWM) that will be generated from the Arduino, and selected through this encoder. I think it is less overhead for the Arduino if the rotary encoder is operating with interrupts. Your thoughts?
Yes, I find that Krishna's code works better. I started there. I did not wire the 8x8 matrix, so my code only reports to the Serial interface. Also, I added bounds checking. and I was getting 2 value changes per 1 click of the dial, so I normalized that with a map() function. I hope this helps someone: const int pinCLK = 10; const int pinDATA = 16; const int pinSW = 14; // to deBounce long TimeOfLastDebounce = 0; float DelayofDebounce = 0.01; // valiables to limit the read, keep it between a minimum and a maximum value; static int rawMax = 400; static int rawMin = -400; // Code was changing by two, for each one click of the wheel. // so I added a rawCounter, and then I map that to a good counter // later in the code. static int rawCounter = 0; static int goodCounter = 0; void setup() { pinMode(pinSW, INPUT_PULLUP); Serial.begin(19200); } void loop() { // If enough time has passed, check the rotary encoder if ((millis() - TimeOfLastDebounce) > DelayofDebounce) { check_rotary(); // Check if switch was pressed if (digitalRead(pinSW) == LOW) { rawCounter = 0; } } // end if for debounce
// fix problem with too much change. goodCounter = map(rawCounter,-400,400,-200,200); Serial.println(goodCounter); delay(1); } // end loop void check_rotary() { static int oldClock = 0; // Initialize to an impossible value. int clockVal = digitalRead(pinCLK); int dataVal = digitalRead(pinDATA); if(clockVal == oldClock) return; // was a bounce. Don't count this.
if ((clockVal ^ dataVal) && (rawCounter+1 < rawMax)) { rawCounter++; } else if (rawCounter > rawMin) { rawCounter--; } oldClock = clockVal; // fix problem with wheel changing the value too much. // now 1 click of wheel = 1 change of goodCounter. goodCounter = map(rawCounter,-400,400,-200,200); Serial.println(goodCounter); } // end of check_rotary()
Really great video Buddy! And Happy New Year! Amazing because I was just struggling with the same exact issue! Thanks so much for sharing!! You are my favorite teacher/ professor!
I tried the code and had high hopes for it. though it seemed too simple i thought it would work.. but when coupled with a program thats actually doing something useful (non-blocking code btw) for example reading from sensors and writing to oled display the program just skips too many steps. especially if turned faster. thanks for your efforts by the way.
If you put this code in an interrupt timer call back function and call it every two milli seconds or so it will interrupt any code in the main loop and read the encoder correctly.
Not using interrupts introduces other issues though. Potentially several bad ones too. Mostly when you are worried about power usage and also the MC doing something while your are checking the RE
When testing this code (working btw, very nice!) I notice you have called out // Variables to debounce Rotary Encoder long TimeOfLastDebounce = 0; int DelayofDebounce = 0.01;
That's actually pretty cool that you saw that... The value should be 10 not 0.01 (refering to 10ms), It's a typo I made in the code when testing. The code still works because it's actually checking all the time since the 0.01 is indeed equal to 0 when using an int. Also, a long variable doesn't allow any decimals just like int doesn't either. Long allows for bigger numbers (-2,147,483,648 to 2,147,483,648) unlike int which tops at (-32,767 to 32,767). For decimals we need to use float. Thank you again for pointing out the error in the code!
That long list of IFs in the first routine seems needlessly complex. If clock and data are equal, the move was counterclockwise, Else it was clockwise. if (digitalRead (PinCLK) == digitalRead(PinDT)) { displaycounter--; } else { displaycounter++; }
Hi big teacher. I want you to use, method to ( I want to built a program for 10 appartements and I want to arduino to show me which door is opened with there numero on 7 segments Afficher and buzzer
Hi thanks for the video, i just did the same project but asking if DL and CLK are equals, if diferent, the movement is Clockwise, else is Counterclockwise, just one line of program. It works.
Wow, every time I run into a snag, it seems you have a video to explain the concept, then write a code snippit to handle the problem. I have had a dozen of those encoders in my kit for a couple of years, never have figured out exactly how to use them. Bought them when I built a tiny white oscilloscope toy kit, when I assembled it, i nuked the encoder and had to buy 12 of them to get the one I needed. The one I installed brought the little scope to life and I do use it about once a week or so when I feel the need for investigation of circuits.
Code works. But I cant understand why counter make errors. In ex. I turn one full turn around and come back to the same place where I was on start: value not the same as was on "start". What are wrong?
All the rotary encoders I have out put 00,01,11,10 rotating one way and 00,10,11,01 when rotated the other direction. Just curious how you get the sequence you get. My alps encoder has detects for each of the 4 states but my ky040 only has one detention at 00.
can you plis recommend me a hard clicking encoder? the one that you are using is really easy to turn i am looking for one that requires more force to move cheers
Make an array with the index count equaling the number of encoders you have, one for the data pin data and one for the clock pin data (or make an array of structs) then loop during this read routine for each encoder
Yes it does, when you turn counterclockwise the displaycounter variable goes negative, but the LED matrix display doesn't show the minus sign. Thanks for watching!
I just find from Arduino site the following code that seems to work fine with the exception-change to 2.000.000 rate instead of 9600. create.arduino.cc/projecthub/vandenbrande/arduino-rotary-encoder-simple-example-ky-040-b78752 But I am still confused because i can not understand why the designer (of the chip) .........................gave us a SW pin....!!!! (what the hell ???..must have some utility.....) Here is the code (simplified) to check if it is working fine.... int CLK = 9; // Pin 9 to clk on encoder int DT = 8; // Pin 8 to DT on encoder int RotPosition = 0; int rotation; int value; boolean LeftRight; void setup() { Serial.begin (2000000); pinMode (CLK,INPUT); pinMode (DT,INPUT); rotation = digitalRead(CLK); RotPosition = 0; Serial.print("Initilising RotPosition at: "); RotPosition%=30; Serial.println(RotPosition); } void loop() { value = digitalRead(CLK); if (value != rotation){ // we use the DT pin to find out which way we turning.
if (digitalRead(DT) != value) { // Clockwise RotPosition ++; LeftRight = true; Serial.print ("Right to :"); } else { //Counterclockwise LeftRight = false; RotPosition--; Serial.print("Left to: "); }
#define encoder0PinA 2 #define encoder0PinB 3 int currentStateCLK; volatile unsigned int encoder0Pos = 0; Void setup(){ Serial.begin(115200); attachInterrupt(0, doEncoder, CHANGE); // encoder pin on interrupt 0 - pin 2 } void loop(){ } void doEncoder(){ currentStateCLK = digitalRead(encoder0PinA); if (currentStateCLK != 1 ){ encoder0Pos++; } else{ encoder0Pos--; } Serial.println(encoder0Pos); } I have changed slightly in the condition like when the currentCLK is 0 and if the datapin is equals to currenclk then it is rotated anticlock wise and is datapin is not equal it is clockwise. It gives me the stable output..
Created by Yvan / Brainy-Bits.com This code is in the public domain... You can: copy it, use it, modify it, share it or just plain ignore it! Thx! */ volatile boolean TurnDetected; // need volatile for Interrupts // Rotary Encoder Module connections const int PinCLK=2; // Generating interrupts using CLK signal const int PinDT=4; // Reading DT signal // Interrupt routine runs if CLK pin changes state void rotarydetect () { TurnDetected = true; // set variable to true } void setup () { Serial.begin(2000000); // high rate to assure good capture attachInterrupt (0,rotarydetect,CHANGE); // interrupt 0 always connected to pin 2 on Arduino UNO } void loop () { if (TurnDetected) { // rotary has been moved TurnDetected = false; // do NOT repeat IF loop until new rotation detected Serial.print("CLK Pin: "); Serial.println(digitalRead(PinCLK)); Serial.print("DT Pin: "); Serial.println(digitalRead(PinDT)); delay(5); } } THE DEBOUNCE CODE After running the previous Arduino sketch, here are the results: Clockwise (Clock, Data pin): 0,1 - 1,0 - 0,1 - 1,0 - … CounterClockwise (Clock, Data pin): 1,1 - 0,0 - 1,1 - 0,0 - … So now we know what pin state to expect when we turn the rotary encoder CW or CCW. In our testing we also saw the change when we went from CW to CCW or CCW to CW: Clockwise to CounterClockwise: 0,1 -> 1,1 or 1,0 -> 0,0 CounterClockwise to Clockwise: 1,1 -> 0,1 or 0,0 -> 1,0 Ok, now let’s check for this in our code using simple IF statements and register a rotation only when the above pin states are correct removing the boucing at the same time. As always please have a look at the tutorial video for more information. /* Arduino New Rotary Encoder Debounce
Created by Yvan / Brainy-Bits.com This code is in the public domain... You can: copy it, use it, modify it, share it or just plain ignore it! Thx! */ // Rotary Encoder Module connections const int PinSW=3; // Rotary Encoder Switch const int PinDT=4; // DATA signal const int PinCLK=2; // CLOCK signal // Variables to debounce Rotary Encoder long TimeOfLastDebounce = 0; int DelayofDebounce = 0.01; // Store previous Pins state int PreviousCLK; int PreviousDATA; int displaycounter=0; // Store current counter value // Library used for LED MATRIX 8x8 #include #include #include #define HARDWARE_TYPE MD_MAX72XX::FC16_HW /* PAROLA_HW, ///< Use the Parola style hardware modules. GENERIC_HW, ///< Use 'generic' style hardware modules commonly available. ICSTATION_HW, ///< Use ICStation style hardware module. FC16_HW ///< Use FC-16 style hardware module. */ // 8x8 LED Matrix connections #define MAX_DEVICES 2 #define CLK_PIN 13 #define DATA_PIN 11 #define CS_PIN 10 // Hardware SPI connection MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); void setup() { // Put current pins state in variables PreviousCLK=digitalRead(PinCLK); PreviousDATA=digitalRead(PinDT); // Set the Switch pin to use Arduino PULLUP resistors pinMode(PinSW, INPUT_PULLUP); // Start and setup the LED MATRIX at startup P.begin(); P.setTextAlignment(PA_RIGHT); P.print(displaycounter); } void loop() { // If enough time has passed check the rotary encoder if ((millis() - TimeOfLastDebounce) > DelayofDebounce) {
very cleaver idea to catch the debounces, because they are making me headaches. thank you for sharing
Wow, thanks so much Brainy. Just tested with some very cheap KY040 style encoders, your code works way better than much of the libraries available via the Lib manager, incl. Paul Stoffregen's Encoder library, him of Teensy fame. His code goes up by 2 every time I make a single detent step - not sure why as didn't hang around to see why it was so bad. Goes to show properly analysing and breaking down the true output of the encoder is always the best option. Great work!
Isn't it simpler to do a bitwise XOR of the pin values? A clockwise move would generate either1,0 or 0,1. XORing these two sets of values would always give a 1.
A counterclockwise move would generate a 1,1 or a 0,0. XORing these two sets of values would always give you a 0. You only need to keep track of previous clock to do debounce checking.
E.g:
void check_rotary() {
static int oldClock = -1; // Initialize to an impossible value.
int clockVal = digitalRead(PinCLK);
int dataVal = digitalRead(PinDT);
if(clockVal == oldClock) return; // was a bounce. Don't count this.
if(clockVal ^ dataVal) {
// clockwise move
displaycounter++
} else {
// counterclockwise move
displaycounter--;
}
oldClock = clockVal; // store clock state for debounce check.
p.print(displaycounter);
}
Any suggestions for when your values are all over the place and don't really fit said formula ?
Or even worse, they f*ckin intersect with one another (same transition exists in both clockwise and counterclockwise moves).
@@demyanrudenko It can be tricky and frustrating. I have found that the amount of delay that you add in can be critical. Try my code above.
@@demyanrudenko I would think use else if and at the end have just an else which does nothing but catch all the stray noise.
thanks bro, it works
@@rocketman179 which one?
Thank you very much. This saved me. Was getting crazy from the "official" sample code. The bouncing was limiting any serious usage of this encoder. I made just a small modification, I increase/decrease the counter only in stages, where value on CLK is 1. That allows me to copy with the counter the full clicks only, not the intermediate states.
Thank you for sharing your knowledge and experience my friend. I picked up a KY-040 & an Arduino Uno for a rotary arcade joystick project. I plan to use it to make a controller that functions like the classic SNK LS-30 8-position rotary joystick used on Ikari Warriors arcade machines. Absolutely NOBODY makes a rotary joystick anymore so DIY is the only solution. Great tutorial, thank you again!
thank you for the code, it is the most accurate code and it doesn't skip counts , thank you
can you give the code
Thanks, this worked for me, and it also made sense. Only thing I don't get is why you're not using the interrupt in the final code?
The test code worked well for my bench test. I'm planning on using an Arduino micro with a rotary encoder to control under vehicle programmable LED lighting on my truck. I'll have multiple light patterns (PWM) that will be generated from the Arduino, and selected through this encoder. I think it is less overhead for the Arduino if the rotary encoder is operating with interrupts. Your thoughts?
Finaly !!! After a year.
You are genious. Thank you man
Thankyou
I subscribe your channel NOW
Very helpful, Thanks for your time in producing this.
Always great to hear the videos are helping others
Thanks for watching
Thank you very much, I had the same problems. A beautiful and simple effective solution.
Thanks for your comment and for watching Stephane.
Yes, I find that Krishna's code works better. I started there. I did not wire the 8x8 matrix, so my code only reports to the Serial interface. Also, I added bounds checking. and I was getting 2 value changes per 1 click of the dial, so I normalized that with a map() function. I hope this helps someone:
const int pinCLK = 10;
const int pinDATA = 16;
const int pinSW = 14;
// to deBounce
long TimeOfLastDebounce = 0;
float DelayofDebounce = 0.01;
// valiables to limit the read, keep it between a minimum and a maximum value;
static int rawMax = 400;
static int rawMin = -400;
// Code was changing by two, for each one click of the wheel.
// so I added a rawCounter, and then I map that to a good counter
// later in the code.
static int rawCounter = 0;
static int goodCounter = 0;
void setup()
{
pinMode(pinSW, INPUT_PULLUP);
Serial.begin(19200);
}
void loop()
{
// If enough time has passed, check the rotary encoder
if ((millis() - TimeOfLastDebounce) > DelayofDebounce)
{
check_rotary();
// Check if switch was pressed
if (digitalRead(pinSW) == LOW)
{
rawCounter = 0;
}
} // end if for debounce
// fix problem with too much change.
goodCounter = map(rawCounter,-400,400,-200,200);
Serial.println(goodCounter);
delay(1);
} // end loop
void check_rotary()
{
static int oldClock = 0; // Initialize to an impossible value.
int clockVal = digitalRead(pinCLK);
int dataVal = digitalRead(pinDATA);
if(clockVal == oldClock) return; // was a bounce. Don't count this.
if ((clockVal ^ dataVal) && (rawCounter+1 < rawMax))
{
rawCounter++;
}
else if (rawCounter > rawMin)
{
rawCounter--;
}
oldClock = clockVal;
// fix problem with wheel changing the value too much.
// now 1 click of wheel = 1 change of goodCounter.
goodCounter = map(rawCounter,-400,400,-200,200);
Serial.println(goodCounter);
} // end of check_rotary()
This code works absolutely amazing. Thank you so much.
I know this video have been 2 years, but thank you.
Really great video Buddy! And Happy New Year! Amazing because I was just struggling with the same exact issue! Thanks so much for sharing!! You are my favorite teacher/ professor!
Thanks for taking the time to comment, great to hear that this helped and Happy New Year to you as well.
I tried the code and had high hopes for it. though it seemed too simple i thought it would work.. but when coupled with a program thats actually doing something useful (non-blocking code btw) for example reading from sensors and writing to oled display the program just skips too many steps. especially if turned faster. thanks for your efforts by the way.
If you put this code in an interrupt timer call back function and call it every two milli seconds or so it will interrupt any code in the main loop and read the encoder correctly.
Not using interrupts introduces other issues though. Potentially several bad ones too. Mostly when you are worried about power usage and also the MC doing something while your are checking the RE
Yeah, this is the worst of 3 debounce methods. Hardware > programmatic > forced delay. Unacceptable for a paid project
Sweet! Saving this for future reference. Thanks!
Thanks for your comment and for watching!
Thank you. I had to remove the matrix part and use the Serial.println but it works perfectly !
Cool, great to hear it worked out. Thanks for watching!
When testing this code (working btw, very nice!) I notice you have called out // Variables to debounce Rotary Encoder
long TimeOfLastDebounce = 0;
int DelayofDebounce = 0.01;
That's actually pretty cool that you saw that... The value should be 10 not 0.01 (refering to 10ms), It's a typo I made in the code when testing. The code still works because it's actually checking all the time since the 0.01 is indeed equal to 0 when using an int. Also, a long variable doesn't allow any decimals just like int doesn't either. Long allows for bigger numbers (-2,147,483,648 to 2,147,483,648) unlike int which tops at (-32,767 to 32,767). For decimals we need to use float. Thank you again for pointing out the error in the code!
That long list of IFs in the first routine seems needlessly complex. If clock and data are equal, the move was counterclockwise, Else it was clockwise.
if (digitalRead (PinCLK) == digitalRead(PinDT))
{
displaycounter--;
}
else
{
displaycounter++;
}
Hi big teacher. I want you to use, method to ( I want to built a program for 10 appartements and I want to arduino to show me which door is opened with there numero on 7 segments Afficher and buzzer
Very nice code and explanation.
Hi thanks for the video, i just did the same project but asking if DL and CLK are equals, if diferent, the movement is Clockwise, else is Counterclockwise, just one line of program. It works.
Always had a problem with grey code. Thanks.
Happy to know that it helped, thanks for watching.
happy new year!
Wow, every time I run into a snag, it seems you have a video to explain the concept, then write a code snippit to handle the problem. I have had a dozen of those encoders in my kit for a couple of years, never have figured out exactly how to use them. Bought them when I built a tiny white oscilloscope toy kit, when I assembled it, i nuked the encoder and had to buy 12 of them to get the one I needed. The one I installed brought the little scope to life and I do use it about once a week or so when I feel the need for investigation of circuits.
Hi Jerry, thanks for your comment and very happy that this might help you with your current and future projects! Cheers!
Hello, would you be so nice to share the code that you show in the video to solve this problem? I would be very grateful, greetings.
Sure... right here buddy: www.brainy-bits.com/arduino-rotary-encoder-ky-040/ Hope that helps and thank you for watching!
Hello again, I appreciate your quick response, I really appreciate it, Darío greets you from Argentina.
@@BrainybitsCanada Thanks for simple solution to use this cheap encoders, looks like this link is down now
@@BrainybitsCanada link no longer working, thanks
Very helpful, Thanks for your time in producing this, can you write how to reset screen, thank you again
Excellent !
You should have links in the description... to your code, and a link to buy the equipment
www.brainy-bits.com/post/best-code-to-use-with-a-ky-040-rotary-encoder-let-s-find-out
How fast can you spin it without it breaking
Just amazing explanation.
Why don't just do and/nand ad have one codeblock?
Code works. But I cant understand why counter make errors. In ex. I turn one full turn around and come back to the same place where I was on start: value not the same as was on "start". What are wrong?
It’s can’t switch case?
Nice, but you couldn't just put a simple link at the top to the code? No?
Can u use optical encoder for this project. For DIY dtg printer
I am newbie here. Great if you could comment about
the resolution (in degrees) possible, with this encoder?
All the rotary encoders I have out put 00,01,11,10 rotating one way and 00,10,11,01 when rotated the other direction.
Just curious how you get the sequence you get. My alps encoder has detects for each of the 4 states but my ky040 only has one detention at 00.
can you plis recommend me a hard clicking encoder?
the one that you are using is really easy to turn
i am looking for one that requires more force to move
cheers
that's cool bro, and how about using 2 rotary encoders? I am very confused. Please help me.
Make an array with the index count equaling the number of encoders you have, one for the data pin data and one for the clock pin data (or make an array of structs) then loop during this read routine for each encoder
Can you please share circuit diagram...
hello, Why dont we use LCS I2C screen ? any reason ? thnk you
Can this be used on nodemcu ??? If not please help me out ...
i want you give me load the code this,are you can help me. Thanks
Does the value increase in either direction when you started at zero?
Yes it does, when you turn counterclockwise the displaycounter variable goes negative, but the LED matrix display doesn't show the minus sign. Thanks for watching!
what is the name of the tool above the rotary which has the color blue ?? please answer sir
It seems to be a 3D printed knob. That particular type of knob is usually called a JOG WHEEL.
Gracias.
Tu devrais mettre un lien direct vers le topic un lien vers ton site ..
How to get the code?
can you provide code ?
I just find from Arduino site the following code that seems to work fine
with the exception-change to 2.000.000 rate instead of 9600.
create.arduino.cc/projecthub/vandenbrande/arduino-rotary-encoder-simple-example-ky-040-b78752
But I am still confused because i can not understand why the designer (of the chip)
.........................gave us a SW pin....!!!! (what the hell ???..must have some utility.....)
Here is the code (simplified) to check if it is working fine....
int CLK = 9; // Pin 9 to clk on encoder
int DT = 8; // Pin 8 to DT on encoder
int RotPosition = 0;
int rotation;
int value;
boolean LeftRight;
void setup() {
Serial.begin (2000000);
pinMode (CLK,INPUT);
pinMode (DT,INPUT);
rotation = digitalRead(CLK);
RotPosition = 0;
Serial.print("Initilising RotPosition at: ");
RotPosition%=30;
Serial.println(RotPosition);
}
void loop() {
value = digitalRead(CLK);
if (value != rotation){ // we use the DT pin to find out which way we turning.
if (digitalRead(DT) != value) { // Clockwise
RotPosition ++;
LeftRight = true;
Serial.print ("Right to :");
}
else { //Counterclockwise
LeftRight = false;
RotPosition--;
Serial.print("Left to: ");
}
RotPosition%=30;
Serial.println(RotPosition);
}
rotation = value;
}
the sw pin is a button
#define encoder0PinA 2
#define encoder0PinB 3
int currentStateCLK;
volatile unsigned int encoder0Pos = 0;
Void setup(){
Serial.begin(115200);
attachInterrupt(0, doEncoder, CHANGE); // encoder pin on interrupt 0 - pin 2
}
void loop(){
}
void doEncoder(){
currentStateCLK = digitalRead(encoder0PinA);
if (currentStateCLK != 1 ){
encoder0Pos++;
}
else{
encoder0Pos--;
}
Serial.println(encoder0Pos);
}
I have changed slightly in the condition like when the currentCLK is 0 and if the datapin is equals to currenclk then it is rotated anticlock wise and is datapin is not equal it is clockwise.
It gives me the stable output..
Where is code?
hello, please can u share the code ?
www.brainy-bits.com/post/best-code-to-use-with-a-ky-040-rotary-encoder-let-s-find-out
Thank you for the code and upload.
btw 666th like and 66th comment... Eeep.
int DelayofDebounce = 0.01;
code
Code plz
/* Arduino New Rotary Encoder Pin states
Created by Yvan / Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!
*/
volatile boolean TurnDetected; // need volatile for Interrupts
// Rotary Encoder Module connections
const int PinCLK=2; // Generating interrupts using CLK signal
const int PinDT=4; // Reading DT signal
// Interrupt routine runs if CLK pin changes state
void rotarydetect () {
TurnDetected = true; // set variable to true
}
void setup () {
Serial.begin(2000000); // high rate to assure good capture
attachInterrupt (0,rotarydetect,CHANGE); // interrupt 0 always connected to pin 2 on Arduino UNO
}
void loop () {
if (TurnDetected) { // rotary has been moved
TurnDetected = false; // do NOT repeat IF loop until new rotation detected
Serial.print("CLK Pin: ");
Serial.println(digitalRead(PinCLK));
Serial.print("DT Pin: ");
Serial.println(digitalRead(PinDT));
delay(5);
}
}
THE DEBOUNCE CODE
After running the previous Arduino sketch, here are the results:
Clockwise (Clock, Data pin): 0,1 - 1,0 - 0,1 - 1,0 - …
CounterClockwise (Clock, Data pin): 1,1 - 0,0 - 1,1 - 0,0 - …
So now we know what pin state to expect when we turn the rotary encoder CW or CCW.
In our testing we also saw the change when we went from CW to CCW or CCW to CW:
Clockwise to CounterClockwise: 0,1 -> 1,1 or 1,0 -> 0,0
CounterClockwise to Clockwise: 1,1 -> 0,1 or 0,0 -> 1,0
Ok, now let’s check for this in our code using simple IF statements and register a rotation only when the above pin states are correct removing the boucing at the same time.
As always please have a look at the tutorial video for more information.
/* Arduino New Rotary Encoder Debounce
Created by Yvan / Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!
*/
// Rotary Encoder Module connections
const int PinSW=3; // Rotary Encoder Switch
const int PinDT=4; // DATA signal
const int PinCLK=2; // CLOCK signal
// Variables to debounce Rotary Encoder
long TimeOfLastDebounce = 0;
int DelayofDebounce = 0.01;
// Store previous Pins state
int PreviousCLK;
int PreviousDATA;
int displaycounter=0; // Store current counter value
// Library used for LED MATRIX 8x8
#include
#include
#include
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
/* PAROLA_HW, ///< Use the Parola style hardware modules.
GENERIC_HW, ///< Use 'generic' style hardware modules commonly available.
ICSTATION_HW, ///< Use ICStation style hardware module.
FC16_HW ///< Use FC-16 style hardware module.
*/
// 8x8 LED Matrix connections
#define MAX_DEVICES 2
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
void setup() {
// Put current pins state in variables
PreviousCLK=digitalRead(PinCLK);
PreviousDATA=digitalRead(PinDT);
// Set the Switch pin to use Arduino PULLUP resistors
pinMode(PinSW, INPUT_PULLUP);
// Start and setup the LED MATRIX at startup
P.begin();
P.setTextAlignment(PA_RIGHT);
P.print(displaycounter);
}
void loop() {
// If enough time has passed check the rotary encoder
if ((millis() - TimeOfLastDebounce) > DelayofDebounce) {
check_rotary(); // Rotary Encoder check routine below
PreviousCLK=digitalRead(PinCLK);
PreviousDATA=digitalRead(PinDT);
TimeOfLastDebounce=millis(); // Set variable to current millis() timer
}
// Check if Rotary Encoder switch was pressed
if (digitalRead(PinSW) == LOW) {
displaycounter=0; // Reset counter to zero
P.print(displaycounter);
}
}
// Check if Rotary Encoder was moved
void check_rotary() {
if ((PreviousCLK == 0) && (PreviousDATA == 1)) {
if ((digitalRead(PinCLK) == 1) && (digitalRead(PinDT) == 0)) {
displaycounter++;
P.print(displaycounter);
}
if ((digitalRead(PinCLK) == 1) && (digitalRead(PinDT) == 1)) {
displaycounter--;
P.print(displaycounter);
}
}
if ((PreviousCLK == 1) && (PreviousDATA == 0)) {
if ((digitalRead(PinCLK) == 0) && (digitalRead(PinDT) == 1)) {
displaycounter++;
P.print(displaycounter);
}
if ((digitalRead(PinCLK) == 0) && (digitalRead(PinDT) == 0)) {
displaycounter--;
P.print(displaycounter);
}
}
if ((PreviousCLK == 1) && (PreviousDATA == 1)) {
if ((digitalRead(PinCLK) == 0) && (digitalRead(PinDT) == 1)) {
displaycounter++;
P.print(displaycounter);
}
if ((digitalRead(PinCLK) == 0) && (digitalRead(PinDT) == 0)) {
displaycounter--;
P.print(displaycounter);
}
}
if ((PreviousCLK == 0) && (PreviousDATA == 0)) {
if ((digitalRead(PinCLK) == 1) && (digitalRead(PinDT) == 0)) {
displaycounter++;
P.print(displaycounter);
}
if ((digitalRead(PinCLK) == 1) && (digitalRead(PinDT) == 1)) {
displaycounter--;
P.print(displaycounter);
}
}
}
Hola, podrías adaptar esta mejora al código de tu otro video th-cam.com/video/e5p7wGEC0Xc/w-d-xo.html
?