@@ -24,94 +24,108 @@ HallSensor::HallSensor(int _hallA, int _hallB, int _hallC, int _pp){
24
24
C_active = 0 ;
25
25
26
26
// velocity calculation variables
27
- prev_Th = 0 ;
28
- pulse_per_second = 0 ;
27
+
29
28
prev_pulse_counter = 0 ;
30
29
prev_timestamp_us = _micros ();
31
30
32
31
// extern pullup as default
33
32
pullup = Pullup::EXTERN;
34
-
35
33
}
36
34
37
35
// HallSensor interrupt callback functions
38
36
// A channel
39
37
void HallSensor::handleA () {
40
- int A = digitalRead (pinA);
41
-
42
- if ( A != A_active ) {
43
- pulse_counter += (A_active == B_active) ? 1 : -1 ;
44
- pulse_timestamp = _micros ();
45
- A_active = A;
46
- }
38
+ A_active= digitalRead (pinA);
39
+ updateState ();
47
40
}
48
41
// B channel
49
42
void HallSensor::handleB () {
50
- int B = digitalRead (pinB);
51
-
52
- if ( B != B_active ) {
53
- pulse_counter += (A_active != B_active) ? 1 : -1 ;
54
- pulse_timestamp = _micros ();
55
- B_active = B;
56
- }
57
-
43
+ B_active = digitalRead (pinB);
44
+ updateState ();
58
45
}
59
46
60
47
// C channel
61
48
void HallSensor::handleC () {
62
- int C = digitalRead (pinB);
63
-
64
- if ( C != C_active ) {
65
- pulse_counter += (A_active != C_active) ? 1 : -1 ;
66
- pulse_timestamp = _micros ();
67
- C_active = C;
49
+ C_active = digitalRead (pinC);
50
+ updateState ();
51
+ }
52
+
53
+ void HallSensor::updateState () {
54
+ int newState = C_active + (B_active << 1 ) + (A_active << 2 );
55
+ Direction direction = decodeDirection (state, newState);
56
+ state = newState;
57
+ pulse_counter += direction;
58
+ pulse_timestamp = _micros ();
59
+ }
60
+
61
+ // determines whether the hallsensr state transition means that it has moved one step CW (+1), CCW (-1) or state transition is invalid (0)
62
+ // states are 3bits, one for each hall sensor
63
+ Direction HallSensor::decodeDirection (int oldState, int newState)
64
+ {
65
+ // here are expected state transitions (oldState > newState).
66
+ // CW state transitions are: ( 6 > 2 > 3 > 1 > 5 > 4 > 6 )
67
+ // CCW state transitions are: ( 6 > 4 > 5 > 1 > 3 > 2 > 6 )
68
+ // invalid state transitions are oldState == newState or if newState or oldState == 0 | 7 as hallsensors can't be all on or all off
69
+
70
+ int rawDirection;
71
+
72
+ if (
73
+ (oldState == 6 && newState == 2 ) || \
74
+ (oldState == 2 && newState == 3 ) || \
75
+ (oldState == 3 && newState == 1 ) || \
76
+ (oldState == 1 && newState == 5 ) || \
77
+ (oldState == 5 && newState == 4 ) || \
78
+ (oldState == 4 && newState == 6 )
79
+ ) {
80
+ rawDirection = Direction::CW;
81
+ } else if (
82
+ (oldState == 6 && newState == 4 ) || \
83
+ (oldState == 4 && newState == 5 ) || \
84
+ (oldState == 5 && newState == 1 ) || \
85
+ (oldState == 1 && newState == 3 ) || \
86
+ (oldState == 3 && newState == 2 ) || \
87
+ (oldState == 2 && newState == 6 )
88
+ ) {
89
+ rawDirection = Direction::CCW;
90
+ } else {
91
+ rawDirection = Direction::UNKNOWN;
68
92
}
69
-
93
+
94
+ // setting sensor.reverse in setup() will reverse direction
95
+ direction = static_cast <Direction>(rawDirection * reverse);
96
+ return direction; // * goofy;
70
97
}
71
98
72
99
/*
73
100
Shaft angle calculation
74
101
*/
75
102
float HallSensor::getAngle (){
76
- return _2PI * (pulse_counter) / ((float )cpr);
103
+
104
+ long dN = pulse_counter - prev_pulse_counter;
105
+
106
+ if (dN != 0 )
107
+ {
108
+
109
+ // time from last impulse
110
+ float Th = (pulse_timestamp - prev_timestamp_us) * 1e-6 ;
111
+ if (Th <= 0 || Th > 0.5 )
112
+ Th = 1e-3 ;
113
+ // save variables for next pass
114
+ prev_timestamp_us = pulse_timestamp;
115
+ prev_pulse_counter = pulse_counter;
116
+ velocity = (float ) _2PI * dN / (cpr * Th);
117
+ }
118
+ angle = (float ) _2PI * pulse_counter / cpr;
119
+
120
+ return angle;
77
121
}
78
122
/*
79
123
Shaft velocity calculation
80
124
function using mixed time and frequency measurement technique
81
125
*/
82
126
float HallSensor::getVelocity (){
83
- // timestamp
84
- long timestamp_us = _micros ();
85
- // sampling time calculation
86
- float Ts = (timestamp_us - prev_timestamp_us) * 1e-6 ;
87
- // quick fix for strange cases (micros overflow)
88
- if (Ts <= 0 || Ts > 0.5 ) Ts = 1e-3 ;
89
-
90
- // time from last impulse
91
- float Th = (timestamp_us - pulse_timestamp) * 1e-6 ;
92
- long dN = pulse_counter - prev_pulse_counter;
93
-
94
- // Pulse per second calculation (Eq.3.)
95
- // dN - impulses received
96
- // Ts - sampling time - time in between function calls
97
- // Th - time from last impulse
98
- // Th_1 - time form last impulse of the previous call
99
- // only increment if some impulses received
100
- float dt = Ts + prev_Th - Th;
101
- pulse_per_second = (dN != 0 && dt > Ts/2 ) ? dN / dt : pulse_per_second;
102
-
103
- // if more than 0.05 passed in between impulses
104
- if ( Th > 0.1 ) pulse_per_second = 0 ;
105
-
106
- // velocity calculation
107
- float velocity = pulse_per_second / ((float )cpr) * (_2PI);
108
-
109
- // save variables for next pass
110
- prev_timestamp_us = timestamp_us;
111
- // save velocity calculation variables
112
- prev_Th = Th;
113
- prev_pulse_counter = pulse_counter;
114
- return (velocity);
127
+ // this is calculated during the last call to getAngle();
128
+ return velocity;
115
129
}
116
130
117
131
// getter for index pin
@@ -131,10 +145,6 @@ float HallSensor::initRelativeZero(){
131
145
float HallSensor::initAbsoluteZero (){
132
146
return 0.0 ;
133
147
}
134
- // private function used to determine if HallSensor has index
135
- int HallSensor::hasIndex (){
136
- return 0 ;
137
- }
138
148
139
149
// HallSensor initialisation of the hardware pins
140
150
// and calculation variables
@@ -154,9 +164,6 @@ void HallSensor::init(){
154
164
// counter setup
155
165
pulse_counter = 0 ;
156
166
pulse_timestamp = _micros ();
157
- // velocity calculation variables
158
- prev_Th = 0 ;
159
- pulse_per_second = 0 ;
160
167
prev_pulse_counter = 0 ;
161
168
prev_timestamp_us = _micros ();
162
169
0 commit comments