3D printing

How to install OctoScreen plugin for OctoPrint

OctoScreen provides a plugin that you can use within OctoPrint to configure the UI. You can find it on GitHub here, but you can simply install it using the OctoPrint plugin manager using the following URL:



Posted by Uli Köhler in 3D printing

How to change OctoScreen minimum extrusion temperature


When trying to extrude low-temperature filaments using OctoScreen, you will see this error message:

The temperature of the hotend is too low to extrude. Please increase the temperature and try again

By default, OctoScreen has a minimum extrusion temperature of 150°C which is fine for PLA, but  for some low temperature materials you need to change the hardcoded value.

Note that setting you minimum extrusion temperature too low might damage or even destroy your extruder, if the material is not properly melted. So take caution in setting the correct value here.


Open utils/tools.go and edit this line:


Just set your desired temperature and then recompile (see the OctoScreen README on how to do that)

Note that often the firmware (like Marlin) has a separate cold extrusion prevention limit, so you need to change the limit in both OctoScreen and the firmware. For Marlin, see How to disable Marlin cold extrusion prevention via G-Code.


Posted by Uli Köhler in 3D printing, Embedded, Raspberry Pi

How to auto-reset Marlin after Kill

Under certain critical circumstances like thermal runaway protection, Marlin entered a killed state. You typically need to hard-reset the mainboard after entering that state. However, in environments where physical access to the machine, hard-resetting Marlin is not possible, so you might need to implement.

Note that diagnosing & fixing the underlying issue that caused the reset is extremely important and ignoring it might lead to further issues, up to a fire hazard or the destruction of the printer. So be sure to know what you are doing before just.

The following guide was tested with Marlin It should work with most Marlin 2.x versions with minor adjustments.

First, note that as an alternative to hard-resetting the mainboard there is the SOFT_RESET_ON_KILL option which allows you to trigger a soft reset out of kill mode using a button connected to a pin. We won’t delve into more detail on this, since it doesn’t really change the requirement for physical access to the printer.

Open Marlin/src/MarlinCore.cpp and find the minkill(bool) function.

At the end, this function contains a preprocessor-controlled branch of the following structure:

  // Branch 1 ...
  // Branch 2 ...

We will replace this entire branch by these lines:

// Wait for 5 seconds for controller to catch up
for (int i = 5000; i--;) { DELAY_US(1000); watchdog_refresh(); } // 5000*1ms = 3s
// Auto-reset after kill

I prefer to insert the 5-second delay into the reboot logic so no superordinate controller (like a Raspberry Pi running OctoPrint) can miss that the Marlin board has been killed. Although most controllers should be able to detect the killed state from the G-Code, this 5-second delay will simulate the default behaviour of not resetting at all after the killed state has been reached. However note that in case you absolutely need to reset ASAP after the kill state has been reached, it’s typically safe to omit the wait loop.

Posted by Uli Köhler in 3D printing, Embedded

Implementing STM32 DFU bootloader firmware upgrade in Marlin using M997

Marlin implements the M997 command which is intended to switch the mainboard into a firmware upgrade mode.

All STM32 variants have an integrated (hard-coded – so no need to flash it yourself) bootloader that is notoriously difficult to active.

However, Marlin implements M997 on the STM32 as just a reboot:

void flashFirmware(const int16_t) { HAL_reboot(); }

This only works if you are using a custom bootloader on your board – however, it does not use the STM32 integrated bootloader.

The following code was tested on the STM32F446 (BigTreeTech Octopus V1) but should work on any STM32 variant. It is based on previous work by Dave Hyland on StackOverflow. Replace the default flashFirmware() function in Marlin/src/HAL/STM32/HAL.cpp

