Yosuke Tsuchiya - Fab Futures - Data Science
Home About

Get Prusa 3D Printer Status with Python¶

Still Unstable... need to revise more

Reference:

  • Prusa firmware specific g-code command
  • RepRap G-code Documentation

We can get current printer status with sending G-Code via serial communication.

For example:

  • M105 : Could get Temperture status of the printer
  • M114 : Could get X,Y,Z position and extrusion amount or position of the extruder
  • M155 : Count output Temperature, fan status and position automatically

Connecting my Prusa Core One to my PC, I tried to get the printer status data.

First, import serial library and time library

In [111]:
import serial
import time
from datetime import datetime as dt
import serial.tools.list_ports as list_ports

Then, check the serial port path.

In [112]:
ports = list_ports.comports()

for port,desc,hwid in sorted(ports):
    print(f"{port}: {desc} [{hwid}]")
/dev/cu.AnkerPowerConf: n/a [n/a]
/dev/cu.Bluetooth-Incoming-Port: n/a [n/a]
/dev/cu.debug-console: n/a [n/a]
/dev/cu.usbmodem2101: Original Prusa COREONE [USB VID:PID=2C99:001F SER=13052-4742441644809810 LOCATION=2-1]
/dev/cu.usbserial-5: FT232R USB UART [USB VID:PID=0403:6001 SER=A9085KFP LOCATION=0-1]
/dev/cu.usbserial-A9085KFP: FT232R USB UART [USB VID:PID=0403:6001 SER=A9085KFP LOCATION=0-1]

I found "/dev/cu.usbmodem2101" is the serial port for my Prusa Core One. Then, open the serial port as baudrate 115200

In [113]:
prusa = serial.Serial('/dev/cu.usbmodem2101',115200,timeout=1)
time.sleep(2)
prusa.reset_input_buffer()

I asked ChatGPT as prompt:

I am connecting to the Prusa printer via USB serial. I want to obtain the results of the M114 command, which reports the x, y, z positions every second, and the M105 command, which reports the temperature status.

Then, he showed the code in the following three code.

  • send_gcode: receive the g-code command (M114 or M105) and write it into serial, read the response.
  • parse_temp, parse_position: Printer sometime send information like "busy: processing", those should be dropped here.
  • main function: using try and while loop to get the data.

to debug and modified his code (his code just print the info from the printer, I wanted to save it), currently, I wrote the below code with modifying ChatGPT's suggested.

In [114]:
def send_gcode(command):
    prusa.write((command + "\n").encode("utf-8"))
    prusa.flush()

    lines = []
    while True:
        line = prusa.readline().decode("utf-8").strip()

        if not line:
            break

        if "busy: processing" in line:
            print("Printer is busy:",line)
            continue

        lines.append(line)

        if line == "ok" or line.startswith("ok "):
            break
    
    return lines
In [ ]:
def parse_temp(lines):

    candidate = None

    for line in lines:

        if "busy: processing" in line:
            continue
        if line.startswith("echo:"):
            continue

        if "T:" in line and "B:" in line:
            candidate = line

    if candidate is not None:
        return candidate.lstrip("ok ").strip()

    print("No temp data is found:", lines)
    return None

def parse_position(lines):

    for line in lines:
        if line.startswith("X:"):
            return line.replace("ok ","")
    
    return None
In [116]:
try:
    while True:
        
        ct = dt.now()
        ct_str = ct.strftime('%Y/%m/%d-%H:%M:%S')

        temp_lines = send_gcode("M105")
        temp_data = parse_temp(temp_lines)

        if temp_data is None:
            print("No temp data is found:",temp_lines)
            time.sleep(1.0)
            continue

        pos_lines = send_gcode("M114")
        position_data = parse_position(pos_lines)

        if position_data is None:
            print("No position data is found", pos_lines)
            time.sleep(1.0)
            continue 

        
        writelines_temp = ct_str + " " + temp_data + "\n"
        writelines_position = ct_str + " " + position_data + "\n"

        with open("./printer_data_temp.txt","a") as f:
            f.write(writelines_temp)
        with open("./printer_data_position.txt","a") as f2:
            f2.write(writelines_position)

        #print(writelines)     

        time.sleep(1.0)

except KeyboardInterrupt:
    print("Finish")
Finish

Then, close the serial port.

In [ ]:
# Serial Close
prusa.close()