doufu7835 2018-12-29 22:55
浏览 134

3D打印机串行通讯

I'm working on building a tool that can communication with 3D printers in Golang. The problem that I'm having is stumping me, it seems that I can initiate the connection to the printer. The LCD screen changes, the code starts to run, but whenever I try to read from the port I never get anything back. Specifically they're supposed to return an "ok" message so I know to continue the next message. Additionally when I send the Gcode strings it never seems to understand them, as far as I can tell they're just dropped. Here's the sample code that I'm using:

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 + "
"
    _, err := p.s.Write([]byte(g))
    if err != nil {
        log.Println("Failed to write: ", g)
        log.Fatal(err)
    }
    if !strings.HasSuffix(p.readPump(), "ok
") {
        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
}

Here's the code I'm using to call the printer:

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)
    }

}

EDIT: This is a Wanhao Duplicator 6. I can get it to work with Cura and Octoprint so I'm pretty certain the serial communication works, I'm just missing something.

EDIT2: Even more puzzling is that if I hook up the Arduino IDE and set the serial baud rate to 250000 it spits out garbage to the console. If I close that and open Cura, let it detect the printer, then close Cura and re-open the console it seems to work ok.

  • 写回答

1条回答 默认 最新

  • dongzai2952 2019-01-01 21:53
    关注

    In case anyone stumbles on having trouble connecting golang to 3D printers, I finally found a solution. It turns out that the current implementation of syscalls in the go standard library does not support non-spec baud rates. Most 3D printers operate at 250K baud and this rate is not supported therefore it will fail. Using a package that implements the termios2 specification allows for unusual bit rates and fixes the problem. Here is the current implementation that I'm using and is working well.

    https://github.com/distributed/sers

    评论

报告相同问题?

悬赏问题

  • ¥17 pro*C预编译“闪回查询”报错SCN不能识别
  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向