Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Entrambe le parti precedenti la revisione Revisione precedente Prossima revisione | Revisione precedente | ||
guide:junction_speed:start [26/05/2018 19:08] Simone Persiani |
guide:junction_speed:start [03/06/2018 22:09] (versione attuale) Simone Persiani |
||
---|---|---|---|
Linea 1: | Linea 1: | ||
- | ====== Jerk Limiting vs Junction Deviation ====== | + | ====== Junction Speed ====== |
- | --- //[[iosonopersia@gmail.com|Simone Persiani]] 26/05/2018 13:00// | + | //Autore: [[iosonopersia@gmail.com|Simone Persiani]]// |
==== Introduzione ==== | ==== Introduzione ==== | ||
- | I progetti ''Marlin'' ed ''MK4duo'', a partire rispettivamente dalle versioni ''1.1.9'' e ''4.3.6'', hanno introdotto una nuova funzionalità nel tentativo di superare l'ormai datata gestione del jerk degli assi. Tale gestione non ha mai convinto del tutto gli sviluppatori di Marlin e ha causato loro molti grattacapi nel corso degli anni. Nel tentativo di superare tale algoritmo si sono ispirati ai codici sorgente di [[http://reprap.org/wiki/Grbl#Grbl|Grbl]], un ben noto firmware per la gestione di macchine CNC, prendendo spunto dall'algoritmo della Junction Deviation (il tutto nel pieno rispetto delle licenze associate a tale prodotto). Ricordiamo che Marlin stesso è nato nell'agosto del 2011 proprio come fork di [[http://reprap.org/wiki/Grbl#Grbl|Grbl]] e di [[http://reprap.org/wiki/List_of_Firmware#Sprinter|Sprinter]]. | + | I progetti [[https://marlinfw.org|Marlin]] ed ''MK4duo'', a partire rispettivamente dalle versioni ''1.1.9'' e ''4.3.6'', hanno introdotto un nuovo algoritmo nel tentativo di superare l'ormai datato [[guide:junction_speed:jerk_limiting|Jerk Limiting]]. Tale gestione non ha mai convinto del tutto gli sviluppatori di [[https://marlinfw.org|Marlin]] e ha causato loro molti grattacapi nel corso degli anni. Nel tentativo di superare tale algoritmo si sono ispirati ai codici sorgente di [[http://reprap.org/wiki/Grbl#Grbl|Grbl]], un ben noto firmware per la gestione di macchine CNC, ottenendo e migliorando il [[guide:junction_speed:junction_deviation|Junction Deviation]] (il tutto nel pieno rispetto delle licenze associate a tale prodotto). Ricordiamo che [[https://marlinfw.org|Marlin]] stesso è nato nell'agosto del 2011 proprio come fork di [[http://reprap.org/wiki/Grbl#Grbl|Grbl]] e di [[http://reprap.org/wiki/List_of_Firmware#Sprinter|Sprinter]]. |
- | + | ||
- | Tali algoritmi (l'uno alternativo all'altro), si rendono necessari nel momento in cui il ''planner'' (il modulo software che si occupa dell'ottimizzazione dei movimenti della macchina) si trova a dover scegliere con quale velocità far terminare un blocco e cominciare il successivo, ovvero la velocità di giunzione dei due blocchi. | + | |
<WRAP center round info 100%> | <WRAP center round info 100%> | ||
- | Per maggiori informazioni sui blocchi e sul loro funzionamento, far riferimento alla guida [[guide:s_curve_acceleration|S-Curve Acceleration]] | + | Tali algoritmi (l'uno alternativo all'altro) si rendono necessari nel momento in cui il ''planner'' (il modulo software che si occupa dell'ottimizzazione dei movimenti della macchina) si trova a dover scegliere con quale velocità far terminare un blocco e cominciare il successivo, ovvero la ''Junction Speed'' (velocità di giunzione tra spostamenti successivi). |
</WRAP> | </WRAP> | ||
+ | |||
==== Premessa ==== | ==== Premessa ==== | ||
In un mondo ideale stamperemmo tutti alla velocità della luce e otterremmo i pezzi stampati in un istante. Ciò ovviamente non è possibile: le nostre macchine hanno dei motori che possono raggiungere solo determinate velocità massime, hanno dei telai in grado di assorbire solo una certa quantità di vibrazioni e di sopportare carichi di forze/tensioni limitati, hanno delle parti in movimento con massa sicuramente diversa da zero, ecc. Le vibrazioni che si vengono a creare quando stampiamo ad alte velocità impattano sulla qualità dell'oggetto stampato (vedi //effetto ghosting//). Si rende quindi necessario trovare una strategia efficiente per gestire le accelerazioni di ciascun asse in modo da trovare un buon compromesso tra qualità e tempi di stampa. | In un mondo ideale stamperemmo tutti alla velocità della luce e otterremmo i pezzi stampati in un istante. Ciò ovviamente non è possibile: le nostre macchine hanno dei motori che possono raggiungere solo determinate velocità massime, hanno dei telai in grado di assorbire solo una certa quantità di vibrazioni e di sopportare carichi di forze/tensioni limitati, hanno delle parti in movimento con massa sicuramente diversa da zero, ecc. Le vibrazioni che si vengono a creare quando stampiamo ad alte velocità impattano sulla qualità dell'oggetto stampato (vedi //effetto ghosting//). Si rende quindi necessario trovare una strategia efficiente per gestire le accelerazioni di ciascun asse in modo da trovare un buon compromesso tra qualità e tempi di stampa. | ||
- | Per la Legge Fondamentale della Dinamica (<m>\vec{F}=m*\vec{a}</m>) le forze esercitate dai motori sul telaio della stampante dipendono contemporaneamente sia dalle masse in movimento sia dalle accelerazioni che esse subiscono. Non è quindi possibile trovare un'accelerazione massima che sia corretta per ogni stampante, perché quest'ultima dipenderà dalla struttura meccanica di ciascuna macchina. In linea generale è corretto assumere che la massima accelerazione possa essere aumentata nel caso in cui si siano alleggerite le parti in movimento (il carrello dell'hotend e/o il piatto di stampa, a seconda della meccanica), e viceversa. | + | Per la Legge Fondamentale della Dinamica (<m>\vec{F}=m*\vec{a}</m>) le forze esercitate dai motori sul telaio della stampante dipendono contemporaneamente sia dalle masse in movimento sia dalle accelerazioni che esse subiscono. Non è quindi possibile trovare un'accelerazione massima che sia corretta per ogni stampante, perché quest'ultima dipenderà dalle caratteristiche meccaniche di ciascuna macchina. In linea generale è corretto assumere che si possa aumentare la massima accelerazione di un asse nel caso in cui se ne siano alleggerite le parti in movimento, e viceversa. |
- | È quindi possibile definire nel firmware le accelerazioni massime per ciascun asse, compresi gli estrusori. Tali accelerazioni definiscono la rapidità con cui l'attuale velocità di un asse può essere aumentata/diminuita per raggiungere una velocità prefissata. **I movimenti pianificati dalla macchina vengono quindi modellati rispettando le accelerazioni massime per ogni asse definite dall'utente.** | + | È quindi possibile definire nel firmware le accelerazioni massime per ciascun asse (compresi gli estrusori!) in base alla loro **inerzia** (nel linguaggio comune diremmo //lentezza// e/o //pesantezza//). Tali accelerazioni definiscono la rapidità con cui l'attuale velocità di un asse possa essere variata per raggiungere una velocità target. **In questo modo gli spostamenti pianificati dalla macchina possono essere modellati tenendo correttamente in considerazione anche le masse in movimento.** |
- | Il ''planner'' si occupa inoltre di concatenare gli spostamenti in modo che la velocità con cui termina un blocco sia la stessa di quella con cui comincia il blocco successivo (<m>\vec{v^{i}}_{finale}=\vec{v^{i+1}}_{iniziale}</m>), con lo scopo di rendere più "fluido" il passaggio da uno spostamento all'altro. La scelta di questa velocità **non è così scontata** come potrebbe apparire ad una prima analisi ed è un fattore critico in grado di produrre effetti apprezzabili sui tempi di stampa. | + | Il ''planner'' si occupa inoltre di concatenare gli spostamenti in modo che la velocità con cui termina un blocco sia la stessa di quella con cui comincia il blocco successivo (<m>\vec{v^{i}}_{finale}=\vec{v^{i+1}}_{iniziale}</m>), con lo scopo di rendere più "fluido" il passaggio da uno spostamento all'altro. La scelta della ''Junction Speed'' non è così scontata come potrebbe apparire ad una prima analisi ed è un fattore critico in grado di produrre effetti apprezzabili sui tempi di stampa. |
- | ==== Il problema ==== | + | ==== Il jerk ==== |
Ogni spostamento è sempre associato ad una velocità: per raggiungerla è necessario effettuare una accelerazione//[decelerazione]//, a seconda che la velocità attuale sia minore//[maggiore]// rispetto al target. | Ogni spostamento è sempre associato ad una velocità: per raggiungerla è necessario effettuare una accelerazione//[decelerazione]//, a seconda che la velocità attuale sia minore//[maggiore]// rispetto al target. | ||
- | Supponiamo che la macchina abbia pianificato di dover eseguire due blocchi in successione: il blocco <m>j</m> a velocità <m>\vec{v}_j</m> ed il blocco <m>k</m> a velocità <m>\vec{v}_k</m>. La velocità di giunzione tra i due blocchi (incognita!) è <m>\vec{v}_{junction}</m>. Il blocco <m>j</m> è ora in esecuzione con velocità <m>\vec{v}_j</m>: gli rimane un tempo <m>t_j</m> per raggiungere <m>\vec{v}_{junction}</m>, ciò significa che si renderà necessaria una accelerazione <m>\vec{a}_j = {\Delta \vec{v}}/{\Delta t} = {\vec{v}_{junction} - \vec{v}_j}/{t_j}</m>. A questo punto il blocco <m>k</m> avrà a disposizione un tempo <m>t_k</m> per portarsi alla velocità <m>\vec{v}_k</m>, ciò significa che si renderà necessaria una accelerazione <m>\vec{a}_k = {\Delta \vec{v}}/{\Delta t} = {\vec{v}_k - \vec{v}_{junction}}/{t_k}</m>. In generale <m>\vec{a}_j <> \vec{a}_k</m>: ciò significa che il jerk (derivata dell'accelerazione nel tempo), assumerà un valore diverso da zero **solo** nell'intervallo di tempo durante la transizione da un'accelerazione all'altra, mentre sarà uguale a zero per il resto del tempo. Esso infatti è calcolato come <m>\vec{jerk} = {\Delta \vec{a}}/{\Delta t} = {\vec{a}_k} - \vec{a}_j}/{t_0}</m>, laddove <m>t_0</m> è un valore molto piccolo dell'ordine di pochi microsecondi. Il jerk è una variazione (aumento/diminuzione) di accelerazione che può produrre effetti indesiderati sulle stampe e questo sistema è in grado di mantenerlo a zero per la maggior parte del tempo. | + | Supponiamo che la macchina abbia pianificato di dover eseguire due blocchi in successione: il blocco <m>j</m> a velocità <m>\vec{v}_j</m> ed il blocco <m>k</m> a velocità <m>\vec{v}_k</m>. La velocità di giunzione tra i due blocchi (incognita!) è <m>\vec{v}_{junction}</m>. Il blocco <m>j</m> è ora in esecuzione con velocità <m>\vec{v}_j</m>: gli rimane un tempo <m>t_j</m> per raggiungere <m>\vec{v}_{junction}</m>, ciò significa che si renderà necessaria una accelerazione <m>\vec{a}_j = {\Delta \vec{v}}/{\Delta t} = {\vec{v}_{junction} - \vec{v}_j}/{t_j}</m>. A questo punto il blocco <m>k</m> avrà a disposizione un tempo <m>t_k</m> per portarsi alla velocità <m>\vec{v}_k</m>, ciò significa che si renderà necessaria una accelerazione <m>\vec{a}_k = {\Delta \vec{v}}/{\Delta t} = {\vec{v}_k - \vec{v}_{junction}}/{t_k}</m>. In generale <m>\vec{a}_j <> \vec{a}_k</m>: ciò significa che il jerk (derivata dell'accelerazione nel tempo), assumerà un valore diverso da zero **solo** nell'intervallo di tempo durante la transizione da un'accelerazione all'altra, mentre sarà uguale a zero per il resto del tempo. Esso infatti è calcolato come <m>\vec{jerk} = {\Delta \vec{a}} / {\Delta t} = {\vec{a}_k - \vec{a}_j}/{t_0}</m>, laddove <m>t_0</m> è un valore molto piccolo dell'ordine di pochi microsecondi. Il jerk è una variazione (aumento/diminuzione) di accelerazione che può produrre effetti indesiderati sulle stampe e questo sistema è in grado di mantenerlo a zero per la maggior parte del tempo. |
<WRAP center round tip 100%> | <WRAP center round tip 100%> | ||
- | Esiste una funzionalità che permette di mantenere **sempre** il jerk a zero. Per informazioni, riferirsi alla guida [[guide:s_curve_acceleration|S-Curve Acceleration]] | + | Se i motori stepper incaricati di eseguire movimenti con jerk non nullo hanno abbastanza coppia (//torque// in inglese), allora saranno in grado di effettuare tali transizioni senza perdita di step (ovvero senza ridurre la precisione e la qualità di stampa). In caso contrario sarà necessario ridurre la massima accelerazione per gli assi che presentano problemi. |
+ | Esiste però una funzionalità che permette di mantenere **sempre** il jerk a zero. Per informazioni, riferirsi alla guida <wrap em>[[guide:s_curve_acceleration|S-Curve Acceleration]]</wrap> | ||
</WRAP> | </WRAP> | ||
- | ==== Soluzione 1: algoritmo "Jerk Limiting" ==== | + | ==== Algoritmi implementati ==== |
- | === Strategia === | + | La guida sugli algoritmi attualmente implementati prosegue nelle rispettive pagine dedicate: |
- | Uno dei problemi di questo sistema è che le accelerazioni e le decelerazioni richiedono tempo: un tempo relativamente piccolo che, moltiplicato per i milioni di movimenti richiesti per una stampa, può aumentare anche di molto i tempi di stampa. | + | * <wrap em>[[guide:junction_speed:jerk_limiting|Jerk Limiting]] (classico)</wrap> |
- | + | * <wrap em>[[guide:junction_speed:junction_deviation|Junction Deviation]] (nuovo)</wrap> | |
- | Si è deciso quindi di evitare il più possibile tali fasi di accelerazione introducendo dei parametri modificabili dall'utente che qui chiameremo //"max_jerk"//. In realtà tali valori si chiamano così perché incidono sul valore del jerk ma non possono essere considerati dei veri e propri jerk. Essi infatti dimensionalmente sono rappresentati da variazioni di velocità e sono quindi misurati in mm/s. | + | |
- | + | ||
- | === L'algoritmo === | + | |
- | Riprendendo l'esempio di prima, avremo una variazione di velocità pari a <m>\Delta \vec{v} = \vec{v}_k - \vec{v}_j</m>: | + | |
- | * **se almeno una tra le componenti XYZ di <m>\Delta \vec{v}</m> supera il relativo //"max_jerk"// impostato**, il firmware realizzerà il passaggio da <m>\vec{v}_j</m> a <m>\vec{v}_k</m> tramite accelerazioni. Stabilirà il valore incognito di <m>\vec{v}_{junction}</m> in modo tale che le variazioni di velocità lungo i tre assi non superino quelle impostate tramite //max_jerk//. In realtà l'algoritmo è nei fatti un po' più complesso di così: deve infatti tener conto anche di altri fattori tra i quali eventuali cambi di direzione degli assi (un qualunque asse deve rallentare fino a fermarsi prima di poter invertire la direzione del proprio moto); | + | |
- | * **altrimenti** il passaggio da una velocità all'altra sarà istantaneo e non si perderà tempo per le accelerazioni/decelerazioni intermedie. | + | |
- | + | ||
- | === Configurazione dei parametri === | + | |
- | Il //"max_jerk"// è quindi **la minima variazione di velocità che richiede un'accelerazione**: se <m>\vec{v}_j</m> e <m>\vec{v}_k</m> fossero abbastanza simili tra loro, il passaggio dall'una all'altra sarebbe istantaneo. Questo trucchetto permette di ridurre leggermente i tempi di stampa ma va impostato correttamente: più i valori di //"max_jerk"// vengono aumentati, maggiori saranno gli spostamenti (statisticamente) che verranno gestiti con il cambio di velocità istantaneo (e maggiori saranno quindi le vibrazioni prodotte). | + | |
- | + | ||
- | Riassumendo, i //"max_jerk"// devono essere impostati tenendo a mente che abbassando tali valori si riducono le vibrazioni e i rumori prodotti dai motori ma si allungano conseguentemente i tempi di stampa, e viceversa. | + | |
- | + | ||
- | Per abilitare il ''Jerk Limiting'' è sufficiente assicurarsi che il ''Junction Deviation'' sia disabilitato. Ecco un esempio di configurazione dei suoi parametri: | + | |
- | <code> | + | |
- | //#define JUNCTION_DEVIATION // per abilitare il Jerk Limiting e disabilitare il Junction Deviation | + | |
- | #define DEFAULT_XJERK 10 | + | |
- | #define DEFAULT_YJERK 10 | + | |
- | #define DEFAULT_ZJERK 0.4 | + | |
- | #define DEFAULT_EJERK {5,5,5,5,5,5} | + | |
- | </code> | + | |
- | + | ||
- | ==== Soluzione 2: algoritmo "Junction Deviation" ==== | + | |
- | === Strategia === | + | |
- | L'algoritmo ''Jerk Limiting'' ragiona su ciascun asse separatamente, senza perciò tener in considerazione l'effettiva traiettoria generata dai movimenti pianificati nel ''planner''. Il risultato è che nelle curve, che sono sempre composte da una moltitudine di segmenti più o meno "corti", il ''planner'' cerca di assicurare che ciascun asse non subisca variazioni troppo alte di velocità limitando separatamente le componenti <m>\vec{v}_X</m>, <m>\vec{v}_Y</m> e <m>\vec{v}_Z</m>, finendo spesso per limitare eccessivamente la velocità totale (data dalla loro somma vettoriale: <m>\vec{v} = \vec{v}_X + \vec{v}_Y +\vec{v}_Z</m>). | + | |
- | + | ||
- | L'algoritmo ''Junction Deviation'' fornisce invece al ''planner'' una visione d'insieme migliore sulla coda di movimenti da eseguire, permettendogli di scegliere <m>\vec{v}_{junction}</m> tenendo conto solamente di fattori relativi alla traiettoria degli spostamenti. Il risultato è un algoritmo più semplice ed efficace, in grado di evitare rallentamenti eccessivi e quindi di velocizzare la percorrenza di tratti curvilinei. Alcuni utenti di ''Marlin'', i primi ad aver testato tale algoritmo, hanno riferito di aver notato una diminuzione di circa il 20% sui tempi di stampa. | + | |
- | + | ||
- | === L'algoritmo === | + | |
- | <WRAP center round todo 100%> | + | |
- | **NOTA DELL'AUTORE:** | + | |
- | Attualmente la migliore spiegazione si trova qui: [[https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/|Improving Grbl cornering algorithm]]. È disponibile solo in lingua inglese e in alcuni passaggi è un po' sbrigativa e confusa, per lo meno agli occhi dell'autore di questa guida. Per questo motivo, se dovesse servire, potrei dedicarmi alla sua riscrittura in lingua italiana. | + | |
- | </WRAP> | + | |
- | + | ||
- | === Configurazione dei parametri === | + | |
- | Per attivare questa funzionalità è necessario assicurarsi di aver abilitato l'opzione ''JUNCTION_DEVIATION''. I parametri attualmente disponibili sono i seguenti: | + | |
- | <code> | + | |
- | #define JUNCTION_DEVIATION // per abilitare il Junction Deviation e disabilitare il Jerk Limiting | + | |
- | #define JUNCTION_DEVIATION_MM 0.05 // valore decimale maggiore o uguale a 0 | + | |
- | #define JUNCTION_ACCELERATION 1000 | + | |
- | //#define JUNCTION_DEVIATION_INCLUDE_E | + | |
- | </code> | + | |
- | + | ||
- | * Per comprendere l'opzione ''JUNCTION_DEVIATION_MM'' è strettamente necessario aver capito a fondo il funzionamento dell'algoritmo. Si faccia riferimento alla guida di cui sopra è stato fornito il link. Si sappia che è un valore espresso in mm e che un range sicuro di possibili valori va da 0mm a 0,5mm. Ovviamente questi valori vanno testati sulla propria macchina procedendo per tentativi; | + | |
- | * ''JUNCTION_ACCELERATION'' è il più semplice da immaginare: trattasi della massima accelerazione centripeta che la meccanica può sostenere. Durante i cambi di direzione il nuovo algoritmo cerca di mantenere costante la velocità: l'accelerazione centripeta è <m>a_{centripeta} = {v^2}/{r}</m>, dove r è il raggio di curvatura. <m>\vec{v}</m> e soprattutto <m>r</m> possono cambiare da un movimento all'altro, determinando di volta in volta un diverso valore di <m>a_{centripetal}</m>. ''JUNCTION_ACCELERATION'' permette quindi di limitare <m>a_{centripeta}</m>; | + | |
- | * Per fare in modo che per la valutazione dell'angolo di curvatura venga tenuto in conto anche l'avanzamento/ritrazione del filamento, è necessario abilitare l'opzione ''JUNCTION_DEVIATION_INCLUDE_E''. Questa opzione è <wrap em>assolutamente sperimentale</wrap>! Siccome abilitando tale opzione l'angolo verrebbe calcolato in uno spazio quadridimensionale XYZE, nemmeno gli sviluppatori del ''Junction Deviation'' sono in grado di predirne con sicurezza gli effetti! L'opzione è presente perché il ''planner'' ha a disposizione anche i dati relativi all'estrusore: siccome lo sforzo che sarebbe servito per aggiungere tale possibilità era davvero minimo, pur non riuscendo ad immaginarne gli effetti o l'utilità, gli sviluppatori hanno pensato di lasciare tale funzione e di permettere agli utenti di sperimentarla sulle loro macchine per verificare se ciò possa produrre miglioramenti apprezzabili o meno. | + | |
- | + | ||
- | === L'analogia dell'automobile === | + | |
- | Se volessimo utilizzare un'analogia per far comprendere meglio il significato dei primi due parametri, faremmo sicuramente riferimento ad un'automobile che si appresta ad affrontare una curva stretta. | + | |
- | + | ||
- | In questa analogia, tratta dalla guida sopra citata, ''JUNCTION_DEVIATION_MM'' rappresenta la larghezza della strada rispetto a quella dell'automobile: impostarlo a zero significa che la strada sarà della stessa larghezza della vettura, la quale sarà costretta (come se fosse su di un binario) a rallentare molto per affrontare la curva senza uscire dalla carreggiata. Viceversa, aumentare tale valore renderà la strada più larga e permetterà all'automobile di scegliere una traiettoria più veloce (con la differenza che nel caso della stampante la traiettoria rimarrà ovviamente la stessa ma sarà percorsa a velocità maggiore). | + | |
- | + | ||
- | ''JUNCTION_ACCELERATION'' rappresenterebbe invece il "grip" (l'aderenza) delle gomme con l'asfalto: se l'aderenza è scarsa, la velocità di percorrenza della curva deve essere limitata di molto per evitare di scivolare fuori traiettoria. Viceversa, un valore alto significa che l'automobile è in grado di sopportare accelerazioni centripete più alte e quindi può premere più bruscamente i pedali del gas e del freno. | + | |
- | + | ||
- | I due parametri vanno quindi impostati tenendo conto del loro significato fisico/geometrico. L'utente è libero di sperimentare per trovare i valori limite della propria stampante ma il consiglio è quello di non allontanarsi troppo dai valori di default, a meno che non si sappia esattamente cosa si stia facendo. | + | |
- | --- //[[iosonopersia@gmail.com|Simone Persiani]] 26/05/2018 13:00// | + | //Autore: [[iosonopersia@gmail.com|Simone Persiani]]// |
- Ultima modifica: 26/05/2018 19:08
- da Simone Persiani