1st Fork
Dependencies: mbed QEI DmTftLibrary
SWPos/SWPos.cpp
- Committer:
- lex9296
- Date:
- 2022-02-15
- Revision:
- 27:654100855f5c
- Parent:
- 23:b9d23a2f390e
File content as of revision 27:654100855f5c:
/* LA: Theory of Operation. // ======================== // // once Encoder/Axis is Homed and Cycle Condition's Sussist, AC_Pos_Positioning is alloweed to take Control. // This is done by keeping "STW1_Control" true. // // if Servolock is off, The Axis is then Set to "Free Wheel Axis" // Otherwise, the System Keeps Actual Position (ServLock works inside the Tolerance window, if there's move), // or a New Move is Started if Target is != Actual Position. // // if ServoLock is true and movement is alloweed, after the positioning will have Actual = Target, Tolerance // flags active and a constant control to keep this. // // if "Axis" is Not Homed, All Positioning Flag(s) are kept clear */ /* LA: Verifica di coerenza del Profilo: // ================================= // // Se Lo spazio di Accelerazione sommato a quello di Decelerazione, ad INIZIO MOVIMENTO, supera la distanza (in Modulo) da percorrere, // allora il profilo và corretto (Non è più un trapezio ma diventa un triangolo). // // Per correggere il profilo occorre: // // 1) Calcolare le equazioni di entrambe le rette (Accelerazione e Decelerazione) // 2) Ricavare il punto di intersezione delle due rette (La cui "Ascissa" sarà la velocità massima raggiungibile, l'"Ordinata" il punto a cui la raggiungerà) // 3) Sostituire all'Accelerazione il valore "Ordinata"- Punto di Partenza (Verificando il segno dell'operazione in base al verso) // 4) Sostituire alla Decelerazione il valore Destinazione - "Ordinata" (Verificando il segno dell'operazione in base al verso) // 5) Sostituire alla Velocità di Movimento l'"Ascissa" // // Avendo già le equazioni di RettaxAcc e RettaxDec: // ================================================= // // RettaxAcc: Y = (m * X)+ q // RettaxDec: Y = (n * X)+ t // // Il punto X a cui le Y si equivalgono è X = (t- q)/ (m- n), la Y è ricavabile, indifferentemente, da entrambe le equazioni al punto X. // Questo permetterà la corretta esecuzione del "Triangolo", col vertice alla "velocità massima calcolata" e rampe teoriche equivalenti a quelle programmate. // // **** // **** // **** // **** // // Se non ho il "tempo" per calcolarlo uso un trucco: // Se il profilo è da correggere (Acc+ Dec > Distance) carico in ActualSpeed la Velocità di Servolock e lascio che l'asse si muova alla "Minima". // */ // LA: Includes #include "mbed.h" #include <stdio.h> #include <stdlib.h> #include "SWPos.h" #include "Timers.h" //in_sPosizionatoreSW in_PosizionatoreSW; //out_sPosizionatoreSW out_PosizionatoreSW; // LA: Basic Function's Integration void PosizionatoreSW (const in_sPosizionatoreSW &in, out_sPosizionatoreSW &out) { static bool InProgress = false; static int64_t i64_TargetPosition_Prec; static bool b_AuxCalculateProfile_003; static bool b_AuxCalculateProfile_002; static bool b_AuxCalculateProfile_001; static bool b_AuxCalculateProfile_000; static int32_t i32_ServoLockSpeed_FW; static int32_t i32_ServoLockSpeed_BW; static double d_X1; static double d_X2; static double d_Y1; static double d_Y2; static double d_Y2_meno_Y1; static double d_X2_meno_X1; static double d_X2_per_Y1; static double d_X1_per_Y2; static double d_m; static double d_q; static double d_n; static double d_t; static int32_t i32_ActualSpeed; static int64_t i64_AccelerationWindow_Local; static int64_t i64_DecelerationWindow_Local; static int32_t i32_MaximumSpeed_FW; static int32_t i32_MaximumSpeed_BW; static int32_t i32_MaximumSpeed_Local; static int64_t i64_StartPosition_Local; static int64_t i64_Distance_Local; static bool b_GoingFW; static bool b_GoingBW; static bool b_Accelerating_Local; static bool b_Decelerating_Local; static bool b_JogFW_Prec_Local; static bool b_JogBW_Prec_Local; static int32_t i32_Aux_ms2Acc; static int32_t i32_Aux_ms2Dec; static float f_Aux_AccelAnyms; static float f_Aux_DecelAnyms; static float f_MaximumJogSpeed_xW; static uint32_t ui32_PreviousStep_ms_Local; uint32_t ui32_ActualStepSampled_ms_Local; uint32_t ui32_PassedActual_ms_Local; if (InProgress) return; else { InProgress = true; // LA: Generazione del millisecondo Attuale // ==================================== // // Invoca il timer di sistema (TimersTimerValue) e lo confronta col suo precedente. // Una volta elaborato e "scevrato" l'eventuale "Rollover" la sezione ritorna "ui32_PassedActual_ms_Local". // "ui32_PassedActual_ms_Local" rappresenta i [ms] passati tra una chiamata e l'altra del Posizionatore SW. // ui32_ActualStepSampled_ms_Local = TimersTimerValue(); // Freezes the Actual Sample. if (ui32_ActualStepSampled_ms_Local >= ui32_PreviousStep_ms_Local) ui32_PassedActual_ms_Local = (ui32_ActualStepSampled_ms_Local- ui32_PreviousStep_ms_Local); // Result => Actual- Previous else ui32_PassedActual_ms_Local = ui32_ActualStepSampled_ms_Local+ (0x7fffffff- ui32_PreviousStep_ms_Local); // Result => Actual+ (Rollover- Previous) // ui32_PreviousStep_ms_Local = ui32_ActualStepSampled_ms_Local; // Store(s)&Hold(s) actual msSample // LA: Test pourposes ... // out.ui32_PreviousStep_ms = ui32_PreviousStep_ms_Local; out.ui32_ActualStepSampled_ms = ui32_ActualStepSampled_ms_Local; out.ui32_PassedActual_ms = ui32_PassedActual_ms_Local; // LA: Valutazione della Distanza (Rimanente) // ====================================== // if (in.i64_ActualPosition > in.i64_TargetPosition) i64_Distance_Local = (in.i64_ActualPosition- in.i64_TargetPosition); else i64_Distance_Local = (in.i64_TargetPosition- in.i64_ActualPosition); // LA: Entering SWPositioner // ===================== // if (in.b_AxisPowered) { if (in.b_JogMode) { // JOG Mode Engaged // if (in.b_JogFW) { if (!b_JogFW_Prec_Local) { // JOG Mode FW "Just" Engaged // b_JogFW_Prec_Local = in.b_JogFW; i32_Aux_ms2Acc = in.i32_JogAccel_ms; // f_MaximumJogSpeed_xW = (((in.f_JogSpeed_x100_FW)* (float)(in.i32_Max_Speed- i32_ActualSpeed)/ 100)); // LA: Speed to be Reached f_Aux_AccelAnyms = (f_MaximumJogSpeed_xW/ (float)in.i32_JogAccel_ms); // LA: Any ms Increment o'Speed b_Accelerating_Local = true; b_Decelerating_Local = false; out.b_MaxSpeedReached = false; } // JOG Move FW // if (i32_Aux_ms2Acc > 0) { i32_Aux_ms2Acc = (i32_Aux_ms2Acc- ui32_PassedActual_ms_Local); // LA: Ms Passed @ this Trip i32_ActualSpeed = (int32_t)((float)(in.i32_JogAccel_ms- i32_Aux_ms2Acc)* f_Aux_AccelAnyms); // LA: Acc Checkpoint } else { i32_ActualSpeed = (int32_t)((in.f_JogSpeed_x100_FW)* (float)(in.i32_Max_Speed- in.i32_ZeroSpeed)/ 100); // LA: Maximum Speed Reached b_Accelerating_Local = false; b_Decelerating_Local = false; out.b_MaxSpeedReached = true; } b_GoingFW = true; // LA: Moves ... b_GoingBW = false; // } else { if (b_JogFW_Prec_Local) { if (!b_Decelerating_Local) { // JOG Mode FW "Just" Released // i32_Aux_ms2Dec = in.i32_JogDecel_ms; f_MaximumJogSpeed_xW = (((in.f_JogSpeed_x100_FW)* (float)(i32_ActualSpeed- in.i32_ZeroSpeed)/ 100)); // LA: Speed to be Reached f_Aux_DecelAnyms = (f_MaximumJogSpeed_xW/ (float)in.i32_JogDecel_ms); // LA: Any ms Increment o'Speed b_Accelerating_Local = false; b_Decelerating_Local = true; out.b_MaxSpeedReached = false; } // JOG Move FW, Decelerating to Zero // if (i32_Aux_ms2Dec > 0) { i32_Aux_ms2Dec = (i32_Aux_ms2Dec- ui32_PassedActual_ms_Local); // LA: Ms Passed @ this Trip i32_ActualSpeed = (int32_t)(f_MaximumJogSpeed_xW- (float)(in.i32_JogDecel_ms- i32_Aux_ms2Dec)* f_Aux_DecelAnyms); // LA: Dec Checkpoint b_GoingFW = true; // LA: Moves ... b_GoingBW = false; // } else { i32_ActualSpeed = in.i32_ZeroSpeed; // LA: Zero Speed Reached b_Accelerating_Local = false; b_Decelerating_Local = false; out.b_MaxSpeedReached = false; // b_JogFW_Prec_Local = false; // LA: Move is Terminated, NOW b_GoingFW = false; // b_GoingBW = false; // } } } if (in.b_JogBW) { if (!b_JogBW_Prec_Local) { // JOG Mode BW "Just" Engaged // b_JogBW_Prec_Local = in.b_JogBW; i32_Aux_ms2Acc = in.i32_JogAccel_ms; // f_MaximumJogSpeed_xW = (((in.f_JogSpeed_x100_BW)* (float)(in.i32_Max_Speed- i32_ActualSpeed)/ 100)); // LA: Speed to be Reached f_Aux_AccelAnyms = (f_MaximumJogSpeed_xW/ (float)in.i32_JogAccel_ms); // LA: Any ms Increment o'Speed b_Accelerating_Local = true; b_Decelerating_Local = false; out.b_MaxSpeedReached = false; } // JOG Move BW // if (i32_Aux_ms2Acc > 0) { i32_Aux_ms2Acc = (i32_Aux_ms2Acc- ui32_PassedActual_ms_Local); // LA: Ms Passed @ this Trip i32_ActualSpeed = (int32_t)((float)(in.i32_JogAccel_ms- i32_Aux_ms2Acc)* f_Aux_AccelAnyms); // LA: Acc Checkpoint } else { i32_ActualSpeed = (int32_t)((in.f_JogSpeed_x100_BW)* (float)(in.i32_Max_Speed- in.i32_ZeroSpeed)/ 100); // LA: Maximum Speed Reached b_Accelerating_Local = false; b_Decelerating_Local = false; out.b_MaxSpeedReached = true; } b_GoingBW = true; // LA: Moves ... b_GoingFW = false; // } else { if (b_JogBW_Prec_Local) { if (!b_Decelerating_Local) { // JOG Mode BW "Just" Released // i32_Aux_ms2Dec = in.i32_JogDecel_ms; f_MaximumJogSpeed_xW = (((in.f_JogSpeed_x100_BW)* (float)(i32_ActualSpeed- in.i32_ZeroSpeed)/ 100)); // LA: Speed to be Reached f_Aux_DecelAnyms = (f_MaximumJogSpeed_xW/ (float)(in.i32_JogDecel_ms)); // LA: Any ms Increment o'Speed b_Accelerating_Local = false; b_Decelerating_Local = true; out.b_MaxSpeedReached = false; } // JOG Move FW, Decelerating to Zero // if (i32_Aux_ms2Dec > 0) { i32_Aux_ms2Dec = (i32_Aux_ms2Dec- ui32_PassedActual_ms_Local); // LA: Ms Passed @ this Trip i32_ActualSpeed = (int32_t)(f_MaximumJogSpeed_xW- (float)(in.i32_JogDecel_ms- i32_Aux_ms2Dec)* f_Aux_DecelAnyms); // LA: Dec Checkpoint b_GoingBW = true; // LA: Moves ... b_GoingFW = false; // } else { i32_ActualSpeed = in.i32_ZeroSpeed; // LA: Zero Speed Reached b_Accelerating_Local = false; b_Decelerating_Local = false; out.b_MaxSpeedReached = false; // b_JogBW_Prec_Local = false; // LA: Move is Terminated, NOW b_GoingBW = false; // b_GoingFW = false; // } } } out.b_Accelerating = b_Accelerating_Local; out.b_Decelerating = b_Decelerating_Local; } else { // !in.b_JogMode // JOG Mode NOT Engaged // Axis Powered // b_JogFW_Prec_Local = false; b_JogBW_Prec_Local = false; if (in.b_ACPos_Homed) { if ( (in.rtServoLock_Q && (in.i64_TargetPosition != in.i64_ActualPosition)) || (in.b_ServoLock && (in.i64_TargetPosition != i64_TargetPosition_Prec)) ) { // LA: An Issue to the Motion to Start is then Present & Valid // i64_TargetPosition_Prec = in.i64_TargetPosition; i64_StartPosition_Local = in.i64_ActualPosition; // wAccelerationWindow è già la Finestra di Accelerazione // wDecelerationWindow è già la Finestra di Decelerazione // wToleranceWindow è già la Finestra di Tolleranza di Posizionamento // i32_MaximumSpeed_FW = (int32_t)(((in.f_MaximumSpeed_x100_FW)* (float)(in.i32_Max_Speed- in.i32_ZeroSpeed)/ 100)); i32_ServoLockSpeed_FW = (int32_t)(((in.f_ServoLockSpeed_x100_FW)* (float)(in.i32_Max_Speed- in.i32_ZeroSpeed)/ 100)); i32_MaximumSpeed_BW = (int32_t)(((in.f_MaximumSpeed_x100_BW)* (float)(in.i32_Max_Speed- in.i32_ZeroSpeed)/ 100)); i32_ServoLockSpeed_BW = (int32_t)(((in.f_ServoLockSpeed_x100_BW)* (float)(in.i32_Max_Speed- in.i32_ZeroSpeed)/ 100)); // LA: Verifica del Profilo (Trapezio o Triangolo) // if (i64_Distance_Local < (in.i64_AccelerationWindow+ in.i64_DecelerationWindow)) { // LA: Attenzione, il Profilo è Triangolare // if (in.i64_ActualPosition < in.i64_TargetPosition) { // LA: Going FW // LA: Calcolare Entrambi i Profili, // Trovare il Punto di Intersezione // Aggiornare Acc/Dec/VMax in Accordo // Punto 1) Ricavo Y = mX+ q // ================ // // Retta x due punti, partendo da (wStartPosition, i32_ZeroSpeed) // (x1, Y1) // x Giungere a (wStartPosition+ wAccelerationWindow, MaximumSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)i64_StartPosition_Local; d_X2 = (double)(i64_StartPosition_Local+ in.i64_AccelerationWindow); d_Y1 = (double)in.i32_ZeroSpeed; d_Y2 = (double)i32_MaximumSpeed_FW; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Zero to Max d_X2_meno_X1 = (d_X2- d_X1); // LA: Acceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_m = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_q = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); // Punto 2) Ricavo Y = nX+ t // ================ // // Retta x due punti, partendo da (wTargetPosition- wDecelerationWindow, MaximumSpeed) // (x1, Y1) // x Giungere a (wTargetPosition, i32_ZeroSpeed) // (x2, Y2) // // Y = nX + t // // X = wActualPosition // Y = ActualSpeed // // n = (y2- y1)/(x2- x1) // t = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)(in.i64_TargetPosition- in.i64_DecelerationWindow); d_X2 = (double)in.i64_TargetPosition; d_Y1 = (double)i32_ActualSpeed; // LA: Maximum Speed Planned MIGHT have NOT been Reached d_Y2 = (double)in.i32_ZeroSpeed; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Max to Zero d_X2_meno_X1 = (d_X2- d_X1); // LA: Deceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_n = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_t = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); // Punto 3) Rilevo il punto di Intersezione x la X // Ricavo conseguentemente Y dall'equazione // ======================================== // // X = (t- q)/ (m- n) // Y = mX+ q (o Y = nX+ t, che in quel punto è equivalente ...) // // Y Rappresenterà la Massima Velocità raggiungibile, con le attuali pendenze // X Rappresenta il punto a cui ridurre Accelerazioni e Decelerazioni di profilo. // // PQM: // // Accwindow = ((t- q)/ (m- n))- StartPosition // Decwindow = FinishPosition- ((t- q)/ (m- n)) // MaxSpeed = (m* ((t- q)/ (m- n))) + q i64_AccelerationWindow_Local = (long)(((d_t- d_q)/ (d_m- d_n))- (double)i64_StartPosition_Local); i64_DecelerationWindow_Local = (long)((double)i64_StartPosition_Local- ((d_t- d_q)/ (d_m- d_n))); i32_MaximumSpeed_Local = (int32_t)((d_m* ((d_t- d_q)/ (d_m- d_n)))+ d_q); } else { // uui64_ActualPosition >= uui64_TargetPosition // LA: Going BW // LA: Calcolare Entrambi i Profili, // Trovare il Punto di Intersezione // Aggiornare Acc/Dec/VMax in Accordo // Punto 1) Ricavo Y = mX+ q // ================ // // Retta x due punti, partendo da (wStartPosition, i32_ZeroSpeed) // (x1, Y1) // x Giungere a (wStartPosition- wAccelerationWindow, MaximumSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)i64_StartPosition_Local; d_X2 = (double)(i64_StartPosition_Local- in.i64_AccelerationWindow); d_Y1 = (double)in.i32_ZeroSpeed; d_Y2 = (double)i32_MaximumSpeed_BW; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Zero to Max d_X2_meno_X1 = (d_X2- d_X1); // LA: Acceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_m = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_q = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); b_AuxCalculateProfile_002 = true; // Punto 2) Ricavo Y = nX+ t // ================ // // Retta x due punti, partendo da (wTargetPosition+ wDecelerationWindow, MaximumSpeed) // (x1, Y1) // x Giungere a (wTargetPosition, i32_ZeroSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)(in.i64_TargetPosition + in.i64_DecelerationWindow); d_X2 = (double)(in.i64_TargetPosition); d_Y1 = (double)(i32_ActualSpeed); // LA: Maximum Speed Planned MIGHT have NOT been Reached d_Y2 = (double)(in.i32_ZeroSpeed); d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Max to Zero d_X2_meno_X1 = (d_X2- d_X1); // LA: Deceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_n = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_t = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); // Punto 3) Rilevo il punto di Intersezione x la X // Ricavo conseguentemente Y dall'equazione // ======================================== // // X = (t- q)/ (m- n) // Y = mX+ q (o Y = nX+ t, che in quel punto è equivalente ...) // // Y Rappresenterà la Massima Velocità raggiungibile, con le attuali pendenze // X Rappresenta il punto a cui ridurre Accelerazioni e Decelerazioni di profilo. // // PQM: // // Accwindow = StartPosition- ((t- q)/ (m- n)) // Decwindow = ((t- q)/ (m- n))- FinishPosition // MaxSpeed = (m* ((t- q)/ (m- n))) + q i64_AccelerationWindow_Local = (long)((double)i64_StartPosition_Local- ((d_t- d_q)/ (d_m- d_n))); i64_DecelerationWindow_Local = (long)(((d_t- d_q)/ (d_m- d_n))- (double)i64_StartPosition_Local); i32_MaximumSpeed_Local = (int32_t)((d_m* ((d_t- d_q)/ (d_m- d_n)))+ d_q); } } else { // LA: il Profilo è Trapeziodale, Nullaltro da fare che assegnare i valori ai contenitori locali. // i64_AccelerationWindow_Local = in.i64_AccelerationWindow; i64_DecelerationWindow_Local = in.i64_DecelerationWindow; if (in.i64_ActualPosition < in.i64_TargetPosition) i32_MaximumSpeed_Local = i32_MaximumSpeed_FW; // LA: Going FW else i32_MaximumSpeed_Local = i32_MaximumSpeed_BW; // LA: Going BW } b_GoingFW = false; out.b_InToleranceFW = false; b_GoingBW = false; out.b_InToleranceBW = false; out.b_Accelerating = false; out.b_MaxSpeedReached = false; out.b_Decelerating = false; out.b_InPosition = false; b_AuxCalculateProfile_000 = false; b_AuxCalculateProfile_001 = false; b_AuxCalculateProfile_002 = false; b_AuxCalculateProfile_003 = false; } if (!in.b_ServoLock) { // LA: Stop the Motion // i32_ActualSpeed = in.i32_ZeroSpeed; b_GoingFW = false; b_GoingBW = false; out.b_STW1_On = false; out.b_STW1_NoCStop = false; out.b_STW1_NoQStop = false; out.b_STW1_Enable = false; // LA: i64_TargetPosition_Prec è ritentiva, per cui è bene inizializzarla != uui64_TargetPosition. // if (in.i64_TargetPosition > 0) // LA: E' Possibile Decrementare senza rollare? i64_TargetPosition_Prec = in.i64_TargetPosition- 1; // LA: Si, Di certo Diverso, Di certo Coerente. else i64_TargetPosition_Prec = in.i64_TargetPosition+ 1; // LA: No, Incremento. Di certo è Diverso e Coerente. // ======================== // ======================== // Axis is Now "Free Wheel" // ======================== // ======================== } else { // LA: Issue to <Start the Motion> // LA: Keep the present Motion <Active> // out.b_STW1_On = true; out.b_STW1_NoCStop = true; out.b_STW1_NoQStop = true; out.b_STW1_Enable = true; // Positioner // if (in.i64_ActualPosition < in.i64_TargetPosition) { // LA: Going FW // out.b_InToleranceBW = false; b_GoingFW = true; b_GoingBW = false; // Case is: Acceleration is Alloweed // ======================== // if ( (in.i64_ActualPosition >= i64_StartPosition_Local) && (in.i64_ActualPosition < (i64_StartPosition_Local+ i64_AccelerationWindow_Local)) ) { out.b_Accelerating = true; out.b_Decelerating = false; out.b_MaxSpeedReached = false; out.b_InPosition = false; out.b_InToleranceFW = false; // Line Profile [m, q] is to be Calculated only once // if (! b_AuxCalculateProfile_000) { // Retta x due punti, partendo da (wStartPosition, i32_ZeroSpeed) // (x1, Y1) // x Giungere a (wStartPosition+ wAccelerationWindow, MaximumSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)i64_StartPosition_Local; d_X2 = (double)(i64_StartPosition_Local+ i64_AccelerationWindow_Local); d_Y1 = (double)in.i32_ZeroSpeed; d_Y2 = (double)i32_MaximumSpeed_Local; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Zero to Max d_X2_meno_X1 = (d_X2- d_X1); // LA: Acceleration EndPoint */ d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_m = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_q = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); b_AuxCalculateProfile_000 = true; } i32_ActualSpeed = (int)((d_m * (double)in.i64_ActualPosition)+ d_q); } // Case is: MiddleWalking @ Planned-Full Speed // ================================== // if ( (in.i64_ActualPosition >= (i64_StartPosition_Local+ i64_AccelerationWindow_Local)) && (in.i64_ActualPosition < (in.i64_TargetPosition - i64_DecelerationWindow_Local)) ) { out.b_Accelerating = false; out.b_Decelerating = false; out.b_MaxSpeedReached = true; out.b_InPosition = false; out.b_InToleranceFW = false; i32_ActualSpeed = i32_MaximumSpeed_Local; } // Case is: Need to Decelerate, up to the Tolerance Window // ============================================== // if ( (in.i64_ActualPosition >= (in.i64_TargetPosition- i64_DecelerationWindow_Local)) && (in.i64_ActualPosition < (in.i64_TargetPosition- in.i64_diToleranceWindow)) ) { out.b_Accelerating = false; out.b_Decelerating = true; out.b_MaxSpeedReached = false; out.b_InPosition = false; out.b_InToleranceFW = false; // Line Profile [m, q] is to be Calculated only once // if (! b_AuxCalculateProfile_001) { // Retta x due punti, partendo da (wTargetPosition- wDecelerationWindow, MaximumSpeed) // (x1, Y1) // x Giungere a (wTargetPosition, i32_ZeroSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)(in.i64_TargetPosition- i64_DecelerationWindow_Local); d_X2 = (double)in.i64_TargetPosition; d_Y1 = (double)i32_ActualSpeed; // LA: Maximum Speed Planned MIGHT have NOT been Reached d_Y2 = (double)in.i32_ZeroSpeed; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Max to Zero d_X2_meno_X1 = (d_X2- d_X1); // LA: Deceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_m = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_q = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); b_AuxCalculateProfile_001 = true; } i32_ActualSpeed = abs((int)((d_m * (double)in.i64_ActualPosition)+ d_q)); } // Case is: Tolerance Reached while Going FW // ================================ // if (in.i64_ActualPosition >= (in.i64_TargetPosition- in.i64_diToleranceWindow)) { out.b_Accelerating = false; out.b_Decelerating = false; out.b_MaxSpeedReached = false; out.b_InPosition = true; out.b_InToleranceFW = true; i64_StartPosition_Local = in.i64_ActualPosition; i32_ActualSpeed = i32_ServoLockSpeed_FW; } } else if (in.i64_ActualPosition > in.i64_TargetPosition) { // LA: Going Bw // out.b_InToleranceFW = false; b_GoingBW = true; b_GoingFW = false; // Case is: Acceleration is Alloweed // ======================== // if ( (in.i64_ActualPosition <= i64_StartPosition_Local) && (in.i64_ActualPosition > (i64_StartPosition_Local- i64_AccelerationWindow_Local)) ) { out.b_Accelerating = true; out.b_Decelerating = false; out.b_MaxSpeedReached = false; out.b_InPosition = false; out.b_InToleranceBW = false; // Line Profile [m, q] is to be Calculated only once // if (! b_AuxCalculateProfile_002) { // Retta x due punti, partendo da (wStartPosition, i32_ZeroSpeed) // (x1, Y1) // x Giungere a (wStartPosition- wAccelerationWindow, MaximumSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)i64_StartPosition_Local; d_X2 = (double)(i64_StartPosition_Local- i64_AccelerationWindow_Local); d_Y1 = (double)in.i32_ZeroSpeed; d_Y2 = (double)i32_MaximumSpeed_Local; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Zero to Max d_X2_meno_X1 = (d_X2- d_X1); // LA: Acceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_m = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_q = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); b_AuxCalculateProfile_002 = true; } i32_ActualSpeed = (int)((d_m * (double)in.i64_ActualPosition)+ d_q); } // Case is: MiddleWalking @ Planned-Full Speed // ================================== // if ( (in.i64_ActualPosition <= (i64_StartPosition_Local- i64_AccelerationWindow_Local)) && (in.i64_ActualPosition > (in.i64_TargetPosition+ i64_DecelerationWindow_Local)) ) { out.b_Accelerating = false; out.b_Decelerating = false; out.b_MaxSpeedReached = true; out.b_InPosition = false; out.b_InToleranceBW = false; i32_ActualSpeed = i32_MaximumSpeed_Local; } // Case is: Need to Decelerate, up to the Tolerance Window // ============================================== // if ( (in.i64_ActualPosition <= (in.i64_TargetPosition+ i64_DecelerationWindow_Local)) && (in.i64_ActualPosition > (in.i64_TargetPosition+ in.i64_diToleranceWindow)) ) { out.b_Accelerating = false; out.b_Decelerating = true; out.b_MaxSpeedReached = false; out.b_InPosition = false; out.b_InToleranceBW = false; // Line Profile [m, q] is to be Calculated only once // if (! b_AuxCalculateProfile_003) { // Retta x due punti, partendo da (wTargetPosition+ wDecelerationWindow, MaximumSpeed) // (x1, Y1) // x Giungere a (wTargetPosition, i32_ZeroSpeed) // (x2, Y2) // // Y = mX + q // // X = wActualPosition // Y = ActualSpeed // // m = (y2- y1)/(x2- x1) // q = ((x2* y1)- (x1* y2))/ (x2- x1) // // ================================== // ================================== d_X1 = (double)(in.i64_TargetPosition + i64_DecelerationWindow_Local); d_X2 = (double)in.i64_TargetPosition; d_Y1 = (double)i32_ActualSpeed; // LA: Maximum Speed Planned MIGHT have NOT been Reached d_Y2 = (double)in.i32_ZeroSpeed; d_Y2_meno_Y1 = (d_Y2- d_Y1); // LA: From Max to Zero d_X2_meno_X1 = (d_X2- d_X1); // LA: Deceleration EndPoint d_X2_per_Y1 = (d_X2* d_Y1); d_X1_per_Y2 = (d_X1* d_Y2); d_m = (d_Y2_meno_Y1)/ (d_X2_meno_X1); d_q = ((d_X2_per_Y1)- (d_X1_per_Y2))/ (d_X2_meno_X1); b_AuxCalculateProfile_003 = true; } i32_ActualSpeed = abs((int)((d_m* (double)(in.i64_ActualPosition))+ d_q)); } // Case is: Tolerance Reached while Going BW // ================================ // if (in.i64_ActualPosition <= (in.i64_TargetPosition + in.i64_diToleranceWindow)) { out.b_Accelerating = false; out.b_Decelerating = false; out.b_MaxSpeedReached = false; out.b_InPosition = true; out.b_InToleranceBW = true; i64_StartPosition_Local = in.i64_ActualPosition; i32_ActualSpeed = i32_ServoLockSpeed_BW; } } else { // LA: In Position // =========== // b_GoingBW = false; out.b_InToleranceBW = true; b_GoingFW = false; out.b_InToleranceFW = true; out.b_Accelerating = false; out.b_Decelerating = false; out.b_MaxSpeedReached = false; out.b_InPosition = true; i64_StartPosition_Local = in.i64_ActualPosition; i32_ActualSpeed = in.i32_ZeroSpeed; } // Arrivato Qui 07/02/2022 // Arrivato Qui 07/02/2022 // Arrivato Qui 07/02/2022 // Arrivato Qui 07/02/2022 // =========================== // =========================== // LA: Managing the Speed Limit(s) // =========================== // =========================== if (i64_Distance_Local >= in.i64_diToleranceWindow) { // i64_Distance_Local >= in.i64_diToleranceWindow if (in.i64_ActualPosition < in.i64_TargetPosition) { // LA: Going FW // if (i32_ActualSpeed > i32_MaximumSpeed_FW) i32_ActualSpeed = i32_MaximumSpeed_FW; if (i32_ActualSpeed < i32_ServoLockSpeed_FW) i32_ActualSpeed = i32_ServoLockSpeed_FW; } else { // LA: Going BW // if (i32_ActualSpeed > i32_MaximumSpeed_BW) i32_ActualSpeed = i32_MaximumSpeed_BW; if (i32_ActualSpeed < i32_ServoLockSpeed_BW) i32_ActualSpeed = i32_ServoLockSpeed_BW; } } else { // i64_Distance_Local < in.i64_diToleranceWindow // LA: Attenzione, questo esegue un OVERRIDE alle assegnazioni precedenti. // =================================================================== // // Se il controllo di distanza vede che l'asse è in Anello di tolleranza forza a Zerospeed la velocità. // Il comportamento conseguente è che l'asse rimane in quiete, senza correnti applicate, fintanto che resta all'interno della finestra. // Se dovesse uscire, il sistema lo riporterebbe in tolleranza (o cercherebbe di farlo) a "ServolockSpeed". // i32_ActualSpeed = in.i32_ZeroSpeed; } } } else { // !in.b_ACPos_Homed // LA: if Not Homed, Positioning Flag(s) are Kept Clear // b_GoingFW = false; out.b_InToleranceFW = false; b_GoingBW = false; out.b_InToleranceBW = false; out.b_Accelerating = false; out.b_MaxSpeedReached = false; out.b_Decelerating = false; out.b_InPosition = false; b_AuxCalculateProfile_000 = false; b_AuxCalculateProfile_001 = false; b_AuxCalculateProfile_002 = false; b_AuxCalculateProfile_003 = false; i32_ActualSpeed = in.i32_ZeroSpeed; } } } else { // !in.b_AxisPowered // LA: if Not Powered, Motion Flag(s) are Kept Clear // b_GoingFW = false; out.b_InToleranceFW = false; b_GoingBW = false; out.b_InToleranceBW = false; out.b_Accelerating = false; out.b_MaxSpeedReached = false; out.b_Decelerating = false; out.b_InPosition = false; b_AuxCalculateProfile_000 = false; b_AuxCalculateProfile_001 = false; b_AuxCalculateProfile_002 = false; b_AuxCalculateProfile_003 = false; i32_ActualSpeed = in.i32_ZeroSpeed; } // =================== // =================== // LA: Finally, RAW Output // =================== // =================== out.i32_ATVSpeed = i32_ActualSpeed; out.b_ATVDirectionFW = b_GoingFW; out.b_ATVDirectionBW = b_GoingBW; out.i64_StartPosition = i64_StartPosition_Local; out.i64_Distance = i64_Distance_Local; } InProgress = false; }