RI Lezione 15
🤖 Robotica Industriale · V Anno · Lezione 15
Registri di posizione PR[ ] e offset 📍
PR[ ] come variabili di posizione · Offset Condition · Deposito su griglia dinamica · LPOS / JPOS
📍 Il robot smette di essere rigido. Finora ogni posizione era fissa: insegnata una volta, uguale per sempre. Con i registri di posizione PR[ ] e la tecnica dell’offset il TCP può spostarsi dinamicamente — calcolato a runtime in base a registri R[ ]. Una griglia 4×6 diventa raggiungibile con un solo punto insegnato e un loop. È la tecnica che abilita palletizzazione, pick-from-feeder, deposito matriciale.
🎯 Obiettivi della lezione
- Capire la struttura di un PR[ ] e come si differenzia da un P[ ]
- Assegnare e modificare singoli componenti di un PR[ ] dal codice TP
- Usare PR[ ] come offset con la sintassi
L P[n] … OFFSET, PR[m] - Costruire il pattern deposito su griglia con loop annidato + offset calcolato
- Leggere la posizione corrente del robot in PR[ ] con LPOS e JPOS
📖 1. Teoria
1.1 — Struttura di un PR[ ]
Un registro di posizione PR[ ] è una variabile che contiene una posizione completa nello stesso formato di P[ ]: sei componenti (X, Y, Z, W, P, R) più il frame di riferimento. Sono disponibili PR[1]…PR[100]. La differenza cruciale rispetto a P[ ] è che PR[ ] può essere scritto e modificato dal codice TP a runtime — le sue componenti si assegnano come variabili.
| Caratteristica | P[ ] — Registro posizione | PR[ ] — Registro posizione variabile |
|---|---|---|
| Come si scrive | Solo via teach (jog + RECORD) | Teach oppure assegnazione TP a runtime |
| Modificabilità | Solo offline, non dal codice | Ogni componente modificabile dal codice |
| Uso tipico | Posizioni fisse della cella | Offset, posizioni calcolate, posizione corrente |
| Range | P[1]…P[999] | PR[1]…PR[100] |
| Persistenza | Conservato dopo spegnimento | Conservato dopo spegnimento |
Ogni componente di un PR[ ] è accessibile con la notazione a punto: PR[n, k] dove k è il numero del componente:
PR[1, 2] = valore ! componente Y (mm)
PR[1, 3] = valore ! componente Z (mm)
PR[1, 4] = valore ! componente W (gradi — Yaw)
PR[1, 5] = valore ! componente P (gradi — Pitch)
PR[1, 6] = valore ! componente R (gradi — Roll)
📌 Convenzione indici PR[ ]: PR[1]–PR[10] per offset di processo · PR[11]–PR[20] per posizioni calcolate · PR[91]–PR[99] per posizione corrente (LPOS/JPOS). Non sovrascrivere PR[ ] in uso: se PR[1] è l’offset colonna, non usarlo anche come buffer temporaneo in un altro punto del programma.
1.2 — Azzeramento di un PR[ ]
Prima di usare un PR[ ] come offset è fondamentale azzerare tutti i componenti non usati. Se PR[1] ha residui da un’esecuzione precedente nelle componenti W, P, R, l’offset ruoterà l’orientamento del TCP oltre a spostarlo — quasi certamente indesiderato.
PR[1, 1]=0 ! X = 0
PR[1, 2]=0 ! Y = 0
PR[1, 3]=0 ! Z = 0
PR[1, 4]=0 ! W = 0 (nessuna rotazione)
PR[1, 5]=0 ! P = 0
PR[1, 6]=0 ! R = 0
Poi si assegnano solo i componenti che devono avere un valore diverso da zero:
PR[1, 1]=R[37] ! offset X = valore calcolato in R[37]
PR[1, 2]=R[36] ! offset Y = valore calcolato in R[36]
! PR[1,3..6] già azzerati — nessun offset in Z né in orientamento
1.3 — Sintassi OFFSET nel movimento
La parola chiave OFFSET, PR[n] aggiunge alla fine dell’istruzione di movimento: il TCP si sposta nella posizione P[ ] più l’offset contenuto in PR[n]. La posizione base P[ ] non viene modificata — l’offset è applicato solo per quella singola esecuzione dell’istruzione.
Punto base della griglia — non cambia mai
Calcolato a runtime dal loop
| Istruzione | Comportamento |
|---|---|
| L P[21] 150mm/sec FINE OFFSET, PR[1] | Movimento lineare a P[21]+PR[1] — traiettoria rettilinea con offset |
| J P[21] 80% FINE OFFSET, PR[1] | Movimento articolare a P[21]+PR[1] — percorso curvo, più veloce |
| L P[20] 200mm/sec CNT50 OFFSET, PR[1] | Approccio con offset e continuazione — usato per il transito verso il punto di lavoro |
1.4 — Pattern completo: deposito su griglia con OFFSET
Questo è il pattern più usato nelle applicazioni industriali con PR[ ]: un punto di riferimento insegnato (angolo della griglia) e un loop che calcola l’offset per ogni cella e lo applica al movimento. Una griglia N×M richiede solo 2 punti insegnati (riferimento + approccio) invece di 2×N×M punti.
! DEPOSITO SU GRIGLIA 3×4 con OFFSET
! P[60] = punto riferimento cella (0,0) della griglia
! P[59] = approccio riferimento (P[60] con Z+150)
! PR[1] = offset corrente (aggiornato ogni cella)
! ============================================================
! — Init parametri griglia —
1: R[30:RIGA ]=0
2: R[31:COL ]=0
3: R[32:N_RIG]=3 ! 3 righe
4: R[33:N_COL]=4 ! 4 colonne
5: R[34:P_RIG]=50 ! passo riga (mm in Y)
6: R[35:P_COL]=60 ! passo colonna (mm in X)
! — Azzeramento PR[1] —
7: PR[1,1]=0
8: PR[1,2]=0
9: PR[1,3]=0
10: PR[1,4]=0
11: PR[1,5]=0
12: PR[1,6]=0
! — Loop esterno: righe —
13: LBL[2]
14: R[31]=0 ! reset colonna
! — Loop interno: colonne —
15: LBL[3]
! Calcola offset cella corrente
16: PR[1,1]=R[31]*R[35] ! offset X = col × passo_col
17: PR[1,2]=R[30]*R[34] ! offset Y = riga × passo_riga
! — PRESA (dal nastro — senza offset) —
18: J P[10:APPR_PICK] 80% CNT100
19: L P[11:PICK ] 150mm/sec FINE
20: DO[1]=ON
21: WAIT DI[1]=ON TIMEOUT, LBL[99]
22: L P[10:APPR_PICK] 150mm/sec FINE
! — DEPOSITO CON OFFSET —
23: J P[59:APPR_REF ] 80% CNT100 OFFSET, PR[1]
24: L P[60:PLACE_REF] 150mm/sec FINE OFFSET, PR[1]
25: DO[1]=OFF
26: WAIT DI[1]=OFF TIMEOUT, LBL[98]
27: L P[59:APPR_REF ] 150mm/sec FINE OFFSET, PR[1]
! Avanza colonna
28: R[31]=R[31]+1
29: IF R[31]<R[33], JMP LBL[3]
! Avanza riga
30: R[30]=R[30]+1
31: IF R[30]<R[32], JMP LBL[2]
! Griglia completata (12 celle)
32: J P[1:HOME] 100% FINE
33: DO[4]=ON ! vassoio pieno
✅ Nota sulla risalita con OFFSET (riga 27): la risalita usa lo stesso PR[1] del deposito — quindi il robot sale verticalmente sopra la cella appena riempita, non sopra il punto di riferimento. Questo è esattamente il comportamento voluto: approccio verticale sopra ogni cella individuale, non diagonale rispetto al riferimento.
1.5 — LPOS e JPOS: leggere la posizione corrente
LPOS (Linear POSition) e JPOS (Joint POSition) sono istruzioni che scrivono la posizione TCP corrente del robot in un PR[ ]. LPOS scrive le coordinate cartesiane X/Y/Z/W/P/R; JPOS scrive i valori degli assi J1…J6.
PR[91]=JPOS ! leggi posizione assi corrente → PR[91]
Usi tipici di LPOS:
| Uso | Esempio |
|---|---|
| Salva posizione attuale come riferimento dinamico | PR[90]=LPOS poi usa PR[90] come base per offset successivi |
| Verifica che il robot sia in home prima di avviare | PR[90]=LPOS · IF PR[90,3]<200, JMP LBL[99] (Z troppo basso) |
| Debug: leggi posizione dopo un movimento sospetto | PR[99]=LPOS — poi leggi PR[99] dal pannello DATA |
💻 2. Esempi guidati nel simulatore
Esempio A — Offset semplice: stesso punto, tre altezze diverse
- Insegna P[60] in una posizione qualsiasi (es. X=200, Y=0, Z=100).
- Azzeramento PR[1]: scrivi le 6 righe
PR[1,k]=0. - Scrivi il programma:
! visita P[60] a 3 altezze diverse con OFFSET su Z
1: PR[1,1]=0 · PR[1,2]=0 · PR[1,3]=0
2: PR[1,4]=0 · PR[1,5]=0 · PR[1,6]=0
3: J P[1:HOME] 100% FINE
4: PR[1,3]=50
5: L P[60] 150mm/sec FINE OFFSET, PR[1]
! TCP va a Z=150 (100+50)
6: PR[1,3]=0
7: L P[60] 150mm/sec FINE OFFSET, PR[1]
! TCP va a Z=100 (posizione base)
8: PR[1,3]=-50
9: L P[60] 150mm/sec FINE OFFSET, PR[1]
! TCP va a Z=50 (100-50)
10: J P[1:HOME] 100% FINE - Esegui con STEP. Dopo ogni movimento apri il pannello DATA → Position Registers e verifica il valore di PR[1,3] e la posizione TCP corrente. Usa LPOS per confermare.
- Verifica: il robot tocca esattamente Z=150, Z=100, Z=50 nelle tre soste.
Esempio B — Fila lineare: 5 posizioni in X con offset
- Insegna P[60] a X=100, Y=0, Z=80 (prima posizione della fila).
- Scrivi il programma:
1: PR[1,1]=0 · PR[1,2]=0 · PR[1,3]=0
2: PR[1,4]=0 · PR[1,5]=0 · PR[1,6]=0
3: R[31]=0
4: R[35]=50
5: J P[1:HOME] 100% FINE
6: LBL[3]
7: PR[1,1]=R[31]*R[35]
! offset X = indice × passo
8: L P[60] 150mm/sec FINE OFFSET, PR[1]
9: WAIT 0.30(sec)
10: R[31]=R[31]+1
11: IF R[31]<5, JMP LBL[3]
12: J P[1:HOME] 100% FINE - Esegui. Il robot visita 5 posizioni a X=100, 150, 200, 250, 300 (passo 50 mm).
- Modifica R[35]=30 prima di eseguire: passo diventa 30 mm, posizioni a X=100, 130, 160, 190, 220.
- Aggiungi una riga
PR[99]=LPOSdopo il WAIT e verifica che PR[99,1] corrisponda al valore atteso di X.
Esempio C — Griglia 2×3 completa con approccio/lavoro
- Insegna P[59] (approccio riferimento, Z+120 rispetto a P[60]) e P[60] (lavoro riferimento).
- Implementa il loop annidato della sezione 1.4 ridotto a griglia 2×3 (passo X=60, passo Y=50). Sostituisci la presa con
WAIT 0.20(sec). - Esegui con STEP le prime 3 celle (prima riga). Per ogni cella verifica nel pannello DATA:
- R[30] e R[31] (indici riga e colonna correnti)
- PR[1,1] e PR[1,2] (offset X e Y calcolati)
- PR[99,1] e PR[99,2] (posizione effettiva TCP via LPOS — aggiungi
PR[99]=LPOSdopo il deposito)
- Verifica che posizione effettiva = posizione riferimento + offset calcolato.
- Esegui a velocità normale (RUN): le 6 celle devono essere visitate in ordine riga per riga.
🏋️ 3. Esercizi
🟢 Esercizio 1 — Calcolo manuale offset griglia (Facile)
Una griglia ha punto di riferimento a X=150, Y=50, Z=80. Passo colonne=45 mm in X, passo righe=40 mm in Y. Calcola i valori di PR[1,1] e PR[1,2] (offset X e Y) per ciascuna delle 6 celle di una griglia 2×3, e le coordinate assolute X,Y risultanti:
Cella (R=0,C=1): PR[1,1]=?, PR[1,2]=?, X_TCP=?, Y_TCP=?
Cella (R=0,C=2): PR[1,1]=?, PR[1,2]=?, X_TCP=?, Y_TCP=?
Cella (R=1,C=0): PR[1,1]=?, PR[1,2]=?, X_TCP=?, Y_TCP=?
Cella (R=1,C=1): PR[1,1]=?, PR[1,2]=?, X_TCP=?, Y_TCP=?
Cella (R=1,C=2): PR[1,1]=?, PR[1,2]=?, X_TCP=?, Y_TCP=?
Verifica i calcoli nel simulatore usando PR[99]=LPOS dopo ogni deposito e confrontando PR[99,1] e PR[99,2] con i valori attesi.
🔵 Esercizio 2 — Integra griglia nel PICK_SORT_3 (Medio)
Modifica il programma PICK_SORT_3 della Lezione 14 in modo che la zona A non abbia un unico punto di deposito P[21], ma una griglia 2×3 (6 celle). I parametri: passo X=60 mm, passo Y=50 mm, punto riferimento P[21] è la cella (0,0).
Aggiungi R[20:COL_A] e R[21:RIG_A] come indici della cella corrente nella zona A. Ogni volta che un pezzo di tipo 1 viene depositato in zona A, avanza alla cella successiva (colonna per colonna, poi riga). Quando la griglia è piena (R[2]=6), accendi DO[7]=ON (zona A satura) e reindirizza i pezzi di tipo 1 agli scarti finché DO[7] non viene spento (reset esterno).
Implementa solo la zona A — le zone B e C rimangono a punto singolo.
🟠 Esercizio 3 — Palletizzazione a strati (Medio)
Un pallet riceve scatole su 2 strati sovrapposti, ciascuno con griglia 3×4 (12 scatole per strato, 24 totali). Ogni scatola è alta 80 mm. Il punto di riferimento P[70] è la cella (strato=0, riga=0, col=0) del pallet.
Scrivi il programma con loop a tre livelli annidati (strato → riga → colonna) che calcola PR[2] per ogni scatola:
PR[2,1]=col×60 (offset X), PR[2,2]=riga×50 (offset Y), PR[2,3]=strato×80 (offset Z).
L’approccio deve tenere conto dello strato: Z approccio = Z riferimento + strato×80 + 120 mm di clearance. Implementa la logica con R[38]=strato (0..1), R[30]=riga (0..2), R[31]=colonna (0..3). Verifica nel simulatore che le 24 posizioni siano corrette usando LPOS.
🟣 Esercizio 4 — Ripresa da interruzione a metà griglia (Difficile)
Il programma di deposito su griglia 3×4 viene interrotto (allarme o stop operatore) dopo aver riempito le prime 7 celle. Al riavvio, il robot deve riprendere dalla cella 8 — non ricominciare dalla cella 0.
Implementa la logica di ripresa: R[1:CONT_TOT] conta i pezzi depositati (persistente tra spegnimento e accensione). All’avvio il programma verifica se R[1]>0 e in tal caso calcola gli indici di riga e colonna di ripresa usando DIV e MOD: R[30]=R[1] DIV R[33], R[31]=R[1] MOD R[33]. Se R[1]=0 (prima accensione) ricomincia dalla cella (0,0).
Verifica: esegui 7 cicli, interrompi, riavvia — il robot deve partire dalla cella 8 con i registri di indice corretti. Verifica anche il caso R[1]=12 (griglia già piena): il programma deve rilevarlo e accendere DO[4] senza eseguire nessun deposito.
❓ 4. Quiz di verifica
1. Perché è necessario azzerare tutti i 6 componenti di PR[1] prima di usarlo come offset, anche se si modificano solo PR[1,1] e PR[1,2]?
Mostra risposta
Perché PR[ ] è persistente: conserva i valori dell’esecuzione precedente dopo lo spegnimento del controller. Se nell’esecuzione precedente PR[1,3] era stato impostato a –30 (offset Z di –30 mm) e ora si vuole usare PR[1] solo come offset X/Y, dimenticare di azzerare PR[1,3] aggiungerà –30 mm in Z a ogni movimento con OFFSET, PR[1]. Il robot scenderebbe 30 mm più in basso del previsto ad ogni cella — potenzialmente collidendo con i pezzi già depositati o con la struttura del vassoio. L’azzeramento completo garantisce uno stato noto prima di impostare i soli componenti necessari.
2. In un movimento L P[60] 150mm/sec FINE OFFSET, PR[1], P[60] viene modificato permanentemente dall’offset?
Mostra risposta
No. L’offset viene applicato solo per quella singola esecuzione dell’istruzione — P[60] rimane invariato nella memoria del controller. Il TCP si sposta fisicamente a P[60]+PR[1], ma il valore registrato di P[60] è immutato. Questo è il vantaggio fondamentale di OFFSET rispetto a modificare direttamente P[60]: si può usare lo stesso punto base per tutte le celle della griglia e cambiare solo PR[1] a ogni iterazione, senza mai riscrivere P[60]. Se si modificasse P[60] a ogni cella, si perderebbe il punto di riferimento originale.
3. Perché nella riga 27 del programma griglia (L P[59:APPR_REF] … OFFSET, PR[1]) si usa lo stesso PR[1] del deposito e non PR[1] azzerato?
Mostra risposta
Perché P[59] (approccio riferimento) ha la stessa X,Y di P[60] ma con Z+150. Applicando lo stesso offset PR[1] anche alla risalita, il robot sale verticalmente sopra la cella appena depositata — cioè a X=P[60].X+PR[1,1], Y=P[60].Y+PR[1,2], Z=P[60].Z+150. Se si usasse PR[1] azzerato per la risalita, il robot tornerebbe all’approccio della cella (0,0) invece di salire sopra la cella corrente — traiettoria diagonale che traverserebbe i pezzi già depositati nelle celle precedenti. L’offset coerente approccio/lavoro/risalita garantisce la simmetria verticale che abbiamo imparato nella Lezione 07.
4. Qual è la differenza tra LPOS e JPOS, e quando si usa ciascuno?
Mostra risposta
LPOS (Linear POSition) scrive la posizione TCP nelle coordinate cartesiane del frame attivo: X, Y, Z in mm e W, P, R in gradi. JPOS (Joint POSition) scrive gli angoli attuali degli assi J1…J6 in gradi. Si usa LPOS quando si vuole lavorare con coordinate spaziali del TCP — verificare posizione, calcolare offset cartesiani, debug. Si usa JPOS quando si vuole salvare una configurazione degli assi indipendente dal TCP — ad esempio per memorizzare la posizione di home in termini di assi e verificare che il robot sia esattamente in quella configurazione prima di avviare un ciclo. JPOS è più affidabile di LPOS per le verifiche di home perché elimina l’ambiguità delle soluzioni cinematiche multiple a parità di posizione TCP.
5. Una griglia 4×5 richiede quanti punti P[ ] insegnati con il metodo OFFSET rispetto al metodo tradizionale (un punto per cella)?
Mostra risposta
Metodo tradizionale: 4×5=20 punti di lavoro + 20 punti di approccio = 40 punti P[ ] da insegnare, verificare e mantenere. Con il metodo OFFSET: 1 punto di riferimento (P[60]) + 1 approccio di riferimento (P[59]) = 2 punti P[ ] totali, più i parametri griglia in R[ ] (passi e dimensioni). Risparmio: 38 punti. Vantaggi aggiuntivi: se il vassoio si sposta di 10 mm, con il metodo tradizionale bisogna correggere 40 punti; con OFFSET si corregge solo P[60] e tutti i 20 depositi si aggiornano automaticamente. Se si cambia il passo (es. da 60 mm a 70 mm), con OFFSET basta modificare R[35] — con il metodo tradizionale bisogna spostare fisicamente 20 punti uno per uno.
📚 Riepilogo della lezione
PR[n,k]— registro di posizione variabile, componente k (1=X … 6=R), modificabile dal codice TP- Azzerare tutti i 6 componenti prima dell’uso come offset — la persistenza può introdurre residui inattesi
OFFSET, PR[n]nella riga di movimento — applica l’offset solo per quella esecuzione, P[ ] rimane invariato- Risalita con stesso PR[n] del deposito — simmetria verticale sopra ogni cella, non diagonale verso il riferimento
- Pattern griglia: 2 punti insegnati + parametri R[ ] + loop annidato = N×M celle senza insegnare ogni punto
PR[n]=LPOS/PR[n]=JPOS— legge la posizione corrente del robot per verifica e debug
Prossima lezione →
Lezione 16 — Ottimizzazione delle traiettorie
CNT vs FINE · Velocità ottimale per tipo di movimento · Profili di accelerazione.
Ridurre i tempi ciclo senza sacrificare sicurezza e precisione.
© Prof. D. Bertolino · Robotica Industriale FANUC ER-4iA · Lezione 15 di 18