3D-принтер Последовательная связь
Я работаю над созданием инструмента, который может общаться с 3D-принтерами в Голанге. Проблема, которая у меня возникла, ставит меня в тупик, похоже, я могу инициировать соединение с принтером. ЖК-экран меняется, код начинает работать, но всякий раз, когда я пытаюсь читать с порта, я ничего не получаю обратно. В частности, они должны возвращать "хорошо" сообщение, поэтому я знаю, чтобы продолжить следующее сообщение. Кроме того, когда я отправляю строки Gcode, кажется, что они их никогда не понимают, насколько я могу судить, они просто отброшены. Вот пример кода, который я использую:
package printer
import (
"errors"
"fmt"
"log"
"strings"
"time"
"io/ioutil"
"path/filepath"
"github.com/tarm/serial"
)
//Printer is a connection to a reprap or similar printer
type Printer struct {
s *serial.Port
}
//Connect creates the printer struct and returns it after initing it
func Connect(port string, speed int64) Printer {
devices, err := getSerialDevices()
if err != nil {
log.Println(err)
}
for _, value := range devices {
log.Println("Found device: ", value)
}
c := &serial.Config{Name: devices[0], Baud: 115200, ReadTimeout: time.Second * 5}
s, err := serial.OpenPort(c)
if err != nil {
log.Println("Failed to open communication")
log.Fatal(err)
}
p := Printer{}
p.s = s
p.readPump()
p.readPump()
return p
}
func (p *Printer) readPump() string {
output := ""
oldLength := -1
for {
buf := make([]byte, 128)
/*
This appears to be where part of the problem is,
I never get anything back from the printer. Per the
tarm documentation since I'm in non-blocking mode
I don't capture the error because it's an EOF
*/
n, _:= p.s.Read(buf)
/*if err != nil {
log.Println("Failed to readPump")
log.Fatal(err)
}*/
output += fmt.Sprintf("%s", buf[:n])
if len(output) == oldLength {
return output
}
oldLength = len(output)
}
}
//SendCommand sends a single GCODE command to the printer
func (p *Printer) SendCommand(g string) error {
g = g + "\n"
_, err := p.s.Write([]byte(g))
if err != nil {
log.Println("Failed to write: ", g)
log.Fatal(err)
}
if !strings.HasSuffix(p.readPump(), "ok\n") {
log.Println(errors.New("command did not complete successfully"))
}
return nil
}
//Retrieve the absolute path for serial devices
func getSerialDevices() ([]string, error) {
log.Println("getting serial devices")
devices, err := ioutil.ReadDir("/dev/serial/by-id")
if err != nil {
log.Println(err)
return nil, err
}
deviceList := make([]string, len(devices))
for index, deviceLink := range devices {
//log.Println("Found device: ", deviceLink.Name())
abs, err := filepath.EvalSymlinks("/dev/serial/by-id/" + deviceLink.Name())
//log.Print("Absolute Device: ")
//log.Println(abs)
deviceList[index] = abs
if err != nil {
log.Println(err)
return nil, err
}
}
return deviceList, nil
}
Вот код, который я использую для вызова принтера:
package main
import (
"fmt"
"log"
"github.com/david-fry/go-3dprinter"
)
func main() {
fmt.Println("Connecting to Printer...")
p := printer.Connect("COM3", 115200)
fmt.Println("Moving Extruder...")
err := p.SendCommand("G28")
err = p.SendCommand("G1 Z20")
err = p.SendCommand("G1 Y100")
err = p.SendCommand("G1 X100")
if err != nil {
log.Fatal(err)
}
fmt.Println("Heating Extruder...")
err = p.SendCommand("M109 S100")
if err != nil {
log.Fatal(err)
}
fmt.Println("Cooling Extruder...")
err = p.SendCommand("M109 S100")
if err != nil {
log.Fatal(err)
}
}
РЕДАКТИРОВАТЬ: Это Wanhao Duplicator 6. Я могу заставить его работать с Cura и Octoprint, так что я уверен, что последовательная связь работает, я просто что-то упустил.
РЕДАКТИРОВАТЬ 2: Еще более загадочным является то, что, если я подключаю IDE Arduino и устанавливаю скорость последовательной передачи данных 250000, он выливает мусор на консоль. Если я закрою это и открою Cura, дайте ему обнаружить принтер, затем закройте Cura и снова откройте консоль, которая, кажется, работает нормально.
1 ответ
На случай, если кто-то столкнется с проблемами при подключении golang к 3D-принтерам, я, наконец, нашел решение. Оказывается, текущая реализация системных вызовов в стандартной библиотеке go не поддерживает скорости передачи данных, не зависящие от спецификации. Большинство 3D-принтеров работают на скорости 250 Кбод, и эта скорость не поддерживается, поэтому она выйдет из строя. Использование пакета, который реализует спецификацию termios2, допускает необычные скорости передачи данных и устраняет проблему. Вот текущая реализация, которую я использую и работает хорошо.