Skip to content

Commit f1c1d0f

Browse files
Merge pull request #58 from Schnilz/dev
CalibratedSensor: Allow saving of lut at runtime
2 parents 9b47aa9 + 5dc0563 commit f1c1d0f

File tree

3 files changed

+47
-28
lines changed

3 files changed

+47
-28
lines changed

examples/encoders/calibrated_sensor/calibration_save/calibration_save.ino

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
/**
22
* The example demonstrates the calibration of the magnetic sensor with the calibration procedure and saving the calibration data.
33
* So that the calibration procedure does not have to be run every time the motor is powered up.
4+
*
5+
* 1. Run this Sketch as is and wait for the calibration data to be generated and printed over Serial.
6+
* 2. Then copy the output from Serial to calibrationLut, zero_electric_angle and sensor_direction
7+
* 3. Change values_provided to true and run the Sketch again to see the motor skipping the calibration.
48
*/
59

610
#include <SimpleFOC.h>
@@ -10,7 +14,9 @@
1014
// fill this array with the calibration values outputed by the calibration procedure
1115
float calibrationLut[50] = {0};
1216
float zero_electric_angle = 0;
13-
Direction sensor_direction = Direction::CW;
17+
Direction sensor_direction = Direction::UNKNOWN;
18+
19+
const bool values_provided = false;
1420

1521
// magnetic sensor instance - SPI
1622
MagneticSensorSPI sensor = MagneticSensorSPI(AS5147_SPI, 14);
@@ -22,7 +28,8 @@ StepperDriver4PWM driver = StepperDriver4PWM(10, 9, 5, 6,8);
2228
// argument 1 - sensor object
2329
// argument 2 - number of samples in the LUT (default 200)
2430
// argument 3 - pointer to the LUT array (defualt nullptr)
25-
CalibratedSensor sensor_calibrated = CalibratedSensor(sensor, 50);
31+
CalibratedSensor sensor_calibrated = CalibratedSensor(
32+
sensor, sizeof(calibrationLut) / sizeof(calibrationLut[0]));
2633

