Skip to content

Commit 955dac0

Browse files
committed
add logic to workout hall state, angle, speed
1 parent 39ffb63 commit 955dac0

File tree

2 files changed

+98
-67
lines changed

2 files changed

+98
-67
lines changed

src/HallSensor.cpp

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,94 +24,108 @@ HallSensor::HallSensor(int _hallA, int _hallB, int _hallC, int _pp){
2424
C_active = 0;
2525

2626
// velocity calculation variables
27-
prev_Th = 0;
28-
pulse_per_second = 0;
27+
2928
prev_pulse_counter = 0;
3029
prev_timestamp_us = _micros();
3130

3231
// extern pullup as default
3332
pullup = Pullup::EXTERN;
34-
3533
}
3634

3735
// HallSensor interrupt callback functions
3836
// A channel
3937
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();
4740
}
4841
// B channel
4942
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();
5845
}
5946

6047
// C channel
6148
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;
6892
}
69-
93+
94+
// setting sensor.reverse in setup() will reverse direction
95+
direction = static_cast<Direction>(rawDirection * reverse);
96+
return direction; // * goofy;
7097
}
7198

7299
/*
73100
Shaft angle calculation
74101
*/
75102
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;
77121
}
78122
/*
79123
Shaft velocity calculation
80124
function using mixed time and frequency measurement technique
81125
*/
82126
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;
115129
}
116130

117131
// getter for index pin
@@ -131,10 +145,6 @@ float HallSensor::initRelativeZero(){
131145
float HallSensor::initAbsoluteZero(){
132146
return 0.0;
133147
}
134-
// private function used to determine if HallSensor has index
135-
int HallSensor::hasIndex(){
136-
return 0;
137-
}
138148

139149
// HallSensor initialisation of the hardware pins
140150
// and calculation variables
@@ -154,9 +164,6 @@ void HallSensor::init(){
154164
// counter setup
155165
pulse_counter = 0;
156166
pulse_timestamp = _micros();
157-
// velocity calculation variables
158-
prev_Th = 0;
159-
pulse_per_second = 0;
160167
prev_pulse_counter = 0;
161168
prev_timestamp_us = _micros();
162169

src/HallSensor.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@
55
#include "FOCutils.h"
66
#include "Sensor.h"
77

8+
/**
9+
* Direction structure
10+
*/
11+
enum Direction{
12+
CW = 1, //clockwise
13+
CCW = -1, // counter clockwise
14+
UNKNOWN = 0 //not yet known or invalid state
15+
};
16+
817
class HallSensor: public Sensor{
918
public:
1019
/**
@@ -76,8 +85,22 @@ class HallSensor: public Sensor{
7685
*/
7786
int needsAbsoluteZeroSearch();
7887

88+
// set sensor.reverse to -1 to reverse direction (and thus angle) outputed by sensor
89+
int reverse = 1;
90+
91+
// whether last step was CW (+1) or CCW (-1) direction
92+
Direction direction;
93+
94+
// the current 3bit state of the hall sensors
95+
int state;
96+
97+
volatile float angle; // rad/s
98+
volatile float velocity; // rad/s
99+
79100
private:
80-
int hasIndex(); //!< function returning 1 if HallSensor has index pin and 0 if not.
101+
102+
Direction decodeDirection(int oldState, int newState);
103+
void updateState();
81104

82105
volatile long pulse_counter;//!< current pulse counter
83106
volatile long pulse_timestamp;//!< last impulse timestamp in us
@@ -86,8 +109,9 @@ class HallSensor: public Sensor{
86109
volatile int C_active; //!< current active states of Index channel
87110

88111
// velocity calculation variables
89-
float prev_Th, pulse_per_second;
112+
// float prev_Th, pulse_per_second;
90113
volatile long prev_pulse_counter, prev_timestamp_us;
114+
91115
};
92116

93117

0 commit comments

Comments
 (0)