Skip to content

Commit 57d0919

Browse files
committed
Update for 1.0.1
Add pdf documentation
1 parent 9676f71 commit 57d0919

File tree

4 files changed

+120
-44
lines changed

4 files changed

+120
-44
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
internal

KY040.pdf

623 KB
Binary file not shown.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# KY040
22
An Arduino library for KY-040 rotary encoders. The library has debouncing and works in polling mode, with pin change interrupts or normal interrupts. In polling or pin change interrupt mode you can attach more then one rotary encoder to your Arduino Uno/Nano.
33

4+
[PDF-Documentation](KY040.pdf)
5+
46
Examples how to use the library
57
- [pollingNoInterrupts](/examples/pollingNoInterrupts/pollingNoInterrupts.ino)
68
- [pinChangeInterrupt](/examples/pinChangeInterrupt/pinChangeInterrupt.ino)
@@ -9,7 +11,7 @@ Examples how to use the library
911
- [withInterrupt](/examples/withInterrupt/withInterrupt.ino)
1012

1113
## License and copyright
12-
This library is licensed under the terms of the 2-Clause BSD License [Copyright (c) 2023 codingABI](LICENSE.txt).
14+
This library is licensed under the terms of the 2-Clause BSD License [Copyright (c) 2024 codingABI](LICENSE.txt).
1315

1416
## Appendix
1517
### Background
@@ -69,6 +71,7 @@ DT | |
6971
| 3 | High/High |
7072

7173
### KY-040 Hardware
74+
7275
![Frontside](assets/images/KY-040_Frontside.jpg)
7376

7477
| Pins | Comment |

src/KY040.h

Lines changed: 115 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*
1+
/**
22
* Class: KY040
33
*
44
* Description:
@@ -8,11 +8,12 @@
88
* by ignoring invalid CLK/DT sequences
99
*
1010
* License: 2-Clause BSD License
11-
* Copyright (c) 2023 codingABI
11+
* Copyright (c) 2024 codingABI
1212
* For details see: LICENSE.txt
1313
*
1414
* Valid clockwise sequence for CLK/DT: Low/High->Low/Low->High/Low->High/High
1515
*
16+
* @code
1617
* 0 1 2 3
1718
* --+ +---- High
1819
* CLK | |
@@ -21,10 +22,11 @@
2122
* ----+ +-- High
2223
* DT | |
2324
* +---+ Low
24-
*
25+
* @endcode
2526
*
2627
* Valid counter-clockwise sequence for CLK/DT: High/Low->Low/Low->Low/High->High/High
2728
*
29+
* @code
2830
* 0 1 2 3
2931
* ----+ +--- High
3032
* CLK | |
@@ -33,24 +35,49 @@
3335
* --+ +----- High
3436
* DT | |
3537
* +---+ Low
36-
*/
38+
* @endcode
39+
*
40+
* Home: https://github.com/codingABI/KY040
41+
*
42+
* @author codingABI https://github.com/codingABI/
43+
* @copyright 2-Clause BSD License
44+
* @file KY040.h
45+
* @version 1.0.1
46+
*/
3747
#pragma once
3848

49+
/** Library version */
3950
#define KY040_VERSION "1.0.1"
4051

4152
#include <arduino.h>
4253

43-
// When using sleep modes wait X milliseconds for next sleep after a CLK/DT sequence start do prevent missing signals
54+
/** When using sleep modes wait X milliseconds for next sleep after a CLK/DT sequence start do prevent missing signals */
4455
#define PREVENTSLEEPMS 150
4556
// Pin idle state
4657
#define INITSTEP 0b11
4758
// Max steps for a signal sequence
4859
#define MAXSEQUENCESTEPS 4
4960

