Layer startLayer(float z, Layer prevLayer) { // if (LayerOpen) // return null; // Z-Lift support if (prevLayer != null && z == prevLayer.getZPosition()) return prevLayer; // Layer lay = layer.get(z); Layer lay = null; int fanspeed = 0; float bedtemp = 0; float extemp = 0; float lh = z; if (prevLayer != null) { if (prevLayer.isPrinted()) { lh = (z - prevLayer.getZPosition()); } fanspeed = prevLayer.getFanspeed(); bedtemp = prevLayer.getBedtemp(); extemp = prevLayer.getExttemp(); } lay = new Layer(z, layercount, Constants.round2digits(lh)); lay.setUnit(unit); // remember last unit lay.setFanspeed(fanspeed); lay.setBedtemp(bedtemp); lay.setExttemp(extemp); // layer.put(z, lay); layer.add(lay); layercount++; // System.out.println("Add Layer:"+z); // LayerOpen = true; return lay; }
/** * Main method to walk through the GCODES and analyze them. * * @return */ public void analyze() { Layer currLayer = startLayer(0, null); Layer lastprinted = currLayer; // Current Positions & Speed float xpos = 0; Position currpos = new Position(0, 0); float lastxpos = 0; float lastypos = 0; float lastzpos = 0; boolean pos_changed = false; float ypos = 0; float zpos = 0; float epos = 0; float f_old = 1000; float f_new = f_old; float bedtemp = 0, extemp = 0; boolean m101 = false; // BFB style extrusion float m108 = 0; // Bfb style extr. GCodeStore gcarr = getGcodes(); int gcnum = gcarr.size(); for (int ig = 0; ig < gcnum; ig++) { GCode gc = gcarr.get(ig); lastxpos = xpos; lastypos = ypos; lastzpos = zpos; // Update Speed if specified // TODO Clarify if default speed is the last used speed or not if (gc.isInitialized(Constants.F_MASK)) { if (!gc.isInitialized(Constants.X_MASK) && !gc.isInitialized(Constants.Y_MASK) && !gc.isInitialized(Constants.Z_MASK) || !ACCELERATION) { f_old = gc.getF(); // no movement no acceleration f_new = gc.getF(); // faccel is the same } else { f_new = gc.getF(); // acceleration } } if (gc.getGcode() == Constants.GCDEF.G1 || gc.getGcode() == Constants.GCDEF.G0 || gc.getGcode() == Constants.GCDEF.G2 || gc.getGcode() == Constants.GCDEF.G3) { if (currLayer.highidx - currLayer.lowidx < 5) { // only set layer temp, if not already printed too much currLayer.setBedtemp(bedtemp); currLayer.setExttemp(extemp); } // Detect Layer change and create new layers. if (gc.isInitialized(Constants.Z_MASK) && gc.getZ() != currLayer.getZPosition()) { // endLayer(currLayer); //finish old layer if (currLayer.isPrinted()) { lastprinted = currLayer; } else if (lastprinted != currLayer) { // Assume zlift // Append non printed layers to last printed one // Z-lift would otherwise cause thousands of layers // for (GCode gco : currLayer.getGcodes()) { // lastprinted.addGcodes(gco,ig); // } lastprinted.highidx = ig; // set high index to new index layercount--; layer.remove(currLayer); // Minor problem is that the beginning of a new layer is sometimes without extrusion // before the first z-lift // this leads to assigning this to the previous printed layer. } currLayer = startLayer(gc.getZ(), lastprinted); // Start new layer currLayer.setBedtemp(bedtemp); currLayer.setExttemp(extemp); } float move = 0; // Move G1 - X/Y at the same time if (gc.getGcode() == Constants.GCDEF.G2 || gc.getGcode() == Constants.GCDEF.G3) { // center I&J relative to x&y float cx = (xpos + gc.getIx()); float cy = (ypos + gc.getJy()); float newxpos = gc.isInitialized(Constants.X_MASK) ? gc.getX() : xpos; float newypos = gc.isInitialized(Constants.Y_MASK) ? gc.getY() : ypos; // triangle float bx = (newxpos - cx); float by = (newypos - cy); float ax = (xpos - cx); float ay = (ypos - cy); // Java drawarc is based on a bonding box // Left upper edge of the bounding box float xmove = Math.abs(cx - xpos); float ymove = Math.abs(cy - ypos); // assume a circle (no oval) float radius = ((float) Math.sqrt((xmove * xmove) + (ymove * ymove))); double angle1, angle2; // Calculate right angle if (gc.getGcode() == Constants.GCDEF.G2) { angle1 = Math.atan2(by, bx) * (180 / Math.PI); angle2 = Math.atan2(ay, ax) * (180 / Math.PI); } else { angle2 = Math.atan2(by, bx) * (180 / Math.PI); angle1 = Math.atan2(ay, ax) * (180 / Math.PI); } double angle = (int) (angle2 - angle1); xpos = newxpos; ypos = newypos; // Bogenlaenge move = (float) (Math.PI * radius * angle / 180); gc.setDistance(move); } else if (gc.isInitialized(Constants.X_MASK) && gc.isInitialized(Constants.Y_MASK)) { float xmove = Math.abs(xpos - gc.getX()); float ymove = Math.abs(ypos - gc.getY()); xpos = gc.getX(); ypos = gc.getY(); move = (float) Math.sqrt((xmove * xmove) + (ymove * ymove)); gc.setDistance(move); } else if (gc.isInitialized(Constants.X_MASK)) { move = Math.abs(xpos - gc.getX()); xpos = gc.getX(); gc.setDistance(move); } else if (gc.isInitialized(Constants.Y_MASK)) { move = Math.abs(ypos - gc.getY()); ypos = gc.getY(); gc.setDistance(move); } else if (gc.isInitialized(Constants.E_MASK)) { // Only E means we need to measure the time move = Math.abs(epos - gc.getE()); } else if (gc.isInitialized(Constants.Z_MASK)) { // Only Z means we need to measure the time // TODO if Z + others move together, Z might take longest. Need to add time move = Math.abs(zpos - gc.getZ()); } // update Z pos when Z changed if (gc.isInitialized(Constants.Z_MASK)) { zpos = gc.getZ(); } // Update epos and extrusion, not add time because the actual move time is already added if (gc.isInitialized(Constants.E_MASK)) { if (relativepos) { gc.setExtrusion(gc.getE()); epos = 0; } else { float oldepos = gc.getE(); gc.setExtrusion(gc.getE() - epos); epos = oldepos; } } else if (m101) { float extr = m108 / 60 * (move / (f_new / 60)); // only for direct drive extr. with r=5 // gc.setInitialized(Constants.E_MASK, extr); //commented out to avoid E to be send to the // printer gc.setExtrusion(extr); } if (useAcceleration) { // Calculate time with a linear acceleration if (f_new >= f_old) { // Assume sprinter _MAX_START_SPEED_UNITS_PER_SECOND {40.0,40.0,....} gc.setTimeAccel( move / (((Math.min(40 * 60, f_old) + f_new) / 2) / 60)); // set time with linear acceleration // System.out.println("F"+f_old+"FA"+f_new+"time"+gc.getTime()+"ACCEL: // "+(Math.abs(40-f_new)/gc.getTimeAccel())); } else { gc.setTimeAccel(move / ((f_old + f_new) / 2 / 60)); // set time with linear acceleration // System.out.println("F"+f_old+"FA"+f_new+" DEACCEL: // "+(Math.abs(f_old-f_new)/gc.getTimeAccel())); } } else { // Calculate time without acceleration gc.setTimeAccel(move / (f_new / 60)); // Set time w/o acceleration } f_old = f_new; // acceleration done. assign new speed // Calculate print size // if(gc.isInitialized(Constants.E_MASK) && gc.getE() > 0) { if ((gc.isExtruding() && gc.getDistance() != 0) || m101) { if (pos_changed) { // make sure that the start position is used for the boundary // calculation currLayer.addPosition(lastxpos, lastypos, lastzpos); } currLayer.addPosition(xpos, ypos, zpos); pos_changed = true; } } else if (gc.getGcode() == Constants.GCDEF.G28 || gc.getGcode() == Constants.GCDEF.G92) { // Initialize Axis if (gc.isInitialized(Constants.E_MASK)) epos = gc.getE(); if (gc.isInitialized(Constants.X_MASK)) xpos = gc.getX(); if (gc.isInitialized(Constants.Y_MASK)) ypos = gc.getY(); if (gc.isInitialized(Constants.Z_MASK)) zpos = gc.getZ(); } else if (gc.getGcode() == Constants.GCDEF.G91) { relativepos = true; } else if (gc.getGcode() == Constants.GCDEF.G90) { relativepos = false; } else if (gc.getGcode() == Constants.GCDEF.G20 || gc.getGcode() == Constants.GCDEF.G21) { // Assume that unit is only set once currLayer.setUnit(gc.getUnit()); } else if (gc.getGcode() == Constants.GCDEF.M101) { // bfb style gcode m101 = true; } else if (gc.getGcode() == Constants.GCDEF.M103) { m101 = false; } else if (gc.getGcode() == Constants.GCDEF.T0) { // extruders=Math.max(extruders, 1); } else if (gc.getGcode() == Constants.GCDEF.T1) { extruderCount = Math.max(extruderCount, 2); } else if (gc.getGcode() == Constants.GCDEF.T2) { extruderCount = Math.max(extruderCount, 3); } else if (gc.getGcode() == Constants.GCDEF.T3) { extruderCount = Math.max(extruderCount, 4); } else if (gc.getGcode() == Constants.GCDEF.T4) { extruderCount = Math.max(extruderCount, 5); } else if (gc.getGcode() == Constants.GCDEF.M218 || gc.getGcode() == Constants.GCDEF.G10) { float xoff = 0; float yoff = 0; if (gc.isInitialized(Constants.X_MASK)) xoff = gc.getX(); if (gc.isInitialized(Constants.Y_MASK)) yoff = gc.getY(); int toff = (int) gc.getR(); // T is stored in R field if (extruderOffset == null) extruderOffset = new Position[] {null, null, null, null, null}; // init for 5 extr. if (toff <= 4) { extruderOffset[toff] = new Position(xoff, yoff); } } else if (gc.getGcode() == Constants.GCDEF.M108) { if (gc.isInitialized(Constants.E_MASK)) m108 = gc.getE(); } else if (gc.isInitialized(Constants.SF_MASK)) { // update Fan if specified currLayer.setFanspeed((int) gc.getFanspeed()); } else if (gc.isInitialized(Constants.SE_MASK)) { // update Temperature if specified extemp = gc.getExtemp(); } else if (gc.isInitialized(Constants.SB_MASK)) { // Update Bed Temperature if specified bedtemp = gc.getBedtemp(); } currpos.updatePos(xpos, ypos); // reuse currposs obj, gcode just copies the floats gc.setCurrentPosition(currpos); // Add Gcode to Layer currLayer.addGcodes(gc, ig); } // System.out.println("Summarize Layers"); for (Layer closelayer : layer) { endLayer(closelayer); // finish old layer } // End last layer // endLayer(currLayer); }