zebra
/
ZebraJointController
zebra joint controller firmware (originally from MIT HKC motor controller by benkatz)
Calibration/calibration.cpp@47:e1196a851f76, 2018-12-05 (annotated)
- Committer:
- benkatz
- Date:
- Wed Dec 05 04:07:46 2018 +0000
- Revision:
- 47:e1196a851f76
- Parent:
- 46:2d4b1dafcfe3
- Child:
- 52:8e74c22ed89f
albert revision;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
benkatz | 22:60276ba87ac6 | 1 | /// Calibration procedures for determining position sensor offset, |
benkatz | 22:60276ba87ac6 | 2 | /// phase ordering, and position sensor linearization |
benkatz | 22:60276ba87ac6 | 3 | /// |
benkatz | 22:60276ba87ac6 | 4 | |
benkatz | 22:60276ba87ac6 | 5 | #include "calibration.h" |
benkatz | 23:2adf23ee0305 | 6 | #include "foc.h" |
benkatz | 23:2adf23ee0305 | 7 | #include "PreferenceWriter.h" |
benkatz | 23:2adf23ee0305 | 8 | #include "user_config.h" |
benkatz | 44:8040fa2fcb0d | 9 | #include "motor_config.h" |
benkatz | 44:8040fa2fcb0d | 10 | #include "current_controller_config.h" |
benkatz | 22:60276ba87ac6 | 11 | |
benkatz | 23:2adf23ee0305 | 12 | void order_phases(PositionSensor *ps, GPIOStruct *gpio, ControllerStruct *controller, PreferenceWriter *prefs){ |
benkatz | 28:8c7e29f719c5 | 13 | |
benkatz | 22:60276ba87ac6 | 14 | ///Checks phase order, to ensure that positive Q current produces |
benkatz | 22:60276ba87ac6 | 15 | ///torque in the positive direction wrt the position sensor. |
benkatz | 22:60276ba87ac6 | 16 | printf("\n\r Checking phase ordering\n\r"); |
benkatz | 22:60276ba87ac6 | 17 | float theta_ref = 0; |
benkatz | 22:60276ba87ac6 | 18 | float theta_actual = 0; |
benkatz | 47:e1196a851f76 | 19 | float v_d = V_CAL; //Put all volts on the D-Axis |
benkatz | 44:8040fa2fcb0d | 20 | float v_q = 0.0f; |
benkatz | 22:60276ba87ac6 | 21 | float v_u, v_v, v_w = 0; |
benkatz | 44:8040fa2fcb0d | 22 | float dtc_u, dtc_v, dtc_w = .5f; |
benkatz | 22:60276ba87ac6 | 23 | int sample_counter = 0; |
benkatz | 22:60276ba87ac6 | 24 | |
benkatz | 22:60276ba87ac6 | 25 | ///Set voltage angle to zero, wait for rotor position to settle |
benkatz | 25:f5741040c4bb | 26 | abc(theta_ref, v_d, v_q, &v_u, &v_v, &v_w); //inverse dq0 transform on voltages |
benkatz | 25:f5741040c4bb | 27 | svm(1.0, v_u, v_v, v_w, &dtc_u, &dtc_v, &dtc_w); //space vector modulation |
benkatz | 22:60276ba87ac6 | 28 | for(int i = 0; i<20000; i++){ |
benkatz | 27:501fee691e0e | 29 | TIM1->CCR3 = (PWM_ARR>>1)*(1.0f-dtc_u); // Set duty cycles |
benkatz | 27:501fee691e0e | 30 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 31 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 32 | wait_us(100); |
benkatz | 22:60276ba87ac6 | 33 | } |
benkatz | 22:60276ba87ac6 | 34 | //ps->ZeroPosition(); |
benkatz | 47:e1196a851f76 | 35 | ps->Sample(DT); |
benkatz | 23:2adf23ee0305 | 36 | wait_us(1000); |
benkatz | 38:67e4e1453a4b | 37 | //float theta_start = ps->GetMechPositionFixed(); //get initial rotor position |
benkatz | 26:2b865c00d7e9 | 38 | float theta_start; |
benkatz | 23:2adf23ee0305 | 39 | controller->i_b = I_SCALE*(float)(controller->adc2_raw - controller->adc2_offset); //Calculate phase currents from ADC readings |
benkatz | 23:2adf23ee0305 | 40 | controller->i_c = I_SCALE*(float)(controller->adc1_raw - controller->adc1_offset); |
benkatz | 23:2adf23ee0305 | 41 | controller->i_a = -controller->i_b - controller->i_c; |
benkatz | 23:2adf23ee0305 | 42 | dq0(controller->theta_elec, controller->i_a, controller->i_b, controller->i_c, &controller->i_d, &controller->i_q); //dq0 transform on currents |
benkatz | 23:2adf23ee0305 | 43 | float current = sqrt(pow(controller->i_d, 2) + pow(controller->i_q, 2)); |
benkatz | 23:2adf23ee0305 | 44 | printf("\n\rCurrent\n\r"); |
benkatz | 23:2adf23ee0305 | 45 | printf("%f %f %f\n\r\n\r", controller->i_d, controller->i_q, current); |
benkatz | 22:60276ba87ac6 | 46 | /// Rotate voltage angle |
benkatz | 25:f5741040c4bb | 47 | while(theta_ref < 4*PI){ //rotate for 2 electrical cycles |
benkatz | 25:f5741040c4bb | 48 | abc(theta_ref, v_d, v_q, &v_u, &v_v, &v_w); //inverse dq0 transform on voltages |
benkatz | 25:f5741040c4bb | 49 | svm(1.0, v_u, v_v, v_w, &dtc_u, &dtc_v, &dtc_w); //space vector modulation |
benkatz | 22:60276ba87ac6 | 50 | wait_us(100); |
benkatz | 27:501fee691e0e | 51 | TIM1->CCR3 = (PWM_ARR>>1)*(1.0f-dtc_u); //Set duty cycles |
benkatz | 27:501fee691e0e | 52 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 53 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 47:e1196a851f76 | 54 | ps->Sample(DT); //sample position sensor |
benkatz | 38:67e4e1453a4b | 55 | theta_actual = ps->GetMechPositionFixed(); |
benkatz | 26:2b865c00d7e9 | 56 | if(theta_ref==0){theta_start = theta_actual;} |
benkatz | 22:60276ba87ac6 | 57 | if(sample_counter > 200){ |
benkatz | 22:60276ba87ac6 | 58 | sample_counter = 0 ; |
benkatz | 22:60276ba87ac6 | 59 | printf("%.4f %.4f\n\r", theta_ref/(NPP), theta_actual); |
benkatz | 22:60276ba87ac6 | 60 | } |
benkatz | 22:60276ba87ac6 | 61 | sample_counter++; |
benkatz | 22:60276ba87ac6 | 62 | theta_ref += 0.001f; |
benkatz | 22:60276ba87ac6 | 63 | } |
benkatz | 38:67e4e1453a4b | 64 | float theta_end = ps->GetMechPositionFixed(); |
benkatz | 22:60276ba87ac6 | 65 | int direction = (theta_end - theta_start)>0; |
benkatz | 22:60276ba87ac6 | 66 | printf("Theta Start: %f Theta End: %f\n\r", theta_start, theta_end); |
benkatz | 22:60276ba87ac6 | 67 | printf("Direction: %d\n\r", direction); |
benkatz | 23:2adf23ee0305 | 68 | if(direction){printf("Phasing correct\n\r");} |
benkatz | 22:60276ba87ac6 | 69 | else if(!direction){printf("Phasing incorrect. Swapping phases V and W\n\r");} |
benkatz | 23:2adf23ee0305 | 70 | PHASE_ORDER = direction; |
benkatz | 22:60276ba87ac6 | 71 | } |
benkatz | 22:60276ba87ac6 | 72 | |
benkatz | 22:60276ba87ac6 | 73 | |
benkatz | 23:2adf23ee0305 | 74 | void calibrate(PositionSensor *ps, GPIOStruct *gpio, ControllerStruct *controller, PreferenceWriter *prefs){ |
benkatz | 22:60276ba87ac6 | 75 | /// Measures the electrical angle offset of the position sensor |
benkatz | 22:60276ba87ac6 | 76 | /// and (in the future) corrects nonlinearity due to position sensor eccentricity |
benkatz | 22:60276ba87ac6 | 77 | printf("Starting calibration procedure\n\r"); |
benkatz | 46:2d4b1dafcfe3 | 78 | float * error_f; |
benkatz | 46:2d4b1dafcfe3 | 79 | float * error_b; |
benkatz | 46:2d4b1dafcfe3 | 80 | int * lut; |
benkatz | 46:2d4b1dafcfe3 | 81 | int * raw_f; |
benkatz | 46:2d4b1dafcfe3 | 82 | int * raw_b; |
benkatz | 46:2d4b1dafcfe3 | 83 | float * error; |
benkatz | 46:2d4b1dafcfe3 | 84 | float * error_filt; |
benkatz | 22:60276ba87ac6 | 85 | |
benkatz | 25:f5741040c4bb | 86 | const int n = 128*NPP; // number of positions to be sampled per mechanical rotation. Multiple of NPP for filtering reasons (see later) |
benkatz | 47:e1196a851f76 | 87 | const int n2 = 40; // increments between saved samples (for smoothing motion) |
benkatz | 25:f5741040c4bb | 88 | float delta = 2*PI*NPP/(n*n2); // change in angle between samples |
benkatz | 46:2d4b1dafcfe3 | 89 | error_f = new float[n](); // error vector rotating forwards |
benkatz | 46:2d4b1dafcfe3 | 90 | error_b = new float[n](); // error vector rotating backwards |
benkatz | 28:8c7e29f719c5 | 91 | const int n_lut = 128; |
benkatz | 46:2d4b1dafcfe3 | 92 | lut = new int[n_lut](); // clear any old lookup table before starting. |
benkatz | 46:2d4b1dafcfe3 | 93 | |
benkatz | 46:2d4b1dafcfe3 | 94 | error = new float[n](); |
benkatz | 46:2d4b1dafcfe3 | 95 | const int window = 128; |
benkatz | 46:2d4b1dafcfe3 | 96 | error_filt = new float[n](); |
benkatz | 46:2d4b1dafcfe3 | 97 | float cogging_current[window] = {0}; |
benkatz | 46:2d4b1dafcfe3 | 98 | |
benkatz | 28:8c7e29f719c5 | 99 | ps->WriteLUT(lut); |
benkatz | 46:2d4b1dafcfe3 | 100 | raw_f = new int[n](); |
benkatz | 46:2d4b1dafcfe3 | 101 | raw_b = new int[n](); |
benkatz | 22:60276ba87ac6 | 102 | float theta_ref = 0; |
benkatz | 22:60276ba87ac6 | 103 | float theta_actual = 0; |
benkatz | 47:e1196a851f76 | 104 | float v_d = V_CAL; // Put volts on the D-Axis |
benkatz | 44:8040fa2fcb0d | 105 | float v_q = 0.0f; |
benkatz | 22:60276ba87ac6 | 106 | float v_u, v_v, v_w = 0; |
benkatz | 44:8040fa2fcb0d | 107 | float dtc_u, dtc_v, dtc_w = .5f; |
benkatz | 22:60276ba87ac6 | 108 | |
benkatz | 22:60276ba87ac6 | 109 | |
benkatz | 22:60276ba87ac6 | 110 | ///Set voltage angle to zero, wait for rotor position to settle |
benkatz | 25:f5741040c4bb | 111 | abc(theta_ref, v_d, v_q, &v_u, &v_v, &v_w); // inverse dq0 transform on voltages |
benkatz | 25:f5741040c4bb | 112 | svm(1.0, v_u, v_v, v_w, &dtc_u, &dtc_v, &dtc_w); // space vector modulation |
benkatz | 22:60276ba87ac6 | 113 | for(int i = 0; i<40000; i++){ |
benkatz | 27:501fee691e0e | 114 | TIM1->CCR3 = (PWM_ARR>>1)*(1.0f-dtc_u); // Set duty cycles |
benkatz | 24:58c2d7571207 | 115 | if(PHASE_ORDER){ |
benkatz | 27:501fee691e0e | 116 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 117 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 118 | } |
benkatz | 22:60276ba87ac6 | 119 | else{ |
benkatz | 27:501fee691e0e | 120 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 121 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 122 | } |
benkatz | 22:60276ba87ac6 | 123 | wait_us(100); |
benkatz | 22:60276ba87ac6 | 124 | } |
benkatz | 47:e1196a851f76 | 125 | ps->Sample(DT); |
benkatz | 23:2adf23ee0305 | 126 | controller->i_b = I_SCALE*(float)(controller->adc2_raw - controller->adc2_offset); //Calculate phase currents from ADC readings |
benkatz | 23:2adf23ee0305 | 127 | controller->i_c = I_SCALE*(float)(controller->adc1_raw - controller->adc1_offset); |
benkatz | 23:2adf23ee0305 | 128 | controller->i_a = -controller->i_b - controller->i_c; |
benkatz | 23:2adf23ee0305 | 129 | dq0(controller->theta_elec, controller->i_a, controller->i_b, controller->i_c, &controller->i_d, &controller->i_q); //dq0 transform on currents |
benkatz | 23:2adf23ee0305 | 130 | float current = sqrt(pow(controller->i_d, 2) + pow(controller->i_q, 2)); |
benkatz | 26:2b865c00d7e9 | 131 | printf(" Current Angle : Rotor Angle : Raw Encoder \n\r\n\r"); |
benkatz | 25:f5741040c4bb | 132 | for(int i = 0; i<n; i++){ // rotate forwards |
benkatz | 22:60276ba87ac6 | 133 | for(int j = 0; j<n2; j++){ |
benkatz | 22:60276ba87ac6 | 134 | theta_ref += delta; |
benkatz | 25:f5741040c4bb | 135 | abc(theta_ref, v_d, v_q, &v_u, &v_v, &v_w); // inverse dq0 transform on voltages |
benkatz | 25:f5741040c4bb | 136 | svm(1.0, v_u, v_v, v_w, &dtc_u, &dtc_v, &dtc_w); // space vector modulation |
benkatz | 27:501fee691e0e | 137 | TIM1->CCR3 = (PWM_ARR>>1)*(1.0f-dtc_u); |
benkatz | 25:f5741040c4bb | 138 | if(PHASE_ORDER){ // Check phase ordering |
benkatz | 27:501fee691e0e | 139 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_v); // Set duty cycles |
benkatz | 27:501fee691e0e | 140 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 141 | } |
benkatz | 22:60276ba87ac6 | 142 | else{ |
benkatz | 27:501fee691e0e | 143 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 144 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 145 | } |
benkatz | 22:60276ba87ac6 | 146 | wait_us(100); |
benkatz | 47:e1196a851f76 | 147 | ps->Sample(DT); |
benkatz | 22:60276ba87ac6 | 148 | } |
benkatz | 47:e1196a851f76 | 149 | ps->Sample(DT); |
benkatz | 38:67e4e1453a4b | 150 | theta_actual = ps->GetMechPositionFixed(); |
benkatz | 22:60276ba87ac6 | 151 | error_f[i] = theta_ref/NPP - theta_actual; |
benkatz | 22:60276ba87ac6 | 152 | raw_f[i] = ps->GetRawPosition(); |
benkatz | 22:60276ba87ac6 | 153 | printf("%.4f %.4f %d\n\r", theta_ref/(NPP), theta_actual, raw_f[i]); |
benkatz | 22:60276ba87ac6 | 154 | //theta_ref += delta; |
benkatz | 22:60276ba87ac6 | 155 | } |
benkatz | 26:2b865c00d7e9 | 156 | |
benkatz | 25:f5741040c4bb | 157 | for(int i = 0; i<n; i++){ // rotate backwards |
benkatz | 22:60276ba87ac6 | 158 | for(int j = 0; j<n2; j++){ |
benkatz | 22:60276ba87ac6 | 159 | theta_ref -= delta; |
benkatz | 25:f5741040c4bb | 160 | abc(theta_ref, v_d, v_q, &v_u, &v_v, &v_w); // inverse dq0 transform on voltages |
benkatz | 25:f5741040c4bb | 161 | svm(1.0, v_u, v_v, v_w, &dtc_u, &dtc_v, &dtc_w); // space vector modulation |
benkatz | 27:501fee691e0e | 162 | TIM1->CCR3 = (PWM_ARR>>1)*(1.0f-dtc_u); |
benkatz | 24:58c2d7571207 | 163 | if(PHASE_ORDER){ |
benkatz | 27:501fee691e0e | 164 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 165 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 166 | } |
benkatz | 22:60276ba87ac6 | 167 | else{ |
benkatz | 27:501fee691e0e | 168 | TIM1->CCR1 = (PWM_ARR>>1)*(1.0f-dtc_v); |
benkatz | 27:501fee691e0e | 169 | TIM1->CCR2 = (PWM_ARR>>1)*(1.0f-dtc_w); |
benkatz | 22:60276ba87ac6 | 170 | } |
benkatz | 22:60276ba87ac6 | 171 | wait_us(100); |
benkatz | 47:e1196a851f76 | 172 | ps->Sample(DT); |
benkatz | 22:60276ba87ac6 | 173 | } |
benkatz | 47:e1196a851f76 | 174 | ps->Sample(DT); // sample position sensor |
benkatz | 38:67e4e1453a4b | 175 | theta_actual = ps->GetMechPositionFixed(); // get mechanical position |
benkatz | 22:60276ba87ac6 | 176 | error_b[i] = theta_ref/NPP - theta_actual; |
benkatz | 22:60276ba87ac6 | 177 | raw_b[i] = ps->GetRawPosition(); |
benkatz | 22:60276ba87ac6 | 178 | printf("%.4f %.4f %d\n\r", theta_ref/(NPP), theta_actual, raw_b[i]); |
benkatz | 22:60276ba87ac6 | 179 | //theta_ref -= delta; |
benkatz | 22:60276ba87ac6 | 180 | } |
benkatz | 22:60276ba87ac6 | 181 | |
benkatz | 22:60276ba87ac6 | 182 | float offset = 0; |
benkatz | 22:60276ba87ac6 | 183 | for(int i = 0; i<n; i++){ |
benkatz | 25:f5741040c4bb | 184 | offset += (error_f[i] + error_b[n-1-i])/(2.0f*n); // calclate average position sensor offset |
benkatz | 22:60276ba87ac6 | 185 | } |
benkatz | 25:f5741040c4bb | 186 | offset = fmod(offset*NPP, 2*PI); // convert mechanical angle to electrical angle |
benkatz | 23:2adf23ee0305 | 187 | |
benkatz | 22:60276ba87ac6 | 188 | |
benkatz | 25:f5741040c4bb | 189 | ps->SetElecOffset(offset); // Set position sensor offset |
benkatz | 23:2adf23ee0305 | 190 | __float_reg[0] = offset; |
benkatz | 23:2adf23ee0305 | 191 | E_OFFSET = offset; |
benkatz | 22:60276ba87ac6 | 192 | |
benkatz | 22:60276ba87ac6 | 193 | /// Perform filtering to linearize position sensor eccentricity |
benkatz | 22:60276ba87ac6 | 194 | /// FIR n-sample average, where n = number of samples in one electrical cycle |
benkatz | 22:60276ba87ac6 | 195 | /// This filter has zero gain at electrical frequency and all integer multiples |
benkatz | 25:f5741040c4bb | 196 | /// So cogging effects should be completely filtered out. |
benkatz | 22:60276ba87ac6 | 197 | |
benkatz | 46:2d4b1dafcfe3 | 198 | |
benkatz | 22:60276ba87ac6 | 199 | float mean = 0; |
benkatz | 25:f5741040c4bb | 200 | for (int i = 0; i<n; i++){ //Average the forward and back directions |
benkatz | 22:60276ba87ac6 | 201 | error[i] = 0.5f*(error_f[i] + error_b[n-i-1]); |
benkatz | 22:60276ba87ac6 | 202 | } |
benkatz | 22:60276ba87ac6 | 203 | for (int i = 0; i<n; i++){ |
benkatz | 22:60276ba87ac6 | 204 | for(int j = 0; j<window; j++){ |
benkatz | 25:f5741040c4bb | 205 | int ind = -window/2 + j + i; // Indexes from -window/2 to + window/2 |
benkatz | 22:60276ba87ac6 | 206 | if(ind<0){ |
benkatz | 25:f5741040c4bb | 207 | ind += n;} // Moving average wraps around |
benkatz | 22:60276ba87ac6 | 208 | else if(ind > n-1) { |
benkatz | 22:60276ba87ac6 | 209 | ind -= n;} |
benkatz | 22:60276ba87ac6 | 210 | error_filt[i] += error[ind]/(float)window; |
benkatz | 22:60276ba87ac6 | 211 | } |
benkatz | 23:2adf23ee0305 | 212 | if(i<window){ |
benkatz | 23:2adf23ee0305 | 213 | cogging_current[i] = current*sinf((error[i] - error_filt[i])*NPP); |
benkatz | 23:2adf23ee0305 | 214 | } |
benkatz | 22:60276ba87ac6 | 215 | //printf("%.4f %4f %.4f %.4f\n\r", error[i], error_filt[i], error_f[i], error_b[i]); |
benkatz | 22:60276ba87ac6 | 216 | mean += error_filt[i]/n; |
benkatz | 22:60276ba87ac6 | 217 | } |
benkatz | 25:f5741040c4bb | 218 | int raw_offset = (raw_f[0] + raw_b[n-1])/2; //Insensitive to errors in this direction, so 2 points is plenty |
benkatz | 28:8c7e29f719c5 | 219 | |
benkatz | 28:8c7e29f719c5 | 220 | |
benkatz | 23:2adf23ee0305 | 221 | printf("\n\r Encoder non-linearity compensation table\n\r"); |
benkatz | 46:2d4b1dafcfe3 | 222 | printf(" Sample Number : Lookup Index : Lookup Value\n\r\n\r"); |
benkatz | 25:f5741040c4bb | 223 | for (int i = 0; i<n_lut; i++){ // build lookup table |
benkatz | 22:60276ba87ac6 | 224 | int ind = (raw_offset>>7) + i; |
benkatz | 22:60276ba87ac6 | 225 | if(ind > (n_lut-1)){ |
benkatz | 22:60276ba87ac6 | 226 | ind -= n_lut; |
benkatz | 22:60276ba87ac6 | 227 | } |
benkatz | 22:60276ba87ac6 | 228 | lut[ind] = (int) ((error_filt[i*NPP] - mean)*(float)(ps->GetCPR())/(2.0f*PI)); |
benkatz | 46:2d4b1dafcfe3 | 229 | printf("%d %d %d \n\r", i, ind, lut[ind]); |
benkatz | 26:2b865c00d7e9 | 230 | wait(.001); |
benkatz | 22:60276ba87ac6 | 231 | } |
benkatz | 23:2adf23ee0305 | 232 | |
benkatz | 25:f5741040c4bb | 233 | ps->WriteLUT(lut); // write lookup table to position sensor object |
benkatz | 23:2adf23ee0305 | 234 | //memcpy(controller->cogging, cogging_current, sizeof(controller->cogging)); //compensation doesn't actually work yet.... |
benkatz | 25:f5741040c4bb | 235 | memcpy(&ENCODER_LUT, lut, sizeof(lut)); // copy the lookup table to the flash array |
benkatz | 23:2adf23ee0305 | 236 | printf("\n\rEncoder Electrical Offset (rad) %f\n\r", offset); |
benkatz | 22:60276ba87ac6 | 237 | |
benkatz | 23:2adf23ee0305 | 238 | if (!prefs->ready()) prefs->open(); |
benkatz | 25:f5741040c4bb | 239 | prefs->flush(); // write offset and lookup table to flash |
benkatz | 25:f5741040c4bb | 240 | prefs->close(); |
benkatz | 46:2d4b1dafcfe3 | 241 | |
benkatz | 46:2d4b1dafcfe3 | 242 | delete[] error_f; //gotta free up that ram |
benkatz | 46:2d4b1dafcfe3 | 243 | delete[] error_b; |
benkatz | 46:2d4b1dafcfe3 | 244 | delete[] lut; |
benkatz | 46:2d4b1dafcfe3 | 245 | delete[] raw_f; |
benkatz | 46:2d4b1dafcfe3 | 246 | delete[] raw_b; |
benkatz | 23:2adf23ee0305 | 247 | |
benkatz | 22:60276ba87ac6 | 248 | } |