Sono appena riuscito (forse) a mettere insieme 4 righe di C, Phyton e HAL per aggiungere l'Anti-Dive al mio THC che avevo proposto tempo fa qui:
https://www.cncitalia.net/forum/viewtopi ... 5&start=15
https://www.cncitalia.net/forum/viewtopi ... 99#p481899
Perdonate il cross-posting ma è necessario per far capire di cosa si tratta.
Ad ogni modo, il THC funzionava abbastanza bene, ma purtroppo il limite è che, nel momento in cui ci si avvicina ad angoli o archi piuttosto stretti, la velocità di avanzamento diminuisce e il THC fallisce nel suo compito di mantenere l'altezza della torcia costante. Diminuendo la velocità, la torcia sfonda il materiale, la tensione d'arco sale, il THC interpreta questo come un allontanamento dal materiale e risponde con l'abbassamento della torcia fino alla collisione.
Per ovviare a questo ho pensato di tenere traccia della velocità di avanzamento attuale e, confrontandola con quella richiesta dal programma G-Code in esecuzione, decidere se far intervenire il THC oppure no.
Per fare questo ho implementato un piccolo programmino in C, un interfaccia in pyVCP con un semplice LED che mi dice quando l'Anti-Dive sta lavorando, e un paio di righe di codice da inserire nel file custom.hal.
Per chi non lo sapesse LinuxCNC è un software basato interamente su componenti HAL. HAL sta per Hardware Abstraction Layer. In poche parole l'intero software è un insieme di microsoftware tenuti insieme da "nets" (fili). Ogni pezzettino di software fa qualcosa e comunica con il resto dell'insieme tramite variabili di ingresso e uscita collegate tra loro da dei fili virtuali. La cosa bella è che noi possiamo aggiungere e costruire componenti HAL e farli lavorare insieme a tutti gli altri come più ci fa comodo.
L'idea è quella di ricevere 2 dati fondamentali: la velocità istantanea e la velocità richiesta dal G-code. In linuxcnc ci sono due componenti HAL che svolgono questo compito:
motion.current-vel che restituisce la velocità in unità di misura d'utente al secondo.
motion.request-vel che restituisce la velocità target del G-Code in quel momento, sempre in unità di misura d'utente al secondo.
Entrambi restituiscono un dato float.
Una cosa non è stata chiarita...come si costruisce un componente HAL? Un componente HAL si costruisce in linguaggio C, basta scriverlo in un file di testo e compilarlo con l'apposita utility Comp, dedicata alla compilazione di componenti HAL.
Per scaricare Comp...sudo apt-get install linuxcnc-dev. (http://linuxcnc.org/docs/html/hal/comp.html)
Di seguito il codice da me utilizzato:
component anti_dive;
pin in float currentvel;
pin in float reqvel;
pin out bit output;
function _;
license "GPL";
;;
float res;
res = reqvel - currentvel;
if (res==0) {
output = FALSE;
}
else {
output = TRUE;
}
Il file si chiama anti_dive.comp e va salvato nella cartella home/andrea/linuxcnc/src/hal/components/anti-dive.comp (se non c'è createla)
A questo punto da terminale si lancia il comando sudo comp --install
/home/andrea/linuxcnc/src/hal/components/anti_dive.comp
A questo punto il compilatore va ad integrare questo nuovo componente all'interno di LinuxCNC. Tuttavia ancora non succede nulla, perchè di ogni componente noi dobbiamo dire a LinuxCNC di caricarlo, di caricare la funzione specifica all'interno del componente (nel mio caso anti_dive ha una sola funzione, ma potremmo fare componenti con più funzioni) e successivamente connetterla con questi "nets" con gli altri componenti che desideriamo.
Nel mio caso anti_dive (che una volta compilata diventa anti-dive...ndr) dovrà essere linkata a motion.current-vel e a motion.request-vel. Per fare questo dobbiamo editare il file custom.hal che troviamo nella cartella di configurazione della nostra macchina. In custom.hal andiamo ad aggiungere:
loadrt anti_dive (carichiamo il modulo anti_dive)
addf anti-dive.0 servo-thread (carichiamo la funzione specifica)
net anti-dive-currentvel motion.current-vel => anti-dive.0.currentvel (anti-dive-currentvel è il nome del net, motion.current-vel va a finire nella variabile currentvel del programmino)
net anti-dive-reqvel motion.requested-vel => anti-dive.0.reqvel (stessa cosa di cui sopra)
net anti-dive-output anti-dive.0.output => parport.0.pin-17-out (l'output del programma va a pilotare il pin 17 della porta parallela)
A questo punto ci rimane di inserire il LED a lato dell'interfaccia che si accenderà ogni volta che interviene l'anti-dive.
In custompanel.XML inseriamo:
<?xml version="1.0" encoding="UTF-8" ?>
- <pyvcp>
- <vbox>
<relief>RIDGE</relief>
<bd>6</bd>
- <label>
<text>"Anti-Dive Enabled:"</text>
<font>("Helvetica",13)</font>
</label>
- <hbox>
- <led>
<halpin>"anti-dive-enabled-led"</halpin>
<size>30</size>
<on_color>"green"</on_color>
<off_color>"grey"</off_color>
</led>
</hbox>
</vbox>
</pyvcp>
E in custom_postgui.hal inseriamo:
net anti-dive-output anti-dive.0.output => pyvcp.anti-dive-enabled-led
Anche qui vediamo che non abbiamo fatto altro che linkare l'output del componente HAL anti-dive al led che abbiamo dichiarato all'interno del codice pyVCP contenuto nel file XML. Immaginate che dalla variabile di output del componente anti-dive escano 2 fili, uno che va al led e uno che va al pin 17 della porta parallela. E' un astrazione software, ma è molto intuitiva.
Il risultato è questo: