Note: Experimental and work in progress, documentation is incomplete and outdated.

See last chapter in this document for a log/history.

3d printer firmware for cartesian FDM printers (ultimaker clones, atmega and stm32, like um2, ramps or jennyprinter).

This firmware is part of the ddprint printing system, which immproves a common FDM printer by a closed loop E-Axis:

Reference printer is a Ultimaker 2 with ddprint installed and some hardware modifications:, and a jennyprinter X340 now too.

Current state

Works for me, experimental.

Update Mar 31 2021:

Merged next branch into master with the following changes:

  • Feed forward temp control (PID hinting, guided PID) :-o AutoTemp algorithm: set new temperature some time before the new flowrate demand, using the information from the material profile.
  • Added a experimental gcode (M901) for part strength (along with new workingpoint command line parameter) :-o
  • Asymmetric PID temperature control: switch between different PID control sets for heating (fast) and cooling (a slower PID set to avoid temperature underruns).
  • Deflate/zip data downloaded to printer to increase download speed over usb-serial. Using python's zlib on the host and uzlib ( on the firmware side.
  • Added a second step to material profile measurement (measuretempflowratecurve2): Measure hotend performance while doing a real print, in addition to the into-the-air extrusion measurement.
  • Some smaller improvements:
    • Moved printer-, nozzle- and material-profiles into their own repository (
    • Show print time in CLI and terminal UI (TUI).
    • Show the number of under-temperature and under-grip warnings in TUI.
    • Added a printlog to log information about the current printjob (gcode info, timestamp, printing time, slicersettings).
    • Added some tools and scripts (plot_mat_profile, ddtool, wrapperscripts).
    • Removed usage of eeprom, configuration now stored on mass storage device (sdcard, usb).
    • And many more...

Key features

  • Uses a incremental sensor to measure extruder flowrate at realtime to "close the loop for E". This limits the speed of the printer if feeder tends to slip.
  • Automatic measurement of feeder system caracteristics for calibration.
  • Automatic measurement of filament caracteristics to create filament profiles .
  • "Auto temperature algorithm": hotend temperature depends on the gcode-requested flowrate.
  • "Temperature-flowrate limiter": speed of printer is limited if hotend has not (yet) the right temperature for the requested flowrate.
  • Extruder pressure advance, of course ;-)

Main part is the Flowrate Sensor realized with a Bourns EMS22AFS incremental encoder:


Firmware part


  • Arduino code/libraries and avr compiler
  • Arduino-Makefile
  • SdCard library
  • Protothreads header

Install them along the checked out ddprint sources so that the directory structure looks like this:

├── ddprint
│   ├── LICENSE
│   ...
├── arduino-1.6.13
│   ├── arduino
│   ...
├── Arduino-Makefile
│   ├──
│   ...
├── SdFat-1.0.5
│   ...
│   └── src
├── protothreads-cpp
│   ├── LICENSE.txt
│   ...

The following versions are used at the moment (maybe newer versions will also work):

Arduino IDE 1.6.13, installed from downloaded archive.

Arduino-Makefile from
    commit c3fe5dcc2fbd5c895b032ca5a5a1f60af163b744
    Merge: 7a26a86 6d3d973
    Author: Simon John <>
    Date:   Thu Dec 28 18:05:18 2017 +0000

