我必须编写一个 java 程序,通过网络接收 G-Code 命令并通过串行通信将它们发送到 3D 打印机。原则上一切似乎都很好,只要打印机需要超过 300 毫秒来执行命令。如果执行时间比这短,打印机接收下一个命令需要太多时间,导致命令执行之间出现延迟(打印机喷嘴静止约 100-200 毫秒)。这可能会成为 3D 打印中的一个问题,因此我必须消除这种延迟。
为了比较:像 Repetier Host 或 Cura 这样的软件可以通过 seial 发送相同的命令,在命令执行之间没有任何延迟,所以它必须以某种方式成为可能。
我使用jSerialComm库进行串行通信。
这是向打印机发送命令的线程:
@Override
public void run() {
if(printer == null) return;
log("Printer Thread started!");
//wait just in case
Main.sleep(3000);
long last = 0;
while(true) {
String cmd = printer.cmdQueue.poll();
if (cmd != null && !cmd.equals("") && !cmd.equals("\n")) {
log(cmd+" last: "+(System.currentTimeMillis()-last)+"ms");
last = System.currentTimeMillis();
send(cmd + "\n", 0);
}
}
}
private void send(String cmd, int timeout) {
printer.serialWrite(cmd);
waitForBuffer(timeout);
}
private void waitForBuffer(int timeout) {
if(!blockForOK(timeout))
log("OK Timeout ("+timeout+"ms)");
}
public boolean blockForOK(int timeoutMillis) {
long millis = System.currentTimeMillis();
while(!printer.bufferAvailable) {
if(timeoutMillis != 0)
if(millis + timeoutMillis < System.currentTimeMillis()) return false;
try {
sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
printer.bufferAvailable = false;
return true;
}
这是printer.serialWrite:(Arduino Java Lib的“灵感”)
public void serialWrite(String s){
comPort.setComPortTimeouts(SerialPort.TIMEOUT_SCANNER, 0, 500);
try{Thread.sleep(5);} catch(Exception e){}
PrintWriter pout = new PrintWriter(comPort.getOutputStream());
pout.print(s);
pout.flush();
}
printer
是Printer
实现 的类的对象com.fazecast.jSerialComm.SerialPortDataListener
打印机相关功能
@Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
byte[] newData = new byte[comPort.bytesAvailable()];
int numRead = comPort.readBytes(newData, newData.length);
handleData(new String(newData));
}
private void handleData(String line) {
//log("RX: "+line);
if(line.contains("ok")) {
bufferAvailable = true;
}
if(line.contains("T:")) {
printerThread.printer.temperature[0] = Utils.readFloat(line.substring(line.indexOf("T:")+2));
}
if(line.contains("T0:")) {
printerThread.printer.temperature[0] = Utils.readFloat(line.substring(line.indexOf("T0:")+3));
}
if(line.contains("T1:")) {
printerThread.printer.temperature[1] = Utils.readFloat(line.substring(line.indexOf("T1:")+3));
}
if(line.contains("T2:")) {
printerThread.printer.temperature[2] = Utils.readFloat(line.substring(line.indexOf("T2:")+3));
}
}
Printer.bufferAvailable
被声明为 volatile 我还尝试在另一个线程中阻塞 jserialcomm 的函数,结果相同。我的瓶颈在哪里?我的代码中是否存在瓶颈,或者 jserialcomm 是否会产生太多开销?
对于没有 3d 打印经验的人:当打印机接收到有效命令时,它将将该命令放入内部缓冲区,以最大程度地减少延迟。只要内部缓冲区中有可用空间,它就会以ok
. 当缓冲区已满时,将ok
延迟直到再次有空闲空间。所以基本上你只需要发送一个命令,等待确定,立即发送另一个。