Files
essetre-pf1500maxrl-3t/Common_PF1250.mlse
T
andrea.villa 54f453c079 Prima versione configurazione macchina.
Derivazione da PF1250MAX, PF12503T, PF1500rl
2024-10-16 11:40:30 +02:00

2558 lines
106 KiB
Plaintext

-- Special Operations macchina Essetre-PF1250 by Egalware s.r.l. 2024/04/09
-- Intestazioni
require( 'EmtGenerator')
EgtEnableDebug( false)
-- Carico libreria
local BD = require( 'BeamData')
---------------------------------------------------------------------
-- *** 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
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
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=70}, { 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
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=70}, { 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
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
else
-- 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
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 = 270 -- 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()
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()
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 -- 'H31'
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)
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 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 = {}
-- Commento
table.insert( vCmd, { 0, '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
-- Sposto il pezzo in posizione di scarico
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)
-- 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 <end>
-- 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 <end>
-- 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], ',*', '')
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], ',*', '')
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