我正在做一个延长的周末项目,我想看看我是否可以通过串行端口和 C# 从我的 Windows PC 发送和打印 GCODE 文件。
我正在连接打印机,但在尝试写入串行流时我没有得到一致的结果。我什至不确定我的串行端口设置是否正确,例如,我找不到任何关于 OctoPrint 如何连接到我的打印机的好例子。我认为我的问题是我一次发送了太多数据,但我也在努力从串行连接中读取并等待“确定”,因为它们似乎出现故障。
我可以连接并发送单线,没问题。一旦我给它一个包含许多行的整个文件,打印机就会到达文件的各个部分并挂起。
如何通过串行端口将大文件传输到 3D 打印机而不会使打印机内部缓冲区过载?
我使用的代码:
private static async Task Main(string[] args)
{
var ports = SerialPort.GetPortNames();
if (!ports.Any())
{
Console.WriteLine("No ports found");
Console.WriteLine("Press any key to continue...");
Console.WriteLine();
Console.ReadKey();
}
else
{
using (SerialPort mySerialPort = new SerialPort(ports.First()))
{
mySerialPort.BaudRate = 115200;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.Open();
mySerialPort.DataReceived += DataRecieved;
using (var fileToPrint = File.OpenRead({Path to GCODE file})
using (var lineReader = new StreamReader(fileToPrint))
{
while (!lineReader.EndOfStream && lineReader is not null)
{
var line = await lineReader.ReadLineAsync() ?? string.Empty;
if (!line.StartsWith(";"))
{
var cleanLine = line. Split(";").First().Trim();
mySerialPort.WriteLine(cleanLine);
}
}
}
Console.WriteLine("Press any key to continue...");
Console.WriteLine();
Console.ReadKey();
mySerialPort.Close();
}
}
}
private static void DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
var line = sp.ReadLine();
Console.WriteLine("Data from printer: {0}", line);
}
为我解决这个问题的代码:
具体来说:
需要改进的地方:
internal class Program
{
private static AutoResetEvent okWaiter = new AutoResetEvent(false);
private static async Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
// Starting application
Log.Information("Application starting...");
try
{
var ports = SerialPort.GetPortNames();
if (!ports.Any())
{
Log.Error("No ports found");
Log.Information("Press any key to continue...");
Console.ReadKey();
}
else
{
using (SerialPort printer = new SerialPort(ports.First()))
{
printer.BaudRate = 115200;
printer.Parity = Parity.None;
printer.StopBits = StopBits.One;
printer.DataBits = 8;
printer.Handshake = Handshake.None;
printer.Open();
printer.DataReceived += DataReceived;
var sender = Task.Factory.StartNew(() =>
{
okWaiter.Set();
using (var fileToPrint = File.OpenRead({Path to GCODE}))
using (var lineReader = new StreamReader(fileToPrint))
{
while (!lineReader.EndOfStream && lineReader is not null)
{
var line = lineReader.ReadLine() ?? string.Empty;
if (!line.StartsWith(";"))
{
var cleanLine = line.Split(";").First().Trim();
okWaiter.WaitOne();
Log.Information("Sending: {gcode}", cleanLine);
printer.WriteLine(cleanLine);
}
}
}
Log.Information("Print complete");
});
Log.Information("Press any key to continue...");
Console.ReadKey();
printer.Close();
}
}
}
catch (Exception e)
{
Log.Error(e, "Application error");
}
finally
{
// Closing application
Log.Information("Application closing...");
await Log.CloseAndFlushAsync();
}
}
private static void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
using (var textReader = new StreamReader(sp.BaseStream))
{
while (!textReader.EndOfStream)
{
var line = textReader.ReadLine() ?? "";
Log.Information("Response: {response}", line);
if (line.StartsWith("T:"))
{
var pattern = @"\d+\.\d{1,2}";
var temps = line.Split(" ");
var nozzleTemp = Regex.Match(temps.First(), pattern);
var bedTemp = Regex.Match(temps.Last(), pattern);
Console.Title = $"Extruder {nozzleTemp} Bed {bedTemp}";
}
if (line == "ok")
{
okWaiter.Set();
}
}
}
}
}