-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathencodertest.ino
191 lines (142 loc) · 4.25 KB
/
encodertest.ino
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#include <LiquidCrystal_I2C.h>
#include <LCD.h>
#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h> //http://playground.arduino.cc/Code/Time
#include <Wire.h> //http://arduino.cc/en/Reference/Wire
#define I2C_ADDR 0x27
// these pins below are for pcf8574 from i2c adapter, not arduino
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
#define ENC_CLK_PIN 2 // encoder clock pin (also with interrupt attached to it)
#define ENC_DATA_PIN 11 // encoder data pin
#define ENC_SW_PIN 10 // encoder switch pin
#define MODE_NORMAL 0
#define MODE_EDIT_HOUR 1
#define MODE_EDIT_MINUTE 2
#define TOTAL_MODES 3 // total number of modes
#define EDIT_UNDEF -9999 // undefined value for editedValue
byte currentMode = MODE_NORMAL;
int editedValue = EDIT_UNDEF;
unsigned long lastEncoderRead;
byte encoderSwitchState = LOW;
byte prevEncoderSwitchState;
byte hoursValid[] = {0, 23};
byte minutesValid[] = {0, 59};
// lcd init
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);
void setup()
{
// init lcd
lcd.begin(20,4);
lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
lcd.setBacklight(HIGH);
pinMode(ENC_CLK_PIN, INPUT);
pinMode(ENC_DATA_PIN, INPUT);
pinMode(ENC_SW_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(ENC_CLK_PIN), handleEncoderClockInterrupt, CHANGE);
setSyncProvider(RTC.get);
}
void loop()
{
encoderSwitchState = digitalRead(ENC_SW_PIN);
// switch modes in loop
if(prevEncoderSwitchState != encoderSwitchState && encoderSwitchState) {
if(currentMode < TOTAL_MODES - 1) {
currentMode++;
} else {
currentMode = 0;
}
editedValue = EDIT_UNDEF; // reset edited value each time when mode changes
}
prevEncoderSwitchState = encoderSwitchState; // remember last to be able to detect state change on next iteration
updateEditedValue();
updateLcd();
delay(100);
}
void handleEncoderClockInterrupt()
{
if(currentMode == MODE_NORMAL) return; // ignore if not in edit mode
unsigned long currTime = micros();
int incr = currTime - lastEncoderRead < 5 * 1000 ? 10 : 1; // boost increment value when rotating rapidly, 5ms between pulses
if(digitalRead(ENC_CLK_PIN) == digitalRead(ENC_DATA_PIN)) { // check rotation direction - CW or CCW
editedValue += incr;
} else {
editedValue -= incr;
}
lastEncoderRead = currTime;
}
void updateEditedValue()
{
// TODO check if edited value was actually changed before proceeding
if (currentMode == MODE_NORMAL) return; // ignore if not in edit mode
time_t tSet;
tmElements_t tm;
RTC.read(tm);
if (currentMode == MODE_EDIT_HOUR) {
if(editedValue == EDIT_UNDEF) editedValue = tm.Hour;
if(editedValue > hoursValid[1]) {
editedValue = hoursValid[0];
} else if (editedValue < hoursValid[0]) {
editedValue = hoursValid[1];
}
tm.Hour = editedValue;
tSet = makeTime(tm);
RTC.set(tSet);
setTime(tSet);
} else if (currentMode == MODE_EDIT_MINUTE) {
if(editedValue == EDIT_UNDEF) editedValue = tm.Minute;
if(editedValue > minutesValid[1]) {
editedValue = minutesValid[0];
} else if (editedValue < minutesValid[0]) {
editedValue = minutesValid[1];
}
tm.Minute = editedValue;
tSet = makeTime(tm);
RTC.set(tSet);
setTime(tSet);
}
}
void updateLcd() {
lcd.setCursor(0, 0);
lcd.print(modeToLabel(currentMode));
lcd.setCursor(0, 1);
if(editedValue == EDIT_UNDEF) {
lcd.print("<None>");
} else {
lcd.print(editedValue);
}
lcd.print(" ");
// int c = RTC.temperature();
// lcd.setCursor(12, 2);
// lcd.write(c);
// lcd.write("C");
// display time
lcd.setCursor(12, 3);
printZeroPadded(hour());
lcd.write(':');
printZeroPadded(minute());
lcd.write(':');
printZeroPadded(second());
}
char* modeToLabel(byte mode) {
switch(mode) {
case MODE_EDIT_HOUR:
return "Edit hour ";
case MODE_EDIT_MINUTE:
return "Edit minute";
case MODE_NORMAL:
return "Normal ";
}
}
void printZeroPadded(int num) {
if(num >= 0 && num < 10) {
lcd.write('0');
}
lcd.print(num, DEC);
}