Contatore filo consumato stampante 3D

Buongiorno a tutti,

sto cercando di costruire un sensore per la mia stampante 3d che sia in grado di monitorare la quantità di filamento plastico che consuma e di conseguenza quello che avanza. Il filamento, avvolto su una bobina, viene spinto da un motore all'interno di un tubicino che poi raggiunge l'ugello dove viene fuso. Sull'albero del motore è avvitato un pignone godronato (un'ingranaggio dentellato) che "morde" il filo e riesce a controllarne lo scorrimento tramite rotazioni gestite dal software. Il filo viene spinto in avanti quando il motore ruota in senso antiorario.

La mia idea è la seguente: creare una piccola asticella che si innesti sull’albero del motore (sopra il pignone) e passi attraverso due finecorsa ottici attivandoli e disattivandoli. La necessità di usare due finecorsa (e non uno) è legata al fatto che il filo non scorre solo in una direzione ma viene anche ritirato per brevi intervalli di tempo, per poi essere nuovamente spinto verso l’ugello. I finecorsa, insieme ad un display e un pulsante di reset, sono collegati ad un Arduino nano (che al momento non ho, ma sto facendo delle prove con Uno). Il problema è far capire ad Arduino in che senso sta ruotando il motore e, quindi, se il filo viene spinto in avanti o all’indietro. Ad ogni rotazione completa Arduino aggiunge al conto del filo consumato un tot e lo mostra sul display. Se poi il motore procede in senso contrario, “annullando" il giro completo, la quantità aggiunta viene sottratta e così via.

Premetto che conosco pochissimo la programmazione e, siccome non ho fretta, sto cercando di imparare pian piano semplicemente con l’esperienza. Ho iniziato a fare delle prove pensando di sfruttare questo tipo di logica: quando il finecorsa A viene attivato Arduino salva nell’array sequenza[2] = {‘O’,’O’} la lettera A al primo posto. Se poi viene attivato il finecorsa B (cioè se il motore sta procedendo spingendo il filo in avanti) Arduino salva B nel secondo posto e ciò significa che è stato compiuto un giro completo e la sequenza scritta è AB. Con una serie di “If” Arduino legge le varie sequenze e capisce se deve aggiungere o sottrarre centimetri di filamento al conto. Il mio problema è che non riesco a capire come far memorizzare il finecorsa che viene attivato per primo nella prima “casella” dell’array e il secondo nella seconda. Ho provato sempre tramite "If" ma il codice sembra non funzionare come dovrebbe. Se entrambe le caselle sono occupate da qualcosa che sia diverso da "O", allora vengono nuovamente ridefinite. Ad esempio se la sequenza è “AB" (quindi sono stati passati entrambi i finecorsa nella direzione di spinta in avanti) Arduino resetta l’array a {‘O’,’O’} e tutto è pronto per un nuovo giro. Se invece, dopo che è stato compiuto un giro, viene attivato il finecorsa B, perché il filamento torna indietro, allora la sequenza diventa “BO” e con questa sequenza Arduino sottrae i cm di filo. Un altro problema è far capire ad Arduino che se la sequenza è BO deve sottrarre un tot alla quantità di filo consumato ma una volta sola (e non continuare a sottrarre finché la sequenza non cambia).

Mi rendo conto che spiegato a parole è piuttosto complicato da capire. Metto una foto dell’estrusore e dello schema che ho in mente. Inoltre posto il codice che ho iniziato ad abbozzare.

#include<LiquidCrystal.h> //Libreria LCD 
#include <Wire.h> //Libreria Wire

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //PIN dell'LCD

int swFinecorsa1 = 1; //Variabile che contiene il valore del segnale trasmesso dal finecorsa (1 se disatttivato, 0 se attivato)
int swFinecorsa2 = 1;
char sequenza [2] = {'O','O'};
float consumato = 0; //Filo consumato
float totale = 335.2836194; //Filo totale

void setup() {

pinMode(6,INPUT_PULLUP); //Pin a cui sono collegati i finecorsa (al momento sto usando dei pulsanti dato che non li ho ancora)
pinMode(7,INPUT_PULLUP);

lcd.begin(16,2); //Initializzo il display LCD 16x2

}

void loop() {
  
  swFinecorsa1 = digitalRead(6);
  swFinecorsa2 = digitalRead(7);
 
 
//Se il finecorsa 1 viene attivato
  if(swFinecorsa1==0){

    if (sequenza[0] == 'O')
    sequenza[0] = 'A'; 
    }
    
else {
    sequenza[1] = 'A';
    } 
  }
   
  
//Se il finecorsa due viene attivato  
  if(swFinecorsa2==0 )
  
  {if (sequenza[0] == 'O'){
    sequenza[0] = 'B';  
    }
    
    else {
    sequenza[1] = 'B';
    }
  }
  
//Ora inizia la parte in cui Arduino legge le sequenze e prende prvvedimenti
if(sequenza[0] == 'A' && sequenza[1]=='B'){

consumato = consumato + 0.0157079632;
sequenza[0] = 'O';
sequenza[1] = 'O';
  
}

