Velocity Closed Loop Dynamic error correction

Dependencies:   mbed QEI PID DmTftLibraryEx

Committer:
lex9296
Date:
Fri Apr 15 07:01:02 2022 +0000
Revision:
39:be7055a0e9a4
Parent:
37:5fc7f2f435e8
Retroazione di velocita e correzione

Who changed what in which revision?

UserRevisionLine numberNew contents of line
GregCr 0:9c0917bfde97 1
lex9296 23:b9d23a2f390e 2 //Warning: Incompatible redefinition of macro "MBED_RAM_SIZE" in "tmp/HU5Hqj", Line: 39, Col: 10
lex9296 23:b9d23a2f390e 3 #ifndef MBED_RAM_SIZE
lex9296 23:b9d23a2f390e 4 #define MBED_RAM_SIZE 0x00018000
lex9296 23:b9d23a2f390e 5 #endif
lex9296 23:b9d23a2f390e 6
lex9296 34:0522cebfe489 7 // ===========================================================
lex9296 34:0522cebfe489 8 // ===========================================================
lex9296 34:0522cebfe489 9 // LA: Stage 01 cleared, Il posizionatore funziona CORRETTAMENTE
lex9296 34:0522cebfe489 10 // ===========================================================
lex9296 34:0522cebfe489 11 // ===========================================================
lex9296 34:0522cebfe489 12 //
lex9296 34:0522cebfe489 13 // Commit & Publish del 11 Aprile 2022, il Pozizionamento è corretto e testato.
lex9296 34:0522cebfe489 14 // La velocità imposta all'asse, tuttavia, NON E' retroazionata.
lex9296 34:0522cebfe489 15 //
lex9296 34:0522cebfe489 16 // Occorrerebbe un anello chiuso sulla velocità, che si muova "almeno" alla velocità di scansione del PWM.
lex9296 34:0522cebfe489 17 // Se la velocità non è ancora raggiunta, la tensione deve venire adeguata conseguentemente agendo sul PWM.
lex9296 34:0522cebfe489 18 //
lex9296 35:0f6adc0b95b9 19 // LA: 11 Aprile 2022, Aggiungo il PID
lex9296 35:0f6adc0b95b9 20 // ===============================
lex9296 35:0f6adc0b95b9 21 //
lex9296 35:0f6adc0b95b9 22 // La retroazione sulla Velocità (Calcolata ogni "cf_MOTPeriod_s") è eseguita, nello stesso intervallo, da "PID_VelocityClosedLoop"
lex9296 35:0f6adc0b95b9 23 // Il parametro di Riferimento è la Velocity Calcolata
lex9296 35:0f6adc0b95b9 24 // Il Fattore di correzione è il PWM in uscita
lex9296 39:be7055a0e9a4 25 // Con la versione Pubblicata 0022 Il Doppio PID è correttamente funzionante.
lex9296 39:be7055a0e9a4 26 //
lex9296 39:be7055a0e9a4 27 // LA: 12 Aprile 2022, Introduco la retroazione ad anello Avanzata
lex9296 39:be7055a0e9a4 28 // ===========================================================
lex9296 39:be7055a0e9a4 29 //
lex9296 39:be7055a0e9a4 30 // Provo ad escludere il PID (I PID, attualmente son due) a favore di un controllo di retroazione più incisivo.
lex9296 39:be7055a0e9a4 31 // L'attuale PID non tiene conto del verso di correzione, mentre nel moto attuale mi aspetto maggiori difficoltà a frenare che ad
lex9296 39:be7055a0e9a4 32 // accelerare.
lex9296 39:be7055a0e9a4 33 // PQM introduco un controllo (in retroazione di proporzionalità all'errore) che possa diversificarsi tra Accelerazione e FRENO.
lex9296 39:be7055a0e9a4 34 // i.e. deve essere più incisivo quando frena, meno quando accelera.
lex9296 39:be7055a0e9a4 35 //
lex9296 39:be7055a0e9a4 36 // 15/4: Retroazione Avanzata e correzione dinamica dell'errore.
lex9296 39:be7055a0e9a4 37 //
lex9296 39:be7055a0e9a4 38 // In base all'errore calcolato sulla velocità, opero una retroazione semplice per far tornare il sistema in stabilità.
lex9296 39:be7055a0e9a4 39 // Ad ogni "chiamata" del motion correggo l'uscita nel verso suggerito dall'errore di un fattore ad esso proporzionale.
lex9296 39:be7055a0e9a4 40 // Ad oggi è il risultato migliore.
lex9296 39:be7055a0e9a4 41 //
lex9296 39:be7055a0e9a4 42 // Committo
lex9296 39:be7055a0e9a4 43 // Forco
lex9296 39:be7055a0e9a4 44 // Pubblico la 0030
lex9296 35:0f6adc0b95b9 45 //
lex9296 34:0522cebfe489 46
lex9296 23:b9d23a2f390e 47 #include "QEI.h"
lex9296 23:b9d23a2f390e 48 #include "SWPos.h"
lex9296 23:b9d23a2f390e 49
GregCr 0:9c0917bfde97 50 #include "Timers.h"
GregCr 0:9c0917bfde97 51 #include "Eeprom.h"
lex9296 39:be7055a0e9a4 52 #include "math.h"
GregCr 0:9c0917bfde97 53
lex9296 27:654100855f5c 54 #define MAX_CHAR_PER_LINE 28
lex9296 27:654100855f5c 55 #define TEXT_ROW_SPACING 16
lex9296 27:654100855f5c 56 #define FONT_CHAR_WIDTH 8
lex9296 27:654100855f5c 57 #define FONT_CHAR_HEIGHT 16
lex9296 27:654100855f5c 58
lex9296 27:654100855f5c 59 #include "DisplayDriver.h"
lex9296 27:654100855f5c 60
lex9296 33:f77aa3ecf87d 61 const float cf_SCOPeriod_s = 0.00025000; // 250us
lex9296 33:f77aa3ecf87d 62 const float cf_PWMPeriod_s = 0.01000000; // 10ms
lex9296 33:f77aa3ecf87d 63 const float cf_MOTPeriod_s = 0.01000000; // 10ms
lex9296 33:f77aa3ecf87d 64
lex9296 37:5fc7f2f435e8 65 int64_t ci64_TargetPOS = 3096; // Used also Outside
lex9296 37:5fc7f2f435e8 66
lex9296 33:f77aa3ecf87d 67 // LA: LCM_ShowTactics
lex9296 33:f77aa3ecf87d 68 // ===============
lex9296 33:f77aa3ecf87d 69 //
lex9296 39:be7055a0e9a4 70 /*
lex9296 32:1be3d79ff4db 71 void LCM_ShowTactics(
lex9296 39:be7055a0e9a4 72 int64_t i64_Pulses,
lex9296 39:be7055a0e9a4 73 float f_ATVSpeed,
lex9296 39:be7055a0e9a4 74 float f_ai0000_Aux,
lex9296 39:be7055a0e9a4 75 float f_ai0001_Aux,
lex9296 39:be7055a0e9a4 76 float f_ai0002_Aux,
lex9296 39:be7055a0e9a4 77 float f_ai0003_Aux,
lex9296 39:be7055a0e9a4 78 float f_ai0004_Aux,
lex9296 39:be7055a0e9a4 79 float f_ai0005_Aux,
lex9296 39:be7055a0e9a4 80 int32_t i32_Velocity,
lex9296 39:be7055a0e9a4 81 int32_t i32_Acceleration,
lex9296 39:be7055a0e9a4 82 int32_t i32_Jerk
lex9296 32:1be3d79ff4db 83 );
lex9296 39:be7055a0e9a4 84 */
lex9296 32:1be3d79ff4db 85
lex9296 33:f77aa3ecf87d 86 // LA: SampleAndStore
lex9296 33:f77aa3ecf87d 87 // LA: SampleTimer ==
lex9296 33:f77aa3ecf87d 88 // ==============
lex9296 33:f77aa3ecf87d 89 //
lex9296 39:be7055a0e9a4 90 //static void SampleAndStore (void);
lex9296 33:f77aa3ecf87d 91 Ticker SampleTimer; // LA: To Sample 1AI any 'x'ms
lex9296 33:f77aa3ecf87d 92
lex9296 29:7ce8c5779f5e 93 float af_PlotSamples[240]; // LA: "Horiz" Plot Array
lex9296 29:7ce8c5779f5e 94
lex9296 30:e45282a70a4d 95 uint16_t aui16_PlotSamples[240];
lex9296 30:e45282a70a4d 96 uint16_t aui16_PlotClears_Lo[240];
lex9296 30:e45282a70a4d 97 uint16_t aui16_PlotClears_Hi[240];
lex9296 30:e45282a70a4d 98
lex9296 33:f77aa3ecf87d 99 int32_t ai32_POS2VelGraph[4000];
lex9296 33:f77aa3ecf87d 100 uint16_t aui16_PlotPOS2VelSamples[240];
lex9296 33:f77aa3ecf87d 101 uint16_t aui16_PlotPOS2VelClears_Lo[240];
lex9296 33:f77aa3ecf87d 102 uint16_t aui16_PlotPOS2VelClears_Hi[240];
lex9296 33:f77aa3ecf87d 103
lex9296 33:f77aa3ecf87d 104 int32_t ai32_POS2AccGraph[4000];
lex9296 33:f77aa3ecf87d 105 int32_t ai32_POS2JrkGraph[4000];
lex9296 33:f77aa3ecf87d 106
lex9296 33:f77aa3ecf87d 107 // LA: MotionHandler
lex9296 33:f77aa3ecf87d 108 // LA: MotionTimer =
lex9296 33:f77aa3ecf87d 109 // =============
lex9296 33:f77aa3ecf87d 110 //
lex9296 39:be7055a0e9a4 111 //static void MotionHandler (void);
lex9296 33:f77aa3ecf87d 112 Ticker MotionTimer; // LA: Gestisce il rilevamento (RT) di Velocità, Accelerazione e Jerk
lex9296 33:f77aa3ecf87d 113 // Esegue il Movimento Programmato
lex9296 33:f77aa3ecf87d 114
lex9296 39:be7055a0e9a4 115 float f_PWMPercent; //
lex9296 39:be7055a0e9a4 116 float F_VelocityLoopFB_FW; // LA: Correzione Dinamica FW
lex9296 39:be7055a0e9a4 117 float F_VelocityLoopFB_BW; // LA: Correzione Dinamica BW
lex9296 39:be7055a0e9a4 118 //float fPID_Error; //
lex9296 39:be7055a0e9a4 119
lex9296 39:be7055a0e9a4 120 float fMOT_VelocityAct; // 0.0= 0%, 1.0= 100%
lex9296 39:be7055a0e9a4 121 float fMOT_VelocityReq; // 0.0= 0%, 1.0= 100%
lex9296 39:be7055a0e9a4 122 float fMOT_VelocityError; //
lex9296 33:f77aa3ecf87d 123
lex9296 33:f77aa3ecf87d 124 float fVelocity;
lex9296 33:f77aa3ecf87d 125 float fAcceleration;
lex9296 33:f77aa3ecf87d 126 float fJerk;
lex9296 33:f77aa3ecf87d 127 float fTorque;
lex9296 33:f77aa3ecf87d 128
lex9296 33:f77aa3ecf87d 129 int64_t i64_Position_Prec;
lex9296 33:f77aa3ecf87d 130 int32_t i32_Velocity;
lex9296 33:f77aa3ecf87d 131 int32_t i32_Velocity_Prec;
lex9296 33:f77aa3ecf87d 132 int32_t i32_Acceleration;
lex9296 33:f77aa3ecf87d 133 int32_t i32_Acceleration_Prec;
lex9296 33:f77aa3ecf87d 134 int32_t i32_Jerk;
lex9296 33:f77aa3ecf87d 135
lex9296 33:f77aa3ecf87d 136 // LA: Motion
lex9296 33:f77aa3ecf87d 137 // ======
lex9296 26:bfca0c471a87 138 // LA: Theory of Operation
lex9296 26:bfca0c471a87 139 // ===================
lex9296 26:bfca0c471a87 140 //
lex9296 26:bfca0c471a87 141 // Il PWM funziona da sè in Interrupt
lex9296 26:bfca0c471a87 142 // Il QEI funziona da sè in Interrupt
lex9296 26:bfca0c471a87 143 // Se si creano dei Ticker (Che sono a loro volta interrupt(s)) è possibile che PWM e QEI perdano correlazione con l'HW.
lex9296 26:bfca0c471a87 144 //
lex9296 26:bfca0c471a87 145 // PQM
lex9296 26:bfca0c471a87 146 //
lex9296 26:bfca0c471a87 147 // Il rinfresco del Display e la gestione del motion vanno fatte il più frequentemente possibile ma fuori dal loop dei Ticker.
lex9296 26:bfca0c471a87 148 // Con qst versione (LA0005, che termina un FORK (il successivo è LA0010) quanto detto sopra è FUNZIONANTE.
lex9296 26:bfca0c471a87 149 // Questo messaggio è incluso nel "commitment"
lex9296 26:bfca0c471a87 150
GregCr 0:9c0917bfde97 151 /*!
GregCr 0:9c0917bfde97 152 * \brief Define IO for Unused Pin
GregCr 0:9c0917bfde97 153 */
lex9296 23:b9d23a2f390e 154 //DigitalOut F_CS (D6); // MBED description of pin
lex9296 23:b9d23a2f390e 155 //DigitalOut SD_CS (D8); // MBED description of pin
lex9296 23:b9d23a2f390e 156
lex9296 23:b9d23a2f390e 157 DigitalIn userButton (USER_BUTTON);
lex9296 32:1be3d79ff4db 158 //
lex9296 32:1be3d79ff4db 159 DigitalOut rENA_Off (PC_0); // CN7.38 - Power Enable Relay, Power Disabled when true
lex9296 32:1be3d79ff4db 160 DigitalOut rDIR_FWD (PC_1); // CN7.36 - Move Direction Relay Bridge, Move FW(Extends) when true
mverdy 15:ed7ed20b7114 161
lex9296 23:b9d23a2f390e 162 AnalogIn adc_temp (ADC_TEMP);
lex9296 23:b9d23a2f390e 163 AnalogIn adc_vref (ADC_VREF);
lex9296 23:b9d23a2f390e 164 AnalogIn adc_vbat (ADC_VBAT);
GregCr 0:9c0917bfde97 165
lex9296 29:7ce8c5779f5e 166 AnalogIn ADC12_IN9 (PA_4); // STM32 PA4
lex9296 29:7ce8c5779f5e 167 AnalogIn ADC12_IN15 (PB_0); // STM32 PB0
lex9296 29:7ce8c5779f5e 168
lex9296 23:b9d23a2f390e 169 // PWM
lex9296 23:b9d23a2f390e 170 // ===
lex9296 23:b9d23a2f390e 171 //
lex9296 25:5fd2d69e2927 172 PwmOut PWM_PB3(PWM_OUT); // LA: PWM_OUT = D3 = PB_3
mverdy 14:ebd89dacc807 173
lex9296 28:443c82750dd9 174 // QEI
lex9296 28:443c82750dd9 175 // ===
lex9296 28:443c82750dd9 176 //
lex9296 28:443c82750dd9 177 QEI Stabilus322699 (PA_1, PA_0, NC, 100, QEI::X4_ENCODING);
lex9296 32:1be3d79ff4db 178 //DigitalIn Hall_A (PA_1);
lex9296 32:1be3d79ff4db 179 //DigitalIn Hall_B (PA_0);
lex9296 28:443c82750dd9 180
lex9296 23:b9d23a2f390e 181 // Motion
lex9296 23:b9d23a2f390e 182 // ======
lex9296 23:b9d23a2f390e 183 //
lex9296 28:443c82750dd9 184 //Ticker POS_MotionScan; // LA: Non uso un Ticker. Agisce sotto Interrupt e falsa la lettura QEI e la sincronicità del PWM
lex9296 23:b9d23a2f390e 185 //
lex9296 23:b9d23a2f390e 186 in_sPosizionatoreSW in_PosizionatoreSW;
lex9296 23:b9d23a2f390e 187 out_sPosizionatoreSW out_PosizionatoreSW;
GregCr 0:9c0917bfde97 188
lex9296 23:b9d23a2f390e 189 // LCD Display
lex9296 23:b9d23a2f390e 190 // ===========
lex9296 23:b9d23a2f390e 191 //
lex9296 28:443c82750dd9 192 //Ticker LCD_RefreshViews; // LA: Non uso un Ticker. Agisce sotto Interrupt e falsa la lettura QEI e la sincronicità del PWM
mverdy 15:ed7ed20b7114 193
lex9296 22:12c555cade79 194 void FactoryReset (void) {
mverdy 15:ed7ed20b7114 195 EepromFactoryReset( );
mverdy 15:ed7ed20b7114 196 HAL_NVIC_SystemReset( );
mverdy 15:ed7ed20b7114 197 }
lex9296 23:b9d23a2f390e 198
lex9296 32:1be3d79ff4db 199 void LCM_ShowTactics(
lex9296 33:f77aa3ecf87d 200 int64_t i64_Pulses,
lex9296 39:be7055a0e9a4 201 float f_ATVSpeed,
lex9296 33:f77aa3ecf87d 202 float f_ai0000_Aux,
lex9296 33:f77aa3ecf87d 203 float f_ai0001_Aux,
lex9296 33:f77aa3ecf87d 204 float f_ai0002_Aux,
lex9296 33:f77aa3ecf87d 205 float f_ai0003_Aux,
lex9296 33:f77aa3ecf87d 206 float f_ai0004_Aux,
lex9296 33:f77aa3ecf87d 207 float f_ai0005_Aux,
lex9296 33:f77aa3ecf87d 208 int32_t i32_Velocity,
lex9296 33:f77aa3ecf87d 209 int32_t i32_Acceleration,
lex9296 33:f77aa3ecf87d 210 int32_t i32_Jerk
lex9296 32:1be3d79ff4db 211 ) {
lex9296 32:1be3d79ff4db 212
lex9296 32:1be3d79ff4db 213 char StringText[MAX_CHAR_PER_LINE+ 1]; // don't forget the /0 (end of string)
lex9296 33:f77aa3ecf87d 214 static int64_t i64_Pulses_Prec;
lex9296 32:1be3d79ff4db 215 static float f_ai0005_prec;
lex9296 37:5fc7f2f435e8 216 static float f_ai0006_prec;
lex9296 39:be7055a0e9a4 217 //static float f_ai0007_prec;
lex9296 39:be7055a0e9a4 218 static float f_ai0008_prec;
lex9296 33:f77aa3ecf87d 219 static uint32_t i32_Velocity_prec;
lex9296 39:be7055a0e9a4 220 static float f_ATVSpeed_prec;
lex9296 33:f77aa3ecf87d 221
lex9296 33:f77aa3ecf87d 222 if (i64_Pulses != i64_Pulses_Prec) {
lex9296 32:1be3d79ff4db 223 sprintf (StringText,
lex9296 33:f77aa3ecf87d 224 "Pulses: %d ", (int32_t)i64_Pulses);
lex9296 32:1be3d79ff4db 225 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 1), StringText);
lex9296 33:f77aa3ecf87d 226 i64_Pulses_Prec = i64_Pulses;
lex9296 32:1be3d79ff4db 227 }
lex9296 32:1be3d79ff4db 228
lex9296 33:f77aa3ecf87d 229 if (i32_Velocity != i32_Velocity_prec) {
lex9296 33:f77aa3ecf87d 230 sprintf (StringText,
lex9296 39:be7055a0e9a4 231 "Velocity[ui/ms]: %d ", i32_Velocity);
lex9296 39:be7055a0e9a4 232 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 2), StringText);
lex9296 33:f77aa3ecf87d 233 i32_Velocity_prec = i32_Velocity;
lex9296 33:f77aa3ecf87d 234 }
lex9296 35:0f6adc0b95b9 235
lex9296 39:be7055a0e9a4 236 if (fMOT_VelocityAct != f_ATVSpeed_prec) {
lex9296 35:0f6adc0b95b9 237 sprintf (StringText,
lex9296 39:be7055a0e9a4 238 "VAct[0..1]: %f ", fMOT_VelocityAct);
lex9296 39:be7055a0e9a4 239 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 3), StringText);
lex9296 39:be7055a0e9a4 240 f_ATVSpeed_prec = fMOT_VelocityAct;
lex9296 39:be7055a0e9a4 241 }
lex9296 39:be7055a0e9a4 242 if (fMOT_VelocityReq != f_ai0008_prec) {
lex9296 39:be7055a0e9a4 243 sprintf (StringText,
lex9296 39:be7055a0e9a4 244 "VReq[0..1]: %f ", fMOT_VelocityReq);
lex9296 35:0f6adc0b95b9 245 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 4), StringText);
lex9296 39:be7055a0e9a4 246 f_ai0008_prec = fMOT_VelocityReq;
lex9296 35:0f6adc0b95b9 247 }
lex9296 35:0f6adc0b95b9 248 if (f_PWMPercent != f_ai0005_prec) {
lex9296 35:0f6adc0b95b9 249 sprintf (StringText,
lex9296 39:be7055a0e9a4 250 "PWM [0..1]: %f ", f_PWMPercent);
lex9296 35:0f6adc0b95b9 251 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 5), StringText);
lex9296 35:0f6adc0b95b9 252 f_ai0005_prec = f_PWMPercent;
lex9296 35:0f6adc0b95b9 253 }
lex9296 39:be7055a0e9a4 254 if (fMOT_VelocityError != f_ai0006_prec) {
lex9296 33:f77aa3ecf87d 255 sprintf (StringText,
lex9296 39:be7055a0e9a4 256 "Err [0..1): %f ", fMOT_VelocityError);
lex9296 39:be7055a0e9a4 257 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 6), StringText);
lex9296 39:be7055a0e9a4 258 f_ai0006_prec = fMOT_VelocityError;
lex9296 33:f77aa3ecf87d 259 }
lex9296 39:be7055a0e9a4 260 /*
lex9296 39:be7055a0e9a4 261 if (F_VelocityLoopFB != f_ai0007_prec) {
lex9296 33:f77aa3ecf87d 262 sprintf (StringText,
lex9296 39:be7055a0e9a4 263 "Corr[0..1]: %f ", F_VelocityLoopFB); //, fJerk);
lex9296 39:be7055a0e9a4 264 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 7), StringText);
lex9296 39:be7055a0e9a4 265 f_ai0007_prec = F_VelocityLoopFB;
lex9296 33:f77aa3ecf87d 266 }
lex9296 35:0f6adc0b95b9 267 */
lex9296 32:1be3d79ff4db 268 }
lex9296 32:1be3d79ff4db 269
lex9296 33:f77aa3ecf87d 270 static void SampleAndStore (void) {
lex9296 29:7ce8c5779f5e 271 int16_t i16_SampleIndex;
lex9296 33:f77aa3ecf87d 272 int64_t i64_SampleIndex;
lex9296 29:7ce8c5779f5e 273
lex9296 32:1be3d79ff4db 274 // af_PlotSamples[240- 1] = ADC12_IN9.read();
lex9296 32:1be3d79ff4db 275 af_PlotSamples[240- 1] = (float) Stabilus322699.getChannelA() * 0.33f;
lex9296 32:1be3d79ff4db 276
lex9296 32:1be3d79ff4db 277 for (i16_SampleIndex = 0; i16_SampleIndex < (240- 1); i16_SampleIndex++)
lex9296 29:7ce8c5779f5e 278 af_PlotSamples[i16_SampleIndex] = af_PlotSamples[i16_SampleIndex+ 1];
lex9296 29:7ce8c5779f5e 279
lex9296 33:f77aa3ecf87d 280 // LA: Position's Graph Section
lex9296 33:f77aa3ecf87d 281 // ========================
lex9296 33:f77aa3ecf87d 282 //
lex9296 33:f77aa3ecf87d 283 i64_SampleIndex = Stabilus322699.getPulses();
lex9296 33:f77aa3ecf87d 284 ai32_POS2VelGraph[i64_SampleIndex] = i32_Velocity;
lex9296 33:f77aa3ecf87d 285 ai32_POS2AccGraph[i64_SampleIndex] = i32_Acceleration;
lex9296 33:f77aa3ecf87d 286 ai32_POS2JrkGraph[i64_SampleIndex] = i32_Jerk;
lex9296 29:7ce8c5779f5e 287 }
lex9296 29:7ce8c5779f5e 288
lex9296 33:f77aa3ecf87d 289 static void MotionHandler (void) {
lex9296 35:0f6adc0b95b9 290 static uint32_t ui32_PreviousStep_ms;
lex9296 35:0f6adc0b95b9 291 uint32_t ui32_ActualStepSampled_ms;
lex9296 35:0f6adc0b95b9 292 uint32_t ui32_PassedActual_ms;
lex9296 35:0f6adc0b95b9 293 //
lex9296 35:0f6adc0b95b9 294 float fPassedActual_sxs;
lex9296 33:f77aa3ecf87d 295
lex9296 33:f77aa3ecf87d 296 // LA: Retrieve Actual Position
lex9296 33:f77aa3ecf87d 297 //
lex9296 33:f77aa3ecf87d 298 in_PosizionatoreSW.i64_ActualPosition = Stabilus322699.getPulses();
lex9296 33:f77aa3ecf87d 299
lex9296 33:f77aa3ecf87d 300 // LA: Execute Motion
lex9296 33:f77aa3ecf87d 301 //
lex9296 33:f77aa3ecf87d 302 PosizionatoreSW (in_PosizionatoreSW, out_PosizionatoreSW);
lex9296 33:f77aa3ecf87d 303 in_PosizionatoreSW.rtServoLock_Q = false;
lex9296 33:f77aa3ecf87d 304
lex9296 33:f77aa3ecf87d 305 // LA: Handle PostServo
lex9296 33:f77aa3ecf87d 306 //
lex9296 33:f77aa3ecf87d 307
lex9296 33:f77aa3ecf87d 308 // int64_t i64_StartPosition;
lex9296 33:f77aa3ecf87d 309 // int64_t i64_Distance;
lex9296 33:f77aa3ecf87d 310 // bool b_Accelerating; // LA: bACPos_Accelerating
lex9296 33:f77aa3ecf87d 311 // bool b_MaxSpeedReached;
lex9296 33:f77aa3ecf87d 312 // bool b_Decelerating; // bACPos_Decelerating
lex9296 33:f77aa3ecf87d 313 // bool b_InPosition;
lex9296 33:f77aa3ecf87d 314 // bool b_InToleranceFW;
lex9296 33:f77aa3ecf87d 315 // bool b_InToleranceBW;
lex9296 33:f77aa3ecf87d 316
lex9296 33:f77aa3ecf87d 317 // int32_t i32_ATVSpeed;
lex9296 34:0522cebfe489 318 // f_PWMPercent = ((float)out_PosizionatoreSW.i32_ATVSpeed)/ (float)in_PosizionatoreSW.i32_Max_Speed; // LA: In Range (float) 0.. 1
lex9296 34:0522cebfe489 319 // PWM_PB3.write((float) 1.0- f_PWMPercent); // Set to x%
lex9296 33:f77aa3ecf87d 320
lex9296 33:f77aa3ecf87d 321 // bool b_ATVDirectionFW;
lex9296 33:f77aa3ecf87d 322 rDIR_FWD = out_PosizionatoreSW.b_ATVDirectionFW;
lex9296 33:f77aa3ecf87d 323
lex9296 33:f77aa3ecf87d 324 // bool b_ATVDirectionBW;
lex9296 33:f77aa3ecf87d 325
lex9296 33:f77aa3ecf87d 326 // bool b_STW1_On;
lex9296 33:f77aa3ecf87d 327 // bool b_STW1_NoCStop;
lex9296 33:f77aa3ecf87d 328 // bool b_STW1_NoQStop;
lex9296 33:f77aa3ecf87d 329 // bool b_STW1_Enable;
lex9296 33:f77aa3ecf87d 330 rENA_Off = !out_PosizionatoreSW.b_STW1_Enable;
lex9296 33:f77aa3ecf87d 331
lex9296 33:f77aa3ecf87d 332 // LA: Update Motion Dynamic References
lex9296 33:f77aa3ecf87d 333 // ================================
lex9296 35:0f6adc0b95b9 334
lex9296 35:0f6adc0b95b9 335 // LA: Generazione del millisecondo Attuale
lex9296 35:0f6adc0b95b9 336 // ====================================
lex9296 33:f77aa3ecf87d 337 //
lex9296 35:0f6adc0b95b9 338 // Invoca il timer di sistema (TimersTimerValue) e lo confronta col suo precedente.
lex9296 35:0f6adc0b95b9 339 // Una volta elaborato e "scevrato" l'eventuale "Rollover" la sezione ritorna "ui32_PassedActual_ms_Local".
lex9296 35:0f6adc0b95b9 340 // "ui32_PassedActual_ms_Local" rappresenta i [ms] passati tra una istanza e l'altra
lex9296 35:0f6adc0b95b9 341 //
lex9296 35:0f6adc0b95b9 342 ui32_ActualStepSampled_ms = TimersTimerValue(); // Freezes the Actual Sample.
lex9296 35:0f6adc0b95b9 343 if (ui32_ActualStepSampled_ms >= ui32_PreviousStep_ms)
lex9296 35:0f6adc0b95b9 344 ui32_PassedActual_ms = (ui32_ActualStepSampled_ms- ui32_PreviousStep_ms); // Result => Actual- Previous
lex9296 35:0f6adc0b95b9 345 else
lex9296 35:0f6adc0b95b9 346 ui32_PassedActual_ms = ui32_ActualStepSampled_ms+ (0x7fffffff- ui32_PreviousStep_ms); // Result => Actual+ (Rollover- Previous)
lex9296 35:0f6adc0b95b9 347 ui32_PreviousStep_ms = ui32_ActualStepSampled_ms; // Store(s)&Hold(s) actual msSample
lex9296 35:0f6adc0b95b9 348 fPassedActual_sxs = ((float) 1000.0/ (float) ui32_PassedActual_ms); // Steps Any [s]
lex9296 34:0522cebfe489 349
lex9296 35:0f6adc0b95b9 350 i32_Velocity = (int32_t) (in_PosizionatoreSW.i64_ActualPosition- i64_Position_Prec); // LA: Velocity in [ui/ms]
lex9296 35:0f6adc0b95b9 351 i64_Position_Prec = in_PosizionatoreSW.i64_ActualPosition;
lex9296 35:0f6adc0b95b9 352 i32_Acceleration = (i32_Velocity- i32_Velocity_Prec); // LA: Acceleration in [ui/ms^2]
lex9296 35:0f6adc0b95b9 353 i32_Velocity_Prec = i32_Velocity;
lex9296 35:0f6adc0b95b9 354 i32_Jerk = (i32_Acceleration- i32_Acceleration_Prec); // LA: Jerk
lex9296 35:0f6adc0b95b9 355 i32_Acceleration_Prec = i32_Acceleration;
lex9296 33:f77aa3ecf87d 356
lex9296 39:be7055a0e9a4 357 fVelocity = (float)i32_Velocity * fPassedActual_sxs; // Velocity in [ui/s]
lex9296 39:be7055a0e9a4 358 fAcceleration = (float)i32_Acceleration * fPassedActual_sxs; // Acceleration in [ui/s^2]
lex9296 39:be7055a0e9a4 359 fJerk = (float)i32_Jerk * fPassedActual_sxs; // Jerk
lex9296 39:be7055a0e9a4 360
lex9296 39:be7055a0e9a4 361 // LA: Elaborazione dell'Uscita di Controllo della velocità
lex9296 39:be7055a0e9a4 362 // ====================================================
lex9296 39:be7055a0e9a4 363 //
lex9296 39:be7055a0e9a4 364 // Verifica della velocità raggiunta.
lex9296 39:be7055a0e9a4 365 // Calcolo dell'ERRORE.
lex9296 39:be7055a0e9a4 366 // Elaborazione e applicazione della correzione.
lex9296 39:be7055a0e9a4 367 //
lex9296 34:0522cebfe489 368
lex9296 39:be7055a0e9a4 369 // LA: i32_Velocity, Velocità Attuale (Reale, rilevata)
lex9296 39:be7055a0e9a4 370 // LA: out_PosizionatoreSW.i32_ATVSpeed, Velocità Richiesta (Elaborata in base al profilo)
lex9296 39:be7055a0e9a4 371 //
lex9296 39:be7055a0e9a4 372 // Si suppone che la velocità massima sia raggiungibile al massimo valore di f_PWMPercent (-> 1.0)
lex9296 39:be7055a0e9a4 373 // Si suppone che la velocità minima sia raggiungibile al minimo valore di f_PWMPercent (-> 0.0)
lex9296 35:0f6adc0b95b9 374 //
lex9296 39:be7055a0e9a4 375
lex9296 39:be7055a0e9a4 376 // LA: Calcolo dell'Errore scalato 0..1
lex9296 39:be7055a0e9a4 377 //
lex9296 39:be7055a0e9a4 378 fMOT_VelocityAct = ((float)abs(i32_Velocity)/ in_PosizionatoreSW.f_Max_Speed); // 0.0= 0%, 1.0= 100%
lex9296 39:be7055a0e9a4 379 fMOT_VelocityReq = (out_PosizionatoreSW.f_ATVSpeed/ in_PosizionatoreSW.f_Max_Speed); // 0.0= 0%, 1.0= 100%
lex9296 39:be7055a0e9a4 380 fMOT_VelocityError = fMOT_VelocityReq- fMOT_VelocityAct; //
lex9296 39:be7055a0e9a4 381
lex9296 39:be7055a0e9a4 382 // f_PWMPercent = out_PosizionatoreSW.f_ATVSpeed/ in_PosizionatoreSW.f_Max_Speed; // LA: In Range (float) 0.. 1
lex9296 36:cab8aa44ef91 383 if (out_PosizionatoreSW.b_ATVDirectionFW) {
lex9296 39:be7055a0e9a4 384 F_VelocityLoopFB_BW = 0.0f;
lex9296 39:be7055a0e9a4 385
lex9296 39:be7055a0e9a4 386 f_PWMPercent = (out_PosizionatoreSW.f_ATVSpeed/ in_PosizionatoreSW.f_Max_Speed)/ 4.0f; // FW is about 4:1 BW
lex9296 39:be7055a0e9a4 387 f_PWMPercent += (fMOT_VelocityError* 0.1f);
lex9296 34:0522cebfe489 388
lex9296 39:be7055a0e9a4 389 /*
lex9296 39:be7055a0e9a4 390 if (fMOT_VelocityError > 0.001f)
lex9296 39:be7055a0e9a4 391 F_VelocityLoopFB_FW += 0.0002f;
lex9296 39:be7055a0e9a4 392 if (fMOT_VelocityError < -0.001f)
lex9296 39:be7055a0e9a4 393 F_VelocityLoopFB_FW -= 0.0002f;
lex9296 39:be7055a0e9a4 394 */
lex9296 39:be7055a0e9a4 395 F_VelocityLoopFB_FW += (0.004f* fMOT_VelocityError);
lex9296 39:be7055a0e9a4 396 f_PWMPercent += F_VelocityLoopFB_FW;
lex9296 36:cab8aa44ef91 397 }
lex9296 36:cab8aa44ef91 398 else {
lex9296 39:be7055a0e9a4 399 F_VelocityLoopFB_FW = 0.0f;
lex9296 39:be7055a0e9a4 400
lex9296 39:be7055a0e9a4 401 f_PWMPercent = (out_PosizionatoreSW.f_ATVSpeed/ in_PosizionatoreSW.f_Max_Speed)/ 1.4f;
lex9296 39:be7055a0e9a4 402 f_PWMPercent += (fMOT_VelocityError* 0.1f);
lex9296 39:be7055a0e9a4 403
lex9296 39:be7055a0e9a4 404 /*
lex9296 39:be7055a0e9a4 405 if (fMOT_VelocityError > 0.001f)
lex9296 39:be7055a0e9a4 406 F_VelocityLoopFB_BW += 0.0005f;
lex9296 39:be7055a0e9a4 407 if (fMOT_VelocityError < -0.001f)
lex9296 39:be7055a0e9a4 408 F_VelocityLoopFB_BW -= 0.0005f;
lex9296 39:be7055a0e9a4 409 */
lex9296 39:be7055a0e9a4 410 F_VelocityLoopFB_BW += (0.01f* fMOT_VelocityError);
lex9296 39:be7055a0e9a4 411 f_PWMPercent += F_VelocityLoopFB_BW;
lex9296 39:be7055a0e9a4 412 }
lex9296 39:be7055a0e9a4 413 if (f_PWMPercent > 1.0f)
lex9296 39:be7055a0e9a4 414 f_PWMPercent = 1.0f;
lex9296 39:be7055a0e9a4 415 if (f_PWMPercent < 0.0f)
lex9296 39:be7055a0e9a4 416 f_PWMPercent = 0.0f;
lex9296 39:be7055a0e9a4 417 PWM_PB3.write((float) 1.0- f_PWMPercent); // Set to x%
lex9296 39:be7055a0e9a4 418 }
lex9296 39:be7055a0e9a4 419
lex9296 39:be7055a0e9a4 420 // =======
lex9296 39:be7055a0e9a4 421 // =======
lex9296 39:be7055a0e9a4 422 // Main(s)
lex9296 39:be7055a0e9a4 423 // =======
lex9296 39:be7055a0e9a4 424 // =======
lex9296 39:be7055a0e9a4 425 //
lex9296 39:be7055a0e9a4 426 int main (void){
lex9296 39:be7055a0e9a4 427 rDIR_FWD = true; // LA: Actuator Extends
lex9296 39:be7055a0e9a4 428 rENA_Off = true; // LA: Drive Power is Off
lex9296 39:be7055a0e9a4 429 //
lex9296 39:be7055a0e9a4 430 in_PosizionatoreSW.b_ServoLock = false;
lex9296 39:be7055a0e9a4 431 in_PosizionatoreSW.rtServoLock_Q = false;
lex9296 39:be7055a0e9a4 432
lex9296 39:be7055a0e9a4 433 EepromInit(); // LA: Inizializza la EEProm
lex9296 39:be7055a0e9a4 434 TimersInit(); // LA: Parte il Timer a 1ms
lex9296 39:be7055a0e9a4 435
lex9296 39:be7055a0e9a4 436 // LA: FactoryReset se "userButton" premuto all'avvio
lex9296 39:be7055a0e9a4 437 //
lex9296 39:be7055a0e9a4 438 if (userButton == 0) {
lex9296 39:be7055a0e9a4 439 FactoryReset();
lex9296 39:be7055a0e9a4 440 }
lex9296 39:be7055a0e9a4 441 DisplayDriverInit();
lex9296 39:be7055a0e9a4 442
lex9296 39:be7055a0e9a4 443 SampleTimer.attach(&SampleAndStore, cf_SCOPeriod_s); // LA: Avvia l'OscilloScopio con TimeBase x [s]
lex9296 39:be7055a0e9a4 444 MotionTimer.attach(&MotionHandler, cf_MOTPeriod_s); // LA: Avvia il Motion con TimeBase x [s]
lex9296 39:be7055a0e9a4 445 PWM_PB3.period(cf_PWMPeriod_s); // LA: Avvia il PWM con TimeBase x [s]
lex9296 39:be7055a0e9a4 446 PWM_PB3.write(0.0f); // Set to 0%
lex9296 39:be7055a0e9a4 447
lex9296 39:be7055a0e9a4 448 // LA: Ok
lex9296 39:be7055a0e9a4 449
lex9296 39:be7055a0e9a4 450 // LA: Motion (1st) Setup
lex9296 39:be7055a0e9a4 451 //
lex9296 39:be7055a0e9a4 452 in_PosizionatoreSW.b_AxisPowered = true;
lex9296 39:be7055a0e9a4 453 in_PosizionatoreSW.b_ACPos_Homed = true;
lex9296 39:be7055a0e9a4 454 in_PosizionatoreSW.f_Max_Speed = 20.0f; // [ui/ms]
lex9296 39:be7055a0e9a4 455 in_PosizionatoreSW.f_ZeroSpeed = 0.0f; //
lex9296 39:be7055a0e9a4 456
lex9296 39:be7055a0e9a4 457 // POS Mode
lex9296 39:be7055a0e9a4 458 // ========
lex9296 39:be7055a0e9a4 459 //
lex9296 39:be7055a0e9a4 460 // in_PosizionatoreSW.b_ServoLock = true;
lex9296 39:be7055a0e9a4 461 // in_PosizionatoreSW.rtServoLock_Q = false;
lex9296 39:be7055a0e9a4 462 //
lex9296 39:be7055a0e9a4 463 in_PosizionatoreSW.i64_TargetPosition = ci64_TargetPOS; // [ui]
lex9296 39:be7055a0e9a4 464 in_PosizionatoreSW.i64_ActualPosition = Stabilus322699.getPulses(); //
lex9296 39:be7055a0e9a4 465 in_PosizionatoreSW.i64_AccelerationWindow = 64; // LA: Spazio concesso alla rampa di Accelerazione
lex9296 39:be7055a0e9a4 466 in_PosizionatoreSW.i64_DecelerationWindow = 1024; // Spazio concesso alla rampa di Decelerazione
lex9296 39:be7055a0e9a4 467 in_PosizionatoreSW.i64_diToleranceWindow = 16; // Finestra di Tolleranza
lex9296 39:be7055a0e9a4 468 //
lex9296 39:be7055a0e9a4 469 in_PosizionatoreSW.f_MaximumSpeed_x100_FW = 100.0f; // % of "i32_Max_Speed"
lex9296 39:be7055a0e9a4 470 in_PosizionatoreSW.f_MaximumSpeed_x100_BW = 100.0f; //
lex9296 39:be7055a0e9a4 471 // in_PosizionatoreSW.f_ServoLockSpeed_x100_FW = 16.0f; // Riferimento di velocità minima a cui (appena) si muove l'asse [verso FW]
lex9296 39:be7055a0e9a4 472 // in_PosizionatoreSW.f_ServoLockSpeed_x100_BW = 24.0f; // Riferimento di velocità minima a cui (appena) si muove l'asse [verso BW]
lex9296 39:be7055a0e9a4 473 in_PosizionatoreSW.f_ServoLockSpeed_x100_FW = 24.0f; // Riferimento di velocità minima a cui (appena) si muove l'asse [verso FW]
lex9296 39:be7055a0e9a4 474 in_PosizionatoreSW.f_ServoLockSpeed_x100_BW = 24.0f; // Riferimento di velocità minima a cui (appena) si muove l'asse [verso BW]
lex9296 39:be7055a0e9a4 475
lex9296 39:be7055a0e9a4 476 // LA: Ok
lex9296 34:0522cebfe489 477
lex9296 39:be7055a0e9a4 478 // JOG Mode
lex9296 39:be7055a0e9a4 479 // ========
lex9296 39:be7055a0e9a4 480 //
lex9296 39:be7055a0e9a4 481 in_PosizionatoreSW.b_JogMode = false;
lex9296 39:be7055a0e9a4 482 in_PosizionatoreSW.b_JogFW = false;
lex9296 39:be7055a0e9a4 483 in_PosizionatoreSW.b_JogBW = false;
lex9296 39:be7055a0e9a4 484 in_PosizionatoreSW.i32_JogAccel_ms = 500; // [ms]
lex9296 39:be7055a0e9a4 485 in_PosizionatoreSW.i32_JogDecel_ms = 250; //
lex9296 39:be7055a0e9a4 486 //
lex9296 39:be7055a0e9a4 487 in_PosizionatoreSW.f_JogSpeed_x100_FW = (in_PosizionatoreSW.f_MaximumSpeed_x100_FW/ 2); // LA: JOG's the Half of Max POS's Speed
lex9296 39:be7055a0e9a4 488 in_PosizionatoreSW.f_JogSpeed_x100_BW = (in_PosizionatoreSW.f_MaximumSpeed_x100_BW/ 2); //
lex9296 39:be7055a0e9a4 489
lex9296 39:be7055a0e9a4 490 // LA: Ok
lex9296 39:be7055a0e9a4 491
lex9296 39:be7055a0e9a4 492 // LA: Color RGB Component(s)
lex9296 39:be7055a0e9a4 493 // ======================
lex9296 39:be7055a0e9a4 494 //
lex9296 39:be7055a0e9a4 495 // RED 0000 1000 0000 0000 min 0x0800 02048
lex9296 39:be7055a0e9a4 496 // 1111 1000 0000 0000 max 0xf800 63488
lex9296 39:be7055a0e9a4 497 //
lex9296 39:be7055a0e9a4 498 // GREEN 0000 0000 0010 0000 min 0x0020 00032
lex9296 39:be7055a0e9a4 499 // 0000 0111 1110 0000 max 0x07e0 02016
lex9296 39:be7055a0e9a4 500 //
lex9296 39:be7055a0e9a4 501 // BLUE 0000 0000 0000 0001 min 0x0001 00001
lex9296 39:be7055a0e9a4 502 // 0000 0000 0001 1111 max 0x001f 00031
lex9296 39:be7055a0e9a4 503 //
lex9296 39:be7055a0e9a4 504 // La componente ROSSA ha 5 bit di escursione (0.. 31),
lex9296 39:be7055a0e9a4 505 // La componente VERDE ha 6 bit di escursione (0.. 63),
lex9296 39:be7055a0e9a4 506 // La componente BLU ha 5 bit di escursione (0.. 31),
lex9296 39:be7055a0e9a4 507 //
lex9296 39:be7055a0e9a4 508 // Le componenti RGB di "Color" sono quindi scritte negli appropriati registri come segue:
lex9296 39:be7055a0e9a4 509 //
lex9296 39:be7055a0e9a4 510 // writeReg(RED, (Color & 0xf800) >> 11);
lex9296 39:be7055a0e9a4 511 // writeReg(GREEN, (Color & 0x07e0) >> 5);
lex9296 39:be7055a0e9a4 512 // writeReg(BLUE, (Color & 0x001f));
lex9296 39:be7055a0e9a4 513 //
lex9296 39:be7055a0e9a4 514 LCM_SetTextColor(Scale2RGBColor (0, 0, 0), Scale2RGBColor (31, 0, 0)); // LA: Red on Black
lex9296 39:be7055a0e9a4 515 LCM_ClearScreen (Scale2RGBColor (0, 0, 0)); // Black Background
lex9296 39:be7055a0e9a4 516 LCM_DrawString (0, 0+ (TEXT_ROW_SPACING* 0), "You Start Me Up ..."); // Intro Text
lex9296 39:be7055a0e9a4 517
lex9296 39:be7055a0e9a4 518 // rDIR_FWD = false; // Collapse
lex9296 39:be7055a0e9a4 519 // rENA_Off = false; // Power On
lex9296 39:be7055a0e9a4 520
lex9296 39:be7055a0e9a4 521 in_PosizionatoreSW.b_ServoLock = true;
lex9296 39:be7055a0e9a4 522 in_PosizionatoreSW.rtServoLock_Q = true;
lex9296 37:5fc7f2f435e8 523
lex9296 39:be7055a0e9a4 524 // LA: Ok
lex9296 39:be7055a0e9a4 525
lex9296 39:be7055a0e9a4 526 while (1) {
lex9296 39:be7055a0e9a4 527
lex9296 39:be7055a0e9a4 528 // LA: Ok
lex9296 39:be7055a0e9a4 529
lex9296 39:be7055a0e9a4 530 // LA: Scope, Theory of operation.
lex9296 39:be7055a0e9a4 531 // ===========================
lex9296 39:be7055a0e9a4 532 //
lex9296 39:be7055a0e9a4 533 // 1) Sample a Value @ any Step
lex9296 39:be7055a0e9a4 534 // 2) Store @ the correct ms
lex9296 39:be7055a0e9a4 535 // 3) Plot the current Section of the Sampling Vector
lex9296 39:be7055a0e9a4 536 //
lex9296 39:be7055a0e9a4 537 LCM_ShowTactics (
lex9296 39:be7055a0e9a4 538 Stabilus322699.getPulses(), // Row 1
lex9296 39:be7055a0e9a4 539
lex9296 39:be7055a0e9a4 540 out_PosizionatoreSW.f_ATVSpeed, // 3
lex9296 39:be7055a0e9a4 541 adc_temp.read(), // 4
lex9296 39:be7055a0e9a4 542 adc_vbat.read(), // 5
lex9296 39:be7055a0e9a4 543 adc_vref.read(), // 6
lex9296 39:be7055a0e9a4 544
lex9296 39:be7055a0e9a4 545 ADC12_IN9.read(), // 8
lex9296 39:be7055a0e9a4 546 ADC12_IN15.read(), // 9
lex9296 39:be7055a0e9a4 547 (f_PWMPercent* 100), // 10
lex9296 39:be7055a0e9a4 548
lex9296 39:be7055a0e9a4 549 i32_Velocity, // 11
lex9296 39:be7055a0e9a4 550 i32_Acceleration, // 12
lex9296 39:be7055a0e9a4 551 i32_Jerk // 13
lex9296 39:be7055a0e9a4 552
lex9296 39:be7055a0e9a4 553 );
lex9296 39:be7055a0e9a4 554
lex9296 39:be7055a0e9a4 555 LCM_PlotScope (
lex9296 39:be7055a0e9a4 556 Scale2RGBColor (0, 0, 0), // Back: Black
lex9296 39:be7055a0e9a4 557 Scale2RGBColor (31, 0, 0) // Fore: Red
lex9296 39:be7055a0e9a4 558 );
lex9296 39:be7055a0e9a4 559
lex9296 39:be7055a0e9a4 560 LCM_PlotSpeed (
lex9296 39:be7055a0e9a4 561 Scale2RGBColor (0, 0, 0), // Back: Black
lex9296 39:be7055a0e9a4 562 Scale2RGBColor (31, 0, 0) // Fore: Red
lex9296 39:be7055a0e9a4 563 );
lex9296 39:be7055a0e9a4 564
lex9296 39:be7055a0e9a4 565 if (out_PosizionatoreSW.b_InPosition)
lex9296 39:be7055a0e9a4 566 if (in_PosizionatoreSW.i64_TargetPosition > 0)
lex9296 39:be7055a0e9a4 567 in_PosizionatoreSW.i64_TargetPosition = 0;
lex9296 39:be7055a0e9a4 568 else
lex9296 39:be7055a0e9a4 569 in_PosizionatoreSW.i64_TargetPosition = ci64_TargetPOS;
lex9296 36:cab8aa44ef91 570 }
lex9296 39:be7055a0e9a4 571 }