diff --git a/LICENSE b/LICENSE index e69de29..fca19f4 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Patrick Knöbel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README-BUILD.md b/README-BUILD.md new file mode 100644 index 0000000..ddb4034 --- /dev/null +++ b/README-BUILD.md @@ -0,0 +1,12 @@ +To build the program (with changes to the source): + +- install version 1.8 (aka 8.0) of the `JDK`, (openJDK variants such as [Azul's Zulu JDK](https://www.azul.com/downloads/?package=jdk&show-old-builds=true#zulu) may have better support for modern systems). + +- copy or hardlink `nrjavaserial-3.9.3.jar` and `jssc.jar` to the directory `./dist/lib/` + +- run `ant` from the top level directory of the repo to build the changes, with a command of the form + ``` + ant -Dplatforms.JDK_1.8.home=/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home -Dnb.internal.action.name=build jar + ``` + +this will produce the output jar files in the dist directory. diff --git a/README.md b/README.md index 71c8c13..48b160a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,28 @@ -cncgcodecontroller +CNC-GCode-Controller ================== +If you use a reprap Controller (like Marlin ...) for a CNC machine then this is your Program ;-) -CNC-GCode-Controller +### Features: +* Communication with the Controller over com port +* Basic movements with preview +* Loading cnc files +* Preview of cnc file +* Autoleveling (at this point only for Marlin firmware because of hit endstop message) + * for GRPL you neet to set $10=2 for this to work! +* Optimise G0 movements +* Most commonly used Gcodes are translated for a Reprap Controller (Tested with Marlin) +* Backlash correction +* Artsupport + +### Tutorial Videos: + * [en] https://youtu.be/xxbBipRvp5I + * [de] https://youtu.be/hYSPs9B2VUM + +### Infos: + http://reprap.org/wiki/CNC_Gcode_controller + +![ccgc](https://cloud.githubusercontent.com/assets/5472845/19075920/327ab30e-8a47-11e6-9517-498ba40fde2b.png) +![ccgc2](https://cloud.githubusercontent.com/assets/5472845/19075921/32827026-8a47-11e6-8370-83a8877f99bc.png) +![cncgcode_simplecontrols](https://cloud.githubusercontent.com/assets/7280879/6883509/cc5aa17a-d5b0-11e4-99d4-b629e83e760d.png) +![cnccontroller2](https://f.cloud.github.com/assets/5472845/1229735/47a2a5e4-27c0-11e3-82fe-a572220cfceb.png) +![cnccontroller3](https://f.cloud.github.com/assets/5472845/1229736/47b8d0f8-27c0-11e3-904b-6daddec09239.png) diff --git a/src/cnc/gcode/controller/CNCCommand.java b/src/cnc/gcode/controller/CNCCommand.java index abe731a..c2fc00b 100644 --- a/src/cnc/gcode/controller/CNCCommand.java +++ b/src/cnc/gcode/controller/CNCCommand.java @@ -81,17 +81,28 @@ public class Move private final double[] s; private final double[] e; private double a; + private double spindle; private final Type t; private final boolean xyz; - public Move(double[] s, double[] e, double a, Type t, boolean xyz) { + public Move(double[] s, double[] e, double a, Type t, boolean xyz, double spindle) { this.s = s; this.e = e; this.t = t; this.a = a; this.xyz=xyz; + this.spindle=spindle; } + public Move(double[] s, double[] e, double a, Type t, boolean xyz) { + this.s = s; + this.e = e; + this.t = t; + this.a = a; + this.xyz=xyz; + this.spindle = Double.NaN; + } + public void scalexy(double[] scale){ for(int i=0;i<2;i++){ s[i]=s[i]*scale[i]; @@ -121,6 +132,10 @@ public double getA(){ return a; } + public double getSpindle(){ + return spindle; + } + public double getDistanceXY() { double dx = s[0]- e[0]; @@ -652,13 +667,17 @@ public State calcCommand(Calchelper c) if(move.a!=0){ used=true; } + if(Double.isNaN(move.spindle) == false){ + message += "Spindle speed set"; + used=true; + } if(used == false) { if(state == State.NORMAL) { state = State.WARNING; } - message += "Command without any movment! "; + message += "Command without any movment!"; } if(move.s[2] != move.e[2] && Double.isNaN(move.e[2]) == false) @@ -710,7 +729,11 @@ public Move[] getMoves() case G1: case HOMING: case SETPOS: - moves.add(new Move(Arrays.copyOfRange(cin.axes, 0, 3), Arrays.copyOfRange(cout.axes, 0, 3),p.contains('A')?p.get('A').value:0.0, type,xyzmove)); + if(p.contains('S')){ + moves.add(new Move(Arrays.copyOfRange(cin.axes, 0, 3), Arrays.copyOfRange(cout.axes, 0, 3),p.contains('A')?p.get('A').value:0.0, type,xyzmove, p.get('S').value)); + } else { + moves.add(new Move(Arrays.copyOfRange(cin.axes, 0, 3), Arrays.copyOfRange(cout.axes, 0, 3),p.contains('A')?p.get('A').value:0.0, type,xyzmove)); + } break; case ARC: @@ -933,6 +956,12 @@ String[] execute(Transform t, boolean autoleveling, boolean noshort) { cmd += " " + 'A' + Tools.dtostr(move.a); doMove = true; } + + if(Double.isNaN(move.spindle)==false){ + cmd += " " + 'S' + Tools.dtostr(move.spindle); + doMove = true; + } + if(doMove == false && !Double.isNaN(cin.axes[3]) && !Double.isNaN(cout.axes[3]) && cin.axes[3] == cout.axes[3]) { continue; diff --git a/src/cnc/gcode/controller/DatabaseV2.java b/src/cnc/gcode/controller/DatabaseV2.java index d4c86c1..d976eed 100644 --- a/src/cnc/gcode/controller/DatabaseV2.java +++ b/src/cnc/gcode/controller/DatabaseV2.java @@ -74,6 +74,7 @@ public enum DatabaseV2 { //Communication Type COMTYPE(Communication.MARLIN.toString()), + CSTREAMAHEAD(EOnOff.OFF.name()), //Color Settings: CBACKGROUND(""+Color.WHITE.getRGB()), @@ -86,7 +87,7 @@ public enum DatabaseV2 { ARTSETTINGS((new ArtSettings()).toString()), ; - enum EHoming{ + public enum EHoming{ //Homing Point 0= upper left; 1= upper right; 2= lower left; 3= lower right; UPPER_LEFT, UPPER_RIGHT, @@ -107,7 +108,7 @@ public void set(){ } } - enum EOnOff{ + public enum EOnOff{ ON, OFF; diff --git a/src/cnc/gcode/controller/JPanelAutoLevel.java b/src/cnc/gcode/controller/JPanelAutoLevel.java index 3d61694..07e77cd 100644 --- a/src/cnc/gcode/controller/JPanelAutoLevel.java +++ b/src/cnc/gcode/controller/JPanelAutoLevel.java @@ -891,7 +891,7 @@ protected String doInBackground() throws Exception { if(pos == false) { - throw new MyException("Timeout: No position report!"); + throw new MyException("Timeout: No position report!\nFor GRPL you neet to set $10=2 for this to work!"); } double thitValue = hitvalue; diff --git a/src/cnc/gcode/controller/JPanelSettings.form b/src/cnc/gcode/controller/JPanelSettings.form index d5e1885..1141b3a 100644 --- a/src/cnc/gcode/controller/JPanelSettings.form +++ b/src/cnc/gcode/controller/JPanelSettings.form @@ -18,10 +18,6 @@ - - - - @@ -68,6 +64,7 @@ + @@ -82,6 +79,7 @@ + @@ -89,6 +87,10 @@ + + + + @@ -169,9 +171,12 @@ - + - + + + + @@ -290,6 +295,12 @@ + + + + + + @@ -636,6 +647,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/cnc/gcode/controller/JPanelSettings.java b/src/cnc/gcode/controller/JPanelSettings.java index df1c067..5a84bcd 100644 --- a/src/cnc/gcode/controller/JPanelSettings.java +++ b/src/cnc/gcode/controller/JPanelSettings.java @@ -72,6 +72,7 @@ public void updateGUI(boolean serial, boolean isworking) } jLSmodal.setText(Tools.convertToMultiline("Allow G1: "+DatabaseV2.EOnOff.get(DatabaseV2.G1MODAL).name()+"\nAllow G0: "+DatabaseV2.EOnOff.get(DatabaseV2.G0MODAL).name())); jLSComType.setText(DatabaseV2.COMTYPE.get()); + jLSCStreamAhead.setText(DatabaseV2.CSTREAMAHEAD.get()); jLSCBack.setBackground(new Color(Integer.parseInt(DatabaseV2.CBACKGROUND.get()))); jLSCGrid.setBackground(new Color(Integer.parseInt(DatabaseV2.CGRID.get()))); jLSCGridDis.setText(DatabaseV2.CGRIDDISTANCE.getsaved()>0?""+DatabaseV2.CGRIDDISTANCE.get():"OFF"); @@ -149,6 +150,9 @@ private void initComponents() { jLabel44 = new javax.swing.JLabel(); jBSComType = new javax.swing.JButton(); jLSComType = new javax.swing.JLabel(); + jLabel51 = new javax.swing.JLabel(); + jBSCStreamAhead = new javax.swing.JButton(); + jLSCStreamAhead = new javax.swing.JLabel(); jLabel46 = new javax.swing.JLabel(); jBSCBack = new javax.swing.JButton(); jLSCBack = new javax.swing.JLabel(); @@ -357,6 +361,17 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jLSComType.setText("Settings Text"); + jLabel51.setText("Stream ahead"); + + jBSCStreamAhead.setText("Change"); + jBSCStreamAhead.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jBSettingsActionPerformed(evt); + } + }); + + jLSCStreamAhead.setText("Settings Text"); + jLabel46.setText("Background color:"); jBSCBack.setText("Change"); @@ -451,9 +466,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(jLabel43)) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -498,7 +510,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(jBSCGridDis) .addComponent(jBSCG0) .addComponent(jBSCG1) - .addComponent(jBSCNCAFeedrate))) + .addComponent(jBSCNCAFeedrate) + .addComponent(jBSCStreamAhead))) .addComponent(jLabel44) .addGroup(layout.createSequentialGroup() .addComponent(jBexport) @@ -509,11 +522,15 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(jLabel50) .addComponent(jLabel47) .addComponent(jLabel48) - .addComponent(jLabel45)) + .addComponent(jLabel45) + .addComponent(jLabel51)) .addGap(50, 50, 50) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLSCNCAFeedrate) .addComponent(jLSCNCG0Feedrate))) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(jLabel43)) .addGroup(layout.createSequentialGroup() .addGap(312, 312, 312) .addComponent(jLSCG1)) @@ -576,7 +593,9 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(jLSHomeing)) .addGroup(layout.createSequentialGroup() .addGap(312, 312, 312) - .addComponent(jLSCBack))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLSCStreamAhead) + .addComponent(jLSCBack)))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( @@ -673,6 +692,11 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addComponent(jBSComType) .addComponent(jLSComType)) .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel51) + .addComponent(jBSCStreamAhead) + .addComponent(jLSCStreamAhead)) + .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel46) .addComponent(jBSCBack) @@ -953,6 +977,16 @@ private void jBSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FI DatabaseV2.COMTYPE.set(Communication.values()[options].toString()); } } + + //CStreamAhead + if(evt.getSource() == jBSCStreamAhead) + { + JSettingsDialog.SEnum setting= new JSettingsDialog.SEnum<>("Stream 3 commands ahead:",DatabaseV2.EOnOff.get(DatabaseV2.G1MODAL)); + if(JSettingsDialog.showSettingsDialog("Stream ahead:",new JSettingsDialog.Setting[]{setting})) + { + setting.getValue().set(DatabaseV2.CSTREAMAHEAD); + } + } //Colors if(evt.getSource() == jBSCBack) @@ -1080,6 +1114,7 @@ public String getDescription() private javax.swing.JButton jBSCNCStart; private javax.swing.JButton jBSCNCToolChange; private javax.swing.JButton jBSCNCToolSize; + private javax.swing.JButton jBSCStreamAhead; private javax.swing.JButton jBSComType; private javax.swing.JButton jBSFastFeedrate; private javax.swing.JButton jBSHoming; @@ -1104,6 +1139,7 @@ public String getDescription() private javax.swing.JLabel jLSCNCStart; private javax.swing.JLabel jLSCNCToolChange; private javax.swing.JLabel jLSCNCToolSize; + private javax.swing.JLabel jLSCStreamAhead; private javax.swing.JLabel jLSComType; private javax.swing.JLabel jLSFastFeedrate; private javax.swing.JLabel jLSHomeing; @@ -1132,6 +1168,7 @@ public String getDescription() private javax.swing.JLabel jLabel48; private javax.swing.JLabel jLabel49; private javax.swing.JLabel jLabel50; + private javax.swing.JLabel jLabel51; // End of variables declaration//GEN-END:variables @Override diff --git a/src/cnc/gcode/controller/MainForm.form b/src/cnc/gcode/controller/MainForm.form index fb0300c..8ca0bd8 100644 --- a/src/cnc/gcode/controller/MainForm.form +++ b/src/cnc/gcode/controller/MainForm.form @@ -155,7 +155,11 @@ + + + + diff --git a/src/cnc/gcode/controller/MainForm.java b/src/cnc/gcode/controller/MainForm.java index 7078c08..08de276 100644 --- a/src/cnc/gcode/controller/MainForm.java +++ b/src/cnc/gcode/controller/MainForm.java @@ -64,51 +64,7 @@ public void fired() { //Show Comports/Speeds avilable (Can take secounds to load!) - (new Thread(new Runnable() { - @Override - public void run() { - final ArrayList ports = Communication.getPortsNames(); - if(ports.isEmpty()) - { - ports.add("No serial port found!"); - } - - final ArrayList speeds= Communication.getPortsSpeeds(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - jCBPort.setModel(new DefaultComboBoxModel(ports.toArray(new String[0]))); - jCBSpeed.setModel(new DefaultComboBoxModel(speeds.toArray(new Integer[0]))); - - int index = 0; - //Load last Comport - for (String port:ports) - { - if(port.equals(DatabaseV2.PORT.get())) - { - jCBPort.setSelectedIndex(index); - break; - } - index++; - } - - //Load last Speed - index = 0; - for (Integer speed:speeds) - { - if(speed.toString().equals(DatabaseV2.SPEED.get())) - { - jCBSpeed.setSelectedIndex(index); - break; - } - index++; - } - - jLStatus.setText(Communication.getStatus()); - } - }); - } - })).start(); + updateComportList(); Communication.addChangedEvent(new IEvent() { @Override @@ -210,6 +166,13 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jLStatus.setText("Loading..."); + jCBPort.setToolTipText("Right Click to Refresh"); + jCBPort.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + jCBPortMouseClicked(evt); + } + }); + jLabel6.setText("@"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); @@ -271,7 +234,65 @@ private void jBConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIR DatabaseV2.PORT.set((String)jCBPort.getModel().getSelectedItem()); DatabaseV2.SPEED.set(((Integer)jCBSpeed.getSelectedItem()).toString()); }//GEN-LAST:event_jBConnectActionPerformed + + private void jCBPortMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jCBPortMouseClicked + if(SwingUtilities.isRightMouseButton(evt)){ + jCBPort.setModel(new DefaultComboBoxModel()); + jCBSpeed.setModel(new DefaultComboBoxModel()); + updateComportList(); + } + }//GEN-LAST:event_jCBPortMouseClicked + + private void updateComportList(){ + (new Thread(new Runnable() { + @Override + public void run() { + final ArrayList ports = Communication.getPortsNames(); + if(ports.isEmpty()) + { + ports.add("No serial port found!"); + } + + final ArrayList speeds= Communication.getPortsSpeeds(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + jCBPort.setModel(new DefaultComboBoxModel(ports.toArray(new String[0]))); + jCBSpeed.setModel(new DefaultComboBoxModel(speeds.toArray(new Integer[0]))); + + int index = 0; + //Load last Comport + for (String port:ports) + { + if(port.equals(DatabaseV2.PORT.get())) + { + jCBPort.setSelectedIndex(index); + break; + } + index++; + } + + //Load last Speed + index = 0; + for (Integer speed:speeds) + { + if(speed.toString().equals(DatabaseV2.SPEED.get())) + { + jCBSpeed.setSelectedIndex(index); + break; + } + index++; + } + + jLStatus.setText(Communication.getStatus()); + } + }); + } + })).start(); + + } + // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/src/cnc/gcode/controller/communication/ComCoreJSSC.java b/src/cnc/gcode/controller/communication/ComCoreJSSC.java index 4accf2c..536d230 100644 --- a/src/cnc/gcode/controller/communication/ComCoreJSSC.java +++ b/src/cnc/gcode/controller/communication/ComCoreJSSC.java @@ -4,9 +4,6 @@ */ package cnc.gcode.controller.communication; -import gnu.io.NRSerialPort; -import java.io.InputStream; -import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Timer; diff --git a/src/cnc/gcode/controller/communication/Communication.java b/src/cnc/gcode/controller/communication/Communication.java index 47f134e..c8c73e3 100644 --- a/src/cnc/gcode/controller/communication/Communication.java +++ b/src/cnc/gcode/controller/communication/Communication.java @@ -10,8 +10,6 @@ import cnc.gcode.controller.MyException; import cnc.gcode.controller.ObjectProxy; import cnc.gcode.controller.Tools; -import java.lang.reflect.InvocationTargetException; -import java.text.ParseException; import java.util.ArrayList; import java.util.LinkedList; import java.util.logging.Level; @@ -163,7 +161,7 @@ protected void internal_receive(String line) throws MyException{ } @Override protected boolean internal_isbusy(){ - return cmdHistroy.size() > receiveCount; + return cmdHistroy.size() > (receiveCount +(DatabaseV2.EOnOff.get(DatabaseV2.CSTREAMAHEAD)==DatabaseV2.EOnOff.ON?3:0)); } @Override protected boolean internal_isConnected(){ @@ -309,7 +307,7 @@ protected void internal_receive(String line) throws MyException{ } @Override protected boolean internal_isbusy(){ - return sendcount > resivecount; + return sendcount > (resivecount+(DatabaseV2.EOnOff.get(DatabaseV2.CSTREAMAHEAD)==DatabaseV2.EOnOff.ON?3:0)); } @Override protected boolean internal_isConnected(){ @@ -463,7 +461,7 @@ else if(!initThread.isAlive()) } @Override protected boolean internal_isbusy(){ - return resivecount ==0 || sendcount > resivecount; + return resivecount ==0 || sendcount > (resivecount+(DatabaseV2.EOnOff.get(DatabaseV2.CSTREAMAHEAD)==DatabaseV2.EOnOff.ON?3:0)); } @Override protected boolean internal_isConnected(){ @@ -491,7 +489,7 @@ protected Double[] internal_LocationString(String line){ { Double[] dpos=new Double[3]; for(int i=0;i<3;i++) - dpos[i]=Tools.strtod(line.split(":")[2].split(",")[i]); + dpos[i]=Tools.strtod(line.split("WPos:")[1].split(",")[i]); return dpos; }