-- Special Operations macchina Essetre-PF1250 by Egalware s.r.l. 2024/04/09 -- Intestazioni require( 'EmtGenerator') EgtEnableDebug( false) -- Carico libreria local BD = require( 'BeamData') --------------------------------------------------------------------- -- *** Generic Machinings *** --------------------------------------------------------------------- require( 'EmtGenMachining') --------------------------------------------------------------------- -- *** Special GetPrevMachiningOffset *** --------------------------------------------------------------------- ----------------------------------------------------------------------------------------- function OnSpecialGetPrevMachiningOffset() -- Aggiorno posizione della testa della trave a seguito di movimenti delle pinze non previsti tra le fasi local function TPosUpdate() local nClId = EgtGetFirstNameInGroup( EMC.CURRMCHID, 'CL') -- recupero Id del gruppo CL della lavorazione corrente local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL) -- Id del primo gruppo nella lavorazione (P1) if not nPathId then EMC.ERR = 12 EMC.MSG = ' Error : CL group path not found' return end local dAuxMoveCount = EgtGetInfo( nPathId, 'AS#', 'd') or 0 -- numero di movimenti ausiliari local dTRepos = nil -- controlla ogni gruppo di movimenti ausiliari for i = 1, dAuxMoveCount do local aAuxMove = EgtGetInfo( nPathId, 'AS' .. tostring( i), 'vs') or {} -- array contenete i parametri di ogni gruppo -- controlla solo i movimenti della testa trave e salva l'ultimo if aAuxMove[1] == '2' or aAuxMove[1] == '3' then for j = 2, #aAuxMove do if aAuxMove[j] == 'T' then dTRepos = aAuxMove[j+1] break end end end end return dTRepos end -- default EMC.ERR = 0 EMC.PREVOFFSX = 0 -- se c'è cambio di fase tra le lavorazioni (quindi la precedente è l'ultima della sua fase e la corrente la prima) if EMC.PREVPHASE ~= EMC.CURRPHASE then -- se la fase corrente è di inizio lavorazione di nuova trave if IsStartOrRestPhase( EMC.CURRPHASE) then -- recupero la posizione finale della lavorazione precedente local vPrevAx = EmtGetFinalAxesPos( EMC.PREVMCHID) -- ricava se e quanto la trave viene spostata tra le due fasi dai movimenti ausiliari e corregge l'offset di fine fase local dNewTPos = TPosUpdate() -- se ci sono dei movimenti della testa trave tra le due fasi ricava il delta tra la vecchia e la nuova posizione if dNewTPos then EMC.PREVOFFSX = dNewTPos - vPrevAx[1] -- oppure la X (L1) di questa corrisponde alla posizione iniziale della nuova trave, se ne deduce l'offset else EMC.PREVOFFSX = ParkV1 - vPrevAx[1] end end end end --------------------------------------------------------------------- -- *** Special Z moves *** --------------------------------------------------------------------- ---------------------- OnSpecialGetMaxZ ----------------------------- local function CalcExtraZ( vtTp, vtT, vMZ) -- la tabella deve esistere ed essere non vuota if not vMZ or #vMZ == 0 then return 0 end -- componente Z di riferimento è la minima local vtTz = min( vtTp:getZ(), vtT:getZ()) -- se oltre il massimo if vtTz > vMZ[1].Tz then return vMZ[1].Ez end -- interpolo for i = 2, #vMZ do if vtTz > vMZ[i].Tz then local dCoeff = ( vtTz - vMZ[i-1].Tz) / ( vMZ[i].Tz - vMZ[i-1].Tz) return (( 1 - dCoeff) * vMZ[i-1].Ez + dCoeff * vMZ[i].Ez) end end -- sotto il minimo return 0 end --------------------------------------------------------------------- function OnSpecialGetMaxZ() -- Inizializzazioni EMC.ERR = 0 -- Gestione speciale per sega a catena if EMC.HEAD == 'H13' then EMC.MAXZ = EgtGetAxisHomePos( 'Z1') return end -- Sistemazione dati di input local vtTp = Vector3d( EMC.TDIRp) local bFromZmax = false -- recupero il gruppo local nSetHead = GetHeadSet( EMC.HEAD) if vtTp:isSmall() then vtTp = X_AX() bFromZmax = true if nSetHead == 1 then EMC.R1p = ParkC1 EMC.R2p = ParkB1 elseif nSetHead == 2 then EMC.R1p = ParkC2 EMC.R2p = ParkB2 elseif nSetHead == 3 then EMC.R1p = ParkC3 EMC.R2p = ParkB3 end end local vtT = Vector3d( EMC.TDIR) local vtTpZm = EgtIf( bFromZmax, vtT, vtTp) local bBSameSign = (( EMC.R2p < 10 and EMC.R2 < 10) or ( EMC.R2p > -10 and EMC.R2 > -10)) -- Calcolo in funzione della testa e dei parametri if EMC.HEAD == 'H11' then if bBSameSign and vtTp:getX() > -0.1 and vtT:getX() > -0.1 then EMC.MAXZ = MaxZ1 else local vMZ = {{ Tz=0.85, Ez=390}, { Tz=0.5, Ez=280}, { Tz=-0.01, Ez=160}} EMC.MAXZ = ParkZ1 + CalcExtraZ( vtTpZm, vtT, vMZ) end elseif EMC.HEAD == 'H12' then if vtTp:getX() > 0.3 and vtT:getX() > 0.3 then if bBSameSign and abs( EMC.R1 - EMC.R1p) < 165 then EMC.MAXZ = MaxZ1Blade - EgtIf( abs( EMC.R2) < 90.1 and abs( EMC.R2p) < 90.1, 0, 130) elseif vtTp:getZ() > 0.707 or vtT:getZ() > 0.707 then EMC.MAXZ = ParkZ1 + 200 elseif vtTp:getZ() > 0.5 or vtT:getZ() > 0.5 then EMC.MAXZ = ParkZ1 + 100 else EMC.MAXZ = ParkZ1 + 1 end elseif bBSameSign and EMC.R1p > 29.9 and EMC.R1p < 180.1 and EMC.R1 > 29.9 and EMC.R1 < 180.1 and EMC.R2p > -10 and EMC.R2 > -10 then EMC.MAXZ = MaxZ1Blade - EgtIf( abs( EMC.R2) < 90.1 and abs( EMC.R2p) < 90.1, 0, 130) elseif bBSameSign and EMC.R1p > -0.1 and EMC.R1p < 180.1 and EMC.R1 > -0.1 and EMC.R1 < 180.1 and EMC.R2p > -10 and EMC.R2 > -10 then local vMZ = {{ Tz=0.85, Ez=440}, { Tz=0.5, Ez=200}, { Tz=-0.01, Ez=5}, { Tz=-0.5, Ez=1}} EMC.MAXZ = ParkZ1 + CalcExtraZ( vtTpZm, vtT, vMZ) else local vMZ = {{ Tz=0.85, Ez=400}, { Tz=0.7, Ez=300}, { Tz=0.5, Ez=195}, { Tz=0.15, Ez=60}, { Tz=-0.01, Ez=5}, { Tz=-0.5, Ez=1}} EMC.MAXZ = ParkZ1 + CalcExtraZ( vtTpZm, vtT, vMZ) end elseif EMC.HEAD == 'H16' then if vtTp:getX() > 0.3 and vtT:getX() > 0.3 then if bBSameSign and abs( EMC.R1 - EMC.R1p) < 165 then EMC.MAXZ = MaxZ1Blade - EgtIf( abs( EMC.R2) < 90.1 and abs( EMC.R2p) < 90.1, 0, 130) elseif vtTp:getZ() > 0.707 or vtT:getZ() > 0.707 then EMC.MAXZ = ParkZ1 + 200 elseif vtTp:getZ() > 0.5 or vtT:getZ() > 0.5 then EMC.MAXZ = ParkZ1 + 100 else EMC.MAXZ = ParkZ1 + 1 end elseif bBSameSign and EMC.R1p > 29.9 and EMC.R1p < 180.1 and EMC.R1 > 29.9 and EMC.R1 < 180.1 and EMC.R2p > -10 and EMC.R2 > -10 then EMC.MAXZ = MaxZ1Blade - EgtIf( abs( EMC.R2) < 90.1 and abs( EMC.R2p) < 90.1, 0, 130) elseif bBSameSign and EMC.R1p > -0.1 and EMC.R1p < 180.1 and EMC.R1 > -0.1 and EMC.R1 < 180.1 and EMC.R2p > -10 and EMC.R2 > -10 then local vMZ = {{ Tz=0.85, Ez=440}, { Tz=0.5, Ez=200}, { Tz=-0.01, Ez=5}, { Tz=-0.5, Ez=1}} EMC.MAXZ = ParkZ1 + CalcExtraZ( vtTpZm, vtT, vMZ) else local vMZ = {{ Tz=0.85, Ez=400}, { Tz=0.7, Ez=300}, { Tz=0.5, Ez=195}, { Tz=0.15, Ez=60}, { Tz=-0.01, Ez=5}, { Tz=-0.5, Ez=1}} EMC.MAXZ = ParkZ1 + CalcExtraZ( vtTpZm, vtT, vMZ) end elseif EMC.HEAD == 'H21' then if bBSameSign and vtTp:getX() > -0.1 and vtT:getX() > -0.1 then EMC.MAXZ = MaxZ2 else local vMZ = {{ Tz=0.85, Ez=390}, { Tz=0.5, Ez=280}, { Tz=-0.01, Ez=160}} EMC.MAXZ = ParkZ2 + CalcExtraZ( vtTpZm, vtT, vMZ) end elseif EMC.HEAD == 'H38' then EMC.MAXZ = SafeZ3RotAxis end end ---------------------- OnSpecialMoveZup ----------------------------- function OnSpecialMoveZup() --EgtOutLog( 'OnSpecialMoveZup : ' .. EMC.HEAD .. '.' .. tostring( EMC.EXIT)) -- Inizializzazioni EMC.ERR = 0 EMC.MODIF = false -- Direzione utensile local vtT = Vector3d( EMC.TDIR) -- recupero Z1 home local nHeadSet = GetHeadSet( EMC.HEAD) local dZmax = EgtGetAxisHomePos( EgtIf( nHeadSet ~= 2, 'Z1', 'Z2')) -- se fresa su testa1 o testa 2 if EMC.HEAD == 'H11' or EMC.HEAD == 'H21' or EMC.HEAD == 'H22' then ; -- se lama elseif EMC.HEAD == 'H12' or EMC.HEAD == 'H16' then -- riporto i valori tra -179 e + 180 local dCheckAxR1 = EMC.R1 if dCheckAxR1 < -180 then dCheckAxR1 = dCheckAxR1 + 360 elseif dCheckAxR1 > 180 then dCheckAxR1 = dCheckAxR1 - 360 end -- se lama su testa1 if EMC.HEAD == 'H12' then -- se inclinata oltre 90 gradi e interferisce con la trave if ( EMC.R2 > 87.9 and ( dCheckAxR1 < 15.0 or dCheckAxR1 > 180.0)) or ( EMC.R2 < -87.9 and ( dCheckAxR1 > -15.0 and dCheckAxR1 < 180.0)) then local dZref = dZmax + min( 330 * vtT:getZ(), 0) + 260 * ( 1 - sqrt( 1- vtT:getZ() * vtT:getZ())) -- se troppo in alto if EMC.L3 > dZref + 1 then ---- sistemo asse rotante --EMC.R2 = EgtIf( ( EMC.R2 > 0), 90, -90) ---- ricalcolo versore utensile --EMC.TDIR = EgtGetCalcToolDirFromAngles( EMC.R1, EMC.R2) ---- porto alla giusta quota --EMC.L3 = dZmax EMC.L3 = dZref -- dichiaro modificato EMC.MODIF = true end end -- se seconda lama su testa1 elseif EMC.HEAD == 'H16' then -- se inclinata oltre 90 gradi e interferisce con la trave if ( EMC.R2 > 87.9 and ( dCheckAxR1 < 15.0 or dCheckAxR1 > 180.0)) or ( EMC.R2 < -87.9 and ( dCheckAxR1 > -15.0 and dCheckAxR1< 180.0)) then local dZref = dZmax + min( 330 * vtT:getZ(), 0) + 260 * ( 1 - sqrt( 1- vtT:getZ() * vtT:getZ())) -- se troppo in alto if EMC.L3 > dZref + 1 then ---- sistemo asse rotante --EMC.R2 = EgtIf( ( EMC.R2 > 0), 90, -90) ---- ricalcolo versore utensile --EMC.TDIR = EgtGetCalcToolDirFromAngles( EMC.R1, EMC.R2) ---- porto alla giusta quota --EMC.L3 = dZmax EMC.L3 = dZref -- dichiaro modificato EMC.MODIF = true end end end elseif EMC.HEAD == 'H38' then EMC.L3 = SafeZ3RotAxis -- dichiaro modificato EMC.MODIF = true else ; -- non si fa nulla end end --------------------------------------------------------------------- -- *** OnSpecialApplyDisposition & OnPostApplyMachining *** --------------------------------------------------------------------- ----------------------- Costanti ------------------------------------ local DELTA_SIC = 1 local MinJoin = BD.MIN_JOIN_S local MinOther = abs( MinY1) + abs( MaxY2) + MinJoin local SIC_V = 50 -- sicurezza da testa local MIN_ENG_V = 115 -- ingombro asse Z local MIN_ENG_RACK_V = 161 -- ingombro asse Z con cremagliera local MIN_ENG_XZ2_V = 180 -- ingombro assi XZ sotto local MIN_Z2_FOR_ENG_XZ2_V = 250 -- quota Z2 da cui considerare ingombro assi XZ sotto local AGG_V = MinDeltaYV -- ingombro rulli pressori + sicurezza local MaxLenSmT = 1500 -- massima lunghezza pezzo scaricato con nastri verdi local DIST_Y1MAX_LOAD = 100 -- distanza carrello Y1 da massimo asse al carico ----------------------- Variabili ----------------------------------- local Test = false local SPLIT --------------------------------------------------------------------- local function PrepareClGroup( nParentId) local nClId = EgtGetFirstNameInGroup( nParentId, 'CL') -- se non c'è, lo aggiungo if not nClId then nClId = EgtGroup( EMC.DISPID) if not nClId then return nil end EgtSetName( nClId, 'CL') -- altrimenti lo svuoto else EgtEmptyGroup( nClId) end return nClId end --------------------------------------------------------------------- local function IsStartOrRestPhase( nPhase) local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE') return ( sVal == 'START' or sVal == 'REST') end --------------------------------------------------------------------- local function IsMidPhase( nPhase) local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE') return ( sVal == 'MID') end --------------------------------------------------------------------- local function IsEndPhase( nPhase) local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE') return ( sVal == 'END') end --------------------------------------------------------------------- local function GetNextStartOrRestPhase( nPhase) local nNextPhase = nPhase + 1 while nNextPhase <= EgtGetPhaseCount() do if IsStartOrRestPhase( nNextPhase) then break ; end nNextPhase = nNextPhase + 1 end return nNextPhase end --------------------------------------------------------------------- local function IsFirstMachiningOfStart( nMchId) -- se non è fase inizio di pezzo, ritorno risultato negativo if not IsStartOrRestPhase( EMC.PHASE) then return false end -- recupero la precedente operazione attiva local nPrevOperId = EgtGetPrevActiveOperation( nMchId) -- se non esiste o non è una disposizione, ritorno risultato negativo if not nPrevOperId or EgtGetOperationType( nPrevOperId) ~= MCH_OY.DISP then return false end -- è la prima return true end --------------------------------------------------------------------- local function UpdateMinJoin() MinJoin = BD.GetMinJoin( EMC.SB, EMC.HB, EMC.LB) MinOther = abs( MinY1) + abs( MaxY2) + MinJoin end --------------------------------------------------------------------- local function GetCUTID() -- recupero CUTID del pezzo in lavoro local nOrd = GetPhaseOrd( EMC.PHASE) local nPartRawId local nRawId = EgtGetFirstRawPart() while nRawId do local nRawOrd = EgtGetInfo( nRawId, 'ORD', 'i') if nRawOrd == nOrd then nPartRawId = nRawId break end nRawId = EgtGetNextRawPart( nRawId) end local CutID = EgtGetInfo( EgtGetFirstPartInRawPart( nPartRawId or GDB_ID.NULL) or GDB_ID.NULL, 'CUTID', 'i') or 0 return CutID end --------------------------------------------------------------------- local function GetNextRawInOrd( nCurrRawId) local nCurrOrd = EgtGetInfo( nCurrRawId, 'ORD', 'i') if not nCurrOrd then return end local nRawId = EgtGetFirstRawPart() while nRawId do local nRawOrd = EgtGetInfo( nRawId, 'ORD', 'i') if nRawOrd == nCurrOrd + 1 then return nRawId end nRawId = EgtGetNextRawPart( nRawId) end end ----------------------------------------------------------------------- local function EnsureZmax( bCloseV, vCmd) -- verifico non sia già inserito nella lista dei comandi for i = 1, #vCmd do if vCmd[i][1] == 4 then -- se richiesta chiusura, eventuale inserimento se non già presente if bCloseV and vCmd[i][2] == 0 then vCmd[i][2] = 1 end return true end end -- posizionamento sicuro teste e rulli table.insert( vCmd, { 4, EgtIf( bCloseV, 1, 0)}) return true end ----------------------------------------------------------------------- local function EmitComment( vCmd, sOut) EgtOutLog( ' ' .. sOut, 1) if Test then table.insert( vCmd, { 0, sOut}) end end --------------------------------------------------------------------- function OnSpecialApplyDisposition() EgtOutLog( ' *** Fase : ' .. EgtNumToString( EMC.PHASE, 0) .. ' ***', 1) -- Inizializzo codice di errore EMC.ERR = 0 -- Campi obbligatori ma non usati EMC.HEAD = "" EMC.EXIT = 1 EMC.TCPOS = "" EMC.SHIFTS = 0 EMC.SBH = false -- Se disposizione da saltare non devo fare alcunché if EgtExistsInfo( EMC.DISPID, 'SKIP') then return end -- Assegno flag di pezzo separato dal resto del grezzo SPLIT = IsEndPhase( EMC.PHASE) -- Recupero il tipo dell'operazione successiva local nNextOpeType = EgtGetOperationType( EgtGetNextActiveOperation( EMC.DISPID) or GDB_ID.NULL) -- Se ci sono lavorazioni successive non devo fare alcunché if nNextOpeType ~= MCH_OY.NONE and nNextOpeType ~= MCH_OY.DISP then return end -- Imposto gruppo e path di movimento local nClId = PrepareClGroup( EMC.DISPID) if not nClId then EMC.ERR = 3 EMC.MSG = ' Error : creation CL group failed' return end local nPathId = EgtGroup( nClId) if not nPathId then EMC.ERR = 6 EMC.MSG = ' Error : creation path in CL group failed' return end EgtSetName( nPathId, 'Empty') EMC.PATHID = nPathId EMC.SHIFTS = -1 -- Se la lavorazione successiva è ancora una disposizione, devo scaricare il pezzo if nNextOpeType == MCH_OY.DISP and SPLIT then -- aggiornamento posizioni local nPrevOpeId = EgtGetPrevActiveOperation( EMC.DISPID) local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL) local nLastEntId = EgtGetLastInGroup( nLastPathId) local vAxes = EmtGetAxesPos( nLastEntId) if #vAxes > 0 then EMC.TPOS = vAxes[1] end EMC.Y1DELTA = EgtGetInfo( nLastPathId, 'Y1DELTA', 'd') EMC.Y2DELTA = EgtGetInfo( nLastPathId, 'Y2DELTA', 'd') EMC.V1POS = EgtGetInfo( nLastPathId, 'V1POS', 'd') or ParkV1 EMC.V2POS = EgtGetInfo( nLastPathId, 'V2POS', 'd') or ParkV2 EMC.CNT = SpecGetCNT( EMC.DISPID) -- Determinazione delle dimensioni del grezzo in lavoro local b3Raw = BBox3d() local nRawId = EgtGetFirstRawPart() while nRawId do if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) and not EgtVerifyRawPartPhase( nRawId, EMC.PHASE + 1) then b3Raw = EgtGetRawPartBBox( nRawId) break end nRawId = EgtGetNextRawPart( nRawId) end EMC.LB = b3Raw:getDimX() EMC.HOVM = EgtGetInfo( nRawId or GDB_ID.NULL, 'HOVM', 'd') or 0 -- Eseguo scarico local vCmd = SpecCalcUnload() SpecOutputCmds( vCmd, true) return end -- Verifico ci sia un solo grezzo nella fase corrente local nRawCount = 0 local nCurrRawId = GDB_ID.NULL local nRawId = EgtGetFirstRawPart() while nRawId do if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) then nRawCount = nRawCount + 1 nCurrRawId = nRawId end nRawId = EgtGetNextRawPart( nRawId) end if nRawCount > 1 then EMC.ERR = 10 EMC.MSG = ' Error : too many Raw Parts in current Phase' return end -- Determinazione delle sue dimensioni local b3Raw = EgtGetRawPartBBox( nCurrRawId) if not b3Raw or b3Raw:isEmpty() then EMC.ERR = 11 EMC.MSG = ' Error : null Raw Part' return end EMC.LB = b3Raw:getDimX() EMC.SB = b3Raw:getDimY() EMC.HB = b3Raw:getDimZ() -- Aggiorno limiti di presa UpdateMinJoin() -- Assegno sovramateriale di testa e ingombro tagli di testa e di coda EMC.HOVM = 0 EMC.HCING = 0 EMC.TCING = 0 -- Devo scaricare il grezzo rimasto (deve essere unico) -- Posizione trave local dPosT -- Se fase 1 eseguo carico con carrello Y local vCmd = {} if EMC.PHASE == 1 then dPosT = LoadT vCmd = SpecCalcLoad( dPosT, 0, 0) -- se altrimenti fase successiva alla prima di tipo inizio o rimanenza elseif IsStartOrRestPhase( EMC.PHASE) then -- recupero posizione trave e quota di aggancio carrello dPosT = EgtGetInfo( EMC.DISPID, 'TPOS', 'd') local dPosY1 = EgtGetInfo( EMC.DISPID, 'Y1POS', 'd') if not dPosY1 then EMC.ERR = 14 EMC.MSG = ' Error : Y1 non clamped (start or rest)' return end -- confermo i nuovi parametri di aggancio table.insert( vCmd, { 21, dPosY1 - dPosT, 0}) -- recupero posizione rulli EMC.V1POS = ParkV1 EMC.V2POS = ParkV2 -- recupero contatore pinza 1 EMC.CNT = SpecGetCNT( EMC.DISPID) -- altrimenti fase successiva pari else EMC.Y2DELTA = EgtGetInfo( EMC.DISPID, 'Y2POS', 'd') EMC.V1POS = EgtGetInfo( EMC.DISPID, 'V1POS', 'd') EMC.V2POS = EgtGetInfo( EMC.DISPID, 'V2POS', 'd') -- recupero contatore pinza 1 EMC.CNT = SpecGetCNT( EMC.DISPID) end -- Se fase inizio o rimanenza, eseguo scambio per avere solo pinza V local vCmd2 = {} if IsStartOrRestPhase( EMC.PHASE) then EMC.TPOS = dPosT SpecSetCarrPosFromCmds( vCmd) local dDistFront = EMC.LB - MinJoin + 10 * GEO.EPS_SMALL local dDistBack = 0 local dY2DeltaMinUL = EMC.LB + MinY2 - EgtIf( EMC.LB < MaxLenSmT, UnloadSmT, UnloadT) if EMC.PHASE == 1 then EMC.LOAD = true end vCmd2 = SpecCalcCarriages( dDistFront, dDistBack, -EMC.V2POS, EMC.V1POS, nil, dY2DeltaMinUL) EMC.LOAD = nil if vCmd and #vCmd > 1 and vCmd2 and #vCmd2 > 1 and SpecTestSomeMoveInCmds( vCmd2) then table.insert( vCmd, { 0, 'CARR_MOVE'}) end end -- eseguo scarico SpecSetCarrPosFromCmds( vCmd2) local vCmd3 = SpecCalcUnload() -- unisco ed emetto i comandi vCmd = EgtJoinTables( vCmd, vCmd2) vCmd = EgtJoinTables( vCmd, vCmd3) SpecOutputCmds( vCmd, true) end --------------------------------------------------------------------- function OnPostApplyMachining() -- Inizializzo codice di errore EMC.ERR = 0 -- Verifico se ultima lavorazione della fase local nNextOpeId = EgtGetNextActiveOperation( EMC.MCHID) local bMchLast = ( not nNextOpeId or EgtGetOperationPhase( nNextOpeId) ~= EMC.PHASE) -- Agisco sui diversi percorsi della lavorazione local nPathId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( EMC.MCHID, 'CL') or GDB_ID.NULL) while nPathId do -- recupero id del successivo nPathId = EgtGetNext( nPathId) -- verifico se ultimo percorso di ultima lavorazione della fase local bLast = ( bMchLast and ( not nPathId)) -- se ultimo, elimino ritorno in home if bLast then EgtRemoveOperationHome( EMC.MCHID) end end end --------------------------------------------------------------------- function OnSpecialApplyMachining() EgtOutLog( ' Lavorazione : ' .. EgtGetName( EMC.MCHID) .. ' (' .. tostring( EMC.MCHID) .. ')') -- Inizializzo codice di errore EMC.ERR = 0 -- Recupero la posizione della trave e dei carrelli al termine della precedente operazione local nPrevOpeId = EgtGetPrevActiveOperation( EMC.MCHID) -- se precedente operazione non esiste, errore if not nPrevOpeId then EMC.ERR = 1 EMC.MSG = ' Error : previous Disposition not found' return -- se precedente operazione è disposizione elseif EgtGetOperationType( nPrevOpeId) == MCH_OY.DISP then if EMC.PHASE == 1 then -- posizioni home EMC.TPOS = nil EMC.Y1DELTA = nil EMC.Y2DELTA = nil EMC.V1POS = ParkV1 EMC.V2POS = ParkV2 EMC.CNT = nil elseif IsStartOrRestPhase( EMC.PHASE) then -- carico le posizioni local dPosT = EgtGetInfo( nPrevOpeId, 'TPOS', 'd') local dPosY = EgtGetInfo( nPrevOpeId, 'Y1POS', 'd') EMC.TPOS = dPosT EMC.Y1DELTA = dPosY - dPosT EMC.Y2DELTA = nil EMC.V1POS = ParkV1 EMC.V2POS = ParkV2 EMC.CNT = SpecGetCNT( EMC.MCHID) else -- aggiornamento posizioni (da lavorazione precedente a disposizione) local nPrev2OpeId = EgtGetPrevActiveOperation( nPrevOpeId) if not nPrev2OpeId then EMC.ERR = 1 EMC.MSG = ' Error : previous Disposition not found' return end local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrev2OpeId, 'CL') or GDB_ID.NULL) local nLastEntId = EgtGetLastInGroup( nLastPathId) local vAxes = EmtGetAxesPos( nLastEntId) if #vAxes > 0 then EMC.TPOS = vAxes[1] end EMC.Y1DELTA = EgtGetInfo( nLastPathId, 'Y1DELTA', 'd') EMC.Y2DELTA = EgtGetInfo( nLastPathId, 'Y2DELTA', 'd') EMC.V1POS = EgtGetInfo( nLastPathId, 'V1POS', 'd') or ParkV1 EMC.V2POS = EgtGetInfo( nLastPathId, 'V2POS', 'd') or ParkV2 EMC.CNT = SpecGetCNT( EMC.MCHID) end -- altrimenti precedente operazione è lavorazione else -- aggiornamento posizioni local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL) local nLastEntId = EgtGetLastInGroup( nLastPathId) local bAtZMax = ( EgtGetClEntMove( nLastEntId) == 0 and EgtGetClEntFlag( nLastEntId) == 3) local vAxes = EmtGetAxesPos( nLastEntId) if #vAxes > 0 then EMC.TPOS = vAxes[1] end EMC.Y1DELTA = EgtGetInfo( nLastPathId, 'Y1DELTA', 'd') EMC.Y2DELTA = EgtGetInfo( nLastPathId, 'Y2DELTA', 'd') EMC.V1POS = EgtIf( bAtZMax, ParkV1, EgtGetInfo( nLastPathId, 'V1POS', 'd') or ParkV1) EMC.V2POS = EgtIf( bAtZMax, ParkV2, EgtGetInfo( nLastPathId, 'V2POS', 'd') or ParkV2) EMC.CNT = SpecGetCNT( EMC.MCHID) end -- Verifico se ultima lavorazione della fase local nNextOpeId = EgtGetNextActiveOperation( EMC.MCHID) local bMchLast = ( not nNextOpeId or EgtGetOperationPhase( nNextOpeId) ~= EMC.PHASE) -- Verifico flag di separazione e fase di scarico local sNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) -- bPreSplit sempre a falso per obbligare a pinzare il pezzo con 1 morsa anche se iniziato il taglio che dividerà grezzo e finito (in genere per sezioni grandi con 2 tagli di lama) -- Tra un taglio e l'altro infatti c'e' inversione del braccio e quindi un'apertura delle rulliere. Se pinzano entrambe le pinze, potrebbero esserci problemi di collisone rulli-morse local bPreSplit = false --( sNotes:find( 'Presplit', 1, true) ~= nil) local bSplitting = ( sNotes:find( 'Split', 1, true) ~= nil) local bPreCut = ( sNotes:find( 'Precut', 1, true) ~= nil) local bCutting = ( sNotes:find( 'Cut', 1, true) ~= nil) local bUnload = IsEndPhase( EMC.PHASE) -- Agisco sui diversi percorsi della lavorazione local nPathId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( EMC.MCHID, 'CL') or GDB_ID.NULL) while nPathId do -- assegno id percorso da elaborare EMC.PATHID = nPathId -- recupero id del successivo nPathId = EgtGetNext( nPathId) -- verifico se ultimo percorso di ultima lavorazione della fase local bLast = ( bMchLast and ( not nPathId)) -- se ultimo, elimino ritorno in home -- if bLast then EgtRemoveOperationHome( EMC.MCHID) end -- salvo lo stato dei carrelli local OriTPos = EMC.TPOS local OriY1Delta = EMC.Y1DELTA local OriY2Delta = EMC.Y2DELTA local OriV1Pos = EMC.V1POS local OriV2Pos = EMC.V2POS local OriCnt = EMC.CNT -- eseguo le elaborazioni SpecApplyPath( bPreSplit, bSplitting, bPreCut, bCutting, bLast and bUnload) -- se separazione, verifico il risultato if bSplitting then -- recupero CUTID del pezzo in lavoro local CutID = GetCUTID() -- in caso di errore mancato pinzaggio uscita riprovo dopo aver disabilitato le lavorazioni finali if EMC.ERR == 18 then -- segnalazione warning EMC.ERR = -101 EMC.MSG = 'Warning : skipped final processes (WRN=101,CUTID='..tostring( CutID)..')' -- ripristino lo stato originale dei carrelli EMC.TPOS = OriTPos EMC.Y1DELTA = OriY1Delta EMC.Y2DELTA = OriY2Delta EMC.V1POS = OriV1Pos EMC.V2POS = OriV2Pos EMC.CNT = OriCnt -- eseguo le elaborazioni SpecApplyPath( bPreSplit, bSplitting, bPreCut, bCutting, bLast and bUnload) -- pinzaggio ancora impossibile, pezzo a caduta if EMC.ERR == 18 then -- segnalazione warning EMC.ERR = -102 EMC.MSG = 'Warning : skipped final processes and unload by fall (WRN=102,CUTID='..tostring( CutID)..')' end -- scarico standard elseif EMC.ERR == 0 then -- segnalazione warning EMC.ERR = -100 EMC.MSG = 'Warning : standard unload (WRN=100,CUTID='..tostring( CutID)..')' end -- se taglio del residuo finale, scarico standard elseif bCutting then -- recupero CUTID del pezzo in lavoro local CutID = GetCUTID() -- se non ci sono errori, segnalazione warning if EMC.ERR == 0 then EMC.ERR = -100 EMC.MSG = 'Warning : standard unload (WRN=100,CUTID='..tostring( CutID)..')' end end if EMC.ERR > 0 then return end -- determino la posizione finale della trave local nLastEntId = EgtGetLastInGroup( EMC.PATHID) local vAxes = EmtGetAxesPos( nLastEntId) if #vAxes > 0 then EMC.TPOS = vAxes[1] end end end --------------------------------------------------------------------- function SpecApplyPath( bPreSplit, bSplitting, bPreCut, bCutting, bUnload) -- Verifico se lavorazione pareti local bWall = ( EgtGetInfo( EgtGetCurrMachGroup() or GDB_ID.NULL, 'Wall', 'd') == 1) -- mi salvo info lavorazione su una lista local AuxInfoMach = {} AuxInfoMach.bPreSplit = bPreSplit AuxInfoMach.bSplitting = bSplitting AuxInfoMach.bPreCut = bPreCut AuxInfoMach.bCutting = bCutting AuxInfoMach.bUnload = bUnload -- Assegno flag di pezzo separato dal resto del grezzo SPLIT = IsEndPhase( EMC.PHASE) -- Determinazione delle dimensioni totali dei grezzi e del grezzo in lavoro local b3Tot = BBox3d() local b3Raw = BBox3d() local nNextOddPhase = GetNextStartOrRestPhase( EMC.PHASE) local nRawId = EgtGetFirstRawPart() local nCurrRawId = GDB_ID.NULL while nRawId do if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) then local b3Tmp = EgtGetRawPartBBox( nRawId) b3Tot:Add( b3Tmp) if EgtGetPartInRawPartCount( nRawId) > 0 and not EgtVerifyRawPartPhase( nRawId, nNextOddPhase) then b3Raw = b3Tmp nCurrRawId = nRawId end end nRawId = EgtGetNextRawPart( nRawId) end if b3Tot:isEmpty() then EMC.ERR = 11 EMC.MSG = ' Error : null Raw Parts' return end EMC.LB = EgtIf( SPLIT, b3Raw:getDimX(), b3Tot:getDimX()) EMC.SB = b3Tot:getDimY() EMC.HB = b3Tot:getDimZ() EMC.LT = b3Raw:getDimX() EgtOutLog( ' BarLen='..EgtNumToString( EMC.LB, 1), 3) -- Aggiorno limiti di presa UpdateMinJoin() -- Recupero sovramateriale di testa e ingombro tagli di testa e di coda EMC.HOVM = EgtGetInfo( nCurrRawId, 'HOVM', 'd') or 0 EMC.HCING = EgtGetInfo( nCurrRawId, 'HCING', 'd') or 0 EMC.TCING = EgtGetInfo( nCurrRawId, 'TCING', 'd') or 0 -- Recupero ingombro dei tagli di testa del prossimo pezzo (se esiste) EMC.NEXT_HCING = 0 local nNextRawId = GetNextRawInOrd( nCurrRawId) if nNextRawId then EMC.NEXT_HCING = EgtGetInfo( nNextRawId, 'HCING', 'd') or 0 end -- Calcolo dell'ingombro della lavorazione local dDistFront, dDistBack, dRollFront, dRollBack = SpecialCalcMachiningEncumbrance( EMC.MCHID, bPreCut) if not dDistFront then return end local dMaxLenLeft = 0 if bPreSplit or bSplitting then local dDistF, dDistB, dRollF, dRollB, dMaxLF = SpecialCalcPhaseEncumbrance( EMC.PHASE + 1) dDistFront = min( dDistFront, dDistF) dDistBack = dDistBack if bSplitting then dMaxLenLeft = dMaxLF end elseif bPreCut or bCutting then local dDistF, dDistB, dRollF, dRollB = SpecialCalcPhaseEncumbrance( EMC.PHASE + 1) dDistFront = min( dDistFront, dDistF) dDistBack = min( dDistBack, dDistB) end -- Verifico lunghezza pezzo if not SPLIT and not VerifyPartLength() then return end -- Calcolo quali carrelli sono necessari local nChar if bPreSplit or bSplitting then nChar = 2 elseif bPreCut or bCutting then nChar = 3 end local dY1DeltaMaxSP if nChar == 2 then dY1DeltaMaxSP = MaxY1 - LoadT + EMC.LT end local dY2DeltaMinUL if ( nChar == 2 or nChar == 3) and not bWall then dY2DeltaMinUL = EMC.LT + MinY2 - EgtIf( EMC.LT < MaxLenSmT, UnloadSmT, UnloadT) end -- Se inizio o appena dopo rotazione, eseguo il carico if not EMC.TPOS then local dPosT = LoadT local vCmd = SpecCalcLoad( dPosT, dDistFront, max( dDistBack, MinJoin, EMC.LB - ( MaxY1 - MinY1) + 6)) EMC.LOAD = true local vCmd2 = SpecCalcCarriages( dDistFront, dDistBack, dRollFront, dRollBack, dY1DeltaMaxSP, dY2DeltaMinUL, nChar, AuxInfoMach) EMC.LOAD = nil if bSplitting and EMC.ERR == 18 then table.insert( vCmd, { 22, dRollBack, -dRollFront}) end if vCmd2 and #vCmd2 > 1 and SpecTestSomeMoveInCmds( vCmd2) then table.insert( vCmd, { 0, 'CARR_MOVE'}) end EgtJoinTables( vCmd, vCmd2) SpecOutputCmds( vCmd) -- Se altrimenti non eseguito SPLIT, eseguo calcoli per carrelli elseif not SPLIT then local vCmd = SpecCalcCarriages( dDistFront, dDistBack, dRollFront, dRollBack, dY1DeltaMaxSP, dY2DeltaMinUL, nChar, AuxInfoMach) -- Se non ci sono spostamenti, confermo i parametri di aggancio e di posizione roller if SpecTestOnlyRemarkInCmds( vCmd) then table.insert( vCmd, { 21, EgtIf( EMC.Y1DELTA, EMC.Y1DELTA, 0), EgtIf( EMC.Y2DELTA, EMC.Y2DELTA, 0)}) table.insert( vCmd, { 22, dRollBack, -dRollFront}) end SpecOutputCmds( vCmd) -- Altrimenti, non muovo i carrelli rispetto alla trave ma impongo la posizione dei rulli else SpecOutputCNT() local vCmd = {} table.insert( vCmd, { 21, EgtIf( EMC.Y1DELTA, EMC.Y1DELTA, 0), EgtIf( EMC.Y2DELTA, EMC.Y2DELTA, 0)}) table.insert( vCmd, { 22, dRollBack, -dRollFront}) SpecOutputCmds( vCmd) end -- Se taglio di separazione local vCmd = {} if bSplitting then -- rimuovo eventuale vecchia info di Skip local NextDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) or GDB_ID.NULL EgtRemoveInfo( NextDispId, 'SKIP') -- verifico se separazione con caduta if not EMC.Y2DELTA then EgtOutLog( ' Warning SPLITTING -> separazione con caduta pezzo') SpecOutputCNT() -- non funziona ma servirebbe un controllo simile, di modo che non possa avvenire la presenza di un pezzo "FALL" più grande di LEN_VERY_SHORT_PART --if EMC.LT > LEN_VERY_SHORT_PART then -- EMC.ERR = 19 -- EMC.MSG = ' Error SPLIT : Y1 or Y2 not clamped' -- return false --end if IsEndPhase( EMC.PHASE + 1) then EgtSetInfo( NextDispId, 'SKIP', '1') local NextOpeId = EgtGetNextOperation( NextDispId) while NextOpeId and EgtGetOperationPhase( NextOpeId) == EMC.PHASE + 1 do EgtSetOperationMode( NextOpeId, false) NextOpeId = EgtGetNextOperation( NextOpeId) end end -- forzo l'errore 18 EMC.ERR = 18 -- verifico che la barra sia agganciata anche al primo carrello elseif not EMC.Y1DELTA then EMC.ERR = 19 EMC.MSG = ' Error SPLIT : Y1 or Y2 not clamped' return false end -- eseguo la separazione EgtOutLog( 'MaxLenLeft=' .. EgtNumToString( dMaxLenLeft, 1), 1) vCmd = SpecCalcSplit( b3Raw:getDimX(), dMaxLenLeft) end -- Se taglio finale di grezzo a perdere if bCutting then -- salvo distanza carrello Y2 da inizio grezzo rimasto nella disposizione della prossima fase local NextDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) if NextDispId then EgtSetInfo( NextDispId, 'Y2POS', EMC.Y2DELTA) EgtSetInfo( NextDispId, 'V1POS', EMC.V1POS) EgtSetInfo( NextDispId, 'V2POS', EMC.V2POS) end end -- Se previsto scarico, lo eseguo if bUnload then EMC.LB = b3Raw:getDimX() local vCmdTmp = SpecCalcUnload() vCmd = EgtJoinTables( vCmd, vCmdTmp) end -- Emetto eventuali comandi di separazione e/o scarico if #vCmd > 0 then SpecOutputCmds( vCmd, true) end end --SpecApplyPath( bLast) --------------------------------------------------------------------- function SpecialCalcMachiningEncumbrance( nMchId, bPreCut) -- gruppi della lavorazione local nClId = EgtGetFirstNameInGroup( nMchId, 'CL') local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL) if not nPathId then EMC.ERR = 12 EMC.MSG = ' Error : CL group path not found' return end -- Recupero ptMin ptMax della lavorazione local ptMin = EgtGetInfo( nClId, 'MMIN', 'p') local ptMax = EgtGetInfo( nClId, 'MMAX', 'p') if not ptMin or not ptMax then EMC.ERR = 13 EMC.MSG = ' Error : machining Min or Max not found' return end -- se pre-taglio, aggiorno ptMax con quello del taglio finale if bPreCut then local ptFinMax = GetFinalCutPmax( nMchId) if ptFinMax then ptMax = ptFinMax end end -- Recupero testa local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) -- Recupero minimi e massimi degli assi macchina della lavorazione local vAxMin = EgtGetInfo( nClId, 'MAXMIN', 'vd') local vAxMax = EgtGetInfo( nClId, 'MAXMAX', 'vd') if not vAxMin or not vAxMax or #vAxMin < 5 or ( sHead == 'H13' and #vAxMin < 6) then EMC.ERR = 15 EMC.MSG = ' Error : machine axes Min or Max not found' return end local vAxMid = {} for i = 1, #vAxMin do vAxMid[i] = ( vAxMin[i] + vAxMax[i]) / 2 end -- recupero il gruppo local nSetHead = GetHeadSet( sHead) -- Calcolo dell'ingombro della testa rispetto allo Zero Macchina (assi rotanti fissi, C=4, B=5, A=6) local b3Enc if nSetHead == 1 then EgtSetAxisPos( 'C1', vAxMid[4]) EgtSetAxisPos( 'B1', vAxMid[5]) if sHead == 'H13' then EgtSetAxisPos( 'A1', vAxMid[6]) end b3Enc = EgtGetBBoxGlob( EgtGetAxisId( 'C1'), GDB_BB.ONLY_VISIBLE) elseif nSetHead == 2 then EgtSetAxisPos( 'C2', vAxMid[4]) EgtSetAxisPos( 'B2', vAxMid[5]) if sHead == 'H22' then EgtSetAxisPos( 'A2', vAxMid[6]) end b3Enc = EgtGetBBoxGlob( EgtGetAxisId( 'C2'), GDB_BB.ONLY_VISIBLE) else -- testa 3 EgtSetAxisPos( 'C3', vAxMid[4]) EgtSetAxisPos( 'B3', vAxMid[5]) b3Enc = EgtGetBBoxGlob( EgtGetAxisId( 'C3'), GDB_BB.ONLY_VISIBLE) end -- Forzo la distanza di sicurezza da utensile local nSecRollerDist = EgtGetValInNotes( EgtTdbGetCurrToolParam( MCH_TP.USERNOTES), 'SECDIST', 'i') or SIC_V local dMinFrontEng = EgtIf( nSetHead ~= 2, MIN_ENG_RACK_V, EgtIf( vAxMax[3] < MIN_Z2_FOR_ENG_XZ2_V, MIN_ENG_V, MIN_ENG_XZ2_V)) local dRollFront = max( b3Enc:getMax():getX(), dMinFrontEng) + nSecRollerDist local dMinBackEng = EgtIf( nSetHead ~= 2, MIN_ENG_V, EgtIf( vAxMax[3] < MIN_Z2_FOR_ENG_XZ2_V, MIN_ENG_V, MIN_ENG_XZ2_V)) local dRollBack = max( -b3Enc:getMin():getX(), dMinBackEng) + nSecRollerDist EgtOutLog( ' RollFront = ' .. EgtNumToString( dRollFront, 1) .. ' RollBack = ' .. EgtNumToString( dRollBack, 1), 3) -- Calcolo della posizione della Punta Utensile rispetto allo Zero Macchina local ptTip ptTip = EgtGetCalcTipFromPositions( 0, 0, 0, vAxMid[4], vAxMid[5], vAxMid[6] or 0, false) EgtOutLog( ' ToolTip = ' .. tostring( ptTip), 5) -- Calcolo dell'ingombro della testa rispetto alla Punta Utensile local dHeadFront = dRollFront + AGG_V - ptTip:getX() local dHeadBack = dRollBack + AGG_V + ptTip:getX() EgtOutLog( ' HeadFront = ' .. EgtNumToString( dHeadFront, 1) .. ' HeadBack = ' .. EgtNumToString( dHeadBack, 1), 5) -- Distanze limiti della pinza di destra da testa trave e della pinza di sinistra da coda trave local dDistFront = - ptMax:getX() - LoadT - dHeadFront local dDistBack = ptMin:getX() + LoadT + EMC.LB - dHeadBack EgtOutLog( ' DistFront = ' .. EgtNumToString( dDistFront, 1) .. ' DistBack = ' .. EgtNumToString( dDistBack, 1), 3) return dDistFront, dDistBack, dRollFront, dRollBack end --------------------------------------------------------------------- function SpecialCalcPhaseEncumbrance( nPhase) -- Deve essere la fase finale di lavorazione di un pezzo (già staccato dal resto della trave) local dDistFront = EMC.LB local dDistBack = EMC.LB local dRollFront = 0 local dRollBack = 0 local dMaxLenLeft = 0 -- Salvo lavorazione e utensile correnti, per ripristinarli alla fine local nOrigMchId = EgtGetCurrMachining() local sOrigTool = EgtTdbGetCurrToolParam( MCH_TP.NAME) local sOrigHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) -- Ciclo sulle lavorazioni local nMchId = EgtGetNextActiveOperation( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL) while nMchId and EgtGetOperationPhase( nMchId) == nPhase do -- imposto lavorazione e utensile correnti EgtSetCurrMachining( nMchId) local sTool = EgtGetMachiningParam( MCH_MP.TOOL) if not sTool or not EgtTdbSetCurrTool( sTool) then local sTuuid = EgtGetMachiningParam( MCH_MP.TUUID) sTool = EgtTdbGetToolFromUUID( sTuuid) or '' EgtTdbSetCurrTool( sTool) end local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) EgtSetCalcTool( sTool, sHead, 1) -- calcolo ingombri local dDistF, dDistB, dRollF, dRollB = SpecialCalcMachiningEncumbrance( nMchId) if dDistF and dDistB then dDistFront = min( dDistFront, dDistF) dDistBack = min( dDistBack, dDistB) dRollFront = max( dRollFront, dRollF) dRollBack = max( dRollBack, dRollB) local dMaxLenL = EMC.LT - dDistF - AGG_V - dRollF EgtOutLog( ' MaxLenLeft = ' .. EgtNumToString( dMaxLenL, 1), 3) dMaxLenLeft = max( dMaxLenLeft, dMaxLenL) end nMchId = EgtGetNextActiveOperation( nMchId) end -- Ripristino lavorazione e utensile correnti if nOrigMchId then EgtSetCurrMachining( nOrigMchId) end if sOrigTool then EgtTdbSetCurrTool( sOrigTool) end if sOrigTool and sOrigHead then EgtSetCalcTool( sOrigTool, sOrigHead, 1) end -- Restituisco gli ingombri trovati return dDistFront, dDistBack, dRollFront, dRollBack, dMaxLenLeft end --------------------------------------------------------------------- function GetFinalCutPmax( nMchId) local nFinalCutId local nId = EgtGetNextActiveOperation( nMchId) while nId and EgtGetOperationPhase( nId) == EMC.PHASE do nFinalCutId = nId nId = EgtGetNextActiveOperation( nId) end if not nFinalCutId then return end local nCLId = EgtGetFirstNameInGroup( nFinalCutId, 'CL') if not nCLId then return end return EgtGetInfo( nCLId, 'MMAX', 'p') end --------------------------------------------------------------------- function VerifyPartLength() -- Verifico lunghezza pezzo if EMC.LB < MinJoin + MinOther + AggLoad + EMC.HCING + EMC.HOVM then EMC.ERR = 17 EMC.MSG = ' Error CLAMP : part too short' return false end return true end --------------------------------------------------------------------- function SpecCalcLoad( dPosT, dDistFront, dDistBack) --[L] local dNewY1min = max( EMC.LB - dDistBack, MinOther + AggLoad + EMC.HCING + EMC.HOVM) local dNewY1max = min( ( MaxY1 - MinY1) - 5, EMC.LB - MinJoin) if dNewY1min > dNewY1max then return nil end -- minimo posizionamento pinza 1 per permettere scarico del restante local dMinLengthRestToUnload = abs( MinY1) + abs( MinV1) + abs( MaxV2) + abs( MaxY2) + MinJoin + AggLoad + EMC.LT + 10 -- calcolo posizionamento con i coefficienti, ma verifico che sia tra il minimo e il massimo pinzabile local dNewY1DeltaMax = EgtClamp( 0.25 * dNewY1min + 0.75 * dNewY1max, dMinLengthRestToUnload, dNewY1max) local dNewY1Delta = EgtClamp( BD.CHAR_LOAD_DIST or 3000, 0.75 * dNewY1min + 0.25 * dNewY1max, dNewY1DeltaMax) local dNewY2Delta = nil local dNewY1 = dPosT + dNewY1Delta local vCmd = {} EgtOutLog( ' *[L]', 1) -- [L-1] if dNewY1 + TurnerOffs + DIST_Y1MAX_LOAD - MaxY1 > 0 then dNewY1Delta = min( EMC.LB - MinJoin, MaxY1 - dPosT - TurnerOffs - DIST_Y1MAX_LOAD) EgtOutLog( ' *[L1]', 1) end --[L-2] if EMC.LB - dNewY1Delta < MinJoin then dNewY1Delta = min( EMC.LB - MinJoin, MaxY1 - dPosT - TurnerOffs - DIST_Y1MAX_LOAD) EgtOutLog( ' *[L2]', 1) end -- Commento table.insert( vCmd, { 0, 'Loading'}) -- posizionamento sicuro teste e rulli EnsureZmax( false, vCmd) -- Apro entrambe le morse table.insert( vCmd, { 11, 0}) EMC.CNT = nil table.insert( vCmd, { 12, 0}) -- Sposto il carrello Y per il carico table.insert( vCmd, { 2, 'Y1', dPosT + dNewY1Delta, 'Y2', ParkY2}) -- Chiudo morsa Y table.insert( vCmd, { 11, 1}) -- Sposto il carrello Y con la testa trave al parcheggio V1 table.insert( vCmd, { 2, 'T', ParkV1, 'Y1', ParkV1 + dNewY1Delta}) -- confermo i nuovi parametri di aggancio table.insert( vCmd, { 21, dNewY1Delta, 0}) -- Inizializzo contatore globale EMC.CNT = 1 SpecOutputCNT() -- Assegno stato corrente EMC.TPOS = ParkV1 EMC.Y1DELTA = dNewY1Delta EMC.Y2DELTA = nil EMC.V1POS = ParkV1 EMC.V2POS = ParkV2 -- Restituisco i comandi return vCmd end -- SpecAdjustLoad [L] --------------------------------------------------------------------- function SpecCalcCarriages( dDistFront, dDistBack, dRollFront, dRollBack, dY1DeltaMaxSP, dY2DeltaMinUL, nChar, AuxInfoMach) local MinFrontJoin = MinJoin + EMC.HCING + EMC.HOVM local MyMinOther = MinOther + EgtIf( EMC.CNT == 1, AggLoad, 0) local dMyDistBack = dDistBack - EgtIf( EMC.CNT == 1, AggLoad, 0) local sMaxSplit = '' if dY1DeltaMaxSP then sMaxSplit = '/'..EgtNumToString( dY1DeltaMaxSP, 1)..'(MaxSplit)' end local sMinUnload = '' if dY2DeltaMinUL then sMinUnload = '/'..EgtNumToString( dY2DeltaMinUL, 1)..'(MinUnload)' end EgtOutLog( ' Dist/Min : Back=' .. EgtNumToString( dMyDistBack, 1) .. '/' .. EgtNumToString( MinJoin, 1) .. sMaxSplit .. ' Front=' .. EgtNumToString( dDistFront, 1) .. '/' .. EgtNumToString( MinFrontJoin, 1) .. sMinUnload, 3) local bBackOk = ( dMyDistBack > MinJoin - GEO.EPS_SMALL) local bFrontOk = ( dDistFront > MinFrontJoin - GEO.EPS_SMALL) -- [A] se non richiesto solo carrello Y2 e posso mettere solo carrello Y1 if ( nChar ~= 2 and nChar ~= 3 and bBackOk) or ( nChar == 2 and bBackOk and not bFrontOk) then local WorkTab = {} WorkTab.dTPosI = EMC.TPOS WorkTab.dY1DeltaI = EMC.Y1DELTA WorkTab.dY2DeltaI = EMC.Y2DELTA WorkTab.dV1PosI = EMC.V1POS WorkTab.bV1CloseI = false WorkTab.dV2PosI = EMC.V2POS WorkTab.bV2CloseI = false WorkTab.dTPosF = nil WorkTab.dY1DeltaMinF = max( EMC.LB - dMyDistBack, MyMinOther + EMC.HCING + EMC.HOVM) WorkTab.dY1DeltaMaxF = min( EMC.LB - MinJoin, MaxY1 + dDistFront + dRollFront + AGG_V) WorkTab.dY2DeltaMinF = nil WorkTab.dY2DeltaMaxF = nil if dY1DeltaMaxSP then WorkTab.dY1DeltaMaxF = min( WorkTab.dY1DeltaMaxF, dY1DeltaMaxSP) end WorkTab.dV1PosF = dRollBack WorkTab.bV1CloseF = false WorkTab.dV2PosF = -dRollFront WorkTab.bV2CloseF = false -- dopo che si è calcolato il minimo e massimo dell'intervallo, verifico che in testa rimanga almeno il minimo per poter fare passaggio pinze e scaricare if AuxInfoMach and ( AuxInfoMach.bSplitting or AuxInfoMach.bCutting) then if WorkTab.dY1DeltaMaxF - WorkTab.dY1DeltaMinF > 1.5 * BD.CHAR_EXTRA_DIST and WorkTab.dY1DeltaMaxF > EMC.LT + BD.MINRAW_S + BD.CHAR_EXTRA_DIST then WorkTab.dY1DeltaMinF = max( min( EMC.LT + BD.MINRAW_S, WorkTab.dY1DeltaMaxF - 1), WorkTab.dY1DeltaMinF + EMC.LT) end end -- verifico validità intervallo ammesso per Y1 if WorkTab.dY1DeltaMinF > WorkTab.dY1DeltaMaxF + 10 * GEO.EPS_SMALL then EMC.ERR = 18 EMC.MSG = ' Error : CLAMP Y1 impossible' return {} end -- al carico o con prima lavorazione di un pezzo si deve ignorare l'ingombro delle lavorazioni di testa per il pinzaggio if EMC.LOAD or IsFirstMachiningOfStart( EMC.MCHID) then EMC.HCING = 0 end return SpecAdjustCarriages( WorkTab) -- [B] se richiesti entrambi e posso metterli elseif nChar == 2 and bBackOk and bFrontOk then local WorkTab = {} WorkTab.dTPosI = EMC.TPOS WorkTab.dY1DeltaI = EMC.Y1DELTA WorkTab.dY2DeltaI = EMC.Y2DELTA WorkTab.dV1PosI = EMC.V1POS WorkTab.bV1CloseI = false WorkTab.dV2PosI = EMC.V2POS WorkTab.bV2CloseI = false WorkTab.dTPosF = nil WorkTab.dY1DeltaMinF = max( EMC.LB - dMyDistBack, MyMinOther + EMC.HCING + EMC.HOVM, EMC.LT + MyMinOther + EMC.NEXT_HCING) WorkTab.dY1DeltaMaxF = min( EMC.LB - MinJoin, MaxY1 + dDistFront + dRollFront + AGG_V) WorkTab.dY2DeltaMinF = max( MinJoin + EMC.HCING + EMC.HOVM, EMC.LB + MinY2 - dMyDistBack - AGG_V - dRollBack) WorkTab.dY2DeltaMaxF = min( dDistFront, EMC.LB - MyMinOther) -- - EMC.TCING if dY1DeltaMaxSP and dY1DeltaMaxSP > WorkTab.dY1DeltaMinF then WorkTab.dY1DeltaMaxF = min( WorkTab.dY1DeltaMaxF, dY1DeltaMaxSP) end if dY2DeltaMinUL then WorkTab.dY2DeltaMinF = max( WorkTab.dY2DeltaMinF, dY2DeltaMinUL) end WorkTab.dV1PosF = dRollBack WorkTab.bV1CloseF = false WorkTab.dV2PosF = -dRollFront WorkTab.bV2CloseF = false -- dopo che si è calcolato il minimo e massimo dell'intervallo, verifico che in testa rimanga almeno il minimo per poter fare passaggio pinze e scaricare if AuxInfoMach and ( AuxInfoMach.bSplitting or AuxInfoMach.bCutting) then if WorkTab.dY1DeltaMaxF - WorkTab.dY1DeltaMinF > 1.5 * BD.CHAR_EXTRA_DIST and WorkTab.dY1DeltaMaxF > EMC.LT + BD.MINRAW_S + BD.CHAR_EXTRA_DIST then WorkTab.dY1DeltaMinF = max( min( EMC.LT + BD.MINRAW_S, WorkTab.dY1DeltaMaxF - 1), WorkTab.dY1DeltaMinF) end end -- verifico validità intervallo ammesso per Y1 if WorkTab.dY1DeltaMinF > WorkTab.dY1DeltaMaxF + 10 * GEO.EPS_SMALL then EMC.ERR = 18 EMC.MSG = ' Error : CLAMP Y1 impossible' return {} end -- verifico validità intervallo ammesso per Y2 if WorkTab.dY2DeltaMinF > WorkTab.dY2DeltaMaxF + 10 * GEO.EPS_SMALL then EMC.ERR = 18 EMC.MSG = ' Error : CLAMP Y2 impossible' return {} end return SpecAdjustCarriages( WorkTab) -- [C] se non richiesti entrambi e posso mettere carrello Y2 elseif bFrontOk then local WorkTab = {} WorkTab.dTPosI = EMC.TPOS WorkTab.dY1DeltaI = EMC.Y1DELTA WorkTab.dY2DeltaI = EMC.Y2DELTA WorkTab.dV1PosI = EMC.V1POS WorkTab.bV1CloseI = false WorkTab.dV2PosI = EMC.V2POS WorkTab.bV2CloseI = false WorkTab.dTPosF = nil WorkTab.dY1DeltaMinF = nil WorkTab.dY1DeltaMaxF = nil WorkTab.dY2DeltaMinF = max( MinJoin + EMC.HCING + EMC.HOVM, EMC.LB + MinY2 - dMyDistBack - AGG_V - dRollBack) WorkTab.dY2DeltaMaxF = min( dDistFront, EMC.LB - MyMinOther) -- - EMC.TCING if dY2DeltaMinUL then WorkTab.dY2DeltaMinF = max( WorkTab.dY2DeltaMinF, dY2DeltaMinUL) end WorkTab.dV1PosF = dRollBack WorkTab.bV1CloseF = false WorkTab.dV2PosF = -dRollFront WorkTab.bV2CloseF = false -- verifico validità intervallo ammesso per Y2 if WorkTab.dY2DeltaMinF > WorkTab.dY2DeltaMaxF + 10 * GEO.EPS_SMALL then EMC.ERR = 18 EMC.MSG = ' Error : CLAMP Y2 impossible' return {} end return SpecAdjustCarriages( WorkTab) -- altrimenti errore else if EgtGetDebugLevel() < 3 then EgtOutLog( ' DistFront=' .. EgtNumToString( dDistFront) .. ' DistBack=' .. EgtNumToString( dMyDistBack) .. ' MinJoin=' .. EgtNumToString( MinJoin) .. ' MinFrontJoin=' .. EgtNumToString( MinFrontJoin)) end EMC.ERR = 18 EMC.MSG = ' Error : CLAMP impossible' return {} end end --------------------------------------------------------------------- function SpecCalcSplit( dLenRaw, dMaxLenLeft) local vCmd = {} EgtOutLog( ' *[S]', 1) local bSplit = ( EMC.Y2DELTA ~= nil) local ParkT = ParkV1 if bSplit then if dMaxLenLeft + 100 > LoadT then ParkT = dMaxLenLeft + 300 elseif dMaxLenLeft + 100 > ParkV1 then ParkT = LoadT end end table.insert( vCmd, { 0, EgtIf( bSplit, 'Split', 'Fall')}) if not bSplit then EnsureZmax( false, vCmd) end -- determino i grezzi da agganciare al carrello Y (sono quelli presenti nella fase successiva dispari) local nNextOddPhase = GetNextStartOrRestPhase( EMC.PHASE) local nRawId = EgtGetFirstRawPart() while nRawId do if EgtVerifyRawPartPhase( nRawId, nNextOddPhase) then table.insert( vCmd, { 31, nRawId, 'Y1'}) end nRawId = EgtGetNextRawPart( nRawId) end -- riporto il carrello Y al carico con il resto della trave local dLDelta = EMC.Y1DELTA - dLenRaw table.insert( vCmd, { 1, 'Y1', ParkT + dLDelta}) table.insert( vCmd, { 21, 0, EMC.Y2DELTA or 0}) -- imposto subito Y non più attaccato alla trave in lavoro EMC.Y1DELTA = nil -- salvo posizione carrello Y in disposizione del pezzo dopo split local PostDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) if PostDispId then if not bSplit then EgtSetInfo( PostDispId, 'TPOS', ParkT) else EgtRemoveInfo( PostDispId, 'TPOS') EgtSetInfo( PostDispId, 'TPARK', ParkT) end EgtSetInfo( PostDispId, 'Y1POS', ParkT + dLDelta) end -- salvo posizione grezzo rimasto e posizione carrello Y nella disposizione iniziale del pezzo succ (prossima fase dispari) local NextDispId = EgtGetPhaseDisposition( nNextOddPhase) if NextDispId then EgtSetInfo( NextDispId, 'TPOS', ParkT) EgtSetInfo( NextDispId, 'Y1POS', ParkT + dLDelta) end return vCmd end --------------------------------------------------------------------- function SpecCalcUnload() local vCmdPre = {} EgtOutLog( ' *[U]', 1) if not EMC.Y1DELTA and not EMC.Y2DELTA then EMC.ERR = 21 EMC.MSG = ' Error : Y1 and Y2 not clamped for unloading' return {} end local dY2DeltaMinUL = EMC.LB + MinY2 - EgtIf( EMC.LB < MaxLenSmT, UnloadSmT, UnloadT) -- Se pinza Y1 chiusa o Y2 troppo a destra, devo effettuare uno scambio if EMC.Y1DELTA or EMC.Y2DELTA < dY2DeltaMinUL then -- determino posizione testa trave local nLastEntId = EgtGetLastInGroup( EMC.PATHID) if not nLastEntId then local nPrevOpeId = EgtGetPrevActiveOperation( EMC.DISPID) local nPathId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL')) nLastEntId = EgtGetLastInGroup( nPathId) end local vAxes = EmtGetAxesPos( nLastEntId) if #vAxes > 0 then EMC.TPOS = vAxes[1] end -- imposto quote aggancio per avere solo pinza V local dDistFront = EMC.LB - MinJoin - EMC.HOVM + 10 * GEO.EPS_SMALL local dDistBack = 0 -- imposto rulli aperti (in ogni caso pezzo sicuramente grande) EMC.V1POS = ParkV1 EMC.V2POS = ParkV2 -- effettuo scambio vCmdPre = SpecCalcCarriages( dDistFront, dDistBack, 0, 0, nil, dY2DeltaMinUL) -- recupero nuova posizione carrelli SpecSetCarrPosFromCmds( vCmdPre) EgtOutLog( ' *[U1]', 1) end local vCmd = {} -- Tipo di scarico local bStdUl = ( not MaxUnloadLen or MaxUnloadLen < 1 or EMC.LB - EMC.HOVM < MaxUnloadLen + 1) -- Commento table.insert( vCmd, { 0, 'Unloading', EgtIf( bStdUl, 'Unloading', 'Manual Unloading')}) -- posizionamento sicuro teste e rulli (non serve ?) --table.insert( vCmd, { 4, 0}) -- Se pinza Y chiusa, la apro if EMC.Y1DELTA then table.insert( vCmd, { 11, 0}) EMC.CNT = nil end -- Se non supero la lunghezza massima di scarico, sposto il pezzo in posizione di scarico if bStdUl then local dFinT = EgtIf( EMC.LB < MaxLenSmT, UnloadSmT, UnloadT) - EMC.LB local dFinY2 = dFinT + EMC.Y2DELTA table.insert( vCmd, { 2, 'T', dFinT, 'Y2', dFinY2}) EgtOutLog( ' Y2PosF=' .. EgtNumToString( dFinY2), 1) else table.insert( vCmd, { 1, 'Y2', MaxY2, 'Manual Unloading'}) end -- apro la morsa table.insert( vCmd, { 12, 0}) -- riporto il carrello in home table.insert( vCmd, { 1, 'Y2', ParkY2}) -- eventuale unione tabelle if #vCmdPre > 0 then vCmd = EgtJoinTables( vCmdPre, vCmd) end return vCmd end --------------------------------------------------------------------- local function ChangedTool( nMchId) local nChanged = 0 -- Salvo lavorazione e utensile correnti, per ripristinarli alla fine local nOrigMchId = EgtGetCurrMachining() local sOrigTool = EgtTdbGetCurrToolParam( MCH_TP.NAME) local sOrigBlockedAx = EgtGetMachiningParam( MCH_MP.BLOCKEDAXIS) -- Recupero l'utensile della lavorazione precedente local nPrevMchId = EgtGetPrevActiveOperation( nMchId or GDB_ID.NULL) if nPrevMchId and EgtGetOperationType( nPrevMchId) ~= MCH_OY.DISP then EgtSetCurrMachining( nPrevMchId) local sTool = EgtGetMachiningParam( MCH_MP.TOOL) nChanged = EgtIf( sTool ~= sOrigTool, 1 , 0) local sBlockedAx = EgtGetMachiningParam( MCH_MP.BLOCKEDAXIS) -- se stesso utensile, ma modo caricamento diverso, è come se fosse un cambio utensile. Vale solo se aggregato su lama da sotto. if sTool == sOrigTool then local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) if sHead == 'H22' and sOrigBlockedAx ~= sBlockedAx then nChanged = 2 end end end -- Ripristino lavorazione e utensile correnti if nOrigMchId then EgtSetCurrMachining( nOrigMchId) end if sOrigTool then EgtTdbSetCurrTool( sOrigTool) end return nChanged end -------------------------------------------------------------------------------------------------------- -- **CHIAMATA DELLE FUNZIONI Spec** -------------------------------------------------------------------------------------------------------- function SpecAdjustCarriages( WorkTab) --EgtOutLog( ' --->>> CNT=' .. EgtIf( EMC.CNT, '1', '_')) local bChangedTool = ChangedTool( EMC.MCHID) -- Aggiorno la posizione dei rulli per eventuale cambio utensile if bChangedTool ~= 0 then WorkTab.dV1PosI = ParkV1 WorkTab.dV2PosI = ParkV2 end -- Verifico se compattare i rulli local bCloseV = false if WorkTab.dY1DeltaI then local dY1DeltaLim = MinJoin + WorkTab.dV1PosI - WorkTab.dV2PosI + 2 * AGG_V + EMC.HCING + EMC.HOVM + EgtIf( EMC.CNT == 1, AggLoad, 0) if WorkTab.dY1DeltaI <= dY1DeltaLim or ( WorkTab.dY1DeltaMaxF and WorkTab.dY1DeltaMaxF <= dY1DeltaLim) then bCloseV = true end end if WorkTab.dY2DeltaI then local dY2DeltaLim = MinJoin + WorkTab.dV1PosI - WorkTab.dV2PosI + 2 * AGG_V if EMC.LB - WorkTab.dY2DeltaI <= dY2DeltaLim or ( WorkTab.dY2DeltaMinF and EMC.LB - WorkTab.dY2DeltaMinF <= dY2DeltaLim) then bCloseV = true end end -- se ho cambiato modo di prendere utensile, forzo chiusura if bChangedTool == 2 then bCloseV = true end -- se i pezzi del cliente sono molto storti, si forza la chiusura per evitare che vada a sbattere. Se parametro non presente, si chiude solo se necessario if ForceToCloseRollersGate then bCloseV = true end WorkTab.bCloseV = bCloseV -- |POSIZIONO Y1| **[A]** if WorkTab.dY1DeltaMinF and ( not WorkTab.dY2DeltaMinF) then -- [A1]/[A2] continuazione da morsa Y1 ( Y1 -> Y1 ) scambio Y2 (Y2 -> Y1) if ( WorkTab.dY1DeltaI and ( not WorkTab.dY2DeltaI)) or ( WorkTab.dY2DeltaI and (not WorkTab.dY1DeltaI)) then WorkTab.bY1Parked = not WorkTab.dY1DeltaI WorkTab.dY1DeltaI = WorkTab.dY1DeltaI or ( ParkY1 - WorkTab.dTPosI) WorkTab.bY2Parked = not WorkTab.dY2DeltaI WorkTab.dY2DeltaI = WorkTab.dY2DeltaI or ( ParkY2 - WorkTab.dTPosI) return SpecAdjustCarrA( WorkTab) else EgtOutLog( ' Error CLAMP NULL-> Y1 impossibile') error( 'Error CLAMP NULL-> Y1 impossibile') end -- |POSIZIONO Y1Y2| **[B]** elseif WorkTab.dY1DeltaMinF and WorkTab.dY2DeltaMinF then -- [B1] passo da carrello Y1 a entrambi if WorkTab.dY1DeltaI and ( not WorkTab.dY2DeltaI) then WorkTab.dY2DeltaI = WorkTab.dY2DeltaI or ( ParkY2 - WorkTab.dTPosI) return SpecAdjustCarrB1( WorkTab) -- [B2] passo da carrello Y2 a entrambi elseif WorkTab.dY2DeltaI and (not WorkTab.dY1DeltaI) then WorkTab.dY1DeltaI = WorkTab.dY1DeltaI or ( ParkY1 - WorkTab.dTPosI) return SpecAdjustCarrB2(WorkTab) -- [B3] rimango con due carrelli ( per ora accetto solo il caso in cui le posizioni sono già valide) elseif WorkTab.dY1DeltaI > WorkTab.dY1DeltaMinF - 10 * GEO.EPS_SMALL and WorkTab.dY1DeltaI < WorkTab.dY1DeltaMaxF + 10 * GEO.EPS_SMALL and WorkTab.dY2DeltaI > WorkTab.dY2DeltaMinF - 10 * GEO.EPS_SMALL and WorkTab.dY2DeltaI < WorkTab.dY2DeltaMaxF + 10 * GEO.EPS_SMALL then EgtOutLog( '*[B3]', 1) return {} else EgtOutLog( ' Error CLAMP NULL-> Y1+Y2 impossibile') error( 'Error CLAMP NULL-> Y1+Y2 impossibile') end -- |POSIZIONO Y2| **[C]** elseif not WorkTab.dY1DeltaMinF and WorkTab.dY2DeltaMinF then -- [C1]/[C2] continuazione da morsa Y2 ( Y2 -> Y2 ) sacmbio Y1 (Y1 -> Y2) if ( WorkTab.dY1DeltaI and ( not WorkTab.dY2DeltaI)) or ( WorkTab.dY2DeltaI and (not WorkTab.dY1DeltaI)) then WorkTab.bY1Parked = not WorkTab.dY1DeltaI WorkTab.dY1DeltaI = WorkTab.dY1DeltaI or ( ParkY1 - WorkTab.dTPosI) WorkTab.bY2Parked = not WorkTab.dY2DeltaI WorkTab.dY2DeltaI = WorkTab.dY2DeltaI or ( ParkY2 - WorkTab.dTPosI) return SpecAdjustCarrC( WorkTab) else EgtOutLog( ' Error CLAMP NULL-> Y2 impossibile') error( 'Error CLAMP NULL-> Y2 impossibile') end end end ----------------------------------------------------------------------- -- calcolo lo spostamento di Y1 (aperta) e Y2 (chiusa) in **accentramento** local function PosForCent1FY1( dY1a, dY2a, dTa, dExtraY1, dCorsaY1c, dCorsaY2Tc) local dY2Delta = dY2a - dTa local dDispl = dCorsaY1c - dExtraY1 if dDispl / 2 <= dCorsaY2Tc then if dDispl / 2 <= dCorsaY1c then dY1a = dY1a - dDispl / 2 dY2a = dY2a + dDispl / 2 else dY1a = dY1a - dCorsaY1c dY2a = dY2a + dDispl - dCorsaY1c end else dY2a = dY2a + dCorsaY2Tc dY1a = dY1a - (dDispl - dCorsaY2Tc) end dTa = dY2a - dY2Delta return dY1a, dY2a, dTa end ----------------------------------------------------------------------- -- calcolo lo spostamento di Y2 (aperta) e Y1 (chiusa) in **accentramento** local function PosForCent1FY2( dY1a, dY2a, dTa, dExtraY2, dCorsaY1Tc, dCorsaY2c) local dY1Delta = dY1a - dTa local dDispl = dCorsaY2c + dExtraY2 if dDispl / 2 <= dCorsaY1Tc then if dDispl / 2 <= dCorsaY2c then dY1a = dY1a - dDispl / 2 dY2a = dY2a + dDispl / 2 else dY2a = dY2a + dCorsaY2c dY1a = dY1a - min( dDispl - dCorsaY2c, dCorsaY1Tc) end else dY1a = dY1a - dCorsaY1Tc dY2a = dY2a + min( dDispl - dCorsaY1Tc, dCorsaY2c) end dTa = dY1a - dY1Delta return dY1a, dY2a, dTa end ----------------------------------------------------------------------- -- calcolo lo spostamento di Y1 (aperta) e Y2 (chiusa) in **allontanamento** local function PosForEnl1FY1( dY1a, dY2a, dTa, dExtra, dCorsaY1e, dCorsaY2Te) local dDispl = MaxY1 - dY1a + dExtra -- eseguo il posizionamento di Y1 allontanando Y1 e (Y2+T) if dDispl/2 <= dCorsaY2Te then if dDispl/2 <= dCorsaY1e then dY1a = dY1a + dDispl / 2 dY2a = dY2a - dDispl / 2 dTa = dTa - dDispl / 2 else dY1a = dY1a + dCorsaY1e dY2a = dY2a - (dDispl - dCorsaY1e) dTa = dTa - (dDispl - dCorsaY1e) end else dY2a = dY2a - dCorsaY2Te dTa = dTa - dCorsaY2Te dY1a = dY1a + (dDispl - dCorsaY2Te) end return dY1a, dY2a, dTa end ----------------------------------------------------------------------- -- calcolo lo spostamento di Y2 (aperta) e Y1 (chiusa) in **allontanamento** local function PosForEnl1FY2( dY1a, dY2a, dTa, dExtra, dCorsaY1Te, dCorsaY2e) local dDispl = dY2a - MinY2 - dExtra -- eseguo il posizionamento di Y2 allontanando (Y1+T) e Y2 if dDispl/2 <= dCorsaY1Te then if dDispl/2 <= dCorsaY2e then dY1a = dY1a + dDispl / 2 dTa = dTa + dDispl / 2 dY2a = dY2a - dDispl / 2 else dY2a = dY2a - dCorsaY2e dY1a = dY1a + (dDispl - dCorsaY2e) dTa = dTa + (dDispl - dCorsaY2e) end else dY1a = dY1a + dCorsaY1Te dTa = dTa + dCorsaY1Te dY2a = dY2a - (dDispl - dCorsaY1Te) end return dY1a, dY2a, dTa end ----------------------------------------------------------------------- local function MaxDispl( TabI, vCmd, sType) local dY1a, dY2a local dTa = TabI.dTPosI -- **[M1]** = allontanamento dei trascinatori con Y1 in presa if sType == 'M1' then EmitComment( vCmd, '[M1]') -- ev' chiudo Y1, apro Y2 table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- allontano (Y1+T) e (Y2) dY1a = MaxY1 dY2a = MinY2 dTa = ( dY1a - TabI.dY1PosI) + dTa -- **[M2]** = allontanamento dei trascinatori con Y2 in presa elseif sType == 'M2' then EmitComment( vCmd, '[M2]') -- ev' chiudo Y2, apro Y1 table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) EMC.CNT = nil -- allontano (Y2+T) e (Y1) dY1a = MaxY1 dY2a = MinY2 dTa = ( dY2a - TabI.dY2PosI) + dTa -- **[M3]** = accentramento dei trascinatori con Y1 in presa elseif sType == 'M3' then EmitComment( vCmd, '[M3]') -- ev' chiudo Y1, apro Y2 table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- accentro (Y1+T) e (Y2) dY1a = TabI.MyMinY1V1 dY2a = TabI.MaxY2V2 dTa = ( dY1a - TabI.dY1PosI) + dTa -- **[M4]** = accentramento dei trascinatori con Y2 in presa elseif sType == 'M4' then EmitComment( vCmd, '[M4]') -- ev' chiudo Y2, apro Y1 table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) EMC.CNT = nil -- accentro (Y2+T) e (Y1) dY1a = TabI.MyMinY1V1 dY2a = TabI.MaxY2V2 dTa = ( dY2a - TabI.dY2PosI) + dTa end -- table.insert( vCmd, { 3, 'Y1', dY1a, 'Y2', dY2a, 'T', dTa, EMC.CNT}) TabI.dY1PosI = dY1a TabI.dY2PosI = dY2a TabI.dTPosI = dTa end -- MaxDisplForRiXw ----------------------------------------------------------------------------------------------------------- -- **ALLONTANAMENTO di Y1** ------------------------------------------------------------------------------------------------------------------ local function PosY1FromY2A( TabI, vCmd) EmitComment( vCmd, '[PosY1FromY2A]') local t = {} -- **calcolo i delta dai dati iniziali** t.dY1NewDelta = ( TabI.dY1DeltaMaxF + TabI.dY1DeltaMinF)/2 -- valuto gli estremi degli intervalli, con riferimento alle posizioni attuali t.dExtraY1New = (TabI.dTPosI + t.dY1NewDelta) - MaxY1 --se > 0, la posizione non è raggiunginile -- corse disponibili in allontanamento (enlargement) dalle posizioni attuali per Y1 e (Y2+T) t.dCorsaY1eI = MaxY1 - TabI.dY1PosI t.dCorsaY2TeI= TabI.dY2PosI - MinY2 -- |RICONOSCO I CASI| -- **[(0)]** morsa Y1 già entro l'intervallo : non si deve muovere t.dY1DeltaI = TabI.dY1PosI-TabI.dTPosI if t.dY1DeltaI < TabI.dY1DeltaMaxF + 10 * GEO.EPS_SMALL and t.dY1DeltaI > TabI.dY1DeltaMinF - 10 * GEO.EPS_SMALL then EmitComment( vCmd, '[Y1(0)] ') --return t.dY1DeltaI -- **[ri]** = posY1New non raggiungibile direttamente -> muovo fino a fine corsa elseif t.dExtraY1New > t.dCorsaY2TeI then EmitComment( vCmd, '[Y1A-ri]') if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y2DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI}) end -- questo movimento serve solo a gestire (in modo complesso) il caso [ri] MaxDispl( TabI, vCmd, 'M2') --t.bXW = true else -- **[rp]** = raggiungo il punto medio Y1New dell'intervallo EmitComment( vCmd, '[Y1A-rp] ') if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y2DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- **1:** calcolo pos. di allontanamento per (Y1) e (Y2+T) (da posizioni iniziali) TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI = PosForEnl1FY1( TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI, t.dExtraY1New, t.dCorsaY1eI, t.dCorsaY2TeI) -- aggiornamento posizioni e dY1Delta dopo -- chiusura di Y1, apertura e parcheggio di Y2 a fine funzione -- ev' chiudo Y2 e apro Y1 ed eseguo allontanamento table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) EMC.CNT = nil table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end t.dY1DeltaA = TabI.dY1PosI - TabI.dTPosI -- chiusura di Y1, ev' apertura e parcheggio di Y2 : in funzioni chiamanti return t.dY1DeltaA end -- PosY1FromY2A -------------------------------------------------------------------------------------------------------- -- **ALLONTANAMENTO di Y2** -------------------------------------------------------------------------------------------------------- local function PosY2FromY1A( TabI, vCmd) EmitComment( vCmd, '[PosY2FromY1A]') local t = {} -- **calcolo i delta dai dati iniziali** t.dY2NewDelta = ( TabI.dY2DeltaMaxF + TabI.dY2DeltaMinF)/2 -- valuto gli estremi degli intervalli, con riferimento alle posizioni attuali t.dExtraY2New = ( TabI.dTPosI + t.dY2NewDelta) - MinY2 --se < 0, la posizione non è raggiunginile -- corse disponibili in allontanamento (enlargement) dalle posizioni attuali per (Y1+T) e Y2 t.dCorsaY1Te = MaxY1 - TabI.dY1PosI t.dCorsaY2e = TabI.dY2PosI - MinY2 -- -- |RICONOSCO I CASI| -- **[(0)]** morsa Y2 già entro l'intervallo : non si deve muovere t.dY2DeltaI = TabI.dY2PosI- TabI.dTPosI if t.dY2DeltaI < TabI.dY2DeltaMaxF + 10 * GEO.EPS_SMALL and t.dY2DeltaI > TabI.dY2DeltaMinF - 10 * GEO.EPS_SMALL then EmitComment( vCmd, '[Y2(0)] ') -- **[ri]** = posY2New non raggiungibile direttamente -> muovo fino a fine corsa elseif -t.dExtraY2New > t.dCorsaY1Te then EmitComment( vCmd, '[Y2A-ri]' ) if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y1DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- questo movimento serve solo a gestire (in modo complesso) il caso [ri] MaxDispl( TabI, vCmd, 'M1') else -- **[rp]** = raggiungo il punto medio Y2New dell'intervallo EmitComment( vCmd, '[Y2A-rp] ') if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y1DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- **1:** calcolo pos. di allontanamento per (Y1+T) e (Y2) (da posizioni iniziali) TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI = PosForEnl1FY2( TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI, t.dExtraY2New, t.dCorsaY1Te, t.dCorsaY2e) -- chiudo Y1 e apro Y2 ed eseguo allontanamento (finale) table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end t.dY2DeltaA = TabI.dY2PosI - TabI.dTPosI -- chiusura di Y2, ev' apertura e parcheggio di Y1 : in funzioni chiamanti return t.dY2DeltaA end -- PosY2FromY1A ------------------------------------------------------------------------------------------------------------ -- **ACCENTRAMENTO di Y1** ------------------------------------------------------------------------------------------------------------ local function PosY1FromY2B( TabI, vCmd) EmitComment( vCmd, '[PosY1FromY2B]') local t = {} -- **calcolo i delta dai dati iniziali** t.dY1NewDelta = ( TabI.dY1DeltaMaxF + TabI.dY1DeltaMinF)/2 -- valuto gli estremi degli intervalli, con riferimento alle posizioni attuali t.dExtraY1New = (TabI.dTPosI + t.dY1NewDelta) - TabI.MyMinY1V1 -- se < 0, la posizione non è raggiunginile -- corse in accentramento disponibili per Y1 e (Y2+T) dalle posizioni iniziali t.dCorsaY1cI = TabI.dY1PosI - TabI.MyMinY1V1 t.dCorsaY2TcI = TabI.MaxY2V2 - TabI.dY2PosI -- -- |RICONOSCO I CASI| -- **[(0)]** morsa Y1 già entro l'intervallo : non si deve muovere t.dY1DeltaI = TabI.dY1PosI-TabI.dTPosI if t.dY1DeltaI < TabI.dY1DeltaMaxF + 10 * GEO.EPS_SMALL and t.dY1DeltaI > TabI.dY1DeltaMinF - 10 * GEO.EPS_SMALL then EmitComment( vCmd, '[Y1(0)] ') -- **[ri]** = posY1New non raggiungibile direttamente -> muovo fino a fine corsa elseif -t.dExtraY1New > t.dCorsaY2TcI then EmitComment( vCmd, '[Y1B-ri]') if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y2DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- questo movimento serve solo a gestire (in modo complesso) il caso [ri] MaxDispl( TabI, vCmd, 'M4') else -- **[rp]** = raggiungo il punto medio Y1New dell'intervallo EmitComment( vCmd, '[Y1B-rp] ') if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y2DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- **1: calcolo accentramento di (Y1) e (Y2+T)** TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI = PosForCent1FY1( TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI, t.dExtraY1New, t.dCorsaY1cI, t.dCorsaY2TcI) -- posizionamento efettivo e aggiornamento di vCmd e dY1Delta dopo -- ch. di Y1 e ap. e parcheggio di Y2 a fine funzione chiamante -- chiudo Y2 e apro Y1 ed eseguo accentramento (finale) table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) EMC.CNT = nil table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end t.dY1DeltaA = TabI.dY1PosI - TabI.dTPosI -- chiusura di Y1, ev' apertura e parcheggio di Y2 : in funzioni chiamanti return t.dY1DeltaA end -- PosY1FromY2B -------------------------------------------------------------------------------------------------------- -- **ACCENTRAMENTO di Y2** -------------------------------------------------------------------------------------------------------- local function PosY2FromY1B( TabI, vCmd) EmitComment( vCmd, '[PosY2FromY1B]') local t = {} -- **calcolo i delta dai dati iniziali** t.dY2NewDelta = ( TabI.dY2DeltaMaxF + TabI.dY2DeltaMinF)/2 -- valuto gli estremi degli intervalli, con riferimento alle posizioni attuali t.dExtraY2New = (TabI.dTPosI + t.dY2NewDelta) - TabI.MaxY2V2 -- se > 0 la posizione non è raggiunginile -- corse in accentramento disponibili per (Y1+T) e (Y2) dalle posizioni iniziali t.dCorsaY1TcI = TabI.dY1PosI - TabI.MyMinY1V1 t.dCorsaY2cI = TabI.MaxY2V2 - TabI.dY2PosI -- |RICONOSCO I CASI| -- **[(0)]** morsa Y2 già entro l'intervallo : non si deve muovere t.dY2DeltaI = TabI.dY2PosI-TabI.dTPosI if t.dY2DeltaI < TabI.dY2DeltaMaxF + 10 * GEO.EPS_SMALL and t.dY2DeltaI > TabI.dY2DeltaMinF - 10 * GEO.EPS_SMALL then EmitComment( vCmd, '[Y2(0)] ') -- **[ri]** = posY2New non raggiungibile direttamente -> muovo fino a fine corsa elseif t.dExtraY2New > t.dCorsaY1TcI then EmitComment( vCmd, '[Y2B-ri]' ) if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y1DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- questo movimento serve solo a gestire (in modo complesso) il caso [ri] MaxDispl( TabI, vCmd, 'M3') else -- **[rp]** = raggiungo il punto medio Y2New dell'intervallo EmitComment( vCmd, '[Y2B-rp] ') if not SpecTestSomeMoveInCmds( vCmd) and not EMC.Y1DELTA then table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end -- Y1 chiuso, Y2 aperto -- **1: calcolo accentramento di (Y1+T) e (Y2)** TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI = PosForCent1FY2( TabI.dY1PosI, TabI.dY2PosI, TabI.dTPosI, t.dExtraY2New, t.dCorsaY1TcI, t.dCorsaY2cI) -- ev' chiudo Y1 e apro Y2 ed eseguo movimento accentramento table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) table.insert( vCmd, { 3, 'Y1', TabI.dY1PosI, 'Y2', TabI.dY2PosI, 'T', TabI.dTPosI, EMC.CNT}) end t.dY2DeltaA = TabI.dY2PosI - TabI.dTPosI -- chiusura di Y2, apertura e parcheggio di Y1 : in funzioni chiamanti return t.dY2DeltaA end -- PosY2FromY1B -------------------------------------------------------------------------------------------------------- -- **ALLONTANAMENTO di Y1 per pos. di Y2 o Y2+Y1** - chiamata da [B2] e [C] -------------------------------------------------------------------------------------------------------- local function PosY1Y2A( TabI, vCmd) EmitComment( vCmd, '[PosY1Y2A]') -- |RICONOSCO I CASI| repeat local dY2NewDelta = ( TabI.dY2DeltaMaxF + TabI.dY2DeltaMinF)/2 local bXW = true -- se intervallo per Y1 raggiungibile in una sola fase -- ossia se posso posizionare 'direttamente' Y1 all'interno dell'intervallo I1 <=> ( -ExtraI1MaxF < Corsa Y2Tc) -- e Y2 è in posizione per aggancio su T if ( TabI.dTPosI + TabI.dY1DeltaMinF) - MaxY1 < TabI.dY2PosI - MinY2 and TabI.dY2PosI > TabI.dTPosI + MinJoin + EMC.HCING + EMC.HOVM - 10 * GEO.EPS_SMALL then -- |POSIZIONO MORSA 1| in **allontanamento** PosY1FromY2A( TabI, vCmd) -- |POSIZIONO MORSA 2| if (TabI.dTPosI + dY2NewDelta) < TabI.dY2PosI then -- in **allontanamento** PosY2FromY1A( TabI, vCmd) else -- in **accentramento** PosY2FromY1B( TabI, vCmd) end bXW = false else -- |POSIZIONO MORSA 2| e poi MORSA 1 -- in **allontanamento** if (TabI.dTPosI + dY2NewDelta) < TabI.dY2PosI then -- se intervallo per Y2 raggiungibile in una sola fase if - (( TabI.dTPosI + TabI.dY2DeltaMaxF) - MinY2) < MaxY1 - TabI.dY1PosI then PosY2FromY1A( TabI, vCmd) PosY1FromY2A( TabI, vCmd) bXW = false end else -- in **accentramento** -- sempre se intervallo per Y2 raggiungibile in una sola fase if ( TabI.dTPosI + TabI.dY2DeltaMinF) - TabI.MaxY2V2 < TabI.dY1PosI - TabI.MyMinY1V1 then PosY2FromY1B( TabI, vCmd) PosY1FromY2A( TabI, vCmd) bXW = false end end end if bXW then -- Massimo trascinamento della trave in direzione negativa ( casi **[xw]**) EmitComment( vCmd, '[Y1A-xw]') if TabI.dY1PosI ~= TabI.MyMinY1V1 then -- accentramento morse, trascinamento trave con Y1 MaxDispl( TabI, vCmd, 'M3') else -- allontanamento morse, trascinamento trave con Y2 MaxDispl( TabI, vCmd, 'M2') end end until ( not bXW) -- chiusura/parcheggio dei trascinatori in funzioni chiamanti local dY1Delta = TabI.dY1PosI - TabI.dTPosI local dY2Delta = TabI.dY2PosI - TabI.dTPosI return dY1Delta, dY2Delta end -- PosY1Y2A -------------------------------------------------------------------------------------------------------- -- **ACCENTRAMENTO di Y1 per pos. di Y2 o Y2+Y1** - chiamata da [B2] e [C] -------------------------------------------------------------------------------------------------------- local function PosY1Y2B( TabI, vCmd) EmitComment( vCmd, '[PosY1Y2B]') -- |RICONOSCO I CASI| local nCnt = 0 repeat local dY2NewDelta = ( TabI.dY2DeltaMaxF + TabI.dY2DeltaMinF) / 2 local bXW = true -- se intervallo per Y1 raggiungibile in una sola fase -- ossia se posso posizionare 'direttamente' Y1 all'interno dell'intervallo I1 <=> ( -ExtraI1MaxF < Corsa Y2Tc) -- e Y2 è in posizione per aggancio su T if -(( TabI.dTPosI + TabI.dY1DeltaMaxF) - TabI.MyMinY1V1) < TabI.MaxY2V2 - TabI.dY2PosI and TabI.dY2PosI > TabI.dTPosI + MinJoin + EMC.HCING + EMC.HOVM - 10 * GEO.EPS_SMALL then -- |POSIZIONO MORSA 1| in **accentramento** PosY1FromY2B( TabI, vCmd) -- |POSIZIONO MORSA 2| local dY2DeltaI = TabI.dY2PosI - TabI.dTPosI -- Se il trascinatore 2 non è già nell'intervallo richiesto if dY2DeltaI > TabI.dY2DeltaMaxF + 10 * GEO.EPS_SMALL or dY2DeltaI < TabI.dY2DeltaMinF - 10 * GEO.EPS_SMALL then if ( TabI.dTPosI + dY2NewDelta) < TabI.dY2PosI then -- in **allontanamento** PosY2FromY1A( TabI, vCmd) else -- in **accentramento** PosY2FromY1B( TabI, vCmd) end end bXW = false -- se posso posizionare 'direttamente' Y2 all'interno dell'intervallo I2 (casi [rp] o [ri]) else -- |POSIZIONO MORSA 2| e poi MORSA 1 -- in **allontanamento** if ( TabI.dTPosI + dY2NewDelta) < TabI.dY2PosI then -- se intervallo per Y2 è raggiungibile in una sola fase e Y1 è in posizione per aggancio su T if -(( TabI.dTPosI + TabI.dY2DeltaMaxF) - MinY2) < MaxY1 - TabI.dY1PosI and TabI.dY1PosI < TabI.dTPosI + EMC.LB - MinJoin - EgtIf( SPLIT, EMC.TCING, 0) + 10 * GEO.EPS_SMALL then PosY2FromY1A( TabI, vCmd) PosY1FromY2B( TabI, vCmd) bXW = false end -- in **accentramento** else -- sempre se intervallo per Y2 è raggiungibile in una sola fase e Y1 è in posizione per aggancio su T if ( TabI.dTPosI + TabI.dY2DeltaMinF) - TabI.MaxY2V2 < TabI.dY1PosI - TabI.MyMinY1V1 and TabI.dY1PosI <= TabI.dTPosI + EMC.LB - MinJoin - EgtIf( SPLIT, EMC.TCING, 0) + 10 * GEO.EPS_SMALL then PosY2FromY1B( TabI, vCmd) PosY1FromY2B( TabI, vCmd) bXW = false end end end if bXW then -- Massimo trascinamento della trave in direzione positiva (casi **[xw]** ) -- se Y1 non è a f.c. e se Y1 può afferrare la trave EmitComment( vCmd, '[Y1B-xw]') if TabI.dY1PosI ~= MaxY1 and TabI.dY1PosI < TabI.dTPosI + EMC.LB - MinJoin - EgtIf( SPLIT, EMC.TCING, 0) + 10 * GEO.EPS_SMALL then -- allontanamento morse, trascinamento trave con Y1 MaxDispl( TabI, vCmd, 'M1') else -- accentramento morse, trascinamento trave con Y2 MaxDispl( TabI, vCmd, 'M4') end end nCnt = nCnt + 1 if nCnt > 10 then return end until ( not bXW) -- chiusura/parcheggio dei trascinatori in funzioni chiamanti local dY1Delta = TabI.dY1PosI - TabI.dTPosI local dY2Delta = TabI.dY2PosI - TabI.dTPosI return dY1Delta, dY2Delta end -- PosY1Y2B -------------------------------------------------------------------------------------------------------- -- **ALLONTANAMENTO di Y2 per pos. di Y1 o Y1+Y2** - chiamata da [A] e [B1] -------------------------------------------------------------------------------------------------------- local function PosY2Y1A( TabI, vCmd) EmitComment( vCmd, '[PosY2Y1A]') -- |RICONOSCO I CASI| repeat local dY1NewDelta = ( TabI.dY1DeltaMaxF + TabI.dY1DeltaMinF)/2 local bXW = true -- se intervallo per Y2 raggiungibile in una sola fase -- ossia se posso posizionare 'direttamente' Y2 all'interno dell'intervallo <=> ( -ExtraI2MaxF < Corsa Y1Te and) -- e Y1 è in posizione per aggancio su T if MinY2 - ( TabI.dTPosI + TabI.dY2DeltaMaxF) < MaxY1 - TabI.dY1PosI and TabI.dY1PosI < TabI.dTPosI + EMC.LB - MinJoin - EgtIf( SPLIT, EMC.TCING, 0) + 10 * GEO.EPS_SMALL then -- |POSIZIONO MORSA 2| in **allontanamento** PosY2FromY1A( TabI, vCmd) -- |POSIZIONO MORSA 1| if ( TabI.dTPosI + dY1NewDelta) > TabI.dY1PosI then -- in **allontanamento** PosY1FromY2A( TabI, vCmd) else -- in **accentramento** PosY1FromY2B( TabI, vCmd) end bXW = false else -- |POSIZIONO MORSA 1| e poi MORSA 2 -- caso di allontanamento if ( TabI.dTPosI + dY1NewDelta) > TabI.dY1PosI then -- se l'intervallo per Y1 è raggiungibile in una sola fase if ( TabI.dTPosI + TabI.dY1DeltaMinF) - MaxY1 < TabI.dY2PosI - MinY2 then PosY1FromY2A( TabI, vCmd) PosY2FromY1A( TabI, vCmd) bXW = false end -- in **accentramento** else -- sempre se l'intervallo per Y1 è raggiungibile in una sola fase if TabI.MyMinY1V1 - ( TabI.dTPosI + TabI.dY1DeltaMaxF) < TabI.MaxY2V2 - TabI.dY2PosI then PosY1FromY2B( TabI, vCmd) PosY2FromY1A( TabI, vCmd) bXW = false end end end if bXW then -- Massimo trascinamento della trave in direzione positiva (casi **[xw]**) EmitComment( vCmd, '[Y2A-xw]') -- accentramento morse, trascinamento trave con Y2 if TabI.dY2PosI ~= TabI.MaxY2V2 then MaxDispl( TabI, vCmd, 'M4') -- allontanamento morse, trascinamento trave con Y1 else MaxDispl( TabI, vCmd, 'M1') end end until ( not bXW) -- chiusura/parcheggio dei trascinatori in funzioni chiamanti local dY1Delta = TabI.dY1PosI - TabI.dTPosI local dY2Delta = TabI.dY2PosI - TabI.dTPosI return dY1Delta, dY2Delta end -- PosY2Y1A -------------------------------------------------------------------------------------------------------- -- **ACCENTRAMENTO di Y2 per pos. di Y1 o Y1+Y2** - chiamata da [A] e [B1] -------------------------------------------------------------------------------------------------------- local function PosY2Y1B( TabI, vCmd) EmitComment( vCmd, '[PosY2Y1B]') -- |RICONOSCO I CASI| local nCnt = 0 repeat local dY1NewDelta = ( TabI.dY1DeltaMaxF + TabI.dY1DeltaMinF) / 2 local bXW = true -- se intervallo per Y2 raggiungibile in una sola fase -- ossia se posso posizionare 'direttamente' Y2 all'interno dell'intervallo I2 <=> (-ExtraI2MinF < Corsa Y1Tc) -- e Y1 è in posizione per aggancio su T if ( TabI.dTPosI + TabI.dY2DeltaMinF) - TabI.MaxY2V2 < TabI.dY1PosI - TabI.MyMinY1V1 and TabI.dY1PosI < TabI.dTPosI + EMC.LB - MinJoin - EgtIf( SPLIT, EMC.TCING, 0) + 10 * GEO.EPS_SMALL then -- |POSIZIONO MORSA 2| in **accentramento** PosY2FromY1B( TabI, vCmd) -- |POSIZIONO MORSA 1| local dY1DeltaI = TabI.dY1PosI - TabI.dTPosI -- Se il trascinatore 1 non è già nell'intervallo richiesto if dY1DeltaI > TabI.dY1DeltaMaxF + 10 * GEO.EPS_SMALL or dY1DeltaI < TabI.dY1DeltaMinF - 10 * GEO.EPS_SMALL then if ( TabI.dTPosI + dY1NewDelta) > TabI.dY1PosI then -- in **allontanamento** PosY1FromY2A( TabI, vCmd) else -- in **accentramento** PosY1FromY2B( TabI, vCmd) end end bXW = false -- se posso posizionare 'direttamente' Y1 all'interno dell'intervallo I1 (casi [rp] o [ri]) else -- |POSIZIONO MORSA 1| e poi MORSA 2 -- in **allontanamento** if ( TabI.dTPosI + dY1NewDelta) > TabI.dY1PosI then -- se intervallo per Y1 è raggiungibile in una sola fase e Y2 è in posizione per aggancio su T if ( TabI.dTPosI + TabI.dY1DeltaMinF) - MaxY1 < TabI.dY2PosI - MinY2 and TabI.dY2PosI > TabI.dTPosI + MinJoin + EMC.HCING + EMC.HOVM - 10 * GEO.EPS_SMALL then PosY1FromY2A( TabI, vCmd) PosY2FromY1B( TabI, vCmd) bXW = false end -- in **accentramento** else -- se (-ExtraI1MaxF < Corsa Y2Tc) e (Y2 è in posizione per aggancio su T) if TabI.MyMinY1V1 - ( TabI.dTPosI + TabI.dY1DeltaMaxF) < TabI.MaxY2V2 - TabI.dY2PosI and TabI.dY2PosI >= TabI.dTPosI + MinJoin + EMC.HCING + EMC.HOVM - 10 * GEO.EPS_SMALL then PosY1FromY2B( TabI, vCmd) PosY2FromY1B( TabI, vCmd) bXW = false end end end if bXW then -- Massimo trascinamento della trave in direzione negativa (casi x[w]) EmitComment( vCmd, '[Y2B-xw]') -- se Y2 non è a f.c. e se Y2 può afferrare la trave if TabI.dY2PosI > MinY2 and TabI.dY2PosI > TabI.dTPosI + MinJoin + EMC.HOVM + EMC.HCING - 10 * GEO.EPS_SMALL then -- allontanamento morse, trascinamento trave con Y2 MaxDispl( TabI, vCmd, 'M2') else -- accentramento morse, trascinamento trave con Y1 MaxDispl( TabI, vCmd, 'M3') end end nCnt = nCnt + 1 if nCnt > 10 then return end until ( not bXW) -- la chiusura delle morse è fatta sopra local dY1Delta = TabI.dY1PosI - TabI.dTPosI local dY2Delta = TabI.dY2PosI - TabI.dTPosI return dY1Delta, dY2Delta end -- PosY2Y1FromY1B --------------------------------------------------------------------- -- **[A] Posizionamento trascinatore Y1 da (Y1 o Y2) <=> Y1/Y2 -> Y1** --------------------------------------------------------------------- function SpecAdjustCarrA( WorkTab) -- Elenco comandi local vCmd = {} table.insert( vCmd, { 0, 'Y1/Y2 -> Y1'}) EmitComment( vCmd, '*[A]') local MinY1V1 = max( WorkTab.dV1PosI + AGG_V, MinY1) local MaxY2V2 = min( WorkTab.dV2PosI - AGG_V, MaxY2) -- se primo scambio local MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1V1 + AggLoad, MinY1V1) -- recupero le posizioni correnti local dY1PosI = WorkTab.dTPosI + WorkTab.dY1DeltaI local dY2PosI = WorkTab.dTPosI + WorkTab.dY2DeltaI local dY1DeltaF -- posizioni obiettivo dei carrelli al centro dei rispettivi intervalli di validità EgtOutLog( ' Y1DeltaI=' .. EgtNumToString( WorkTab.dY1DeltaI) .. ' Y2DeltaI=' .. EgtNumToString( WorkTab.dY2DeltaI), 1) EgtOutLog( ' Y1DeltaMinF=' .. EgtNumToString( WorkTab.dY1DeltaMinF)..' Y1DeltaMaxF=' .. EgtNumToString( WorkTab.dY1DeltaMaxF), 1) -- [A(1)] - Se il trascinatore Y1 non è nell'intervallo valido, devo posizionarlo if WorkTab.dY1DeltaI < WorkTab.dY1DeltaMinF - GEO.EPS_SMALL or WorkTab.dY1DeltaI > WorkTab.dY1DeltaMaxF + GEO.EPS_SMALL then EmitComment( vCmd, '*[A(1)]') -- ----------------------------------------- -- |VERIFICO POSIZIONE RULLI| -- ------------------------------------------ -- eseguo eventuale posizionamento sicuro di teste e rulli if WorkTab.bCloseV then EnsureZmax( true, vCmd) MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1 + AggLoad, MinY1) MaxY2V2 = MaxY2 end -- ------------------------------------------ -- |DEFINISCO INTERVALLO 2| -- ------------------------------------------ WorkTab.dY2DeltaMaxF = WorkTab.dY1DeltaMinF - ( MyMinY1V1 - MaxY2V2) + ( WorkTab.dY1DeltaMaxF - WorkTab.dY1DeltaMinF) WorkTab.dY2DeltaMinF = WorkTab.dY1DeltaMaxF - ( MaxY1 - MinY2) - ( WorkTab.dY1DeltaMaxF - WorkTab.dY1DeltaMinF) -- se Y2 deve allontanarsi assegno il primo punto valido (altrimenti mantengo tutto l'intervallo valido) if WorkTab.dY2DeltaI > WorkTab.dY2DeltaMaxF then WorkTab.dY2DeltaMinF = max( WorkTab.dY2DeltaMaxF - ( WorkTab.dY1DeltaMaxF - WorkTab.dY1DeltaMinF), MinJoin + EMC.HCING + EMC.HOVM) end -- se la trave è più 'corta' dell'intervallo per Y2 aggiorno l'intervallo (potrei essere comunque in un punto valido) if WorkTab.dY2DeltaMinF < MinJoin + EMC.HCING + EMC.HOVM then WorkTab.dY2DeltaMinF = MinJoin + EMC.HCING + EMC.HOVM -- se Y2 deve accentrarsi if WorkTab.dY2DeltaI < WorkTab.dY2DeltaMinF then WorkTab.dY2DeltaMaxF = 2 * MinJoin + EMC.HCING + EMC.HOVM end end -- posizioni obiettivo dei carrelli al centro dei rispettivi intervalli di validità local dY1NewDelta = ( WorkTab.dY1DeltaMinF + WorkTab.dY1DeltaMaxF) / 2 local dY2NewDelta = ( WorkTab.dY2DeltaMinF + WorkTab.dY2DeltaMaxF) / 2 -------------------------------------------- -- |RICONOSCO I CASI| -------------------------------------------- TabValI = {dY1PosI=dY1PosI, dY2PosI=dY2PosI, dTPosI=WorkTab.dTPosI, MyMinY1V1=MyMinY1V1, MaxY2V2=MaxY2V2, dY1DeltaMaxF=WorkTab.dY1DeltaMaxF, dY1DeltaMinF=WorkTab.dY1DeltaMinF, dY2DeltaMaxF=WorkTab.dY2DeltaMaxF, dY2DeltaMinF=WorkTab.dY2DeltaMinF } if WorkTab.dY1DeltaI > dY1NewDelta then --[A(1)B] **ACCENTRAMENTO** (dall'origine) del trascinatore Y1 EmitComment( vCmd, '[A-Y1B]') dY1DeltaF = PosY1Y2B( TabValI, vCmd) else --[A(1)A] **ALLONTANAMENTO** (dall'origine) del trascinatore Y1 EmitComment( vCmd, '[A-Y1A]') dY1DeltaF = PosY1Y2A( TabValI, vCmd) end -- chiudo Y1 table.insert( vCmd, { 11, 1}) -- dichiaro Y2 da parcheggiare WorkTab.bY2Parked = false -- [A(0)] - Se Y1 è già nell'intervallo valido, si lascia dove è else EmitComment( vCmd, '*[A(0)]') if not WorkTab.bY2Parked then -- dichiaro posizione di Y2 e T table.insert( vCmd, { 2, 'T', WorkTab.dTPosI, 'Y2', dY2PosI}) end if WorkTab.bY1Parked then -- chiudo Y1 table.insert( vCmd, { 11, 1}) end dY1DeltaF = WorkTab.dY1DeltaI end if not WorkTab.bY2Parked then -- apro e parcheggio Y2 table.insert( vCmd, { 12, 0}) table.insert( vCmd, { 1, 'Y2', ParkY2}) end -- aggiorno e segnalo la posizione finale Y1Delta table.insert( vCmd, { 21, dY1DeltaF, 0}) EgtOutLog( ' Y1DeltaF=' .. EgtNumToString( dY1DeltaF), 1) -- segnalo la posizione dei rulli table.insert( vCmd, { 22, WorkTab.dV1PosF, WorkTab.dV2PosF}) SpecOutputCNT() return vCmd end -- SpecAdjustCarrAA -------------------------------------------------------------------- -- **[B1] da trascinatore Y1 a entrambi <=> Y1 -> Y1+Y2** -------------------------------------------------------------------- function SpecAdjustCarrB1( WorkTab) -- Elenco comandi local vCmd = {} table.insert( vCmd, { 0, 'Y1 -> Y1+Y2'}) EmitComment( vCmd, '*[B1]') local MinY1V1 = max( WorkTab.dV1PosI + AGG_V, MinY1) local MaxY2V2 = min( WorkTab.dV2PosI - AGG_V, MaxY2) -- se primo scambio local MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1V1 + AggLoad, MinY1V1) -- recupero le posizioni correnti local dY1PosI = WorkTab.dTPosI + WorkTab.dY1DeltaI local dY2PosI = WorkTab.dTPosI + WorkTab.dY2DeltaI local dY1DeltaF, dY2DeltaF -- posizioni obiettivo dei carrelli al centro dei rispettivi intervalli di validità local dY1NewDelta = ( WorkTab.dY1DeltaMinF + WorkTab.dY1DeltaMaxF) / 2 local dY2NewDelta = ( WorkTab.dY2DeltaMinF + WorkTab.dY2DeltaMaxF) / 2 -- EgtOutLog( ' Y1DeltaI='..EgtNumToString( WorkTab.dY1DeltaI) .. ' Y2DeltaI='..EgtNumToString( WorkTab.dY2DeltaI), 1) EgtOutLog( ' Y1DeltaMinF=' .. EgtNumToString( WorkTab.dY1DeltaMinF)..' Y1DeltaMaxF=' .. EgtNumToString( WorkTab.dY1DeltaMaxF), 1) EgtOutLog( ' Y2DeltaMinF=' .. EgtNumToString( WorkTab.dY2DeltaMinF)..' Y2DeltaMaxF=' .. EgtNumToString( WorkTab.dY2DeltaMaxF), 1) -- Il controllo che i trascinatori non siano già nell'intervallo valido è svolto nelle funzioni a valle -- ----------------------------------------- -- |VERIFICO POSIZIONE RULLI| -- ------------------------------------------ if WorkTab.bCloseV then EnsureZmax( true, vCmd) MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1 + AggLoad, MinY1) MaxY2V2 = MaxY2 end -- ----------------------------------------- -- |RICONOSCO I CASI| -- ------------------------------------------ -- definisco la tabella delle posizioni iniziali TabValI = {dY1PosI=dY1PosI, dY2PosI=dY2PosI, dTPosI=WorkTab.dTPosI, MyMinY1V1=MyMinY1V1, MaxY2V2=MaxY2V2, dY1DeltaMaxF=WorkTab.dY1DeltaMaxF, dY1DeltaMinF=WorkTab.dY1DeltaMinF, dY2DeltaMaxF=WorkTab.dY2DeltaMaxF, dY2DeltaMinF=WorkTab.dY2DeltaMinF } -- [B1-Y2A] **ALLONTANAMENTO** del trascinatore **Y2** e (eventuale) posizionamento di Y1 if WorkTab.dY2DeltaI > dY2NewDelta then EmitComment( vCmd, '[B1-Y2A]') dY1DeltaF, dY2DeltaF = PosY2Y1A( TabValI, vCmd) else -- [B1-Y2B] **ACCENTRAMENTO** del trascinatore **Y2** e (eventuale) posizionamento di Y1 EmitComment( vCmd, '[B1-Y2B] ') dY1DeltaF, dY2DeltaF = PosY2Y1B( TabValI, vCmd) end -- ----------------------------------------- -- |CHIUSURA MORSE| -- ------------------------------------------ if not SpecTestSomeMoveInCmds( vCmd) then table.insert( vCmd, { 3, 'Y1', dY1PosI, 'Y2', dY2PosI, 'T', WorkTab.dTPosI, EMC.CNT}) end table.insert( vCmd, { 12, 1}) -- Chiudo Y2 table.insert( vCmd, { 11, 1}) -- chiudo Y1 -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, dY1DeltaF, dY2DeltaF}) EgtOutLog( ' Y1DeltaF=' .. EgtNumToString( dY1DeltaF) .. ' Y2DeltaF=' .. EgtNumToString( dY2DeltaF), 1) -- segnalo la posizione dei rulli table.insert( vCmd, { 22, WorkTab.dV1PosF, WorkTab.dV2PosF}) SpecOutputCNT() return vCmd end -- SpecAdjustCarrB1 --------------------------------------------------------------------- -- **[B2] da trascinatore Y2 a entrambi <=> Y2 -> Y1+Y2** -------------------------------------------------------------------- function SpecAdjustCarrB2( WorkTab) -- Elenco comandi local vCmd = {} table.insert( vCmd, { 0, 'Y2 -> Y1+Y2'}) EmitComment( vCmd, '*[B2]') local MinY1V1 = max( WorkTab.dV1PosI + AGG_V, MinY1) local MaxY2V2 = min( WorkTab.dV2PosI - AGG_V, MaxY2) -- se primo scambio local MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1V1 + AggLoad, MinY1V1) -- definisco le posizioni **Iniziali** (= recupero le posizioni correnti) local dY1PosI = WorkTab.dTPosI + WorkTab.dY1DeltaI local dY2PosI = WorkTab.dTPosI + WorkTab.dY2DeltaI local dY2DeltaF, dY1DeltaF -- posizioni obiettivo dei carrelli al centro dei rispettivi intervalli di validità local dY1NewDelta = ( WorkTab.dY1DeltaMinF + WorkTab.dY1DeltaMaxF) / 2 local dY2NewDelta = ( WorkTab.dY2DeltaMinF + WorkTab.dY2DeltaMaxF) / 2 -- EgtOutLog( ' Y1DeltaI='..EgtNumToString( WorkTab.dY1DeltaI)..' Y2DeltaI='..EgtNumToString( WorkTab.dY2DeltaI), 1) EgtOutLog( ' Y1DeltaMinF=' .. EgtNumToString( WorkTab.dY1DeltaMinF)..' Y1DeltaMaxF=' .. EgtNumToString( WorkTab.dY1DeltaMaxF), 1) EgtOutLog( ' Y2DeltaMinF=' .. EgtNumToString( WorkTab.dY2DeltaMinF)..' Y2DeltaMaxF=' .. EgtNumToString( WorkTab.dY2DeltaMaxF), 1) -- Il controllo che i trascinatori non siano già nell'intervallo valido è svolto nelle funzioni a valle -- ----------------------------------------- -- |VERIFICO POSIZIONE RULLI| -- ------------------------------------------ -- eseguo eventuale posizionamento sicuro di teste e rulli if WorkTab.bCloseV then EnsureZmax( true, vCmd) MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1 + AggLoad, MinY1) MaxY2V2 = MaxY2 end -- ----------------------------------------- -- |RICONOSCO I CASI| -- ------------------------------------------ -- definisco la tabella delle posizioni iniziali TabValI = {dY1PosI=dY1PosI, dY2PosI=dY2PosI, dTPosI=WorkTab.dTPosI, MyMinY1V1=MyMinY1V1, MaxY2V2=MaxY2V2, dY1DeltaMaxF=WorkTab.dY1DeltaMaxF, dY1DeltaMinF=WorkTab.dY1DeltaMinF, dY2DeltaMaxF=WorkTab.dY2DeltaMaxF, dY2DeltaMinF=WorkTab.dY2DeltaMinF } -- [B2-Y1A] **ALLONTANAMENTO** del trascinatore **Y1** e (eventuale) posizionamento di Y2 if WorkTab.dY1DeltaI < dY1NewDelta then EmitComment( vCmd, '[B2-Y1A]') dY1DeltaF, dY2DeltaF = PosY1Y2A( TabValI, vCmd) else -- [B2-Y1B] **ACCENTRAMENTO** del trascinatore **Y1** e (eventuale) posizionamento di Y2 EmitComment( vCmd, '[B2-Y1B]') dY1DeltaF, dY2DeltaF = PosY1Y2B( TabValI, vCmd) end -- ----------------------------------------- -- |CHIUSURA MORSE| -- ------------------------------------------ if not SpecTestSomeMoveInCmds( vCmd) then table.insert( vCmd, { 3, 'Y1', dY1PosI, 'Y2', dY2PosI, 'T', WorkTab.dTPosI, EMC.CNT}) end table.insert( vCmd, { 12, 1}) -- Chiudo Y2 table.insert( vCmd, { 11, 1}) -- chiudo Y1 -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, dY1DeltaF, dY2DeltaF}) EgtOutLog( ' Y1DeltaF=' .. EgtNumToString( dY1DeltaF) .. ' Y2DeltaF=' .. EgtNumToString( dY2DeltaF), 1) -- segnalo la posizione dei rulli table.insert( vCmd, { 22, WorkTab.dV1PosF, WorkTab.dV2PosF}) SpecOutputCNT() return vCmd end -- SpecAdjustCarrB2 --------------------------------------------------------------------- -- **[C] ex[C1]/[C2] Posizionamento trascinatore Y2 da (Y1 o Y2) <=> Y1/Y2 -> Y2** --------------------------------------------------------------------- function SpecAdjustCarrC( WorkTab) -- Elenco comandi local vCmd = {} table.insert( vCmd, { 0, 'Y1/Y2 -> Y2'}) EmitComment( vCmd, '*[C]') local MinY1V1 = max( WorkTab.dV1PosI + AGG_V, MinY1) local MaxY2V2 = min( WorkTab.dV2PosI - AGG_V, MaxY2) local MyTCING = EgtIf( SPLIT, EMC.TCING, 0) -- se primo scambio local MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1V1 + AggLoad, MinY1V1) -- recupero le posizioni correnti local dY1PosI = WorkTab.dTPosI + WorkTab.dY1DeltaI local dY2PosI = WorkTab.dTPosI + WorkTab.dY2DeltaI local dY2DeltaF -- EgtOutLog( ' Y1DeltaI=' .. EgtNumToString( WorkTab.dY1DeltaI) .. ' Y2DeltaI=' .. EgtNumToString( WorkTab.dY2DeltaI), 1) EgtOutLog( ' Y2DeltaMinF=' .. EgtNumToString( WorkTab.dY2DeltaMinF)..' Y2DeltaMaxF=' .. EgtNumToString( WorkTab.dY2DeltaMaxF), 1) -- [C(1)] - Se il trascinatore Y2 non è nell'intervallo valido, devo posizionarlo if WorkTab.dY2DeltaI < WorkTab.dY2DeltaMinF - GEO.EPS_SMALL or WorkTab.dY2DeltaI > WorkTab.dY2DeltaMaxF + GEO.EPS_SMALL then EmitComment( vCmd, '*[C(1)]') -- ----------------------------------------- -- |VERIFICO POSIZIONE RULLI| -- ------------------------------------------ -- eseguo eventuale posizionamento sicuro di teste e rulli if WorkTab.bCloseV then EnsureZmax( true, vCmd) MyMinY1V1 = EgtIf( EMC.CNT == 1, MinY1 + AggLoad, MinY1) MaxY2V2 = MaxY2 end -- ------------------------------------------ -- |DEFINISCO INTERVALLO 1| -- ------------------------------------------ WorkTab.dY1DeltaMaxF = WorkTab.dY2DeltaMinF + (MaxY1 - MinY2) + (WorkTab.dY2DeltaMaxF - WorkTab.dY2DeltaMinF) WorkTab.dY1DeltaMinF = WorkTab.dY2DeltaMaxF + (MyMinY1V1 - MaxY2V2) - (WorkTab.dY2DeltaMaxF - WorkTab.dY2DeltaMinF) -- se Y1 deve allontanarsi assegno il primo punto valido (altrimenti lascio l'intervallo) if WorkTab.dY1DeltaI < WorkTab.dY1DeltaMinF then WorkTab.dY1DeltaMaxF = min( WorkTab.dY1DeltaMinF + (WorkTab.dY2DeltaMaxF - WorkTab.dY2DeltaMinF), EMC.LB - MinJoin - MyTCING) end -- se la trave è più 'corta' dell'intervallo per Y1 aggiorno l'intervallo (potrei essere comunque in un punto valido) if WorkTab.dY1DeltaMaxF > EMC.LB - ( MinJoin + MyTCING) then WorkTab.dY1DeltaMaxF = EMC.LB - ( MinJoin + MyTCING) -- se Y1 deve accentrarsi if WorkTab.dY1DeltaI > WorkTab.dY1DeltaMaxF then WorkTab.dY1DeltaMinF = EMC.LB - 2 * MinJoin - MyTCING end end -- posizioni obiettivo dei carrelli al centro dei rispettivi intervalli di validità local dY1NewDelta = ( WorkTab.dY1DeltaMinF + WorkTab.dY1DeltaMaxF) / 2 local dY2NewDelta = ( WorkTab.dY2DeltaMinF + WorkTab.dY2DeltaMaxF) / 2 -- ------------------------------------------ -- |RICONOSCO I CASI| -- ------------------------------------------ TabValI = {dY1PosI=dY1PosI, dY2PosI=dY2PosI, dTPosI=WorkTab.dTPosI, MyMinY1V1=MyMinY1V1, MaxY2V2=MaxY2V2, dY1DeltaMaxF=WorkTab.dY1DeltaMaxF, dY1DeltaMinF=WorkTab.dY1DeltaMinF, dY2DeltaMaxF=WorkTab.dY2DeltaMaxF, dY2DeltaMinF=WorkTab.dY2DeltaMinF} if WorkTab.dY2DeltaI < dY2NewDelta then -- [C-Y2B] **ACCENTRAMENTO** (dall'origine) del trascinatore Y2 EmitComment( vCmd, '[C-Y2B]') _, dY2DeltaF = PosY2Y1B( TabValI, vCmd) else -- [C-Y2A] **ALLONTANAMENTO** (dall'origine) del trascinatore Y2 EmitComment( vCmd, '[C-Y2A]') _, dY2DeltaF = PosY2Y1A( TabValI, vCmd) end -- chiudo Y2 table.insert( vCmd, { 12, 1}) -- dichiaro Y1 da parcheggiare WorkTab.bY1Parked = false -- [C(0)] - Se Y2 è già nell'intervallo valido, si lascia dove è else EmitComment( vCmd, '*[C(0)]') if not WorkTab.bY1Parked then -- dichiaro posizione di Y1 e T table.insert( vCmd, { 2, 'T', WorkTab.dTPosI, 'Y1', dY1PosI, EMC.CNT}) end if WorkTab.bY2Parked then -- chiudo Y2 table.insert( vCmd, { 12, 1}) end dY2DeltaF = WorkTab.dY2DeltaI end if not WorkTab.bY1Parked then -- apro e parcheggio Y1 table.insert( vCmd, { 11, 0}) EMC.CNT = nil table.insert( vCmd, { 1, 'Y1', ParkY1}) end -- aggiorno e segnalo la posizione finale Y2Delta table.insert( vCmd, { 21, 0, dY2DeltaF}) EgtOutLog( ' Y2DeltaF=' .. EgtNumToString( dY2DeltaF), 1) -- segnalo la posizione dei rulli table.insert( vCmd, { 22, WorkTab.dV1PosF, WorkTab.dV2PosF}) SpecOutputCNT() return vCmd end -- SpecAdjustCarrC2 --------------------------------------------------------------------- function SpecOutputCNT() if EMC.CNT == 1 then EgtSetInfo( EMC.PATHID, 'CNT', 1) else EgtRemoveInfo( EMC.PATHID, 'CNT') end end --------------------------------------------------------------------- function SpecGetCNT( CurrOpeId) while CurrOpeId do local nPrevOpeId = EgtGetPrevActiveOperation( CurrOpeId) if not nPrevOpeId then return nil end local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL) if nLastPathId then return EgtGetInfo( nLastPathId, 'CNT', 'i') end CurrOpeId = nPrevOpeId end return nil end --------------------------------------------------------------------- function SpecOutputCmds( vCmd, bEnd) local sRoot = EgtIf( not bEnd, 'AS', 'AE') -- Registro il numero di comandi if vCmd and #vCmd > 0 then EgtSetInfo( EMC.PATHID, sRoot..'#', #vCmd) else EgtRemoveInfo( EMC.PATHID, sRoot..'#') end -- Registro i comandi for i = 1, #(vCmd or {}) do local Cmd = vCmd[i] local sKey = sRoot .. tostring( i) -- commento if Cmd[1] == 0 then local sInfo = '0,'..Cmd[2] EgtSetInfo( EMC.PATHID, sKey, sInfo) -- movimento di 1 asse elseif Cmd[1] == 1 then local sInfo = '1,'..Cmd[2]..','..EgtNumToString( Cmd[3],3)..EgtIf( Cmd[4], ','..tostring(Cmd[4]), '') EgtSetInfo( EMC.PATHID, sKey, sInfo) -- movimento di 2 assi elseif Cmd[1] == 2 then local sInfo = '2,'..Cmd[2]..','..EgtNumToString( Cmd[3],3)..','..Cmd[4]..','..EgtNumToString( Cmd[5],3)..EgtIf( Cmd[6], ','..tostring(Cmd[6]), '') EgtSetInfo( EMC.PATHID, sKey, sInfo) -- movimento di 3 assi elseif Cmd[1] == 3 then local sInfo = '3,'..Cmd[2]..','..EgtNumToString( Cmd[3],3)..','..Cmd[4]..','..EgtNumToString( Cmd[5],3)..','.. Cmd[6]..','..EgtNumToString( Cmd[7],3)..EgtIf( Cmd[8], ',*', '') EgtSetInfo( EMC.PATHID, sKey, sInfo) -- posizione sicura per movimento carrelli elseif Cmd[1] == 4 then local sInfo = '4,'..EgtNumToString( Cmd[2],0) EgtSetInfo( EMC.PATHID, sKey, sInfo) -- apertura/chiusura morsa Y elseif Cmd[1] == 11 then local sInfo = '11,'..EgtNumToString( Cmd[2],0) EgtSetInfo( EMC.PATHID, sKey, sInfo) -- apertura/chiusura morsa V elseif Cmd[1] == 12 then local sInfo = '12,'..EgtNumToString( Cmd[2],0) EgtSetInfo( EMC.PATHID, sKey, sInfo) -- impostazione nuovo stato dei carrelli elseif Cmd[1] == 21 then local sInfo = '21,'..EgtNumToString( Cmd[2],3)..','..EgtNumToString( Cmd[3],3) EgtSetInfo( EMC.PATHID, sKey, sInfo) if Cmd[2] > 0 and Cmd[3] > 0 then EMC.Y1DELTA = Cmd[2] EMC.Y2DELTA = Cmd[3] elseif Cmd[2] > 0 then EMC.Y1DELTA = Cmd[2] EMC.Y2DELTA = nil elseif Cmd[3] > 0 then EMC.Y1DELTA = nil EMC.Y2DELTA = Cmd[3] end -- impostazione nuova posizione dei rulli elseif Cmd[1] == 22 then local sInfo = '22,'..EgtNumToString( Cmd[2],3)..','..EgtNumToString( Cmd[3],3) EgtSetInfo( EMC.PATHID, sKey, sInfo) EMC.V1POS = Cmd[2] EMC.V2POS = Cmd[3] -- aggancio grezzo a carrello elseif Cmd[1] == 31 then local sInfo = '31,'..EgtNumToString( Cmd[2],0)..','..Cmd[3] EgtSetInfo( EMC.PATHID, sKey, sInfo) -- segnalazione errore elseif Cmd[1] == 99 then local sInfo = '99,' .. Cmd[2] .. ',' .. Cmd[3] EgtSetInfo( EMC.PATHID, sKey, sInfo) end end -- Salvo i nuovi delta dei carrelli if EMC.Y1DELTA then EgtSetInfo( EMC.PATHID, 'Y1DELTA', EMC.Y1DELTA) else EgtRemoveInfo( EMC.PATHID, 'Y1DELTA') end if EMC.Y2DELTA then EgtSetInfo( EMC.PATHID, 'Y2DELTA', EMC.Y2DELTA) else EgtRemoveInfo( EMC.PATHID, 'Y2DELTA') end --Salvo le nuove posizioni dei rulli EgtSetInfo( EMC.PATHID, 'V1POS', EMC.V1POS) EgtSetInfo( EMC.PATHID, 'V2POS', EMC.V2POS) -- Se comandi finali if bEnd then -- Se operazione successiva è disposizione, salvo anche lì le posizioni dei rulli local NextDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) if NextDispId and NextDispId == EgtGetNextActiveOperation( EMC.DISPID or EMC.MCHID) then EgtSetInfo( NextDispId, 'V1POS', EMC.V1POS) EgtSetInfo( NextDispId, 'V2POS', EMC.V2POS) end end end --------------------------------------------------------------------- function SpecSetCarrPosFromCmds( vCmd) -- recupero nuova posizione carrelli for i = 1, #(vCmd or {}) do local Cmd = vCmd[i] if Cmd[1] == 21 then if Cmd[2] > 0 and Cmd[3] > 0 then EMC.Y1DELTA = Cmd[2] EMC.Y2DELTA = Cmd[3] elseif Cmd[2] > 0 then EMC.Y1DELTA = Cmd[2] EMC.Y2DELTA = nil elseif Cmd[3] > 0 then EMC.Y1DELTA = nil EMC.Y2DELTA = Cmd[3] end elseif Cmd[1] == 22 then EMC.V1POS = Cmd[2] EMC.V2POS = Cmd[3] end end end --------------------------------------------------------------------- function SpecTestOnlyRemarkInCmds( vCmd) if not vCmd then return true end -- verifico se nella lista dei comandi ci sono solo commenti for i = 1, #vCmd do if vCmd[i][1] ~= 0 then return false end end return true end --------------------------------------------------------------------- function SpecTestSomeMoveInCmds( vCmd) if not vCmd then return false end -- verifico se nella lista dei comandi c'è almeno un movimento for i = 1, #vCmd do if vCmd[i][1] == 1 or vCmd[i][1] == 2 or vCmd[i][1] == 3 then return true end end return false end