-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencoder.cpp
More file actions
163 lines (109 loc) · 5.89 KB
/
encoder.cpp
File metadata and controls
163 lines (109 loc) · 5.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// this is a base input class, this class will not access any of the other
// files, other files will include this file this file doesnt need to include
// any other file in this project
// i estimated this file to take about 3% of the arduino memeory
// the memeory usage is not right it should be lower check it later
#include <Arduino.h>
#include "encoder.h"
namespace Encoder {
// encoder pins are not exposed you can only change them
// inside this file only
const int encoder_clock_pin = 12; // Connected to CLK on KY-040
const int encoder_dt_pin = 11; // dt pin
const unsigned long encoder_cooldown_ms = 50; // this is the cool down after the encoder has been rotated
// this will help avoid the encoder internal bounce effect
int local_last_encoder_clock; // this will be used to detect the change after every step
typedef void (*EncoderCallback)(int delta); // create the call back type
const int MAX_CALLBACKS = 1; // each array can only hold 5 callbacks if you try to add
// more than 5 callbacks then what comes after 5 will be
// ignored
EncoderCallback callbacks[MAX_CALLBACKS];
int callbacks_count = 0;
void on_encoder_event(int delta) {
// this is where the event is routed when we detect it
for (int i = 0; i < callbacks_count; i++) {
if (callbacks[i] != nullptr) {
callbacks[i](delta);
}
}
}
bool encoder_event_cool_down_passed(){
// this function will filter out the encoer internal boundce
// and it will also trigger the event so we can code without
// worry in the upper parts
static unsigned long last_event_time = 0;
unsigned long now = millis();
if (now - last_event_time < encoder_cooldown_ms) {
return false; // too soon, ignore
}
last_event_time = now;
return true; // accept event
}
void init(){
// encoder
pinMode(encoder_clock_pin, INPUT);
pinMode(encoder_dt_pin, INPUT);
local_last_encoder_clock = (digitalRead(encoder_clock_pin) << 1) | digitalRead(encoder_dt_pin); // store the current state of the encoder
}
/*
void loop(){
// old code this worked but it required high value of encoder_cooldown_ms so
// i wrote a better function check the function under here though this one
// worked better for the encoder in the lab
// this will check if the encoder state changes if it did run it run it back
// and detect the change, then map the change to the transitino that we know
// that are either clockwise or anticlock wise
int current_state = (digitalRead(encoder_clock_pin) << 1) | digitalRead(encoder_dt_pin); // detect the current state
if (current_state != local_last_encoder_clock) { // check if a change had occured
// Clockwise we only accpet them if they are in these transitions [00 → 01 → 11 → 10 → 00]
if ((local_last_encoder_clock == 0b00 && current_state == 0b01) ||
(local_last_encoder_clock == 0b01 && current_state == 0b11) ||
(local_last_encoder_clock == 0b11 && current_state == 0b10) ||
(local_last_encoder_clock == 0b10 && current_state == 0b00))
{
if (encoder_event_cool_down_passed()) // apply the cool down
on_encoder_event(-1); // the filter will decide if to trigger the event
local_last_encoder_clock = current_state;
}
// Counter-clockwise we only accpet them if they are in these transitions [00 → 10 → 11 → 01 → 00]
else if ((local_last_encoder_clock == 0b00 && current_state == 0b10) ||
(local_last_encoder_clock == 0b10 && current_state == 0b11) ||
(local_last_encoder_clock == 0b11 && current_state == 0b01) ||
(local_last_encoder_clock == 0b01 && current_state == 0b00))
{
if (encoder_event_cool_down_passed()) // apply the cool down
on_encoder_event(1); // the filter will decide if to trigger the event
local_last_encoder_clock = current_state;
}
//local_last_encoder_clock = current_state; // this line of code failed dont add it back
// rely on the encoder cool down value to remove
// the internal bounce
}
}
*/
void loop() {
// this function only works if the clock changed this elemnates
// 2 of the transitions that can lead to you going both ways,
// which means that this code should in theory not work in some
// rotations but i have had no issues with it so far
int current_encoder_clock = digitalRead(encoder_clock_pin);
int current_encoder_dt = digitalRead(encoder_dt_pin);
// detect rising edge on current_encoder_clock
if (current_encoder_clock == HIGH && local_last_encoder_clock == LOW) {
if (encoder_event_cool_down_passed()) {
// this if statment takes care of the internal bounce
if (current_encoder_dt == LOW) {
on_encoder_event(1);
} else {
on_encoder_event(-1);
}
}
}
local_last_encoder_clock = current_encoder_clock;
}
void register_encoder_callback(EncoderCallback callback) {
if (callbacks_count < MAX_CALLBACKS) {
callbacks[callbacks_count++] = callback;
}
}
}