2734
// voltage set point variable
2835
float target_voltage = 2;
@@ -57,9 +64,13 @@ void setup() {
5764
// initialize motor
5865
motor.init();
5966

60-
// Running calibration
61-
// the function will setup everything for the provided calibration LUT
62-
sensor_calibrated.calibrate(motor, calibrationLut, zero_electric_angle, sensor_direction);
67+
if(values_provided) {
68+
motor.zero_electric_angle = zero_electric_angle;
69+
motor.sensor_direction = sensor_direction;
70+
} else {
71+
// Running calibration
72+
sensor_calibrated.calibrate(motor);
73+
}
6374

6475
// Linking sensor to motor object
6576
motor.linkSensor(&sensor_calibrated);

src/encoders/calibrated/CalibratedSensor.cpp

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
// CalibratedSensor()
44
// sensor - instance of original sensor object
55
// n_lut - number of samples in the LUT
6-
CalibratedSensor::CalibratedSensor(Sensor &wrapped, int n_lut) : _wrapped(wrapped) {
7-
this->n_lut = n_lut;
8-
};
6+
CalibratedSensor::CalibratedSensor(Sensor &wrapped, int n_lut, float *lut)
7+
: _wrapped(wrapped), n_lut(n_lut), allocated(false), calibrationLut(lut) {
8+
};
99

1010
CalibratedSensor::~CalibratedSensor() {
1111
// delete calibrationLut;
12+
if(allocated) {
13+
delete []calibrationLut;
14+
}
1215
};
1316

1417
// call update of calibrated sensor
@@ -28,6 +31,9 @@ void CalibratedSensor::init()
2831
// Retrieve the calibrated sensor angle
2932
float CalibratedSensor::getSensorAngle()
3033
{
34+
if(!calibrationLut) {
35+
return _wrapped.getMechanicalAngle();
36+
}
3137
// raw encoder position e.g. 0-2PI
3238
float raw_angle = fmodf(_wrapped.getMechanicalAngle(), _2PI);
3339
raw_angle += raw_angle < 0 ? _2PI:0;
@@ -86,19 +92,15 @@ void CalibratedSensor::filter_error(float* error, float &error_mean, int n_ticks
8692

8793
}
8894

89-
void CalibratedSensor::calibrate(FOCMotor &motor, float* lut, float zero_electric_angle, Direction senor_direction, int settle_time_ms)
95+
void CalibratedSensor::calibrate(FOCMotor &motor, int settle_time_ms)
9096
{
9197
// if the LUT is already defined, skip the calibration
92-
if(lut != nullptr){
93-
motor.monitor_port->println("Using the provided LUT.");
94-
motor.zero_electric_angle = zero_electric_angle;
95-
motor.sensor_direction = senor_direction;
96-
this->calibrationLut = lut;
97-
return;
98-
}else{
99-
this->calibrationLut = new float[n_lut]();
100-
motor.monitor_port->println("Starting Sensor Calibration.");
98+
99+
if(calibrationLut == NULL) {
100+
allocated = true;
101+
calibrationLut = new float[n_lut];
101102
}
103+
motor.monitor_port->println("Starting Sensor Calibration.");
102104

103105
// Calibration variables
104106

@@ -174,11 +176,11 @@ void CalibratedSensor::calibrate(FOCMotor &motor, float* lut, float zero_electri
174176
_delay(settle_time_ms);
175177
_wrapped.update();
176178
// calculate the error
177-
theta_actual = motor.sensor_direction*(_wrapped.getAngle() - theta_init);
179+
theta_actual = (int)motor.sensor_direction * (_wrapped.getAngle() - theta_init);
178180
error[i] = 0.5 * (theta_actual - elec_angle / _NPP);
179181

180182
// calculate the current electrical zero angle
181-
float zero_angle = (motor.sensor_direction*_wrapped.getMechanicalAngle() * _NPP ) - (elec_angle + _PI_2);
183+
float zero_angle = ((int)motor.sensor_direction * _wrapped.getMechanicalAngle() * _NPP ) - (elec_angle + _PI_2);
182184
zero_angle = _normalizeAngle(zero_angle);
183185
// remove the 2PI jumps
184186
if(zero_angle - zero_angle_prev > _PI){
@@ -214,10 +216,10 @@ void CalibratedSensor::calibrate(FOCMotor &motor, float* lut, float zero_electri
214216
_delay(settle_time_ms);
215217
_wrapped.update();
216218
// calculate the error
217-
theta_actual = motor.sensor_direction*(_wrapped.getAngle() - theta_init);
219+
theta_actual = (int)motor.sensor_direction * (_wrapped.getAngle() - theta_init);
218220
error[i] += 0.5 * (theta_actual - elec_angle / _NPP);
219221
// calculate the current electrical zero angle
220-
float zero_angle = (motor.sensor_direction*_wrapped.getMechanicalAngle() * _NPP ) - (elec_angle + _PI_2);
222+
float zero_angle = ((int)motor.sensor_direction * _wrapped.getMechanicalAngle() * _NPP ) - (elec_angle + _PI_2);
221223
zero_angle = _normalizeAngle(zero_angle);
222224
// remove the 2PI jumps
223225
if(zero_angle - zero_angle_prev > _PI){
@@ -272,7 +274,7 @@ void CalibratedSensor::calibrate(FOCMotor &motor, float* lut, float zero_electri
272274
if (ind < 0) ind += n_lut;
273275
calibrationLut[ind] = (float)(error[(int)(i * dn)] - error_mean);
274276
// negate the error if the sensor is in the opposite direction
275-
calibrationLut[ind] = motor.sensor_direction * calibrationLut[ind];
277+
calibrationLut[ind] = (int)motor.sensor_direction * calibrationLut[ind];
276278
}
277279
motor.monitor_port->println("");
278280
_delay(1000);

src/encoders/calibrated/CalibratedSensor.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@
1010
class CalibratedSensor: public Sensor{
1111

1212
public:
13-
// constructor of class with pointer to base class sensor and driver
14-
CalibratedSensor(Sensor& wrapped, int n_lut = 200);
13+
/**
14+
* @brief Constructor of class with pointer to base class sensor and driver
15+
* @param wrapped the wrapped sensor which needs calibration
16+
* @param n_lut the number of entries in the lut
17+
* @param lut the look up table (if null, the lut will be allocated on the heap)
18+
*/
19+
CalibratedSensor(Sensor& wrapped, int n_lut = 200, float* lut = nullptr);
1520

1621
~CalibratedSensor();
1722

@@ -23,7 +28,7 @@ class CalibratedSensor: public Sensor{
2328
/**
2429
* Calibrate method computes the LUT for the correction
2530
*/
26-
virtual void calibrate(FOCMotor& motor, float* lut = nullptr, float zero_electric_angle = 0.0, Direction senor_direction= Direction::CW, int settle_time_ms = 30);
31+
virtual void calibrate(FOCMotor& motor, int settle_time_ms = 30);
2732

2833
// voltage to run the calibration: user input
2934
float voltage_calibration = 1;
@@ -49,9 +54,10 @@ class CalibratedSensor: public Sensor{
4954

5055
// lut size - settable by the user
5156
int n_lut { 200 } ;
52-
// create pointer for lut memory
57+
// pointer for lut memory
5358
// depending on the size of the lut
54-
// will be allocated in the constructor
59+
// will be allocated in the calibrate function if not given.
60+
bool allocated;
5561
float* calibrationLut;
5662
};
5763

0 commit comments

Comments
 (0)