| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | # Code overview
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | This document describes the overall code layout and major code flow of | 
					
						
							|  |  |  | Klipper. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Directory Layout
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | The **src/** directory contains the C source for the micro-controller | 
					
						
							| 
									
										
										
										
											2019-11-07 10:08:21 -05:00
										 |  |  | code. The **src/atsam/**, **src/atsamd/**, **src/avr/**, | 
					
						
							|  |  |  | **src/linux/**, **src/lpc176x/**, **src/pru/**, and **src/stm32/** | 
					
						
							| 
									
										
										
										
											2018-12-26 15:41:37 -05:00
										 |  |  | directories contain architecture specific micro-controller code. The | 
					
						
							|  |  |  | **src/simulator/** contains code stubs that allow the micro-controller | 
					
						
							|  |  |  | to be test compiled on other architectures. The **src/generic/** | 
					
						
							|  |  |  | directory contains helper code that may be useful across different | 
					
						
							|  |  |  | architectures. The build arranges for includes of "board/somefile.h" | 
					
						
							|  |  |  | to first look in the current architecture directory (eg, | 
					
						
							|  |  |  | src/avr/somefile.h) and then in the generic directory (eg, | 
					
						
							|  |  |  | src/generic/somefile.h). | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  | The **klippy/** directory contains the host software. Most of the host | 
					
						
							|  |  |  | software is written in Python, however the **klippy/chelper/** | 
					
						
							| 
									
										
										
										
											2018-11-17 14:56:15 -05:00
										 |  |  | directory contains some C code helpers. The **klippy/kinematics/** | 
					
						
							|  |  |  | directory contains the robot kinematics code. The **klippy/extras/** | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  | directory contains the host code extensible "modules". | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | The **lib/** directory contains external 3rd-party library code that | 
					
						
							|  |  |  | is necessary to build some targets. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | The **config/** directory contains example printer configuration | 
					
						
							|  |  |  | files. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The **scripts/** directory contains build-time scripts useful for | 
					
						
							|  |  |  | compiling the micro-controller code. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | The **test/** directory contains automated test cases. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | During compilation, the build may create an **out/** directory. This | 
					
						
							|  |  |  | contains temporary build time objects. The final micro-controller | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | object that is built is **out/klipper.elf.hex** on AVR and | 
					
						
							|  |  |  | **out/klipper.bin** on ARM. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Micro-controller code flow
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | Execution of the micro-controller code starts in architecture specific | 
					
						
							|  |  |  | code (eg, **src/avr/main.c**) which ultimately calls sched_main() | 
					
						
							|  |  |  | located in **src/sched.c**. The sched_main() code starts by running | 
					
						
							|  |  |  | all functions that have been tagged with the DECL_INIT() macro. It | 
					
						
							|  |  |  | then goes on to repeatedly run all functions tagged with the | 
					
						
							|  |  |  | DECL_TASK() macro. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 11:55:30 -04:00
										 |  |  | One of the main task functions is command_dispatch() located in | 
					
						
							|  |  |  | **src/command.c**. This function is called from the board specific | 
					
						
							| 
									
										
										
										
											2019-11-07 10:08:21 -05:00
										 |  |  | input/output code (eg, **src/avr/serial.c**, | 
					
						
							|  |  |  | **src/generic/serial_irq.c**) and it runs the command functions | 
					
						
							|  |  |  | associated with the commands found in the input stream. Command | 
					
						
							|  |  |  | functions are declared using the DECL_COMMAND() macro (see the | 
					
						
							|  |  |  | [protocol](Protocol.md) document for more information). | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Task, init, and command functions always run with interrupts enabled | 
					
						
							|  |  |  | (however, they can temporarily disable interrupts if needed). These | 
					
						
							| 
									
										
										
										
											2022-05-17 11:46:09 -04:00
										 |  |  | functions should avoid long pauses, delays, or do work that lasts a | 
					
						
							| 
									
										
										
										
											2022-05-17 11:55:17 -04:00
										 |  |  | significant time. (Long delays in these "task" functions result in | 
					
						
							| 
									
										
										
										
											2022-05-17 11:46:09 -04:00
										 |  |  | scheduling jitter for other "tasks" - delays over 100us may become | 
					
						
							|  |  |  | noticeable, delays over 500us may result in command retransmissions, | 
					
						
							| 
									
										
										
										
											2022-05-17 11:55:17 -04:00
										 |  |  | delays over 100ms may result in watchdog reboots.) These functions | 
					
						
							|  |  |  | schedule work at specific times by scheduling timers. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-10 22:12:05 -05:00
										 |  |  | Timer functions are scheduled by calling sched_add_timer() (located in | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | **src/sched.c**). The scheduler code will arrange for the given | 
					
						
							|  |  |  | function to be called at the requested clock time. Timer interrupts | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | are initially handled in an architecture specific interrupt handler | 
					
						
							| 
									
										
										
										
											2017-03-27 16:38:01 -04:00
										 |  |  | (eg, **src/avr/timer.c**) which calls sched_timer_dispatch() located | 
					
						
							|  |  |  | in **src/sched.c**. The timer interrupt leads to execution of schedule | 
					
						
							| 
									
										
										
										
											2020-03-02 21:54:22 -05:00
										 |  |  | timer functions. Timer functions always run with interrupts disabled. | 
					
						
							|  |  |  | The timer functions should always complete within a few micro-seconds. | 
					
						
							|  |  |  | At completion of the timer event, the function may choose to | 
					
						
							|  |  |  | reschedule itself. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | In the event an error is detected the code can invoke shutdown() (a | 
					
						
							|  |  |  | macro which calls sched_shutdown() located in **src/sched.c**). | 
					
						
							|  |  |  | Invoking shutdown() causes all functions tagged with the | 
					
						
							|  |  |  | DECL_SHUTDOWN() macro to be run. Shutdown functions always run with | 
					
						
							|  |  |  | interrupts disabled. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Much of the functionality of the micro-controller involves working | 
					
						
							|  |  |  | with General-Purpose Input/Output pins (GPIO). In order to abstract | 
					
						
							|  |  |  | the low-level architecture specific code from the high-level task | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | code, all GPIO events are implemented in architecture specific | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | wrappers (eg, **src/avr/gpio.c**). The code is compiled with gcc's | 
					
						
							|  |  |  | "-flto -fwhole-program" optimization which does an excellent job of | 
					
						
							|  |  |  | inlining functions across compilation units, so most of these tiny | 
					
						
							|  |  |  | gpio functions are inlined into their callers, and there is no | 
					
						
							|  |  |  | run-time cost to using them. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Klippy code overview
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | The host code (Klippy) is intended to run on a low-cost computer (such | 
					
						
							|  |  |  | as a Raspberry Pi) paired with the micro-controller. The code is | 
					
						
							|  |  |  | primarily written in Python, however it does use CFFI to implement | 
					
						
							|  |  |  | some functionality in C code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Initial execution starts in **klippy/klippy.py**. This reads the | 
					
						
							|  |  |  | command-line arguments, opens the printer config file, instantiates | 
					
						
							|  |  |  | the main printer objects, and starts the serial connection. The main | 
					
						
							| 
									
										
										
										
											2025-09-16 11:35:11 -04:00
										 |  |  | execution of G-code commands is in the _process_commands() method in | 
					
						
							| 
									
										
										
										
											2017-04-27 15:14:11 -04:00
										 |  |  | **klippy/gcode.py**. This code translates the G-code commands into | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | printer object calls, which frequently translate the actions to | 
					
						
							|  |  |  | commands to be executed on the micro-controller (as declared via the | 
					
						
							|  |  |  | DECL_COMMAND macro in the micro-controller code). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-16 11:35:11 -04:00
										 |  |  | There are several threads in the Klipper host code: | 
					
						
							|  |  |  | * There is a Python "main thread" that handles incoming G-Code | 
					
						
							|  |  |  |   commands and is the starting point for most actions. This thread | 
					
						
							|  |  |  |   runs the [reactor](https://en.wikipedia.org/wiki/Reactor_pattern) | 
					
						
							|  |  |  |   (**klippy/reactor.py**) and most high-level actions originate from | 
					
						
							|  |  |  |   IO and timer event callbacks from that reactor. | 
					
						
							|  |  |  | * A thread for writing messages to the log so that the other threads | 
					
						
							|  |  |  |   do not block on log writes. This thread resides entirely in the | 
					
						
							|  |  |  |   **klippy/queuelogger.py** code and its operation is generally not | 
					
						
							|  |  |  |   exposed to the main Python thread. | 
					
						
							|  |  |  | * A thread per micro-controller that performs the low-level reading | 
					
						
							|  |  |  |   and writing of messages to that micro-controller. It resides in the | 
					
						
							|  |  |  |   **klippy/chelper/serialqueue.c** C code and its operation is | 
					
						
							|  |  |  |   generally not exposed to the Python code. | 
					
						
							|  |  |  | * A thread per micro-controller for processing messages received from | 
					
						
							|  |  |  |   that micro-controller in the Python code. This thread is created in | 
					
						
							|  |  |  |   **klippy/serialhdl.py**. Care must be taken in Python callbacks | 
					
						
							|  |  |  |   invoked from this thread as this thread may directly interact with | 
					
						
							|  |  |  |   the main Python thread. | 
					
						
							|  |  |  | * A thread per stepper motor that calculates the timing of stepper | 
					
						
							|  |  |  |   motor step pulses and compresses those times. This thread resides in | 
					
						
							| 
									
										
										
										
											2025-09-24 15:30:46 -04:00
										 |  |  |   the **klippy/chelper/steppersync.c** C code and its operation is | 
					
						
							| 
									
										
										
										
											2025-09-16 11:35:11 -04:00
										 |  |  |   generally not exposed to the Python code. | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Code flow of a move command
 | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | A typical printer movement starts when a "G1" command is sent to the | 
					
						
							|  |  |  | Klippy host and it completes when the corresponding step pulses are | 
					
						
							|  |  |  | produced on the micro-controller. This section outlines the code flow | 
					
						
							| 
									
										
										
										
											2017-04-15 15:22:50 -04:00
										 |  |  | of a typical move command. The [kinematics](Kinematics.md) document | 
					
						
							|  |  |  | provides further information on the mechanics of moves. | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  | * Processing for a move command starts in gcode.py. The goal of | 
					
						
							| 
									
										
										
										
											2020-08-17 00:05:41 -04:00
										 |  |  |   gcode.py is to translate G-code into internal calls. A G1 command | 
					
						
							|  |  |  |   will invoke cmd_G1() in klippy/extras/gcode_move.py. The | 
					
						
							|  |  |  |   gcode_move.py code handles changes in origin (eg, G92), changes in | 
					
						
							|  |  |  |   relative vs absolute positions (eg, G90), and unit changes (eg, | 
					
						
							|  |  |  |   F6000=100mm/s). The code path for a move is: `_process_data() -> | 
					
						
							|  |  |  |   _process_commands() -> cmd_G1()`. Ultimately the ToolHead class is | 
					
						
							|  |  |  |   invoked to execute the actual request: `cmd_G1() -> ToolHead.move()` | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-27 12:02:15 -04:00
										 |  |  | * The ToolHead class (in toolhead.py) handles "look-ahead" and tracks | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   the timing of printing actions. The main codepath for a move is: | 
					
						
							| 
									
										
										
										
											2025-09-24 15:30:46 -04:00
										 |  |  |   `ToolHead.move() -> LookAheadQueue.add_move()`, then | 
					
						
							|  |  |  |   `ToolHead.move() -> ToolHead._process_lookahead() -> | 
					
						
							|  |  |  |   LookAheadQueue.flush() -> Move.set_junction()`, and then | 
					
						
							|  |  |  |   `ToolHead._process_lookahead() -> trapq_append()`. | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  |   * ToolHead.move() creates a Move() object with the parameters of the | 
					
						
							|  |  |  |   move (in cartesian space and in units of seconds and millimeters). | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   * The kinematics class is given the opportunity to audit each move | 
					
						
							|  |  |  |   (`ToolHead.move() -> kin.check_move()`). The kinematics classes are | 
					
						
							|  |  |  |   located in the klippy/kinematics/ directory. The check_move() code | 
					
						
							|  |  |  |   may raise an error if the move is not valid. If check_move() | 
					
						
							|  |  |  |   completes successfully then the underlying kinematics must be able | 
					
						
							|  |  |  |   to handle the move. | 
					
						
							| 
									
										
										
										
											2024-01-18 12:16:47 -05:00
										 |  |  |   * LookAheadQueue.add_move() places the move object on the | 
					
						
							|  |  |  |   "look-ahead" queue. | 
					
						
							|  |  |  |   * LookAheadQueue.flush() determines the start and end velocities of | 
					
						
							|  |  |  |   each move. | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  |   * Move.set_junction() implements the "trapezoid generator" on a | 
					
						
							|  |  |  |   move. The "trapezoid generator" breaks every move into three parts: | 
					
						
							|  |  |  |   a constant acceleration phase, followed by a constant velocity | 
					
						
							|  |  |  |   phase, followed by a constant deceleration phase. Every move | 
					
						
							|  |  |  |   contains these three phases in this order, but some phases may be of | 
					
						
							|  |  |  |   zero duration. | 
					
						
							| 
									
										
										
										
											2025-09-24 15:30:46 -04:00
										 |  |  |   * When ToolHead._process_lookahead() resumes, everything about the | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   move is known - its start location, its end location, its | 
					
						
							|  |  |  |   acceleration, its start/cruising/end velocity, and distance traveled | 
					
						
							|  |  |  |   during acceleration/cruising/deceleration. All the information is | 
					
						
							|  |  |  |   stored in the Move() class and is in cartesian space in units of | 
					
						
							|  |  |  |   millimeters and seconds. | 
					
						
							| 
									
										
										
										
											2025-09-16 11:35:11 -04:00
										 |  |  |   * The moves are then placed on a "trapezoid motion queue" via | 
					
						
							|  |  |  |   trapq_append() (in klippy/chelper/trapq.c). The trapq stores all the | 
					
						
							|  |  |  |   information in the Move() class in a C struct accessible to the host | 
					
						
							|  |  |  |   C code. | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | * Note that the extruder is handled in its own kinematic class: | 
					
						
							| 
									
										
										
										
											2025-09-24 15:30:46 -04:00
										 |  |  |   `ToolHead._process_lookahead() -> PrinterExtruder.process_move()`. | 
					
						
							|  |  |  |   Since the Move() class specifies the exact movement time and since | 
					
						
							|  |  |  |   step pulses are sent to the micro-controller with specific timing, | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   stepper movements produced by the extruder class will be in sync | 
					
						
							|  |  |  |   with head movement even though the code is kept separate. | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-18 22:38:59 -04:00
										 |  |  | * For efficiency reasons, stepper motion is generated in the C code in | 
					
						
							|  |  |  |   a thread per stepper motor. The threads are notified when steps | 
					
						
							|  |  |  |   should be generated by the motion_queuing module | 
					
						
							|  |  |  |   (klippy/extras/motion_queuing.py): | 
					
						
							| 
									
										
										
										
											2025-09-16 11:35:11 -04:00
										 |  |  |   `PrinterMotionQueuing._flush_handler() -> | 
					
						
							|  |  |  |   PrinterMotionQueuing._advance_move_time() -> | 
					
						
							| 
									
										
										
										
											2025-09-18 22:38:59 -04:00
										 |  |  |   steppersyncmgr_gen_steps() -> se_start_gen_steps()`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * Klipper uses an | 
					
						
							|  |  |  |   [iterative solver](https://en.wikipedia.org/wiki/Root-finding_algorithm) | 
					
						
							|  |  |  |   to generate the step times for each stepper. The step times are | 
					
						
							|  |  |  |   generated from the background thread (klippy/chelper/steppersync.c): | 
					
						
							|  |  |  |   `se_background_thread() -> se_generate_steps() -> | 
					
						
							| 
									
										
										
										
											2025-09-16 11:35:11 -04:00
										 |  |  |   itersolve_generate_steps() -> itersolve_gen_steps_range()` (in | 
					
						
							|  |  |  |   klippy/chelper/itersolve.c). The goal of the iterative solver is to | 
					
						
							|  |  |  |   find step times given a function that calculates a stepper position | 
					
						
							|  |  |  |   from a time. This is done by repeatedly "guessing" various times | 
					
						
							|  |  |  |   until the stepper position formula returns the desired position of | 
					
						
							|  |  |  |   the next step on the stepper. The feedback produced from each guess | 
					
						
							|  |  |  |   is used to improve future guesses so that the process rapidly | 
					
						
							|  |  |  |   converges to the desired time. The kinematic stepper position | 
					
						
							|  |  |  |   formulas are located in the klippy/chelper/ directory (eg, | 
					
						
							|  |  |  |   kin_cart.c, kin_corexy.c, kin_delta.c, kin_extruder.c). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | * After the iterative solver calculates the step times they are added | 
					
						
							| 
									
										
										
										
											2020-03-02 21:54:22 -05:00
										 |  |  |   to an array: `itersolve_gen_steps_range() -> stepcompress_append()` | 
					
						
							|  |  |  |   (in klippy/chelper/stepcompress.c). The array (struct | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  |   stepcompress.queue) stores the corresponding micro-controller clock | 
					
						
							|  |  |  |   counter times for every step. Here the "micro-controller clock | 
					
						
							|  |  |  |   counter" value directly corresponds to the micro-controller's | 
					
						
							|  |  |  |   hardware counter - it is relative to when the micro-controller was | 
					
						
							|  |  |  |   last powered up. | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  | * The next major step is to compress the steps: `stepcompress_flush() | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  |   -> compress_bisect_add()` (in klippy/chelper/stepcompress.c). This | 
					
						
							|  |  |  |   code generates and encodes a series of micro-controller "queue_step" | 
					
						
							|  |  |  |   commands that correspond to the list of stepper step times built in | 
					
						
							|  |  |  |   the previous stage. These "queue_step" commands are then queued, | 
					
						
							|  |  |  |   prioritized, and sent to the micro-controller (via | 
					
						
							| 
									
										
										
										
											2025-09-18 22:38:59 -04:00
										 |  |  |   steppersync.c:steppersync and serialqueue.c:serialqueue). | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | * Processing of the queue_step commands on the micro-controller starts | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  |   in src/command.c which parses the command and calls | 
					
						
							|  |  |  |   `command_queue_step()`. The command_queue_step() code (in | 
					
						
							|  |  |  |   src/stepper.c) just appends the parameters of each queue_step | 
					
						
							|  |  |  |   command to a per stepper queue. Under normal operation the | 
					
						
							|  |  |  |   queue_step command is parsed and queued at least 100ms before the | 
					
						
							|  |  |  |   time of its first step. Finally, the generation of stepper events is | 
					
						
							|  |  |  |   done in `stepper_event()`. It's called from the hardware timer | 
					
						
							|  |  |  |   interrupt at the scheduled time of the first step. The | 
					
						
							|  |  |  |   stepper_event() code generates a step pulse and then reschedules | 
					
						
							|  |  |  |   itself to run at the time of the next step pulse for the given | 
					
						
							|  |  |  |   queue_step parameters. The parameters for each queue_step command | 
					
						
							|  |  |  |   are "interval", "count", and "add". At a high-level, stepper_event() | 
					
						
							|  |  |  |   runs the following, 'count' times: `do_step(); next_wake_time = | 
					
						
							|  |  |  |   last_wake_time + interval; interval += add;` | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 21:54:22 -05:00
										 |  |  | The above may seem like a lot of complexity to execute a movement. | 
					
						
							|  |  |  | However, the only really interesting parts are in the ToolHead and | 
					
						
							|  |  |  | kinematic classes. It's this part of the code which specifies the | 
					
						
							|  |  |  | movements and their timings. The remaining parts of the processing is | 
					
						
							|  |  |  | mostly just communication and plumbing. | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Adding a host module
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | The Klippy host code has a dynamic module loading capability. If a | 
					
						
							|  |  |  | config section named "[my_module]" is found in the printer config file | 
					
						
							|  |  |  | then the software will automatically attempt to load the python module | 
					
						
							|  |  |  | klippy/extras/my_module.py . This module system is the preferred | 
					
						
							|  |  |  | method for adding new functionality to Klipper. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The easiest way to add a new module is to use an existing module as a | 
					
						
							|  |  |  | reference - see **klippy/extras/servo.py** as an example. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following may also be useful: | 
					
						
							|  |  |  | * Execution of the module starts in the module level `load_config()` | 
					
						
							|  |  |  |   function (for config sections of the form [my_module]) or in | 
					
						
							|  |  |  |   `load_config_prefix()` (for config sections of the form | 
					
						
							|  |  |  |   [my_module my_name]). This function is passed a "config" object and | 
					
						
							|  |  |  |   it must return a new "printer object" associated with the given | 
					
						
							|  |  |  |   config section. | 
					
						
							|  |  |  | * During the process of instantiating a new printer object, the config | 
					
						
							|  |  |  |   object can be used to read parameters from the given config | 
					
						
							|  |  |  |   section. This is done using `config.get()`, `config.getfloat()`, | 
					
						
							|  |  |  |   `config.getint()`, etc. methods. Be sure to read all values from the | 
					
						
							|  |  |  |   config during the construction of the printer object - if the user | 
					
						
							|  |  |  |   specifies a config parameter that is not read during this phase then | 
					
						
							|  |  |  |   it will be assumed it is a typo in the config and an error will be | 
					
						
							|  |  |  |   raised. | 
					
						
							|  |  |  | * Use the `config.get_printer()` method to obtain a reference to the | 
					
						
							|  |  |  |   main "printer" class. This "printer" class stores references to all | 
					
						
							|  |  |  |   the "printer objects" that have been instantiated. Use the | 
					
						
							|  |  |  |   `printer.lookup_object()` method to find references to other printer | 
					
						
							|  |  |  |   objects. Almost all functionality (even core kinematic modules) are | 
					
						
							|  |  |  |   encapsulated in one of these printer objects. Note, though, that | 
					
						
							|  |  |  |   when a new module is instantiated, not all other printer objects | 
					
						
							|  |  |  |   will have been instantiated. The "gcode" and "pins" modules will | 
					
						
							|  |  |  |   always be available, but for other modules it is a good idea to | 
					
						
							|  |  |  |   defer the lookup. | 
					
						
							| 
									
										
										
										
											2019-01-08 11:34:09 -05:00
										 |  |  | * Register event handlers using the `printer.register_event_handler()` | 
					
						
							|  |  |  |   method if the code needs to be called during "events" raised by | 
					
						
							|  |  |  |   other printer objects. Each event name is a string, and by | 
					
						
							|  |  |  |   convention it is the name of the main source module that raises the | 
					
						
							|  |  |  |   event along with a short name for the action that is occurring (eg, | 
					
						
							|  |  |  |   "klippy:connect"). The parameters passed to each event handler are | 
					
						
							|  |  |  |   specific to the given event (as are exception handling and execution | 
					
						
							|  |  |  |   context). Two common startup events are: | 
					
						
							|  |  |  |   * klippy:connect - This event is generated after all printer objects | 
					
						
							|  |  |  |     are instantiated. It is commonly used to lookup other printer | 
					
						
							|  |  |  |     objects, to verify config settings, and to perform an initial | 
					
						
							|  |  |  |     "handshake" with printer hardware. | 
					
						
							|  |  |  |   * klippy:ready - This event is generated after all connect handlers | 
					
						
							|  |  |  |     have completed successfully. It indicates the printer is | 
					
						
							|  |  |  |     transitioning to a state ready to handle normal operations. Do not | 
					
						
							|  |  |  |     raise an error in this callback. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * If there is an error in the user's config, be sure to raise it | 
					
						
							| 
									
										
										
										
											2019-01-08 11:34:09 -05:00
										 |  |  |   during the `load_config()` or "connect event" phases. Use either | 
					
						
							|  |  |  |   `raise config.error("my error")` or `raise printer.config_error("my | 
					
						
							|  |  |  |   error")` to report the error. | 
					
						
							| 
									
										
										
										
											2025-05-14 18:47:36 -04:00
										 |  |  | * Do not store a reference to the `config` object in a class member | 
					
						
							|  |  |  |   variable (nor in any similar location that may persist past initial | 
					
						
							|  |  |  |   module loading). The `config` object is a reference to a "config | 
					
						
							|  |  |  |   loading phase" class and it is not valid to invoke its methods after | 
					
						
							|  |  |  |   the "config loading phase" has completed. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * Use the "pins" module to configure a pin on a micro-controller. This | 
					
						
							|  |  |  |   is typically done with something similar to | 
					
						
							|  |  |  |   `printer.lookup_object("pins").setup_pin("pwm", | 
					
						
							|  |  |  |   config.get("my_pin"))`. The returned object can then be commanded at | 
					
						
							|  |  |  |   run-time. | 
					
						
							| 
									
										
										
										
											2021-11-16 19:15:20 -05:00
										 |  |  | * If the printer object defines a `get_status()` method then the | 
					
						
							|  |  |  |   module can export [status information](Status_Reference.md) via | 
					
						
							|  |  |  |   [macros](Command_Templates.md) and via the | 
					
						
							|  |  |  |   [API Server](API_Server.md). The `get_status()` method must return a | 
					
						
							|  |  |  |   Python dictionary with keys that are strings and values that are | 
					
						
							|  |  |  |   integers, floats, strings, lists, dictionaries, True, False, or | 
					
						
							|  |  |  |   None. Tuples (and named tuples) may also be used (these appear as | 
					
						
							|  |  |  |   lists when accessed via the API Server). Lists and dictionaries that | 
					
						
							|  |  |  |   are exported must be treated as "immutable" - if their contents | 
					
						
							|  |  |  |   change then a new object must be returned from `get_status()`, | 
					
						
							|  |  |  |   otherwise the API Server will not detect those changes. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * If the module needs access to system timing or external file | 
					
						
							|  |  |  |   descriptors then use `printer.get_reactor()` to obtain access to the | 
					
						
							|  |  |  |   global "event reactor" class. This reactor class allows one to | 
					
						
							|  |  |  |   schedule timers, wait for input on file descriptors, and to "sleep" | 
					
						
							|  |  |  |   the host code. | 
					
						
							|  |  |  | * Do not use global variables. All state should be stored in the | 
					
						
							|  |  |  |   printer object returned from the `load_config()` function. This is | 
					
						
							|  |  |  |   important as otherwise the RESTART command may not perform as | 
					
						
							|  |  |  |   expected. Also, for similar reasons, if any external files (or | 
					
						
							| 
									
										
										
										
											2019-01-08 11:34:09 -05:00
										 |  |  |   sockets) are opened then be sure to register a "klippy:disconnect" | 
					
						
							|  |  |  |   event handler and close them from that callback. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * Avoid accessing the internal member variables (or calling methods | 
					
						
							|  |  |  |   that start with an underscore) of other printer objects. Observing | 
					
						
							|  |  |  |   this convention makes it easier to manage future changes. | 
					
						
							| 
									
										
										
										
											2021-11-16 19:25:34 -05:00
										 |  |  | * It is recommended to assign a value to all member variables in the | 
					
						
							|  |  |  |   Python constructor of Python classes. (And therefore avoid utilizing | 
					
						
							|  |  |  |   Python's ability to dynamically create new member variables.) | 
					
						
							|  |  |  | * If a Python variable is to store a floating point value then it is | 
					
						
							|  |  |  |   recommended to always assign and manipulate that variable with | 
					
						
							|  |  |  |   floating point constants (and never use integer constants). For | 
					
						
							|  |  |  |   example, prefer `self.speed = 1.` over `self.speed = 1`, and prefer | 
					
						
							| 
									
										
										
										
											2021-11-16 20:33:12 -05:00
										 |  |  |   `self.speed = 2. * x` over `self.speed = 2 * x`. Consistent use of | 
					
						
							| 
									
										
										
										
											2021-11-16 19:25:34 -05:00
										 |  |  |   floating point values can avoid hard to debug quirks in Python type | 
					
						
							|  |  |  |   conversions. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * If submitting the module for inclusion in the main Klipper code, be | 
					
						
							|  |  |  |   sure to place a copyright notice at the top of the module. See the | 
					
						
							|  |  |  |   existing modules for the preferred format. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Adding new kinematics
 | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | This section provides some tips on adding support to Klipper for | 
					
						
							|  |  |  | additional types of printer kinematics. This type of activity requires | 
					
						
							|  |  |  | excellent understanding of the math formulas for the target | 
					
						
							|  |  |  | kinematics. It also requires software development skills - though one | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | should only need to update the host software. | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | Useful steps: | 
					
						
							| 
									
										
										
										
											2018-04-23 18:23:39 -04:00
										 |  |  | 1. Start by studying the | 
					
						
							|  |  |  |    "[code flow of a move](#code-flow-of-a-move-command)" section and | 
					
						
							|  |  |  |    the [Kinematics document](Kinematics.md). | 
					
						
							| 
									
										
										
										
											2018-11-17 14:56:15 -05:00
										 |  |  | 2. Review the existing kinematic classes in the klippy/kinematics/ | 
					
						
							|  |  |  |    directory. The kinematic classes are tasked with converting a move | 
					
						
							|  |  |  |    in cartesian coordinates to the movement on each stepper. One | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  |    should be able to copy one of these files as a starting point. | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | 3. Implement the C stepper kinematic position functions for each | 
					
						
							|  |  |  |    stepper if they are not already available (see kin_cart.c, | 
					
						
							|  |  |  |    kin_corexy.c, and kin_delta.c in klippy/chelper/). The function | 
					
						
							|  |  |  |    should call `move_get_coord()` to convert a given move time (in | 
					
						
							|  |  |  |    seconds) to a cartesian coordinate (in millimeters), and then | 
					
						
							|  |  |  |    calculate the desired stepper position (in millimeters) from that | 
					
						
							|  |  |  |    cartesian coordinate. | 
					
						
							| 
									
										
										
										
											2021-05-01 00:27:43 -04:00
										 |  |  | 4. Implement the `calc_position()` method in the new kinematics class. | 
					
						
							|  |  |  |    This method calculates the position of the toolhead in cartesian | 
					
						
							|  |  |  |    coordinates from the position of each stepper. It does not need to | 
					
						
							|  |  |  |    be efficient as it is typically only called during homing and | 
					
						
							|  |  |  |    probing operations. | 
					
						
							| 
									
										
										
										
											2019-11-12 22:47:10 -05:00
										 |  |  | 5. Other methods. Implement the `check_move()`, `get_status()`, | 
					
						
							| 
									
										
										
										
											2025-01-10 15:41:09 +00:00
										 |  |  |    `get_steppers()`, `home()`, `clear_homing_state()`, and `set_position()` | 
					
						
							|  |  |  |    methods. These functions are typically used to provide kinematic | 
					
						
							|  |  |  |    specific checks. However, at the start of development one can use | 
					
						
							|  |  |  |    boiler-plate code here. | 
					
						
							| 
									
										
										
										
											2018-06-22 13:03:07 -04:00
										 |  |  | 6. Implement test cases. Create a g-code file with a series of moves | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  |    that can test important cases for the given kinematics. Follow the | 
					
						
							|  |  |  |    [debugging documentation](Debugging.md) to convert this g-code file | 
					
						
							|  |  |  |    to micro-controller commands. This is useful to exercise corner | 
					
						
							|  |  |  |    cases and to check for regressions. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Porting to a new micro-controller
 | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | This section provides some tips on porting Klipper's micro-controller | 
					
						
							|  |  |  | code to a new architecture. This type of activity requires good | 
					
						
							|  |  |  | knowledge of embedded development and hands-on access to the target | 
					
						
							|  |  |  | micro-controller. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Useful steps: | 
					
						
							|  |  |  | 1. Start by identifying any 3rd party libraries that will be used | 
					
						
							|  |  |  |    during the port. Common examples include "CMSIS" wrappers and | 
					
						
							|  |  |  |    manufacturer "HAL" libraries. All 3rd party code needs to be GNU | 
					
						
							|  |  |  |    GPLv3 compatible. The 3rd party code should be committed to the | 
					
						
							|  |  |  |    Klipper lib/ directory. Update the lib/README file with information | 
					
						
							|  |  |  |    on where and when the library was obtained. It is preferable to | 
					
						
							|  |  |  |    copy the code into the Klipper repository unchanged, but if any | 
					
						
							|  |  |  |    changes are required then those changes should be listed explicitly | 
					
						
							|  |  |  |    in the lib/README file. | 
					
						
							|  |  |  | 2. Create a new architecture sub-directory in the src/ directory and | 
					
						
							|  |  |  |    add initial Kconfig and Makefile support. Use the existing | 
					
						
							|  |  |  |    architectures as a guide. The src/simulator provides a basic | 
					
						
							|  |  |  |    example of a minimum starting point. | 
					
						
							|  |  |  | 3. The first main coding task is to bring up communication support to | 
					
						
							|  |  |  |    the target board. This is the most difficult step in a new port. | 
					
						
							|  |  |  |    Once basic communication is working, the remaining steps tend to be | 
					
						
							| 
									
										
										
										
											2021-11-22 11:01:39 -05:00
										 |  |  |    much easier. It is typical to use a UART type serial device during | 
					
						
							|  |  |  |    initial development as these types of hardware devices are | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  |    generally easier to enable and control. During this phase, make | 
					
						
							|  |  |  |    liberal use of helper code from the src/generic/ directory (check | 
					
						
							|  |  |  |    how src/simulator/Makefile includes the generic C code into the | 
					
						
							|  |  |  |    build). It is also necessary to define timer_read_time() (which | 
					
						
							|  |  |  |    returns the current system clock) in this phase, but it is not | 
					
						
							|  |  |  |    necessary to fully support timer irq handling. | 
					
						
							|  |  |  | 4. Get familiar with the the console.py tool (as described in the | 
					
						
							|  |  |  |    [debugging document](Debugging.md)) and verify connectivity to the | 
					
						
							|  |  |  |    micro-controller with it. This tool translates the low-level | 
					
						
							|  |  |  |    micro-controller communication protocol to a human readable form. | 
					
						
							|  |  |  | 5. Add support for timer dispatch from hardware interrupts. See | 
					
						
							|  |  |  |    Klipper | 
					
						
							| 
									
										
										
										
											2021-09-23 19:37:27 -04:00
										 |  |  |    [commit 970831ee](https://github.com/Klipper3d/klipper/commit/970831ee0d3b91897196e92270d98b2a3067427f) | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  |    as an example of steps 1-5 done for the LPC176x architecture. | 
					
						
							|  |  |  | 6. Bring up basic GPIO input and output support. See Klipper | 
					
						
							| 
									
										
										
										
											2021-09-23 19:37:27 -04:00
										 |  |  |    [commit c78b9076](https://github.com/Klipper3d/klipper/commit/c78b90767f19c9e8510c3155b89fb7ad64ca3c54) | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  |    as an example of this. | 
					
						
							|  |  |  | 7. Bring up additional peripherals - for example see Klipper commit | 
					
						
							| 
									
										
										
										
											2021-09-23 19:37:27 -04:00
										 |  |  |    [65613aed](https://github.com/Klipper3d/klipper/commit/65613aeddfb9ef86905cb1dade9e773a02ef3c27), | 
					
						
							|  |  |  |    [c812a40a](https://github.com/Klipper3d/klipper/commit/c812a40a3782415e454b04bf7bd2158a6f0ec8b5), | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  |    and | 
					
						
							| 
									
										
										
										
											2021-09-23 19:37:27 -04:00
										 |  |  |    [c381d03a](https://github.com/Klipper3d/klipper/commit/c381d03aad5c3ee761169b7c7bced519cc14da29). | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  | 8. Create a sample Klipper config file in the config/ directory. Test | 
					
						
							|  |  |  |    the micro-controller with the main klippy.py program. | 
					
						
							|  |  |  | 9. Consider adding build test cases in the test/ directory. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 11:01:39 -05:00
										 |  |  | Additional coding tips: | 
					
						
							|  |  |  | 1. Avoid using "C bitfields" to access IO registers; prefer direct | 
					
						
							|  |  |  |    read and write operations of 32bit, 16bit, or 8bit integers. The C | 
					
						
							|  |  |  |    language specifications don't clearly specify how the compiler must | 
					
						
							|  |  |  |    implement C bitfields (eg, endianness, and bit layout), and it's | 
					
						
							|  |  |  |    difficult to determine what IO operations will occur on a C | 
					
						
							|  |  |  |    bitfield read or write. | 
					
						
							|  |  |  | 2. Prefer writing explicit values to IO registers instead of using | 
					
						
							|  |  |  |    read-modify-write operations. That is, if updating a field in an IO | 
					
						
							|  |  |  |    register where the other fields have known values, then it is | 
					
						
							|  |  |  |    preferable to explicitly write the full contents of the register. | 
					
						
							|  |  |  |    Explicit writes produce code that is smaller, faster, and easier to | 
					
						
							|  |  |  |    debug. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Coordinate Systems
 | 
					
						
							| 
									
										
										
										
											2019-12-04 11:09:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-04 12:05:31 -05:00
										 |  |  | Internally, Klipper primarily tracks the position of the toolhead in | 
					
						
							|  |  |  | cartesian coordinates that are relative to the coordinate system | 
					
						
							|  |  |  | specified in the config file. That is, most of the Klipper code will | 
					
						
							|  |  |  | never experience a change in coordinate systems. If the user makes a | 
					
						
							|  |  |  | request to change the origin (eg, a `G92` command) then that effect is | 
					
						
							|  |  |  | obtained by translating future commands to the primary coordinate | 
					
						
							|  |  |  | system. | 
					
						
							| 
									
										
										
										
											2019-12-04 11:09:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | However, in some cases it is useful to obtain the toolhead position in | 
					
						
							|  |  |  | some other coordinate system and Klipper has several tools to | 
					
						
							|  |  |  | facilitate that. This can be seen by running the GET_POSITION | 
					
						
							|  |  |  | command. For example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | Send: GET_POSITION | 
					
						
							|  |  |  | Recv: // mcu: stepper_a:-2060 stepper_b:-1169 stepper_c:-1613 | 
					
						
							|  |  |  | Recv: // stepper: stepper_a:457.254159 stepper_b:466.085669 stepper_c:465.382132 | 
					
						
							|  |  |  | Recv: // kinematic: X:8.339144 Y:-3.131558 Z:233.347121 | 
					
						
							|  |  |  | Recv: // toolhead: X:8.338078 Y:-3.123175 Z:233.347878 E:0.000000 | 
					
						
							|  |  |  | Recv: // gcode: X:8.338078 Y:-3.123175 Z:233.347878 E:0.000000 | 
					
						
							|  |  |  | Recv: // gcode base: X:0.000000 Y:0.000000 Z:0.000000 E:0.000000 | 
					
						
							|  |  |  | Recv: // gcode homing: X:0.000000 Y:0.000000 Z:0.000000 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The "mcu" position (`stepper.get_mcu_position()` in the code) is the | 
					
						
							|  |  |  | total number of steps the micro-controller has issued in a positive | 
					
						
							|  |  |  | direction minus the number of steps issued in a negative direction | 
					
						
							| 
									
										
										
										
											2021-04-02 12:18:05 -04:00
										 |  |  | since the micro-controller was last reset. If the robot is in motion | 
					
						
							|  |  |  | when the query is issued then the reported value includes moves | 
					
						
							|  |  |  | buffered on the micro-controller, but does not include moves on the | 
					
						
							|  |  |  | look-ahead queue. | 
					
						
							| 
									
										
										
										
											2019-12-04 11:09:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | The "stepper" position (`stepper.get_commanded_position()`) is the | 
					
						
							| 
									
										
										
										
											2019-12-04 12:05:31 -05:00
										 |  |  | position of the given stepper as tracked by the kinematics code. This | 
					
						
							|  |  |  | generally corresponds to the position (in mm) of the carriage along | 
					
						
							| 
									
										
										
										
											2019-12-04 12:17:13 -05:00
										 |  |  | its rail, relative to the position_endstop specified in the config | 
					
						
							| 
									
										
										
										
											2019-12-04 12:05:31 -05:00
										 |  |  | file. (Some kinematics track stepper positions in radians instead of | 
					
						
							|  |  |  | millimeters.) If the robot is in motion when the query is issued then | 
					
						
							|  |  |  | the reported value includes moves buffered on the micro-controller, | 
					
						
							|  |  |  | but does not include moves on the look-ahead queue. One may use the | 
					
						
							|  |  |  | `toolhead.flush_step_generation()` or `toolhead.wait_moves()` calls to | 
					
						
							|  |  |  | fully flush the look-ahead and step generation code. | 
					
						
							| 
									
										
										
										
											2019-12-04 11:09:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 23:02:05 -04:00
										 |  |  | The "kinematic" position (`kin.calc_position()`) is the cartesian | 
					
						
							|  |  |  | position of the toolhead as derived from "stepper" positions and is | 
					
						
							|  |  |  | relative to the coordinate system specified in the config file. This | 
					
						
							|  |  |  | may differ from the requested cartesian position due to the | 
					
						
							|  |  |  | granularity of the stepper motors. If the robot is in motion when the | 
					
						
							|  |  |  | "stepper" positions are taken then the reported value includes moves | 
					
						
							|  |  |  | buffered on the micro-controller, but does not include moves on the | 
					
						
							|  |  |  | look-ahead queue. One may use the `toolhead.flush_step_generation()` | 
					
						
							|  |  |  | or `toolhead.wait_moves()` calls to fully flush the look-ahead and | 
					
						
							|  |  |  | step generation code. | 
					
						
							| 
									
										
										
										
											2019-12-04 11:09:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | The "toolhead" position (`toolhead.get_position()`) is the last | 
					
						
							|  |  |  | requested position of the toolhead in cartesian coordinates relative | 
					
						
							|  |  |  | to the coordinate system specified in the config file. If the robot is | 
					
						
							|  |  |  | in motion when the query is issued then the reported value includes | 
					
						
							|  |  |  | all requested moves (even those in buffers waiting to be issued to the | 
					
						
							|  |  |  | stepper motor drivers). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The "gcode" position is the last requested position from a `G1` (or | 
					
						
							|  |  |  | `G0`) command in cartesian coordinates relative to the coordinate | 
					
						
							|  |  |  | system specified in the config file. This may differ from the | 
					
						
							|  |  |  | "toolhead" position if a g-code transformation (eg, bed_mesh, | 
					
						
							|  |  |  | bed_tilt, skew_correction) is in effect. This may differ from the | 
					
						
							|  |  |  | actual coordinates specified in the last `G1` command if the g-code | 
					
						
							|  |  |  | origin has been changed (eg, `G92`, `SET_GCODE_OFFSET`, `M221`). The | 
					
						
							| 
									
										
										
										
											2020-08-05 11:43:45 -04:00
										 |  |  | `M114` command (`gcode_move.get_status()['gcode_position']`) will | 
					
						
							|  |  |  | report the last g-code position relative to the current g-code | 
					
						
							|  |  |  | coordinate system. | 
					
						
							| 
									
										
										
										
											2019-12-04 11:09:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | The "gcode base" is the location of the g-code origin in cartesian | 
					
						
							|  |  |  | coordinates relative to the coordinate system specified in the config | 
					
						
							|  |  |  | file. Commands such as `G92`, `SET_GCODE_OFFSET`, and `M221` alter | 
					
						
							|  |  |  | this value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The "gcode homing" is the location to use for the g-code origin (in | 
					
						
							|  |  |  | cartesian coordinates relative to the coordinate system specified in | 
					
						
							|  |  |  | the config file) after a `G28` home command. The `SET_GCODE_OFFSET` | 
					
						
							|  |  |  | command can alter this value. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 13:29:36 -04:00
										 |  |  | ## Time
 | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Fundamental to the operation of Klipper is the handling of clocks, | 
					
						
							|  |  |  | times, and timestamps. Klipper executes actions on the printer by | 
					
						
							|  |  |  | scheduling events to occur in the near future. For example, to turn on | 
					
						
							|  |  |  | a fan, the code might schedule a change to a GPIO pin in a 100ms. It | 
					
						
							|  |  |  | is rare for the code to attempt to take an instantaneous action. Thus, | 
					
						
							|  |  |  | the handling of time within Klipper is critical to correct operation. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are three types of times tracked internally in the Klipper host | 
					
						
							|  |  |  | software: | 
					
						
							|  |  |  | * System time. The system time uses the system's monotonic clock - it | 
					
						
							|  |  |  |   is a floating point number stored as seconds and it is (generally) | 
					
						
							|  |  |  |   relative to when the host computer was last started. System times | 
					
						
							|  |  |  |   have limited use in the software - they are primarily used when | 
					
						
							|  |  |  |   interacting with the operating system. Within the host code, system | 
					
						
							|  |  |  |   times are frequently stored in variables named *eventtime* or | 
					
						
							|  |  |  |   *curtime*. | 
					
						
							|  |  |  | * Print time. The print time is synchronized to the main | 
					
						
							|  |  |  |   micro-controller clock (the micro-controller defined in the "[mcu]" | 
					
						
							|  |  |  |   config section). It is a floating point number stored as seconds and | 
					
						
							|  |  |  |   is relative to when the main mcu was last restarted. It is possible | 
					
						
							|  |  |  |   to convert from a "print time" to the main micro-controller's | 
					
						
							|  |  |  |   hardware clock by multiplying the print time by the mcu's statically | 
					
						
							|  |  |  |   configured frequency rate. The high-level host code uses print times | 
					
						
							| 
									
										
										
										
											2019-08-09 00:13:34 -04:00
										 |  |  |   to calculate almost all physical actions (eg, head movement, heater | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  |   changes, etc.). Within the host code, print times are generally | 
					
						
							|  |  |  |   stored in variables named *print_time* or *move_time*. | 
					
						
							|  |  |  | * MCU clock. This is the hardware clock counter on each | 
					
						
							|  |  |  |   micro-controller. It is stored as an integer and its update rate is | 
					
						
							|  |  |  |   relative to the frequency of the given micro-controller. The host | 
					
						
							|  |  |  |   software translates its internal times to clocks before transmission | 
					
						
							|  |  |  |   to the mcu. The mcu code only ever tracks time in clock | 
					
						
							|  |  |  |   ticks. Within the host code, clock values are tracked as 64bit | 
					
						
							|  |  |  |   integers, while the mcu code uses 32bit integers. Within the host | 
					
						
							|  |  |  |   code, clocks are generally stored in variables with names containing | 
					
						
							|  |  |  |   *clock* or *ticks*. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Conversion between the different time formats is primarily implemented | 
					
						
							|  |  |  | in the **klippy/clocksync.py** code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some things to be aware of when reviewing the code: | 
					
						
							|  |  |  | * 32bit and 64bit clocks: To reduce bandwidth and to improve | 
					
						
							|  |  |  |   micro-controller efficiency, clocks on the micro-controller are | 
					
						
							|  |  |  |   tracked as 32bit integers. When comparing two clocks in the mcu | 
					
						
							|  |  |  |   code, the `timer_is_before()` function must always be used to ensure | 
					
						
							|  |  |  |   integer rollovers are handled properly. The host software converts | 
					
						
							|  |  |  |   32bit clocks to 64bit clocks by appending the high-order bits from | 
					
						
							|  |  |  |   the last mcu timestamp it has received - no message from the mcu is | 
					
						
							|  |  |  |   ever more than 2^31 clock ticks in the future or past so this | 
					
						
							|  |  |  |   conversion is never ambiguous. The host converts from 64bit clocks | 
					
						
							|  |  |  |   to 32bit clocks by simply truncating the high-order bits. To ensure | 
					
						
							|  |  |  |   there is no ambiguity in this conversion, the | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  |   **klippy/chelper/serialqueue.c** code will buffer messages until | 
					
						
							|  |  |  |   they are within 2^31 clock ticks of their target time. | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  | * Multiple micro-controllers: The host software supports using | 
					
						
							|  |  |  |   multiple micro-controllers on a single printer. In this case, the | 
					
						
							|  |  |  |   "MCU clock" of each micro-controller is tracked separately. The | 
					
						
							|  |  |  |   clocksync.py code handles clock drift between micro-controllers by | 
					
						
							|  |  |  |   modifying the way it converts from "print time" to "MCU clock". On | 
					
						
							|  |  |  |   secondary mcus, the mcu frequency that is used in this conversion is | 
					
						
							|  |  |  |   regularly updated to account for measured drift. |