SdFat-1.0.5, installed from downloaded zip archive (,
apply ddprint/patches/SdFat-1.0.5.patch.

Protothreads from
    commit 984aa540dd4325b7e23dc76135ca28a36526f0c6
    Author: Ben Hoyt <>
    Date:   Tue Dec 4 16:48:52 2018 -0500

    Apply ddprint/patches/protothreads-cpp.patch

Build and upload firmware

Note:keep a backup of your previous firmware in case you want to go back.
Note:ddPrint does not use EEProm.

For a ultimaker UM2 do:

make -f Makefile.fw
make -f Makefile.fw do_upload

For a ramps based printer do:

make -f Makefile.ramps
make -f Makefile.ramps do_upload
Todo:Add info about configuration.

Host part


  • apt-get install python python-serial
  • pip install npyscreen vor the TUI (

No installation procedure yet, checkout the repository and run or from the ddprint/host subdirectory.


Parts of printer configuration hardcoded in firmware, parts come from printer profile at runtime.

Todo:describe configuration.

Only one setting stored in printer: the printer name.

Todo:describe printer name setting.

Gcode input

Easier slicing, simple gcode

Note:Simplify3d is used as of this writing.

Use mostly plain gcode with ddprint, many of the advanced features of the slicers (i call it slicer hacks) are not needed, see

The (automatically measured) material profile gives a picture of the hotend melting capacity for a given machine/filament combination. This eases the determination of a good printing speed.

Simplify3d example slicer settings in

Usage, Commandline Interface

Machine setup and calibration


Store printer name in printer's runtime config (on mass storage device):

./ setPrinterName UM2-1

See also: getprintername command.


Get current endstop state.

./ getEndstops


Machine setup and calibration: Automatically determine extruder e-steps value for printer profile:

./ calibrateesteps

Example screencast:


Machine setup and calibration: Automatically determine flowrate sensor calibration value for printer profile:

./ calibratefilsensor

Example screencast:


Test e-steps and flowrate sensor calibration:

./ testFilSensor UM2-2 100

Autotune hotend PID, autoTune

Run PID autotune to determine the hotend PID parameters:

./ autoTune petg_1.75mm
cd pid_tune
PYTHONPATH=.. ./ ../autotune.raw.json


Todo:describe command

Material measurment

Measure material profile, measureTempFlowrateCurve

Extrude some filament into air and measure the material properties (melting capacity, temperatures) of this machine/filament combination.

./ measureTempFlowrateCurve nozzle80 petg_1.75mm 2.5



./ home


Heat hotend and start filament insertion process.

./ removeFilament petg_1.75mm


Heat hotend and pull back/remove filament.

./ removeFilament petg_1.75mm

Preprocess gcode file, pre

Preprocess a gcode file, this parses the given gcode file and runs all processing steps without actually sending anything to the printer. Used for development, debugging and to check if a given gcode file can be processed by ddprint.

./  -smat esun_petg_transparent-orange-6-922572-263079 pre UM2-1 nozzle80 petg_1.75mm quader_10x20.gcode

Misc commands


Switch off stepper current, printer no longer homed after that.

./ disableSteppers

Manual movement, moverel

Move axis relative to current position.

./ moverel X 100

Manual movement, moveabs

Move axis to absolute position.

./ moveabs X 0


Todo:describe command


Get current position of filament sensor

./ getFilSensor


Get current printer free memory.

./ getFreeMem


Get current printer positions.

./ getpos

Read printer name from printer, getPrinterName

Read printer name from printer, stored on mass storage device (sdcard, usbmemory).

./ getprintername


Get bed- and hotend temperatures from printer.

./ getTemps


./ getStatus

Usage, Userinterface (TUI)

Print a gcode file with the TUI:

./  -smat esun_petg_transparent-orange-6-922572-263079 nozzle80 petg quader_10x20.gcode

Some implementation notes

Host side preprocessing and stepgeneration

The software is split into two main parts:

  • The host part where the cpu intensive work (gcode preprocessing, path planning, lookahead, acceleration, advance...) is done. The host part is written in Python.
  • And the firmware part that runs on the ATMega Controller in the printer. This part executes the move commands from the host and does other things like the temperature control of the printer.
  • Host software and printer firmware are connected through the usual atmega rs232 USB emulation.

Use printers SD card as a swap device

To overcome the limited memory of the atmega, the unused SD card is converted to something like a swap device: It buffers the received data. This decouples the USB transfer and actual use of the received data, too. The SD card is used in 'raw/blockwise mode' without a filesystem on it.

Working SD cards

Not all cards are working in SPI mode, some fail to initialize, some freeze after some time. See, also.

Some working ones:

  • The ones that come with your printer should work.
  • SandDisk, 2Gb, SD
  • SandDisk, 2Gb, Micro-SD
  • SandDisk, 4Gb, SDHC, Class 2
  • SandDisk, 4Gb, SDHC, Class 4

Not working ones:

  • MediaRange, 4Gb, SDHC, Class 10


AutoTemp algorithm: the hotend temperature is increased for parts of the model where high printing speeds are reached and vice-versa.


The firmware part is implemented using the great protothreads library:, thanks for this work.


  • Look ahead path planning with linear acceleration ramps.
  • Hardened USB communication using COBS encoding and CCITT checksums in BOTH directions.
  • Simulator mode for testing/development: Firmware runs as a host-program with serial communication over a ptty device.
  • Debugging: plot/display generated acceleration ramps

Things todo, nice to have

  • Improve documentation, examples, videos.
  • Cleanup and stabilisation, make binary releases.
  • Python3 port (currently python 2.7).
  • Other convenient things like automatic bedleveling and so on.


Thanks to all open/free software people that make this all possible.


Fri Jun 25 09:49:51 CEST 2021

Merged *next* branch into master, changes are:

* Flowrate/grip measurement:
* Added a experimental reprap usbserial interface using a pseudo-tty to use OctoPrint
  as a frontend for ddPrint. Not much functionality yet: display temperatures and some
  SD card commands (stubs).
* Flowrate limiter: max. slowdown now four times instead of 16.

Wed Jun 16 23:47:01 CEST 2021

Current development (cleanup, minor fixes, documentation) is done on *next* branch.
Adding asciinema screencast to show how to use ddPrint.

Wed Jun  9 21:17:22 CEST 2021

Merged *fix-avr* branch into master.

Tue Jun  8 14:41:41 CEST 2021

Pushed fix-avr branch to github. The JennyPrinter port made the avr/atmega side to slow.
Changes are:

* Integer math instead of floating point.
* Reworked usb-serial interface: store 512byte blocks.
* Removed compression with zlib, the avr has not enough cpu cycles.
* Experiment: auto-baudrate. Switch between 1000000, 500000 and 250000 baud.
* SDReader: double-buffering.
* Many other improvements and cleanup.

So for now, fix-avr is the branch to use for avr/atmega based printers and master is for
the stm32 JennyPrinter. Branch fix-avr has will be merged into master.