-
Notifications
You must be signed in to change notification settings - Fork 719
Expand file tree
/
Copy pathSensor.cpp
More file actions
151 lines (122 loc) · 3.88 KB
/
Copy pathSensor.cpp
File metadata and controls
151 lines (122 loc) · 3.88 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "Sensor.h"
#include "../foc_utils.h"
#include "../time_utils.h"
void Sensor::update() {
angle_type val = getSensorAngle();
if (val<0) // sensor angles are strictly non-negative. Negative values are used to signal errors.
return; // TODO signal error, e.g. via a flag and counter
angle_prev_ts = _micros();
setAngleContinuous(val);
}
/** get current angular velocity (rad/s) */
float Sensor::getVelocity() {
// calculate sample time
// if timestamps were unsigned, we could get rid of this section, unsigned overflow handles it correctly
#ifdef INTEGER_ANGLE
angle_type Ts = angle_prev_ts - vel_angle_prev_ts;
#else
float Ts = (angle_prev_ts - vel_angle_prev_ts)*1e-6f;
#endif
#if 0
if (Ts < 0.0f) { // handle micros() overflow - we need to reset vel_angle_prev_ts
vel_angle_prev = angle_prev;
#ifndef INTEGER_ANGLE
vel_full_rotations = full_rotations;
#endif
vel_angle_prev_ts = angle_prev_ts;
return velocity;
}
#endif
if (Ts < min_elapsed_time) return velocity; // don't update velocity if deltaT is too small
// Calculate change in angle. Handles `full_rotations` integer wrap-arounds,
// and avoids float precision loss issues by keeping numbers small.
angle_type delta_angle = angle_prev - vel_angle_prev;
#ifndef INTEGER_ANGLE
const int32_t delta_full_rotations = full_rotations - vel_full_rotations;
if (delta_full_rotations) {
delta_angle += delta_full_rotations * _2PI;
}
#endif
#ifdef INTEGER_ANGLE
if (abs(delta_angle) > 0)
{
velocity = delta_angle * 1000000 * _2PI / (Ts * steps_per_revolution);
}
else
{
velocity = 0.0f;
}
#else
// floating point equality checks are bad, so instead we check that the angle change is very small
if (fabsf(delta_angle) > 1e-8f) {
velocity = delta_angle / Ts;
} else {
velocity = 0.0f;
}
#endif
// Always advance the velocity reference sample to avoid stale deltas/time windows.
vel_angle_prev = angle_prev;
#ifndef INTEGER_ANGLE
vel_full_rotations = full_rotations;
#endif
vel_angle_prev_ts = angle_prev_ts;
return velocity;
}
void Sensor::init() {
// initialize all the internal variables of Sensor to ensure a "smooth" startup (without a 'jump' from zero)
getSensorAngle(); // call once
delayMicroseconds(1);
vel_angle_prev = getSensorAngle(); // call again
vel_angle_prev_ts = _micros();
delay(1);
getSensorAngle(); // call once
delayMicroseconds(1);
angle_prev = getSensorAngle(); // call again
angle_prev_ts = _micros();
}
angle_type Sensor::getMechanicalAngle() {
return angle_prev;
}
float Sensor::getAngle(){
#ifdef INTEGER_ANGLE
return angle_prev / (float)steps_per_revolution * _2PI;
#else
return (float)full_rotations * _2PI + angle_prev;
#endif
}
double Sensor::getPreciseAngle() {
#ifdef INTEGER_ANGLE
return angle_prev / (double)steps_per_revolution * _2PI;
#else
return (double)full_rotations * (double)_2PI + (double)angle_prev;
#endif
}
int32_t Sensor::getFullRotations() {
#ifdef INTEGER_ANGLE
return angle_prev/steps_per_revolution;
#else
return full_rotations;
#endif
}
int Sensor::needsSearch() {
return 0; // default false
}
void Sensor::setAngleContinuous(angle_type sensor_angle)
{
#ifdef INTEGER_ANGLE
angle_type d_angle = sensor_angle - sensor_angle_prev;
if(abs(d_angle) > (steps_per_revolution/2) )
{
d_angle += d_angle > 0 ? -steps_per_revolution : steps_per_revolution;
}
angle_prev += d_angle;
sensor_angle_prev = sensor_angle;
#else
angle_type d_angle = sensor_angle - angle_prev;
if(abs(d_angle) > (0.8f*_2PI) )
{
full_rotations += ( d_angle > 0 ) ? -1 : 1;
}
angle_prev = sensor_angle;
#endif
}