void flashFirmware(const int16_t) {


    // arm-none-eabi-gcc 4.9.0 does not correctly inline this
    // MSP function, so we write it out explicitly here.
    //__set_MSP(*((uint32_t*) 0x00000000));
    __ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp");

    ((void (*)(void)) *((uint32_t*) 0x00000004))();

    // This will never be executed

Note that we left a HAL_reboot() call as a safeguard at the end, just in case the previous calls fail.

On my BigTreeTech Octopus V1 (STM32F446), by using this code, you can successfully enter the integrated DFU bootloader.

Also see our previous posts on how to use the STM32 in DFU bootloader mode:

Posted by Uli Köhler in 3D printing, C/C++, STM32

M206 Set home offset: Positive or negative coordinates? A simple rule for Marlin

When adjusting the home offset (most often the Z offset) of a 3D printer using the M206 command, many users wonder which sign to use. In other words, in order to move the nozzle 0.1mm closer to the bed, do you use M206Z0.1 or M206Z-0.1. However, there’s a simple rule:

To move the nozzle closer to the bed, use positive coordinates, e.g. M206Z0.1 to move the nozzle 0.1mm closer to the print bed.

To move the nozzle further away from the bed, use negative coordinates, e.g. M206Z-0.2 to move the nozzle 0.2mm further away from the print bed.


Posted by Uli Köhler in 3D printing

How to run single command on 3D printer using picocom

In our previous post How to connect to your 3D printer using picocom we showed how to open an interactive serial session on the command line using picocom. But you can also use picocom to run just a single command such as the M997 firmware update command:

echo "M997" | picocom -b 115200 /dev/ttyACM0 --imap lfcrlf --echo

If your USB serial device is named /dev/ttyUSB0 instead of /dev/ttyACM0 you can use this alternative version:

echo "M997" | picocom -b 115200 /dev/ttyACM0 --imap lfcrlf --echo



Posted by Uli Köhler in 3D printing, Linux

How to home only ONE axis in Marlin

In the Marlin 3D printer firmware, you can home one axis without homing the other axes using G28[Axis].

In order to home the X axis:


In order to home the Y axis:


In order to home the Z axis:


Homing X & Y without homing Z

You can also home multiple axes using G28[Axis 1][Axis 2]. So in order to home the X and the Y axis (but not home the Z axis), run



Posted by Uli Köhler in 3D printing

How to flash Marlin on BigTreeTech Octopus V1 using debug adapter

In order to flash the Bigtreetech Octopus V1 using my STLinkv2 debug adapter, I needed. First we need to note that the first 32k of flash memory are occupied by the bootloader (0x08000000 to 0x08008000). So we need to flash the firmware at address 0x08008000. By default, this is not configured correctly in Marlin.

Open ini/stm32f4.ini and edit the [env:BIGTREE_OCTOPUS_V1]:

platform           = ${common_stm32.platform}
extends            = stm32_variant
board              = marlin_BigTree_Octopus_v1
board_build.offset = 0x8000
board_upload.offset_address = 0x08008000
build_flags        = ${stm32_variant.build_flags}
                     -DSTM32F446_5VX -DUSE_USB_HS_IN_FS
upload_protocol = stlink

Note that you absolutely need to re-flash the bootloader in case you accidentally flashed with the old configuration. Follow the official documentation in order to flash the bootloader. I flash usin STM32CubeProgrammer 2.7.0 (2.8.0 does not work) on both Linux and Windows.

The [env:BIGTREE_OCTOPUS_V1_USB] will be updated automatically as it includes [env:BIGTREE_OCTOPUS_V1]

Posted by Uli Köhler in 3D printing, Electronics, STM32

How to turn case light on/off in Marlin using G-Code

In order to turn the case light on in Marlin, use M355S1P255is full brightness:


In order to turn the case light off, use S0


In order to turn it on at half brightness, use P128



Posted by Uli Köhler in 3D printing, Electronics

How to autotune Marlin Hotend/Extruder PID parameters

In order to autotune the extruder E0 hotend in Marlin, use



  • M303: Autotune PID
  • E0 tune extruder E0 (this is the only extruder on single-extruder printers)
  • C5: Perform 5 cycles (one cycle: heat up to the specified temperature, then cool down to room temperature)
  • S210: Tune at a temperature of 210°C

I always recommend to tune at whatever temperature you use most (e.g. if you want to print mostly PLA at 185°C, use S185 instead of S210 in the command). Tuning at the correct temperature will increase the accuracy of the system.

Regarding the number of cycles, C3 = 3 cycles is mostly for quick tuning. Since heating up and cooling down takes a long time, but doing many cycles increases the accuracy of the tuning. Typical values are:

  • C1: Tuning mostly just for testing, for example if you have modified your extruder hardware
  • C3: Really quick tuning
  • C5: “Standard” tuning
  • C8: Thorough tuning
Posted by Uli Köhler in 3D printing, Electronics

Where to enable extruder-temperature controlled fans in Marlin?

In order to enable a fan in Marlin that is controlled automatically based on the extruder temperature (read: If the extruder is hot, turn on the fan), open Configuration_adv.h and look for the Extruder cooling fans section and set for example E0_AUTO_FAN_PIN to whatever pin you want to be automatically controlled.

 * Extruder cooling fans
 * Extruder auto fans automatically turn on when their extruders'
 * temperatures go above EXTRUDER_AUTO_FAN_TEMPERATURE.
 * Your board's pins file specifies the recommended pins. Override those here
 * or set to -1 to disable completely.
 * Multiple extruders can be assigned to the same pin in which case
 * the fan will turn on when any selected extruder is above the threshold.
#define E0_AUTO_FAN_PIN PA_8
#define E1_AUTO_FAN_PIN -1
#define E2_AUTO_FAN_PIN -1
#define E3_AUTO_FAN_PIN -1
#define E4_AUTO_FAN_PIN -1
#define E5_AUTO_FAN_PIN -1
#define E6_AUTO_FAN_PIN -1
#define E7_AUTO_FAN_PIN -1
#define COOLER_FAN_PIN -1


Posted by Uli Köhler in 3D printing, Electronics

How to fix Pronterface/Printrun UnicodeDecodeError: ‘utf-8’ codec can’t decode byte … in position …: invalid continuation byte


When starting Pronterface / Printrun on Linux using pronterfaceprintrunpython3 pronterface.py or similar, you see an error message like

Traceback (most recent call last):
  File "pronterface.py", line 62, in <module>
    app = PronterApp(False)
  File "/home/uli/dev/tools/Printrun/printrun/pronterface.py", line 2464, in __init__
    self.mainwindow = PronterWindow(self)
  File "/home/uli/dev/tools/Printrun/printrun/pronterface.py", line 170, in __init__
  File "/home/uli/dev/tools/Printrun/printrun/pronsole.py", line 786, in parse_cmdline
  File "/home/uli/dev/tools/Printrun/printrun/pronterface.py", line 1031, in process_cmdline_arguments
    pronsole.pronsole.process_cmdline_arguments(self, args)
  File "/home/uli/dev/tools/Printrun/printrun/pronsole.py", line 769, in process_cmdline_arguments
  File "/home/uli/dev/tools/Printrun/printrun/pronsole.py", line 664, in load_default_rc
  File "/home/uli/dev/tools/Printrun/printrun/pronsole.py", line 632, in load_rc
    for rc_cmd in rc:
  File "/usr/lib/python3.8/codecs.py", line 714, in __next__
    return next(self.reader)
  File "/usr/lib/python3.8/codecs.py", line 645, in __next__
    line = self.readline()
  File "/usr/lib/python3.8/codecs.py", line 558, in readline
    data = self.read(readsize, firstline=True)
  File "/usr/lib/python3.8/codecs.py", line 504, in read
    newchars, decodedbytes = self.decode(data, self.errors)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd3 in position 4: invalid continuation byte


When you see this error message, typically your pronsolerc is corrupted. In order to remove it,

rm -rf ~/.config/Printrun
Posted by Uli Köhler in 3D printing, Python

How to disable Marlin cold extrusion prevention via G-Code

If you want to test your extruder, you can disable cold extrusion prevention using M302:

M302 P1

Re-enable with

M302 P0

Set the temperature (and enable) using

M302 P0 S170

In order to report the current status, run


Example output if disabled:

echo:Cold extrudes are disabled (min temp 170C)

Example output if enabled:

echo:Cold extrudes are enabled (min temp 170C)

Whatever you configure will not persist after reboot. In case you want to save the settings to EEPROM in order to persist after reboot, run

Posted by Uli Köhler in 3D printing, Electronics

How to unpause Marlin after M0/M1 echo:busy: paused for user

In Marlin, you can pause the firmware using M0 or M1 which will cause the firmware to loop-print

echo:busy: paused for user
echo:busy: paused for user
echo:busy: paused for user
echo:busy: paused for user
echo:busy: paused for user
echo:busy: paused for user

In order to continue or unpause, use



Posted by Uli Köhler in 3D printing

How to reboot Marlin using G-Code

On most Marlin boards, you can use M997 to reboot/restart the microcontroller:


While this is technically the command to update the firmware, on most boards this is implemented by a simple reboot, which will load the bootloader which could update the firmware e.g. if there is a firmware.bin file on the SD card. Since unless a firmware update is intended there is no such file on the SD card, the M997 command will just reboot the board.

Posted by Uli Köhler in 3D printing

How to get or set Trinamic TMC stepper motor current in Marlin firmware

In Marlin, you can dynamically configure the stepper motor current for Trinamic stepper drivers like the TMC2208 or the TMC5160.

Changing the motor current via G-Code

The easiest option is by using G-Codes. In order to set the stepper motor current for X , Y and Z to 2 Amperes (2000 mA), use M906 like this:


Now save the settings to the EEPROM using


You can also query the current stepper motor current using

X driver current: 2000
Y driver current: 2000
Z driver current: 2000
E driver current: 800

Changing the motor current in the config file

You can also set default stepper motor current values in the Marlin config files. Note that these will be overridden by any value in the EEPROM.

In Configuration_adv.h, look for


which contains axis definitions like

  #define X_CURRENT       800        // (mA) RMS current. Multiply by 1.414 for peak current.
  #define X_CURRENT_HOME  X_CURRENT  // (mA) RMS current for sensorless homing
  #define X_MICROSTEPS     32        // 0..256
  #define X_RSENSE          0.11
  #define X_CHAIN_POS      -1        // -1..0: Not chained. 1: MCU MOSI connected. 2: Next in chain, ...
  //#define X_INTERPOLATE  true      // Enable to override 'INTERPOLATE' for the X axis

Change the value in the line

#define X_CURRENT 800 // (mA) RMS current. Multiply by 1.414 for peak current.

so, for example to set 2A (2000 mA), set it to

#define X_CURRENT 2000 // (mA) RMS current. Multiply by 1.414 for peak current.


Posted by Uli Köhler in 3D printing