Skip to content

Commit 98a10e4

Browse files
committed
Reduced interrupt blocking time
Changed interrupt-based sensors to only copy volatile variables during interrupt-blocking sections, and do computations with them after re-enabling interrupts.
1 parent 5e35fb8 commit 98a10e4

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

src/sensors/Encoder.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,14 @@ void Encoder::handleIndex() {
101101

102102
// Sensor update function. Safely copy volatile interrupt variables into Sensor base class state variables.
103103
void Encoder::update() {
104+
// Copy volatile variables in minimal-duration blocking section to ensure no interrupts are missed
104105
noInterrupts();
105-
// TODO: numerical precision issue here if the pulse_counter overflows the angle will be lost
106-
full_rotations = pulse_counter / (int)cpr;
107-
angle_prev = _2PI * ((pulse_counter) % ((int)cpr)) / ((float)cpr);
108106
angle_prev_ts = pulse_timestamp;
107+
long copy_pulse_counter = pulse_counter;
109108
interrupts();
109+
// TODO: numerical precision issue here if the pulse_counter overflows the angle will be lost
110+
full_rotations = copy_pulse_counter / (int)cpr;
111+
angle_prev = _2PI * ((copy_pulse_counter) % ((int)cpr)) / ((float)cpr);
110112
}
111113

112114
/*
@@ -123,8 +125,11 @@ float Encoder::getSensorAngle(){
123125
function using mixed time and frequency measurement technique
124126
*/
125127
float Encoder::getVelocity(){
126-
// Make sure no interrupts modify the state variables in the middle of these calculations
128+
// Copy volatile variables in minimal-duration blocking section to ensure no interrupts are missed
127129
noInterrupts();
130+
long copy_pulse_counter = pulse_counter;
131+
long copy_pulse_timestamp = pulse_timestamp;
132+
interrupts();
128133
// timestamp
129134
long timestamp_us = _micros();
130135
// sampling time calculation
@@ -133,8 +138,8 @@ float Encoder::getVelocity(){
133138
if(Ts <= 0 || Ts > 0.5f) Ts = 1e-3f;
134139

135140
// time from last impulse
136-
float Th = (timestamp_us - pulse_timestamp) * 1e-6f;
137-
long dN = pulse_counter - prev_pulse_counter;
141+
float Th = (timestamp_us - copy_pulse_timestamp) * 1e-6f;
142+
long dN = copy_pulse_counter - prev_pulse_counter;
138143

139144
// Pulse per second calculation (Eq.3.)
140145
// dN - impulses received
@@ -155,9 +160,7 @@ float Encoder::getVelocity(){
155160
prev_timestamp_us = timestamp_us;
156161
// save velocity calculation variables
157162
prev_Th = Th;
158-
prev_pulse_counter = pulse_counter;
159-
// Re-enable interrupts (ideally this would restore to the previous state rather than unconditionally enabling)
160-
interrupts();
163+
prev_pulse_counter = copy_pulse_counter;
161164
return velocity;
162165
}
163166

src/sensors/HallSensor.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,14 @@ void HallSensor::attachSectorCallback(void (*_onSectorChange)(int sector)) {
9696

9797
// Sensor update function. Safely copy volatile interrupt variables into Sensor base class state variables.
9898
void HallSensor::update() {
99+
// Copy volatile variables in minimal-duration blocking section to ensure no interrupts are missed
99100
noInterrupts();
100-
angle_prev = ((float)((electric_rotations * 6 + electric_sector) % cpr) / (float)cpr) * _2PI ;
101-
full_rotations = (int32_t)((electric_rotations * 6 + electric_sector) / cpr);
102101
angle_prev_ts = pulse_timestamp;
102+
long last_electric_rotations = electric_rotations;
103+
int8_t last_electric_sector = electric_sector;
103104
interrupts();
105+
angle_prev = ((float)((last_electric_rotations * 6 + last_electric_sector) % cpr) / (float)cpr) * _2PI ;
106+
full_rotations = (int32_t)((last_electric_rotations * 6 + last_electric_sector) / cpr);
104107
}
105108

106109

@@ -119,14 +122,16 @@ float HallSensor::getSensorAngle() {
119122
*/
120123
float HallSensor::getVelocity(){
121124
noInterrupts();
122-
float vel = 0;
123-
if (pulse_diff != 0 && ((long)(_micros() - pulse_timestamp) < pulse_diff*2) ) // last velocity isn't accurate if too old
124-
vel = direction * (_2PI / (float)cpr) / (pulse_diff / 1000000.0f);
125+
long last_pulse_timestamp = pulse_timestamp;
126+
long last_pulse_diff = pulse_diff;
125127
interrupts();
126-
return vel;
127-
}
128-
128+
if (last_pulse_diff == 0 || ((long)(_micros() - last_pulse_timestamp) > last_pulse_diff*2) ) { // last velocity isn't accurate if too old
129+
return 0;
130+
} else {
131+
return direction * (_2PI / (float)cpr) / (last_pulse_diff / 1000000.0f);
132+
}
129133

134+
}
130135

131136
// HallSensor initialisation of the hardware pins
132137
// and calculation variables

0 commit comments

Comments
 (0)