if(sequenza[0] =='B' && sequenza[1]=='O'){

consumato = consumato - 0.0157079632;
}

if(sequenza[0] =='B' && sequenza[1]=='A'){
sequenza[0] = 'O';
sequenza[1] = 'O';
}

if(sequenza[0] =='B' && sequenza[1]=='B'){
  
consumato = consumato + 0.0157079632;
sequenza[0] = 'O';
sequenza[1] = 'O';
}

if(sequenza[0] =='A' && sequenza[1]=='A'){
sequenza[0] = 'O';
sequenza[1] = 'O';
}


//Scrive su LCD
lcd.setCursor(0,0);
lcd.print("Rimasto");
lcd.setCursor(10,0);
lcd.print(totale-consumato);
lcd.setCursor(0,1);
lcd.print("Usato");
lcd.setCursor(10,1);
lcd.print(consumato);
}

Prima di andare avanti con il tuo progetto, ti consiglio un attento studio di quanto è già stato fatto (... con altro scopo, ma che fa già quanto tu chiedi ed estende il conecetto) leggendo QUI ...

Troverai sia tutta la parte elettronica con gli encoder ottici, sia il FW per ATmega328P (ma stessa MCU di Arduino) ... quindi ... un ottima fonte di idee.

Posso assicurare, per esperienza personale, che funziona benissimo dato che ...
... sono il coautore, assieme a tinkergnome, della modifica per farlo andare sulla Ultimaker 2 (... come puoi leggere a fondo pagna QUI ... nella paragrafo LATEST UPDATE) :grin: :grin: :grin:

Guglielmo

Grazie Guglielmo! Ora me lo studio bene :wink:

Con un encoder dovresti avere una soluzione migliore dei passi che fa il motore (200 passi in 16 microstepping non sono pochi). Se hai una risoluzione troppo bassa non puó essere certo di capire sempre la direzione del motore.

Vedo una soluzione molto piú semplice. Prendi il segnale STEP e DIR con il quale il driver del motore passo passo del estrusore viene pilotato.

Cosí non hai bisogno di aggiungere qualcosa e il segnale é anche piú semplice.

Ciao Uwe

gpb01:
...
Posso assicurare, per esperienza personale, che funziona benissimo dato che ...
... sono il coautore ...

Eh, no, cosi non va, mica si chiede all'oste se il vino che vende e' buono ... bisogna fare come disse De Andre' ... "... chiedere al mercante di liquore, tu che lo vendi, cosa ti compri di migliore" ... :smiley:

(scusa Guglielmo, non ho proprio resistito :D)

Robercrotti: scherzi a parte, se non avesse gia postato Guglielmo te l'avrei suggerito io ... usare un'encoder direttamente sul filamento e' il sistema piu sicuro, perche' rileva l'effettivo movimento del filo e quanto ne passa ...

uwe: leggere gli impulsi del motore e' un'altro sistema buono, ma se il filamento dovesse bloccarsi e l'ingranaggio "mangiare" il filo, conteresti come movimento anche il tempo in cui rimane fermo incastrato ... :wink:

Se il filamento si blocca nell'estrusore, con conseguente "mangiamento" dello stesso ad opera della meccanica di trazione, poco importa se il conteggio del filamento non è più corretto, la stampa è persa e va rifatta.
Tutti i software di slicing forniscono la quantità di filamento necessaria per la stampa e il relativo peso, sebbene sono valori stimati sono sempre abbastanza precisi, quindi non è realmente necessario conteggiarlo durante la stampa, diverso è il discorso del dispositivo linkato da Guglielmo il cui scopo è verificare il corretto scorrimento del filamento durante la stampa e la interrompe se c'è un problema, p.e. filamento finito o spezzato.
Se la stampante 3D usa Marlin come software c'è una variabile, non mi ricordo quale, che conteggia il filamento estruso dal momento dello start stampa, basta inviarla sulla seriale, o visualizzarla sul display, per avere in tempo reale il filamento estruso.

Astro: ... dubbio ... se l'encoder rileva il blocco del filamento e ferma il tutto, la stampante non ha in memoria il punto in cui si e' fermata la stampa ? ... non potrebbe quindi ricominciare da quel layer, magari con una deposizione piu lenta per rifondere lo strato sottostante, e poi proseguire, senza buttare il lavoro ? ... o fin'ora nessun software lo prevede ?

Piu che altro, se non lo prevedono e' perche' non e' fattibile, o perche' nessuno ci ha ancora provato ? ...

Le stampe 3D interrotte per problemi al filamento difficilmente possono essere riprese, quasi mai, sopratutto se c'è un blocco dell'estrusione che richiede un intervento di pulizia manuale con relativo smontaggio del hot end.

