Skip to content

Commit aee0863

Browse files
committed
The return of the encoder test
1 parent 22bb160 commit aee0863

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

extras/encoder_test/encoder_test.ino

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// What input is associated with each control?
2+
#define CTRL_SEL A2 //main select button - must be equipped
3+
#define CTRL_UP A1 //main up/down buttons or rotary encoder - must be equipped
4+
#define CTRL_DN A0
5+
6+
#define ROT_VEL_START 80 //if encoder step rate falls below this, kick into high velocity set (x10)
7+
#define ROT_VEL_STOP 500 //if encoder step rate rises above this, drop into low velocity set (x1)
8+
9+
//This clock is 2x3 multiplexed: two tubes powered at a time.
10+
//The anode channel determines which two tubes are powered,
11+
//and the two SN74141 cathode driver chips determine which digits are lit.
12+
//4 pins out to each SN74141, representing a binary number with values [1,2,4,8]
13+
#define OUT_A1 2
14+
#define OUT_A2 3
15+
#define OUT_A3 4
16+
#define OUT_A4 5
17+
#define OUT_B1 6
18+
#define OUT_B2 7
19+
#define OUT_B3 8
20+
#define OUT_B4 9
21+
//3 pins out to anode channel switches
22+
#define ANODE_1 11
23+
#define ANODE_2 12
24+
#define ANODE_3 13
25+
26+
27+
#include <Wire.h>
28+
#include <Encoder.h>
29+
Encoder rot(CTRL_DN,CTRL_UP);
30+
31+
32+
byte theVal = 0;
33+
34+
35+
////////// Main code control //////////
36+
37+
void setup(){
38+
Serial.begin(9600);
39+
Wire.begin();
40+
initInputs();
41+
initOutputs();
42+
updateDisplay();
43+
}
44+
45+
void loop(){
46+
checkInputs(); //if inputs have changed, this will do things + updateDisplay as needed
47+
cycleDisplay(); //keeps the display hardware multiplexing cycle going
48+
//TODO why isn't the display working
49+
}
50+
51+
52+
////////// Control inputs //////////
53+
void initInputs(){
54+
//TODO are there no "loose" pins left floating after this? per https://electronics.stackexchange.com/q/37696/151805
55+
pinMode(CTRL_SEL, INPUT_PULLUP);
56+
pinMode(CTRL_UP, INPUT_PULLUP);
57+
pinMode(CTRL_DN, INPUT_PULLUP);
58+
}
59+
60+
void checkInputs(){
61+
checkRot();
62+
}
63+
64+
bool rotVel = 0; //high velocity setting (x10 rather than x1)
65+
unsigned long rotLastStep = 0; //timestamp of last completed step (detent)
66+
int rotLastVal = 0;
67+
void checkRot(){
68+
int rotCurVal = rot.read();
69+
if(rotCurVal!=rotLastVal){ //we've sensed a state change
70+
rotLastVal = rotCurVal;
71+
Serial.println(rotCurVal,DEC);
72+
if(rotCurVal>=4 || rotCurVal<=-4){ //we've completed a step of 4 states (this library doesn't seem to drop states much, so this is reasonably reliable)
73+
unsigned long now = millis();
74+
if((unsigned long)(now-rotLastStep)<=ROT_VEL_START) rotVel = 1; //kick into high velocity setting (x10)
75+
else if((unsigned long)(now-rotLastStep)>=ROT_VEL_STOP) rotVel = 0; //fall into low velocity setting (x1)
76+
rotLastStep = now;
77+
while(rotCurVal>=4) { rotCurVal-=4; theVal+=1; }
78+
while(rotCurVal<=-4) { rotCurVal+=4; theVal-=1; }
79+
rot.write(rotCurVal);
80+
updateDisplay();
81+
}
82+
}
83+
} //end checkRot()
84+
85+
86+
////////// Display data formatting //////////
87+
88+
byte displayNext[6] = {15,15,15,15,15,15};
89+
byte displayLast[6] = {15,15,15,15,15,15};
90+
91+
void updateDisplay(){
92+
Serial.print(F("---")); Serial.print(theVal,DEC); if(rotVel) Serial.print(F("!")); Serial.println();
93+
editDisplay(theVal,0,3,false,false);
94+
blankDisplay(4,5,false);
95+
}
96+
97+
void editDisplay(word n, byte posStart, byte posEnd, bool leadingZeros, bool fade){
98+
//Splits n into digits, sets them into displayNext in places posSt-posEnd (inclusive), with or without leading zeros
99+
//If there are blank places (on the left of a non-leading-zero number), uses value 15 to blank tube
100+
//If number has more places than posEnd-posStart, the higher places are truncated off (e.g. 10015 on 4 tubes --> 0015)
101+
word place;
102+
for(byte i=0; i<=posEnd-posStart; i++){
103+
switch(i){ //because int(pow(10,1))==10 but int(pow(10,2))==99...
104+
case 0: place=1; break;
105+
case 1: place=10; break;
106+
case 2: place=100; break;
107+
case 3: place=1000; break;
108+
case 4: place=10000; break;
109+
case 5: place=100000; break;
110+
default: break;
111+
}
112+
displayNext[posEnd-i] = (i==0&&n==0 ? 0 : (n>=place ? (n/place)%10 : (leadingZeros?0:15)));
113+
if(!fade) displayLast[posEnd-i] = displayNext[posEnd-i]; //cycleDisplay will be none the wiser
114+
}
115+
} //end editDisplay()
116+
void blankDisplay(byte posStart, byte posEnd, byte fade){
117+
for(byte i=posStart; i<=posEnd; i++) { displayNext[i]=15; if(!fade) displayLast[i]=15; }
118+
} //end blankDisplay();
119+
120+
121+
////////// Hardware outputs //////////
122+
123+
byte binOutA[4] = {OUT_A1,OUT_A2,OUT_A3,OUT_A4};
124+
byte binOutB[4] = {OUT_B1,OUT_B2,OUT_B3,OUT_B4};
125+
byte anodes[3] = {ANODE_1,ANODE_2,ANODE_3};
126+
127+
const int fadeLastDur = 5;
128+
const int fadeNextDur = 0;
129+
130+
void initOutputs() {
131+
for(byte i=0; i<4; i++) { pinMode(binOutA[i],OUTPUT); pinMode(binOutB[i],OUTPUT); }
132+
for(byte i=0; i<3; i++) { pinMode(anodes[i],OUTPUT); }
133+
}
134+
135+
void cycleDisplay(){
136+
//Anode channel 0: tubes #2 (min x10) and #5 (sec x1)
137+
setCathodes(displayLast[2],displayLast[5]); //Via d2b decoder chip, set cathodes to old digits
138+
digitalWrite(anodes[0], HIGH); //Turn on tubes
139+
delay(fadeLastDur); //Display for fade-out cycles
140+
setCathodes(displayNext[2],displayNext[5]); //Switch cathodes to new digits
141+
delay(fadeNextDur); //Display for fade-in cycles
142+
digitalWrite(anodes[0], LOW); //Turn off tubes
143+
144+
//Anode channel 1: tubes #4 (sec x10) and #1 (hour x1)
145+
setCathodes(displayLast[4],displayLast[1]);
146+
digitalWrite(anodes[1], HIGH);
147+
delay(fadeLastDur);
148+
setCathodes(displayNext[4],displayNext[1]);
149+
delay(fadeNextDur);
150+
digitalWrite(anodes[1], LOW);
151+
152+
//Anode channel 2: tubes #0 (hour x10) and #3 (min x1)
153+
setCathodes(displayLast[0],displayLast[3]);
154+
digitalWrite(anodes[2], HIGH);
155+
delay(fadeLastDur);
156+
setCathodes(displayNext[0],displayNext[3]);
157+
delay(fadeNextDur);
158+
digitalWrite(anodes[2], LOW);
159+
} //end cycleDisplay()
160+
161+
void setCathodes(byte decValA, byte decValB){
162+
bool binVal[4]; //4-bit binary number with values [1,2,4,8]
163+
decToBin(binVal,decValA); //have binary value of decVal set into binVal
164+
for(byte i=0; i<4; i++) digitalWrite(binOutA[i],binVal[i]); //set bin inputs of SN74141
165+
decToBin(binVal,decValB);
166+
for(byte i=0; i<4; i++) digitalWrite(binOutB[i],binVal[i]); //set bin inputs of SN74141
167+
} //end setCathodes()
168+
169+
void decToBin(bool binVal[], byte i){
170+
//binVal is a reference (modify in place) of a binary number bool[4] with values [1,2,4,8]
171+
if(i<0 || i>15) i=15; //default value, turns tubes off
172+
binVal[3] = int(i/8)%2;
173+
binVal[2] = int(i/4)%2;
174+
binVal[1] = int(i/2)%2;
175+
binVal[0] = i%2;
176+
} //end decToBin()

0 commit comments

Comments
 (0)