Using a HDD motor as RotaryEncoder.
Use this schematic: Instructables HDDJ Use for: R11, R12, R13 100 Ohms and for: R14, R15, 13 20kOhms so you get a better resolution.
This rotary encoder uses none interrups. The INPUT pins are polled in the main loop. So use no delay functions. When the main loop needs to much time the encoder can't read the rotary.
// Declaration of RotaryEncoder RotaryEncoder rotaryEncoder = RotaryEncoder(2,3,4);
// Pins for LED's show the Toward int pinTowardLeft = 12; int pinTowardRight = 10;
void setup() {
pinMode(pinTowardLeft, OUTPUT); pinMode(pinTowardRight, OUTPUT);
}
void loop() {
int toward = rotaryEncoder.getToward();
switch(toward) { case -1: digitalWrite(pinTowardLeft, HIGH); digitalWrite(pinTowardRight, LOW); delay(1); break;
case 0: digitalWrite(pinTowardLeft, LOW); digitalWrite(pinTowardRight, LOW); break; case 1: digitalWrite(pinTowardLeft, LOW); digitalWrite(pinTowardRight, HIGH); delay(1); break; }
}
The cpp file.
RotaryEncoder::RotaryEncoder(int phaseOne, int phaseTow, int phaseThree) {
PINS_Phases[0] = phaseOne; // Pin Number where digtal signal of phase one PINS_Phases[1] = phaseTow; // Pin Number where digtal signal of phase two PINS_Phases[2] = phaseThree; // Pin Number where digtal signal of phase three
pinMode(phaseOne, INPUT); pinMode(phaseOne, INPUT); pinMode(phaseOne, INPUT);
for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { flankMap[i][j] = false; } }
}
int RotaryEncoder::getToward() {
// return -1 for rotating left // return 0 for none rotating // return 1 for rotating right int rotation = 0; int firstHigh = -1; fillData();
for(int i = 0; i < 3; i++) { if(flankMap[0][i]) { firstHigh = i; } }
if(firstHigh > -1) { int pos[3] = {0,0,0}; pos[0] = firstHigh; pos[1] = nextPosition(firstHigh,true); pos[2] = nextPosition(pos[1],true);
// if last state filled the map will shift one to left if(flankMap[0][pos[0]] && flankMap[1][pos[1]] && flankMap[2][pos[2]]) { rotation = 1; shiftMapLeft(); } else { pos[0] = firstHigh; pos[1] = nextPosition(firstHigh,false); pos[2] = nextPosition(pos[1],false);
if(flankMap[0][pos[0]] && flankMap[1][pos[1]] && flankMap[2][pos[2]]) { rotation = -1; shiftMapLeft(); } } } return rotation;
}
bool RotaryEncoder::risePin(int pinNumber, int lastState) // search rises on a pin {
int currentState = digitalRead(pinNumber); bool retrunVal = false;
if(currentState == HIGH && lastState == LOW) { retrunVal = true; } return retrunVal;
}
void RotaryEncoder::shiftMapLeft() // shift the map one to left {
for(int i = 0; i < 3; i++) { flankMap[i][0] = flankMap[i][1]; flankMap[i][1] = flankMap[i][2]; flankMap[i][2] = false; }
}
void RotaryEncoder::fillData() // fill the flankMap with data {
bool wasFlank[3] = {false, false, false}; for(int i = 0; i < 3; i++) { wasFlank[i] = risePin(PINS_Phases[i], lastStates[i]); lastStates[i] = digitalRead(PINS_Phases[i]); } int countFlanks = 0; int phaseFlank = -1; for(int i = 0; i< 3;i++) { if(wasFlank[i]) { countFlanks++; phaseFlank = i; } } if(countFlanks == 1) { if(flankMap[0][2] || flankMap[1][2] || flankMap[2][2]) { shiftMapLeft(); } for(int i = 0; i < 3; i++) { flankMap[i][2] = wasFlank[i]; } }
}
int RotaryEncoder::nextPosition(int startPos, bool right) {
int pos = 0; if(right) { switch(startPos) { case 0: pos = 1; break; case 1: pos = 2; break; case 2: pos = 0; break; } } else { switch(startPos) { case 0: pos = 2; break; case 1: pos = 0; break; case 2: pos = 1; break; } } return pos;
}
The header file:
class RotaryEncoder {
private: int PINS_Phases[3]; int lastStates[3]; bool flankMap[3][3];
bool risePin(int pinNumber, int lastState); void shiftMapLeft(); void fillData(); int nextPosition(int startPos, bool right);
public:
RotaryEncoder(int phaseOne, int phaseTow, int phaseThree);
int getToward();
};