forked from hoantv/VNWheel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Encoder.cpp
102 lines (92 loc) · 2.69 KB
/
Encoder.cpp
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
#include "Encoder.h"
#include "DigitalWriteFast.h"
Encoder::Encoder() {
pinMode (encoderPinA, INPUT_PULLUP);
pinMode (encoderPinB, INPUT_PULLUP);
pinMode (encoderPinZ, INPUT_PULLUP);
}
Encoder::~Encoder() {
}
void Encoder::setConfig(WheelConfig wheelConfig) {
cPR = wheelConfig.configCPR ;
maxAngle = wheelConfig.configMaxAngle;
inverted = wheelConfig.configInverted;
resetPosition = wheelConfig.configResetEncoderPosition;
maxValue = (float)maxAngle / 2 / 360 * cPR ;
minValue = -maxValue;
usePinZ = wheelConfig.configUsePinZ;
initVariables();
}
void Encoder::initVariables() {
currentPosition = 0;
lastPosition = 0;
correctPosition = 0;
currentPinA = LOW;
currentPinB = LOW;
currentPinZ = LOW;
lastPinA = LOW;
lastPinB = LOW;
lastPinZ = LOW;
z1stUp = false;
maxAcceleration = 0;
maxVelocity = 0;
lastEncoderTime = (uint32_t) millis();
lastVelocity = 0;
}
void Encoder::updatePosition() {
if (usePinZ) {
currentPinZ = digitalReadFast(encoderPinZ);
if (z1stUp) {
correctPosition = correctPosition; //found correct position
z1stUp = true;
} else {
if (currentPosition > correctPosition * 0.05 || currentPosition < correctPosition * 0.05 ) {
currentPosition = correctPosition;
}
}
}
positionChange = currentPosition - lastPosition;
uint32_t currentEncoderTime = (int32_t) millis();
int16_t diffTime = (int16_t)(currentEncoderTime - lastEncoderTime) ;
if (diffTime > 0) {
currentVelocity = positionChange / diffTime;
currentAcceleration = (abs(currentVelocity) - abs(lastVelocity)) / diffTime;
lastEncoderTime = currentEncoderTime;
lastVelocity = currentVelocity;
}
lastPosition = currentPosition;
}
int8_t Encoder::parsePosition() { //4 state
if (lastPinA && lastPinB) {
if (!currentPinA && currentPinB) return 1;
if (currentPinA && !currentPinB) return -1;
}
else if (!lastPinA && lastPinB) {
if (!currentPinA && !currentPinB) return 1;
if (currentPinA && currentPinB) return -1;
}
else if (!lastPinA && !lastPinB) {
if (currentPinA && !currentPinB) return 1;
if (!currentPinA && currentPinB) return -1;
}
else if (lastPinA && !lastPinB) {
if (currentPinA && currentPinB) return 1;
if (!currentPinA && !currentPinB) return -1;
}
}
//this code copy from Rotary Encoder of Matthias Hertel
const int8_t KNOBDIR[] = {
0, -1, 1, 0,
1, 0, 0, -1,
-1, 0, 0, 1,
0, 1, -1, 0 };
void Encoder::tick(void)
{
int sig1 = digitalReadFast(encoderPinA);
int sig2 = digitalReadFast(encoderPinB);
int8_t thisState = sig1 | (sig2 << 1);
if (oldState != thisState) {
currentPosition += KNOBDIR[thisState | (oldState<<2)];
oldState = thisState;
}
}