Grazie a tutti per le risposte! Il mio obiettivo era cercare di conteggiare i centimetri di filamento consumati dal momento in cui cambio la bobina in modo da sapere, indicativamente, quanto ne ho a disposizione. Penso che si possa trovare una soluzione a livello software sfruttando la scheda della stampante che sicuramente "sa" quanto filo viene estruso man mano. Il problema è che non ho alcun tipo di competenza in questo senso e non saprei come modificare il firmware (Marlin) affinché la stampante invii sull'usb i dati che riguardano il filamento e come modificare Pronterface affinché nell'interfaccia compaia una sezione dove vengono mostrati. È interessante anche la questione del dispositivo che mette in pausa la stampa se il filamento finisce, ma quello è un altro discorso. Più interessante ancora sarebbe un sistema di emergenza che, se viene a mancare la corrente, attivi un gruppo di continuità, metta in pausa la stampa salvando la posizione e permetta il raffreddamento dell'ugello in tutta sicurezza.

Comunque ho ripreso in mano il codice che ho postato all'inizio e l'ho sistemato un po'. Mi piace l'idea di sfruttare finecorsa ottici anche perché ho delle stampanti da buttare e riuscirei a recuperarne qualcuno. Ho fatto delle simulazioni sostituendo i finecorsa con dei pulsanti. Il problema sta nel fatto che quando viene premuto un pulsante, ad esempio quello che funge da finecorsa B, il filo consumato viene incrementato come previsto (Infatti in corrispondenza del finecorsa B il giro del motore viene completato). Tuttavia il consumo continua a salire finché il pulsante resta premuto e ciò non dovrebbe accadere. Quello che mi servirebbe è capire come far sì che aumenti solo quando il pulsante viene rilasciato dopo essere stato premuto.

Etemenanki:

Astro: ... dubbio ... se l'encoder rileva il blocco del filamento e ferma il tutto, la stampante non ha in memoria il punto in cui si e' fermata la stampa ? ... non potrebbe quindi ricominciare da quel layer, magari con una deposizione piu lenta per rifondere lo strato sottostante, e poi proseguire, senza buttare il lavoro ? ... o fin'ora nessun software lo prevede ?

Piu che altro, se non lo prevedono e' perche' non e' fattibile, o perche' nessuno ci ha ancora provato ? ...

... male Etem, molto male, vedo che NON hai letto, sul sito dell'oggetto, come funziona :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes: :stuck_out_tongue_closed_eyes:

Ed in effetti NON ferma la stampante, ma sfrutta un pin per indicargli di andare in "pausa" ... dato che potrebbe benissimo essere finito il filo, essersi spezzato, ecc. ecc. e quindi, con un semplice intervento, la stampa può essere ripresa da dove si è interrotta :grin:

Ovvio che, come nel caso citato da Astro, se ti si intasa l'estrusore o se devi smontare mezza stampante per sistemare la cosa ... beh .. c'è poco da fare :confused:

Guglielmo

Penso di essermi espresso male io ... intendevo proprio un sistema di gestione della posizione per la ripresa della stampa in caso di intasamento ...

Cerco di spiegarmi ... servirebbe probabilmente un sensore di zero preciso (ma mi sembra cghe esistano gia), ed una "zona di lavoro" specifica per la rimozione del fusore ... mettiamo che inizi una stampa, la macchina prima di iniziare memorizza gli assi x, y e z ... inizi la stampa, a meta' si intasa l'ugello, l'encoder rileva il blocco e manda in pausa, ma allo stesso tempo il firmware memorizza le posizioni "relative" dell'ugello in punto di blocco, rispetto allo zero iniziale, poi con un comando apposito sposti la testa nella zona di lavoro, togli l'ugello (o il fusore se e' integrato), pulisci, rimonti, a quel punto ovviamente l'estremita' dell'ugello difficilmente sara' ancora alla stessa altezza della partenza, quindi il firmware dovrebbe rifare gli azzeramenti, poi riportare l'estrusore alla stessa posizione relativa al blocco, relativa ovviamente ai nuovi azzeramenti ...

Teoricamente, la cosa e' possibile, gia la fanno parecchie macchine CNC, in caso di rottura dell'utensile, dopo la sostituzione viene rimisurata l'estremita' dell'utensile e si riparte da li con la nuova misura ... pero' non so se il firmware di una 3D sia in grado di gestire una cosa del genere, e soprattutto se poi la stampa riesca, ovviamente, che sarebbe la cosa importante ...

... si, sicuramente non è difficile da implementare, devi ricordarti dove eri arrivato nel Gcode, la posizione del hot-end e poco più, però ... non so se su qualche stampante sia implementato; avevo forse letto qualche cosa per la Ultimaker 3 ...

Guglielmo

Etemenanki:
a meta' si intasa l'ugello, l'encoder rileva il blocco e manda in pausa,

Se il problema è un intasamento dell'estrusore la stampa è persa, non c'è nulla da fare, questo perché prima che il sistema si accorge che il filamento è bloccato la stampa prosegue per diversi secondi, il blocco non è istantaneo, ed è impossibile fare un fix del punto di ripresa.
Se poi il blocco avviene lentamente, o è un problema di scorrevolezza, ti ritrovi con vari layer stampati male, solo questo fatto basta per far buttare il pezzo.
Se il problema è solo il filamento finito, o spezzato, con la messa in pausa in automatico, comando di cambio filamento e comando di ripresa stampa non perdi nulla.