61+
/** Class for a KY-040 rotary encoder */
5062
class KY040 {
5163
public:
52-
enum directions { IDLE, ACTIVE, CLOCKWISE, COUNTERCLOCKWISE };
53-
KY040(byte clk_pin, byte dt_pin) {
64+
/** Rotation states */
65+
enum directions
66+
{
67+
IDLE, /**< Rotary encoder is idle */
68+
ACTIVE, /**< Rotary encoder is rotating, but the CLK/DT sequence has not finished */
69+
CLOCKWISE, /**< CLK/DT sequence for one step clockwise rotation has finished */
70+
COUNTERCLOCKWISE /**< CLK/DT sequence for one step counter-clockwise rotation has finished */
71+
};
72+
73+
/**@brief
74+
* Constructor of a the KY040 rotary encoder
75+
*
76+
* @param[in] clk_pin Digital input pin connected to CLK aka. A
77+
* @param[in] dt_pin Digital input pin connected to DT aka. B
78+
*/
79+
KY040(byte clk_pin, byte dt_pin)
80+
{
5481
m_clk_pin = clk_pin; // aka. A
5582
m_dt_pin = dt_pin; // aka. B
5683
v_state = 255;
@@ -60,43 +87,20 @@ class KY040 {
6087
v_direction = IDLE;
6188
v_oldState = INITSTEP;
6289
}
63-
// Get pin states for CLK and DT (Left bit is for CLK, right bit is for DT). Should be called from ISR, when needed
64-
byte getState() {
65-
return v_state;
66-
}
67-
// Set pin states for CLK and DT (Left bit is for CLK, right bit is for DT). Should be called from ISR, when needed
68-
void setState(byte state) {
69-
v_state = state;
70-
}
71-
// Returns true, if device was running long enough to get a full sequence (Do not use inside ISR)
72-
bool readyForSleep() {
73-
cli();
74-
unsigned long lastStepMillis = v_lastSequenceStartMillis;
75-
sei();
76-
return (millis()-lastStepMillis > PREVENTSLEEPMS);
77-
}
78-
// Get and reset the last rotary rotation (Do not use inside ISR)
79-
byte getAndResetLastRotation() {
80-
cli();
81-
byte result = v_lastResult;
82-
v_lastResult = IDLE;
83-
sei();
84-
return result;
85-
}
86-
// Get pin state for CLK and DT and returns the current rotation state
87-
byte getRotation() {
88-
setState((digitalRead(m_clk_pin)<<1)+digitalRead(m_dt_pin));
89-
return checkRotation();
90-
}
91-
/* Returns current rotation state:
92-
* - KY040::CLOCKWISE = CLK/DT Sequence for clockwise rotation has finished
93-
* - KY040::COUNTERCLOCKWISE = CLK/DT Sequence for counter-clockwise rotation has finished
94-
* - KY040::IDLE = Rotary encoder is not rotating
95-
* - KY040::ACTIVE = Rotary encoder is rotating, but the CLK/DT sequence has not finished
96-
* If you do not use interrupts, you have to start checkRotation() or a function using
97-
* checkRotation() very frequently in your loop to prevent missing signals
90+
91+
/**@brief
92+
* Returns current rotation state from stored pin state.
93+
*
94+
* If you do not use interrupts, you have to start setState() and checkRotation() or a function using
95+
* these (for example getRotation()) very frequently in your loop to prevent missing signals
96+
*
97+
* @retval KY040::CLOCKWISE CLK/DT sequence for one step clockwise rotation has finished
98+
* @retval KY040::COUNTERCLOCKWISE CLK/DT sequence for one step counter-clockwise rotation has finished
99+
* @retval KY040::IDLE Rotary encoder is idle
100+
* @retval KY040::ACTIVE Rotary encoder is rotating, but the CLK/DT sequence has not finished
98101
*/
99-
byte checkRotation() {
102+
byte checkRotation()
103+
{
100104
byte result = IDLE;
101105

102106
if (v_state != v_oldState) { // State changed?
@@ -157,6 +161,74 @@ class KY040 {
157161
}
158162
return result;
159163
}
164+
165+
/**@brief
166+
* Get and reset last finished rotation step (Do not use inside ISR)
167+
*
168+
* @retval KY040::CLOCKWISE CLK/DT sequence for one step clockwise rotation has finished
169+
* @retval KY040::COUNTERCLOCKWISE CLK/DT sequence for one step counter-clockwise rotation has finished
170+
* @retval KY040::IDLE Rotary encoder is idle
171+
*/
172+
byte getAndResetLastRotation()
173+
{
174+
cli();
175+
byte result = v_lastResult;
176+
v_lastResult = IDLE;
177+
sei();
178+
return result;
179+
}
180+
181+
/**@brief
182+
* Read and stores current pin state for CLK and DT and returns the current rotation state.
183+
*
184+
* Reads pin state for CLK and DT with DigitalRead() and checks current rotation state by calling checkRotation()
185+
*
186+
* @retval KY040::CLOCKWISE CLK/DT sequence for one step clockwise rotation has finished
187+
* @retval KY040::COUNTERCLOCKWISE CLK/DT sequence for one step counter-clockwise rotation has finished
188+
* @retval KY040::IDLE Rotary encoder is idle
189+
* @retval KY040::ACTIVE Rotary encoder is rotating, but the CLK/DT sequence has not finished
190+
*/
191+
byte getRotation()
192+
{
193+
setState((digitalRead(m_clk_pin)<<1)+digitalRead(m_dt_pin));
194+
return checkRotation();
195+
}
196+
197+
/**@brief
198+
* Get stored pin states for CLK and DT (Left bit is for CLK, right bit is for DT). Should be called from ISR, when needed
199+
*
200+
* @returns Stored pin states for CLK and DT in two bits (Left bit is for CLK, right bit is for DT)
201+
*/
202+
byte getState()
203+
{
204+
return v_state;
205+
}
206+
207+
/**@brief
208+
* Checks, if it save to go to sleep
209+
*
210+
* Returns true, if device was running long enough to get a full sequence (Do not use inside ISR)
211+
*
212+
* @retval true Yes, it is save to go to sleep
213+
* @retval false No, it is not save and you could miss signals, if you go to sleep anyway
214+
*/
215+
bool readyForSleep()
216+
{
217+
cli();
218+
unsigned long lastStepMillis = v_lastSequenceStartMillis;
219+
sei();
220+
return (millis()-lastStepMillis > PREVENTSLEEPMS);
221+
}
222+
223+
/**@brief
224+
* Stores pin states for CLK and DT (Left bit is for CLK, right bit is for DT). Should be called from ISR, when needed.
225+
*
226+
* @param[in] state Pin state for CLK and DT in two bits (Left bit is for CLK, right bit is for DT)
227+
*/
228+
void setState(byte state)
229+
{
230+
v_state = state;
231+
}
160232
private:
161233
byte m_clk_pin; // aka. A
162234
byte m_dt_pin; // aka. B

0 commit comments

Comments
 (0)