ExtruAndWinder/fr
English • العربية • български • català • čeština • Deutsch • Ελληνικά • español • فارسی • français • hrvatski • magyar • italiano • română • 日本語 • 한국어 • lietuvių • Nederlands • norsk • polski • português • русский • Türkçe • українська • 中文(中国大陆) • 中文(台灣) • עברית • azərbaycanca • |
Contents
Introduction
Les machines comme Filabot, Filastruder ou encore Filamaker produise un filament mais n'assure par un filament de diametre constant.
Filastruder propose une seconde machine nommé Filawinder, sont tarif est plutôt abordable. Elle permet d'avoir une certaine constante dans la fabrication du filament.
Apres étude avec TheFredaxe (fas83), du travaille de Hugh Lyman, de Filawinder mais aussi de quelque photo trouvé sur internet de machine induststrielle, je me suis décider à crée une version de cette machine avec des éléments facilement trouvable dans le commerce et communément utilisé dans l'impresion 3D des RepRapeur.
Le filament est extrudé la gravité attire naturelement le filament vers le sol, sur les 50 premier centimetres pas de probleme, puis la masse tire sur le filament et change le diametres du filament. Quand le filament entre en contact avec le sol, la tension redevient plus faible mais cella crée des irégularité dans le filament.
La technique de Fas83 et de la Filawinder pour compenser ce probleme est d'enroulé le filament en continue pour avoir une certaine "tension" et continuité dans la production du filament.
Un autre probléme sur la machine de Filawinder est la régularité dans le moteur d'extrusion. En effet lors de la chauffe de la bande chauffante pour monter à la bonne température le moteur tourne réguliérement, par contre des que la machine est à bonne temperature, le PID maintient la bonne température d'extrusion en stoppant et relancant la chauffe, ce qui à pour effet de faire varié la vitesse du moteur.
Construction de la machine
Cette machine est construite aux maximum avec des éléments facilement trouvable dans le commerce et standardisé (Pas de sur-messure).
La machine est constitué de plusieur ensembles que voici :
- Extrudeuse de filament
- Controleuse de diametre
- Moteur de traction
- Controleur de tension
- Enrouleur de filament
Extrudeuse de filament
L'extrudeuse est constitué de plusieur sous-ensembles :
- Une motorisation
- Le chargement du pellets
- L'entrainement
- La chauffe
- La buse de sortie
BOM
- Téflon (0,95€ chez LeRoyMerlin réf.60029095)
- 2 Raccords Té en laiton à visser F20X27 (5,60€ les 2 chez LeRoyMerlin)
- 1 Mammelons en laiton à visser M20X27 (2,29€ les 2 chez LRM)
- 2 Manchons en laiton à visser F20X27 (4€ les 2 chez LRM)
- 4 Bobine + 2 contre écrous en laiton à visser M20X27 (62€ les 4 chez LRM)
- 2 Mammelons réducteur en laiton à visser M20X27 vers M12X17 (3€ les 2 chez LRM)
- 1 Coude femelle 20x27mm/femelle 20x27mm (3,95€ les 2 chez LRM)
- 1 Bouchons en laiton à visser F12X17 (1.39€ chez LRM réf.65816044)
- Ruban adhésif aluminium (5,1€ chez LRM)
- 1 meche a simple spirale Lewis de 18mm de diamétre et 450 de long (La spirale Lewis est vraiment importante, la longeur aussi) (42,30€ chez www.sesatools.com réf.12010818450)
- 1 PID REX-C100 (En lot avec le SSR sur eBay 14€)
- 1 SSR (En lot avec le PID sur eBay 14€)
- 1m Thermocouple K-type (Doit supporter jusqu'a 300°C (1,7€ sur eBay)
- Bande chauffante (Band Heater) AC 220V 110W 30mmx30mm (5,5€ sur Aliexpress)
- Un planche en bois
- Quellque vise
- Equere (imprimable)
- Isolant (Optionel mais conseiller pour ne pas perdre de la chaleur et avoir une témpérature au mieux stabilisé).
- Moteur, courroie et engrenage à venire
- Ecrous de xxx
- Roulement a bille axiale (5,8€ sur eBay)
Outil :
- 1 foret fer de 2.8mm
- 1 foret fer entre 5 et 8mm
Source
Winder
#include <Servo.h> #include <AccelStepper.h> //https://www.pjrc.com/teensy/td_libs_AccelStepper.html // Décompenter pour debugger //#define DEBUG // Réglage des broches #define NEMA_ENROULEUR_PIN_STEP 11 #define NEMA_ENROULEUR_PIN_DIR 10 #define PIN_ENDSTOP 7 #define PIN_LED 13 int servoAngleMax = 140; // Angle maximum que peux avoir le moteur pour bobiner, ce trouve normalement sur la gauche de la bobine int servoAngleMin = 45; // Angle minimum que peux avoir le moteur pour bobiner, ce trouve normalement sur la droite de la bobine int bobineAnglePremierTour = 125; // Angle que doit avoir le servo pour le premier tour, liér à la position de l'orifice permetant de maintenire le filament // TODO : Verifier que si bobineAnglePremierTour = servoAngleMax ou servoAngleMin cella ne crée pas de BUG dans les calcules float filamentDiametreSouhaiter = 1.70; // En mm int bobineLargeur = 65; // En mm // Variable interne mais a définir pour éviter les beuges // TODO: Trouver une solution a la définition du tableau int interneServoDifferentePosition[38] = {}; // Le chiffre entre [] est à définir par un entier correspondant à (bobineLargeur / filamentDiametreSouhaiter), il faut mieux trop que pas assez int bobineDiametreCentre = 91; // En mm int bobineDiametreExterieur = 200; // En mm int bobineTempsArreter = 5000; // En milliseconde int bobineVitesseMin = 50; // En pas par seconde int bobineTempsInterAcceleration = 2000; // En milliseconde Temps enetre les acceleration int bobineVitesseMax = 150; // En pas par seconde int bobinePasAugmentationVitesse = 10; // En pas par seconde int bobinePremiereDirection = 0; // En regardant la machine du coter de l'arrivé du fil en direction de la bobine, 0 si le trou qui bloque le filament est à gauche, 1 si il est à droite, si le trou est à gauche on bobinera de gauche à droite, sinon l'inverse // (Step par tour d'enrouement est égale à "pas par tour du moteur * démultiplication d'engrenage * résolution du driver (1 = full step, 2 = 1/2 pas, 4 = 1/4 de pas, 8 = 1/8 de pas et 16 = 1/16 de pas)" 200*2.5*4 // L'enregrane actuelle à 21 dents pour la petite roue et 53 pour la grande long enroulementStepParTour = 2000; int tour = 0; AccelStepper nemaEnroulement(1, NEMA_ENROULEUR_PIN_STEP, NEMA_ENROULEUR_PIN_DIR); Servo servoGuide; float interneBobineDernierMillis; // float interneTmpCalcule; // float interneDegreEntreFilament; // int internetLargeurBobineEnDegree; // long interneNemaDernierPositionValideTour = 0; int interneNombreTourSurBobine; // int interneServoPosition; // int interneServoDirection; // int interneEndStopStatue; // Le end stop est il enclencher void setup(void) { interneServoDirection = bobinePremiereDirection; servoGuide.attach(12, 1000, 2000); servoGuide.write(90); nemaEnroulement.setMinPulseWidth(1000); nemaEnroulement.setMaxSpeed(bobineVitesseMax); //Arbitrary value, might want to change it nemaEnroulement.setSpeed(bobineVitesseMin); interneBobineDernierMillis = millis(); pinMode(PIN_ENDSTOP, INPUT); pinMode(PIN_LED, OUTPUT); // Configuration de la broche led en tant que sortie numerique #ifdef DEBUG Serial.begin(115200); #endif // Calcule les differents pas que prendra le servo pour bobiner /**/ interneNombreTourSurBobine = ((bobineLargeur / filamentDiametreSouhaiter)); /**/ internetLargeurBobineEnDegree = servoAngleMax - servoAngleMin; /**/ interneDegreEntreFilament = ((float)internetLargeurBobineEnDegree / ((float)interneNombreTourSurBobine-1)); /**/ /**/ for (int i = 0; i < interneNombreTourSurBobine; i++) { /**/ interneServoDifferentePosition[i] = (int)(servoAngleMin + (i * interneDegreEntreFilament)); /**/ } /**/ /**/ // Definit le pas le plus proche du l'emplacement du début de filament /**/ if(interneServoDirection == 0) { /**/ for(int i = 0; i < interneNombreTourSurBobine; i++) { /**/ if(bobineAnglePremierTour > interneServoDifferentePosition[i]) { /**/ interneServoPosition = i; /**/ } else { /**/ break; /**/ } /**/ } /**/ } else { /**/ for(int i = 0; i < interneNombreTourSurBobine; i++) { /**/ if(bobineAnglePremierTour < interneServoDifferentePosition[i]) { /**/ interneServoPosition = i; /**/ break; /**/ } /**/ } /**/ } // Pause avant le GRAND démarage :) delay(2000); } void loop (void) { #ifdef DEBUG Serial.print("NEMA : \t"); Serial.print(nemaEnroulement.currentPosition()); Serial.print("\t SERVO : \t"); Serial.print(servoGuide.read()); Serial.print("\t DIR : \t"); if(interneServoDirection == 0) { Serial.print("->"); } else { Serial.print("<-"); } Serial.print("\t TOUR : \t "); Serial.print(tour); Serial.print("\t SERVO R : \t "); Serial.print(interneServoPosition); Serial.print("\t NB TOUR : \t "); Serial.print(interneNombreTourSurBobine); Serial.println(); #endif if((interneNemaDernierPositionValideTour + enroulementStepParTour) <= nemaEnroulement.currentPosition()) { interneNemaDernierPositionValideTour = interneNemaDernierPositionValideTour + enroulementStepParTour; if(interneServoDirection == 0) { interneServoPosition--; } else { interneServoPosition++; } if(interneServoPosition < 0) { interneServoPosition = 0; interneServoDirection = !interneServoDirection; } if(interneServoPosition > interneNombreTourSurBobine-1) { interneServoPosition = interneNombreTourSurBobine-1; interneServoDirection = !interneServoDirection; } tour++; } // Partie qui s'occupe de bloquer la roue quand le end-stop est enclenché et reprend de plus en plus rapidement interneEndStopStatue = digitalRead(PIN_ENDSTOP); if(interneEndStopStatue == LOW) { digitalWrite(PIN_LED, LOW); nemaEnroulement.setSpeed(0); interneBobineDernierMillis = millis(); } else { if((nemaEnroulement.speed() < bobineVitesseMin) && (interneBobineDernierMillis+bobineTempsArreter) < millis()) { nemaEnroulement.setSpeed(bobineVitesseMin); interneBobineDernierMillis = millis(); } if(((nemaEnroulement.speed() >= bobineVitesseMin) || (nemaEnroulement.speed() <= bobineVitesseMax)) && (interneBobineDernierMillis+bobineTempsArreter) < millis()) { interneTmpCalcule = nemaEnroulement.speed() + bobinePasAugmentationVitesse; nemaEnroulement.setSpeed(interneTmpCalcule); interneBobineDernierMillis = millis(); } digitalWrite(PIN_LED,HIGH); } // Execution des commandes nemaEnroulement.runSpeed(); servoGuide.write(interneServoDifferentePosition[interneServoPosition]); }
Calibration et élongation
#include <Wire.h> #include <TimerOne.h> #include "Adafruit_LEDBackpack.h" #include "Adafruit_GFX.h" Adafruit_7segment segDiametre = Adafruit_7segment(); Adafruit_7segment segVitesse = Adafruit_7segment(); #define FASTADC 1 // defines for setting and clearing register bits #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #define AOpin 0 // Analog output - yellow #define SIpin 3 // Start Integration - orange #define CLKpin 2 // Clock - red #define NPIXELS 128 // No. of pixels in array byte pixel[NPIXELS]; // Field for measured values <0-255> int noir = 0; int blanc = 0; // directions #define FORWARD HIGH #define BACKWARD LOW // PINs for Pololu controller #define PIN_STEP 5 #define PIN_DIR 4 int vitesse = 300; int vitessePas = 1; int actual_direction; int ticks; int tick_count; int button; int previous_time; int temps_defini = 2000; const int buttonPinMoins = 9; const int buttonPinPlus = 8; int buttonStateMoins = 0, buttonStatePlus = 0; long appuisDebutPlus, appuisDebutMoins, appuisFinPlus, appuisFinMoins, appuisDifferencePlus, appuisDifferenceMoins; void setup(void) { pinMode(SIpin, OUTPUT); pinMode(CLKpin, OUTPUT); digitalWrite(SIpin, LOW); // IDLE state digitalWrite(CLKpin, LOW); // IDLE state // Serial.begin(115200); segDiametre.begin(0x71); segDiametre.setBrightness(1); segDiametre.clear(); segDiametre.print(9999); segDiametre.writeDisplay(); segVitesse.begin(0x70); segVitesse.setBrightness(1); // init the timer1, interrupt every 0.1ms Timer1.initialize(100); Timer1.attachInterrupt(timerIsr); // pins direction pinMode(PIN_STEP, OUTPUT); pinMode(PIN_DIR, OUTPUT); // initial values actual_direction = FORWARD; tick_count = 0; ticks = 0; digitalWrite(PIN_DIR, actual_direction); pinMode(buttonPinPlus, INPUT); pinMode(buttonPinMoins, INPUT); } void loop (void) { // delayMicroseconds(1); /* Integration time in microseconds */ digitalWrite(CLKpin, LOW); digitalWrite(SIpin, HIGH); digitalWrite(CLKpin, HIGH); digitalWrite(SIpin, LOW); // delayMicroseconds(1); for(int i = 0; i < NPIXELS; i++) { pixel[i] = analogRead(AOpin)/4 ; // 8-bit is enough digitalWrite(CLKpin, LOW); // delayMicroseconds(1); digitalWrite(CLKpin, HIGH); } int maxValue, minValue = 0; float maxValue10m, maxValue10p; maxValue = pixel[0]; minValue = pixel[0]; for (int i = 0; i < NPIXELS; i++) { maxValue = max(maxValue, pixel[i]); minValue = min(minValue, pixel[i]); } maxValue10m = maxValue*0.9; maxValue10p = maxValue*1.1; noir = 0; blanc = 0; for(int i = 0; i < NPIXELS; i++) { if(between(pixel[i], maxValue10m, maxValue10p)) { // Serial.print("0"); noir++; } else { // Serial.print("1"); blanc++; } } // Serial.print(" - "); // Serial.print(noir); // Serial.print(" - "); // Serial.print(blanc); // Serial.println(); segDiametre.clear(); segDiametre.print(blanc); segDiametre.writeDisplay(); segVitesse.clear(); segVitesse.print(ticks, DEC); segVitesse.writeDisplay(); buttonStatePlus = digitalRead(buttonPinPlus); buttonStateMoins = digitalRead(buttonPinMoins); if(buttonStatePlus == LOW) { if(appuisDebutPlus == 0) { appuisDebutPlus = millis(); } else { if(appuisDebutPlus < (millis() - 50)) { decrease_speed(); appuisDebutPlus = millis(); } } } if(buttonStateMoins == LOW) { if(appuisDebutMoins == 0) { appuisDebutMoins = millis(); } else { if(appuisDebutMoins < (millis() - 50)) { increase_speed(); appuisDebutMoins = millis(); } } } } boolean between(float x, float mini, float maxi) { if(mini > maxi) { int tmp; tmp = mini; mini = maxi; maxi = tmp; } if (x >= mini && x <= maxi) { return true; } else { return false; } } void increase_speed() { tick_count = 0; vitesse = vitesse + vitessePas; ticks = vitesse; } void decrease_speed() { tick_count = 0; vitesse = vitesse - vitessePas; ticks = vitesse; } void change_direction(int new_direction) { if(actual_direction != new_direction) { actual_direction = new_direction; digitalWrite(PIN_DIR, actual_direction); } } // timer1 interrupt function void timerIsr() { // if(actual_speed == 0) return; tick_count++; if(tick_count == ticks) { // make a step digitalWrite(PIN_STEP, HIGH); digitalWrite(PIN_STEP, LOW); tick_count = 0; } }
Coloration et modification du filament
Colorant alimentaire : La teinte obtenue trop légère, a peine visible dans le filament et invisible une fois imprimé.
Toner d'imprimante : Excellent résultat mais reste translucide
Je vais tester le dioxyde de titane qui à un pouvoir opacifiant ainsi que de la poudre de laiton (risque d’érodé la buse d’impression) mélange de minimum 5g pour 100g.
Pour avoir un effet crais platre, il faut utiliser du mortier ou du pilon, fin dans les deux cas.
Ne pas essayer de mélanger du carbone avec du PLA, ABS, risque d'explosion ! Ne pas essayer le fulmicoton, risque d'explosion, évaluer les risque de la cellulose
Pour aider au dossage du toner dans le but d'avoir une couleur précise utiliser ces cercles chromatique :
Remerciment
Je remercie gaston_ et boboss pour leur soutient et aide.
Je remercie fas83 pour le partage de ces connaisances.
Je remerci Viproz pour l'aide au développement sur Arduino
Je remerci gregorio pour ces informations sur la chimie
Je remerci jerome- du chan IRC irc://irc.freenode.net/arduino-fr
Je remercie l'ensemble des membres du chan IRC irc://irc.freenode.net/reprap-fr
Je remercie xxxx pour la correction de cette article