RI Lezione 18
🤖 Robotica Industriale · V Anno · Lezione 18 — Progetto Finale
Cella Robotizzata Completa 🏆
Integrazione di tutto il percorso · Architettura modulare · Griglia con offset · Ottimizzazione traiettorie · Collaudo formale
🏆 Questo è il progetto finale del percorso triennale. Non ci sono nuove istruzioni da imparare — si tratta di integrare tutto: cinematica, sistemi di riferimento, movimenti J/L, I/O, registri, strutture di controllo, loop, offset su griglia, ottimizzazione traiettorie e architettura modulare. La cella progettata in questa lezione è un impianto industriale realistico che potrebbe girare sul robot fisico in laboratorio.
🎯 Obiettivi del progetto finale
- Leggere e interpretare le specifiche di una cella industriale complessa
- Progettare l’architettura modulare completa prima di scrivere una riga di codice
- Implementare tutti i sotto-programmi con interfacce documentate
- Applicare la metodologia di ottimizzazione traiettorie (CNT, velocità, ACC)
- Eseguire il collaudo formale a 5 fasi e documentarne i risultati
- Discutere le scelte progettuali in un colloquio tecnico simulato
📐 1. Specifiche della cella: “CELL_FINAL”
1.1 — Descrizione impianto
La cella gestisce il fine-linea di un processo di assemblaggio. Un nastro trasportatore porta pezzi già assemblati in uscita dalla linea. Un sistema di visione (già integrato, scrive R[5]) classifica ogni pezzo come conforme tipo 1, conforme tipo 2 o non conforme. Il robot FANUC ER-4iA deve prelevare ogni pezzo, depositare i conformi su due vassoi (tipo 1 → vassoio A 3×3, tipo 2 → vassoio B 3×3) e inviare i non conformi al bin di scarto. Quando un vassoio è pieno (9 pezzi), il robot lo segnala al PLC e attende il cambio vassoio prima di continuare.
1.2 — Layout e coordinate TCP
| Zona | TCP riferimento (0,0) | Griglia | Passo X | Passo Y | Config |
|---|---|---|---|---|---|
| Nastro presa | X=320, Y=0, Z=55 | — | — | — | NUT,0,0,0 |
| Vassoio A (tipo 1) | X=–180, Y=160, Z=45 | 3×3 | 55 mm | 55 mm | NUT,0,0,0 |
| Vassoio B (tipo 2) | X=180, Y=160, Z=45 | 3×3 | 55 mm | 55 mm | NUT,0,0,0 |
| Bin scarti | X=0, Y=–220, Z=60 | — | — | — | NUT,0,0,0 |
| Home | J1=0°, J2=0°, J3=0°, J4=0°, J5=–90°, J6=0° | Posizione asse — teach e salva | |||
1.3 — Segnali I/O
| DI | Funzione |
|---|---|
| DI[1] | Conferma stato pinza (reed) |
| DI[2] | Pezzo presente sul nastro |
| DI[3] | Start ciclo da PLC |
| DI[4] | Stop ciclo da PLC |
| DI[5] | Vassoio A sostituito (ok per continuare) |
| DI[6] | Vassoio B sostituito |
| DI[7] | Reset allarme generico |
| DO | Funzione |
|---|---|
| DO[1] | Pinza (ON=chiusa) |
| DO[2] | Robot pronto / in attesa start |
| DO[3] | Ciclo attivo |
| DO[4] | Vassoio A pieno — richiesta cambio |
| DO[5] | Vassoio B pieno — richiesta cambio |
| DO[6] | Allarme pinza (timeout) |
| DO[7] | Allarme generico |
1.4 — Registri R[ ] del progetto
| Registro | Nome | Funzione | Init |
|---|---|---|---|
| R[1] | CONT_TOT | Pezzi totali processati | 0 |
| R[2] | CONT_A | Pezzi sul vassoio A (corrente) | 0 |
| R[3] | CONT_B | Pezzi sul vassoio B (corrente) | 0 |
| R[4] | CONT_SC | Scarti totali | 0 |
| R[5] | TIPO_PEZZO | Tipo da sistema visione (1/2/0) | — |
| R[10] | CAP_VASS | Capacità vassoio (fisso: 9) | 9 |
| R[20] | RIG_A | Indice riga vassoio A (0–2) | 0 |
| R[21] | COL_A | Indice colonna vassoio A (0–2) | 0 |
| R[22] | RIG_B | Indice riga vassoio B (0–2) | 0 |
| R[23] | COL_B | Indice colonna vassoio B (0–2) | 0 |
| R[50] | PARAM_DEST | Parametro destinazione per CALL DEPOSITA | — |
| R[56] | FLAG_ERR | Flag errore sotto-programmi (0=ok) | — |
| R[90] | LAST_ERR | Codice ultimo errore (diagnostica) | 0 |
1.5 — Punti P[ ] e PR[ ] da insegnare
| P[ ] | Nome | Descrizione | Come si ottiene |
|---|---|---|---|
| P[1] | HOME | Posizione di home (joint) | Teach diretto |
| P[10] | APPR_PICK | Approccio nastro (Z+130) | Derivato da P[11] |
| P[11] | PICK | Punto presa sul nastro | Teach diretto |
| P[20] | APPR_A0 | Approccio riferimento vassoio A cella(0,0) | Derivato da P[21] |
| P[21] | PLACE_A0 | Riferimento vassoio A cella(0,0) | Teach diretto |
| P[30] | APPR_B0 | Approccio riferimento vassoio B cella(0,0) | Derivato da P[31] |
| P[31] | PLACE_B0 | Riferimento vassoio B cella(0,0) | Teach diretto |
| P[40] | APPR_SC | Approccio bin scarti | Derivato da P[41] |
| P[41] | PLACE_SC | Punto deposito scarti | Teach diretto |
🗂️ 2. Architettura del progetto
OUT: R[56] flag errore
Offset PR + place + risalita
OUT: R[56] flag errore
Spegni tutti DO
Vai in HOME
Accende DO[4]/DO[5], aspetta DI[5]/DI[6]
Azzera contatore e indici griglia
Spegni segnali attivi
Torna a LBL[5] (attesa start)
💾 3. Codice completo
CELL_MAIN
! CELL_MAIN — Orchestrazione cella fine-linea
! ============================================================
1: CALL INIT_CELLA
! — Attesa start —
2: LBL[5]
3: DO[2]=ON
4: WAIT DI[3]=ON
5: DO[2]=OFF · DO[3]=ON
! — Inizio ciclo —
6: LBL[1]
7: IF DI[4]=ON, JMP LBL[9] ! stop richiesto?
! — Presa —
8: WAIT DI[2]=ON ! pezzo presente
9: CALL PRESA
10: IF R[56]=1, JMP LBL[99] ! check errore pinza
! — Routing per tipo —
11: SELECT R[5]=1, JMP LBL[10] ! tipo 1 → vassoio A
=2, JMP LBL[20] ! tipo 2 → vassoio B
ELSE, JMP LBL[30] ! non conforme → scarti
! — Ramo A —
12: LBL[10]
13: R[50]=1
14: CALL DEPOSITA
15: IF R[56]=1, JMP LBL[99]
16: R[2]=R[2]+1
17: IF R[2]>=R[10], CALL CAMBIA_VASSOIO ! vassoio A pieno?
18: JMP LBL[49]
! — Ramo B —
19: LBL[20]
20: R[50]=2
21: CALL DEPOSITA
22: IF R[56]=1, JMP LBL[99]
23: R[3]=R[3]+1
24: IF R[3]>=R[10], CALL CAMBIA_VASSOIO ! vassoio B pieno?
25: JMP LBL[49]
! — Ramo scarti —
26: LBL[30]
27: R[50]=0
28: CALL DEPOSITA
29: IF R[56]=1, JMP LBL[99]
30: R[4]=R[4]+1
! — Convergenza —
31: LBL[49]
32: R[1]=R[1]+1
33: JMP LBL[1]
! — Stop pulito —
34: LBL[9]
35: CALL STOP_PULITO
36: JMP LBL[5]
! — Errore —
37: LBL[99]
38: DO[1]=OFF
39: J P[1:HOME] 100% FINE
40: DO[3]=OFF · DO[6]=ON
41: R[90]=R[56] ! salva codice errore
! [attende intervento tecnico — non ritorna]
PRESA
! IN: nessun parametro
! OUT: R[56]=0 ok · R[56]=1 timeout chiusura pinza
1: R[56]=0
2: ACC 100
3: J P[10:APPR_PICK] 80% CNT50
4: L P[11:PICK ] 120mm/sec FINE
5: DO[1]=ON
6: WAIT DI[1]=ON TIMEOUT, LBL[99]
7: ACC 40 ! dolce con pezzo
8: L P[10:APPR_PICK] 250mm/sec CNT80
! fine — ritorno ok
9: LBL[99] ! timeout pinza
10: R[56]=1
! fine sotto-programma — chiamante gestisce errore
DEPOSITA
! IN: R[50]=1 vassoio A · R[50]=2 vassoio B · R[50]=0 scarti
! OUT: R[56]=0 ok · R[56]=1 timeout apertura pinza
! Aggiorna PR[1] o PR[2] con offset cella corrente
1: R[56]=0
2: SELECT R[50]=1, JMP LBL[10]
=2, JMP LBL[20]
ELSE, JMP LBL[30]
! — Vassoio A —
3: LBL[10]
4: PR[1,1]=0 · PR[1,2]=0 · PR[1,3]=0
5: PR[1,4]=0 · PR[1,5]=0 · PR[1,6]=0
6: PR[1,1]=R[21]*55 ! offset X = colonna × 55mm
7: PR[1,2]=R[20]*55 ! offset Y = riga × 55mm
8: ACC 100
9: J P[20:APPR_A0] 80% CNT50 OFFSET, PR[1]
10: L P[21:PLACE_A0] 120mm/sec FINE OFFSET, PR[1]
11: DO[1]=OFF
12: WAIT DI[1]=OFF TIMEOUT, LBL[98]
13: ACC 100
14: L P[20:APPR_A0] 300mm/sec CNT80 OFFSET, PR[1]
! avanza indice cella vassoio A
15: R[21]=R[21]+1
16: IF R[21]<3, JMP LBL[49] ! ancora colonne in questa riga
17: R[21]=0 ! reset colonna, avanza riga
18: R[20]=R[20]+1
19: JMP LBL[49]
! — Vassoio B (identico ad A con PR[2], R[22], R[23], P[30]/P[31]) —
20: LBL[20]
21: PR[2,1]=0 · PR[2,2]=0 · PR[2,3]=0
22: PR[2,4]=0 · PR[2,5]=0 · PR[2,6]=0
23: PR[2,1]=R[23]*55
24: PR[2,2]=R[22]*55
25: J P[30:APPR_B0] 80% CNT50 OFFSET, PR[2]
26: L P[31:PLACE_B0] 120mm/sec FINE OFFSET, PR[2]
27: DO[1]=OFF
28: WAIT DI[1]=OFF TIMEOUT, LBL[98]
29: L P[30:APPR_B0] 300mm/sec CNT80 OFFSET, PR[2]
30: R[23]=R[23]+1
31: IF R[23]<3, JMP LBL[49]
32: R[23]=0 · R[22]=R[22]+1
33: JMP LBL[49]
! — Scarti —
34: LBL[30]
35: J P[40:APPR_SC] 80% CNT80
36: L P[41:PLACE_SC] 120mm/sec FINE
37: DO[1]=OFF
38: WAIT DI[1]=OFF TIMEOUT, LBL[98]
39: L P[40:APPR_SC] 300mm/sec CNT100
! — Convergenza —
40: LBL[49]
41: R[56]=0
! fine sotto-programma — ritorno ok
42: LBL[98] ! timeout apertura pinza
43: R[56]=1
! fine sotto-programma — chiamante gestisce errore
CAMBIA_VASSOIO
! IN: R[50]=1 vassoio A · R[50]=2 vassoio B
! OUT: contatore vassoio azzerato · indici griglia azzerati
1: J P[1:HOME] 100% FINE ! in home per sicurezza operatore
2: SELECT R[50]=1, JMP LBL[10]
ELSE, JMP LBL[20]
3: LBL[10]
4: DO[4]=ON ! segnala vassoio A pieno
5: WAIT DI[5]=ON ! attende conferma sostituzione
6: DO[4]=OFF
7: R[2]=0 · R[20]=0 · R[21]=0 ! azzera contatore e indici A
8: JMP LBL[49]
9: LBL[20]
10: DO[5]=ON
11: WAIT DI[6]=ON
12: DO[5]=OFF
13: R[3]=0 · R[22]=0 · R[23]=0
14: LBL[49]
! fine — ritorno al ciclo
INIT_CELLA e STOP_PULITO
1: R[1]=0 · R[2]=0 · R[3]=0 · R[4]=0
2: R[10]=9 · R[20]=0 · R[21]=0 · R[22]=0 · R[23]=0
3: R[90]=0
4: DO[1]=OFF · DO[3]=OFF · DO[4]=OFF · DO[5]=OFF · DO[6]=OFF · DO[7]=OFF
5: J P[1:HOME] 100% FINE
! STOP_PULITO — fine ciclo ordinato
1: J P[1:HOME] 100% FINE
2: DO[3]=OFF
! fine — CELL_MAIN torna a LBL[5]
🔬 4. Procedura di collaudo formale
& Review
10%
3 rami
griglia 9
errori
🎓 5. Colloquio tecnico — domande di discussione
Il progetto finale si conclude con un colloquio tecnico simulato. Per ciascuna delle domande seguenti, prepara una risposta che faccia riferimento a scelte specifiche del progetto CELL_FINAL.
D1. Perché DEPOSITA aggiorna gli indici di griglia (R[20], R[21]) invece di farlo nel CELL_MAIN?
Mostra risposta
Perché l’indice di cella è strettamente accoppiato all’operazione di deposito: si avanza alla cella successiva esattamente quando un pezzo è stato depositato con successo. Se l’aggiornamento fosse in CELL_MAIN dopo il ritorno di DEPOSITA, si creerebbe un’asimmetria: DEPOSITA potrebbe tornare con R[56]=1 (timeout apertura pinza) dopo aver fisicamente rilasciato il pezzo, e CELL_MAIN salterebbe a LBL[99] senza avanzare l’indice — la prossima volta che il vassoio viene usato, il robot tornerebbe sulla cella già occupata. Tenere l’aggiornamento dentro DEPOSITA garantisce coerenza: indice e deposito fisico avanzano sempre insieme, nello stesso contesto di esecuzione.
D2. In CAMBIA_VASSOIO il robot torna a HOME prima di segnalare DO[4]/DO[5]. Perché è obbligatorio e non opzionale?
Mostra risposta
Perché il cambio vassoio richiede l’accesso fisico dell’operatore alla cella. Se il robot rimanesse sul vassoio con il pezzo ancora afferrato in attesa di DI[5], l’operatore si troverebbe il braccio del robot sopra il vassoio che deve rimuovere — rischio di collisione tra l’operatore e il TCP durante la rimozione del vassoio pieno o l’inserimento del vassoio vuoto. Portare il robot in HOME prima di segnalare DO[4] garantisce che il braccio sia nella posizione di sicurezza certificata, fuori dalla zona di lavoro, prima che l’operatore entri. Questo è un requisito di sicurezza funzionale — non una scelta di comodo.
D3. CELL_MAIN usa IF R[2]>=R[10], CALL CAMBIA_VASSOIO sulla riga 17, dopo aver già incrementato R[2]. Perché non si usa IF R[2]>R[10]?
Mostra risposta
Perché R[2] viene incrementato prima del check: dopo il deposito del 9° pezzo, R[2] diventa 9, e R[10]=9. La condizione R[2]>=R[10] è vera (9>=9) → cambio vassoio corretto. Con R[2]>R[10] sarebbe falsa (9>9 è falso) e il cambio non verrebbe chiamato. Il robot tornerebbe alla riga 6 (LBL[1]) e alla prossima iterazione tenterà di depositare il 10° pezzo su una griglia con indici R[21] che, dopo l’avanzamento in DEPOSITA, valgono R[21]=0 e R[20]=3 — riga 3 di una griglia 0-indexed 3×3, che non esiste. Causa posizioni errate o collisioni. Il >= è la condizione corretta per un confronto su valore già incrementato rispetto a un limite superiore inclusivo.
D4. Il programma non ha un limite di cicli totali — gira indefinitamente. In un impianto reale, come si aggiunge un meccanismo di manutenzione preventiva basato sul conteggio?
Mostra risposta
Si aggiunge un registro R[80:MAINT_CNT] che conta i cicli dall’ultima manutenzione (persistente tra spegnimenti) e un limite R[81:MAINT_LIM] impostato a es. 50000 cicli. In LBL[49] (convergenza), dopo R[1]++, si aggiunge: R[80]=R[80]+1, poi IF R[80]>=R[81], JMP LBL[95]. LBL[95] è la sequenza di manutenzione: HOME, DO[3]=OFF, DO[8]=ON (segnale manutenzione al PLC), WAIT DI[8]=ON (conferma manutenzione eseguita), DO[8]=OFF, R[80]=0, JMP LBL[5]. Il tecnico esegue la manutenzione (ingrassaggio, controllo riduttori, verifica calibrazione) e preme il pulsante di reset manutenzione. Il robot riparte con R[80]=0. Questo pattern — contatore di cicli con soglia configurabile — è standard negli impianti di produzione seria.
D5. Descrivi in 5 frasi cosa hai imparato in questo percorso triennale che non sapevi prima.
Mostra risposta
Risposta libera — è la domanda più importante del colloquio. Una risposta modello potrebbe essere: “Ho imparato che un robot industriale non è una macchina misteriosa ma un sistema cinematico preciso con sei gradi di libertà, che obbedisce a regole matematiche precise. Ho capito che scrivere codice che funziona è solo l’inizio — scrivere codice sicuro, ottimizzato e manutenibile richiede metodo, non solo tecnica. Ho visto che la scelta di una terminazione (FINE vs CNT) può valere un 40% di produttività. Ho capito che la modularità non è un lusso ma l’unico modo per scrivere programmi che si possono mantenere nel tempo. E ho capito che il robot è uno strumento al servizio di un processo produttivo — programmare bene significa conoscere quel processo, non solo conoscere le istruzioni TP.”
📚 Riepilogo del progetto finale
- Cinematica e sistemi di riferimento (Lez. 02–03) — configurazione NUT, W=180°, approccio verticale
- Jog e teach dei punti (Lez. 04–08) — P[ ] derivati, 9 punti per una cella completa
- Movimenti J/L con FINE e CNT (Lez. 07, 16) — ACC dolce con pezzo, aggressivo a vuoto
- I/O digitali con TIMEOUT (Lez. 10) — DI conferma pinza, DO segnali PLC, LBL[98/99] distinti
- Registri R[ ] come contatori, limiti, parametri (Lez. 11) — R[1..4], R[10], R[50], R[56], R[90]
- Strutture di controllo e loop (Lez. 12–13) — SELECT a 3 vie, IF errore, loop infinito con start/stop
- Offset su griglia con PR[ ] (Lez. 15) — 2 punti insegnati per 9 celle, indici R[20–23]
- Architettura modulare con CALL (Lez. 17) — 6 programmi, interfaccia R[50]/R[56], max 2 livelli
🎓 Fine del percorso — Robotica Industriale FANUC ER-4iA
Hai completato 18 lezioni di programmazione robotica industriale. Sai leggere le specifiche di una cella, progettare l’architettura, scrivere il codice TP, ottimizzare le traiettorie e collaudare il programma con metodo. Il robot fisico in laboratorio usa lo stesso controller R-30iB Mate e lo stesso linguaggio TP che hai usato nel simulatore.
© Prof. D. Bertolino · Robotica Industriale FANUC ER-4iA · Lezione 18 di 18