Skip to content
Snippets Groups Projects
Commit cbb65794 authored by Thomas Oster's avatar Thomas Oster
Browse files

Merge pull request #23 from t-oster/smoothieboard

Smoothieboard Support
parents 0f9646d4 99a72b90
No related branches found
No related tags found
No related merge requests found
This is a library intended to provide suppport This is a library intended to provide suppport
for Lasercutters on any platform. for Lasercutters on any platform.
Currently it supports moste Epilog Lasers Currently it supports most Epilog Lasers,
and the current LAOS board. (www.laoslaser.org). the current LAOS board. (www.laoslaser.org),
the SmoothieBoard (www.smoothieware.org),
generic GRBL based boards,
and some untested work-in-progress drivers like the Roland iModela and the Lasersaur.
It was created for VisiCut (http://visicut.org) It was created for VisiCut (http://visicut.org)
but you are invited to use it for your own programs. but you are invited to use it for your own programs.
......
File added
...@@ -44,6 +44,7 @@ dist.javadoc.dir=${dist.dir}/javadoc ...@@ -44,6 +44,7 @@ dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath= endorsed.classpath=
excludes= excludes=
file.reference.commons-net-3.1.jar=lib/commons-net-3.1.jar file.reference.commons-net-3.1.jar=lib/commons-net-3.1.jar
file.reference.corn-httpclient-1.0.12.jar=lib/corn-httpclient-1.0.12.jar
file.reference.GLPKSolverPack.jar=lib/GLPKSolverPack.jar file.reference.GLPKSolverPack.jar=lib/GLPKSolverPack.jar
file.reference.jna-4.0.0.jar=lib/jna-4.0.0.jar file.reference.jna-4.0.0.jar=lib/jna-4.0.0.jar
file.reference.js.jar=lib/js.jar file.reference.js.jar=lib/js.jar
...@@ -59,7 +60,8 @@ javac.classpath=\ ...@@ -59,7 +60,8 @@ javac.classpath=\
${file.reference.GLPKSolverPack.jar}:\ ${file.reference.GLPKSolverPack.jar}:\
${file.reference.SCPSolver.jar}:\ ${file.reference.SCPSolver.jar}:\
${file.reference.jna-4.0.0.jar}:\ ${file.reference.jna-4.0.0.jar}:\
${file.reference.purejavacomm-0.0.22.jar} ${file.reference.purejavacomm-0.0.22.jar}:\
${file.reference.corn-httpclient-1.0.12.jar}
# Space-separated list of extra javac options # Space-separated list of extra javac options
javac.compilerargs= javac.compilerargs=
javac.deprecation=false javac.deprecation=false
......
/**
* This file is part of LibLaserCut.
* Copyright (C) 2011 - 2014 Thomas Oster <mail@thomas-oster.de>
*
* LibLaserCut is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LibLaserCut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibLaserCut. If not, see <http://www.gnu.org/licenses/>.
*
**/
package com.t_oster.liblasercut;
/**
* The LaserProperty holds all the parameters for parts of the LaserJob.
* The Frequency value is ignored for Engraving operations
*
* @author oster
*/
public class FloatPowerSpeedFocusProperty implements LaserProperty
{
private float power = 20;
private float speed = 100;
private float focus = 0;
public FloatPowerSpeedFocusProperty()
{
}
/**
* Sets the Laserpower. Valid values are from 0 to 100.
* In 3d-Raster mode, the intensity is scaled to this power setting
* @param power
*/
public void setPower(float power)
{
power = power < 0 ? 0 : power;
power = power > 100 ? 100 : power;
this.power = power;
}
public float getPower()
{
return power;
}
/**
* Sets the speed for the Laser. Valid values is from 0 to 100
* @param speed
*/
public void setSpeed(float speed)
{
speed = speed < 0 ? 0 : speed;
speed = speed > 100 ? 100 : speed;
this.speed = speed;
}
public float getSpeed()
{
return speed;
}
/**
* Sets the Focus aka moves the Z axis. Values are given in mm.
* Positive values move the Z axis down aka makes the distance between
* laser and object bigger.
* The possible range depends on the LaserCutter, so wrong setting
* may result in IllegalJobExceptions
* @param focus the relative Distance from object to Laser in mm
*/
public void setFocus(float focus)
{
this.focus = focus;
}
/**
* Returns the relative (to the distance at starting the job) distance
* between laser and object in mm/10s
*/
public float getFocus()
{
return this.focus;
}
@Override
public FloatPowerSpeedFocusProperty clone()
{
FloatPowerSpeedFocusProperty p = new FloatPowerSpeedFocusProperty();
p.focus = focus;
p.power = power;
p.speed = speed;
return p;
}
private static String[] propertyNames = new String[]{"power", "speed", "focus"};
@Override
public String[] getPropertyKeys()
{
return propertyNames;
}
@Override
public Object getProperty(String name)
{
if ("power".equals(name))
{
return (Float) this.getPower();
}
else if ("speed".equals(name))
{
return (Float) this.getSpeed();
}
else if ("focus".equals(name))
{
return (Float) this.getFocus();
}
return null;
}
@Override
public void setProperty(String name, Object value)
{
if ("power".equals(name))
{
this.setPower((Float) value);
}
else if ("speed".equals(name))
{
this.setSpeed((Float) value);
}
else if ("focus".equals(name))
{
this.setFocus((Float) value);
}
else
{
throw new IllegalArgumentException("Unknown setting '"+name+"'");
}
}
@Override
public Object getMinimumValue(String name)
{
if ("power".equals(name))
{
return (Float) 0f;
}
else if ("speed".equals(name))
{
return (Float) 0f;
}
else if ("focus".equals(name))
{
return null;
}
else if ("frequency".equals(name))
{
return null;
}
else
{
throw new IllegalArgumentException("Unknown setting '"+name+"'");
}
}
@Override
public Object getMaximumValue(String name)
{
if ("power".equals(name))
{
return (Float) 100f;
}
else if ("speed".equals(name))
{
return (Float) 100f;
}
else if ("focus".equals(name))
{
return null;
}
else if ("frequency".equals(name))
{
return null;
}
else
{
throw new IllegalArgumentException("Unknown setting '"+name+"'");
}
}
@Override
public Object[] getPossibleValues(String name)
{
return null;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final FloatPowerSpeedFocusProperty other = (FloatPowerSpeedFocusProperty) obj;
if (Float.floatToIntBits(this.power) != Float.floatToIntBits(other.power)) {
return false;
}
if (Float.floatToIntBits(this.speed) != Float.floatToIntBits(other.speed)) {
return false;
}
if (Float.floatToIntBits(this.focus) != Float.floatToIntBits(other.focus)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + Float.floatToIntBits(this.power);
hash = 67 * hash + Float.floatToIntBits(this.speed);
hash = 67 * hash + Float.floatToIntBits(this.focus);
return hash;
}
}
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
*/ */
package com.t_oster.liblasercut; package com.t_oster.liblasercut;
import com.t_oster.liblasercut.platform.Point;
import com.t_oster.liblasercut.platform.Util; import com.t_oster.liblasercut.platform.Util;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
...@@ -173,6 +174,118 @@ public abstract class LaserCutter implements Cloneable, Customizable { ...@@ -173,6 +174,118 @@ public abstract class LaserCutter implements Cloneable, Customizable {
public abstract String getModelName(); public abstract String getModelName();
protected VectorPart convertRasterToVectorPart(RasterPart rp, LaserProperty blackPixelProperty, LaserProperty whitePixelProperty, double resolution, boolean unidirectional)
{
boolean dirRight = true;
Point rasterStart = rp.getRasterStart();
VectorPart result = new VectorPart(blackPixelProperty, resolution);
for (int line = 0; line < rp.getRasterHeight(); line++)
{
Point lineStart = rasterStart.clone();
lineStart.y += line;
//Convert BlackWhite line into line of 0 and 255 bytes
BlackWhiteRaster bwr = rp.image;
List<Byte> bytes = new LinkedList<Byte>();
boolean lookForStart = true;
for (int x = 0; x < bwr.getWidth(); x++)
{
if (lookForStart)
{
if (bwr.isBlack(x, line))
{
lookForStart = false;
bytes.add((byte) 255);
}
else
{
lineStart.x += 1;
}
}
else
{
bytes.add(bwr.isBlack(x, line) ? (byte) 255 : (byte) 0);
}
}
//remove trailing zeroes
while (bytes.size() > 0 && bytes.get(bytes.size() - 1) == 0)
{
bytes.remove(bytes.size() - 1);
}
if (bytes.size() > 0)
{
if (dirRight)
{
//move to the first nonempyt point of the line
result.moveto(lineStart.x, lineStart.y);
byte old = bytes.get(0);
for (int pix = 0; pix < bytes.size(); pix++)
{
if (bytes.get(pix) != old)
{
if (old == 0)
{//beginning of "black" segment -> move with 0 power
result.setProperty(whitePixelProperty);
result.lineto(lineStart.x + pix, lineStart.y);
}
else
{//end of "black" segment -> move with power to pixel before
result.setProperty(blackPixelProperty);
result.lineto(lineStart.x + pix - 1, lineStart.y);
}
old = bytes.get(pix);
}
}
result.setProperty(blackPixelProperty);
result.lineto(lineStart.x + bytes.size() - 1, lineStart.y);
}
else
{
//move to the last nonempty point of the line
result.moveto(lineStart.x + bytes.size() - 1, lineStart.y);
byte old = bytes.get(bytes.size() - 1);
for (int pix = bytes.size() - 1; pix >= 0; pix--)
{
if (bytes.get(pix) != old || pix == 0)
{
if (old == 0)
{
result.setProperty(whitePixelProperty);
result.lineto(lineStart.x + pix, lineStart.y);
}
else
{
result.setProperty(blackPixelProperty);
result.lineto(lineStart.x + pix + 1, lineStart.y);
}
old = bytes.get(pix);
}
}
//last pixel is always black (white pixels are stripped before)
result.setProperty(blackPixelProperty);
result.lineto(lineStart.x, lineStart.y);
}
}
if (!unidirectional)
{
dirRight = !dirRight;
}
}
return result;
}
/**
* Intented for use in the clone mehtod. Copies all properties
* of that to this
* @param that
*/
protected void copyProperties(LaserCutter that)
{
for (String prop : that.getPropertyKeys())
{
setProperty(prop, that.getProperty(prop));
}
}
@Override @Override
public abstract LaserCutter clone(); public abstract LaserCutter clone();
} }
...@@ -45,7 +45,10 @@ public class LibInfo ...@@ -45,7 +45,10 @@ public class LibInfo
Dummy.class, Dummy.class,
IModelaMill.class, IModelaMill.class,
SampleDriver.class, SampleDriver.class,
ExportSVG.class ExportSVG.class,
GenericGcodeDriver.class,
SmoothieBoard.class,
Marlin.class
}; };
} }
} }
This diff is collapsed.
/**
* This file is part of LibLaserCut.
* Copyright (C) 2011 - 2014 Thomas Oster <mail@thomas-oster.de>
*
* LibLaserCut is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LibLaserCut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibLaserCut. If not, see <http://www.gnu.org/licenses/>.
*
**/
package com.t_oster.liblasercut.drivers;
import com.t_oster.liblasercut.drivers.GenericGcodeDriver;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* This class implements a driver for the laser cutter fork of Marlin.
*
* @author quillford
*/
public class Marlin extends GenericGcodeDriver {
public Marlin()
{
//set some Marlin specific defaults
setIdentificationLine("start");
setWaitForOKafterEachLine(true);
setBaudRate(115200);
setLineend("CRLF");
setInitDelay(0);
setPreJobGcode(getPreJobGcode()+",G28 XY,M5");
setPostJobGcode(getPostJobGcode()+",M5,G28 XY");
setSerialTimeout(35000);
//Marlin has no way to upload over the network so remove the upload url text
setHttpUploadUrl("");
setHost("");
}
@Override
public String getIdentificationLine()
{
return("start");
}
@Override
public String[] getPropertyKeys()
{
List<String> result = new LinkedList<String>();
result.addAll(Arrays.asList(super.getPropertyKeys()));
result.remove(GenericGcodeDriver.SETTING_IDENTIFICATION_STRING);
result.remove(GenericGcodeDriver.SETTING_WAIT_FOR_OK);
result.remove(GenericGcodeDriver.SETTING_LINEEND);
result.remove(GenericGcodeDriver.SETTING_INIT_DELAY);
result.remove(GenericGcodeDriver.SETTING_HTTP_UPLOAD_URL);
result.remove(GenericGcodeDriver.SETTING_HOST);
return result.toArray(new String[0]);
}
/**
* Waits for the Identification line and returns null if it's alright
* Otherwise it returns the wrong line
* @return
* @throws IOException
*/
@Override
protected String waitForIdentificationLine() throws IOException
{
if (getIdentificationLine() != null && getIdentificationLine().length() > 0)
{
String line = waitForLine();
if (line.startsWith(getIdentificationLine()))
{//we received the identification line ("start"), now we have to skip the rest of Marlin's dump
while(!(waitForLine().startsWith("echo:SD")))
{
//do nothing and wait until Marlin has dumped all of the settings
}
return null;
}
}
return null;
}
@Override
public String getModelName()
{
return "Marlin";
}
@Override
public Marlin clone()
{
Marlin clone = new Marlin();
clone.copyProperties(this);
return clone;
}
}
\ No newline at end of file
/**
* This file is part of LibLaserCut.
* Copyright (C) 2011 - 2014 Thomas Oster <mail@thomas-oster.de>
*
* LibLaserCut is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LibLaserCut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibLaserCut. If not, see <http://www.gnu.org/licenses/>.
*
**/
package com.t_oster.liblasercut.drivers;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* This class implements a driver for SmoothieBoard.
*
* @author Thomas Oster <mail@thomas-oster.de>
*/
public class SmoothieBoard extends GenericGcodeDriver {
public SmoothieBoard()
{
//set some smoothie-specific defaults
setIdentificationLine("Smoothie");
setWaitForOKafterEachLine(true);
setBaudRate(115200);
setLineend("CRLF");
setInitDelay(0);
setPreJobGcode(getPreJobGcode()+",M3");
setPostJobGcode(getPostJobGcode()+",M5");
}
@Override
public String getIdentificationLine()
{
if (getHost() == null || "".equals(getHost()))
{
return "Smoothie";
}
else
{
return "Smoothie command shell";
}
}
@Override
protected String waitForLine() throws IOException
{
String line = super.waitForLine();
//The telnet interface for smoothie prepends lines with '> '
if (getHost() != null && !"".equals(getHost()) && line.startsWith("> "))
{
return line.substring(2);
}
return line;
}
@Override
public String[] getPropertyKeys()
{
List<String> result = new LinkedList<String>();
result.addAll(Arrays.asList(super.getPropertyKeys()));
result.remove(GenericGcodeDriver.SETTING_IDENTIFICATION_STRING);
result.remove(GenericGcodeDriver.SETTING_WAIT_FOR_OK);
result.remove(GenericGcodeDriver.SETTING_BAUDRATE);
result.remove(GenericGcodeDriver.SETTING_LINEEND);
result.remove(GenericGcodeDriver.SETTING_INIT_DELAY);
return result.toArray(new String[0]);
}
@Override
public String getModelName()
{
return "Smoothie Board";
}
@Override
public SmoothieBoard clone()
{
SmoothieBoard clone = new SmoothieBoard();
clone.copyProperties(this);
return clone;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment