ExtruAndWinder/fr

From RepRap
Revision as of 12:48, 12 January 2015 by Blumax (talk | contribs) (Coloration et modification du filament)
Jump to: navigation, search


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.


Pourquoi une extrudeuse seul ne remplit pas son role ?
FilaWinder

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 :

  1. Extrudeuse de filament
  2. Controleuse de diametre
  3. Moteur de traction
  4. Controleur de tension
  5. Enrouleur de filament

Extrudeuse de filament

Extrudeuse made in Blumax

L'extrudeuse est constitué de plusieur sous-ensembles :

  1. Une motorisation
  2. Le chargement du pellets
  3. L'entrainement
  4. La chauffe
  5. 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 :


ChromaRVB.jpgChroma100Cyan.jpg

Chroma100Magenta.jpgChroma100Jaune.jpg

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