/** * */ package org.reprap.devices; import java.io.IOException; import org.reprap.Device; import org.reprap.Extruder; import org.reprap.Printer; import org.reprap.Preferences; import org.reprap.ReprapException; import javax.media.j3d.Appearance; import javax.vecmath.Color3f; import javax.media.j3d.Material; /** * @author Adrian * */ public class NullExtruder implements Extruder{ /** * Offset of 0 degrees celcius from absolute zero */ private static final double absZero = 273.15; /** * The temperature to maintain */ private double requestedTemperature = 0; /** * The temperature most recently read from the device */ private double currentTemperature = 0; /** * */ private boolean currentMaterialOutSensor = false; /** * Indicates when polled values are first ready */ private boolean sensorsInitialised = false; /** * */ private Thread pollThread = null; /** * */ private boolean pollThreadExiting = false; /** * */ private int vRefFactor = 7; /** * */ private int tempScaler = 4; /** * Thermistor beta */ private double beta; /** * Thermistor resistance at 0C */ private double rz; /** * Thermistor timing capacitor in farads */ private double cap; /** * Heater power gradient */ private double hm; /** * Heater power intercept * TODO hb should probably be ambient temperature measured at this point */ private double hb; /** * Maximum motor speed (0-255) */ private int maxExtruderSpeed; /** * The actual extrusion speed */ private int extrusionSpeed; /** * The extrusion temperature */ private double extrusionTemp; /** * The extrusion width in XY */ private double extrusionSize; /** * The extrusion height in Z * Should this be a machine-wide constant? - AB */ private double extrusionHeight; /** * The step between infill tracks */ private double extrusionInfillWidth; /** * below this infill finely */ private double lowerFineThickness; /** * Above this infill finely */ private double upperFineThickness; /** * Use this for broad infill in the middle; if negative, always * infill fine. */ private double extrusionBroadWidth; /** * The number of s to cool between layers */ private int coolingPeriod; /** * The speed of movement in XY when depositing */ private int xySpeed; /** * Zero torque speed */ private int t0; /** * Infill speed [0,1]*maxSpeed */ private double iSpeed; /** * Outline speed [0,1]*maxSpeed */ private double oSpeed; /** * Length (mm) to speed up round corners */ private double asLength; /** * Factor by which to speed up round corners */ private double asFactor; /** * Line length below which to plot faster */ private double shortLength; /** *Factor for short line speeds */ private double shortSpeed; /** * The name of this extruder's material */ private String materialType; /** * Number of mm to overlap the hatching infill with the outline. 0 gives none; -ve will * leave a gap between the two */ private double infillOverlap = 0; /** * Where to put the nozzle */ private double offsetX, offsetY, offsetZ; /** * */ private long lastTemperatureUpdate = 0; /** * Flag indicating if initialisation succeeded. Usually this * indicates if the extruder is present in the network. */ private boolean isCommsAvailable = false; /** * The colour black */ protected static final Color3f black = new Color3f(0, 0, 0); /** * The colour of the material to use in the simulation windows */ private Appearance materialColour; /** * Enable wiping procedure for nozzle */ private boolean nozzleWipeEnabled; /** * Co-ordinates for the nozzle wiper */ private double nozzleWipeDatumX; private double nozzleWipeDatumY; /** * X Distance to move nozzle over wiper */ private double nozzleWipeStrokeX; /** * Y Distance to move nozzle over wiper */ private double nozzleWipeStrokeY; /** * Number of wipes per procedure */ private int nozzleWipeFreq; /** * Number of seconds to run to re-start the nozzle before a wipe */ private double nozzleClearTime; /** * Number of seconds to wait after restarting the nozzle */ private double nozzleWaitTime; /** * The number of ms to pulse the valve to open or close it * -ve to supress */ private double valvePulseTime; /** * Start polygons at random perimiter points */ private boolean randSt = false; /** * Start polygons at incremented perimiter points */ private boolean incrementedSt = false; /** * The number of milliseconds to wait before starting a border track */ private double extrusionDelayForLayer = 0; /** * The number of milliseconds to wait before starting a hatch track */ private double extrusionDelayForPolygon = 0; /** * The number of milliseconds to wait before starting a border track */ private double valveDelayForLayer = 0; /** * The number of milliseconds to wait before starting a hatch track */ private double valveDelayForPolygon = 0; /** * The number of mm to stop extruding before the end of a track */ private double extrusionOverRun; /** * The number of mm to stop extruding before the end of a track */ private double valveOverRun; /** * The smallest allowable free-movement height above the base */ private double minLiftedZ = 1; /** * The number of outlines to plot */ int shells = 1; /** * @param prefs * @param extruderId */ public NullExtruder(Preferences prefs, int extruderId) { String prefName = "Extruder" + extruderId + "_"; beta = prefs.loadDouble(prefName + "Beta(K)"); rz = prefs.loadDouble(prefName + "Rz(ohms)"); cap = prefs.loadDouble(prefName + "Capacitor(F)"); hm = prefs.loadDouble(prefName + "hm(C/pwr)"); hb = prefs.loadDouble(prefName + "hb(C)"); maxExtruderSpeed = prefs.loadInt(prefName + "MaxSpeed(0..255)"); extrusionSpeed = prefs.loadInt(prefName + "ExtrusionSpeed(0..255)"); extrusionTemp = prefs.loadDouble(prefName + "ExtrusionTemp(C)"); extrusionSize = prefs.loadDouble(prefName + "ExtrusionSize(mm)"); extrusionHeight = prefs.loadDouble(prefName + "ExtrusionHeight(mm)"); extrusionInfillWidth = prefs.loadDouble(prefName + "ExtrusionInfillWidth(mm)"); lowerFineThickness = prefs.loadDouble(prefName + "LowerFineThickness(mm)"); upperFineThickness = prefs.loadDouble(prefName + "UpperFineThickness(mm)"); extrusionBroadWidth = prefs.loadDouble(prefName + "ExtrusionBroadWidth(mm)"); coolingPeriod = prefs.loadInt(prefName + "CoolingPeriod(s)"); xySpeed = prefs.loadInt(prefName + "XYSpeed(0..255)"); t0 = prefs.loadInt(prefName + "t0(0..255)"); iSpeed = prefs.loadDouble(prefName + "InfillSpeed(0..1)"); oSpeed = prefs.loadDouble(prefName + "OutlineSpeed(0..1)"); asLength = prefs.loadDouble(prefName + "AngleSpeedLength(mm)"); asFactor = prefs.loadDouble(prefName + "AngleSpeedFactor(0..1)"); materialType = prefs.loadString(prefName + "MaterialType(name)"); offsetX = prefs.loadDouble(prefName + "OffsetX(mm)"); offsetY = prefs.loadDouble(prefName + "OffsetY(mm)"); offsetZ = prefs.loadDouble(prefName + "OffsetZ(mm)"); nozzleWipeEnabled = prefs.loadBool(prefName + "NozzleWipeEnabled"); nozzleWipeDatumX = prefs.loadDouble(prefName + "NozzleWipeDatumX(mm)"); nozzleWipeDatumY = prefs.loadDouble(prefName + "NozzleWipeDatumY(mm)"); nozzleWipeStrokeX = prefs.loadDouble(prefName + "NozzleWipeStrokeX(mm)"); nozzleWipeStrokeY = prefs.loadDouble(prefName + "NozzleWipeStrokeY(mm)"); nozzleWipeFreq = prefs.loadInt(prefName + "NozzleWipeFreq"); nozzleClearTime = prefs.loadDouble(prefName + "NozzleClearTime(s)"); nozzleWaitTime = prefs.loadDouble(prefName + "NozzleWaitTime(s)"); randSt = prefs.loadBool(prefName + "RandomStart"); incrementedSt = prefs.loadBool(prefName + "IncrementedStart"); shortLength = prefs.loadDouble(prefName + "ShortLength(mm)"); shortSpeed = prefs.loadDouble(prefName + "ShortSpeed(0..1)"); infillOverlap = prefs.loadDouble(prefName + "InfillOverlap(mm)"); extrusionDelayForLayer = prefs.loadDouble(prefName + "ExtrusionDelayForLayer(ms)"); extrusionDelayForPolygon = prefs.loadDouble(prefName + "ExtrusionDelayForPolygon(ms)"); extrusionOverRun = prefs.loadDouble(prefName + "ExtrusionOverRun(mm)"); valveDelayForLayer = prefs.loadDouble(prefName + "ValveDelayForLayer(ms)"); valveDelayForPolygon = prefs.loadDouble(prefName + "ValveDelayForPolygon(ms)"); valveOverRun = prefs.loadDouble(prefName + "ValveOverRun(mm)"); minLiftedZ = prefs.loadDouble(prefName + "MinimumZClearance(mm)"); // NB - store as 2ms ticks to allow longer pulses valvePulseTime = 0.5*prefs.loadDouble(prefName + "ValvePulseTime(ms)"); shells = prefs.loadInt(prefName + "NumberOfShells(0..N)"); materialColour = getAppearanceFromNumber(extruderId); isCommsAvailable = true; } /** * @return the material type */ public String toString() { return materialType; } /* (non-Javadoc) * @see org.reprap.Extruder#dispose() */ public void dispose() { if (pollThread != null) { pollThreadExiting = true; pollThread.interrupt(); } } /** * Start the extruder motor at a given speed. This ranges from 0 * to 255 but is scaled by maxSpeed and t0, so that 255 corresponds to the * highest permitted speed. It is also scaled so that 0 would correspond * with the lowest extrusion speed. * @param speed The speed to drive the motor at (0-255) * @throws IOException */ public void setExtrusion(int speed) throws IOException { setExtrusion(speed, false); } /** * Start the extruder motor at a given speed. This ranges from 0 * to 255 but is scaled by maxSpeed and t0, so that 255 corresponds to the * highest permitted speed. It is also scaled so that 0 would correspond * with the lowest extrusion speed. * @param speed The speed to drive the motor at (0-255) * @param reverse If set, run extruder in reverse * @throws IOException */ public void setExtrusion(int speed, boolean reverse) throws IOException { // Assumption: Between t0 and maxSpeed, the speed is fairly linear } /** * Open or close the valve. pulseTime is the number of ms to zap it. * @param pulseTime * @param valveOpen * @throws IOException */ public void setValve(boolean valveOpen) throws IOException { } /* (non-Javadoc) * @see org.reprap.Extruder#heatOn() */ public void heatOn() throws Exception { } /** * Set extruder temperature * @param temperature * @throws Exception */ public void setTemperature(double temperature) throws Exception { } /** * Set a heat output power. For normal production use you would * normally call setTemperature, however this method may be useful * for lower temperature profiling, etc. * @param heat Heater power (0-255) * @param maxTemp Cutoff temperature in celcius * @throws IOException */ public void setHeater(int heat, double maxTemp) throws IOException { } /** * Check if the extruder is out of feedstock * @return true if there is no material remaining */ public boolean isEmpty() { return currentMaterialOutSensor; } /* (non-Javadoc) * @see org.reprap.Extruder#getTemperatureTarget() */ public double getTemperatureTarget() { return requestedTemperature; } /* (non-Javadoc) * @see org.reprap.Extruder#getDefaultTemperature() */ public double getDefaultTemperature() { return extrusionTemp; } /* (non-Javadoc) * @see org.reprap.Extruder#getTemperature() */ public double getTemperature() { return currentTemperature; } /** * The the outline speed and the infill speed [0,1] */ public double getInfillSpeed() { return iSpeed; } public double getOutlineSpeed() { return oSpeed; } /** * The length in mm to speed up when going round corners */ public double getAngleSpeedUpLength() { return asLength; } /** * The factor by which to speed up when going round a corner. * The formula is speed = baseSpeed*[1 - 0.5*(1 + ca)*getAngleSpeedFactor()] * where ca is the cos of the angle between the lines. So it goes fastest when * the line doubles back on itself (returning 1), and slowest when it * continues straight (returning 1 - getAngleSpeedFactor()). */ public double getAngleSpeedFactor() { return asFactor; } /* (non-Javadoc) * @see org.reprap.Extruder#setCooler(boolean) */ public void setCooler(boolean f) throws IOException { } /* (non-Javadoc) * @see org.reprap.Extruder#isAvailable() */ public boolean isAvailable() { return isCommsAvailable; } /* (non-Javadoc) * @see org.reprap.Extruder#getXYSpeed() */ public int getXYSpeed() { return xySpeed; } /* (non-Javadoc) * @see org.reprap.Extruder#getExtruderSpeed() */ public int getExtruderSpeed() { return extrusionSpeed; } /* (non-Javadoc) * @see org.reprap.Extruder#getExtrusionSize() */ public double getExtrusionSize() { return extrusionSize; } /* (non-Javadoc) * @see org.reprap.Extruder#getExtrusionHeight() */ public double getExtrusionHeight() { return extrusionHeight; } /** * At the top and bottom return the fine width; in between * return the braod one. If the braod one is negative, just do fine. */ public double getExtrusionInfillWidth(double z, double zMax) { if(z < lowerFineThickness) return extrusionInfillWidth; if(z > zMax - upperFineThickness) return extrusionInfillWidth; if(extrusionBroadWidth < 0) return extrusionInfillWidth; return extrusionBroadWidth; } /* (non-Javadoc) * @see org.reprap.Extruder#getCoolingPeriod() */ public int getCoolingPeriod() { return coolingPeriod; } /* (non-Javadoc) * @see org.reprap.Extruder#getOffsetX() */ public double getOffsetX() { return offsetX; } /* (non-Javadoc) * @see org.reprap.Extruder#getOffsetY() */ public double getOffsetY() { return offsetY; } /* (non-Javadoc) * @see org.reprap.Extruder#getOffsetZ() */ public double getOffsetZ() { return offsetZ; } /* (non-Javadoc) * @see org.reprap.Extruder#getColour() */ public Appearance getAppearance() { return materialColour; } public static int getNumberFromMaterial(String material) { String[] names; try { names = Preferences.allMaterials(); for(int i = 0; i < names.length; i++) { if(names[i].equals(material)) return i; } } catch (Exception ex) { System.err.println(ex.toString()); } return -1; } public static Appearance getAppearanceFromNumber(int n) { String prefName = "Extruder" + n + "_"; Color3f col = null; try { col = new Color3f((float)Preferences.loadGlobalDouble(prefName + "ColourR(0..1)"), (float)Preferences.loadGlobalDouble(prefName + "ColourG(0..1)"), (float)Preferences.loadGlobalDouble(prefName + "ColourB(0..1)")); } catch (Exception ex) { System.err.println(ex.toString()); } Appearance a = new Appearance(); a.setMaterial(new Material(col, black, col, black, 101f)); return a; } public static Appearance getAppearanceFromMaterial(String material) { return(getAppearanceFromNumber(getNumberFromMaterial(material))); } /** * @return determine whether nozzle wipe method is enabled or not */ public boolean getNozzleWipeEnabled() { return nozzleWipeEnabled; } /** * @return the X-cord for the nozzle wiper */ public double getNozzleWipeDatumX() { return nozzleWipeDatumX; } /** * @return the Y-cord for the nozzle wiper */ public double getNozzleWipeDatumY() { return nozzleWipeDatumY; } /** * @return the length of the nozzle movement over the wiper */ public double getNozzleWipeStrokeX() { return nozzleWipeStrokeX; } /** * @return the length of the nozzle movement over the wiper */ public double getNozzleWipeStrokeY() { return nozzleWipeStrokeY; } /** * @return the number of times the nozzle moves over the wiper */ public int getNozzleWipeFreq() { return nozzleWipeFreq; } /** * @return the time to extrude before wiping the nozzle */ public double getNozzleClearTime() { return nozzleClearTime; } /** * @return the time to wait after extruding before wiping the nozzle */ public double getNozzleWaitTime() { return nozzleWaitTime; } /** * Start polygons at a random location round their perimiter * @return */ public boolean randomStart() { return randSt; } /** * Start polygons at a incremented location round their perimiter * @return */ public boolean incrementedStart() { return incrementedSt; } /** * get short lengths which need to be plotted faster * set -ve to turn this off. * @return */ public double getShortLength() { return shortLength; } /** * Factor (between 0 and 1) to use to set the speed for * short lines. * @return */ public double getShortSpeed() { return shortSpeed; } /** * Number of mm to overlap the hatching infill with the outline. 0 gives none; -ve will * leave a gap between the two * @return */ public double getInfillOverlap() { return infillOverlap; } /** * Gets the number of milliseconds to wait before starting a border track * @return */ public double getExtrusionDelayForLayer() { return extrusionDelayForLayer; } /** * Gets the number of milliseconds to wait before starting a hatch track * @return */ public double getExtrusionDelayForPolygon() { return extrusionDelayForPolygon; } /** * Gets the number of milliseconds to wait before opening the valve * for the first track of a layer * @return */ public double getValveDelayForLayer() { return valveDelayForLayer; } /** * Gets the number of milliseconds to wait before opening the valve * for any other track * @return */ public double getValveDelayForPolygon() { return valveDelayForPolygon; } /* (non-Javadoc) * @see org.reprap.Extruder#getExtrusionOverRun() */ public double getExtrusionOverRun() { return extrusionOverRun; } /** * @return the valve overrun in millimeters (i.e. how many mm * before the end of a track to turn off the extrude motor) */ public double getValveOverRun() { return valveOverRun; } /** * The smallest allowable free-movement height above the base * @return */ public double getMinLiftedZ() { return minLiftedZ; } /** * The number of times to go round the outline (0 to supress) * @return */ public int getShells() { return shells; } public void finishedLayer(int layerNumber, Printer printer) throws Exception {} public void betweenLayers(int layerNumber, Printer printer) throws Exception {} public void startingLayer(int layerNumber, Printer printer) throws Exception {} }