klipper update
403
docs/API_Server.md
Normal file
@@ -0,0 +1,403 @@
|
||||
# API server
|
||||
|
||||
This document describes Klipper's Application Programmer Interface
|
||||
(API). This interface enables external applications to query and
|
||||
control the Klipper host software.
|
||||
|
||||
## Enabling the API socket
|
||||
|
||||
In order to use the API server, the klippy.py host software must be
|
||||
started with the `-a` parameter. For example:
|
||||
```
|
||||
~/klippy-env/bin/python ~/klipper/klippy/klippy.py ~/printer.cfg -a /tmp/klippy_uds -l /tmp/klippy.log
|
||||
```
|
||||
|
||||
This causes the host software to create a Unix Domain Socket. A client
|
||||
can then open a connection on that socket and send commands to
|
||||
Klipper.
|
||||
|
||||
See the [Moonraker](https://github.com/Arksine/moonraker) project for
|
||||
a popular tool that can forward HTTP requests to Klipper's API Server
|
||||
Unix Domain Socket.
|
||||
|
||||
## Request format
|
||||
|
||||
Messages sent and received on the socket are JSON encoded strings
|
||||
terminated by an ASCII 0x03 character:
|
||||
```
|
||||
<json_object_1><0x03><json_object_2><0x03>...
|
||||
```
|
||||
|
||||
Klipper contains a `scripts/whconsole.py` tool that can perform the
|
||||
above message framing. For example:
|
||||
```
|
||||
~/klipper/scripts/whconsole.py /tmp/klippy_uds
|
||||
```
|
||||
|
||||
This tool can read a series of JSON commands from stdin, send them to
|
||||
Klipper, and report the results. The tool expects each JSON command to
|
||||
be on a single line, and it will automatically append the 0x03
|
||||
terminator when transmitting a request. (The Klipper API server does
|
||||
not have a newline requirement.)
|
||||
|
||||
## API Protocol
|
||||
|
||||
The command protocol used on the communication socket is inspired by
|
||||
[json-rpc](https://www.jsonrpc.org/).
|
||||
|
||||
A request might look like:
|
||||
|
||||
`{"id": 123, "method": "info", "params": {}}`
|
||||
|
||||
and a response might look like:
|
||||
|
||||
`{"id": 123, "result": {"state_message": "Printer is ready",
|
||||
"klipper_path": "/home/pi/klipper", "config_file":
|
||||
"/home/pi/printer.cfg", "software_version": "v0.8.0-823-g883b1cb6",
|
||||
"hostname": "octopi", "cpu_info": "4 core ARMv7 Processor rev 4
|
||||
(v7l)", "state": "ready", "python_path":
|
||||
"/home/pi/klippy-env/bin/python", "log_file": "/tmp/klippy.log"}}`
|
||||
|
||||
Each request must be a JSON dictionary. (This document uses the Python
|
||||
term "dictionary" to describe a "JSON object" - a mapping of key/value
|
||||
pairs contained within `{}`.)
|
||||
|
||||
The request dictionary must contain a "method" parameter that is the
|
||||
string name of an available Klipper "endpoint".
|
||||
|
||||
The request dictionary may contain a "params" parameter which must be
|
||||
of a dictionary type. The "params" provide additional parameter
|
||||
information to the Klipper "endpoint" handling the request. Its
|
||||
content is specific to the "endpoint".
|
||||
|
||||
The request dictionary may contain an "id" parameter which may be of
|
||||
any JSON type. If "id" is present then Klipper will respond to the
|
||||
request with a response message containing that "id". If "id" is
|
||||
omitted (or set to a JSON "null" value) then Klipper will not provide
|
||||
any response to the request. A response message is a JSON dictionary
|
||||
containing "id" and "result". The "result" is always a dictionary -
|
||||
its contents are specific to the "endpoint" handling the request.
|
||||
|
||||
If the processing of a request results in an error, then the response
|
||||
message will contain an "error" field instead of a "result" field. For
|
||||
example, the request:
|
||||
`{"id": 123, "method": "gcode/script", "params": {"script": "G1
|
||||
X200"}}`
|
||||
might result in an error response such as:
|
||||
`{"id": 123, "error": {"message": "Must home axis
|
||||
first: 200.000 0.000 0.000 [0.000]", "error": "WebRequestError"}}`
|
||||
|
||||
Klipper will always start processing requests in the order that they
|
||||
are received. However, some request may not complete immediately,
|
||||
which could cause the associated response to be sent out of order with
|
||||
respect to responses from other requests. A JSON request will never
|
||||
pause the processing of future JSON requests.
|
||||
|
||||
## Subscriptions
|
||||
|
||||
Some Klipper "endpoint" requests allow one to "subscribe" to future
|
||||
asynchronous update messages.
|
||||
|
||||
For example:
|
||||
|
||||
`{"id": 123, "method": "gcode/subscribe_output", "params":
|
||||
{"response_template":{"key": 345}}}`
|
||||
|
||||
may initially respond with:
|
||||
|
||||
`{"id": 123, "result": {}}`
|
||||
|
||||
and cause Klipper to send future messages similar to:
|
||||
|
||||
`{"params": {"response": "ok B:22.8 /0.0 T0:22.4 /0.0"}, "key": 345}`
|
||||
|
||||
A subscription request accepts a "response_template" dictionary in the
|
||||
"params" field of the request. That "response_template" dictionary is
|
||||
used as a template for future asynchronous messages - it may contain
|
||||
arbitrary key/value pairs. When sending these future asynchronous
|
||||
messages, Klipper will add a "params" field containing a dictionary
|
||||
with "endpoint" specific contents to the response template and then
|
||||
send that template. If a "response_template" field is not provided
|
||||
then it defaults to an empty dictionary (`{}`).
|
||||
|
||||
## Available "endpoints"
|
||||
|
||||
By convention, Klipper "endpoints" are of the form
|
||||
`<module_name>/<some_name>`. When making a request to an "endpoint",
|
||||
the full name must be set in the "method" parameter of the request
|
||||
dictionary (eg, `{"method"="gcode/restart"}`).
|
||||
|
||||
### info
|
||||
|
||||
The "info" endpoint is used to obtain system and version information
|
||||
from Klipper. It is also used to provide the client's version
|
||||
information to Klipper. For example:
|
||||
`{"id": 123, "method": "info", "params": { "client_info": { "version":
|
||||
"v1"}}}`
|
||||
|
||||
If present, the "client_info" parameter must be a dictionary, but that
|
||||
dictionary may have arbitrary contents. Clients are encouraged to
|
||||
provide the name of the client and its software version when first
|
||||
connecting to the Klipper API server.
|
||||
|
||||
### emergency_stop
|
||||
|
||||
The "emergency_stop" endpoint is used to instruct Klipper to
|
||||
transition to a "shutdown" state. It behaves similarly to the G-Code
|
||||
`M112` command. For example:
|
||||
`{"id": 123, "method": "emergency_stop"}`
|
||||
|
||||
### register_remote_method
|
||||
|
||||
This endpoint allows clients to register methods that can be called
|
||||
from klipper. It will return an empty object upon success.
|
||||
|
||||
For example:
|
||||
`{"id": 123, "method": "register_remote_method",
|
||||
"params": {"response_template": {"action": "run_paneldue_beep"},
|
||||
"remote_method": "paneldue_beep"}}`
|
||||
will return:
|
||||
`{"id": 123, "result": {}}`
|
||||
|
||||
The remote method `paneldue_beep` may now be called from Klipper. Note
|
||||
that if the method takes parameters they should be provided as keyword
|
||||
arguments. Below is an example of how it may called from a gcode_macro:
|
||||
```
|
||||
[gcode_macro PANELDUE_BEEP]
|
||||
gcode:
|
||||
{action_call_remote_method("paneldue_beep", frequency=300, duration=1.0)}
|
||||
```
|
||||
|
||||
When the PANELDUE_BEEP gcode macro is executed, Klipper would send something
|
||||
like the following over the socket:
|
||||
`{"action": "run_paneldue_beep",
|
||||
"params": {"frequency": 300, "duration": 1.0}}`
|
||||
|
||||
### objects/list
|
||||
|
||||
This endpoint queries the list of available printer "objects" that one
|
||||
may query (via the "objects/query" endpoint). For example:
|
||||
`{"id": 123, "method": "objects/list"}`
|
||||
might return:
|
||||
`{"id": 123, "result": {"objects":
|
||||
["webhooks", "configfile", "heaters", "gcode_move", "query_endstops",
|
||||
"idle_timeout", "toolhead", "extruder"]}}`
|
||||
|
||||
### objects/query
|
||||
|
||||
This endpoint allows one to query information from printer objects.
|
||||
For example:
|
||||
`{"id": 123, "method": "objects/query", "params": {"objects":
|
||||
{"toolhead": ["position"], "webhooks": null}}}`
|
||||
might return:
|
||||
`{"id": 123, "result": {"status": {"webhooks": {"state": "ready",
|
||||
"state_message": "Printer is ready"}, "toolhead": {"position":
|
||||
[0.0, 0.0, 0.0, 0.0]}}, "eventtime": 3051555.377933684}}`
|
||||
|
||||
The "objects" parameter in the request must be a dictionary containing
|
||||
the printer objects that are to be queried - the key contains the
|
||||
printer object name and the value is either "null" (to query all
|
||||
fields) or a list of field names.
|
||||
|
||||
The response message will contain a "status" field containing a
|
||||
dictionary with the queried information - the key contains the printer
|
||||
object name and the value is a dictionary containing its fields. The
|
||||
response message will also contain an "eventtime" field containing the
|
||||
timestamp from when the query was taken.
|
||||
|
||||
Available fields are documented in the
|
||||
[Status Reference](Status_Reference.md) document.
|
||||
|
||||
### objects/subscribe
|
||||
|
||||
This endpoint allows one to query and then subscribe to information
|
||||
from printer objects. The endpoint request and response is identical
|
||||
to the "objects/query" endpoint. For example:
|
||||
`{"id": 123, "method": "objects/subscribe", "params":
|
||||
{"objects":{"toolhead": ["position"], "webhooks": ["state"]},
|
||||
"response_template":{}}}`
|
||||
might return:
|
||||
`{"id": 123, "result": {"status": {"webhooks": {"state": "ready"},
|
||||
"toolhead": {"position": [0.0, 0.0, 0.0, 0.0]}},
|
||||
"eventtime": 3052153.382083195}}`
|
||||
and result in subsequent asynchronous messages such as:
|
||||
`{"params": {"status": {"webhooks": {"state": "shutdown"}},
|
||||
"eventtime": 3052165.418815847}}`
|
||||
|
||||
### gcode/help
|
||||
|
||||
This endpoint allows one to query available G-Code commands that have
|
||||
a help string defined. For example:
|
||||
`{"id": 123, "method": "gcode/help"}`
|
||||
might return:
|
||||
`{"id": 123, "result": {"RESTORE_GCODE_STATE": "Restore a previously
|
||||
saved G-Code state", "PID_CALIBRATE": "Run PID calibration test",
|
||||
"QUERY_ADC": "Report the last value of an analog pin", ...}}`
|
||||
|
||||
### gcode/script
|
||||
|
||||
This endpoint allows one to run a series of G-Code commands. For example:
|
||||
`{"id": 123, "method": "gcode/script", "params": {"script": "G90"}}`
|
||||
|
||||
If the provided G-Code script raises an error, then an error response
|
||||
is generated. However, if the G-Code command produces terminal output,
|
||||
that terminal output is not provided in the response. (Use the
|
||||
"gcode/subscribe_output" endpoint to obtain G-Code terminal output.)
|
||||
|
||||
If there is a G-Code command being processed when this request is
|
||||
received, then the provided script will be queued. This delay could be
|
||||
significant (eg, if a G-Code wait for temperature command is running).
|
||||
The JSON response message is sent when the processing of the script
|
||||
fully completes.
|
||||
|
||||
### gcode/restart
|
||||
|
||||
This endpoint allows one to request a restart - it is similar to
|
||||
running the G-Code "RESTART" command. For example:
|
||||
`{"id": 123, "method": "gcode/restart"}`
|
||||
|
||||
As with the "gcode/script" endpoint, this endpoint only completes
|
||||
after any pending G-Code commands complete.
|
||||
|
||||
### gcode/firmware_restart
|
||||
|
||||
This is similar to the "gcode/restart" endpoint - it implements the
|
||||
G-Code "FIRMWARE_RESTART" command. For example:
|
||||
`{"id": 123, "method": "gcode/firmware_restart"}`
|
||||
|
||||
As with the "gcode/script" endpoint, this endpoint only completes
|
||||
after any pending G-Code commands complete.
|
||||
|
||||
### gcode/subscribe_output
|
||||
|
||||
This endpoint is used to subscribe to G-Code terminal messages that
|
||||
are generated by Klipper. For example:
|
||||
`{"id": 123, "method": "gcode/subscribe_output", "params":
|
||||
{"response_template":{}}}`
|
||||
might later produce asynchronous messages such as:
|
||||
`{"params": {"response": "// Klipper state: Shutdown"}}`
|
||||
|
||||
This endpoint is intended to support human interaction via a "terminal
|
||||
window" interface. Parsing content from the G-Code terminal output is
|
||||
discouraged. Use the "objects/subscribe" endpoint to obtain updates on
|
||||
Klipper's state.
|
||||
|
||||
### motion_report/dump_stepper
|
||||
|
||||
This endpoint is used to subscribe to Klipper's internal stepper
|
||||
queue_step command stream for a stepper. Obtaining these low-level
|
||||
motion updates may be useful for diagnostic and debugging
|
||||
purposes. Using this endpoint may increase Klipper's system load.
|
||||
|
||||
A request may look like:
|
||||
`{"id": 123, "method":"motion_report/dump_stepper",
|
||||
"params": {"name": "stepper_x", "response_template": {}}}`
|
||||
and might return:
|
||||
`{"id": 123, "result": {"header": ["interval", "count", "add"]}}`
|
||||
and might later produce asynchronous messages such as:
|
||||
`{"params": {"first_clock": 179601081, "first_time": 8.98,
|
||||
"first_position": 0, "last_clock": 219686097, "last_time": 10.984,
|
||||
"data": [[179601081, 1, 0], [29573, 2, -8685], [16230, 4, -1525],
|
||||
[10559, 6, -160], [10000, 976, 0], [10000, 1000, 0], [10000, 1000, 0],
|
||||
[10000, 1000, 0], [9855, 5, 187], [11632, 4, 1534], [20756, 2, 9442]]}}`
|
||||
|
||||
The "header" field in the initial query response is used to describe
|
||||
the fields found in later "data" responses.
|
||||
|
||||
### motion_report/dump_trapq
|
||||
|
||||
This endpoint is used to subscribe to Klipper's internal "trapezoid
|
||||
motion queue". Obtaining these low-level motion updates may be useful
|
||||
for diagnostic and debugging purposes. Using this endpoint may
|
||||
increase Klipper's system load.
|
||||
|
||||
A request may look like:
|
||||
`{"id": 123, "method": "motion_report/dump_trapq", "params":
|
||||
{"name": "toolhead", "response_template":{}}}`
|
||||
and might return:
|
||||
`{"id": 1, "result": {"header": ["time", "duration",
|
||||
"start_velocity", "acceleration", "start_position", "direction"]}}`
|
||||
and might later produce asynchronous messages such as:
|
||||
`{"params": {"data": [[4.05, 1.0, 0.0, 0.0, [300.0, 0.0, 0.0],
|
||||
[0.0, 0.0, 0.0]], [5.054, 0.001, 0.0, 3000.0, [300.0, 0.0, 0.0],
|
||||
[-1.0, 0.0, 0.0]]]}}`
|
||||
|
||||
The "header" field in the initial query response is used to describe
|
||||
the fields found in later "data" responses.
|
||||
|
||||
### adxl345/dump_adxl345
|
||||
|
||||
This endpoint is used to subscribe to ADXL345 accelerometer data.
|
||||
Obtaining these low-level motion updates may be useful for diagnostic
|
||||
and debugging purposes. Using this endpoint may increase Klipper's
|
||||
system load.
|
||||
|
||||
A request may look like:
|
||||
`{"id": 123, "method":"adxl345/dump_adxl345",
|
||||
"params": {"sensor": "adxl345", "response_template": {}}}`
|
||||
and might return:
|
||||
`{"id": 123,"result":{"header":["time","x_acceleration","y_acceleration",
|
||||
"z_acceleration"]}}`
|
||||
and might later produce asynchronous messages such as:
|
||||
`{"params":{"overflows":0,"data":[[3292.432935,-535.44309,-1529.8374,9561.4],
|
||||
[3292.433256,-382.45935,-1606.32927,9561.48375]]}}`
|
||||
|
||||
The "header" field in the initial query response is used to describe
|
||||
the fields found in later "data" responses.
|
||||
|
||||
### angle/dump_angle
|
||||
|
||||
This endpoint is used to subscribe to
|
||||
[angle sensor data](Config_Reference.md#angle). Obtaining these
|
||||
low-level motion updates may be useful for diagnostic and debugging
|
||||
purposes. Using this endpoint may increase Klipper's system load.
|
||||
|
||||
A request may look like:
|
||||
`{"id": 123, "method":"angle/dump_angle",
|
||||
"params": {"sensor": "my_angle_sensor", "response_template": {}}}`
|
||||
and might return:
|
||||
`{"id": 123,"result":{"header":["time","angle"]}}`
|
||||
and might later produce asynchronous messages such as:
|
||||
`{"params":{"position_offset":3.151562,"errors":0,
|
||||
"data":[[1290.951905,-5063],[1290.952321,-5065]]}}`
|
||||
|
||||
The "header" field in the initial query response is used to describe
|
||||
the fields found in later "data" responses.
|
||||
|
||||
### pause_resume/cancel
|
||||
|
||||
This endpoint is similar to running the "PRINT_CANCEL" G-Code command.
|
||||
For example:
|
||||
`{"id": 123, "method": "pause_resume/cancel"}`
|
||||
|
||||
As with the "gcode/script" endpoint, this endpoint only completes
|
||||
after any pending G-Code commands complete.
|
||||
|
||||
### pause_resume/pause
|
||||
|
||||
This endpoint is similar to running the "PAUSE" G-Code command. For
|
||||
example:
|
||||
`{"id": 123, "method": "pause_resume/pause"}`
|
||||
|
||||
As with the "gcode/script" endpoint, this endpoint only completes
|
||||
after any pending G-Code commands complete.
|
||||
|
||||
### pause_resume/resume
|
||||
|
||||
This endpoint is similar to running the "RESUME" G-Code command. For
|
||||
example:
|
||||
`{"id": 123, "method": "pause_resume/resume"}`
|
||||
|
||||
As with the "gcode/script" endpoint, this endpoint only completes
|
||||
after any pending G-Code commands complete.
|
||||
|
||||
### query_endstops/status
|
||||
|
||||
This endpoint will query the active endpoints and return their status.
|
||||
For example:
|
||||
`{"id": 123, "method": "query_endstops/status"}`
|
||||
might return:
|
||||
`{"id": 123, "result": {"y": "open", "x": "open", "z": "TRIGGERED"}}`
|
||||
|
||||
As with the "gcode/script" endpoint, this endpoint only completes
|
||||
after any pending G-Code commands complete.
|
||||
262
docs/BLTouch.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# BL-Touch
|
||||
|
||||
## Connecting BL-Touch
|
||||
|
||||
A **warning** before you start: Avoid touching the BL-Touch pin with
|
||||
your bare fingers, since it is quite sensitive to finger grease. And
|
||||
if you do touch it, be very gentle, in order to not bend or push
|
||||
anything.
|
||||
|
||||
Hook up the BL-Touch "servo" connector to a `control_pin` according to
|
||||
the BL-Touch documentation or your MCU documentation. Using the
|
||||
original wiring, the yellow wire from the triple is the `control_pin`
|
||||
and the white wire from the pair is the `sensor_pin`. You need to
|
||||
configure these pins according to your wiring. Most BL-Touch devices
|
||||
require a pullup on the sensor pin (prefix the pin name with "^"). For
|
||||
example:
|
||||
|
||||
```
|
||||
[bltouch]
|
||||
sensor_pin: ^P1.24
|
||||
control_pin: P1.26
|
||||
```
|
||||
|
||||
If the BL-Touch will be used to home the Z axis then set `endstop_pin:
|
||||
probe:z_virtual_endstop` and remove `position_endstop` in the `[stepper_z]` config section,
|
||||
then add a `[safe_z_home]` config section to raise the z axis, home the xy axes,
|
||||
move to the center of the bed, and home the z axis. For example:
|
||||
|
||||
```
|
||||
[safe_z_home]
|
||||
home_xy_position: 100, 100 # Change coordinates to the center of your print bed
|
||||
speed: 50
|
||||
z_hop: 10 # Move up 10mm
|
||||
z_hop_speed: 5
|
||||
```
|
||||
|
||||
It's important that the z_hop movement in safe_z_home is high enough
|
||||
that the probe doesn't hit anything even if the probe pin happens to
|
||||
be in its lowest state.
|
||||
|
||||
## Initial tests
|
||||
|
||||
Before moving on, verify that the BL-Touch is mounted at the correct
|
||||
height, the pin should be roughly 2 mm above the nozzle when retracted
|
||||
|
||||
When you turn on the printer, the BL-Touch probe should perform a
|
||||
self-test and move the pin up and down a couple of times. Once the
|
||||
self-test is completed, the pin should be retracted and the red LED on
|
||||
the probe should be lit. If there are any errors, for example the
|
||||
probe is flashing red or the pin is down instead of up, please turn
|
||||
off the printer and check the wiring and configuration.
|
||||
|
||||
If the above is looking good, it's time to test that the control pin
|
||||
is working correctly. First run `BLTOUCH_DEBUG COMMAND=pin_down` in
|
||||
your printer terminal. Verify that the pin moves down and that the red
|
||||
LED on the probe turns off. If not, check your wiring and
|
||||
configuration again. Next issue a `BLTOUCH_DEBUG COMMAND=pin_up`,
|
||||
verify that the pin moves up, and that the red light turns on
|
||||
again. If it's flashing then there's some problem.
|
||||
|
||||
The next step is to confirm that the sensor pin is working correctly.
|
||||
Run `BLTOUCH_DEBUG COMMAND=pin_down`, verify that the pin moves down,
|
||||
run `BLTOUCH_DEBUG COMMAND=touch_mode`, run `QUERY_PROBE`, and verify
|
||||
that command reports "probe: open". Then while gently pushing the pin
|
||||
up slightly with the nail of your finger run `QUERY_PROBE` again.
|
||||
Verify the command reports "probe: TRIGGERED". If either query does
|
||||
not report the correct message then it usually indicates an incorrect
|
||||
wiring or configuration (though some [clones](#bl-touch-clones) may
|
||||
require special handling). At the completion of this test run
|
||||
`BLTOUCH_DEBUG COMMAND=pin_up` and verify that the pin moves up.
|
||||
|
||||
After completing the BL-Touch control pin and sensor pin tests, it is
|
||||
now time to test probing, but with a twist. Instead of letting the
|
||||
probe pin touch the print bed, let it touch the nail on your finger.
|
||||
Position the toolhead far from the bed, issue a `G28` (or `PROBE` if
|
||||
not using probe:z_virtual_endstop), wait until the toolhead starts to
|
||||
move down, and stop the movement by very gently touching the pin with
|
||||
your nail. You may have to do it twice, since the default homing
|
||||
configuration probes twice. Be prepared to turn off the printer if it
|
||||
doesn't stop when you touch the pin.
|
||||
|
||||
If that was successful, do another `G28` (or `PROBE`) but this time
|
||||
let it touch the bed as it should.
|
||||
|
||||
## BL-Touch gone bad
|
||||
|
||||
Once the BL-Touch is in inconsistent state, it starts blinking red.
|
||||
You can force it to leave that state by issuing:
|
||||
|
||||
BLTOUCH_DEBUG COMMAND=reset
|
||||
|
||||
This may happen if its calibration is interrupted by the probe being
|
||||
blocked from being extracted.
|
||||
|
||||
However, the BL-Touch may also not be able to calibrate itself
|
||||
anymore. This happens if the screw on its top is in the wrong position
|
||||
or the magnetic core inside the probe pin has moved. If it has moved
|
||||
up so that it sticks to the screw, it may not be able to lower its pin
|
||||
anymore. With this behavior you need to open the screw and use a
|
||||
ball-point pen to push it gently back into place. Re-Insert the pin
|
||||
into the BL-Touch so that it falls into the extracted position.
|
||||
Carefully readjust the headless screw into place. You need to find the
|
||||
right position so it is able to lower and raise the pin and the red
|
||||
light turns on and of. Use the `reset`, `pin_up` and `pin_down`
|
||||
commands to achieve this.
|
||||
|
||||
## BL-Touch "clones"
|
||||
|
||||
Many BL-Touch "clone" devices work correctly with Klipper using the
|
||||
default configuration. However, some "clone" devices may not support
|
||||
the `QUERY_PROBE` command and some "clone" devices may require
|
||||
configuration of `pin_up_reports_not_triggered` or
|
||||
`pin_up_touch_mode_reports_triggered`.
|
||||
|
||||
Important! Do not configure `pin_up_reports_not_triggered` or
|
||||
`pin_up_touch_mode_reports_triggered` to False without first following
|
||||
these directions. Do not configure either of these to False on a
|
||||
genuine BL-Touch. Incorrectly setting these to False can increase
|
||||
probing time and can increase the risk of damaging the printer.
|
||||
|
||||
Some "clone" devices do not support `touch_mode` and as a result the
|
||||
`QUERY_PROBE` command does not work. Despite this, it may still be
|
||||
possible to perform probing and homing with these devices. On these
|
||||
devices the `QUERY_PROBE` command during the
|
||||
[initial tests](#initial-tests) will not succeed, however the
|
||||
subsequent `G28` (or `PROBE`) test does succeed. It may be possible to
|
||||
use these "clone" devices with Klipper if one does not utilize the
|
||||
`QUERY_PROBE` command and one does not enable the
|
||||
`probe_with_touch_mode` feature.
|
||||
|
||||
Some "clone" devices are unable to perform Klipper's internal sensor
|
||||
verification test. On these devices, attempts to home or probe can
|
||||
result in Klipper reporting a "BLTouch failed to verify sensor state"
|
||||
error. If this occurs, then manually run the steps to confirm the
|
||||
sensor pin is working as described in the
|
||||
[initial tests section](#initial-tests). If the `QUERY_PROBE` commands
|
||||
in that test always produce the expected results and "BLTouch failed
|
||||
to verify sensor state" errors still occur, then it may be necessary
|
||||
to set `pin_up_touch_mode_reports_triggered` to False in the Klipper
|
||||
config file.
|
||||
|
||||
A rare number of old "clone" devices are unable to report when they
|
||||
have successfully raised their probe. On these devices Klipper will
|
||||
report a "BLTouch failed to raise probe" error after every home or
|
||||
probe attempt. One can test for these devices - move the head far from
|
||||
the bed, run `BLTOUCH_DEBUG COMMAND=pin_down`, verify the pin has
|
||||
moved down, run `QUERY_PROBE`, verify that command reports "probe:
|
||||
open", run `BLTOUCH_DEBUG COMMAND=pin_up`, verify the pin has moved
|
||||
up, and run `QUERY_PROBE`. If the pin remains up, the device does not
|
||||
enter an error state, and the first query reports "probe: open" while
|
||||
the second query reports "probe: TRIGGERED" then it indicates that
|
||||
`pin_up_reports_not_triggered` should be set to False in the Klipper
|
||||
config file.
|
||||
|
||||
## BL-Touch v3
|
||||
|
||||
Some BL-Touch v3.0 and BL-Touch 3.1 devices may require configuring
|
||||
`probe_with_touch_mode` in the printer config file.
|
||||
|
||||
If the BL-Touch v3.0 has its signal wire connected to an endstop pin
|
||||
(with a noise filtering capacitor), then the BL-Touch v3.0 may not be
|
||||
able to consistently send a signal during homing and probing. If the
|
||||
`QUERY_PROBE` commands in the [initial tests section](#initial-tests)
|
||||
always produce the expected results, but the toolhead does not always
|
||||
stop during G28/PROBE commands, then it is indicative of this issue. A
|
||||
workaround is to set `probe_with_touch_mode: True` in the config file.
|
||||
|
||||
The BL-Touch v3.1 may incorrectly enter an error state after a
|
||||
successful probe attempt. The symptoms are an occasional flashing
|
||||
light on the BL-Touch v3.1 that lasts for a couple of seconds after it
|
||||
successfully contacts the bed. Klipper should clear this error
|
||||
automatically and it is generally harmless. However, one may set
|
||||
`probe_with_touch_mode` in the config file to avoid this issue.
|
||||
|
||||
Important! Some "clone" devices and the BL-Touch v2.0 (and earlier)
|
||||
may have reduced accuracy when `probe_with_touch_mode` is set to True.
|
||||
Setting this to True also increases the time it takes to deploy the
|
||||
probe. If configuring this value on a "clone" or older BL-Touch
|
||||
device, be sure to test the probe accuracy before and after setting
|
||||
this value (use the `PROBE_ACCURACY` command to test).
|
||||
|
||||
## Multi-probing without stowing
|
||||
|
||||
By default, Klipper will deploy the probe at the start of each probe
|
||||
attempt and then stow the probe afterwards. This repetitive deploying
|
||||
and stowing of the probe may increase the total time of calibration
|
||||
sequences that involve many probe measurements. Klipper supports
|
||||
leaving the probe deployed between consecutive probes, which can
|
||||
reduce the total time of probing. This mode is enabled by configuring
|
||||
`stow_on_each_sample` to False in the config file.
|
||||
|
||||
Important! Setting `stow_on_each_sample` to False can lead to Klipper
|
||||
making horizontal toolhead movements while the probe is deployed. Be
|
||||
sure to verify all probing operations have sufficient Z clearance
|
||||
prior to setting this value to False. If there is insufficient
|
||||
clearance then a horizontal move may cause the pin to catch on an
|
||||
obstruction and result in damage to the printer.
|
||||
|
||||
Important! It is recommended to use `probe_with_touch_mode` configured
|
||||
to True when using `stow_on_each_sample` configured to False. Some
|
||||
"clone" devices may not detect a subsequent bed contact if
|
||||
`probe_with_touch_mode` is not set. On all devices, using the
|
||||
combination of these two settings simplifies the device signaling,
|
||||
which can improve overall stability.
|
||||
|
||||
Note, however, that some "clone" devices and the BL-Touch v2.0 (and
|
||||
earlier) may have reduced accuracy when `probe_with_touch_mode` is set
|
||||
to True. On these devices it is a good idea to test the probe accuracy
|
||||
before and after setting `probe_with_touch_mode` (use the
|
||||
`PROBE_ACCURACY` command to test).
|
||||
|
||||
## Calibrating the BL-Touch offsets
|
||||
|
||||
Follow the directions in the [Probe Calibrate](Probe_Calibrate.md)
|
||||
guide to set the x_offset, y_offset, and z_offset config parameters.
|
||||
|
||||
It's a good idea to verify that the Z offset is close to 1mm. If not,
|
||||
then you probably want to move the probe up or down to fix this. You
|
||||
want it to trigger well before the nozzle hits the bed, so that
|
||||
possible stuck filament or a warped bed doesn't affect any probing
|
||||
action. But at the same time, you want the retracted position to be as
|
||||
far above the nozzle as possible to avoid it touching printed parts.
|
||||
If an adjustment is made to the probe position, then rerun the probe
|
||||
calibration steps.
|
||||
|
||||
## BL-Touch output mode
|
||||
|
||||
* A BL-Touch V3.0 supports setting a 5V or OPEN-DRAIN output mode,
|
||||
a BL-Touch V3.1 supports this too, but can also store this in its
|
||||
internal EEPROM. If your controller board needs the fixed 5V high
|
||||
logic level of the 5V mode you may set the 'set_output_mode'
|
||||
parameter in the [bltouch] section of the printer config file to
|
||||
"5V".
|
||||
|
||||
*** Only use the 5V mode if your controller boards input line is
|
||||
5V tolerant. This is why the default configuration of these BL-Touch
|
||||
versions is OPEN-DRAIN mode. You could potentially damage your
|
||||
controller boards CPU ***
|
||||
|
||||
So therefore:
|
||||
If a controller board NEEDs 5V mode AND it is 5V tolerant on its
|
||||
input signal line AND if
|
||||
|
||||
- you have a BL-Touch Smart V3.0, you need the use 'set_output_mode: 5V'
|
||||
parameter to ensure this setting at each startup, since the probe
|
||||
cannot remember the needed setting.
|
||||
- you have a BL-Touch Smart V3.1, you have the choice of using
|
||||
'set_output_mode: 5V' or storing the mode once by use of a
|
||||
'BLTOUCH_STORE MODE=5V' command manually and NOT using the parameter
|
||||
'set_output_mode:'.
|
||||
- you have some other probe: Some probes have a trace on the circuit board
|
||||
to cut or a jumper to set in order to (permanently) set the output mode.
|
||||
In that case, omit the 'set_output_mode' parameter completely.
|
||||
|
||||
If you have a V3.1, do not automate or repeat storing the output mode to
|
||||
avoid wearing out the EEPROM of the probe.The BLTouch EEPROM is good for
|
||||
about 100.000 updates. 100 stores per day would add up to about 3 years
|
||||
of operation prior to wearing it out. Thus, storing the output mode in a
|
||||
V3.1 is designed by the vendor to be a complicated operation (the factory
|
||||
default being a safe OPEN DRAIN mode) and is not suited to be repeatedly
|
||||
issued by any slicer, macro or anything else, it is preferably only to be
|
||||
used when first integrating the probe into a printers electronics.
|
||||
100
docs/Beaglebone.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Beaglebone
|
||||
|
||||
This document describes the process of running Klipper on a Beaglebone
|
||||
PRU.
|
||||
|
||||
## Building an OS image
|
||||
|
||||
Start by installing the
|
||||
[Debian 9.9 2019-08-03 4GB SD IoT](https://beagleboard.org/latest-images)
|
||||
image. One may run the image from either a micro-SD card or from
|
||||
builtin eMMC. If using the eMMC, install it to eMMC now by following
|
||||
the instructions from the above link.
|
||||
|
||||
Then ssh into the Beaglebone machine (`ssh debian@beaglebone` --
|
||||
password is `temppwd`) and install Klipper by running the following
|
||||
commands:
|
||||
|
||||
```
|
||||
git clone https://github.com/Klipper3d/klipper
|
||||
./klipper/scripts/install-beaglebone.sh
|
||||
```
|
||||
|
||||
## Install Octoprint
|
||||
|
||||
One may then install Octoprint:
|
||||
```
|
||||
git clone https://github.com/foosel/OctoPrint.git
|
||||
cd OctoPrint/
|
||||
virtualenv venv
|
||||
./venv/bin/python setup.py install
|
||||
```
|
||||
|
||||
And setup OctoPrint to start at bootup:
|
||||
```
|
||||
sudo cp ~/OctoPrint/scripts/octoprint.init /etc/init.d/octoprint
|
||||
sudo chmod +x /etc/init.d/octoprint
|
||||
sudo cp ~/OctoPrint/scripts/octoprint.default /etc/default/octoprint
|
||||
sudo update-rc.d octoprint defaults
|
||||
```
|
||||
|
||||
It is necessary to modify OctoPrint's **/etc/default/octoprint**
|
||||
configuration file. One must change the `OCTOPRINT_USER` user to
|
||||
`debian`, change `NICELEVEL` to `0`, uncomment the `BASEDIR`, `CONFIGFILE`,
|
||||
and `DAEMON` settings and change the references from `/home/pi/` to
|
||||
`/home/debian/`:
|
||||
```
|
||||
sudo nano /etc/default/octoprint
|
||||
```
|
||||
|
||||
Then start the Octoprint service:
|
||||
```
|
||||
sudo systemctl start octoprint
|
||||
```
|
||||
|
||||
Make sure the OctoPrint web server is accessible - it should be at:
|
||||
[http://beaglebone:5000/](http://beaglebone:5000/)
|
||||
|
||||
## Building the micro-controller code
|
||||
|
||||
To compile the Klipper micro-controller code, start by configuring it
|
||||
for the "Beaglebone PRU":
|
||||
```
|
||||
cd ~/klipper/
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
To build and install the new micro-controller code, run:
|
||||
```
|
||||
sudo service klipper stop
|
||||
make flash
|
||||
sudo service klipper start
|
||||
```
|
||||
|
||||
It is also necessary to compile and install the micro-controller code
|
||||
for a Linux host process. Configure it a second time for a "Linux process":
|
||||
```
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
Then install this micro-controller code as well:
|
||||
```
|
||||
sudo service klipper stop
|
||||
make flash
|
||||
sudo service klipper start
|
||||
```
|
||||
|
||||
## Remaining configuration
|
||||
|
||||
Complete the installation by configuring Klipper and Octoprint
|
||||
following the instructions in
|
||||
the main [Installation](Installation.md#configuring-klipper) document.
|
||||
|
||||
## Printing on the Beaglebone
|
||||
|
||||
Unfortunately, the Beaglebone processor can sometimes struggle to run
|
||||
OctoPrint well. Print stalls have been known to occur on complex
|
||||
prints (the printer may move faster than OctoPrint can send movement
|
||||
commands). If this occurs, consider using the "virtual_sdcard" feature
|
||||
(see [Config Reference](Config_Reference.md#virtual_sdcard) for
|
||||
details) to print directly from Klipper.
|
||||
217
docs/Bed_Level.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Bed leveling
|
||||
|
||||
Bed leveling (sometimes also referred to as "bed tramming") is
|
||||
critical to getting high quality prints. If a bed is not properly
|
||||
"leveled" it can lead to poor bed adhesion, "warping", and subtle
|
||||
problems throughout the print. This document serves as a guide to
|
||||
performing bed leveling in Klipper.
|
||||
|
||||
It's important to understand the goal of bed leveling. If the printer
|
||||
is commanded to a position `X0 Y0 Z10` during a print, then the goal
|
||||
is for the printer's nozzle to be exactly 10mm from the printer's
|
||||
bed. Further, should the printer then be commanded to a position of
|
||||
`X50 Z10` the goal is for the nozzle to maintain an exact distance of
|
||||
10mm from the bed during that entire horizontal move.
|
||||
|
||||
In order to get good quality prints the printer should be calibrated
|
||||
so that Z distances are accurate to within about 25 microns (.025mm).
|
||||
This is a small distance - significantly smaller than the width of a
|
||||
typical human hair. This scale can not be measured "by eye". Subtle
|
||||
effects (such as heat expansion) impact measurements at this scale.
|
||||
The secret to getting high accuracy is to use a repeatable process and
|
||||
to use a leveling method that leverages the high accuracy of the
|
||||
printer's own motion system.
|
||||
|
||||
## Choose the appropriate calibration mechanism
|
||||
|
||||
Different types of printers use different methods for performing bed
|
||||
leveling. All of them ultimately depend on the "paper test" (described
|
||||
below). However, the actual process for a particular type of printer
|
||||
is described in other documents.
|
||||
|
||||
Prior to running any of these calibration tools, be sure to run the
|
||||
checks described in the [config check document](Config_checks.md). It
|
||||
is necessary to verify basic printer motion before performing bed
|
||||
leveling.
|
||||
|
||||
For printers with an "automatic Z probe" be sure to calibrate the
|
||||
probe following the directions in the
|
||||
[Probe Calibrate](Probe_Calibrate.md) document. For delta printers,
|
||||
see the [Delta Calibrate](Delta_Calibrate.md) document. For printers
|
||||
with bed screws and traditional Z endstops, see the
|
||||
[Manual Level](Manual_Level.md) document.
|
||||
|
||||
During calibration it may be necessary to set the printer's Z
|
||||
`position_min` to a negative number (eg, `position_min = -2`). The
|
||||
printer enforces boundary checks even during calibration
|
||||
routines. Setting a negative number allows the printer to move below
|
||||
the nominal position of the bed, which may help when trying to
|
||||
determine the actual bed position.
|
||||
|
||||
## The "paper test"
|
||||
|
||||
The primary bed calibration mechanism is the "paper test". It involves
|
||||
placing a regular piece of "copy machine paper" between the printer's
|
||||
bed and nozzle, and then commanding the nozzle to different Z heights
|
||||
until one feels a small amount of friction when pushing the paper back
|
||||
and forth.
|
||||
|
||||
It is important to understand the "paper test" even if one has an
|
||||
"automatic Z probe". The probe itself often needs to be calibrated to
|
||||
get good results. That probe calibration is done using this "paper
|
||||
test".
|
||||
|
||||
In order to perform the paper test, cut a small rectangular piece of
|
||||
paper using a pair of scissors (eg, 5x3 cm). The paper generally has a
|
||||
thickness of around 100 microns (0.100mm). (The exact thickness of the paper
|
||||
isn't crucial.)
|
||||
|
||||
The first step of the paper test is to inspect the printer's nozzle
|
||||
and bed. Make sure there is no plastic (or other debris) on the nozzle
|
||||
or bed.
|
||||
|
||||
**Inspect the nozzle and bed to ensure no plastic is present!**
|
||||
|
||||
If one always prints on a particular tape or printing surface then one
|
||||
may perform the paper test with that tape/surface in place. However,
|
||||
note that tape itself has a thickness and different tapes (or any other
|
||||
printing surface) will impact Z measurements. Be sure to rerun the
|
||||
paper test to measure each type of surface that is in use.
|
||||
|
||||
If there is plastic on the nozzle then heat up the extruder and use a
|
||||
metal tweezers to remove that plastic. Wait for the extruder to fully
|
||||
cool to room temperature before continuing with the paper test. While
|
||||
the nozzle is cooling, use the metal tweezers to remove any plastic
|
||||
that may ooze out.
|
||||
|
||||
**Always perform the paper test when both nozzle and bed are at room
|
||||
temperature!**
|
||||
|
||||
When the nozzle is heated, its position (relative to the bed) changes
|
||||
due to thermal expansion. This thermal expansion is typically around a
|
||||
100 microns, which is about the same thickness as a typical piece of
|
||||
printer paper. The exact amount of thermal expansion isn't crucial,
|
||||
just as the exact thickness of the paper isn't crucial. Start with the
|
||||
assumption that the two are equal (see below for a method of
|
||||
determining the difference between the two distances).
|
||||
|
||||
It may seem odd to calibrate the distance at room temperature when the
|
||||
goal is to have a consistent distance when heated. However, if one
|
||||
calibrates when the nozzle is heated, it tends to impart small amounts
|
||||
of molten plastic on to the paper, which changes the amount of
|
||||
friction felt. That makes it harder to get a good calibration.
|
||||
Calibrating while the bed/nozzle is hot also greatly increases the
|
||||
risk of burning oneself. The amount of thermal expansion is stable, so
|
||||
it is easily accounted for later in the calibration process.
|
||||
|
||||
**Use an automated tool to determine precise Z heights!**
|
||||
|
||||
Klipper has several helper scripts available (eg, MANUAL_PROBE,
|
||||
Z_ENDSTOP_CALIBRATE, PROBE_CALIBRATE, DELTA_CALIBRATE). See the
|
||||
documents
|
||||
[described above](#choose-the-appropriate-calibration-mechanism) to
|
||||
choose one of them.
|
||||
|
||||
Run the appropriate command in the OctoPrint terminal window. The
|
||||
script will prompt for user interaction in the OctoPrint terminal
|
||||
output. It will look something like:
|
||||
```
|
||||
Recv: // Starting manual Z probe. Use TESTZ to adjust position.
|
||||
Recv: // Finish with ACCEPT or ABORT command.
|
||||
Recv: // Z position: ?????? --> 5.000 <-- ??????
|
||||
```
|
||||
|
||||
The current height of the nozzle (as the printer currently understands
|
||||
it) is shown between the "--> <--". The number to the right is the
|
||||
height of the last probe attempt just greater than the current height,
|
||||
and to the left is the last probe attempt less than the current height
|
||||
(or ?????? if no attempt has been made).
|
||||
|
||||
Place the paper between the nozzle and bed. It can be useful to fold a
|
||||
corner of the paper so that it is easier to grab. (Try not to push
|
||||
down on the bed when moving the paper back and forth.)
|
||||
|
||||

|
||||
|
||||
Use the TESTZ command to request the nozzle to move closer to the
|
||||
paper. For example:
|
||||
```
|
||||
TESTZ Z=-.1
|
||||
```
|
||||
|
||||
The TESTZ command will move the nozzle a relative distance from the
|
||||
nozzle's current position. (So, `Z=-.1` requests the nozzle to move
|
||||
closer to the bed by .1mm.) After the nozzle stops moving, push the
|
||||
paper back and forth to check if the nozzle is in contact with the
|
||||
paper and to feel the amount of friction. Continue issuing TESTZ
|
||||
commands until one feels a small amount of friction when testing with
|
||||
the paper.
|
||||
|
||||
If too much friction is found then one can use a positive Z value to
|
||||
move the nozzle up. It is also possible to use `TESTZ Z=+` or `TESTZ
|
||||
Z=-` to "bisect" the last position - that is to move to a position
|
||||
half way between two positions. For example, if one received the
|
||||
following prompt from a TESTZ command:
|
||||
```
|
||||
Recv: // Z position: 0.130 --> 0.230 <-- 0.280
|
||||
```
|
||||
Then a `TESTZ Z=-` would move the nozzle to a Z position of 0.180
|
||||
(half way between 0.130 and 0.230). One can use this feature to help
|
||||
rapidly narrow down to a consistent friction. It is also possible to
|
||||
use `Z=++` and `Z=--` to return directly to a past measurement - for
|
||||
example, after the above prompt a `TESTZ Z=--` command would move the
|
||||
nozzle to a Z position of 0.130.
|
||||
|
||||
After finding a small amount of friction run the ACCEPT command:
|
||||
```
|
||||
ACCEPT
|
||||
```
|
||||
This will accept the given Z height and proceed with the given
|
||||
calibration tool.
|
||||
|
||||
The exact amount of friction felt isn't crucial, just as the amount of
|
||||
thermal expansion and exact width of the paper isn't crucial. Just try
|
||||
to obtain the same amount of friction each time one runs the test.
|
||||
|
||||
If something goes wrong during the test, one can use the `ABORT`
|
||||
command to exit the calibration tool.
|
||||
|
||||
## Determining Thermal Expansion
|
||||
|
||||
After successfully performing bed leveling, one may go on to calculate
|
||||
a more precise value for the combined impact of "thermal expansion",
|
||||
"thickness of the paper", and "amount of friction felt during the paper
|
||||
test".
|
||||
|
||||
This type of calculation is generally not needed as most users find
|
||||
the simple "paper test" provides good results.
|
||||
|
||||
The easiest way to make this calculation is to print a test object
|
||||
that has straight walls on all sides. The large hollow square found in
|
||||
[docs/prints/square.stl](prints/square.stl) can be used for this.
|
||||
When slicing the object, make sure the slicer uses the same layer
|
||||
height and extrusion widths for the first level that it does for all
|
||||
subsequent layers. Use a coarse layer height (the layer height should
|
||||
be around 75% of the nozzle diameter) and do not use a brim or raft.
|
||||
|
||||
Print the test object, wait for it to cool, and remove it from the
|
||||
bed. Inspect the lowest layer of the object. (It may also be useful to
|
||||
run a finger or nail along the bottom edge.) If one finds the bottom
|
||||
layer bulges out slightly along all sides of the object then it
|
||||
indicates the nozzle was slightly closer to the bed then it should
|
||||
be. One can issue a `SET_GCODE_OFFSET Z=+.010` command to increase the
|
||||
height. In subsequent prints one can inspect for this behavior and
|
||||
make further adjustment as needed. Adjustments of this type are
|
||||
typically in 10s of microns (.010mm).
|
||||
|
||||
If the bottom layer consistently appears narrower than subsequent
|
||||
layers then one can use the SET_GCODE_OFFSET command to make a
|
||||
negative Z adjustment. If one is unsure, then one can decrease the Z
|
||||
adjustment until the bottom layer of prints exhibit a small bulge, and
|
||||
then back-off until it disappears.
|
||||
|
||||
The easiest way to apply the desired Z adjustment is to create a
|
||||
START_PRINT g-code macro, arrange for the slicer to call that macro
|
||||
during the start of each print, and add a SET_GCODE_OFFSET command to
|
||||
that macro. See the [slicers](Slicers.md) document for further
|
||||
details.
|
||||
451
docs/Bed_Mesh.md
Normal file
@@ -0,0 +1,451 @@
|
||||
# Bed Mesh
|
||||
|
||||
The Bed Mesh module may be used to compensate for bed surface irregularties to
|
||||
achieve a better first layer across the entire bed. It should be noted that
|
||||
software based correction will not achieve perfect results, it can only
|
||||
approximate the shape of the bed. Bed Mesh also cannot compensate for
|
||||
mechanical and electrical issues. If an axis is skewed or a probe is not
|
||||
accurate then the bed_mesh module will not receive accurate results from
|
||||
the probing process.
|
||||
|
||||
Prior to Mesh Calibration you will need to be sure that your Probe's
|
||||
Z-Offset is calibrated. If using an endstop for Z homing it will need
|
||||
to be calibrated as well. See [Probe Calibrate](Probe_Calibrate.md)
|
||||
and Z_ENDSTOP_CALIBRATE in [Manual Level](Manual_Level.md) for more
|
||||
information.
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
### Rectangular Beds
|
||||
This example assumes a printer with a 250 mm x 220 mm rectangular
|
||||
bed and a probe with an x-offset of 24 mm and y-offset of 5 mm.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_min: 35, 6
|
||||
mesh_max: 240, 198
|
||||
probe_count: 5, 3
|
||||
```
|
||||
|
||||
- `speed: 120`\
|
||||
_Default Value: 50_\
|
||||
The speed in which the tool moves between points.
|
||||
|
||||
- `horizontal_move_z: 5`\
|
||||
_Default Value: 5_\
|
||||
The Z coordinate the probe rises to prior to traveling between points.
|
||||
|
||||
- `mesh_min: 35, 6`\
|
||||
_Required_\
|
||||
The first probed coordinate, nearest to the origin. This coordinate
|
||||
is relative to the probe's location.
|
||||
|
||||
- `mesh_max: 240, 198`\
|
||||
_Required_\
|
||||
The probed coordinate farthest farthest from the origin. This is not
|
||||
necessarily the last point probed, as the probing process occurs in a
|
||||
zig-zag fashion. As with `mesh_min`, this coordiante is relative to
|
||||
the probe's location.
|
||||
|
||||
- `probe_count: 5, 3`\
|
||||
_Default Value: 3, 3_\
|
||||
The number of points to probe on each axis, specified as X, Y integer
|
||||
values. In this example 5 points will be probed along the X axis, with
|
||||
3 points along the Y axis, for a total of 15 probed points. Note that
|
||||
if you wanted a square grid, for example 3x3, this could be specified
|
||||
as a single integer value that is used for both axes, ie `probe_count: 3`.
|
||||
Note that a mesh requires a minimum probe_count of 3 along each axis.
|
||||
|
||||
The illustration below demonstrates how the `mesh_min`, `mesh_max`, and
|
||||
`probe_count` options are used to generate probe points. The arrows indicate
|
||||
the direction of the probing procedure, beginning at `mesh_min`. For reference,
|
||||
when the probe is at `mesh_min` the nozzle will be at (11, 1), and when the probe
|
||||
is at `mesh_max`, the nozzle will be at (206, 193).
|
||||
|
||||

|
||||
|
||||
### Round beds
|
||||
This example assumes a printer equipped with a round bed radius of 100mm.
|
||||
We will use the same probe offsets as the rectangular example, 24 mm on X
|
||||
and 5 mm on Y.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_radius: 75
|
||||
mesh_origin: 0, 0
|
||||
round_probe_count: 5
|
||||
```
|
||||
|
||||
- `mesh_radius: 75`\
|
||||
_Required_\
|
||||
The radius of the probed mesh in mm, relative to the `mesh_origin`. Note
|
||||
that the probe's offsets limit the size of the mesh radius. In this example,
|
||||
a radius larger than 76 would move the tool beyond the range of the printer.
|
||||
|
||||
- `mesh_origin: 0, 0`\
|
||||
_Default Value: 0, 0_\
|
||||
The center point of the mesh. This coordinate is relative to the probe's
|
||||
location. While the default is 0, 0, it may be useful to adjust the origin
|
||||
in an effort to probe a larger portion of the bed. See the illustration
|
||||
below.
|
||||
|
||||
- `round_probe_count: 5`\
|
||||
_Default Value: 5_\
|
||||
This is an integer value that defines the maximum number of probed points
|
||||
along the X and Y axes. By "maximum", we mean the number of points probed
|
||||
along the mesh origin. This value must be an odd number, as it is required
|
||||
that the center of the mesh is probed.
|
||||
|
||||
The illustration below shows how the probed points are generated. As you can see,
|
||||
setting the `mesh_origin` to (-10, 0) allows us to specifiy a larger mesh radius
|
||||
of 85.
|
||||
|
||||

|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
Below the more advanced configuration options are explained in detail. Each
|
||||
example will build upon the basic rectangular bed configuration shown above.
|
||||
Each of the advanced options apply to round beds in the same manner.
|
||||
|
||||
### Mesh Interpolation
|
||||
|
||||
While its possible to sample the probed matrix directly using simple bilinear
|
||||
interpolation to determine the Z-Values between probed points, it is often
|
||||
useful to interpolate extra points using more advanced interpolation algorithms
|
||||
to increase mesh density. These algorithms add curvature to the mesh,
|
||||
attempting to simulate the material properties of the bed. Bed Mesh offers
|
||||
lagrange and bicubic interpolation to accomplish this.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_min: 35, 6
|
||||
mesh_max: 240, 198
|
||||
probe_count: 5, 3
|
||||
mesh_pps: 2, 3
|
||||
algorithm: bicubic
|
||||
bicubic_tension: 0.2
|
||||
```
|
||||
|
||||
- `mesh_pps: 2, 3`\
|
||||
_Default Value: 2, 2_\
|
||||
The `mesh_pps` option is shorthand for Mesh Points Per Segment. This
|
||||
option specifies how many points to interpolate for each segment along
|
||||
the X and Y axes. Consider a 'segment' to be the space between each
|
||||
probed point. Like `probe_count`, `mesh_pps` is specified as an X, Y
|
||||
integer pair, and also may be specified a single integer that is applied
|
||||
to both axes. In this example there are 4 segments along the X axis
|
||||
and 2 segments along the Y axis. This evaluates to 8 interpolated
|
||||
points along X, 6 interpolated points along Y, which results in a 13x8
|
||||
mesh. Note that if mesh_pps is set to 0 then mesh interpolation is
|
||||
disabled and the probed matrix will be sampled directly.
|
||||
|
||||
- `algorithm: lagrange`\
|
||||
_Default Value: lagrange_\
|
||||
The algorithm used to interpolate the mesh. May be `lagrange` or `bicubic`.
|
||||
Lagrange interpolation is capped at 6 probed points as oscillation tends to
|
||||
occur with a larger number of samples. Bicubic interpolation requires a
|
||||
minimum of 4 probed points along each axis, if less than 4 points are
|
||||
specified then lagrange sampling is forced. If `mesh_pps` is set to 0 then
|
||||
this value is ignored as no mesh interpolation is done.
|
||||
|
||||
- `bicubic_tension: 0.2`\
|
||||
_Default Value: 0.2_\
|
||||
If the `algorithm` option is set to bicubic it is possible to specify the
|
||||
tension value. The higher the tension the more slope is interpolated. Be
|
||||
careful when adjusting this, as higher values also create more overshoot,
|
||||
which will result in interpolated values higher or lower than your probed
|
||||
points.
|
||||
|
||||
The illustration below shows how the options above are used to generate an
|
||||
interpolated mesh.
|
||||
|
||||

|
||||
|
||||
### Move Splitting
|
||||
|
||||
Bed Mesh works by intercepting gcode move commands and applying a
|
||||
transform to their Z coordinate. Long moves must be split into smaller
|
||||
moves to correctly follow the shape of the bed. The options below
|
||||
control the splitting behavior.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_min: 35, 6
|
||||
mesh_max: 240, 198
|
||||
probe_count: 5, 3
|
||||
move_check_distance: 5
|
||||
split_delta_z: .025
|
||||
```
|
||||
|
||||
- `move_check_distance: 5`\
|
||||
_Default Value: 5_\
|
||||
The minimum distance to check for the desired change in Z before performing
|
||||
a split. In this example, a move longer than 5mm will be traversed by the
|
||||
algorithm. Each 5mm a mesh Z lookup will occur, comparing it with the Z
|
||||
value of the previous move. If the delta meets the threshold set by
|
||||
`split_delta_z`, the move will be split and traversal will continue. This
|
||||
process repeats until the end of the move is reached, where a final
|
||||
adjustment will be applied. Moves shorter than the `move_check_distance`
|
||||
have the correct Z adjustment applied directly to the move without
|
||||
traversal or splitting.
|
||||
|
||||
- `split_delta_z: .025`\
|
||||
_Default Value: .025_\
|
||||
As mentioned above, this is the minimum deviation required to trigger a
|
||||
move split. In this example, any Z value with a deviation +/- .025mm
|
||||
will trigger a split.
|
||||
|
||||
Generally the default values for these options are sufficient, in fact the
|
||||
default value of 5mm for the `move_check_distance` may be overkill. However an
|
||||
advanced user may wish to experiment with these options in an effort to squeeze
|
||||
out the optimial first layer.
|
||||
|
||||
### Mesh Fade
|
||||
|
||||
When "fade" is enabled Z adjustment is phased out over a distance defined
|
||||
by the configuration. This is accomplished by applying small adjustments
|
||||
to the layer height, either increasing or decreasing depending on the shape
|
||||
of the bed. When fade has completed, Z adjustment is no longer applied,
|
||||
allowing the top of the print to be flat rather than mirror the shape of the
|
||||
bed. Fade also may have some undesirable traits, if you fade too quickly it
|
||||
can result in visible artifacts on the print. Also, if your bed is
|
||||
significantly warped, fade can shrink or stretch the Z height of the print.
|
||||
As such, fade is disabled by default.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_min: 35, 6
|
||||
mesh_max: 240, 198
|
||||
probe_count: 5, 3
|
||||
fade_start: 1
|
||||
fade_end: 10
|
||||
fade_target: 0
|
||||
```
|
||||
|
||||
- `fade_start: 1`\
|
||||
_Default Value: 1_\
|
||||
The Z height in which to start phasing out adjustment. It is a good idea
|
||||
to get a few layers down before starting the fade process.
|
||||
|
||||
- `fade_end: 10`\
|
||||
_Default Value: 0_\
|
||||
The Z height in which fade should complete. If this value is lower than
|
||||
`fade_start` then fade is disabled. This value may be adjusted depending
|
||||
on how warped the print surface is. A significantly warped surface should
|
||||
fade out over a longer distance. A near flat surface may be able to reduce
|
||||
this value to phase out more quickly. 10mm is a sane value to begin with if
|
||||
using the default value of 1 for `fade_start`.
|
||||
|
||||
- `fade_target: 0`\
|
||||
_Default Value: The average Z value of the mesh_\
|
||||
The `fade_target` can be thought of as an additional Z offset applied to the
|
||||
entire bed after fade completes. Generally speaking we would like this value
|
||||
to be 0, however there are circumstances where it should not be. For
|
||||
example, lets assume your homing position on the bed is an outlier, its
|
||||
.2 mm lower than the average probed height of the bed. If the `fade_target`
|
||||
is 0, fade will shrink the print by an average of .2 mm across the bed. By
|
||||
setting the `fade_target` to .2, the homed area will expand by .2 mm, however
|
||||
the rest of the bed will have an accurately sized. Generally its a good idea
|
||||
to leave `fade_target` out of the configuration so the average height of the
|
||||
mesh is used, however it may be desirable to manually adjust the fade target
|
||||
if one wants to print on a specific portion of the bed.
|
||||
|
||||
### The Relative Reference Index
|
||||
|
||||
Most probes are suceptible to drift, ie: inaccuracies in probing introduced by
|
||||
heat or interference. This can make calculating the probe's z-offset
|
||||
challenging, particuarly at different bed temperatures. As such, some printers
|
||||
use an endstop for homing the Z axis, and a probe for calibrating the mesh.
|
||||
These printers can benefit from configuring the relative reference index.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_min: 35, 6
|
||||
mesh_max: 240, 198
|
||||
probe_count: 5, 3
|
||||
relative_reference_index: 7
|
||||
```
|
||||
|
||||
- `relative_reference_index: 7`\
|
||||
_Default Value: None (disabled)_\
|
||||
When the probed points are generated they are each assigned an index. You
|
||||
can look up this index in klippy.log or by using BED_MESH_OUTPUT (see the
|
||||
section on Bed Mesh GCodes below for more information). If you assign an
|
||||
index to the `relative_reference_index` option, the value probed at this
|
||||
coordinate will replace the probe's z_offset. This effectively makes
|
||||
this coordinate the "zero" reference for the mesh.
|
||||
|
||||
When using the relative reference index, you should choose the index nearest
|
||||
to the spot on the bed where Z endstop calibration was done. Note that
|
||||
when looking up the index using the log or BED_MESH_OUTPUT, you should use
|
||||
the coordinates listed under the "Probe" header to find the correct index.
|
||||
|
||||
### Faulty Regions
|
||||
|
||||
It is possible for some areas of a bed to report inaccurate results when
|
||||
probing due to a "fault" at specific locations. The best example of this
|
||||
are beds with series of integrated magnets used to retain removable steel
|
||||
sheets. The magnetic field at and around these magnets may cause an inductive
|
||||
probe to trigger at a distance higher or lower than it would otherwise,
|
||||
resulting in a mesh that does not accurately represent the surface at these
|
||||
locations. **Note: This should not be confused with probe location bias, which
|
||||
produces inaccurate results across the entire bed.**
|
||||
|
||||
The `faulty_region` options may be configured to compensate for this affect.
|
||||
If a generated point lies within a faulty region bed mesh will attempt to
|
||||
probe up to 4 points at the boundaries of this region. These probed values
|
||||
will be averaged and inserted in the mesh as the Z value at the generated
|
||||
(X, Y) coordinate.
|
||||
|
||||
```
|
||||
[bed_mesh]
|
||||
speed: 120
|
||||
horizontal_move_z: 5
|
||||
mesh_min: 35, 6
|
||||
mesh_max: 240, 198
|
||||
probe_count: 5, 3
|
||||
faulty_region_1_min: 130.0, 0.0
|
||||
faulty_region_1_max: 145.0, 40.0
|
||||
faulty_region_2_min: 225.0, 0.0
|
||||
faulty_region_2_max: 250.0, 25.0
|
||||
faulty_region_3_min: 165.0, 95.0
|
||||
faulty_region_3_max: 205.0, 110.0
|
||||
faulty_region_4_min: 30.0, 170.0
|
||||
faulty_region_4_max: 45.0, 210.0
|
||||
```
|
||||
|
||||
- `faulty_region_{1...99}_min`\
|
||||
`faulty_region_{1..99}_max`\
|
||||
_Default Value: None (disabled)_\
|
||||
Faulty Regions are defined in a way similar to that of mesh itself, where
|
||||
minimum and maximum (X, Y) coordinates must be specified for each region.
|
||||
A faulty region may extend outside of a mesh, however the alternate points
|
||||
generated will always be within the mesh boundary. No two regions may
|
||||
overlap.
|
||||
|
||||
The image below illustrates how replacement points are generated when
|
||||
a generated point lies within a faulty region. The regions shown match those
|
||||
in the sample config above. The replacement points and their coordinates
|
||||
are identified in green.
|
||||
|
||||

|
||||
|
||||
## Bed Mesh Gcodes
|
||||
|
||||
### Calibration
|
||||
|
||||
`BED_MESH_CALIBRATE PROFILE=<name> METHOD=[manual | automatic] [<probe_parameter>=<value>]
|
||||
[<mesh_parameter>=<value>]`\
|
||||
_Default Profile: default_\
|
||||
_Default Method: automatic if a probe is detected, otherwise manual_
|
||||
|
||||
Initiates the probing procedure for Bed Mesh Calibration.
|
||||
|
||||
The mesh will be saved into a profile specified by the `PROFILE` parameter,
|
||||
or `default` if unspecified. If `METHOD=manual` is selected then manual probing
|
||||
will occur. When switching between automatic and manual probing the generated
|
||||
mesh points will automatically be adjusted.
|
||||
|
||||
It is possible to specify mesh parameters to modify the probed area. The
|
||||
following parameters are available:
|
||||
|
||||
- Rectangular beds (cartesian):
|
||||
- `MESH_MIN`
|
||||
- `MESH_MAX`
|
||||
- `PROBE_COUNT`
|
||||
- Round beds (delta):
|
||||
- `MESH_RADIUS`
|
||||
- `MESH_ORIGIN`
|
||||
- `ROUND_PROBE_COUNT`
|
||||
- All beds:
|
||||
- `RELATIVE_REFERNCE_INDEX`
|
||||
- `ALGORITHM`
|
||||
|
||||
See the configuration documentation above for details on how each parameter
|
||||
applies to the mesh.
|
||||
|
||||
### Profiles
|
||||
|
||||
`BED_MESH_PROFILE SAVE=<name> LOAD=<name> REMOVE=<name>`
|
||||
|
||||
After a BED_MESH_CALIBRATE has been performed, it is possible to save the
|
||||
current mesh state into a named profile. This makes it possible to load
|
||||
a mesh without re-probing the bed. After a profile has been saved using
|
||||
`BED_MESH_PROFILE SAVE=<name>` the `SAVE_CONFIG` gcode may be executed
|
||||
to write the profile to printer.cfg.
|
||||
|
||||
Profiles can be loaded by executing `BED_MESH_PROFILE LOAD=<name>`.
|
||||
|
||||
It should be noted that each time a BED_MESH_CALIBRATE occurs, the current
|
||||
state is automatically saved to the _default_ profile. If this profile
|
||||
exists it is automatically loaded when Klipper starts. If this behavior
|
||||
is not desirable the _default_ profile can be removed as follows:
|
||||
|
||||
`BED_MESH_PROFILE REMOVE=default`
|
||||
|
||||
Any other saved profile can be removed in the same fashion, replacing
|
||||
_default_ with the named profile you wish to remove.
|
||||
|
||||
### Output
|
||||
|
||||
`BED_MESH_OUTPUT PGP=[0 | 1]`
|
||||
|
||||
Outputs the current mesh state to the terminal. Note that the mesh itself
|
||||
is output
|
||||
|
||||
The PGP parameter is shorthand for "Print Generated Points". If `PGP=1` is
|
||||
set, the generated probed points will be output to the terminal:
|
||||
|
||||
```
|
||||
// bed_mesh: generated points
|
||||
// Index | Tool Adjusted | Probe
|
||||
// 0 | (11.0, 1.0) | (35.0, 6.0)
|
||||
// 1 | (62.2, 1.0) | (86.2, 6.0)
|
||||
// 2 | (113.5, 1.0) | (137.5, 6.0)
|
||||
// 3 | (164.8, 1.0) | (188.8, 6.0)
|
||||
// 4 | (216.0, 1.0) | (240.0, 6.0)
|
||||
// 5 | (216.0, 97.0) | (240.0, 102.0)
|
||||
// 6 | (164.8, 97.0) | (188.8, 102.0)
|
||||
// 7 | (113.5, 97.0) | (137.5, 102.0)
|
||||
// 8 | (62.2, 97.0) | (86.2, 102.0)
|
||||
// 9 | (11.0, 97.0) | (35.0, 102.0)
|
||||
// 10 | (11.0, 193.0) | (35.0, 198.0)
|
||||
// 11 | (62.2, 193.0) | (86.2, 198.0)
|
||||
// 12 | (113.5, 193.0) | (137.5, 198.0)
|
||||
// 13 | (164.8, 193.0) | (188.8, 198.0)
|
||||
// 14 | (216.0, 193.0) | (240.0, 198.0)
|
||||
```
|
||||
|
||||
The "Tool Adjusted" points refer to the nozzle location for each point, and
|
||||
the "Probe" points refer to the probe location. Note that when manually
|
||||
probing the "Probe" points will refer to both the tool and nozzle locations.
|
||||
|
||||
### Clear Mesh State
|
||||
|
||||
`BED_MESH_CLEAR`
|
||||
|
||||
This gcode may be used to clear the internal mesh state.
|
||||
|
||||
### Apply X/Y offsets
|
||||
|
||||
`BED_MESH_OFFSET [X=<value>] [Y=<value>]`
|
||||
|
||||
This is useful for printers with multiple independent extruders, as an offset
|
||||
is necessary to produce correct Z adjustment after a tool change. Offsets
|
||||
should be specified relative to the primary extruder. That is, a positive
|
||||
X offset should be specified if the secondary extruder is mounted to the
|
||||
right of the primary extruder, and a positive Y offset should be specified
|
||||
if the secondary extruder is mounted "behind" the primary extruder.
|
||||
428
docs/Benchmarks.md
Normal file
@@ -0,0 +1,428 @@
|
||||
# Benchmarks
|
||||
|
||||
This document describes Klipper benchmarks.
|
||||
|
||||
## Micro-controller Benchmarks
|
||||
|
||||
This section describes the mechanism used to generate the Klipper
|
||||
micro-controller step rate benchmarks.
|
||||
|
||||
The primary goal of the benchmarks is to provide a consistent
|
||||
mechanism for measuring the impact of coding changes within the
|
||||
software. A secondary goal is to provide high-level metrics for
|
||||
comparing the performance between chips and between software
|
||||
platforms.
|
||||
|
||||
The step rate benchmark is designed to find the maximum stepping rate
|
||||
that the hardware and software can reach. This benchmark stepping rate
|
||||
is not achievable in day-to-day use as Klipper needs to perform other
|
||||
tasks (eg, mcu/host communication, temperature reading, endstop
|
||||
checking) in any real-world usage.
|
||||
|
||||
In general, the pins for the benchmark tests are chosen to flash LEDs
|
||||
or other innocuous pins. **Always verify that it is safe to drive the
|
||||
configured pins prior to running a benchmark.** It is not recommended
|
||||
to drive an actual stepper during a benchmark.
|
||||
|
||||
### Step rate benchmark test
|
||||
|
||||
The test is performed using the console.py tool (described in
|
||||
[Debugging.md](Debugging.md)). The micro-controller is configured for
|
||||
the particular hardware platform (see below) and then the following is
|
||||
cut-and-paste into the console.py terminal window:
|
||||
```
|
||||
SET start_clock {clock+freq}
|
||||
SET ticks 1000
|
||||
|
||||
reset_step_clock oid=0 clock={start_clock}
|
||||
set_next_step_dir oid=0 dir=0
|
||||
queue_step oid=0 interval={ticks} count=60000 add=0
|
||||
set_next_step_dir oid=0 dir=1
|
||||
queue_step oid=0 interval=3000 count=1 add=0
|
||||
|
||||
reset_step_clock oid=1 clock={start_clock}
|
||||
set_next_step_dir oid=1 dir=0
|
||||
queue_step oid=1 interval={ticks} count=60000 add=0
|
||||
set_next_step_dir oid=1 dir=1
|
||||
queue_step oid=1 interval=3000 count=1 add=0
|
||||
|
||||
reset_step_clock oid=2 clock={start_clock}
|
||||
set_next_step_dir oid=2 dir=0
|
||||
queue_step oid=2 interval={ticks} count=60000 add=0
|
||||
set_next_step_dir oid=2 dir=1
|
||||
queue_step oid=2 interval=3000 count=1 add=0
|
||||
```
|
||||
|
||||
The above tests three steppers simultaneously stepping. If running the
|
||||
above results in a "Rescheduled timer in the past" or "Stepper too far
|
||||
in past" error then it indicates the `ticks` parameter is too low (it
|
||||
results in a stepping rate that is too fast). The goal is to find the
|
||||
lowest setting of the ticks parameter that reliably results in a
|
||||
successful completion of the test. It should be possible to bisect the
|
||||
ticks parameter until a stable value is found.
|
||||
|
||||
On a failure, one can copy-and-paste the following to clear the error
|
||||
in preparation for the next test:
|
||||
```
|
||||
clear_shutdown
|
||||
```
|
||||
|
||||
To obtain the single stepper benchmarks, the same configuration
|
||||
sequence is used, but only the first block of the above test is
|
||||
cut-and-paste into the console.py window.
|
||||
|
||||
To produce the benchmarks found in the [Features](Features.md) document, the total
|
||||
number of steps per second is calculated by multiplying the number of
|
||||
active steppers with the nominal mcu frequency and dividing by the
|
||||
final ticks parameter. The results are rounded to the nearest K. For
|
||||
example, with three active steppers:
|
||||
```
|
||||
ECHO Test result is: {"%.0fK" % (3. * freq / ticks / 1000.)}
|
||||
```
|
||||
|
||||
The benchmarks are run with parameters suitable for TMC Drivers. For
|
||||
micro-controllers that support `STEPPER_BOTH_EDGE=1` (as reported in
|
||||
the `MCU config` line when console.py first starts) use
|
||||
`step_pulse_duration=0` and `invert_step=-1` to enable optimized
|
||||
stepping on both edges of the step pulse. For other micro-controllers
|
||||
use a `step_pulse_duration` corresponding to 100ns.
|
||||
|
||||
### AVR step rate benchmark
|
||||
|
||||
The following configuration sequence is used on AVR chips:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PA5 dir_pin=PA4 invert_step=0 step_pulse_ticks=32
|
||||
config_stepper oid=1 step_pin=PA3 dir_pin=PA2 invert_step=0 step_pulse_ticks=32
|
||||
config_stepper oid=2 step_pin=PC7 dir_pin=PC6 invert_step=0 step_pulse_ticks=32
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version `avr-gcc
|
||||
(GCC) 5.4.0`. Both the 16Mhz and 20Mhz tests were run using simulavr
|
||||
configured for an atmega644p (previous tests have confirmed simulavr
|
||||
results match tests on both a 16Mhz at90usb and a 16Mhz atmega2560).
|
||||
|
||||
| avr | ticks |
|
||||
| ---------------- | ----- |
|
||||
| 1 stepper | 102 |
|
||||
| 3 stepper | 486 |
|
||||
|
||||
### Arduino Due step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the Due:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PB27 dir_pin=PA21 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PB26 dir_pin=PC30 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PA21 dir_pin=PC30 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`.
|
||||
|
||||
| sam3x8e | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 66 |
|
||||
| 3 stepper | 257 |
|
||||
|
||||
### Duet Maestro step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the Duet Maestro:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PC26 dir_pin=PC18 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PC26 dir_pin=PA8 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PC26 dir_pin=PB4 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`.
|
||||
|
||||
| sam4s8c | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 71 |
|
||||
| 3 stepper | 260 |
|
||||
|
||||
### Duet Wifi step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the Duet Wifi:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PD6 dir_pin=PD11 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PD7 dir_pin=PD12 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PD8 dir_pin=PD13 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`gcc version 10.3.1 20210621 (release) (GNU Arm Embedded Toolchain 10.3-2021.07)`.
|
||||
|
||||
| sam4e8e | ticks |
|
||||
| ---------------- | ----- |
|
||||
| 1 stepper | 48 |
|
||||
| 3 stepper | 215 |
|
||||
|
||||
### Beaglebone PRU step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the PRU:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=gpio0_23 dir_pin=gpio1_12 invert_step=0 step_pulse_ticks=20
|
||||
config_stepper oid=1 step_pin=gpio1_15 dir_pin=gpio0_26 invert_step=0 step_pulse_ticks=20
|
||||
config_stepper oid=2 step_pin=gpio0_22 dir_pin=gpio2_1 invert_step=0 step_pulse_ticks=20
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version `pru-gcc
|
||||
(GCC) 8.0.0 20170530 (experimental)`.
|
||||
|
||||
| pru | ticks |
|
||||
| ---------------- | ----- |
|
||||
| 1 stepper | 231 |
|
||||
| 3 stepper | 847 |
|
||||
|
||||
### STM32F042 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the STM32F042:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PA1 dir_pin=PA2 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PA3 dir_pin=PA2 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PB8 dir_pin=PA2 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`.
|
||||
|
||||
| stm32f042 | ticks |
|
||||
| ---------------- | ----- |
|
||||
| 1 stepper | 59 |
|
||||
| 3 stepper | 249 |
|
||||
|
||||
### STM32F103 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the STM32F103:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PC13 dir_pin=PB5 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PB3 dir_pin=PB6 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PA4 dir_pin=PB7 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`.
|
||||
|
||||
| stm32f103 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 61 |
|
||||
| 3 stepper | 264 |
|
||||
|
||||
### STM32F4 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the STM32F4:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PA5 dir_pin=PB5 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PB2 dir_pin=PB6 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PB3 dir_pin=PB7 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`. The STM32F407
|
||||
results were obtained by running an STM32F407 binary on an STM32F446
|
||||
(and thus using a 168Mhz clock).
|
||||
|
||||
| stm32f446 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 46 |
|
||||
| 3 stepper | 205 |
|
||||
|
||||
| stm32f407 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 46 |
|
||||
| 3 stepper | 205 |
|
||||
|
||||
### STM32G0B1 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the STM32G0B1:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PB13 dir_pin=PB12 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PB10 dir_pin=PB2 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PB0 dir_pin=PC5 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `247cd753` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`.
|
||||
|
||||
| stm32g0b1 | ticks |
|
||||
| ---------------- | ----- |
|
||||
| 1 stepper | 58 |
|
||||
| 3 stepper | 243 |
|
||||
|
||||
### LPC176x step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the LPC176x:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=P1.20 dir_pin=P1.18 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=P1.21 dir_pin=P1.18 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=P1.23 dir_pin=P1.18 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0`. The 120Mhz LPC1769
|
||||
results were obtained by overclocking an LPC1768 to 120Mhz.
|
||||
|
||||
| lpc1768 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 52 |
|
||||
| 3 stepper | 222 |
|
||||
|
||||
| lpc1769 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 51 |
|
||||
| 3 stepper | 222 |
|
||||
|
||||
### SAMD21 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the SAMD21:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PA27 dir_pin=PA20 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PB3 dir_pin=PA21 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PA17 dir_pin=PA21 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0` on a SAMD21G18
|
||||
micro-controller.
|
||||
|
||||
| samd21 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 70 |
|
||||
| 3 stepper | 306 |
|
||||
|
||||
### SAMD51 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the SAMD51:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=PA22 dir_pin=PA20 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=PA22 dir_pin=PA21 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=PA22 dir_pin=PA19 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0` on a SAMD51J19A
|
||||
micro-controller.
|
||||
|
||||
| samd51 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 39 |
|
||||
| 3 stepper | 191 |
|
||||
| 1 stepper (200Mhz) | 39 |
|
||||
| 3 stepper (200Mhz) | 181 |
|
||||
|
||||
### RP2040 step rate benchmark
|
||||
|
||||
The following configuration sequence is used on the RP2040:
|
||||
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=gpio25 dir_pin=gpio3 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=1 step_pin=gpio26 dir_pin=gpio4 invert_step=-1 step_pulse_ticks=0
|
||||
config_stepper oid=2 step_pin=gpio27 dir_pin=gpio5 invert_step=-1 step_pulse_ticks=0
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0` on a Raspberry Pi
|
||||
Pico board.
|
||||
|
||||
| rp2040 | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 5 |
|
||||
| 3 stepper | 22 |
|
||||
|
||||
### Linux MCU step rate benchmark
|
||||
|
||||
The following configuration sequence is used on a Raspberry Pi:
|
||||
```
|
||||
allocate_oids count=3
|
||||
config_stepper oid=0 step_pin=gpio2 dir_pin=gpio3 invert_step=0 step_pulse_ticks=5
|
||||
config_stepper oid=1 step_pin=gpio4 dir_pin=gpio5 invert_step=0 step_pulse_ticks=5
|
||||
config_stepper oid=2 step_pin=gpio6 dir_pin=gpio17 invert_step=0 step_pulse_ticks=5
|
||||
finalize_config crc=0
|
||||
```
|
||||
|
||||
The test was last run on commit `59314d99` with gcc version
|
||||
`gcc (Raspbian 8.3.0-6+rpi1) 8.3.0` on a Raspberry Pi 3 (revision
|
||||
a02082). It was difficult to get stable results in this benchmark.
|
||||
|
||||
| Linux (RPi3) | ticks |
|
||||
| -------------------- | ----- |
|
||||
| 1 stepper | 160 |
|
||||
| 3 stepper | 380 |
|
||||
|
||||
## Command dispatch benchmark
|
||||
|
||||
The command dispatch benchmark tests how many "dummy" commands the
|
||||
micro-controller can process. It is primarily a test of the hardware
|
||||
communication mechanism. The test is run using the console.py tool
|
||||
(described in [Debugging.md](Debugging.md)). The following is
|
||||
cut-and-paste into the console.py terminal window:
|
||||
```
|
||||
DELAY {clock + 2*freq} get_uptime
|
||||
FLOOD 100000 0.0 debug_nop
|
||||
get_uptime
|
||||
```
|
||||
|
||||
When the test completes, determine the difference between the clocks
|
||||
reported in the two "uptime" response messages. The total number of
|
||||
commands per second is then `100000 * mcu_frequency / clock_diff`.
|
||||
|
||||
Note that this test may saturate the USB/CPU capacity of a Raspberry
|
||||
Pi. If running on a Raspberry Pi, Beaglebone, or similar host computer
|
||||
then increase the delay (eg, `DELAY {clock + 20*freq} get_uptime`).
|
||||
Where applicable, the benchmarks below are with console.py running on
|
||||
a desktop class machine with the device connected via a high-speed
|
||||
hub.
|
||||
|
||||
| MCU | Rate | Build | Build compiler |
|
||||
| ------------------- | ---- | -------- | ------------------- |
|
||||
| stm32f042 (CAN) | 18K | c105adc8 | arm-none-eabi-gcc (GNU Tools 7-2018-q3-update) 7.3.1 |
|
||||
| atmega2560 (serial) | 23K | b161a69e | avr-gcc (GCC) 4.8.1 |
|
||||
| sam3x8e (serial) | 23K | b161a69e | arm-none-eabi-gcc (Fedora 7.1.0-5.fc27) 7.1.0 |
|
||||
| at90usb1286 (USB) | 75K | 01d2183f | avr-gcc (GCC) 5.4.0 |
|
||||
| samd21 (USB) | 223K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| pru (shared memory) | 260K | c5968a08 | pru-gcc (GCC) 8.0.0 20170530 (experimental) |
|
||||
| stm32f103 (USB) | 355K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| sam3x8e (USB) | 418K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| lpc1768 (USB) | 534K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| lpc1769 (USB) | 628K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| sam4s8c (USB) | 650K | 8d4a5c16 | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| samd51 (USB) | 864K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| stm32f446 (USB) | 870K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
|
||||
| rp2040 (USB) | 873K | c5667193 | arm-none-eabi-gcc (Fedora 10.2.0-4.fc34) 10.2.0 |
|
||||
|
||||
## Host Benchmarks
|
||||
|
||||
It is possible to run timing tests on the host software using the
|
||||
"batch mode" processing mechanism (described in
|
||||
[Debugging.md](Debugging.md)). This is typically done by choosing a
|
||||
large and complex G-Code file and timing how long it takes for the
|
||||
host software to process it. For example:
|
||||
```
|
||||
time ~/klippy-env/bin/python ./klippy/klippy.py config/example-cartesian.cfg -i something_complex.gcode -o /dev/null -d out/klipper.dict
|
||||
```
|
||||
620
docs/Bootloaders.md
Normal file
@@ -0,0 +1,620 @@
|
||||
# Bootloaders
|
||||
|
||||
This document provides information on common bootloaders found on
|
||||
micro-controllers that Klipper supports.
|
||||
|
||||
The bootloader is 3rd-party software that runs on the micro-controller
|
||||
when it is first powered on. It is typically used to flash a new
|
||||
application (eg, Klipper) to the micro-controller without requiring
|
||||
specialized hardware. Unfortunately, there is no industry wide
|
||||
standard for flashing a micro-controller, nor is there a standard
|
||||
bootloader that works across all micro-controllers. Worse, it is
|
||||
common for each bootloader to require a different set of steps to
|
||||
flash an application.
|
||||
|
||||
If one can flash a bootloader to a micro-controller then one can
|
||||
generally also use that mechanism to flash an application, but care
|
||||
should be taken when doing this as one may inadvertently remove the
|
||||
bootloader. In contrast, a bootloader will generally only permit a
|
||||
user to flash an application. It is therefore recommended to use a
|
||||
bootloader to flash an application where possible.
|
||||
|
||||
This document attempts to describe common bootloaders, the steps
|
||||
needed to flash a bootloader, and the steps needed to flash an
|
||||
application. This document is not an authoritative reference; it is
|
||||
intended as a collection of useful information that the Klipper
|
||||
developers have accumulated.
|
||||
|
||||
## AVR micro-controllers
|
||||
|
||||
|
||||
In general, the Arduino project is a good reference for bootloaders
|
||||
and flashing procedures on the 8-bit Atmel Atmega micro-controllers.
|
||||
In particular, the "boards.txt" file:
|
||||
[https://github.com/arduino/Arduino/blob/1.8.5/hardware/arduino/avr/boards.txt](https://github.com/arduino/Arduino/blob/1.8.5/hardware/arduino/avr/boards.txt)
|
||||
is a useful reference.
|
||||
|
||||
To flash a bootloader itself, the AVR chips require an external
|
||||
hardware flashing tool (which communicates with the chip using
|
||||
SPI). This tool can be purchased (for example, do a web search for
|
||||
"avr isp", "arduino isp", or "usb tiny isp"). It is also possible to
|
||||
use another Arduino or Raspberry Pi to flash an AVR bootloader (for
|
||||
example, do a web search for "program an avr using raspberry pi"). The
|
||||
examples below are written assuming an "AVR ISP Mk2" type device is in
|
||||
use.
|
||||
|
||||
The "avrdude" program is the most common tool used to flash atmega
|
||||
chips (both bootloader flashing and application flashing).
|
||||
|
||||
### Atmega2560
|
||||
|
||||
This chip is typically found in the "Arduino Mega" and is very common
|
||||
in 3d printer boards.
|
||||
|
||||
To flash the bootloader itself use something like:
|
||||
```
|
||||
wget 'https://github.com/arduino/Arduino/raw/1.8.5/hardware/arduino/avr/bootloaders/stk500v2/stk500boot_v2_mega2560.hex'
|
||||
|
||||
avrdude -cavrispv2 -patmega2560 -P/dev/ttyACM0 -b115200 -e -u -U lock:w:0x3F:m -U efuse:w:0xFD:m -U hfuse:w:0xD8:m -U lfuse:w:0xFF:m
|
||||
avrdude -cavrispv2 -patmega2560 -P/dev/ttyACM0 -b115200 -U flash:w:stk500boot_v2_mega2560.hex
|
||||
avrdude -cavrispv2 -patmega2560 -P/dev/ttyACM0 -b115200 -U lock:w:0x0F:m
|
||||
```
|
||||
|
||||
To flash an application use something like:
|
||||
```
|
||||
avrdude -cwiring -patmega2560 -P/dev/ttyACM0 -b115200 -D -Uflash:w:out/klipper.elf.hex:i
|
||||
```
|
||||
|
||||
### Atmega1280
|
||||
|
||||
This chip is typically found in earlier versions of the "Arduino
|
||||
Mega".
|
||||
|
||||
To flash the bootloader itself use something like:
|
||||
```
|
||||
wget 'https://github.com/arduino/Arduino/raw/1.8.5/hardware/arduino/avr/bootloaders/atmega/ATmegaBOOT_168_atmega1280.hex'
|
||||
|
||||
avrdude -cavrispv2 -patmega1280 -P/dev/ttyACM0 -b115200 -e -u -U lock:w:0x3F:m -U efuse:w:0xF5:m -U hfuse:w:0xDA:m -U lfuse:w:0xFF:m
|
||||
avrdude -cavrispv2 -patmega1280 -P/dev/ttyACM0 -b115200 -U flash:w:ATmegaBOOT_168_atmega1280.hex
|
||||
avrdude -cavrispv2 -patmega1280 -P/dev/ttyACM0 -b115200 -U lock:w:0x0F:m
|
||||
```
|
||||
|
||||
To flash an application use something like:
|
||||
```
|
||||
avrdude -carduino -patmega1280 -P/dev/ttyACM0 -b57600 -D -Uflash:w:out/klipper.elf.hex:i
|
||||
```
|
||||
|
||||
### Atmega1284p
|
||||
|
||||
This chip is commonly found in "Melzi" style 3d printer boards.
|
||||
|
||||
To flash the bootloader itself use something like:
|
||||
```
|
||||
wget 'https://github.com/Lauszus/Sanguino/raw/1.0.2/bootloaders/optiboot/optiboot_atmega1284p.hex'
|
||||
|
||||
avrdude -cavrispv2 -patmega1284p -P/dev/ttyACM0 -b115200 -e -u -U lock:w:0x3F:m -U efuse:w:0xFD:m -U hfuse:w:0xDE:m -U lfuse:w:0xFF:m
|
||||
avrdude -cavrispv2 -patmega1284p -P/dev/ttyACM0 -b115200 -U flash:w:optiboot_atmega1284p.hex
|
||||
avrdude -cavrispv2 -patmega1284p -P/dev/ttyACM0 -b115200 -U lock:w:0x0F:m
|
||||
```
|
||||
|
||||
To flash an application use something like:
|
||||
```
|
||||
avrdude -carduino -patmega1284p -P/dev/ttyACM0 -b115200 -D -Uflash:w:out/klipper.elf.hex:i
|
||||
```
|
||||
|
||||
Note that a number of "Melzi" style boards come preloaded with a
|
||||
bootloader that uses a baud rate of 57600. In this case, to flash an
|
||||
application use something like this instead:
|
||||
```
|
||||
avrdude -carduino -patmega1284p -P/dev/ttyACM0 -b57600 -D -Uflash:w:out/klipper.elf.hex:i
|
||||
```
|
||||
|
||||
### At90usb1286
|
||||
|
||||
This document does not cover the method to flash a bootloader to the
|
||||
At90usb1286 nor does it cover general application flashing to this
|
||||
device.
|
||||
|
||||
The Teensy++ device from pjrc.com comes with a proprietary bootloader.
|
||||
It requires a custom flashing tool from
|
||||
[https://github.com/PaulStoffregen/teensy_loader_cli](https://github.com/PaulStoffregen/teensy_loader_cli).
|
||||
One can flash an application with it using something like:
|
||||
|
||||
```
|
||||
teensy_loader_cli --mcu=at90usb1286 out/klipper.elf.hex -v
|
||||
```
|
||||
|
||||
### Atmega168
|
||||
|
||||
The atmega168 has limited flash space. If using a bootloader, it is
|
||||
recommended to use the Optiboot bootloader. To flash that bootloader
|
||||
use something like:
|
||||
```
|
||||
wget 'https://github.com/arduino/Arduino/raw/1.8.5/hardware/arduino/avr/bootloaders/optiboot/optiboot_atmega168.hex'
|
||||
|
||||
avrdude -cavrispv2 -patmega168 -P/dev/ttyACM0 -b115200 -e -u -U lock:w:0x3F:m -U efuse:w:0x04:m -U hfuse:w:0xDD:m -U lfuse:w:0xFF:m
|
||||
avrdude -cavrispv2 -patmega168 -P/dev/ttyACM0 -b115200 -U flash:w:optiboot_atmega168.hex
|
||||
avrdude -cavrispv2 -patmega168 -P/dev/ttyACM0 -b115200 -U lock:w:0x0F:m
|
||||
```
|
||||
|
||||
To flash an application via the Optiboot bootloader use something
|
||||
like:
|
||||
```
|
||||
avrdude -carduino -patmega168 -P/dev/ttyACM0 -b115200 -D -Uflash:w:out/klipper.elf.hex:i
|
||||
```
|
||||
|
||||
## SAM3 micro-controllers (Arduino Due)
|
||||
|
||||
It is not common to use a bootloader with the SAM3 mcu. The chip
|
||||
itself has a ROM that allows the flash to be programmed from 3.3V
|
||||
serial port or from USB.
|
||||
|
||||
To enable the ROM, the "erase" pin is held high during a reset, which
|
||||
erases the flash contents, and causes the ROM to run. On an Arduino
|
||||
Due, this sequence can be accomplished by setting a baud rate of 1200
|
||||
on the "programming usb port" (the USB port closest to the power
|
||||
supply).
|
||||
|
||||
The code at
|
||||
[https://github.com/shumatech/BOSSA](https://github.com/shumatech/BOSSA)
|
||||
can be used to program the SAM3. It is recommended to use version 1.9
|
||||
or later.
|
||||
|
||||
To flash an application use something like:
|
||||
```
|
||||
bossac -U -p /dev/ttyACM0 -a -e -w out/klipper.bin -v -b
|
||||
bossac -U -p /dev/ttyACM0 -R
|
||||
```
|
||||
|
||||
## SAM4 micro-controllers (Duet Wifi)
|
||||
|
||||
It is not common to use a bootloader with the SAM4 mcu. The chip
|
||||
itself has a ROM that allows the flash to be programmed from 3.3V
|
||||
serial port or from USB.
|
||||
|
||||
To enable the ROM, the "erase" pin is held high during a reset, which
|
||||
erases the flash contents, and causes the ROM to run.
|
||||
|
||||
The code at
|
||||
[https://github.com/shumatech/BOSSA](https://github.com/shumatech/BOSSA)
|
||||
can be used to program the SAM4. It is necessary to use version
|
||||
`1.8.0` or higher.
|
||||
|
||||
To flash an application use something like:
|
||||
```
|
||||
bossac --port=/dev/ttyACM0 -b -U -e -w -v -R out/klipper.bin
|
||||
```
|
||||
|
||||
## SAMD21 micro-controllers (Arduino Zero)
|
||||
|
||||
The SAMD21 bootloader is flashed via the ARM Serial Wire Debug (SWD)
|
||||
interface. This is commonly done with a dedicated SWD hardware dongle.
|
||||
Alternatively, one can use a
|
||||
[Raspberry Pi with OpenOCD](#running-openocd-on-the-raspberry-pi).
|
||||
|
||||
To flash a bootloader with OpenOCD use the following chip config:
|
||||
```
|
||||
source [find target/at91samdXX.cfg]
|
||||
```
|
||||
Obtain a bootloader - for example:
|
||||
```
|
||||
wget 'https://github.com/arduino/ArduinoCore-samd/raw/1.8.3/bootloaders/zero/samd21_sam_ba.bin'
|
||||
```
|
||||
Flash with OpenOCD commands similar to:
|
||||
```
|
||||
at91samd bootloader 0
|
||||
program samd21_sam_ba.bin verify
|
||||
```
|
||||
|
||||
The most common bootloader on the SAMD21 is the one found on the
|
||||
"Arduino Zero". It uses an 8KiB bootloader (the application must be
|
||||
compiled with a start address of 8KiB). One can enter this bootloader
|
||||
by double clicking the reset button. To flash an application use
|
||||
something like:
|
||||
```
|
||||
bossac -U -p /dev/ttyACM0 --offset=0x2000 -w out/klipper.bin -v -b -R
|
||||
```
|
||||
|
||||
In contrast, the "Arduino M0" uses a 16KiB bootloader (the application
|
||||
must be compiled with a start address of 16KiB). To flash an
|
||||
application on this bootloader, reset the micro-controller and run the
|
||||
flash command within the first few seconds of boot - something like:
|
||||
```
|
||||
avrdude -c stk500v2 -p atmega2560 -P /dev/ttyACM0 -u -Uflash:w:out/klipper.elf.hex:i
|
||||
```
|
||||
|
||||
## SAMD51 micro-controllers (Adafruit Metro-M4 and similar)
|
||||
|
||||
Like the SAMD21, the SAMD51 bootloader is flashed via the ARM Serial
|
||||
Wire Debug (SWD) interface. To flash a bootloader with
|
||||
[OpenOCD on a Raspberry Pi](#running-openocd-on-the-raspberry-pi) use
|
||||
the following chip config:
|
||||
```
|
||||
source [find target/atsame5x.cfg]
|
||||
```
|
||||
Obtain a bootloader - several bootloaders are available from
|
||||
[https://github.com/adafruit/uf2-samdx1/releases/latest](https://github.com/adafruit/uf2-samdx1/releases/latest). For example:
|
||||
```
|
||||
wget 'https://github.com/adafruit/uf2-samdx1/releases/download/v3.7.0/bootloader-itsybitsy_m4-v3.7.0.bin'
|
||||
```
|
||||
Flash with OpenOCD commands similar to:
|
||||
```
|
||||
at91samd bootloader 0
|
||||
program bootloader-itsybitsy_m4-v3.7.0.bin verify
|
||||
at91samd bootloader 16384
|
||||
```
|
||||
|
||||
The SAMD51 uses a 16KiB bootloader (the application must be compiled
|
||||
with a start address of 16KiB). To flash an application use something
|
||||
like:
|
||||
```
|
||||
bossac -U -p /dev/ttyACM0 --offset=0x4000 -w out/klipper.bin -v -b -R
|
||||
```
|
||||
|
||||
## STM32F103 micro-controllers (Blue Pill devices)
|
||||
|
||||
The STM32F103 devices have a ROM that can flash a bootloader or
|
||||
application via 3.3V serial. Typically one would wire the PA10 (MCU
|
||||
Rx) and PA9 (MCU Tx) pins to a 3.3V UART adapter. To access the ROM,
|
||||
one should connect the "boot 0" pin to high and "boot 1" pin to low,
|
||||
and then reset the device. The "stm32flash" package can then be used
|
||||
to flash the device using something like:
|
||||
```
|
||||
stm32flash -w out/klipper.bin -v -g 0 /dev/ttyAMA0
|
||||
```
|
||||
|
||||
Note that if one is using a Raspberry Pi for the 3.3V serial, the
|
||||
stm32flash protocol uses a serial parity mode which the Raspberry Pi's
|
||||
"mini UART" does not support. See
|
||||
[https://www.raspberrypi.com/documentation/computers/configuration.html#configuring-uarts](https://www.raspberrypi.com/documentation/computers/configuration.html#configuring-uarts)
|
||||
for details on enabling the full uart on the Raspberry Pi GPIO pins.
|
||||
|
||||
After flashing, set both "boot 0" and "boot 1" back to low so that
|
||||
future resets boot from flash.
|
||||
|
||||
### STM32F103 with stm32duino bootloader
|
||||
|
||||
The "stm32duino" project has a USB capable bootloader - see:
|
||||
[https://github.com/rogerclarkmelbourne/STM32duino-bootloader](https://github.com/rogerclarkmelbourne/STM32duino-bootloader)
|
||||
|
||||
This bootloader can be flashed via 3.3V serial with something like:
|
||||
```
|
||||
wget 'https://github.com/rogerclarkmelbourne/STM32duino-bootloader/raw/master/binaries/generic_boot20_pc13.bin'
|
||||
|
||||
stm32flash -w generic_boot20_pc13.bin -v -g 0 /dev/ttyAMA0
|
||||
```
|
||||
|
||||
This bootloader uses 8KiB of flash space (the application must be
|
||||
compiled with a start address of 8KiB). Flash an application with
|
||||
something like:
|
||||
```
|
||||
dfu-util -d 1eaf:0003 -a 2 -R -D out/klipper.bin
|
||||
```
|
||||
|
||||
The bootloader typically runs for only a short period after boot. It
|
||||
may be necessary to time the above command so that it runs while the
|
||||
bootloader is still active (the bootloader will flash a board led
|
||||
while it is running). Alternatively, set the "boot 0" pin to low and
|
||||
"boot 1" pin to high to stay in the bootloader after a reset.
|
||||
|
||||
### STM32F103 with HID bootloader
|
||||
|
||||
The [HID bootloader](https://github.com/Serasidis/STM32_HID_Bootloader) is a
|
||||
compact, driverless bootloader capable of flashing over USB. Also available
|
||||
is a [fork with builds specific to the SKR Mini E3 1.2](
|
||||
https://github.com/Arksine/STM32_HID_Bootloader/releases/latest).
|
||||
|
||||
For generic STM32F103 boards such as the blue pill it is possible to flash
|
||||
the bootloader via 3.3v serial using stm32flash as noted in the stm32duino
|
||||
section above, substituting the file name for the desired hid bootloader binary
|
||||
(ie: hid_generic_pc13.bin for the blue pill).
|
||||
|
||||
It is not possible to use stm32flash for the SKR Mini E3 as the boot0 pin is
|
||||
tied directly to ground and not broken out via header pins. It is recommended
|
||||
to use a STLink V2 with STM32Cubeprogrammer to flash the bootloader. If you
|
||||
don't have access to a STLink it is also possible to use a
|
||||
[Raspberry Pi and OpenOCD](#running-openocd-on-the-raspberry-pi) with
|
||||
the following chip config:
|
||||
|
||||
```
|
||||
source [find target/stm32f1x.cfg]
|
||||
```
|
||||
If you wish you can make a backup of the current flash with the following
|
||||
command. Note that it may take some time to complete:
|
||||
```
|
||||
flash read_bank 0 btt_skr_mini_e3_backup.bin
|
||||
```
|
||||
finally, you can flash with commands similar to:
|
||||
```
|
||||
stm32f1x mass_erase 0
|
||||
program hid_btt_skr_mini_e3.bin verify 0x08000000
|
||||
```
|
||||
NOTES:
|
||||
- The example above erases the chip then programs the bootloader. Regardless
|
||||
of the method chosen to flash it is recommended to erase the chip prior to
|
||||
flashing.
|
||||
- Prior flashing the SKR Mini E3 with this bootloader you should be aware
|
||||
that you will no longer be able to update firmware via the sdcard.
|
||||
- You may need to hold down the reset button on the board while launching
|
||||
OpenOCD. It should display something like:
|
||||
```
|
||||
Open On-Chip Debugger 0.10.0+dev-01204-gc60252ac-dirty (2020-04-27-16:00)
|
||||
Licensed under GNU GPL v2
|
||||
For bug reports, read
|
||||
http://openocd.org/doc/doxygen/bugs.html
|
||||
DEPRECATED! use 'adapter speed' not 'adapter_khz'
|
||||
Info : BCM2835 GPIO JTAG/SWD bitbang driver
|
||||
Info : JTAG and SWD modes enabled
|
||||
Info : clock speed 40 kHz
|
||||
Info : SWD DPIDR 0x1ba01477
|
||||
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
|
||||
Info : stm32f1x.cpu: external reset detected
|
||||
Info : starting gdb server for stm32f1x.cpu on 3333
|
||||
Info : Listening on port 3333 for gdb connections
|
||||
```
|
||||
After which you can release the reset button.
|
||||
|
||||
|
||||
This bootloader requires 2KiB of flash space (the application
|
||||
must be compiled with a start address of 2KiB).
|
||||
|
||||
The hid-flash program is used to upload a binary to the bootloader. You
|
||||
can install this software with the following commands:
|
||||
```
|
||||
sudo apt install libusb-1.0
|
||||
cd ~/klipper/lib/hidflash
|
||||
make
|
||||
```
|
||||
|
||||
If the bootloader is running you can flash with something like:
|
||||
```
|
||||
~/klipper/lib/hidflash/hid-flash ~/klipper/out/klipper.bin
|
||||
```
|
||||
alternatively, you can use `make flash` to flash klipper directly:
|
||||
```
|
||||
make flash FLASH_DEVICE=1209:BEBA
|
||||
```
|
||||
OR if klipper has been previously flashed:
|
||||
```
|
||||
make flash FLASH_DEVICE=/dev/ttyACM0
|
||||
```
|
||||
|
||||
It may be necessary to manually enter the bootloader, this can be done by
|
||||
setting "boot 0" low and "boot 1" high. On the SKR Mini E3 "Boot 1" is
|
||||
not available, so it may be done by setting pin PA2 low if you flashed
|
||||
"hid_btt_skr_mini_e3.bin". This pin is labeld "TX0" on the TFT header in
|
||||
the SKR Mini E3's "PIN" document. There is a ground pin next to PA2
|
||||
which you can use to pull PA2 low.
|
||||
|
||||
### STM32F103/STM32F072 with MSC bootloader
|
||||
|
||||
The [MSC bootloader](https://github.com/Telekatz/MSC-stm32f103-bootloader) is a driverless bootloader capable of flashing over USB.
|
||||
|
||||
It is possible to flash the bootloader via 3.3v serial using stm32flash as noted
|
||||
in the stm32duino section above, substituting the file name for the desired
|
||||
MSC bootloader binary (ie: MSCboot-Bluepill.bin for the blue pill).
|
||||
|
||||
For STM32F072 boards it is also possible to flash the bootloader over USB (via DFU)
|
||||
with something like:
|
||||
|
||||
```
|
||||
dfu-util -d 0483:df11 -a 0 -R -D MSCboot-STM32F072.bin -s0x08000000:leave
|
||||
```
|
||||
|
||||
This bootloader uses 8KiB or 16KiB of flash space, see description of the bootloader
|
||||
(the application must be compiled with with the corresponding starting address).
|
||||
|
||||
The bootloader can be activated by pressing the reset button of the board twice.
|
||||
As soon as the bootloader is activated, the board appears as a USB flash drive
|
||||
onto which the klipper.bin file can be copied.
|
||||
|
||||
### STM32F103/STM32F0x2 with CanBoot bootloader
|
||||
|
||||
The [CanBoot](https://github.com/Arksine/CanBoot) bootloader provides an option
|
||||
for uploading Klipper firmware over the CANBUS. The bootloader itself is
|
||||
derived from Klipper's source code. Currently CanBoot supports the STM32F103,
|
||||
STM32F042, and STM32F072 models.
|
||||
|
||||
It is recommended to use a ST-Link Programmer to flash CanBoot, however it
|
||||
should be possible to flash using `stm32flash` on STM32F103 devices, and
|
||||
`dfu-util` on STM32F042/STM32F072 devices. See the previous sections in this
|
||||
document for instructions on these flashing methods, substituting `canboot.bin`
|
||||
for the file name where appropriate. The CanBoot repo linked above provides
|
||||
instructions for building the bootloader.
|
||||
|
||||
The first time CanBoot has been flashed it should detect that no application
|
||||
is present and enter the bootloader. If this doesn't occur it is possible to
|
||||
enter the bootloader by pressing the reset button twice in succession.
|
||||
|
||||
The `flash_can.py` utility supplied in the `lib/canboot` folder may be used to
|
||||
upload Klipper firmware. The device UUID is necessary to flash. If you do not
|
||||
have a UUID it is possible to query nodes currently running the bootloader:
|
||||
```
|
||||
python3 flash_can.py -q
|
||||
```
|
||||
This will return UUIDs for all connected nodes not currently assigned a UUID.
|
||||
This should include all nodes currently in the bootloader.
|
||||
|
||||
Once you have a UUID, you may upload firmware with following command:
|
||||
```
|
||||
python3 flash_can.py -i can0 -f ~/klipper/out/klipper.bin -u aabbccddeeff
|
||||
```
|
||||
|
||||
Where `aabbccddeeff` is replaced by your UUID. Note that the `-i` and `-f`
|
||||
options may be omitted, they default to `can0` and `~/klipper/out/klipper.bin`
|
||||
respectively.
|
||||
|
||||
When building Klipper for use with CanBoot, select the 8 KiB Bootloader option.
|
||||
|
||||
## STM32F4 micro-controllers (SKR Pro 1.1)
|
||||
|
||||
STM32F4 microcontrollers come equipped with a built-in system bootloader
|
||||
capable of flashing over USB (via DFU), 3.3v Serial, and various other
|
||||
methods (see STM Document AN2606 for more information). Some
|
||||
STM32F4 boards, such as the SKR Pro 1.1, are not able to enter the DFU
|
||||
bootloader. The HID bootloader is available for STM32F405/407
|
||||
based boards should the user prefer flashing over USB over using the sdcard.
|
||||
Note that you may need to configure and build a version specific to your
|
||||
board, a [build for the SKR Pro 1.1 is available here](
|
||||
https://github.com/Arksine/STM32_HID_Bootloader/releases/latest).
|
||||
|
||||
Unless your board is DFU capable the most accessable flashing method
|
||||
is likely via 3.3v serial, which follows the same procedure as
|
||||
[flashing the STM32F103 using stm32flash](#stm32f103-micro-controllers-blue-pill-devices).
|
||||
For example:
|
||||
```
|
||||
wget https://github.com/Arksine/STM32_HID_Bootloader/releases/download/v0.5-beta/hid_bootloader_SKR_PRO.bin
|
||||
|
||||
stm32flash -w hid_bootloader_SKR_PRO.bin -v -g 0 /dev/ttyAMA0
|
||||
```
|
||||
|
||||
This bootloader requires 16Kib of flash space on the STM32F4 (the application
|
||||
must be compiled with a start address of 16KiB).
|
||||
|
||||
As with the STM32F1, the STM32F4 uses the hid-flash tool to upload binaries to
|
||||
the MCU. See the instructions above for details on how to build and use
|
||||
hid-flash.
|
||||
|
||||
It may be necessary to manually enter the bootloader, this can be done by
|
||||
setting "boot 0" low, "boot 1" high and plugging in the device. After
|
||||
programming is complete unplug the device and set "boot 1" back to low
|
||||
so the application will be loaded.
|
||||
|
||||
## LPC176x micro-controllers (Smoothieboards)
|
||||
|
||||
This document does not describe the method to flash a bootloader
|
||||
itself - see:
|
||||
[http://smoothieware.org/flashing-the-bootloader](http://smoothieware.org/flashing-the-bootloader)
|
||||
for further information on that topic.
|
||||
|
||||
It is common for Smoothieboards to come with a bootloader from:
|
||||
[https://github.com/triffid/LPC17xx-DFU-Bootloader](https://github.com/triffid/LPC17xx-DFU-Bootloader).
|
||||
When using this bootloader the application must be compiled with a
|
||||
start address of 16KiB. The easiest way to flash an application with
|
||||
this bootloader is to copy the application file (eg,
|
||||
`out/klipper.bin`) to a file named `firmware.bin` on an SD card, and
|
||||
then to reboot the micro-controller with that SD card.
|
||||
|
||||
## Running OpenOCD on the Raspberry PI
|
||||
|
||||
OpenOCD is a software package that can perform low-level chip flashing
|
||||
and debugging. It can use the GPIO pins on a Raspberry Pi to
|
||||
communicate with a variety of ARM chips.
|
||||
|
||||
This section describes how one can install and launch OpenOCD. It is
|
||||
derived from the instructions at:
|
||||
[https://learn.adafruit.com/programming-microcontrollers-using-openocd-on-raspberry-pi](https://learn.adafruit.com/programming-microcontrollers-using-openocd-on-raspberry-pi)
|
||||
|
||||
Begin by downloading and compiling the software (each step may take
|
||||
several minutes and the "make" step may take 30+ minutes):
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install autoconf libtool telnet
|
||||
mkdir ~/openocd
|
||||
cd ~/openocd/
|
||||
git clone http://openocd.zylin.com/openocd
|
||||
cd openocd
|
||||
./bootstrap
|
||||
./configure --enable-sysfsgpio --enable-bcm2835gpio --prefix=/home/pi/openocd/install
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
### Configure OpenOCD
|
||||
|
||||
Create an OpenOCD config file:
|
||||
|
||||
```
|
||||
nano ~/openocd/openocd.cfg
|
||||
```
|
||||
|
||||
Use a config similar to the following:
|
||||
|
||||
```
|
||||
# Uses RPi pins: GPIO25 for SWDCLK, GPIO24 for SWDIO, GPIO18 for nRST
|
||||
source [find interface/raspberrypi2-native.cfg]
|
||||
bcm2835gpio_swd_nums 25 24
|
||||
bcm2835gpio_srst_num 18
|
||||
transport select swd
|
||||
|
||||
# Use hardware reset wire for chip resets
|
||||
reset_config srst_only
|
||||
adapter_nsrst_delay 100
|
||||
adapter_nsrst_assert_width 100
|
||||
|
||||
# Specify the chip type
|
||||
source [find target/atsame5x.cfg]
|
||||
|
||||
# Set the adapter speed
|
||||
adapter_khz 40
|
||||
|
||||
# Connect to chip
|
||||
init
|
||||
targets
|
||||
reset halt
|
||||
```
|
||||
|
||||
### Wire the Raspberry Pi to the target chip
|
||||
|
||||
Poweroff both the the Raspberry Pi and the target chip before wiring!
|
||||
Verify the target chip uses 3.3V prior to connecting to a Raspberry
|
||||
Pi!
|
||||
|
||||
Connect GND, SWDCLK, SWDIO, and RST on the target chip to GND, GPIO25,
|
||||
GPIO24, and GPIO18 respectively on the Raspberry Pi.
|
||||
|
||||
Then power up the Raspberry Pi and provide power to the target chip.
|
||||
|
||||
### Run OpenOCD
|
||||
|
||||
Run OpenOCD:
|
||||
|
||||
```
|
||||
cd ~/openocd/
|
||||
sudo ~/openocd/install/bin/openocd -f ~/openocd/openocd.cfg
|
||||
```
|
||||
|
||||
The above should cause OpenOCD to emit some text messages and then
|
||||
wait (it should not immediately return to the Unix shell prompt). If
|
||||
OpenOCD exits on its own or if it continues to emit text messages then
|
||||
double check the wiring.
|
||||
|
||||
Once OpenOCD is running and is stable, one can send it commands via
|
||||
telnet. Open another ssh session and run the following:
|
||||
|
||||
```
|
||||
telnet 127.0.0.1 4444
|
||||
```
|
||||
|
||||
(One can exit telnet by pressing ctrl+] and then running the "quit"
|
||||
command.)
|
||||
|
||||
### OpenOCD and gdb
|
||||
|
||||
It is possible to use OpenOCD with gdb to debug Klipper. The following
|
||||
commands assume one is running gdb on a desktop class machine.
|
||||
|
||||
Add the following to the OpenOCD config file:
|
||||
|
||||
```
|
||||
bindto 0.0.0.0
|
||||
gdb_port 44444
|
||||
```
|
||||
|
||||
Restart OpenOCD on the Raspberry Pi and then run the following Unix
|
||||
command on the desktop machine:
|
||||
|
||||
```
|
||||
cd /path/to/klipper/
|
||||
gdb out/klipper.elf
|
||||
```
|
||||
|
||||
Within gdb run:
|
||||
|
||||
```
|
||||
target remote octopi:44444
|
||||
```
|
||||
|
||||
(Replace "octopi" with the host name of the Raspberry Pi.) Once gdb is
|
||||
running it is possible to set breakpoints and to inspect registers.
|
||||
124
docs/CANBUS.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# CANBUS
|
||||
|
||||
This document describes Klipper's CAN bus support.
|
||||
|
||||
## Device Hardware
|
||||
|
||||
Klipper currently only supports CAN on stm32 chips. In addition, the
|
||||
micro-controller chip must support CAN and it must be on a board that
|
||||
has a CAN transceiver.
|
||||
|
||||
To compile for CAN, run `make menuconfig` and select "CAN bus" as the
|
||||
communication interface. Finally, compile the micro-controller code
|
||||
and flash it to the target board.
|
||||
|
||||
## Host Hardware
|
||||
|
||||
In order to use a CAN bus, it is necessary to have a host adapter.
|
||||
There are currently two common options:
|
||||
|
||||
1. Use a
|
||||
[Waveshare Raspberry Pi CAN hat](https://www.waveshare.com/rs485-can-hat.htm)
|
||||
or one of its many clones.
|
||||
|
||||
2. Use a USB CAN adapter (for example
|
||||
[https://hacker-gadgets.com/product/cantact-usb-can-adapter/](https://hacker-gadgets.com/product/cantact-usb-can-adapter/)). There
|
||||
are many different USB to CAN adapters available - when choosing
|
||||
one, we recommend verifying it can run the
|
||||
[candlelight firmware](https://github.com/candle-usb/candleLight_fw).
|
||||
(Unfortunately, we've found some USB adapters run defective
|
||||
firmware and are locked down, so verify before purchasing.)
|
||||
|
||||
It is also necessary to configure the host operating system to use the
|
||||
adapter. This is typically done by creating a new file named
|
||||
`/etc/network/interfaces.d/can0` with the following contents:
|
||||
```
|
||||
auto can0
|
||||
iface can0 can static
|
||||
bitrate 500000
|
||||
up ifconfig $IFACE txqueuelen 128
|
||||
```
|
||||
|
||||
Note that the "Raspberry Pi CAN hat" also requires
|
||||
[changes to config.txt](https://www.waveshare.com/wiki/RS485_CAN_HAT).
|
||||
|
||||
## Terminating Resistors
|
||||
|
||||
A CAN bus should have two 120 ohm resistors between the CANH and CANL
|
||||
wires. Ideally, one resistor located at each the end of the bus.
|
||||
|
||||
Note that some devices have a builtin 120 ohm resistor (for example,
|
||||
the "Waveshare Raspberry Pi CAN hat" has a soldered on resistor that
|
||||
can not be easily removed). Some devices do not include a resistor at
|
||||
all. Other devices have a mechanism to select the resistor (typically
|
||||
by connecting a "pin jumper"). Be sure to check the schematics of all
|
||||
devices on the CAN bus to verify that there are two and only two 120
|
||||
Ohm resistors on the bus.
|
||||
|
||||
To test that the resistors are correct, one can remove power to the
|
||||
printer and use a multi-meter to check the resistance between the CANH
|
||||
and CANL wires - it should report ~60 ohms on a correctly wired CAN
|
||||
bus.
|
||||
|
||||
## Finding the canbus_uuid for new micro-controllers
|
||||
|
||||
Each micro-controller on the CAN bus is assigned a unique id based on
|
||||
the factory chip identifier encoded into each micro-controller. To
|
||||
find each micro-controller device id, make sure the hardware is
|
||||
powered and wired correctly, and then run:
|
||||
```
|
||||
~/klippy-env/bin/python ~/klipper/scripts/canbus_query.py can0
|
||||
```
|
||||
|
||||
If uninitialized CAN devices are detected the above command will
|
||||
report lines like the following:
|
||||
```
|
||||
Found canbus_uuid=11aa22bb33cc
|
||||
```
|
||||
|
||||
Each device will have a unique identifier. In the above example,
|
||||
`11aa22bb33cc` is the micro-controller's "canbus_uuid".
|
||||
|
||||
Note that the `canbus_query.py` tool will only report uninitialized
|
||||
devices - if Klipper (or a similar tool) configures the device then it
|
||||
will no longer appear in the list.
|
||||
|
||||
## Configuring Klipper
|
||||
|
||||
Update the Klipper [mcu configuration](Config_Reference.md#mcu) to use
|
||||
the CAN bus to communicate with the device - for example:
|
||||
```
|
||||
[mcu my_can_mcu]
|
||||
canbus_uuid: 11aa22bb33cc
|
||||
```
|
||||
|
||||
## USB to CAN bus bridge mode
|
||||
|
||||
Some micro-controllers support selecting "USB to CAN bus bridge" mode
|
||||
during "make menuconfig". This mode may allow one to use a
|
||||
micro-controller as both a "USB to CAN bus adapter" and as a Klipper
|
||||
node.
|
||||
|
||||
When Klipper uses this mode the micro-controller appears as a "USB CAN
|
||||
bus adapter" under Linux. The "Klipper bridge mcu" itself will appear
|
||||
as if was on this CAN bus - it can be identified via `canbus_query.py`
|
||||
and configured like other CAN bus Klipper nodes. It will appear
|
||||
alongside other devices that are actually on the CAN bus.
|
||||
|
||||
Some important notes when using this mode:
|
||||
|
||||
* The "bridge mcu" is not actually on the CAN bus. Messages to and
|
||||
from it do not consume bandwidth on the CAN bus. The mcu can not be
|
||||
seen by other adapters that may be on the CAN bus.
|
||||
|
||||
* It is necessary to configure the `can0` (or similar) interface in
|
||||
Linux in order to communicate with the bus. However, Linux CAN bus
|
||||
speed and CAN bus bit-timing options are ignored by Klipper.
|
||||
Currently, the CAN bus frequency is specified during "make
|
||||
menuconfig" and the bus speed specified in Linux is ignored.
|
||||
|
||||
* Whenever the "bridge mcu" is reset, Linux will disable the
|
||||
corresponding `can0` interface. Generally, this may require running
|
||||
commands such as "ip up" to restart the interface. Thus, Klipper
|
||||
FIRMWARE_RESTART commands (or regular RESTART after a config change)
|
||||
may require restarting the `can0` interface.
|
||||
69
docs/CANBUS_protocol.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# CANBUS protocol
|
||||
|
||||
This document describes the protocol Klipper uses to communicate over
|
||||
[CAN bus](https://en.wikipedia.org/wiki/CAN_bus). See
|
||||
[CANBUS.md](CANBUS.md) for information on configuring Klipper with CAN
|
||||
bus.
|
||||
|
||||
## Micro-controller id assignment
|
||||
|
||||
Klipper uses only CAN 2.0A standard size CAN bus packets, which are
|
||||
limited to 8 data bytes and an 11-bit CAN bus identifier. In order to
|
||||
support efficient communication, each micro-controller is assigned at
|
||||
run-time a unique 1-byte CAN bus nodeid (`canbus_nodeid`) for general
|
||||
Klipper command and response traffic. Klipper command messages going
|
||||
from host to micro-controller use the CAN bus id of `canbus_nodeid *
|
||||
2 + 256`, while Klipper response messages from micro-controller to
|
||||
host use `canbus_nodeid * 2 + 256 + 1`.
|
||||
|
||||
Each micro-controller has a factory assigned unique chip identifier
|
||||
that is used during id assignment. This identifier can exceed the
|
||||
length of one CAN packet, so a hash function is used to generate a
|
||||
unique 6-byte id (`canbus_uuid`) from the factory id.
|
||||
|
||||
## Admin messages
|
||||
|
||||
Admin messages are used for id assignment. Admin messages sent from
|
||||
host to micro-controller use the CAN bus id `0x3f0` and messages sent
|
||||
from micro-controller to host use the CAN bus id `0x3f1`. All
|
||||
micro-controllers listen to messages on id `0x3f0`; that id can be
|
||||
thought of as a "broadcast address".
|
||||
|
||||
### CMD_QUERY_UNASSIGNED message
|
||||
|
||||
This command queries all micro-controllers that have not yet been
|
||||
assigned a `canbus_nodeid`. Unassigned micro-controllers will respond
|
||||
with a RESP_NEED_NODEID response message.
|
||||
|
||||
The CMD_QUERY_UNASSIGNED message format is:
|
||||
`<1-byte message_id = 0x00>`
|
||||
|
||||
### CMD_SET_NODEID message
|
||||
|
||||
This command assigns a `canbus_nodeid` to the micro-controller with a
|
||||
given `canbus_uuid`.
|
||||
|
||||
The CMD_SET_NODEID message format is:
|
||||
`<1-byte message_id = 0x01><6-byte canbus_uuid><1-byte canbus_nodeid>`
|
||||
|
||||
### RESP_NEED_NODEID message
|
||||
|
||||
The RESP_NEED_NODEID message format is:
|
||||
`<1-byte message_id = 0x20><6-byte canbus_uuid>`
|
||||
|
||||
## Data Packets
|
||||
|
||||
A micro-controller that has been assigned a nodeid via the
|
||||
CMD_SET_NODEID command can send and receive data packets.
|
||||
|
||||
The packet data in messages using the node's receive CAN bus id
|
||||
(`canbus_nodeid * 2 + 256`) are simply appended to a buffer, and when
|
||||
a complete [mcu protocol message](Protocol.md) is found its contents
|
||||
are parsed and processed. The data is treated as a byte stream - there
|
||||
is no requirement for the start of a Klipper message block to align
|
||||
with the start of a CAN bus packet.
|
||||
|
||||
Similarly, mcu protocol message responses are sent from
|
||||
micro-controller to host by copying the message data into one or more
|
||||
packets with the node's transmit CAN bus id (`canbus_nodeid * 2 +
|
||||
256 + 1`).
|
||||
1
docs/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
www.klipper3d.org
|
||||
331
docs/CONTRIBUTING.md
Normal file
@@ -0,0 +1,331 @@
|
||||
# Contributing to Klipper
|
||||
|
||||
Thank you for contributing to Klipper! This document describes the
|
||||
process for contributing changes to Klipper.
|
||||
|
||||
Please see the [contact page](Contact.md) for information on reporting
|
||||
an issue or for details on contacting the developers.
|
||||
|
||||
## Overview of Contribution Process
|
||||
|
||||
Contributions to Klipper generally follow a high-level process:
|
||||
|
||||
1. A submitter starts by creating a
|
||||
[GitHub Pull Request](https://github.com/Klipper3d/klipper/pulls)
|
||||
when a submission is ready for widespread deployment.
|
||||
2. When a [reviewer](#reviewers) is available to
|
||||
[review](#what-to-expect-in-a-review) the submission, they will
|
||||
assign themselves to the Pull Request on GitHub. The goal of the
|
||||
review is to look for defects and to check that the submission
|
||||
follows documented guidelines.
|
||||
3. After a successful review, the reviewer will "approve the review"
|
||||
on GitHub and a [maintainer](#reviewers) will commit the change to
|
||||
the Klipper master branch.
|
||||
|
||||
When working on enhancements, consider starting (or contributing to) a
|
||||
topic on [Klipper Discourse](Contact.md). An ongoing discussion on the
|
||||
forum can improve visibility of development work and may attract
|
||||
others interested in testing new work.
|
||||
|
||||
## What to expect in a review
|
||||
|
||||
Contributions to Klipper are reviewed before merging. The primary goal
|
||||
of the review process is to check for defects and to check that the
|
||||
submission follows guidelines specified in the Klipper documentation.
|
||||
|
||||
It is understood that there are many ways to accomplish a task; it is
|
||||
not the intent of the review to discuss the "best" implementation.
|
||||
Where possible, review discussions focused on facts and measurements
|
||||
are preferable.
|
||||
|
||||
The majority of submissions will result in feedback from a review. Be
|
||||
prepared to obtain feedback, provide further details, and to update
|
||||
the submission if needed.
|
||||
|
||||
Common things a reviewer will look for:
|
||||
|
||||
1. Is the submission free of defects and is it ready to be widely
|
||||
deployed?
|
||||
|
||||
Submitters are expected to test their changes prior to submission.
|
||||
The reviewers look for errors, but they don't, in general, test
|
||||
submissions. An accepted submission is often deployed to thousands
|
||||
of printers within a few weeks of acceptance. Quality of
|
||||
submissions is therefore considered a priority.
|
||||
|
||||
The main [Klipper3d/klipper](https://github.com/Klipper3d/klipper)
|
||||
GitHub repository does not accept experimental work. Submitters
|
||||
should perform experimentation, debugging, and testing in their own
|
||||
repositories. The [Klipper Discourse](Contact.md) server is a good
|
||||
place to raise awareness of new work and to find users interested
|
||||
in providing real-world feedback.
|
||||
|
||||
Submissions must pass all [regression test cases](Debugging.md).
|
||||
|
||||
Code submissions should not contain excessive debugging code,
|
||||
debugging options, nor run-time debug logging.
|
||||
|
||||
Comments in code submissions should focus on enhancing code
|
||||
maintenance. Submissions should not contain "commented out code"
|
||||
nor excessive comments describing past implementations. There
|
||||
should not be excessive "todo" comments.
|
||||
|
||||
Updates to documentation should not declare that they are a "work
|
||||
in progress".
|
||||
|
||||
2. Does the submission provide a "high impact" benefit to real-world
|
||||
users performing real-world tasks?
|
||||
|
||||
Reviewers need to identify, at least in their own minds, roughly
|
||||
"who the target audience is", a rough scale of "the size of that
|
||||
audience", the "benefit" they will obtain, how the "benefit is
|
||||
measured", and the "results of those measurement tests". In most
|
||||
cases this will be obvious to both the submitter and the reviewer,
|
||||
and it is not explicitly stated during a review.
|
||||
|
||||
Submissions to the master Klipper branch are expected to have a
|
||||
noteworthy target audience. As a general "rule of thumb",
|
||||
submissions should target a user base of at least a 100 real-world
|
||||
users.
|
||||
|
||||
If a reviewer asks for details on the "benefit" of a submission,
|
||||
please don't consider it criticism. Being able to understand the
|
||||
real-world benefits of a change is a natural part of a review.
|
||||
|
||||
When discussing benefits it is preferable to discuss "facts and
|
||||
measurements". In general, reviewers are not looking for responses
|
||||
of the form "someone may find option X useful", nor are they
|
||||
looking for responses of the form "this submission adds a feature
|
||||
that firmware X implements". Instead, it is generally preferable to
|
||||
discuss details on how the quality improvement was measured and
|
||||
what were the results of those measurements - for example, "tests
|
||||
on Acme X1000 printers show improved corners as seen in picture
|
||||
...", or for example "print time of real-world object X on a
|
||||
Foomatic X900 printer went from 4 hours to 3.5 hours". It is
|
||||
understood that testing of this type can take significant time and
|
||||
effort. Some of Klipper's most notable features took months of
|
||||
discussion, rework, testing, and documentation prior to being
|
||||
merged into the master branch.
|
||||
|
||||
All new modules, config options, commands, command parameters, and
|
||||
documents should have "high impact". We do not want to burden users
|
||||
with options that they can not reasonably configure nor do we want
|
||||
to burden them with options that don't provide a notable benefit.
|
||||
|
||||
A reviewer may ask for clarification on how a user is to configure
|
||||
an option - an ideal response will contain details on the process -
|
||||
for example, "users of the MegaX500 are expected to set option X to
|
||||
99.3 while users of the Elite100Y are expected to calibrate option
|
||||
X using procedure ...".
|
||||
|
||||
If the goal of an option is to make the code more modular then
|
||||
prefer using code constants instead of user facing config options.
|
||||
|
||||
New modules, new options, and new parameters should not provide
|
||||
similar functionality to existing modules - if the differences are
|
||||
arbitrary than it's preferable to utilize the existing system or
|
||||
refactor the existing code.
|
||||
|
||||
3. Is the copyright of the submission clear, non-gratuitous, and
|
||||
compatible?
|
||||
|
||||
New C files and Python files should have an unambiguous copyright
|
||||
statement. See the existing files for the preferred format.
|
||||
Declaring a copyright on an existing file when making minor changes
|
||||
to that file is discouraged.
|
||||
|
||||
Code taken from 3rd party sources must be compatible with the
|
||||
Klipper license (GNU GPLv3). Large 3rd party code additions should
|
||||
be added to the `lib/` directory (and follow the format described
|
||||
in [lib/README](../lib/README)).
|
||||
|
||||
Submitters must provide a
|
||||
[Signed-off-by line](#format-of-commit-messages) using their full
|
||||
real name. It indicates the submitter agrees with the
|
||||
[developer certificate of origin](developer-certificate-of-origin).
|
||||
|
||||
4. Does the submission follow guidelines specified in the Klipper
|
||||
documentation?
|
||||
|
||||
In particular, code should follow the guidelines in
|
||||
[Code_Overview.md](Code_Overview.md) and config files should follow
|
||||
the guidelines in [Example_Configs.md](Example_Configs.md).
|
||||
|
||||
5. Is the Klipper documentation updated to reflect new changes?
|
||||
|
||||
At a minimum, the reference documentation must be updated with
|
||||
corresponding changes to the code:
|
||||
* All commands and command parameters must be documented in
|
||||
[G-Codes.md](G-Codes.md).
|
||||
* All user facing modules and their config parameters must be
|
||||
documented in [Config_Reference.md](Config_Reference.md).
|
||||
* All exported "status variables" must be documented in
|
||||
[Status_Reference.md](Status_Reference.md).
|
||||
* All new "webhooks" and their parameters must be documented in
|
||||
[API_Server.md](API_Server.md).
|
||||
* Any change that makes a non-backwards compatible change to a
|
||||
command or config file setting must be documented in
|
||||
[Config_Changes.md](Config_Changes.md).
|
||||
|
||||
New documents should be added to [Overview.md](Overview.md) and be
|
||||
added to the website index
|
||||
[docs/_klipper3d/mkdocs.yml](../docs/_klipper3d/mkdocs.yml).
|
||||
|
||||
6. Are commits well formed, address a single topic per commit, and
|
||||
independent?
|
||||
|
||||
Commit messages should follow the
|
||||
[preferred format](#format-of-commit-messages).
|
||||
|
||||
Commits must not have a merge conflict. New additions to the
|
||||
Klipper master branch are always done via a "rebase" or "squash and
|
||||
rebase". It is generally not necessary for submitters to re-merge
|
||||
their submission on every update to the Klipper master repository.
|
||||
However, if there is a merge conflict, then submitters are
|
||||
recommended to use `git rebase` to address the conflict.
|
||||
|
||||
Each commit should address a single high-level change. Large
|
||||
changes should be broken up into multiple independent commits. Each
|
||||
commit should "stand on its own" so that tools like `git bisect`
|
||||
and `git revert` work reliably.
|
||||
|
||||
Whitespace changes should not be mixed with functional changes. In
|
||||
general, gratuitous whitespace changes are not accepted unless they
|
||||
are from the established "owner" of the code being modified.
|
||||
|
||||
Klipper does not implement a strict "coding style guide", but
|
||||
modifications to existing code should follow the high-level code flow,
|
||||
code indentation style, and format of that existing code. Submissions
|
||||
of new modules and systems have more flexibility in coding style, but
|
||||
it is preferable for that new code to follow an internally consistent
|
||||
style and to generally follow industry wide coding norms.
|
||||
|
||||
It is not a goal of a review to discuss "better implementations".
|
||||
However, if a reviewer struggles to understand the implementation of a
|
||||
submission, then they may ask for changes to make the implementation
|
||||
more transparent. In particular, if reviewers can not convince
|
||||
themselves that a submission is free of defects then changes may be
|
||||
necessary.
|
||||
|
||||
As part of a review, a reviewer may create an alternate Pull Request
|
||||
for a topic. This may be done to avoid excessive "back and forth" on
|
||||
minor procedural items and thus streamline the submission process. It
|
||||
may also be done because the discussion inspires a reviewer to build
|
||||
an alternative implementation. Both situations are a normal result of
|
||||
a review and should not be considered criticism of the original
|
||||
submission.
|
||||
|
||||
### Helping with reviews
|
||||
|
||||
We appreciate help with reviews! It is not necessary to be a
|
||||
[listed reviewer](#reviewers) to perform a review. Submitters of
|
||||
GitHub Pull Requests are also encouraged to review their own
|
||||
submissions.
|
||||
|
||||
To help with a review, follow the steps outlined in
|
||||
[what to expect in a review](#what-to-expect-in-a-review) to verify
|
||||
the submission. After completing the review, add a comment to the
|
||||
GitHub Pull Request with your findings. If the submission passes the
|
||||
review then please state that explicitly in the comment - for example
|
||||
something like "I reviewed this change according to the steps in the
|
||||
CONTRIBUTING document and everything looks good to me". If unable to
|
||||
complete some steps in the review then please explicitly state which
|
||||
steps were reviewed and which steps were not reviewed - for example
|
||||
something like "I didn't check the code for defects, but I reviewed
|
||||
everything else in the CONTRIBUTING document and it looks good".
|
||||
|
||||
We also appreciate testing of submissions. If the code was tested then
|
||||
please add a comment to the GitHub Pull Request with the results of
|
||||
your test - success or failure. Please explicitly state that the code
|
||||
was tested and the results - for example something like "I tested this
|
||||
code on my Acme900Z printer with a vase print and the results were
|
||||
good".
|
||||
|
||||
### Reviewers
|
||||
|
||||
The Klipper "reviewers" are:
|
||||
|
||||
| Name | GitHub Id | Areas of interest |
|
||||
| ---------------------- | ----------------- | ----------------- |
|
||||
| Dmitry Butyugin | @dmbutyugin | Input shaping, resonance testing, kinematics |
|
||||
| Eric Callahan | @Arksine | Bed leveling, MCU flashing |
|
||||
| Kevin O'Connor | @KevinOConnor | Core motion system, Micro-controller code |
|
||||
| Paul McGowan | @mental405 | Configuration files, documentation |
|
||||
|
||||
Please do not "ping" any of the reviewers and please do not direct
|
||||
submissions at them. All of the reviewers monitor the forums and PRs,
|
||||
and will take on reviews when they have time to.
|
||||
|
||||
The Klipper "maintainers" are:
|
||||
|
||||
| Name | GitHub name |
|
||||
| ---------------------- | ----------------- |
|
||||
| Kevin O'Connor | @KevinOConnor |
|
||||
|
||||
## Format of commit messages
|
||||
|
||||
Each commit should have a commit message formatted similar to the
|
||||
following:
|
||||
|
||||
```
|
||||
module: Capitalized, short (50 chars or less) summary
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 75
|
||||
characters or so. In some contexts, the first line is treated as the
|
||||
subject of an email and the rest of the text as the body. The blank
|
||||
line separating the summary from the body is critical (unless you omit
|
||||
the body entirely); tools like rebase can get confused if you run the
|
||||
two together.
|
||||
|
||||
Further paragraphs come after blank lines..
|
||||
|
||||
Signed-off-by: My Name <myemail@example.org>
|
||||
```
|
||||
|
||||
In the above example, `module` should be the name of a file or
|
||||
directory in the repository (without a file extension). For example,
|
||||
`clocksync: Fix typo in pause() call at connect time`. The purpose of
|
||||
specifying a module name in the commit message is to help provide
|
||||
context for the commit comments.
|
||||
|
||||
It is important to have a "Signed-off-by" line on each commit - it
|
||||
certifies that you agree to the
|
||||
[developer certificate of origin](developer-certificate-of-origin). It
|
||||
must contain your real name (sorry, no pseudonyms or anonymous
|
||||
contributions) and contain a current email address.
|
||||
|
||||
## Contributing to Klipper Translations
|
||||
|
||||
[Klipper-translations Project](https://github.com/Klipper3d/klipper-translations)
|
||||
is a project dedicated to translating Klipper to different languages.
|
||||
[Weblate](https://hosted.weblate.org/projects/klipper/) hosts all the
|
||||
Gettext strings for translating and reviewing. Locales can be displayed on
|
||||
[klipper3d.org](https://www.klipper3d.org) once they satisfy the following requirements:
|
||||
|
||||
- [ ] 75% Total coverage
|
||||
- [ ] All titles (H1) are translated
|
||||
- [ ] An updated navigation hierarchy PR in klipper-translations.
|
||||
|
||||
To reduce the frustration of translating domain-specific terms and
|
||||
gain awareness of the ongoing translations, you can submit a PR
|
||||
modifying the
|
||||
[Klipper-translations Project](https://github.com/Klipper3d/klipper-translations)
|
||||
`readme.md`. Once a translation is ready, the corresponding
|
||||
modification to the Klipper project can be made.
|
||||
|
||||
If a translation already exists in the Klipper repository and no
|
||||
longer meets the checklist above, it will be marked out-of-date after
|
||||
a month without updates.
|
||||
|
||||
Once the requirements are met, you need to:
|
||||
|
||||
1. update klipper-tranlations repository
|
||||
[active_translations](https://github.com/Klipper3d/klipper-translations/blob/translations/active_translations)
|
||||
2. Optional: add a manual-index.md file in klipper-translations repository's
|
||||
`docs\locals\<lang>` folder to replace the language specific index.md (generated
|
||||
index.md does not render correctly).
|
||||
|
||||
Known Issues:
|
||||
1. Currently, there isn't a method for correctly translating pictures in
|
||||
the documentation
|
||||
2. It is impossible to translate titles in mkdocs.yml.
|
||||
581
docs/Code_Overview.md
Normal file
@@ -0,0 +1,581 @@
|
||||
# Code overview
|
||||
|
||||
This document describes the overall code layout and major code flow of
|
||||
Klipper.
|
||||
|
||||
## Directory Layout
|
||||
|
||||
The **src/** directory contains the C source for the micro-controller
|
||||
code. The **src/atsam/**, **src/atsamd/**, **src/avr/**,
|
||||
**src/linux/**, **src/lpc176x/**, **src/pru/**, and **src/stm32/**
|
||||
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).
|
||||
|
||||
The **klippy/** directory contains the host software. Most of the host
|
||||
software is written in Python, however the **klippy/chelper/**
|
||||
directory contains some C code helpers. The **klippy/kinematics/**
|
||||
directory contains the robot kinematics code. The **klippy/extras/**
|
||||
directory contains the host code extensible "modules".
|
||||
|
||||
The **lib/** directory contains external 3rd-party library code that
|
||||
is necessary to build some targets.
|
||||
|
||||
The **config/** directory contains example printer configuration
|
||||
files.
|
||||
|
||||
The **scripts/** directory contains build-time scripts useful for
|
||||
compiling the micro-controller code.
|
||||
|
||||
The **test/** directory contains automated test cases.
|
||||
|
||||
During compilation, the build may create an **out/** directory. This
|
||||
contains temporary build time objects. The final micro-controller
|
||||
object that is built is **out/klipper.elf.hex** on AVR and
|
||||
**out/klipper.bin** on ARM.
|
||||
|
||||
## Micro-controller code flow
|
||||
|
||||
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.
|
||||
|
||||
One of the main task functions is command_dispatch() located in
|
||||
**src/command.c**. This function is called from the board specific
|
||||
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).
|
||||
|
||||
Task, init, and command functions always run with interrupts enabled
|
||||
(however, they can temporarily disable interrupts if needed). These
|
||||
functions should avoid long pauses, delays, or do work that lasts a
|
||||
significant time. (Long delays in these "task" functions result in
|
||||
scheduling jitter for other "tasks" - delays over 100us may become
|
||||
noticeable, delays over 500us may result in command retransmissions,
|
||||
delays over 100ms may result in watchdog reboots.) These functions
|
||||
schedule work at specific times by scheduling timers.
|
||||
|
||||
Timer functions are scheduled by calling sched_add_timer() (located in
|
||||
**src/sched.c**). The scheduler code will arrange for the given
|
||||
function to be called at the requested clock time. Timer interrupts
|
||||
are initially handled in an architecture specific interrupt handler
|
||||
(eg, **src/avr/timer.c**) which calls sched_timer_dispatch() located
|
||||
in **src/sched.c**. The timer interrupt leads to execution of schedule
|
||||
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.
|
||||
|
||||
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
|
||||
code, all GPIO events are implemented in architecture specific
|
||||
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.
|
||||
|
||||
## Klippy code overview
|
||||
|
||||
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
|
||||
execution of G-code commands is in the process_commands() method in
|
||||
**klippy/gcode.py**. This code translates the G-code commands into
|
||||
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).
|
||||
|
||||
There are four threads in the Klippy host code. The main thread
|
||||
handles incoming gcode commands. A second thread (which resides
|
||||
entirely in the **klippy/chelper/serialqueue.c** C code) handles
|
||||
low-level IO with the serial port. The third thread is used to process
|
||||
response messages from the micro-controller in the Python code (see
|
||||
**klippy/serialhdl.py**). The fourth thread writes debug messages to
|
||||
the log (see **klippy/queuelogger.py**) so that the other threads
|
||||
never block on log writes.
|
||||
|
||||
## Code flow of a move command
|
||||
|
||||
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
|
||||
of a typical move command. The [kinematics](Kinematics.md) document
|
||||
provides further information on the mechanics of moves.
|
||||
|
||||
* Processing for a move command starts in gcode.py. The goal of
|
||||
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()`
|
||||
|
||||
* The ToolHead class (in toolhead.py) handles "look-ahead" and tracks
|
||||
the timing of printing actions. The main codepath for a move is:
|
||||
`ToolHead.move() -> MoveQueue.add_move() -> MoveQueue.flush() ->
|
||||
Move.set_junction() -> ToolHead._process_moves()`.
|
||||
* ToolHead.move() creates a Move() object with the parameters of the
|
||||
move (in cartesian space and in units of seconds and millimeters).
|
||||
* 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.
|
||||
* MoveQueue.add_move() places the move object on the "look-ahead"
|
||||
queue.
|
||||
* MoveQueue.flush() determines the start and end velocities of each
|
||||
move.
|
||||
* 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.
|
||||
* When ToolHead._process_moves() is called, everything about the
|
||||
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.
|
||||
|
||||
* Klipper uses an
|
||||
[iterative solver](https://en.wikipedia.org/wiki/Root-finding_algorithm)
|
||||
to generate the step times for each stepper. For efficiency reasons,
|
||||
the stepper pulse times are generated in C code. The moves are first
|
||||
placed on a "trapezoid motion queue": `ToolHead._process_moves() ->
|
||||
trapq_append()` (in klippy/chelper/trapq.c). The step times are then
|
||||
generated: `ToolHead._process_moves() ->
|
||||
ToolHead._update_move_time() -> MCU_Stepper.generate_steps() ->
|
||||
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).
|
||||
|
||||
* Note that the extruder is handled in its own kinematic class:
|
||||
`ToolHead._process_moves() -> PrinterExtruder.move()`. Since
|
||||
the Move() class specifies the exact movement time and since step
|
||||
pulses are sent to the micro-controller with specific timing,
|
||||
stepper movements produced by the extruder class will be in sync
|
||||
with head movement even though the code is kept separate.
|
||||
|
||||
* After the iterative solver calculates the step times they are added
|
||||
to an array: `itersolve_gen_steps_range() -> stepcompress_append()`
|
||||
(in klippy/chelper/stepcompress.c). The array (struct
|
||||
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.
|
||||
|
||||
* The next major step is to compress the steps: `stepcompress_flush()
|
||||
-> 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
|
||||
stepcompress.c:steppersync and serialqueue.c:serialqueue).
|
||||
|
||||
* Processing of the queue_step commands on the micro-controller starts
|
||||
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;`
|
||||
|
||||
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.
|
||||
|
||||
## Adding a host module
|
||||
|
||||
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.
|
||||
* 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.
|
||||
* If there is an error in the user's config, be sure to raise it
|
||||
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.
|
||||
* 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.
|
||||
* 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.
|
||||
* 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
|
||||
sockets) are opened then be sure to register a "klippy:disconnect"
|
||||
event handler and close them from that callback.
|
||||
* 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.
|
||||
* 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
|
||||
`self.speed = 2. * x` over `self.speed = 2 * x`. Consistent use of
|
||||
floating point values can avoid hard to debug quirks in Python type
|
||||
conversions.
|
||||
* 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.
|
||||
|
||||
## Adding new kinematics
|
||||
|
||||
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
|
||||
should only need to update the host software.
|
||||
|
||||
Useful steps:
|
||||
1. Start by studying the
|
||||
"[code flow of a move](#code-flow-of-a-move-command)" section and
|
||||
the [Kinematics document](Kinematics.md).
|
||||
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
|
||||
should be able to copy one of these files as a starting point.
|
||||
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.
|
||||
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.
|
||||
5. Other methods. Implement the `check_move()`, `get_status()`,
|
||||
`get_steppers()`, `home()`, 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.
|
||||
6. Implement test cases. Create a g-code file with a series of moves
|
||||
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.
|
||||
|
||||
## Porting to a new micro-controller
|
||||
|
||||
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
|
||||
much easier. It is typical to use a UART type serial device during
|
||||
initial development as these types of hardware devices are
|
||||
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
|
||||
[commit 970831ee](https://github.com/Klipper3d/klipper/commit/970831ee0d3b91897196e92270d98b2a3067427f)
|
||||
as an example of steps 1-5 done for the LPC176x architecture.
|
||||
6. Bring up basic GPIO input and output support. See Klipper
|
||||
[commit c78b9076](https://github.com/Klipper3d/klipper/commit/c78b90767f19c9e8510c3155b89fb7ad64ca3c54)
|
||||
as an example of this.
|
||||
7. Bring up additional peripherals - for example see Klipper commit
|
||||
[65613aed](https://github.com/Klipper3d/klipper/commit/65613aeddfb9ef86905cb1dade9e773a02ef3c27),
|
||||
[c812a40a](https://github.com/Klipper3d/klipper/commit/c812a40a3782415e454b04bf7bd2158a6f0ec8b5),
|
||||
and
|
||||
[c381d03a](https://github.com/Klipper3d/klipper/commit/c381d03aad5c3ee761169b7c7bced519cc14da29).
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## Coordinate Systems
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
The "stepper" position (`stepper.get_commanded_position()`) is the
|
||||
position of the given stepper as tracked by the kinematics code. This
|
||||
generally corresponds to the position (in mm) of the carriage along
|
||||
its rail, relative to the position_endstop specified in the config
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
`M114` command (`gcode_move.get_status()['gcode_position']`) will
|
||||
report the last g-code position relative to the current g-code
|
||||
coordinate system.
|
||||
|
||||
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.
|
||||
|
||||
## Time
|
||||
|
||||
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
|
||||
to calculate almost all physical actions (eg, head movement, heater
|
||||
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
|
||||
**klippy/chelper/serialqueue.c** code will buffer messages until
|
||||
they are within 2^31 clock ticks of their target time.
|
||||
* 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.
|
||||
348
docs/Command_Templates.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# Commands templates
|
||||
|
||||
This document provides information on implementing G-Code command
|
||||
sequences in gcode_macro (and similar) config sections.
|
||||
|
||||
## G-Code Macro Naming
|
||||
|
||||
Case is not important for the G-Code macro name - MY_MACRO and
|
||||
my_macro will evaluate the same and may be called in either upper or
|
||||
lower case. If any numbers are used in the macro name then they must
|
||||
all be at the end of the name (eg, TEST_MACRO25 is valid, but
|
||||
MACRO25_TEST3 is not).
|
||||
|
||||
## Formatting of G-Code in the config
|
||||
|
||||
Indentation is important when defining a macro in the config file. To
|
||||
specify a multi-line G-Code sequence it is important for each line to
|
||||
have proper indentation. For example:
|
||||
|
||||
```
|
||||
[gcode_macro blink_led]
|
||||
gcode:
|
||||
SET_PIN PIN=my_led VALUE=1
|
||||
G4 P2000
|
||||
SET_PIN PIN=my_led VALUE=0
|
||||
```
|
||||
|
||||
Note how the `gcode:` config option always starts at the beginning of
|
||||
the line and subsequent lines in the G-Code macro never start at the
|
||||
beginning.
|
||||
|
||||
## Add a description to your macro
|
||||
|
||||
To help identify the functionality a short description can be added.
|
||||
Add `description:` with a short text to describe the functionality.
|
||||
Default is "G-Code macro" if not specified.
|
||||
For example:
|
||||
|
||||
```
|
||||
[gcode_macro blink_led]
|
||||
description: Blink my_led one time
|
||||
gcode:
|
||||
SET_PIN PIN=my_led VALUE=1
|
||||
G4 P2000
|
||||
SET_PIN PIN=my_led VALUE=0
|
||||
```
|
||||
|
||||
The terminal will display the description when you use the `HELP` command or the autocomplete function.
|
||||
|
||||
## Save/Restore state for G-Code moves
|
||||
|
||||
Unfortunately, the G-Code command language can be challenging to use.
|
||||
The standard mechanism to move the toolhead is via the `G1` command
|
||||
(the `G0` command is an alias for `G1` and it can be used
|
||||
interchangeably with it). However, this command relies on the "G-Code
|
||||
parsing state" setup by `M82`, `M83`, `G90`, `G91`, `G92`, and
|
||||
previous `G1` commands. When creating a G-Code macro it is a good
|
||||
idea to always explicitly set the G-Code parsing state prior to
|
||||
issuing a `G1` command. (Otherwise, there is a risk the `G1` command
|
||||
will make an undesirable request.)
|
||||
|
||||
A common way to accomplish that is to wrap the `G1` moves in
|
||||
`SAVE_GCODE_STATE`, `G91`, and `RESTORE_GCODE_STATE`. For example:
|
||||
|
||||
```
|
||||
[gcode_macro MOVE_UP]
|
||||
gcode:
|
||||
SAVE_GCODE_STATE NAME=my_move_up_state
|
||||
G91
|
||||
G1 Z10 F300
|
||||
RESTORE_GCODE_STATE NAME=my_move_up_state
|
||||
```
|
||||
|
||||
The `G91` command places the G-Code parsing state into "relative move
|
||||
mode" and the `RESTORE_GCODE_STATE` command restores the state to what
|
||||
it was prior to entering the macro. Be sure to specify an explicit
|
||||
speed (via the `F` parameter) on the first `G1` command.
|
||||
|
||||
## Template expansion
|
||||
|
||||
The gcode_macro `gcode:` config section is evaluated using the Jinja2
|
||||
template language. One can evaluate expressions at run-time by
|
||||
wrapping them in `{ }` characters or use conditional statements
|
||||
wrapped in `{% %}`. See the
|
||||
[Jinja2 documentation](http://jinja.pocoo.org/docs/2.10/templates/)
|
||||
for further information on the syntax.
|
||||
|
||||
An example of a complex macro:
|
||||
```
|
||||
[gcode_macro clean_nozzle]
|
||||
gcode:
|
||||
{% set wipe_count = 8 %}
|
||||
SAVE_GCODE_STATE NAME=clean_nozzle_state
|
||||
G90
|
||||
G0 Z15 F300
|
||||
{% for wipe in range(wipe_count) %}
|
||||
{% for coordinate in [(275, 4),(235, 4)] %}
|
||||
G0 X{coordinate[0]} Y{coordinate[1] + 0.25 * wipe} Z9.7 F12000
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
RESTORE_GCODE_STATE NAME=clean_nozzle_state
|
||||
```
|
||||
|
||||
### Macro parameters
|
||||
|
||||
It is often useful to inspect parameters passed to the macro when
|
||||
it is called. These parameters are available via the `params`
|
||||
pseudo-variable. For example, if the macro:
|
||||
|
||||
```
|
||||
[gcode_macro SET_PERCENT]
|
||||
gcode:
|
||||
M117 Now at { params.VALUE|float * 100 }%
|
||||
```
|
||||
|
||||
were invoked as `SET_PERCENT VALUE=.2` it would evaluate to `M117 Now
|
||||
at 20%`. Note that parameter names are always in upper-case when
|
||||
evaluated in the macro and are always passed as strings. If performing
|
||||
math then they must be explicitly converted to integers or floats.
|
||||
|
||||
It's common to use the Jinja2 `set` directive to use a default
|
||||
parameter and assign the result to a local name. For example:
|
||||
|
||||
```
|
||||
[gcode_macro SET_BED_TEMPERATURE]
|
||||
gcode:
|
||||
{% set bed_temp = params.TEMPERATURE|default(40)|float %}
|
||||
M140 S{bed_temp}
|
||||
```
|
||||
|
||||
### The "rawparams" variable
|
||||
|
||||
The full unparsed parameters for the running macro can be access via the
|
||||
`rawparams` pseudo-variable.
|
||||
|
||||
Note that this will include any comments that were part of the original command.
|
||||
|
||||
See the [sample-macros.cfg](../config/sample-macros.cfg) file for an example
|
||||
showing how to override the `M117` command using `rawparams`.
|
||||
|
||||
### The "printer" Variable
|
||||
|
||||
It is possible to inspect (and alter) the current state of the printer
|
||||
via the `printer` pseudo-variable. For example:
|
||||
|
||||
```
|
||||
[gcode_macro slow_fan]
|
||||
gcode:
|
||||
M106 S{ printer.fan.speed * 0.9 * 255}
|
||||
```
|
||||
|
||||
Available fields are defined in the
|
||||
[Status Reference](Status_Reference.md) document.
|
||||
|
||||
Important! Macros are first evaluated in entirety and only then are
|
||||
the resulting commands executed. If a macro issues a command that
|
||||
alters the state of the printer, the results of that state change will
|
||||
not be visible during the evaluation of the macro. This can also
|
||||
result in subtle behavior when a macro generates commands that call
|
||||
other macros, as the called macro is evaluated when it is invoked
|
||||
(which is after the entire evaluation of the calling macro).
|
||||
|
||||
By convention, the name immediately following `printer` is the name of
|
||||
a config section. So, for example, `printer.fan` refers to the fan
|
||||
object created by the `[fan]` config section. There are some
|
||||
exceptions to this rule - notably the `gcode_move` and `toolhead`
|
||||
objects. If the config section contains spaces in it, then one can
|
||||
access it via the `[ ]` accessor - for example:
|
||||
`printer["generic_heater my_chamber_heater"].temperature`.
|
||||
|
||||
Note that the Jinja2 `set` directive can assign a local name to an
|
||||
object in the `printer` hierarchy. This can make macros more readable
|
||||
and reduce typing. For example:
|
||||
```
|
||||
[gcode_macro QUERY_HTU21D]
|
||||
gcode:
|
||||
{% set sensor = printer["htu21d my_sensor"] %}
|
||||
M117 Temp:{sensor.temperature} Humidity:{sensor.humidity}
|
||||
```
|
||||
|
||||
## Actions
|
||||
|
||||
There are some commands available that can alter the state of the
|
||||
printer. For example, `{ action_emergency_stop() }` would cause the
|
||||
printer to go into a shutdown state. Note that these actions are taken
|
||||
at the time that the macro is evaluated, which may be a significant
|
||||
amount of time before the generated g-code commands are executed.
|
||||
|
||||
Available "action" commands:
|
||||
- `action_respond_info(msg)`: Write the given `msg` to the
|
||||
/tmp/printer pseudo-terminal. Each line of `msg` will be sent with a
|
||||
"// " prefix.
|
||||
- `action_raise_error(msg)`: Abort the current macro (and any calling
|
||||
macros) and write the given `msg` to the /tmp/printer
|
||||
pseudo-terminal. The first line of `msg` will be sent with a "!! "
|
||||
prefix and subsequent lines will have a "// " prefix.
|
||||
- `action_emergency_stop(msg)`: Transition the printer to a shutdown
|
||||
state. The `msg` parameter is optional, it may be useful to describe
|
||||
the reason for the shutdown.
|
||||
- `action_call_remote_method(method_name)`: Calls a method registered
|
||||
by a remote client. If the method takes parameters they should
|
||||
be provided via keyword arguments, ie:
|
||||
`action_call_remote_method("print_stuff", my_arg="hello_world")`
|
||||
|
||||
## Variables
|
||||
|
||||
The SET_GCODE_VARIABLE command may be useful for saving state between
|
||||
macro calls. Variable names may not contain any upper case characters.
|
||||
For example:
|
||||
|
||||
```
|
||||
[gcode_macro start_probe]
|
||||
variable_bed_temp: 0
|
||||
gcode:
|
||||
# Save target temperature to bed_temp variable
|
||||
SET_GCODE_VARIABLE MACRO=start_probe VARIABLE=bed_temp VALUE={printer.heater_bed.target}
|
||||
# Disable bed heater
|
||||
M140
|
||||
# Perform probe
|
||||
PROBE
|
||||
# Call finish_probe macro at completion of probe
|
||||
finish_probe
|
||||
|
||||
[gcode_macro finish_probe]
|
||||
gcode:
|
||||
# Restore temperature
|
||||
M140 S{printer["gcode_macro start_probe"].bed_temp}
|
||||
```
|
||||
|
||||
Be sure to take the timing of macro evaluation and command execution
|
||||
into account when using SET_GCODE_VARIABLE.
|
||||
|
||||
## Delayed Gcodes
|
||||
|
||||
The [delayed_gcode] configuration option can be used to execute a delayed
|
||||
gcode sequence:
|
||||
|
||||
```
|
||||
[delayed_gcode clear_display]
|
||||
gcode:
|
||||
M117
|
||||
|
||||
[gcode_macro load_filament]
|
||||
gcode:
|
||||
G91
|
||||
G1 E50
|
||||
G90
|
||||
M400
|
||||
M117 Load Complete!
|
||||
UPDATE_DELAYED_GCODE ID=clear_display DURATION=10
|
||||
```
|
||||
|
||||
When the `load_filament` macro above executes, it will display a
|
||||
"Load Complete!" message after the extrusion is finished. The
|
||||
last line of gcode enables the "clear_display" delayed_gcode, set
|
||||
to execute in 10 seconds.
|
||||
|
||||
The `initial_duration` config option can be set to execute the
|
||||
delayed_gcode on printer startup. The countdown begins when the
|
||||
printer enters the "ready" state. For example, the below delayed_gcode
|
||||
will execute 5 seconds after the printer is ready, initializing
|
||||
the display with a "Welcome!" message:
|
||||
|
||||
```
|
||||
[delayed_gcode welcome]
|
||||
initial_duration: 5.
|
||||
gcode:
|
||||
M117 Welcome!
|
||||
```
|
||||
|
||||
Its possible for a delayed gcode to repeat by updating itself in
|
||||
the gcode option:
|
||||
|
||||
```
|
||||
[delayed_gcode report_temp]
|
||||
initial_duration: 2.
|
||||
gcode:
|
||||
{action_respond_info("Extruder Temp: %.1f" % (printer.extruder0.temperature))}
|
||||
UPDATE_DELAYED_GCODE ID=report_temp DURATION=2
|
||||
```
|
||||
|
||||
The above delayed_gcode will send "// Extruder Temp: [ex0_temp]" to
|
||||
Octoprint every 2 seconds. This can be canceled with the following
|
||||
gcode:
|
||||
|
||||
|
||||
```
|
||||
UPDATE_DELAYED_GCODE ID=report_temp DURATION=0
|
||||
```
|
||||
|
||||
## Menu templates
|
||||
|
||||
If a [display config section](Config_Reference.md#display) is enabled,
|
||||
then it is possible to customize the menu with
|
||||
[menu](Config_Reference.md#menu) config sections.
|
||||
|
||||
The following read-only attributes are available in menu templates:
|
||||
* `menu.width` - element width (number of display columns)
|
||||
* `menu.ns` - element namespace
|
||||
* `menu.event` - name of the event that triggered the script
|
||||
* `menu.input` - input value, only available in input script context
|
||||
|
||||
The following actions are available in menu templates:
|
||||
* `menu.back(force, update)`: will execute menu back command, optional
|
||||
boolean parameters `<force>` and `<update>`.
|
||||
* When `<force>` is set True then it will also stop editing. Default
|
||||
value is False.
|
||||
* When `<update>` is set False then parent container items are not
|
||||
updated. Default value is True.
|
||||
* `menu.exit(force)` - will execute menu exit command, optional
|
||||
boolean parameter `<force>` default value False.
|
||||
* When `<force>` is set True then it will also stop editing. Default
|
||||
value is False.
|
||||
|
||||
## Save Variables to disk
|
||||
|
||||
If a
|
||||
[save_variables config section](Config_Reference.md#save_variables)
|
||||
has been enabled, `SAVE_VARIABLE VARIABLE=<name> VALUE=<value>` can be
|
||||
used to save the variable to disk so that it can be used across
|
||||
restarts. All stored variables are loaded into the
|
||||
`printer.save_variables.variables` dict at startup and can be used in
|
||||
gcode macros. to avoid overly long lines you can add the following at
|
||||
the top of the macro:
|
||||
```
|
||||
{% set svv = printer.save_variables.variables %}
|
||||
```
|
||||
|
||||
As an example, it could be used to save the state of 2-in-1-out hotend
|
||||
and when starting a print ensure that the active extruder is used,
|
||||
instead of T0:
|
||||
|
||||
```
|
||||
[gcode_macro T1]
|
||||
gcode:
|
||||
ACTIVATE_EXTRUDER extruder=extruder1
|
||||
SAVE_VARIABLE VARIABLE=currentextruder VALUE='"extruder1"'
|
||||
|
||||
[gcode_macro T0]
|
||||
gcode:
|
||||
ACTIVATE_EXTRUDER extruder=extruder
|
||||
SAVE_VARIABLE VARIABLE=currentextruder VALUE='"extruder"'
|
||||
|
||||
[gcode_macro START_GCODE]
|
||||
gcode:
|
||||
{% set svv = printer.save_variables.variables %}
|
||||
ACTIVATE_EXTRUDER extruder={svv.currentextruder}
|
||||
```
|
||||
435
docs/Config_Changes.md
Normal file
@@ -0,0 +1,435 @@
|
||||
# Configuration Changes
|
||||
|
||||
This document covers recent software changes to the config file that
|
||||
are not backwards compatible. It is a good idea to review this
|
||||
document when upgrading the Klipper software.
|
||||
|
||||
All dates in this document are approximate.
|
||||
|
||||
## Changes
|
||||
|
||||
20220616: It was previously possible to flash an rp2040 in bootloader
|
||||
mode by running `make flash FLASH_DEVICE=first`. The equivalent
|
||||
command is now `make flash FLASH_DEVICE=2e8a:0003`.
|
||||
|
||||
20220612: The rp2040 micro-controller now has a workaround for the
|
||||
"rp2040-e5" USB errata. This should make initial USB connections more
|
||||
reliable. However, it may result in a change in behavior for the
|
||||
gpio15 pin. It is unlikely the gpio15 behavior change will be
|
||||
noticeable.
|
||||
|
||||
20220407: The temperature_fan `pid_integral_max` config option has
|
||||
been removed (it was deprecated on 20210612).
|
||||
|
||||
20220407: The default color order for pca9632 LEDs is now "RGBW". Add
|
||||
an explicit `color_order: RBGW` setting to the pca9632 config section
|
||||
to obtain the previous behavior.
|
||||
|
||||
20220330: The format of the `printer.neopixel.color_data` status
|
||||
information for neopixel and dotstar modules has changed. The
|
||||
information is now stored as a list of color lists (instead of a list
|
||||
of dictionaries). See the [status reference](Status_Reference.md#led)
|
||||
for details.
|
||||
|
||||
20220307: `M73` will no longer set print progress to 0 if `P` is missing.
|
||||
|
||||
20220304: There is no longer a default for the `extruder` parameter of
|
||||
[extruder_stepper](Config_Reference.md#extruder_stepper) config
|
||||
sections. If desired, specify `extruder: extruder` explicitly to
|
||||
associate the stepper motor with the "extruder" motion queue at
|
||||
startup.
|
||||
|
||||
20220210: The `SYNC_STEPPER_TO_EXTRUDER` command is deprecated; the
|
||||
`SET_EXTRUDER_STEP_DISTANCE` command is deprecated; the
|
||||
[extruder](Config_Reference.md#extruder) `shared_heater` config option
|
||||
is deprecated. These features will be removed in the near future.
|
||||
Replace `SET_EXTRUDER_STEP_DISTANCE` with
|
||||
`SET_EXTRUDER_ROTATION_DISTANCE`. Replace `SYNC_STEPPER_TO_EXTRUDER`
|
||||
with `SYNC_EXTRUDER_MOTION`. Replace extruder config sections using
|
||||
`shared_heater` with
|
||||
[extruder_stepper](Config_Reference.md#extruder_stepper) config
|
||||
sections and update any activation macros to use
|
||||
[SYNC_EXTRUDER_MOTION](G-Codes.md#sync_extruder_motion).
|
||||
|
||||
20220116: The tmc2130, tmc2208, tmc2209, and tmc2660 `run_current`
|
||||
calculation code has changed. For some `run_current` settings the
|
||||
drivers may now be configured differently. This new configuration
|
||||
should be more accurate, but it may invalidate previous tmc driver
|
||||
tuning.
|
||||
|
||||
20211230: Scripts to tune input shaper (`scripts/calibrate_shaper.py`
|
||||
and `scripts/graph_accelerometer.py`) were migrated to use Python3
|
||||
by default. As a result, users must install Python3 versions of certain
|
||||
packages (e.g. `sudo apt install python3-numpy python3-matplotlib`) to
|
||||
continue using these scripts. For more details, refer to
|
||||
[Software installation](Measuring_Resonances.md#software-installation).
|
||||
Alternatively, users can temporarily force the execution of these scripts
|
||||
under Python 2 by explicitly calling Python2 interpretor in the console:
|
||||
`python2 ~/klipper/scripts/calibrate_shaper.py ...`
|
||||
|
||||
20211110: The "NTC 100K beta 3950" temperature sensor is deprecated.
|
||||
This sensor will be removed in the near future. Most users will find
|
||||
the "Generic 3950" temperature sensor more accurate. To continue to
|
||||
use the older (typically less accurate) definition, define a custom
|
||||
[thermistor](Config_Reference.md#thermistor) with `temperature1: 25`,
|
||||
`resistance1: 100000`, and `beta: 3950`.
|
||||
|
||||
20211104: The "step pulse duration" option in "make menuconfig" has
|
||||
been removed. The default step duration for TMC drivers configured in
|
||||
UART or SPI mode is now 100ns. A new `step_pulse_duration` setting in
|
||||
the [stepper config section](Config_Reference.md#stepper) should be
|
||||
set for all steppers that need a custom pulse duration.
|
||||
|
||||
20211102: Several deprecated features have been removed. The stepper
|
||||
`step_distance` option has been removed (deprecated on 20201222). The
|
||||
`rpi_temperature` sensor alias has been removed (deprecated on
|
||||
20210219). The mcu `pin_map` option has been removed (deprecated on
|
||||
20210325). The gcode_macro `default_parameter_<name>` and macro
|
||||
access to command parameters other than via the `params`
|
||||
pseudo-variable has been removed (deprecated on 20210503). The heater
|
||||
`pid_integral_max` option has been removed (deprecated on 20210612).
|
||||
|
||||
20210929: Klipper v0.10.0 released.
|
||||
|
||||
20210903: The default [`smooth_time`](Config_Reference.md#extruder)
|
||||
for heaters has changed to 1 second (from 2 seconds). For most
|
||||
printers this will result in more stable temperature control.
|
||||
|
||||
20210830: The default adxl345 name is now "adxl345". The default CHIP
|
||||
parameter for the `ACCELEROMETER_MEASURE` and `ACCELEROMETER_QUERY` is
|
||||
now also "adxl345".
|
||||
|
||||
20210830: The adxl345 ACCELEROMETER_MEASURE command no longer supports
|
||||
a RATE parameter. To alter the query rate, update the printer.cfg
|
||||
file and issue a RESTART command.
|
||||
|
||||
20210821: Several config settings in `printer.configfile.settings`
|
||||
will now be reported as lists instead of raw strings. If the actual
|
||||
raw string is desired, use `printer.configfile.config` instead.
|
||||
|
||||
20210819: In some cases, a `G28` homing move may end in a position
|
||||
that is nominally outside the valid movement range. In rare
|
||||
situations this may result in confusing "Move out of range" errors
|
||||
after homing. If this occurs, change your start scripts to move the
|
||||
toolhead to a valid position immediately after homing.
|
||||
|
||||
20210814: The analog only pseudo-pins on the atmega168 and atmega328
|
||||
have been renamed from PE0/PE1 to PE2/PE3.
|
||||
|
||||
20210720: A controller_fan section now monitors all stepper motors by
|
||||
default (not just the kinematic stepper motors). If the previous
|
||||
behavior is desired, see the `stepper` config option in the
|
||||
[config reference](Config_Reference.md#controller_fan).
|
||||
|
||||
20210703: A `samd_sercom` config section must now specify the sercom
|
||||
bus it is configuring via the `sercom` option.
|
||||
|
||||
20210612: The `pid_integral_max` config option in heater and
|
||||
temperature_fan sections is deprecated. The option will be removed in
|
||||
the near future.
|
||||
|
||||
20210503: The gcode_macro `default_parameter_<name>` config option is
|
||||
deprecated. Use the `params` pseudo-variable to access macro
|
||||
parameters. Other methods for accessing macro parameters will be
|
||||
removed in the near future. Most users can replace a
|
||||
`default_parameter_NAME: VALUE` config option with a line like the
|
||||
following in the start of the macro: ` {% set NAME =
|
||||
params.NAME|default(VALUE)|float %}`. See the [Command Templates
|
||||
document](Command_Templates.md#macro-parameters) for examples.
|
||||
|
||||
20210430: The SET_VELOCITY_LIMIT (and M204) command may now set a
|
||||
velocity, acceleration, and square_corner_velocity larger than the
|
||||
specified values in the config file.
|
||||
|
||||
20210325: Support for the `pin_map` config option is deprecated. Use
|
||||
the [sample-aliases.cfg](../config/sample-aliases.cfg) file to
|
||||
translate to the actual micro-controller pin names. The `pin_map`
|
||||
config option will be removed in the near future.
|
||||
|
||||
20210313: Klipper's support for micro-controllers that communicate
|
||||
with CAN bus has changed. If using CAN bus then all micro-controllers
|
||||
must be reflashed and the
|
||||
[Klipper configuration must be updated](CANBUS.md).
|
||||
|
||||
20210310: The TMC2660 default for driver_SFILT has been changed from 1
|
||||
to 0.
|
||||
|
||||
20210227: TMC stepper motor drivers in UART or SPI mode are now
|
||||
queried once per second whenever they are enabled - if the driver can
|
||||
not be contacted or if the driver reports an error, then Klipper will
|
||||
transition to a shutdown state.
|
||||
|
||||
20210219: The `rpi_temperature` module has been renamed to
|
||||
`temperature_host`. Replace any occurrences of `sensor_type:
|
||||
rpi_temperature` with `sensor_type: temperature_host`. The path to
|
||||
the temperature file may be specified in the `sensor_path` config
|
||||
variable. The `rpi_temperature` name is deprecated and will be
|
||||
removed in the near future.
|
||||
|
||||
20210201: The `TEST_RESONANCES` command will now disable input shaping
|
||||
if it was previously enabled (and re-enable it after the test). In order
|
||||
to override this behavior and keep the input shaping enabled, one can
|
||||
pass an additional parameter `INPUT_SHAPING=1` to the command.
|
||||
|
||||
20210201: The `ACCELEROMETER_MEASURE` command will now append the name
|
||||
of the accelerometer chip to the output file name if the chip was given
|
||||
a name in the corresponding adxl345 section of the printer.cfg.
|
||||
|
||||
20201222: The `step_distance` setting in the stepper config sections
|
||||
is deprecated. It is advised to update the config to use the
|
||||
[`rotation_distance`](Rotation_Distance.md) setting. Support for
|
||||
`step_distance` will be removed in the near future.
|
||||
|
||||
20201218: The `endstop_phase` setting in the endstop_phase module has
|
||||
been replaced with `trigger_phase`. If using the endstop phases module
|
||||
then it will be necessary to convert to
|
||||
[`rotation_distance`](Rotation_Distance.md) and recalibrate any
|
||||
endstop phases by running the ENDSTOP_PHASE_CALIBRATE command.
|
||||
|
||||
20201218: Rotary delta and polar printers must now specify a
|
||||
`gear_ratio` for their rotary steppers, and they may no longer specify
|
||||
a `step_distance` parameter. See the
|
||||
[config reference](Config_Reference.md#stepper) for the format of the
|
||||
new gear_ratio paramter.
|
||||
|
||||
20201213: It is not valid to specify a Z "position_endstop" when using
|
||||
"probe:z_virtual_endstop". An error will now be raised if a Z
|
||||
"position_endstop" is specified with "probe:z_virtual_endstop".
|
||||
Remove the Z "position_endstop" definition to fix the error.
|
||||
|
||||
20201120: The `[board_pins]` config section now specifies the mcu name
|
||||
in an explicit `mcu:` parameter. If using board_pins for a secondary
|
||||
mcu, then the config must be updated to specify that name. See the
|
||||
[config reference](Config_Reference.md#board_pins) for further
|
||||
details.
|
||||
|
||||
20201112: The time reported by `print_stats.print_duration` has
|
||||
changed. The duration prior to the first detected extrusion is
|
||||
now excluded.
|
||||
|
||||
20201029: The neopixel `color_order_GRB` config option has been
|
||||
removed. If necessary, update the config to set the new `color_order`
|
||||
option to RGB, GRB, RGBW, or GRBW.
|
||||
|
||||
20201029: The serial option in the mcu config section no longer
|
||||
defaults to /dev/ttyS0. In the rare situation where /dev/ttyS0 is the
|
||||
desired serial port, it must be specified explicitly.
|
||||
|
||||
20201020: Klipper v0.9.0 released.
|
||||
|
||||
20200902: The RTD resistance-to-temperature calculation for MAX31865
|
||||
converters has been corrected to not read low. If you are using such a
|
||||
device, you should recalibrate your print temperature and PID settings.
|
||||
|
||||
20200816: The gcode macro `printer.gcode` object has been renamed to
|
||||
`printer.gcode_move`. Several undocumented variables in
|
||||
`printer.toolhead` and `printer.gcode` have been removed. See
|
||||
docs/Command_Templates.md for a list of available template variables.
|
||||
|
||||
20200816: The gcode macro "action_" system has changed. Replace any
|
||||
calls to `printer.gcode.action_emergency_stop()` with
|
||||
`action_emergency_stop()`, `printer.gcode.action_respond_info()` with
|
||||
`action_respond_info()`, and `printer.gcode.action_respond_error()`
|
||||
with `action_raise_error()`.
|
||||
|
||||
20200809: The menu system has been rewritten. If the menu has been
|
||||
customized then it will be necessary to update to the new
|
||||
configuration. See config/example-menu.cfg for configuration details
|
||||
and see klippy/extras/display/menu.cfg for examples.
|
||||
|
||||
20200731: The behavior of the `progress` attribute reported by
|
||||
the `virtual_sdcard` printer object has changed. Progress is no
|
||||
longer reset to 0 when a print is paused. It will now always report
|
||||
progress based on the internal file position, or 0 if no file is
|
||||
currently loaded.
|
||||
|
||||
20200725: The servo `enable` config parameter and the SET_SERVO
|
||||
`ENABLE` parameter have been removed. Update any macros to use
|
||||
`SET_SERVO SERVO=my_servo WIDTH=0` to disable a servo.
|
||||
|
||||
20200608: The LCD display support has changed the name of some
|
||||
internal "glyphs". If a custom display layout was implemented it may
|
||||
be necessary to update to the latest glyph names (see
|
||||
klippy/extras/display/display.cfg for a list of available glyphs).
|
||||
|
||||
20200606: The pin names on linux mcu have changed. Pins now have names
|
||||
of the form `gpiochip<chipid>/gpio<gpio>`. For gpiochip0 you can also
|
||||
use a short `gpio<gpio>`. For example, what was previously referred
|
||||
to as `P20` now becomes `gpio20` or `gpiochip0/gpio20`.
|
||||
|
||||
20200603: The default 16x4 LCD layout will no longer show the
|
||||
estimated time remaining in a print. (Only the elapsed time will be
|
||||
shown.) If the old behavior is desired one can customize the menu
|
||||
display with that information (see the description of display_data in
|
||||
config/example-extras.cfg for details).
|
||||
|
||||
20200531: The default USB vendor/product id is now 0x1d50/0x614e.
|
||||
These new ids are reserved for Klipper (thanks to the openmoko
|
||||
project). This change should not require any config changes, but the
|
||||
new ids may appear in system logs.
|
||||
|
||||
20200524: The default value for the tmc5160 pwm_freq field is now zero
|
||||
(instead of one).
|
||||
|
||||
20200425: The gcode_macro command template variable `printer.heater`
|
||||
was renamed to `printer.heaters`.
|
||||
|
||||
20200313: The default lcd layout for multi-extruder printers with a
|
||||
16x4 screen has changed. The single extruder screen layout is now the
|
||||
default and it will show the currently active extruder. To use the
|
||||
previous display layout set "display_group: _multiextruder_16x4" in
|
||||
the [display] section of the printer.cfg file.
|
||||
|
||||
20200308: The default `__test` menu item was removed. If the config
|
||||
file has a custom menu then be sure to remove all references to this
|
||||
`__test` menu item.
|
||||
|
||||
20200308: The menu "deck" and "card" options were removed. To
|
||||
customize the layout of an lcd screen use the new display_data config
|
||||
sections (see config/example-extras.cfg for the details).
|
||||
|
||||
20200109: The bed_mesh module now references the probe's location
|
||||
in for the mesh configuration. As such, some configuration options
|
||||
have been renamed to more accurately reflect their intended
|
||||
functionality. For rectangular beds, `min_point` and `max_point`
|
||||
have been renamed to `mesh_min` and `mesh_max` respectively. For
|
||||
round beds, `bed_radius` has been renamed to `mesh_radius`. A new
|
||||
`mesh_origin` option has also been added for round beds. Note that
|
||||
these changes are also incompatible with previously saved mesh profiles.
|
||||
If an incompatible profile is detected it will be ignored and scheduled
|
||||
for removal. The removal process can be completed by issuing the
|
||||
SAVE_CONFIG command. The user will need to re-calibrate each profile.
|
||||
|
||||
20191218: The display config section no longer supports "lcd_type:
|
||||
st7567". Use the "uc1701" display type instead - set "lcd_type:
|
||||
uc1701" and change the "rs_pin: some_pin" to "rst_pin: some_pin". It
|
||||
may also be necessary to add a "contrast: 60" config setting.
|
||||
|
||||
20191210: The builtin T0, T1, T2, ... commands have been removed. The
|
||||
extruder activate_gcode and deactivate_gcode config options have been
|
||||
removed. If these commands (and scripts) are needed then define
|
||||
individual [gcode_macro T0] style macros that call the
|
||||
ACTIVATE_EXTRUDER command. See the config/sample-idex.cfg and
|
||||
sample-multi-extruder.cfg files for examples.
|
||||
|
||||
20191210: Support for the M206 command has been removed. Replace with
|
||||
calls to SET_GCODE_OFFSET. If support for M206 is needed, add a
|
||||
[gcode_macro M206] config section that calls SET_GCODE_OFFSET. (For
|
||||
example "SET_GCODE_OFFSET Z=-{params.Z}".)
|
||||
|
||||
20191202: Support for the undocumented "S" parameter of the "G4"
|
||||
command has been removed. Replace any occurrences of S with the
|
||||
standard "P" parameter (the delay specified in milliseconds).
|
||||
|
||||
20191126: The USB names have changed on micro-controllers with native
|
||||
USB support. They now use a unique chip id by default (where
|
||||
available). If an "mcu" config section uses a "serial" setting that
|
||||
starts with "/dev/serial/by-id/" then it may be necessary to update
|
||||
the config. Run "ls /dev/serial/by-id/*" in an ssh terminal to
|
||||
determine the new id.
|
||||
|
||||
20191121: The pressure_advance_lookahead_time parameter has been
|
||||
removed. See example.cfg for alternate configuration settings.
|
||||
|
||||
20191112: The tmc stepper driver virtual enable capability is now
|
||||
automatically enabled if the stepper does not have a dedicated stepper
|
||||
enable pin. Remove references to tmcXXXX:virtual_enable from the
|
||||
config. The ability to control multiple pins in the stepper
|
||||
enable_pin config has been removed. If multiple pins are needed then
|
||||
use a multi_pin config section.
|
||||
|
||||
20191107: The primary extruder config section must be specified as
|
||||
"extruder" and may no longer be specified as "extruder0". Gcode
|
||||
command templates that query the extruder status are now accessed via
|
||||
"{printer.extruder}".
|
||||
|
||||
20191021: Klipper v0.8.0 released
|
||||
|
||||
20191003: The move_to_previous option in [safe_z_homing] now defaults
|
||||
to False. (It was effectively False prior to 20190918.)
|
||||
|
||||
20190918: The zhop option in [safe_z_homing] is always re-applied
|
||||
after Z axis homing completed. This might need users to update custom
|
||||
scripts based on this module.
|
||||
|
||||
20190806: The SET_NEOPIXEL command has been renamed to SET_LED.
|
||||
|
||||
20190726: The mcp4728 digital-to-analog code has changed. The default
|
||||
i2c_address is now 0x60 and the voltage reference is now relative to
|
||||
the mcp4728's internal 2.048 volt reference.
|
||||
|
||||
20190710: The z_hop option was removed from the [firmware_retract]
|
||||
config section. The z_hop support was incomplete and could cause
|
||||
incorrect behavior with several common slicers.
|
||||
|
||||
20190710: The optional parameters of the PROBE_ACCURACY command have
|
||||
changed. It may be necessary to update any macros or scripts that use
|
||||
that command.
|
||||
|
||||
20190628: All configuration options have been removed from the
|
||||
[skew_correction] section. Configuration for skew_correction
|
||||
is now done via the SET_SKEW gcode. See [Skew Correction](Skew_Correction.md)
|
||||
for recommended usage.
|
||||
|
||||
20190607: The "variable_X" parameters of gcode_macro (along with the
|
||||
VALUE parameter of SET_GCODE_VARIABLE) are now parsed as Python
|
||||
literals. If a value needs to be assigned a string then wrap the value
|
||||
in quotes so that it is evaluated as a string.
|
||||
|
||||
20190606: The "samples", "samples_result", and "sample_retract_dist"
|
||||
config options have been moved to the "probe" config section. These
|
||||
options are no longer supported in the "delta_calibrate", "bed_tilt",
|
||||
"bed_mesh", "screws_tilt_adjust", "z_tilt", or "quad_gantry_level"
|
||||
config sections.
|
||||
|
||||
20190528: The magic "status" variable in gcode_macro template
|
||||
evaluation has been renamed to "printer".
|
||||
|
||||
20190520: The SET_GCODE_OFFSET command has changed; update any g-code
|
||||
macros accordingly. The command will no longer apply the requested
|
||||
offset to the next G1 command. The old behavior may be approximated by
|
||||
using the new "MOVE=1" parameter.
|
||||
|
||||
20190404: The Python host software packages were updated. Users will
|
||||
need to rerun the ~/klipper/scripts/install-octopi.sh script (or
|
||||
otherwise upgrade the python dependencies if not using a standard
|
||||
OctoPi installation).
|
||||
|
||||
20190404: The i2c_bus and spi_bus parameters (in various config
|
||||
sections) now take a bus name instead of a number.
|
||||
|
||||
20190404: The sx1509 config parameters have changed. The 'address'
|
||||
parameter is now 'i2c_address' and it must be specified as a decimal
|
||||
number. Where 0x3E was previously used, specify 62.
|
||||
|
||||
20190328: The min_speed value in [temperature_fan] config
|
||||
will now be respected and the fan will always run at this
|
||||
speed or higher in PID mode.
|
||||
|
||||
20190322: The default value for "driver_HEND" in [tmc2660] config
|
||||
sections was changed from 6 to 3. The "driver_VSENSE" field was
|
||||
removed (it is now automatically calculated from run_current).
|
||||
|
||||
20190310: The [controller_fan] config section now always takes a name
|
||||
(such as [controller_fan my_controller_fan]).
|
||||
|
||||
20190308: The "driver_BLANK_TIME_SELECT" field in [tmc2130] and
|
||||
[tmc2208] config sections has been renamed to "driver_TBL".
|
||||
|
||||
20190308: The [tmc2660] config section has changed. A new
|
||||
sense_resistor config parameter must now be provided. The meaning of
|
||||
several of the driver_XXX parameters has changed.
|
||||
|
||||
20190228: Users of SPI or I2C on SAMD21 boards must now specify the
|
||||
bus pins via a [samd_sercom] config section.
|
||||
|
||||
20190224: The bed_shape option has been removed from bed_mesh. The
|
||||
radius option has been renamed to bed_radius. Users with round beds
|
||||
should supply the bed_radius and round_probe_count options.
|
||||
|
||||
20190107: The i2c_address parameter in the mcp4451 config section
|
||||
changed. This is a common setting on Smoothieboards. The new value is
|
||||
half the old value (88 should be changed to 44, and 90 should be
|
||||
changed to 45).
|
||||
|
||||
20181220: Klipper v0.7.0 released
|
||||
4252
docs/Config_Reference.md
Normal file
169
docs/Config_checks.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Configuration checks
|
||||
|
||||
This document provides a list of steps to help confirm the pin
|
||||
settings in the Klipper printer.cfg file. It is a good idea to run
|
||||
through these steps after following the steps in the
|
||||
[installation document](Installation.md).
|
||||
|
||||
During this guide, it may be necessary to make changes to the Klipper
|
||||
config file. Be sure to issue a RESTART command after every change to
|
||||
the config file to ensure that the change takes effect (type "restart"
|
||||
in the Octoprint terminal tab and then click "Send"). It's also a good
|
||||
idea to issue a STATUS command after every RESTART to verify that the
|
||||
config file is successfully loaded.
|
||||
|
||||
## Verify temperature
|
||||
|
||||
Start by verifying that temperatures are being properly reported.
|
||||
Navigate to the Octoprint temperature tab.
|
||||
|
||||

|
||||
|
||||
Verify that the temperature of the nozzle and bed (if applicable) are
|
||||
present and not increasing. If it is increasing, remove power from the
|
||||
printer. If the temperatures are not accurate, review the
|
||||
"sensor_type" and "sensor_pin" settings for the nozzle and/or bed.
|
||||
|
||||
## Verify M112
|
||||
|
||||
Navigate to the Octoprint terminal tab and issue an M112 command in
|
||||
the terminal box. This command requests Klipper to go into a
|
||||
"shutdown" state. It will cause Octoprint to disconnect from Klipper -
|
||||
navigate to the Connection area and click on "Connect" to cause
|
||||
Octoprint to reconnect. Then navigate to the Octoprint temperature tab
|
||||
and verify that temperatures continue to update and the temperatures
|
||||
are not increasing. If temperatures are increasing, remove power from
|
||||
the printer.
|
||||
|
||||
The M112 command causes Klipper to go into a "shutdown" state. To
|
||||
clear this state, issue a FIRMWARE_RESTART command in the Octoprint
|
||||
terminal tab.
|
||||
|
||||
## Verify heaters
|
||||
|
||||
Navigate to the Octoprint temperature tab and type in 50 followed by
|
||||
enter in the "Tool" temperature box. The extruder temperature in the
|
||||
graph should start to increase (within about 30 seconds or so). Then
|
||||
go to the "Tool" temperature drop-down box and select "Off". After
|
||||
several minutes the temperature should start to return to its initial
|
||||
room temperature value. If the temperature does not increase then
|
||||
verify the "heater_pin" setting in the config.
|
||||
|
||||
If the printer has a heated bed then perform the above test again with
|
||||
the bed.
|
||||
|
||||
## Verify stepper motor enable pin
|
||||
|
||||
Verify that all of the printer axes can manually move freely (the
|
||||
stepper motors are disabled). If not, issue an M84 command to disable
|
||||
the motors. If any of the axes still can not move freely, then verify
|
||||
the stepper "enable_pin" configuration for the given axis. On most
|
||||
commodity stepper motor drivers, the motor enable pin is "active low"
|
||||
and therefore the enable pin should have a "!" before the pin (for
|
||||
example, "enable_pin: !ar38").
|
||||
|
||||
## Verify endstops
|
||||
|
||||
Manually move all the printer axes so that none of them are in contact
|
||||
with an endstop. Send a QUERY_ENDSTOPS command via the Octoprint
|
||||
terminal tab. It should respond with the current state of all of the
|
||||
configured endstops and they should all report a state of "open". For
|
||||
each of the endstops, rerun the QUERY_ENDSTOPS command while manually
|
||||
triggering the endstop. The QUERY_ENDSTOPS command should report the
|
||||
endstop as "TRIGGERED".
|
||||
|
||||
If the endstop appears inverted (it reports "open" when triggered and
|
||||
vice-versa) then add a "!" to the pin definition (for example,
|
||||
"endstop_pin: ^!ar3"), or remove the "!" if there is already one
|
||||
present.
|
||||
|
||||
If the endstop does not change at all then it generally indicates that
|
||||
the endstop is connected to a different pin. However, it may also
|
||||
require a change to the pullup setting of the pin (the '^' at the
|
||||
start of the endstop_pin name - most printers will use a pullup
|
||||
resistor and the '^' should be present).
|
||||
|
||||
## Verify stepper motors
|
||||
|
||||
Use the STEPPER_BUZZ command to verify the connectivity of each
|
||||
stepper motor. Start by manually positioning the given axis to a
|
||||
midway point and then run `STEPPER_BUZZ STEPPER=stepper_x`. The
|
||||
STEPPER_BUZZ command will cause the given stepper to move one
|
||||
millimeter in a positive direction and then it will return to its
|
||||
starting position. (If the endstop is defined at position_endstop=0
|
||||
then at the start of each movement the stepper will move away from the
|
||||
endstop.) It will perform this oscillation ten times.
|
||||
|
||||
If the stepper does not move at all, then verify the "enable_pin" and
|
||||
"step_pin" settings for the stepper. If the stepper motor moves but
|
||||
does not return to its original position then verify the "dir_pin"
|
||||
setting. If the stepper motor oscillates in an incorrect direction,
|
||||
then it generally indicates that the "dir_pin" for the axis needs to
|
||||
be inverted. This is done by adding a '!' to the "dir_pin" in the
|
||||
printer config file (or removing it if one is already there). If the
|
||||
motor moves significantly more or significantly less than one
|
||||
millimeter then verify the "rotation_distance" setting.
|
||||
|
||||
Run the above test for each stepper motor defined in the config
|
||||
file. (Set the STEPPER parameter of the STEPPER_BUZZ command to the
|
||||
name of the config section that is to be tested.) If there is no
|
||||
filament in the extruder then one can use STEPPER_BUZZ to verify the
|
||||
extruder motor connectivity (use STEPPER=extruder). Otherwise, it's
|
||||
best to test the extruder motor separately (see the next section).
|
||||
|
||||
After verifying all endstops and verifying all stepper motors the
|
||||
homing mechanism should be tested. Issue a G28 command to home all
|
||||
axes. Remove power from the printer if it does not home properly.
|
||||
Rerun the endstop and stepper motor verification steps if necessary.
|
||||
|
||||
## Verify extruder motor
|
||||
|
||||
To test the extruder motor it will be necessary to heat the extruder
|
||||
to a printing temperature. Navigate to the Octoprint temperature tab
|
||||
and select a target temperature from the temperature drop-down box (or
|
||||
manually enter an appropriate temperature). Wait for the printer to
|
||||
reach the desired temperature. Then navigate to the Octoprint control
|
||||
tab and click the "Extrude" button. Verify that the extruder motor
|
||||
turns in the correct direction. If it does not, see the
|
||||
troubleshooting tips in the previous section to confirm the
|
||||
"enable_pin", "step_pin", and "dir_pin" settings for the extruder.
|
||||
|
||||
## Calibrate PID settings
|
||||
|
||||
Klipper supports
|
||||
[PID control](https://en.wikipedia.org/wiki/PID_controller) for the
|
||||
extruder and bed heaters. In order to use this control mechanism, it is
|
||||
necessary to calibrate the PID settings on each printer (PID settings
|
||||
found in other firmwares or in the example configuration files often
|
||||
work poorly).
|
||||
|
||||
To calibrate the extruder, navigate to the OctoPrint terminal tab and
|
||||
run the PID_CALIBRATE command. For example: `PID_CALIBRATE
|
||||
HEATER=extruder TARGET=170`
|
||||
|
||||
At the completion of the tuning test run `SAVE_CONFIG` to update the
|
||||
printer.cfg file the new PID settings.
|
||||
|
||||
If the printer has a heated bed and it supports being driven by PWM
|
||||
(Pulse Width Modulation) then it is recommended to use PID control for
|
||||
the bed. (When the bed heater is controlled using the PID algorithm it
|
||||
may turn on and off ten times a second, which may not be suitable for
|
||||
heaters using a mechanical switch.) A typical bed PID calibration
|
||||
command is: `PID_CALIBRATE HEATER=heater_bed TARGET=60`
|
||||
|
||||
## Next steps
|
||||
|
||||
This guide is intended to help with basic verification of pin settings
|
||||
in the Klipper configuration file. Be sure to read the
|
||||
[bed leveling](Bed_Level.md) guide. Also see the [Slicers](Slicers.md)
|
||||
document for information on configuring a slicer with Klipper.
|
||||
|
||||
After one has verified that basic printing works, it is a good idea to
|
||||
consider calibrating [pressure advance](Pressure_Advance.md).
|
||||
|
||||
It may be necessary to perform other types of detailed printer
|
||||
calibration - a number of guides are available online to help with
|
||||
this (for example, do a web search for "3d printer calibration").
|
||||
As an example, if you experience the effect called ringing,
|
||||
you may try following [resonance compensation](Resonance_Compensation.md)
|
||||
tuning guide.
|
||||
165
docs/Contact.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Contact
|
||||
|
||||
This document provides contact information for Klipper.
|
||||
|
||||
1. [Community Forum](#community-forum)
|
||||
2. [Discord Chat](#discord-chat)
|
||||
3. [I have a question about Klipper](#i-have-a-question-about-klipper)
|
||||
4. [I have a feature request](#i-have-a-feature-request)
|
||||
5. [Help! It doesn't work!](#help-it-doesnt-work)
|
||||
6. [I have diagnosed a defect in the Klipper software](#i-have-diagnosed-a-defect-in-the-klipper-software)
|
||||
7. [I am making changes that I'd like to include in Klipper](#i-am-making-changes-that-id-like-to-include-in-klipper)
|
||||
|
||||
## Community Forum
|
||||
|
||||
There is a
|
||||
[Klipper Community Discourse server](https://community.klipper3d.org)
|
||||
for discussions on Klipper.
|
||||
|
||||
## Discord Chat
|
||||
|
||||
There is a Discord server dedicated to Klipper at:
|
||||
[https://discord.klipper3d.org](https://discord.klipper3d.org).
|
||||
|
||||
This server is run by a community of Klipper enthusiasts dedicated to
|
||||
discussions on Klipper. It allows users to chat with other users in
|
||||
real-time.
|
||||
|
||||
## I have a question about Klipper
|
||||
|
||||
Many questions we receive are already answered in the
|
||||
[Klipper documentation](Overview.md). Please be sure to to read the
|
||||
documentation and follow the directions provided there.
|
||||
|
||||
It is also possible to search for similar questions in the
|
||||
[Klipper Community Forum](#community-forum).
|
||||
|
||||
If you are interested in sharing your knowledge and experience with
|
||||
other Klipper users then you can join the
|
||||
[Klipper Community Forum](#community-forum) or
|
||||
[Klipper Discord Chat](#discord-chat). Both are communities where
|
||||
Klipper users can discuss Klipper with other users.
|
||||
|
||||
Many questions we receive are general 3d-printing questions that are
|
||||
not specific to Klipper. If you have a general question or are
|
||||
experiencing general printing problems, then you will likely get a
|
||||
better response by asking in a general 3d-printing forum or a forum
|
||||
dedicated to your printer hardware.
|
||||
|
||||
Do not open a Klipper github issue to ask a question.
|
||||
|
||||
## I have a feature request
|
||||
|
||||
All new features require someone interested and able to implement that
|
||||
feature. If you are interested in helping to implement or test a new
|
||||
feature, you can search for ongoing developments in the
|
||||
[Klipper Community Forum](#community-forum). There is also
|
||||
[Klipper Discord Chat](#discord-chat) for discussions between
|
||||
collaborators.
|
||||
|
||||
Do not open a Klipper github issue to request a feature.
|
||||
|
||||
## Help! It doesn't work!
|
||||
|
||||
Unfortunately, we receive many more requests for help than we could
|
||||
possibly answer. Most problem reports we see are eventually tracked
|
||||
down to:
|
||||
1. Subtle errors in the hardware, or
|
||||
2. Not following all the steps described in the Klipper documentation.
|
||||
|
||||
If you are experiencing problems we recommend you carefully read the
|
||||
[Klipper documentation](Overview.md) and double check that all steps
|
||||
were followed.
|
||||
|
||||
If you are experiencing a printing problem, then we recommend
|
||||
carefully inspecting the printer hardware (all joints, wires, screws,
|
||||
etc.) and verify nothing is abnormal. We find most printing problems
|
||||
are not related to the Klipper software. If you do find a problem with
|
||||
the printer hardware then you will likely get a better response by
|
||||
searching in a general 3d-printing forum or in a forum dedicated to
|
||||
your printer hardware.
|
||||
|
||||
It is also possible to search for similar issues in the
|
||||
[Klipper Community Forum](#community-forum).
|
||||
|
||||
If you are interested in sharing your knowledge and experience with
|
||||
other Klipper users then you can join the
|
||||
[Klipper Community Forum](#community-forum) or
|
||||
[Klipper Discord Chat](#discord-chat). Both are communities where
|
||||
Klipper users can discuss Klipper with other users.
|
||||
|
||||
Do not open a Klipper github issue to request help.
|
||||
|
||||
## I have diagnosed a defect in the Klipper software
|
||||
|
||||
Klipper is an open-source project and we appreciate when collaborators
|
||||
diagnose errors in the software.
|
||||
|
||||
There is important information that will be needed in order to fix a
|
||||
bug. Please follow these steps:
|
||||
1. Be sure the bug is in the Klipper software. If you are thinking
|
||||
"there is a problem, I can't figure out why, and therefore it is a
|
||||
Klipper bug", then **do not** open a github issue. In that case,
|
||||
someone interested and able will need to first research and
|
||||
diagnose the root cause of the problem. If you would like to share
|
||||
the results of your research or check if other users are
|
||||
experiencing similar issues then you can search the
|
||||
[Klipper Community Forum](#community-forum).
|
||||
2. Make sure you are running unmodified code from
|
||||
[https://github.com/Klipper3d/klipper](https://github.com/Klipper3d/klipper).
|
||||
If the code has been modified or is obtained from another source,
|
||||
then you will need to reproduce the problem on the unmodified code
|
||||
from
|
||||
[https://github.com/Klipper3d/klipper](https://github.com/Klipper3d/klipper)
|
||||
prior to reporting an issue.
|
||||
3. If possible, run an `M112` command in the OctoPrint terminal window
|
||||
immediately after the undesirable event occurs. This causes Klipper
|
||||
to go into a "shutdown state" and it will cause additional
|
||||
debugging information to be written to the log file.
|
||||
4. Obtain the Klipper log file from the event. The log file has been
|
||||
engineered to answer common questions the Klipper developers have
|
||||
about the software and its environment (software version, hardware
|
||||
type, configuration, event timing, and hundreds of other
|
||||
questions).
|
||||
1. The Klipper log file is located in `/tmp/klippy.log` on the
|
||||
Klipper "host" computer (the Raspberry Pi).
|
||||
2. An "scp" or "sftp" utility is needed to copy this log file to
|
||||
your desktop computer. The "scp" utility comes standard with
|
||||
Linux and MacOS desktops. There are freely available scp
|
||||
utilities for other desktops (eg, WinSCP). If using a graphical
|
||||
scp utility that can not directly copy `/tmp/klippy.log` then
|
||||
repeatedly click on `..` or `parent folder` until you get to the
|
||||
root directory, click on the `tmp` folder, and then select the
|
||||
`klippy.log` file.
|
||||
3. Copy the log file to your desktop so that it can be attached to
|
||||
an issue report.
|
||||
4. Do not modify the log file in any way; do not provide a snippet
|
||||
of the log. Only the full unmodified log file provides the
|
||||
necessary information.
|
||||
5. If the log file is very large (eg, greater than 2MB) then one
|
||||
may need to compress the log with zip or gzip.
|
||||
5. Open a new github issue at
|
||||
[https://github.com/Klipper3d/klipper/issues](https://github.com/Klipper3d/klipper/issues)
|
||||
and provide a clear description of the problem. The Klipper
|
||||
developers need to understand what steps were taken, what the
|
||||
desired outcome was, and what outcome actually occurred. The
|
||||
Klipper log file **must be attached** to that ticket:
|
||||
|
||||

|
||||
|
||||
## I am making changes that I'd like to include in Klipper
|
||||
|
||||
Klipper is open-source software and we appreciate new contributions.
|
||||
|
||||
New contributions (for both code and documentation) are submitted via
|
||||
Github Pull Requests. See the [CONTRIBUTING document](CONTRIBUTING.md)
|
||||
for important information.
|
||||
|
||||
There are several
|
||||
[documents for developers](Overview.md#developer-documentation). If
|
||||
you have questions on the code then you can also ask in the
|
||||
[Klipper Community Forum](#community-forum) or on the
|
||||
[Klipper Community Discord](#discord-chat). If you would like to
|
||||
provide an update on your current progress then you can open a Github
|
||||
issue with the location of your code, an overview of the changes, and
|
||||
a description of its current status.
|
||||
280
docs/Debugging.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# Debugging
|
||||
|
||||
This document describes some of the Klipper debugging tools.
|
||||
|
||||
## Running the regression tests
|
||||
|
||||
The main Klipper GitHub repository uses "github actions" to run a
|
||||
series of regression tests. It can be useful to run some of these
|
||||
tests locally.
|
||||
|
||||
The source code "whitespace check" can be run with:
|
||||
```
|
||||
./scripts/check_whitespace.sh
|
||||
```
|
||||
|
||||
The Klippy regression test suite requires "data dictionaries" from
|
||||
many platforms. The easiest way to obtain them is to
|
||||
[download them from github](https://github.com/Klipper3d/klipper/issues/1438).
|
||||
Once the data dictionaries are downloaded, use the following to run
|
||||
the regression suite:
|
||||
```
|
||||
tar xfz klipper-dict-20??????.tar.gz
|
||||
~/klippy-env/bin/python ~/klipper/scripts/test_klippy.py -d dict/ ~/klipper/test/klippy/*.test
|
||||
```
|
||||
|
||||
## Manually sending commands to the micro-controller
|
||||
|
||||
Normally, the host klippy.py process would be used to translate gcode
|
||||
commands to Klipper micro-controller commands. However, it's also
|
||||
possible to manually send these MCU commands (functions marked with
|
||||
the DECL_COMMAND() macro in the Klipper source code). To do so, run:
|
||||
|
||||
```
|
||||
~/klippy-env/bin/python ./klippy/console.py /tmp/pseudoserial
|
||||
```
|
||||
|
||||
See the "HELP" command within the tool for more information on its
|
||||
functionality.
|
||||
|
||||
Some command-line options are available. For more information run:
|
||||
`~/klippy-env/bin/python ./klippy/console.py --help`
|
||||
|
||||
## Translating gcode files to micro-controller commands
|
||||
|
||||
The Klippy host code can run in a batch mode to produce the low-level
|
||||
micro-controller commands associated with a gcode file. Inspecting
|
||||
these low-level commands is useful when trying to understand the
|
||||
actions of the low-level hardware. It can also be useful to compare
|
||||
the difference in micro-controller commands after a code change.
|
||||
|
||||
To run Klippy in this batch mode, there is a one time step necessary
|
||||
to generate the micro-controller "data dictionary". This is done by
|
||||
compiling the micro-controller code to obtain the **out/klipper.dict**
|
||||
file:
|
||||
|
||||
```
|
||||
make menuconfig
|
||||
make
|
||||
```
|
||||
|
||||
Once the above is done it is possible to run Klipper in batch mode
|
||||
(see [installation](Installation.md) for the steps necessary to build
|
||||
the python virtual environment and a printer.cfg file):
|
||||
|
||||
```
|
||||
~/klippy-env/bin/python ./klippy/klippy.py ~/printer.cfg -i test.gcode -o test.serial -v -d out/klipper.dict
|
||||
```
|
||||
|
||||
The above will produce a file **test.serial** with the binary serial
|
||||
output. This output can be translated to readable text with:
|
||||
|
||||
```
|
||||
~/klippy-env/bin/python ./klippy/parsedump.py out/klipper.dict test.serial > test.txt
|
||||
```
|
||||
|
||||
The resulting file **test.txt** contains a human readable list of
|
||||
micro-controller commands.
|
||||
|
||||
The batch mode disables certain response / request commands in order
|
||||
to function. As a result, there will be some differences between
|
||||
actual commands and the above output. The generated data is useful for
|
||||
testing and inspection; it is not useful for sending to a real
|
||||
micro-controller.
|
||||
|
||||
## Motion analysis and data logging
|
||||
|
||||
Klipper supports logging its internal motion history, which can be
|
||||
later analyzed. To use this feature, Klipper must be started with the
|
||||
[API Server](API_Server.md) enabled.
|
||||
|
||||
Data logging is enabled with the `data_logger.py` tool. For example:
|
||||
```
|
||||
~/klipper/scripts/motan/data_logger.py /tmp/klippy_uds mylog
|
||||
```
|
||||
|
||||
This command will connect to the Klipper API Server, subscribe to
|
||||
status and motion information, and log the results. Two files are
|
||||
generated - a compressed data file and an index file (eg,
|
||||
`mylog.json.gz` and `mylog.index.gz`). After starting the logging, it
|
||||
is possible to complete prints and other actions - the logging will
|
||||
continue in the background. When done logging, hit `ctrl-c` to exit
|
||||
from the `data_logger.py` tool.
|
||||
|
||||
The resulting files can be read and graphed using the `motan_graph.py`
|
||||
tool. To generate graphs on a Raspberry Pi, a one time step is
|
||||
necessary to install the "matplotlib" package:
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install python-matplotlib
|
||||
```
|
||||
However, it may be more convenient to copy the data files to a desktop
|
||||
class machine along with the Python code in the `scripts/motan/`
|
||||
directory. The motion analysis scripts should run on any machine with
|
||||
a recent version of [Python](https://python.org) and
|
||||
[Matplotlib](https://matplotlib.org/) installed.
|
||||
|
||||
Graphs can be generated with a command like the following:
|
||||
```
|
||||
~/klipper/scripts/motan/motan_graph.py mylog -o mygraph.png
|
||||
```
|
||||
|
||||
One can use the `-g` option to specify the datasets to graph (it takes
|
||||
a Python literal containing a list of lists). For example:
|
||||
```
|
||||
~/klipper/scripts/motan/motan_graph.py mylog -g '[["trapq(toolhead,velocity)"], ["trapq(toolhead,accel)"]]'
|
||||
```
|
||||
|
||||
The list of available datasets can be found using the `-l` option -
|
||||
for example:
|
||||
```
|
||||
~/klipper/scripts/motan/motan_graph.py -l
|
||||
```
|
||||
|
||||
It is also possible to specify matplotlib plot options for each
|
||||
dataset:
|
||||
```
|
||||
~/klipper/scripts/motan/motan_graph.py mylog -g '[["trapq(toolhead,velocity)?color=red&alpha=0.4"]]'
|
||||
```
|
||||
Many matplotlib options are available; some examples are "color",
|
||||
"label", "alpha", and "linestyle".
|
||||
|
||||
The `motan_graph.py` tool supports several other command-line
|
||||
options - use the `--help` option to see a list. It may also be
|
||||
convenient to view/modify the
|
||||
[motan_graph.py](../scripts/motan/motan_graph.py) script itself.
|
||||
|
||||
The raw data logs produced by the `data_logger.py` tool follow the
|
||||
format described in the [API Server](API_Server.md). It may be useful
|
||||
to inspect the data with a Unix command like the following:
|
||||
`gunzip < mylog.json.gz | tr '\03' '\n' | less`
|
||||
|
||||
## Generating load graphs
|
||||
|
||||
The Klippy log file (/tmp/klippy.log) stores statistics on bandwidth,
|
||||
micro-controller load, and host buffer load. It can be useful to graph
|
||||
these statistics after a print.
|
||||
|
||||
To generate a graph, a one time step is necessary to install the
|
||||
"matplotlib" package:
|
||||
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install python-matplotlib
|
||||
```
|
||||
|
||||
Then graphs can be produced with:
|
||||
|
||||
```
|
||||
~/klipper/scripts/graphstats.py /tmp/klippy.log -o loadgraph.png
|
||||
```
|
||||
|
||||
One can then view the resulting **loadgraph.png** file.
|
||||
|
||||
Different graphs can be produced. For more information run:
|
||||
`~/klipper/scripts/graphstats.py --help`
|
||||
|
||||
## Extracting information from the klippy.log file
|
||||
|
||||
The Klippy log file (/tmp/klippy.log) also contains debugging
|
||||
information. There is a logextract.py script that may be useful when
|
||||
analyzing a micro-controller shutdown or similar problem. It is
|
||||
typically run with something like:
|
||||
|
||||
```
|
||||
mkdir work_directory
|
||||
cd work_directory
|
||||
cp /tmp/klippy.log .
|
||||
~/klipper/scripts/logextract.py ./klippy.log
|
||||
```
|
||||
|
||||
The script will extract the printer config file and will extract MCU
|
||||
shutdown information. The information dumps from an MCU shutdown (if
|
||||
present) will be reordered by timestamp to assist in diagnosing cause
|
||||
and effect scenarios.
|
||||
|
||||
## Testing with simulavr
|
||||
|
||||
The [simulavr](http://www.nongnu.org/simulavr/) tool enables one to
|
||||
simulate an Atmel ATmega micro-controller. This section describes how
|
||||
one can run test gcode files through simulavr. It is recommended to
|
||||
run this on a desktop class machine (not a Raspberry Pi) as it does
|
||||
require significant cpu to run efficiently.
|
||||
|
||||
To use simulavr, download the simulavr package and compile with python
|
||||
support. Note that the build system may need to have some packages (such as
|
||||
swig) installed in order to build the python module.
|
||||
|
||||
```
|
||||
git clone git://git.savannah.nongnu.org/simulavr.git
|
||||
cd simulavr
|
||||
make python
|
||||
make build
|
||||
```
|
||||
Make sure a file like **./build/pysimulavr/_pysimulavr.*.so** is present
|
||||
after the above compilation:
|
||||
```
|
||||
ls ./build/pysimulavr/_pysimulavr.*.so
|
||||
```
|
||||
This commmand should report a specific file (e.g.
|
||||
**./build/pysimulavr/_pysimulavr.cpython-39-x86_64-linux-gnu.so**) and
|
||||
not an error.
|
||||
|
||||
If you are on a Debian-based system (Debian, Ubuntu, etc.) you can
|
||||
install the following packages and generate *.deb files for system-wide
|
||||
installation of simulavr:
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install g++ make cmake swig rst2pdf help2man texinfo
|
||||
make cfgclean python debian
|
||||
sudo dpkg -i build/debian/python3-simulavr*.deb
|
||||
```
|
||||
|
||||
To compile Klipper for use in simulavr, run:
|
||||
|
||||
```
|
||||
cd /path/to/klipper
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
and compile the micro-controller software for an AVR atmega644p and
|
||||
select SIMULAVR software emulation support. Then one can compile
|
||||
Klipper (run `make`) and then start the simulation with:
|
||||
|
||||
```
|
||||
PYTHONPATH=/path/to/simulavr/build/pysimulavr/ ./scripts/avrsim.py out/klipper.elf
|
||||
```
|
||||
Note that if you have installed python3-simulavr system-wide, you do
|
||||
not need to set `PYTHONPATH`, and can simply run the simulator as
|
||||
```
|
||||
./scripts/avrsim.py out/klipper.elf
|
||||
```
|
||||
|
||||
Then, with simulavr running in another window, one can run the
|
||||
following to read gcode from a file (eg, "test.gcode"), process it
|
||||
with Klippy, and send it to Klipper running in simulavr (see
|
||||
[installation](Installation.md) for the steps necessary to build the
|
||||
python virtual environment):
|
||||
|
||||
```
|
||||
~/klippy-env/bin/python ./klippy/klippy.py config/generic-simulavr.cfg -i test.gcode -v
|
||||
```
|
||||
|
||||
### Using simulavr with gtkwave
|
||||
|
||||
One useful feature of simulavr is its ability to create signal wave
|
||||
generation files with the exact timing of events. To do this, follow
|
||||
the directions above, but run avrsim.py with a command-line like the
|
||||
following:
|
||||
|
||||
```
|
||||
PYTHONPATH=/path/to/simulavr/src/python/ ./scripts/avrsim.py out/klipper.elf -t PORTA.PORT,PORTC.PORT
|
||||
```
|
||||
|
||||
The above would create a file **avrsim.vcd** with information on each
|
||||
change to the GPIOs on PORTA and PORTB. This could then be viewed
|
||||
using gtkwave with:
|
||||
|
||||
```
|
||||
gtkwave avrsim.vcd
|
||||
```
|
||||
250
docs/Delta_Calibrate.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# Delta calibration
|
||||
|
||||
This document describes Klipper's automatic calibration system for
|
||||
"delta" style printers.
|
||||
|
||||
Delta calibration involves finding the tower endstop positions, tower
|
||||
angles, delta radius, and delta arm lengths. These settings control
|
||||
printer motion on a delta printer. Each one of these parameters has a
|
||||
non-obvious and non-linear impact and it is difficult to calibrate
|
||||
them manually. In contrast, the software calibration code can provide
|
||||
excellent results with just a few minutes of time. No special probing
|
||||
hardware is necessary.
|
||||
|
||||
Ultimately, the delta calibration is dependent on the precision of the
|
||||
tower endstop switches. If one is using Trinamic stepper motor drivers
|
||||
then consider enabling [endstop phase](Endstop_Phase.md) detection to
|
||||
improve the accuracy of those switches.
|
||||
|
||||
## Automatic vs manual probing
|
||||
|
||||
Klipper supports calibrating the delta parameters via a manual probing
|
||||
method or via an automatic Z probe.
|
||||
|
||||
A number of delta printer kits come with automatic Z probes that are
|
||||
not sufficiently accurate (specifically, small differences in arm
|
||||
length can cause effector tilt which can skew an automatic probe). If
|
||||
using an automatic probe then first
|
||||
[calibrate the probe](Probe_Calibrate.md) and then check for a
|
||||
[probe location bias](Probe_Calibrate.md#location-bias-check). If the
|
||||
automatic probe has a bias of more than 25 microns (.025mm) then use
|
||||
manual probing instead. Manual probing only takes a few minutes and it
|
||||
eliminates error introduced by the probe.
|
||||
|
||||
If using a probe that is mounted on the side of the hotend (that is,
|
||||
it has an X or Y offset) then note that performing delta calibration
|
||||
will invalidate the results of probe calibration. These types of
|
||||
probes are rarely suitable for use on a delta (because minor effector
|
||||
tilt will result in a probe location bias). If using the probe anyway,
|
||||
then be sure to rerun probe calibration after any delta calibration.
|
||||
|
||||
## Basic delta calibration
|
||||
|
||||
Klipper has a DELTA_CALIBRATE command that can perform basic delta
|
||||
calibration. This command probes seven different points on the bed and
|
||||
calculates new values for the tower angles, tower endstops, and delta
|
||||
radius.
|
||||
|
||||
In order to perform this calibration the initial delta parameters (arm
|
||||
lengths, radius, and endstop positions) must be provided and they
|
||||
should have an accuracy to within a few millimeters. Most delta
|
||||
printer kits will provide these parameters - configure the printer
|
||||
with these initial defaults and then go on to run the DELTA_CALIBRATE
|
||||
command as described below. If no defaults are available then search
|
||||
online for a delta calibration guide that can provide a basic starting
|
||||
point.
|
||||
|
||||
During the delta calibration process it may be necessary for the
|
||||
printer to probe below what would otherwise be considered the plane of
|
||||
the bed. It is typical to permit this during calibration by updating
|
||||
the config so that the printer's `minimum_z_position=-5`. (Once
|
||||
calibration completes, one can remove this setting from the config.)
|
||||
|
||||
There are two ways to perform the probing - manual probing
|
||||
(`DELTA_CALIBRATE METHOD=manual`) and automatic probing
|
||||
(`DELTA_CALIBRATE`). The manual probing method will move the head near
|
||||
the bed and then wait for the user to follow the steps described at
|
||||
["the paper test"](Bed_Level.md#the-paper-test) to determine the
|
||||
actual distance between the nozzle and bed at the given location.
|
||||
|
||||
To perform the basic probe, make sure the config has a
|
||||
[delta_calibrate] section defined and then run the tool:
|
||||
```
|
||||
G28
|
||||
DELTA_CALIBRATE METHOD=manual
|
||||
```
|
||||
After probing the seven points new delta parameters will be
|
||||
calculated. Save and apply these parameters by running:
|
||||
```
|
||||
SAVE_CONFIG
|
||||
```
|
||||
|
||||
The basic calibration should provide delta parameters that are
|
||||
accurate enough for basic printing. If this is a new printer, this is
|
||||
a good time to print some basic objects and verify general
|
||||
functionality.
|
||||
|
||||
## Enhanced delta calibration
|
||||
|
||||
The basic delta calibration generally does a good job of calculating
|
||||
delta parameters such that the nozzle is the correct distance from the
|
||||
bed. However, it does not attempt to calibrate X and Y dimensional
|
||||
accuracy. It's a good idea to perform an enhanced delta calibration to
|
||||
verify dimensional accuracy.
|
||||
|
||||
This calibration procedure requires printing a test object and
|
||||
measuring parts of that test object with digital calipers.
|
||||
|
||||
Prior to running an enhanced delta calibration one must run the basic
|
||||
delta calibration (via the DELTA_CALIBRATE command) and save the
|
||||
results (via the SAVE_CONFIG command). Make sure there hasn't been any
|
||||
notable change to the printer configuration nor hardware since last
|
||||
performing a basic delta calibration (if unsure, rerun the
|
||||
[basic delta calibration](#basic-delta-calibration), including
|
||||
SAVE_CONFIG, just prior to printing the test object described below.)
|
||||
|
||||
Use a slicer to generate G-Code from the
|
||||
[docs/prints/calibrate_size.stl](prints/calibrate_size.stl) file.
|
||||
Slice the object using a slow speed (eg, 40mm/s). If possible, use a
|
||||
stiff plastic (such as PLA) for the object. The object has a diameter
|
||||
of 140mm. If this is too large for the printer then one can scale it
|
||||
down (but be sure to uniformly scale both the X and Y axes). If the
|
||||
printer supports significantly larger prints then this object can also
|
||||
be increased in size. A larger size can improve the measurement
|
||||
accuracy, but good print adhesion is more important than a larger
|
||||
print size.
|
||||
|
||||
Print the test object and wait for it to fully cool. The commands
|
||||
described below must be run with the same printer settings used to
|
||||
print the calibration object (don't run DELTA_CALIBRATE between
|
||||
printing and measuring, or do something that would otherwise change
|
||||
the printer configuration).
|
||||
|
||||
If possible, perform the measurements described below while the object
|
||||
is still attached to the print bed, but don't worry if the part
|
||||
detaches from the bed - just try to avoid bending the object when
|
||||
performing the measurements.
|
||||
|
||||
Start by measuring the distance between the center pillar and the
|
||||
pillar next to the "A" label (which should also be pointing towards
|
||||
the "A" tower).
|
||||
|
||||

|
||||
|
||||
Then go counterclockwise and measure the distances between the center
|
||||
pillar and the other pillars (distance from center to pillar across
|
||||
from C label, distance from center to pillar with B label, etc.).
|
||||
|
||||

|
||||
|
||||
Enter these parameters into Klipper with a comma separated list of
|
||||
floating point numbers:
|
||||
```
|
||||
DELTA_ANALYZE CENTER_DISTS=<a_dist>,<far_c_dist>,<b_dist>,<far_a_dist>,<c_dist>,<far_b_dist>
|
||||
```
|
||||
Provide the values without spaces between them.
|
||||
|
||||
Then measure the distance between the A pillar and the pillar across
|
||||
from the C label.
|
||||
|
||||

|
||||
|
||||
Then go counterclockwise and measure the distance between the pillar
|
||||
across from C to the B pillar, the distance between the B pillar and
|
||||
the pillar across from A, and so on.
|
||||
|
||||

|
||||
|
||||
Enter these parameters into Klipper:
|
||||
```
|
||||
DELTA_ANALYZE OUTER_DISTS=<a_to_far_c>,<far_c_to_b>,<b_to_far_a>,<far_a_to_c>,<c_to_far_b>,<far_b_to_a>
|
||||
```
|
||||
|
||||
At this point it is okay to remove the object from the bed. The final
|
||||
measurements are of the pillars themselves. Measure the size of the
|
||||
center pillar along the A spoke, then the B spoke, and then the C
|
||||
spoke.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Enter them into Klipper:
|
||||
```
|
||||
DELTA_ANALYZE CENTER_PILLAR_WIDTHS=<a>,<b>,<c>
|
||||
```
|
||||
|
||||
The final measurements are of the outer pillars. Start by measuring
|
||||
the distance of the A pillar along the line from A to the pillar
|
||||
across from C.
|
||||
|
||||

|
||||
|
||||
Then go counterclockwise and measure the remaining outer pillars
|
||||
(pillar across from C along the line to B, B pillar along the line to
|
||||
pillar across from A, etc.).
|
||||
|
||||

|
||||
|
||||
And enter them into Klipper:
|
||||
```
|
||||
DELTA_ANALYZE OUTER_PILLAR_WIDTHS=<a>,<far_c>,<b>,<far_a>,<c>,<far_b>
|
||||
```
|
||||
|
||||
If the object was scaled to a smaller or larger size then provide the
|
||||
scale factor that was used when slicing the object:
|
||||
```
|
||||
DELTA_ANALYZE SCALE=1.0
|
||||
```
|
||||
(A scale value of 2.0 would mean the object is twice its original
|
||||
size, 0.5 would be half its original size.)
|
||||
|
||||
Finally, perform the enhanced delta calibration by running:
|
||||
```
|
||||
DELTA_ANALYZE CALIBRATE=extended
|
||||
```
|
||||
This command can take several minutes to complete. After completion it
|
||||
will calculate updated delta parameters (delta radius, tower angles,
|
||||
endstop positions, and arm lengths). Use the SAVE_CONFIG command to
|
||||
save and apply the settings:
|
||||
```
|
||||
SAVE_CONFIG
|
||||
```
|
||||
|
||||
The SAVE_CONFIG command will save both the updated delta parameters
|
||||
and information from the distance measurements. Future DELTA_CALIBRATE
|
||||
commands will also utilize this distance information. Do not attempt
|
||||
to reenter the raw distance measurements after running SAVE_CONFIG, as
|
||||
this command changes the printer configuration and the raw
|
||||
measurements no longer apply.
|
||||
|
||||
### Additional notes
|
||||
|
||||
* If the delta printer has good dimensional accuracy then the distance
|
||||
between any two pillars should be around 74mm and the width of every
|
||||
pillar should be around 9mm. (Specifically, the goal is for the
|
||||
distance between any two pillars minus the width of one of the
|
||||
pillars to be exactly 65mm.) Should there be a dimensional
|
||||
inaccuracy in the part then the DELTA_ANALYZE routine will calculate
|
||||
new delta parameters using both the distance measurements and the
|
||||
previous height measurements from the last DELTA_CALIBRATE command.
|
||||
|
||||
* DELTA_ANALYZE may produce delta parameters that are surprising. For
|
||||
example, it may suggest arm lengths that do not match the printer's
|
||||
actual arm lengths. Despite this, testing has shown that
|
||||
DELTA_ANALYZE often produces superior results. It is believed that
|
||||
the calculated delta parameters are able to account for slight
|
||||
errors elsewhere in the hardware. For example, small differences in
|
||||
arm length may result in a tilt to the effector and some of that
|
||||
tilt may be accounted for by adjusting the arm length parameters.
|
||||
|
||||
## Using Bed Mesh on a Delta
|
||||
|
||||
It is possible to use [bed mesh](Bed_Mesh.md) on a delta. However, it
|
||||
is important to obtain good delta calibration prior to enabling a bed
|
||||
mesh. Running bed mesh with poor delta calibration will result in
|
||||
confusing and poor results.
|
||||
|
||||
Note that performing delta calibration will invalidate any previously
|
||||
obtained bed mesh. After performing a new delta calibration be sure to
|
||||
rerun BED_MESH_CALIBRATE.
|
||||
126
docs/Endstop_Phase.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Endstop phase
|
||||
|
||||
This document describes Klipper's stepper phase adjusted endstop
|
||||
system. This functionality can improve the accuracy of traditional
|
||||
endstop switches. It is most useful when using a Trinamic stepper
|
||||
motor driver that has run-time configuration.
|
||||
|
||||
A typical endstop switch has an accuracy of around 100 microns. (Each
|
||||
time an axis is homed the switch may trigger slightly earlier or
|
||||
slightly later.) Although this is a relatively small error, it can
|
||||
result in unwanted artifacts. In particular, this positional deviation
|
||||
may be noticeable when printing the first layer of an object. In
|
||||
contrast, typical stepper motors can obtain significantly higher
|
||||
precision.
|
||||
|
||||
The stepper phase adjusted endstop mechanism can use the precision of
|
||||
the stepper motors to improve the precision of the endstop switches.
|
||||
A stepper motor moves by cycling through a series of phases until in
|
||||
completes four "full steps". So, a stepper motor using 16 micro-steps
|
||||
would have 64 phases and when moving in a positive direction it would
|
||||
cycle through phases: 0, 1, 2, ... 61, 62, 63, 0, 1, 2, etc.
|
||||
Crucially, when the stepper motor is at a particular position on a
|
||||
linear rail it should always be at the same stepper phase. Thus, when
|
||||
a carriage triggers the endstop switch the stepper controlling that
|
||||
carriage should always be at the same stepper motor phase. Klipper's
|
||||
endstop phase system combines the stepper phase with the endstop
|
||||
trigger to improve the accuracy of the endstop.
|
||||
|
||||
In order to use this functionality it is necessary to be able to
|
||||
identify the phase of the stepper motor. If one is using Trinamic
|
||||
TMC2130, TMC2208, TMC2224 or TMC2660 drivers in run-time configuration
|
||||
mode (ie, not stand-alone mode) then Klipper can query the stepper
|
||||
phase from the driver. (It is also possible to use this system on
|
||||
traditional stepper drivers if one can reliably reset the stepper
|
||||
drivers - see below for details.)
|
||||
|
||||
## Calibrating endstop phases
|
||||
|
||||
If using Trinamic stepper motor drivers with run-time configuration
|
||||
then one can calibrate the endstop phases using the
|
||||
ENDSTOP_PHASE_CALIBRATE command. Start by adding the following to the
|
||||
config file:
|
||||
```
|
||||
[endstop_phase]
|
||||
```
|
||||
|
||||
Then RESTART the printer and run a `G28` command followed by an
|
||||
`ENDSTOP_PHASE_CALIBRATE` command. Then move the toolhead to a new
|
||||
location and run `G28` again. Try moving the toolhead to several
|
||||
different locations and rerun `G28` from each position. Run at least
|
||||
five `G28` commands.
|
||||
|
||||
After performing the above, the `ENDSTOP_PHASE_CALIBRATE` command will
|
||||
often report the same (or nearly the same) phase for the stepper. This
|
||||
phase can be saved in the config file so that all future G28 commands
|
||||
use that phase. (So, in future homing operations, Klipper will obtain
|
||||
the same position even if the endstop triggers a little earlier or a
|
||||
little later.)
|
||||
|
||||
To save the endstop phase for a particular stepper motor, run
|
||||
something like the following:
|
||||
```
|
||||
ENDSTOP_PHASE_CALIBRATE STEPPER=stepper_z
|
||||
```
|
||||
|
||||
Run the above for all the steppers one wishes to save. Typically, one
|
||||
would use this on stepper_z for cartesian and corexy printers, and for
|
||||
stepper_a, stepper_b, and stepper_c on delta printers. Finally, run
|
||||
the following to update the configuration file with the data:
|
||||
```
|
||||
SAVE_CONFIG
|
||||
```
|
||||
|
||||
### Additional notes
|
||||
|
||||
* This feature is most useful on delta printers and on the Z endstop
|
||||
of cartesian/corexy printers. It is possible to use this feature on
|
||||
the XY endstops of cartesian printers, but that isn't particularly
|
||||
useful as a minor error in X/Y endstop position is unlikely to
|
||||
impact print quality. It is not valid to use this feature on the XY
|
||||
endstops of corexy printers (as the XY position is not determined by
|
||||
a single stepper on corexy kinematics). It is not valid to use this
|
||||
feature on a printer using a "probe:z_virtual_endstop" Z endstop (as
|
||||
the stepper phase is only stable if the endstop is at a static
|
||||
location on a rail).
|
||||
|
||||
* After calibrating the endstop phase, if the endstop is later moved
|
||||
or adjusted then it will be necessary to recalibrate the endstop.
|
||||
Remove the calibration data from the config file and rerun the steps
|
||||
above.
|
||||
|
||||
* In order to use this system the endstop must be accurate enough to
|
||||
identify the stepper position within two "full steps". So, for
|
||||
example, if a stepper is using 16 micro-steps with a step distance
|
||||
of 0.005mm then the endstop must have an accuracy of at least
|
||||
0.160mm. If one gets "Endstop stepper_z incorrect phase" type error
|
||||
messages than in may be due to an endstop that is not sufficiently
|
||||
accurate. If recalibration does not help then disable endstop phase
|
||||
adjustments by removing them from the config file.
|
||||
|
||||
* If one is using a traditional stepper controlled Z axis (as on a
|
||||
cartesian or corexy printer) along with traditional bed leveling
|
||||
screws then it is also possible to use this system to arrange for
|
||||
each print layer to be performed on a "full step" boundary. To
|
||||
enable this feature be sure the G-Code slicer is configured with a
|
||||
layer height that is a multiple of a "full step", manually enable
|
||||
the endstop_align_zero option in the endstop_phase config section
|
||||
(see [config reference](Config_Reference.md#endstop_phase) for
|
||||
further details), and then re-level the bed screws.
|
||||
|
||||
* It is possible to use this system with traditional (non-Trinamic)
|
||||
stepper motor drivers. However, doing this requires making sure that
|
||||
the stepper motor drivers are reset every time the micro-controller
|
||||
is reset. (If the two are always reset together then Klipper can
|
||||
determine the stepper phase by tracking the total number of steps it
|
||||
has commanded the stepper to move.) Currently, the only way to do
|
||||
this reliably is if both the micro-controller and stepper motor
|
||||
drivers are powered solely from USB and that USB power is provided
|
||||
from a host running on a Raspberry Pi. In this situation one can
|
||||
specify an mcu config with "restart_method: rpi_usb" - that option
|
||||
will arrange for the micro-controller to always be reset via a USB
|
||||
power reset, which would arrange for both the micro-controller and
|
||||
stepper motor drivers to be reset together. If using this mechanism,
|
||||
one would then need to manually configure the "trigger_phase" config
|
||||
sections (see [config reference](Config_Reference.md#endstop_phase)
|
||||
for the details).
|
||||
110
docs/Example_Configs.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Example configurations
|
||||
|
||||
This document contains guidelines for contributing an example Klipper
|
||||
configuration to the Klipper github repository (located in the
|
||||
[config directory](../config/)).
|
||||
|
||||
Note that the
|
||||
[Klipper Community Discourse server](https://community.klipper3d.org)
|
||||
is also a useful resource for finding and sharing config files.
|
||||
|
||||
## Guidelines
|
||||
|
||||
1. Select the appropriate config filename prefix:
|
||||
1. The `printer` prefix is used for stock printers sold by a
|
||||
mainstream manufacturer.
|
||||
2. The `generic` prefix is used for a 3d printer board that may be
|
||||
used in many different types of printers.
|
||||
3. The `kit` prefix is for 3d printers that are assembled according
|
||||
to a widely used specification. These "kit" printers are
|
||||
generally distinct from normal "printers" in that they are not
|
||||
sold by a manufacturer.
|
||||
4. The `sample` prefix is used for config "snippets" that one may
|
||||
copy-and-paste into the main config file.
|
||||
5. The `example` prefix is used to describe printer kinematics.
|
||||
This type of config is typically only added along with code for
|
||||
a new type of printer kinematics.
|
||||
2. All configuration files must end in a `.cfg` suffix. The `printer`
|
||||
config files must end in a year followed by `.cfg` (eg,
|
||||
`-2019.cfg`). In this case, the year is an approximate year the
|
||||
given printer was sold.
|
||||
3. Do not use spaces or special characters in the config filename. The
|
||||
filename should contain only characters `A-Z`, `a-z`, `0-9`, `-`,
|
||||
and `.`.
|
||||
4. Klipper must be able to start `printer`, `generic`, and `kit`
|
||||
example config file without error. These config files should be
|
||||
added to the
|
||||
[test/klippy/printers.test](../test/klippy/printers.test)
|
||||
regression test case. Add new config files to that test case in the
|
||||
appropriate section and in alphabetical order within that section.
|
||||
5. The example configuration should be for the "stock" configuration
|
||||
of the printer. (There are too many "customized" configurations to
|
||||
track in the main Klipper repository.) Similarly, we only add
|
||||
example config files for printers, kits, and boards that have
|
||||
mainstream popularity (eg, there should be at least a 100 of them
|
||||
in active use). Consider using the
|
||||
[Klipper Community Discourse server](https://community.klipper3d.org)
|
||||
for other configs.
|
||||
6. Only specify those devices present on the given printer or board.
|
||||
Do not specify settings specific to your particular setup.
|
||||
1. For `generic` config files, only those devices on the mainboard
|
||||
should be described. For example, it would not make sense to add
|
||||
a display config section to a "generic" config as there is no
|
||||
way to know if the board will be attached to that type of
|
||||
display. If the board has a specific hardware port to facilitate
|
||||
an optional peripheral (eg, a bltouch port) then one can add a
|
||||
"commented out" config section for the given device.
|
||||
2. Do not specify `pressure_advance` in an example config, as that
|
||||
value is specific to the filament, not the printer hardware.
|
||||
Similarly, do not specify `max_extrude_only_velocity` nor
|
||||
`max_extrude_only_accel` settings.
|
||||
3. Do not specify a config section containing a host path or host
|
||||
hardware. For example, do not specify `[virtual_sdcard]` nor
|
||||
`[temperature_host]` config sections.
|
||||
4. Only define macros that utilize functionality specific to the
|
||||
given printer or to define g-codes that are commonly emitted by
|
||||
slicers configured for the given printer.
|
||||
7. Where possible, it is best to use the same wording, phrasing,
|
||||
indentation, and section ordering as the existing config files.
|
||||
1. The top of each config file should list the type of
|
||||
micro-controller the user should select during "make
|
||||
menuconfig". It should also have a reference to
|
||||
"docs/Config_Reference.md".
|
||||
2. Do not copy the field documentation into the example config
|
||||
files. (Doing so creates a maintenance burden as an update to
|
||||
the documentation would then require changing it in many
|
||||
places.)
|
||||
3. Example config files should not contain a "SAVE_CONFIG" section.
|
||||
If necessary, copy the relevant fields from the SAVE_CONFIG
|
||||
section to the appropriate section in the main config area.
|
||||
4. Use `field: value` syntax instead of `field=value`.
|
||||
5. When adding an extruder `rotation_distance` it is preferable to
|
||||
specify a `gear_ratio` if the extruder has a gearing mechanism.
|
||||
We expect the rotation_distance in the example configs to
|
||||
correlate with the circumference of the hobbed gear in the
|
||||
extruder - it is normally in the range of 20 to 35mm. When
|
||||
specifying a `gear_ratio` it is preferable to specify the actual
|
||||
gears on the mechanism (eg, prefer `gear_ratio: 80:20` over
|
||||
`gear_ratio: 4:1`). See the
|
||||
[rotation distance document](Rotation_Distance.md#using-a-gear_ratio)
|
||||
for more information.
|
||||
6. Avoid defining field values that are set to their default
|
||||
value. For example, one should not specify `min_extrude_temp:
|
||||
170` as that is already the default value.
|
||||
7. Where possible, lines should not exceed 80 columns.
|
||||
8. Avoid adding attribution or revision messages to the config
|
||||
files. (For example, avoid adding lines like "this file was
|
||||
created by ...".) Place attribution and change history in the
|
||||
git commit message.
|
||||
8. Do not use any deprecated features in the example config file.
|
||||
9. Do not disable a default safety system in an example config file.
|
||||
For example, a config should not specify a custom
|
||||
`max_extrude_cross_section`. Do not enable debugging features. For
|
||||
example there should not be a `force_move` config section.
|
||||
10. All known boards that Klipper supports can use the default serial
|
||||
baud rate of 250000. Do not recommend a different baud rate in an
|
||||
example config file.
|
||||
|
||||
Example config files are submitted by creating a github "pull
|
||||
request". Please also follow the directions in the
|
||||
[contributing document](CONTRIBUTING.md).
|
||||
99
docs/Exclude_Object.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Exclude Objects
|
||||
|
||||
The `[exclude_object]` module allows Klipper to exclude objects while a print is
|
||||
in progress. To enable this feature include an [exclude_object config
|
||||
section](Config_Reference.md#exclude_object) (also see the [command
|
||||
reference](G-Codes.md#exclude-object) and
|
||||
[sample-macros.cfg](../config/sample-macros.cfg) file for a
|
||||
Marlin/RepRapFirmware compatible M486 G-Code macro.)
|
||||
|
||||
Unlike other 3D printer firmware options, a printer running Klipper utilizes a
|
||||
suite of components and users have many options to choose from. Therefore, in
|
||||
order to provide a a consistent user experience, the `[exclude_object]` module
|
||||
will establish a contract or API of sorts. The contract covers the contents of
|
||||
the gcode file, how the internal state of the module is controlled, and how that
|
||||
state is provided to clients.
|
||||
|
||||
## Workflow Overview
|
||||
A typical workflow for printing a file might look like this:
|
||||
1. Slicing is completed and the file is uploaded for printing. During the
|
||||
upload, the file is processed and `[exclude_object]` markers are added to
|
||||
the file. Alternately, slicers may be configured to prepare object exclusion
|
||||
markers natively, or in it's own pre-processing step.
|
||||
2. When printing starts, Klipper will reset the `[exclude_object]`
|
||||
[status](Status_Reference.md#exclude_object).
|
||||
3. When Klipper processes the `EXCLUDE_OBJECT_DEFINE` block, it will update the
|
||||
status with the known objects and pass it on to clients.
|
||||
4. The client may use that information to present a UI to the user so that
|
||||
progress can be tracked. Klipper will update the status to include the
|
||||
currently printing object which the client can use for display purposes.
|
||||
5. If the user requests that an object be cancelled, the client will issue an
|
||||
`EXCLUDE_OBJECT NAME=<name>` command to Klipper.
|
||||
6. When Klipper process the command, it will add the object to the list of
|
||||
excluded objects and update the status for the client.
|
||||
7. The client will receive the updated status from Klipper and can use that
|
||||
information to reflect the object's status in the UI.
|
||||
8. When printing finishes, the `[exclude_object]` status will continue to be
|
||||
available until another action resets it.
|
||||
|
||||
## The GCode File
|
||||
The specialized gcode processing needed to support excluding objects does not
|
||||
fit into Klipper's core design goals. Therefore, this module requires that the
|
||||
file is processed before being sent to Klipper for printing. Using a
|
||||
post-process script in the slicer or having middleware process the file on
|
||||
upload are two possibilities for preparing the file for Klipper. A reference
|
||||
post-processing script is available both as an executable and a python library,
|
||||
see
|
||||
[cancelobject-preprocessor](https://github.com/kageurufu/cancelobject-preprocessor).
|
||||
|
||||
### Object Definitions
|
||||
|
||||
The `EXCLUDE_OBJECT_DEFINE` command is used to provide a summary of each object
|
||||
in the gcode file to be printed. Provides a summary of an object in the file.
|
||||
Objects don't need to be defined in order to be referenced by other commands.
|
||||
The primary purpose of this command is to provide information to the UI without
|
||||
needing to parse the entire gcode file.
|
||||
|
||||
Object definitions are named, to allow users to easily select an object to be
|
||||
excluded, and additional metadata may be provided to allow for graphical
|
||||
cancellation displays. Currently defined metadata includes a `CENTER` X,Y
|
||||
coordinate, and a `POLYGON` list of X,Y points representing a minimal outline of
|
||||
the object. This could be a simple bounding box, or a complicated hull for
|
||||
showing more detailed visualizations of the printed objects. Especially when
|
||||
gcode files include multiple parts with overlapping bounding regions, center
|
||||
points become hard to visually distinguish. `POLYGONS` must be a json-compatible
|
||||
array of point `[X,Y]` tuples without whitespace. Additional parameters will be
|
||||
saved as strings in the object definition and provided in status updates.
|
||||
|
||||
`EXCLUDE_OBJECT_DEFINE NAME=calibration_pyramid CENTER=50,50
|
||||
POLYGON=[[40,40],[50,60],[60,40]]`
|
||||
|
||||
All available G-Code commands are documented in the [G-Code
|
||||
Reference](./G-Codes.md#excludeobject)
|
||||
|
||||
## Status Information
|
||||
The state of this module is provided to clients by the [exclude_object
|
||||
status](Status_Reference.md#exclude_object).
|
||||
|
||||
The status is reset when:
|
||||
- The Klipper firmware is restarted.
|
||||
- There is a reset of the `[virtual_sdcard]`. Notably, this is reset by Klipper
|
||||
at the start of a print.
|
||||
- When an `EXCLUDE_OBJECT_DEFINE RESET=1` command is issued.
|
||||
|
||||
The list of defined objects is represented in the `exclude_object.objects`
|
||||
status field. In a well defined gcode file, this will be done with
|
||||
`EXCLUDE_OBJECT_DEFINE` commands at the beginning of the file. This will
|
||||
provide clients with object names and coordinates so the UI can provide a
|
||||
graphical representation of the objects if desired.
|
||||
|
||||
As the print progresses, the `exclude_object.current_object` status field will
|
||||
be updated as Klipper processes `EXCLUDE_OBJECT_START` and `EXCLUDE_OBJECT_END`
|
||||
commands. The `current_object` field will be set even if the object has been
|
||||
excluded. Undefined objects marked with a `EXCLUDE_OBJECT_START` will be added
|
||||
to the known objects to assist in UI hinting, without any additional metadata.
|
||||
|
||||
As `EXCLUDE_OBJECT` commands are issued, the list of excluded objects is
|
||||
provided in the `exclude_object.excluded_objects` array. Since Klipper looks
|
||||
ahead to process upcoming gcode, there may be a delay between when the command
|
||||
is issued and when the status is updated.
|
||||
492
docs/FAQ.md
Normal file
@@ -0,0 +1,492 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
## How can I donate to the project?
|
||||
|
||||
Thank you for your support. See the [Sponsors page](Sponsors.md) for
|
||||
information.
|
||||
|
||||
## How do I calculate the rotation_distance config parameter?
|
||||
|
||||
See the [rotation distance document](Rotation_Distance.md).
|
||||
|
||||
## Where's my serial port?
|
||||
|
||||
The general way to find a USB serial port is to run `ls
|
||||
/dev/serial/by-id/*` from an ssh terminal on the host machine. It will
|
||||
likely produce output similar to the following:
|
||||
```
|
||||
/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
```
|
||||
|
||||
The name found in the above command is stable and it is possible to
|
||||
use it in the config file and while flashing the micro-controller
|
||||
code. For example, a flash command might look similar to:
|
||||
```
|
||||
sudo service klipper stop
|
||||
make flash FLASH_DEVICE=/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
sudo service klipper start
|
||||
```
|
||||
and the updated config might look like:
|
||||
```
|
||||
[mcu]
|
||||
serial: /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
```
|
||||
|
||||
Be sure to copy-and-paste the name from the "ls" command that you ran
|
||||
above as the name will be different for each printer.
|
||||
|
||||
If you are using multiple micro-controllers and they do not have
|
||||
unique ids (common on boards with a CH340 USB chip) then follow the
|
||||
directions above using the command `ls /dev/serial/by-path/*` instead.
|
||||
|
||||
## When the micro-controller restarts the device changes to /dev/ttyUSB1
|
||||
|
||||
Follow the directions in the
|
||||
"[Where's my serial port?](#wheres-my-serial-port)" section to prevent
|
||||
this from occurring.
|
||||
|
||||
## The "make flash" command doesn't work
|
||||
|
||||
The code attempts to flash the device using the most common method for
|
||||
each platform. Unfortunately, there is a lot of variance in flashing
|
||||
methods, so the "make flash" command may not work on all boards.
|
||||
|
||||
If you're having an intermittent failure or you do have a standard
|
||||
setup, then double check that Klipper isn't running when flashing
|
||||
(sudo service klipper stop), make sure OctoPrint isn't trying to
|
||||
connect directly to the device (open the Connection tab in the web
|
||||
page and click Disconnect if the Serial Port is set to the device),
|
||||
and make sure FLASH_DEVICE is set correctly for your board (see the
|
||||
[question above](#wheres-my-serial-port)).
|
||||
|
||||
However, if "make flash" just doesn't work for your board, then you
|
||||
will need to manually flash. See if there is a config file in the
|
||||
[config directory](../config) with specific instructions for flashing
|
||||
the device. Also, check the board manufacturer's documentation to see
|
||||
if it describes how to flash the device. Finally, it may be possible
|
||||
to manually flash the device using tools such as "avrdude" or
|
||||
"bossac" - see the [bootloader document](Bootloaders.md) for
|
||||
additional information.
|
||||
|
||||
## How do I change the serial baud rate?
|
||||
|
||||
The recommended baud rate for Klipper is 250000. This baud rate works
|
||||
well on all micro-controller boards that Klipper supports. If you've
|
||||
found an online guide recommending a different baud rate, then ignore
|
||||
that part of the guide and continue with the default value of 250000.
|
||||
|
||||
If you want to change the baud rate anyway, then the new rate will
|
||||
need to be configured in the micro-controller (during **make
|
||||
menuconfig**) and that updated code will need to be compiled and
|
||||
flashed to the micro-controller. The Klipper printer.cfg file will
|
||||
also need to be updated to match that baud rate (see the
|
||||
[config reference](Config_Reference.md#mcu) for details). For
|
||||
example:
|
||||
```
|
||||
[mcu]
|
||||
baud: 250000
|
||||
```
|
||||
|
||||
The baud rate shown on the OctoPrint web page has no impact on the
|
||||
internal Klipper micro-controller baud rate. Always set the OctoPrint
|
||||
baud rate to 250000 when using Klipper.
|
||||
|
||||
The Klipper micro-controller baud rate is not related to the baud rate
|
||||
of the micro-controller's bootloader. See the
|
||||
[bootloader document](Bootloaders.md) for additional information on
|
||||
bootloaders.
|
||||
|
||||
## Can I run Klipper on something other than a Raspberry Pi 3?
|
||||
|
||||
The recommended hardware is a Raspberry Pi 2, Raspberry Pi 3, or
|
||||
Raspberry Pi 4.
|
||||
|
||||
Klipper will run on a Raspberry Pi 1 and on the Raspberry Pi Zero, but
|
||||
these boards don't have enough processing power to run OctoPrint
|
||||
well. It is common for print stalls to occur on these slower machines
|
||||
when printing directly from OctoPrint. (The printer may move faster
|
||||
than OctoPrint can send movement commands.) If you wish to run on one
|
||||
one of these slower boards anyway, consider using the "virtual_sdcard"
|
||||
feature when printing (see
|
||||
[config reference](Config_Reference.md#virtual_sdcard) for details).
|
||||
|
||||
For running on the Beaglebone, see the
|
||||
[Beaglebone specific installation instructions](Beaglebone.md).
|
||||
|
||||
Klipper has been run on other machines. The Klipper host software only
|
||||
requires Python running on a Linux (or similar) computer. However, if
|
||||
you wish to run it on a different machine you will need Linux admin
|
||||
knowledge to install the system prerequisites for that particular
|
||||
machine. See the [install-octopi.sh](../scripts/install-octopi.sh)
|
||||
script for further information on the necessary Linux admin steps.
|
||||
|
||||
If you are looking to run the Klipper host software on a low-end chip,
|
||||
then be aware that, at a minimum, a machine with "double precision
|
||||
floating point" hardware is required.
|
||||
|
||||
If you are looking to run the Klipper host software on a shared
|
||||
general-purpose desktop or server class machine, then note that
|
||||
Klipper has some real-time scheduling requirements. If, during a
|
||||
print, the host computer also performs an intensive general-purpose
|
||||
computing task (such as defragmenting a hard drive, 3d rendering,
|
||||
heavy swapping, etc.), then it may cause Klipper to report print
|
||||
errors.
|
||||
|
||||
Note: If you are not using an OctoPi image, be aware that several
|
||||
Linux distributions enable a "ModemManager" (or similar) package that
|
||||
can disrupt serial communication. (Which can cause Klipper to report
|
||||
seemingly random "Lost communication with MCU" errors.) If you install
|
||||
Klipper on one of these distributions you may need to disable that
|
||||
package.
|
||||
|
||||
## Can I run multiple instances of Klipper on the same host machine?
|
||||
|
||||
It is possible to run multiple instances of the Klipper host software,
|
||||
but doing so requires Linux admin knowledge. The Klipper installation
|
||||
scripts ultimately cause the following Unix command to be run:
|
||||
```
|
||||
~/klippy-env/bin/python ~/klipper/klippy/klippy.py ~/printer.cfg -l /tmp/klippy.log
|
||||
```
|
||||
One can run multiple instances of the above command as long as each
|
||||
instance has its own printer config file, its own log file, and its
|
||||
own pseudo-tty. For example:
|
||||
```
|
||||
~/klippy-env/bin/python ~/klipper/klippy/klippy.py ~/printer2.cfg -l /tmp/klippy2.log -I /tmp/printer2
|
||||
```
|
||||
|
||||
If you choose to do this, you will need to implement the necessary
|
||||
start, stop, and installation scripts (if any). The
|
||||
[install-octopi.sh](../scripts/install-octopi.sh) script and the
|
||||
[klipper-start.sh](../scripts/klipper-start.sh) script may be useful
|
||||
as examples.
|
||||
|
||||
## Do I have to use OctoPrint?
|
||||
|
||||
The Klipper software is not dependent on OctoPrint. It is possible to
|
||||
use alternative software to send commands to Klipper, but doing so
|
||||
requires Linux admin knowledge.
|
||||
|
||||
Klipper creates a "virtual serial port" via the "/tmp/printer" file,
|
||||
and it emulates a classic 3d-printer serial interface via that file.
|
||||
In general, alternative software may work with Klipper as long as it
|
||||
can be configured to use "/tmp/printer" for the printer serial port.
|
||||
|
||||
## Why can't I move the stepper before homing the printer?
|
||||
|
||||
The code does this to reduce the chance of accidentally commanding the
|
||||
head into the bed or a wall. Once the printer is homed the software
|
||||
attempts to verify each move is within the position_min/max defined in
|
||||
the config file. If the motors are disabled (via an M84 or M18
|
||||
command) then the motors will need to be homed again prior to
|
||||
movement.
|
||||
|
||||
If you want to move the head after canceling a print via OctoPrint,
|
||||
consider changing the OctoPrint cancel sequence to do that for
|
||||
you. It's configured in OctoPrint via a web browser under:
|
||||
Settings->GCODE Scripts
|
||||
|
||||
If you want to move the head after a print finishes, consider adding
|
||||
the desired movement to the "custom g-code" section of your slicer.
|
||||
|
||||
If the printer requires some additional movement as part of the homing
|
||||
process itself (or fundamentally does not have a homing process) then
|
||||
consider using a safe_z_home or homing_override section in the config
|
||||
file. If you need to move a stepper for diagnostic or debugging
|
||||
purposes then consider adding a force_move section to the config
|
||||
file. See [config reference](Config_Reference.md#customized_homing)
|
||||
for further details on these options.
|
||||
|
||||
## Why is the Z position_endstop set to 0.5 in the default configs?
|
||||
|
||||
For cartesian style printers the Z position_endstop specifies how far
|
||||
the nozzle is from the bed when the endstop triggers. If possible, it
|
||||
is recommended to use a Z-max endstop and home away from the bed (as
|
||||
this reduces the potential for bed collisions). However, if one must
|
||||
home towards the bed then it is recommended to position the endstop so
|
||||
it triggers when the nozzle is still a small distance away from the
|
||||
bed. This way, when homing the axis, it will stop before the nozzle
|
||||
touches the bed. See the [bed level document](Bed_Level.md) for more
|
||||
information.
|
||||
|
||||
## I converted my config from Marlin and the X/Y axes work fine, but I just get a screeching noise when homing the Z axis
|
||||
|
||||
Short answer: First, make sure you have verified the stepper
|
||||
configuration as described in the
|
||||
[config check document](Config_checks.md). If the problem persists,
|
||||
try reducing the max_z_velocity setting in the printer config.
|
||||
|
||||
Long answer: In practice Marlin can typically only step at a rate of
|
||||
around 10000 steps per second. If it is requested to move at a speed
|
||||
that would require a higher step rate then Marlin will generally just
|
||||
step as fast as it can. Klipper is able to achieve much higher step
|
||||
rates, but the stepper motor may not have sufficient torque to move at
|
||||
a higher speed. So, for a Z axis with a high gearing ratio or high
|
||||
microsteps setting the actual obtainable max_z_velocity may be smaller
|
||||
than what is configured in Marlin.
|
||||
|
||||
## My TMC motor driver turns off in the middle of a print
|
||||
|
||||
If using the TMC2208 (or TMC2224) driver in "standalone mode" then
|
||||
make sure to use the
|
||||
[latest version of Klipper](#how-do-i-upgrade-to-the-latest-software). A
|
||||
workaround for a TMC2208 "stealthchop" driver problem was added to
|
||||
Klipper in mid-March of 2020.
|
||||
|
||||
## I keep getting random "Lost communication with MCU" errors
|
||||
|
||||
This is commonly caused by hardware errors on the USB connection
|
||||
between the host machine and the micro-controller. Things to look for:
|
||||
- Use a good quality USB cable between the host machine and
|
||||
micro-controller. Make sure the plugs are secure.
|
||||
- If using a Raspberry Pi, use a
|
||||
[good quality power supply](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#power-supply)
|
||||
for the Raspberry Pi and use a
|
||||
[good quality USB cable](https://forums.raspberrypi.com/viewtopic.php?p=589877#p589877)
|
||||
to connect that power supply to the Pi. If you get "under voltage"
|
||||
warnings from OctoPrint, this is related to the power supply and it
|
||||
must be fixed.
|
||||
- Make sure the printer's power supply is not being overloaded. (Power
|
||||
fluctuations to the micro-controller's USB chip may result in resets
|
||||
of that chip.)
|
||||
- Verify stepper, heater, and other printer wires are not crimped or
|
||||
frayed. (Printer movement may place stress on a faulty wire causing
|
||||
it to lose contact, briefly short, or generate excessive noise.)
|
||||
- There have been reports of high USB noise when both the printer's
|
||||
power supply and the host's 5V power supply are mixed. (If you find
|
||||
that the micro-controller powers on when either the printer's power
|
||||
supply is on or the USB cable is plugged in, then it indicates the
|
||||
5V power supplies are being mixed.) It may help to configure the
|
||||
micro-controller to use power from only one source. (Alternatively,
|
||||
if the micro-controller board can not configure its power source,
|
||||
one may modify a USB cable so that it does not carry 5V power
|
||||
between the host and micro-controller.)
|
||||
|
||||
## My Raspberry Pi keeps rebooting during prints
|
||||
|
||||
This is most likely do to voltage fluctuations. Follow the same
|
||||
troubleshooting steps for a
|
||||
["Lost communication with MCU"](#i-keep-getting-random-lost-communication-with-mcu-errors)
|
||||
error.
|
||||
|
||||
## When I set `restart_method=command` my AVR device just hangs on a restart
|
||||
|
||||
Some old versions of the AVR bootloader have a known bug in watchdog
|
||||
event handling. This typically manifests when the printer.cfg file has
|
||||
restart_method set to "command". When the bug occurs, the AVR device
|
||||
will be unresponsive until power is removed and reapplied to the
|
||||
device (the power or status LEDs may also blink repeatedly until the
|
||||
power is removed).
|
||||
|
||||
The workaround is to use a restart_method other than "command" or to
|
||||
flash an updated bootloader to the AVR device. Flashing a new
|
||||
bootloader is a one time step that typically requires an external
|
||||
programmer - see [Bootloaders](Bootloaders.md) for further details.
|
||||
|
||||
## Will the heaters be left on if the Raspberry Pi crashes?
|
||||
|
||||
The software has been designed to prevent that. Once the host enables
|
||||
a heater, the host software needs to confirm that enablement every 5
|
||||
seconds. If the micro-controller does not receive a confirmation every
|
||||
5 seconds it goes into a "shutdown" state which is designed to turn
|
||||
off all heaters and stepper motors.
|
||||
|
||||
See the "config_digital_out" command in the
|
||||
[MCU commands](MCU_Commands.md) document for further details.
|
||||
|
||||
In addition, the micro-controller software is configured with a
|
||||
minimum and maximum temperature range for each heater at startup (see
|
||||
the min_temp and max_temp parameters in the
|
||||
[config reference](Config_Reference.md#extruder) for details). If the
|
||||
micro-controller detects that the temperature is outside of that range
|
||||
then it will also enter a "shutdown" state.
|
||||
|
||||
Separately, the host software also implements code to check that
|
||||
heaters and temperature sensors are functioning correctly. See the
|
||||
[config reference](Config_Reference.md#verify_heater) for further
|
||||
details.
|
||||
|
||||
## How do I convert a Marlin pin number to a Klipper pin name?
|
||||
|
||||
Short answer: A mapping is available in the
|
||||
[sample-aliases.cfg](../config/sample-aliases.cfg) file. Use that file
|
||||
as a guide to finding the actual micro-controller pin names. (It is
|
||||
also possible to copy the relevant
|
||||
[board_pins](Config_Reference.md#board_pins) config section into your
|
||||
config file and use the aliases in your config, but it is preferable
|
||||
to translate and use the actual micro-controller pin names.) Note that
|
||||
the sample-aliases.cfg file uses pin names that start with the prefix
|
||||
"ar" instead of "D" (eg, Arduino pin `D23` is Klipper alias `ar23`)
|
||||
and the prefix "analog" instead of "A" (eg, Arduino pin `A14` is
|
||||
Klipper alias `analog14`).
|
||||
|
||||
Long answer: Klipper uses the standard pin names defined by the
|
||||
micro-controller. On the Atmega chips these hardware pins have names
|
||||
like `PA4`, `PC7`, or `PD2`.
|
||||
|
||||
Long ago, the Arduino project decided to avoid using the standard
|
||||
hardware names in favor of their own pin names based on incrementing
|
||||
numbers - these Arduino names generally look like `D23` or `A14`. This
|
||||
was an unfortunate choice that has lead to a great deal of confusion.
|
||||
In particular the Arduino pin numbers frequently don't translate to
|
||||
the same hardware names. For example, `D21` is `PD0` on one common
|
||||
Arduino board, but is `PC7` on another common Arduino board.
|
||||
|
||||
To avoid this confusion, the core Klipper code uses the standard pin
|
||||
names defined by the micro-controller.
|
||||
|
||||
## Do I have to wire my device to a specific type of micro-controller pin?
|
||||
|
||||
It depends on the type of device and type of pin:
|
||||
|
||||
ADC pins (or Analog pins): For thermistors and similar "analog"
|
||||
sensors, the device must be wired to an "analog" or "ADC" capable pin
|
||||
on the micro-controller. If you configure Klipper to use a pin that is
|
||||
not analog capable, Klipper will report a "Not a valid ADC pin" error.
|
||||
|
||||
PWM pins (or Timer pins): Klipper does not use hardware PWM by default
|
||||
for any device. So, in general, one may wire heaters, fans, and
|
||||
similar devices to any general purpose IO pin. However, fans and
|
||||
output_pin devices may be optionally configured to use `hardware_pwm:
|
||||
True`, in which case the micro-controller must support hardware PWM on
|
||||
the pin (otherwise, Klipper will report a "Not a valid PWM pin"
|
||||
error).
|
||||
|
||||
IRQ pins (or Interrupt pins): Klipper does not use hardware interrupts
|
||||
on IO pins, so it is never necessary to wire a device to one of these
|
||||
micro-controller pins.
|
||||
|
||||
SPI pins: When using hardware SPI it is necessary to wire the pins to
|
||||
the micro-controller's SPI capable pins. However, most devices can be
|
||||
configured to use "software SPI", in which case any general purpose IO
|
||||
pins may be used.
|
||||
|
||||
I2C pins: When using I2C it is necessary to wire the pins to the
|
||||
micro-controller's I2C capable pins.
|
||||
|
||||
Other devices may be wired to any general purpose IO pin. For example,
|
||||
steppers, heaters, fans, Z probes, servos, LEDs, common hd44780/st7920
|
||||
LCD displays, the Trinamic UART control line may be wired to any
|
||||
general purpose IO pin.
|
||||
|
||||
## How do I cancel an M109/M190 "wait for temperature" request?
|
||||
|
||||
Navigate to the OctoPrint terminal tab and issue an M112 command in
|
||||
the terminal box. The M112 command will cause Klipper to enter into a
|
||||
"shutdown" state, and it will cause OctoPrint to disconnect from
|
||||
Klipper. Navigate to the OctoPrint connection area and click on
|
||||
"Connect" to cause OctoPrint to reconnect. Navigate back to the
|
||||
terminal tab and issue a FIRMWARE_RESTART command to clear the Klipper
|
||||
error state. After completing this sequence, the previous heating
|
||||
request will be canceled and a new print may be started.
|
||||
|
||||
## Can I find out whether the printer has lost steps?
|
||||
|
||||
In a way, yes. Home the printer, issue a `GET_POSITION` command, run
|
||||
your print, home again and issue another `GET_POSITION`. Then compare
|
||||
the values in the `mcu:` line.
|
||||
|
||||
This might be helpful to tune settings like stepper motor currents,
|
||||
accelerations and speeds without needing to actually print something
|
||||
and waste filament: just run some high-speed moves in between the
|
||||
`GET_POSITION` commands.
|
||||
|
||||
Note that endstop switches themselves tend to trigger at slightly
|
||||
different positions, so a difference of a couple of microsteps is
|
||||
likely the result of endstop inaccuracies. A stepper motor itself can
|
||||
only lose steps in increments of 4 full steps. (So, if one is using 16
|
||||
microsteps, then a lost step on the stepper would result in the "mcu:"
|
||||
step counter being off by a multiple of 64 microsteps.)
|
||||
|
||||
## Why does Klipper report errors? I lost my print!
|
||||
|
||||
Short answer: We want to know if our printers detect a problem so that
|
||||
the underlying issue can be fixed and we can obtain great quality
|
||||
prints. We definitely do not want our printers to silently produce low
|
||||
quality prints.
|
||||
|
||||
Long answer: Klipper has been engineered to automatically workaround
|
||||
many transient problems. For example, it automatically detects
|
||||
communication errors and will retransmit; it schedules actions in
|
||||
advance and buffers commands at multiple layers to enable precise
|
||||
timing even with intermittent interference. However, should the
|
||||
software detect an error that it can not recover from, if it is
|
||||
commanded to take an invalid action, or if it detects it is hopelessly
|
||||
unable to perform its commanded task, then Klipper will report an
|
||||
error. In these situations there is a high risk of producing a
|
||||
low-quality print (or worse). It is hoped that alerting the user will
|
||||
empower them to fix the underlying issue and improve the overall
|
||||
quality of their prints.
|
||||
|
||||
There are some related questions: Why doesn't Klipper pause the print
|
||||
instead? Report a warning instead? Check for errors before the print?
|
||||
Ignore errors in user typed commands? etc? Currently Klipper reads
|
||||
commands using the G-Code protocol, and unfortunately the G-Code
|
||||
command protocol is not flexible enough to make these alternatives
|
||||
practical today. There is developer interest in improving the user
|
||||
experience during abnormal events, but it is expected that will
|
||||
require notable infrastructure work (including a shift away from
|
||||
G-Code).
|
||||
|
||||
## How do I upgrade to the latest software?
|
||||
|
||||
The first step to upgrading the software is to review the latest
|
||||
[config changes](Config_Changes.md) document. On occasion, changes are
|
||||
made to the software that require users to update their settings as
|
||||
part of a software upgrade. It is a good idea to review this document
|
||||
prior to upgrading.
|
||||
|
||||
When ready to upgrade, the general method is to ssh into the Raspberry
|
||||
Pi and run:
|
||||
|
||||
```
|
||||
cd ~/klipper
|
||||
git pull
|
||||
~/klipper/scripts/install-octopi.sh
|
||||
```
|
||||
|
||||
Then one can recompile and flash the micro-controller code. For
|
||||
example:
|
||||
|
||||
```
|
||||
make menuconfig
|
||||
make clean
|
||||
make
|
||||
|
||||
sudo service klipper stop
|
||||
make flash FLASH_DEVICE=/dev/ttyACM0
|
||||
sudo service klipper start
|
||||
```
|
||||
|
||||
However, it's often the case that only the host software changes. In
|
||||
this case, one can update and restart just the host software with:
|
||||
|
||||
```
|
||||
cd ~/klipper
|
||||
git pull
|
||||
sudo service klipper restart
|
||||
```
|
||||
|
||||
If after using this shortcut the software warns about needing to
|
||||
reflash the micro-controller or some other unusual error occurs, then
|
||||
follow the full upgrade steps outlined above.
|
||||
|
||||
If any errors persist then double check the
|
||||
[config changes](Config_Changes.md) document, as you may need to
|
||||
modify the printer configuration.
|
||||
|
||||
Note that the RESTART and FIRMWARE_RESTART g-code commands do not load
|
||||
new software - the above "sudo service klipper restart" and "make
|
||||
flash" commands are needed for a software change to take effect.
|
||||
|
||||
## How do I uninstall Klipper?
|
||||
|
||||
On the firmware end, nothing special needs to happen. Just follow the
|
||||
flashing directions for the new firmware.
|
||||
|
||||
On the raspberry pi end, an uninstall script is available in
|
||||
[scripts/klipper-uninstall.sh](../scripts/klipper-uninstall.sh). For
|
||||
example:
|
||||
```
|
||||
sudo ~/klipper/scripts/klipper-uninstall.sh
|
||||
rm -rf ~/klippy-env ~/klipper
|
||||
```
|
||||
184
docs/Features.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Features
|
||||
|
||||
Klipper has several compelling features:
|
||||
|
||||
* High precision stepper movement. Klipper utilizes an application
|
||||
processor (such as a low-cost Raspberry Pi) when calculating printer
|
||||
movements. The application processor determines when to step each
|
||||
stepper motor, it compresses those events, transmits them to the
|
||||
micro-controller, and then the micro-controller executes each event
|
||||
at the requested time. Each stepper event is scheduled with a
|
||||
precision of 25 micro-seconds or better. The software does not use
|
||||
kinematic estimations (such as the Bresenham algorithm) - instead it
|
||||
calculates precise step times based on the physics of acceleration
|
||||
and the physics of the machine kinematics. More precise stepper
|
||||
movement translates to quieter and more stable printer operation.
|
||||
|
||||
* Best in class performance. Klipper is able to achieve high stepping
|
||||
rates on both new and old micro-controllers. Even old 8bit
|
||||
micro-controllers can obtain rates over 175K steps per second. On
|
||||
more recent micro-controllers, several million steps per second are
|
||||
possible. Higher stepper rates enable higher print velocities. The
|
||||
stepper event timing remains precise even at high speeds which
|
||||
improves overall stability.
|
||||
|
||||
* Klipper supports printers with multiple micro-controllers. For
|
||||
example, one micro-controller could be used to control an extruder,
|
||||
while another controls the printer's heaters, while a third controls
|
||||
the rest of the printer. The Klipper host software implements clock
|
||||
synchronization to account for clock drift between
|
||||
micro-controllers. No special code is needed to enable multiple
|
||||
micro-controllers - it just requires a few extra lines in the config
|
||||
file.
|
||||
|
||||
* Configuration via simple config file. There's no need to reflash the
|
||||
micro-controller to change a setting. All of Klipper's configuration
|
||||
is stored in a standard config file which can be easily edited. This
|
||||
makes it easier to setup and maintain the hardware.
|
||||
|
||||
* Klipper supports "Smooth Pressure Advance" - a mechanism to account
|
||||
for the effects of pressure within an extruder. This reduces
|
||||
extruder "ooze" and improves the quality of print corners. Klipper's
|
||||
implementation does not introduce instantaneous extruder speed
|
||||
changes, which improves overall stability and robustness.
|
||||
|
||||
* Klipper supports "Input Shaping" to reduce the impact of vibrations
|
||||
on print quality. This can reduce or eliminate "ringing" (also known
|
||||
as "ghosting", "echoing", or "rippling") in prints. It may also
|
||||
allow one to obtain faster printing speeds while still maintaining
|
||||
high print quality.
|
||||
|
||||
* Klipper uses an "iterative solver" to calculate precise step times
|
||||
from simple kinematic equations. This makes porting Klipper to new
|
||||
types of robots easier and it keeps timing precise even with complex
|
||||
kinematics (no "line segmentation" is needed).
|
||||
|
||||
* Portable code. Klipper works on ARM, AVR, and PRU based
|
||||
micro-controllers. Existing "reprap" style printers can run Klipper
|
||||
without hardware modification - just add a Raspberry Pi. Klipper's
|
||||
internal code layout makes it easier to support other
|
||||
micro-controller architectures as well.
|
||||
|
||||
* Simpler code. Klipper uses a very high level language (Python) for
|
||||
most code. The kinematics algorithms, the G-code parsing, the
|
||||
heating and thermistor algorithms, etc. are all written in Python.
|
||||
This makes it easier to develop new functionality.
|
||||
|
||||
* Custom programmable macros. New G-Code commands can be defined in
|
||||
the printer config file (no code changes are necessary). Those
|
||||
commands are programmable - allowing them to produce different
|
||||
actions depending on the state of the printer.
|
||||
|
||||
* Builtin API server. In addition to the standard G-Code interface,
|
||||
Klipper supports a rich JSON based application interface. This
|
||||
enables programmers to build external applications with detailed
|
||||
control of the printer.
|
||||
|
||||
## Additional features
|
||||
|
||||
Klipper supports many standard 3d printer features:
|
||||
|
||||
* Works with Octoprint. This allows the printer to be controlled using
|
||||
a regular web-browser. The same Raspberry Pi that runs Klipper can
|
||||
also run Octoprint.
|
||||
|
||||
* Standard G-Code support. Common g-code commands that are produced by
|
||||
typical "slicers" (SuperSlicer, Cura, PrusaSlicer, etc.) are
|
||||
supported.
|
||||
|
||||
* Support for multiple extruders. Extruders with shared heaters and
|
||||
extruders on independent carriages (IDEX) are also supported.
|
||||
|
||||
* Support for cartesian, delta, corexy, corexz, hybrid-corexy,
|
||||
hybrid-corexz, rotary delta, polar, and cable winch style printers.
|
||||
|
||||
* Automatic bed leveling support. Klipper can be configured for basic
|
||||
bed tilt detection or full mesh bed leveling. If the bed uses
|
||||
multiple Z steppers then Klipper can also level by independently
|
||||
manipulating the Z steppers. Most Z height probes are supported,
|
||||
including BL-Touch probes and servo activated probes.
|
||||
|
||||
* Automatic delta calibration support. The calibration tool can
|
||||
perform basic height calibration as well as an enhanced X and Y
|
||||
dimension calibration. The calibration can be done with a Z height
|
||||
probe or via manual probing.
|
||||
|
||||
* Support for common temperature sensors (eg, common thermistors,
|
||||
AD595, AD597, AD849x, PT100, PT1000, MAX6675, MAX31855, MAX31856,
|
||||
MAX31865, BME280, HTU21D, DS18B20, and LM75). Custom thermistors and
|
||||
custom analog temperature sensors can also be configured. One can
|
||||
monitor the internal micro-controller temperature sensor and the
|
||||
internal temperature sensor of a Raspberry Pi.
|
||||
|
||||
* Basic thermal heater protection enabled by default.
|
||||
|
||||
* Support for standard fans, nozzle fans, and temperature controlled
|
||||
fans. No need to keep fans running when the printer is idle. Fan
|
||||
speed can be monitored on fans that have a tachometer.
|
||||
|
||||
* Support for run-time configuration of TMC2130, TMC2208/TMC2224,
|
||||
TMC2209, TMC2660, and TMC5160 stepper motor drivers. There is also
|
||||
support for current control of traditional stepper drivers via
|
||||
AD5206, MCP4451, MCP4728, MCP4018, and PWM pins.
|
||||
|
||||
* Support for common LCD displays attached directly to the printer. A
|
||||
default menu is also available. The contents of the display and menu
|
||||
can be fully customized via the config file.
|
||||
|
||||
* Constant acceleration and "look-ahead" support. All printer moves
|
||||
will gradually accelerate from standstill to cruising speed and then
|
||||
decelerate back to a standstill. The incoming stream of G-Code
|
||||
movement commands are queued and analyzed - the acceleration between
|
||||
movements in a similar direction will be optimized to reduce print
|
||||
stalls and improve overall print time.
|
||||
|
||||
* Klipper implements a "stepper phase endstop" algorithm that can
|
||||
improve the accuracy of typical endstop switches. When properly
|
||||
tuned it can improve a print's first layer bed adhesion.
|
||||
|
||||
* Support for filament presence sensors, filament motion sensors, and
|
||||
filament width sensors.
|
||||
|
||||
* Support for measuring and recording acceleration using an adxl345
|
||||
accelerometer.
|
||||
|
||||
* Support for limiting the top speed of short "zigzag" moves to reduce
|
||||
printer vibration and noise. See the [kinematics](Kinematics.md)
|
||||
document for more information.
|
||||
|
||||
* Sample configuration files are available for many common printers.
|
||||
Check the [config directory](../config/) for a list.
|
||||
|
||||
To get started with Klipper, read the [installation](Installation.md)
|
||||
guide.
|
||||
|
||||
## Step Benchmarks
|
||||
|
||||
Below are the results of stepper performance tests. The numbers shown
|
||||
represent total number of steps per second on the micro-controller.
|
||||
|
||||
| Micro-controller | 1 stepper active | 3 steppers active |
|
||||
| ------------------------------- | ----------------- | ----------------- |
|
||||
| 16Mhz AVR | 157K | 99K |
|
||||
| 20Mhz AVR | 196K | 123K |
|
||||
| SAMD21 | 686K | 471K |
|
||||
| STM32F042 | 814K | 578K |
|
||||
| Beaglebone PRU | 866K | 708K |
|
||||
| STM32G0B1 | 1103K | 790K |
|
||||
| STM32F103 | 1180K | 818K |
|
||||
| SAM3X8E | 1273K | 981K |
|
||||
| SAM4S8C | 1690K | 1385K |
|
||||
| LPC1768 | 1923K | 1351K |
|
||||
| LPC1769 | 2353K | 1622K |
|
||||
| RP2040 | 2400K | 1636K |
|
||||
| SAM4E8E | 2500K | 1674K |
|
||||
| SAMD51 | 3077K | 1885K |
|
||||
| STM32F407 | 3652K | 2459K |
|
||||
| STM32F446 | 3913K | 2634K |
|
||||
|
||||
If unsure of the micro-controller on a particular board, find the
|
||||
appropriate [config file](../config/), and look for the
|
||||
micro-controller name in the comments at the top of that file.
|
||||
|
||||
Further details on the benchmarks are available in the
|
||||
[Benchmarks document](Benchmarks.md).
|
||||
1279
docs/G-Codes.md
Normal file
67
docs/Hall_Filament_Width_Sensor.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Hall filament width sensor
|
||||
|
||||
This document describes Filament Width Sensor host module. Hardware used for
|
||||
developing this host module is based on two Hall linear sensors (ss49e for
|
||||
example). Sensors in the body are located opposite sides. Principle of operation:
|
||||
two hall sensors work in differential mode, temperature drift same for sensor.
|
||||
Special temperature compensation not needed.
|
||||
|
||||
You can find designs at [Thingiverse](https://www.thingiverse.com/thing:4138933),
|
||||
an assembly video is also available on [Youtube](https://www.youtube.com/watch?v=TDO9tME8vp4)
|
||||
|
||||
To use Hall filament width sensor, read
|
||||
[Config Reference](Config_Reference.md#hall_filament_width_sensor) and
|
||||
[G-Code documentation](G-Codes.md#hall_filament_width_sensor).
|
||||
|
||||
|
||||
## How does it work?
|
||||
|
||||
Sensor generates two analog output based on calculated filament width. Sum of
|
||||
output voltage always equals to detected filament width. Host module monitors
|
||||
voltage changes and adjusts extrusion multiplier. I use aux2 connector on
|
||||
ramps-like board analog11 and analog12 pins. You can use different pins and
|
||||
differenr boards.
|
||||
|
||||
## Template for menu variables
|
||||
|
||||
```
|
||||
[menu __main __filament __width_current]
|
||||
type: command
|
||||
enable: {'hall_filament_width_sensor' in printer}
|
||||
name: Dia: {'%.2F' % printer.hall_filament_width_sensor.Diameter}
|
||||
index: 0
|
||||
|
||||
[menu __main __filament __raw_width_current]
|
||||
type: command
|
||||
enable: {'hall_filament_width_sensor' in printer}
|
||||
name: Raw: {'%4.0F' % printer.hall_filament_width_sensor.Raw}
|
||||
index: 1
|
||||
```
|
||||
|
||||
## Calibration procedure
|
||||
|
||||
To get raw sensor value you can use menu item or **QUERY_RAW_FILAMENT_WIDTH**
|
||||
command in terminal.
|
||||
|
||||
1. Insert first calibration rod (1.5 mm size) get first raw sensor value
|
||||
|
||||
2. Insert second calibration rod (2.0 mm size) get second raw sensor value
|
||||
|
||||
3. Save raw sensor values in config parameter `Raw_dia1` and `Raw_dia2`
|
||||
|
||||
## How to enable sensor
|
||||
|
||||
By default, the sensor is disabled at power-on.
|
||||
|
||||
To enable the sensor, issue **ENABLE_FILAMENT_WIDTH_SENSOR** command or
|
||||
set the `enable` parameter to `true`.
|
||||
|
||||
## Logging
|
||||
|
||||
By default, diameter logging is disabled at power-on.
|
||||
|
||||
Issue **ENABLE_FILAMENT_WIDTH_LOG** command to start logging and issue
|
||||
**DISABLE_FILAMENT_WIDTH_LOG** command to stop logging. To enable logging
|
||||
at power-on, set the `logging` parameter to `true`.
|
||||
|
||||
Filament diameter is logged on every measurement interval (10 mm by default).
|
||||
222
docs/Installation.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# Installation
|
||||
|
||||
These instructions assume the software will run on a Raspberry Pi
|
||||
computer in conjunction with OctoPrint. It is recommended that a
|
||||
Raspberry Pi 2, 3, or 4 computer be used as the host machine (see the
|
||||
[FAQ](FAQ.md#can-i-run-klipper-on-something-other-than-a-raspberry-pi-3)
|
||||
for other machines).
|
||||
|
||||
## Obtain a Klipper Configuration File
|
||||
|
||||
Most Klipper settings are determined by a "printer configuration file"
|
||||
that will be stored on the Raspberry Pi. An appropriate configuration
|
||||
file can often be found by looking in the Klipper
|
||||
[config directory](../config/) for a file starting with a "printer-"
|
||||
prefix that corresponds to the target printer. The Klipper
|
||||
configuration file contains technical information about the printer
|
||||
that will be needed during the installation.
|
||||
|
||||
If there isn't an appropriate printer configuration file in the
|
||||
Klipper config directory then try searching the printer manufacturer's
|
||||
website to see if they have an appropriate Klipper configuration file.
|
||||
|
||||
If no configuration file for the printer can be found, but the type of
|
||||
printer control board is known, then look for an appropriate
|
||||
[config file](../config/) starting with a "generic-" prefix. These
|
||||
example printer board files should allow one to successfully complete
|
||||
the initial installation, but will require some customization to
|
||||
obtain full printer functionality.
|
||||
|
||||
It is also possible to define a new printer configuration from
|
||||
scratch. However, this requires significant technical knowledge about
|
||||
the printer and its electronics. It is recommended that most users
|
||||
start with an appropriate configuration file. If creating a new custom
|
||||
printer configuration file, then start with the closest example
|
||||
[config file](../config/) and use the Klipper
|
||||
[config reference](Config_Reference.md) for further information.
|
||||
|
||||
## Prepping an OS image
|
||||
|
||||
Start by installing [OctoPi](https://github.com/guysoft/OctoPi) on the
|
||||
Raspberry Pi computer. Use OctoPi v0.17.0 or later - see the
|
||||
[OctoPi releases](https://github.com/guysoft/OctoPi/releases) for
|
||||
release information. One should verify that OctoPi boots and that the
|
||||
OctoPrint web server works. After connecting to the OctoPrint web
|
||||
page, follow the prompt to upgrade OctoPrint to v1.4.2 or later.
|
||||
|
||||
After installing OctoPi and upgrading OctoPrint, it will be necessary
|
||||
to ssh into the target machine to run a handful of system commands. If
|
||||
using a Linux or MacOS desktop, then the "ssh" software should already
|
||||
be installed on the desktop. There are free ssh clients available for
|
||||
other desktops (eg,
|
||||
[PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/)). Use the
|
||||
ssh utility to connect to the Raspberry Pi (ssh pi@octopi -- password
|
||||
is "raspberry") and run the following commands:
|
||||
|
||||
```
|
||||
git clone https://github.com/Klipper3d/klipper
|
||||
./klipper/scripts/install-octopi.sh
|
||||
```
|
||||
|
||||
The above will download Klipper, install some system dependencies,
|
||||
setup Klipper to run at system startup, and start the Klipper host
|
||||
software. It will require an internet connection and it may take a few
|
||||
minutes to complete.
|
||||
|
||||
## Building and flashing the micro-controller
|
||||
|
||||
To compile the micro-controller code, start by running these commands
|
||||
on the Raspberry Pi:
|
||||
|
||||
```
|
||||
cd ~/klipper/
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
The comments at the top of the
|
||||
[printer configuration file](#obtain-a-klipper-configuration-file)
|
||||
should describe the settings that need to be set during "make
|
||||
menuconfig". Open the file in a web browser or text editor and look
|
||||
for these instructions near the top of the file. Once the appropriate
|
||||
"menuconfig" settings have been configured, press "Q" to exit, and
|
||||
then "Y" to save. Then run:
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
If the comments at the top of the
|
||||
[printer configuration file](#obtain-a-klipper-configuration-file)
|
||||
describe custom steps for "flashing" the final image to the printer
|
||||
control board then follow those steps and then proceed to
|
||||
[configuring OctoPrint](#configuring-octoprint-to-use-klipper).
|
||||
|
||||
Otherwise, the following steps are often used to "flash" the printer
|
||||
control board. First, it is necessary to determine the serial port
|
||||
connected to the micro-controller. Run the following:
|
||||
|
||||
```
|
||||
ls /dev/serial/by-id/*
|
||||
```
|
||||
|
||||
It should report something similar to the following:
|
||||
|
||||
```
|
||||
/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
```
|
||||
|
||||
It's common for each printer to have its own unique serial port name.
|
||||
This unique name will be used when flashing the micro-controller. It's
|
||||
possible there may be multiple lines in the above output - if so,
|
||||
choose the line corresponding to the micro-controller (see the
|
||||
[FAQ](FAQ.md#wheres-my-serial-port) for more information).
|
||||
|
||||
For common micro-controllers, the code can be flashed with something
|
||||
similar to:
|
||||
|
||||
```
|
||||
sudo service klipper stop
|
||||
make flash FLASH_DEVICE=/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
sudo service klipper start
|
||||
```
|
||||
|
||||
Be sure to update the FLASH_DEVICE with the printer's unique serial
|
||||
port name.
|
||||
|
||||
When flashing for the first time, make sure that OctoPrint is not
|
||||
connected directly to the printer (from the OctoPrint web page, under
|
||||
the "Connection" section, click "Disconnect").
|
||||
|
||||
## Configuring OctoPrint to use Klipper
|
||||
|
||||
The OctoPrint web server needs to be configured to communicate with
|
||||
the Klipper host software. Using a web browser, login to the OctoPrint
|
||||
web page and then configure the following items:
|
||||
|
||||
Navigate to the Settings tab (the wrench icon at the top of the
|
||||
page). Under "Serial Connection" in "Additional serial ports" add
|
||||
"/tmp/printer". Then click "Save".
|
||||
|
||||
Enter the Settings tab again and under "Serial Connection" change the
|
||||
"Serial Port" setting to "/tmp/printer".
|
||||
|
||||
In the Settings tab, navigate to the "Behavior" sub-tab and select the
|
||||
"Cancel any ongoing prints but stay connected to the printer"
|
||||
option. Click "Save".
|
||||
|
||||
From the main page, under the "Connection" section (at the top left of
|
||||
the page) make sure the "Serial Port" is set to "/tmp/printer" and
|
||||
click "Connect". (If "/tmp/printer" is not an available selection then
|
||||
try reloading the page.)
|
||||
|
||||
Once connected, navigate to the "Terminal" tab and type "status"
|
||||
(without the quotes) into the command entry box and click "Send". The
|
||||
terminal window will likely report there is an error opening the
|
||||
config file - that means OctoPrint is successfully communicating with
|
||||
Klipper. Proceed to the next section.
|
||||
|
||||
## Configuring Klipper
|
||||
|
||||
The next step is to copy the
|
||||
[printer configuration file](#obtain-a-klipper-configuration-file) to
|
||||
the Raspberry Pi.
|
||||
|
||||
Arguably the easiest way to set the Klipper configuration file is to
|
||||
use a desktop editor that supports editing files over the "scp" and/or
|
||||
"sftp" protocols. There are freely available tools that support this
|
||||
(eg, Notepad++, WinSCP, and Cyberduck). Load the printer config file
|
||||
in the editor and then save it as a file named "printer.cfg" in the
|
||||
home directory of the pi user (ie, /home/pi/printer.cfg).
|
||||
|
||||
Alternatively, one can also copy and edit the file directly on the
|
||||
Raspberry Pi via ssh. That may look something like the following (be
|
||||
sure to update the command to use the appropriate printer config
|
||||
filename):
|
||||
|
||||
```
|
||||
cp ~/klipper/config/example-cartesian.cfg ~/printer.cfg
|
||||
nano ~/printer.cfg
|
||||
```
|
||||
|
||||
It's common for each printer to have its own unique name for the
|
||||
micro-controller. The name may change after flashing Klipper, so rerun
|
||||
these steps again even if they were already done when flashing. Run:
|
||||
|
||||
```
|
||||
ls /dev/serial/by-id/*
|
||||
```
|
||||
|
||||
It should report something similar to the following:
|
||||
|
||||
```
|
||||
/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
```
|
||||
|
||||
Then update the config file with the unique name. For example, update
|
||||
the `[mcu]` section to look something similar to:
|
||||
|
||||
```
|
||||
[mcu]
|
||||
serial: /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0
|
||||
```
|
||||
|
||||
After creating and editing the file it will be necessary to issue a
|
||||
"restart" command in the OctoPrint web terminal to load the config. A
|
||||
"status" command will report the printer is ready if the Klipper
|
||||
config file is successfully read and the micro-controller is
|
||||
successfully found and configured.
|
||||
|
||||
When customizing the printer config file, it is not uncommon for
|
||||
Klipper to report a configuration error. If an error occurs, make any
|
||||
necessary corrections to the printer config file and issue "restart"
|
||||
until "status" reports the printer is ready.
|
||||
|
||||
Klipper reports error messages via the OctoPrint terminal tab. The
|
||||
"status" command can be used to re-report error messages. The default
|
||||
Klipper startup script also places a log in **/tmp/klippy.log** which
|
||||
provides more detailed information.
|
||||
|
||||
After Klipper reports that the printer is ready, proceed to the
|
||||
[config check document](Config_checks.md) to perform some basic checks
|
||||
on the definitions in the config file. See the main
|
||||
[documentation reference](Overview.md) for other information.
|
||||
293
docs/Kinematics.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# Kinematics
|
||||
|
||||
This document provides an overview of how Klipper implements robot
|
||||
motion (its [kinematics](https://en.wikipedia.org/wiki/Kinematics)).
|
||||
The contents may be of interest to both developers interested in
|
||||
working on the Klipper software as well as users interested in better
|
||||
understanding the mechanics of their machines.
|
||||
|
||||
## Acceleration
|
||||
|
||||
Klipper implements a constant acceleration scheme whenever the print
|
||||
head changes velocity - the velocity is gradually changed to the new
|
||||
speed instead of suddenly jerking to it. Klipper always enforces
|
||||
acceleration between the tool head and the print. The filament leaving
|
||||
the extruder can be quite fragile - rapid jerks and/or extruder flow
|
||||
changes lead to poor quality and poor bed adhesion. Even when not
|
||||
extruding, if the print head is at the same level as the print then
|
||||
rapid jerking of the head can cause disruption of recently deposited
|
||||
filament. Limiting speed changes of the print head (relative to the
|
||||
print) reduces risks of disrupting the print.
|
||||
|
||||
It is also important to limit acceleration so that the stepper motors
|
||||
do not skip or put excessive stress on the machine. Klipper limits the
|
||||
torque on each stepper by virtue of limiting the acceleration of the
|
||||
print head. Enforcing acceleration at the print head naturally also
|
||||
limits the torque of the steppers that move the print head (the
|
||||
inverse is not always true).
|
||||
|
||||
Klipper implements constant acceleration. The key formula for constant
|
||||
acceleration is:
|
||||
```
|
||||
velocity(time) = start_velocity + accel*time
|
||||
```
|
||||
|
||||
## Trapezoid generator
|
||||
|
||||
Klipper uses a traditional "trapezoid generator" to model the motion
|
||||
of each move - each move has a start speed, it accelerates to a
|
||||
cruising speed at constant acceleration, it cruises at a constant
|
||||
speed, and then decelerates to the end speed using constant
|
||||
acceleration.
|
||||
|
||||

|
||||
|
||||
It's called a "trapezoid generator" because a velocity diagram of the
|
||||
move looks like a trapezoid.
|
||||
|
||||
The cruising speed is always greater than or equal to both the start
|
||||
speed and the end speed. The acceleration phase may be of zero
|
||||
duration (if the start speed is equal to the cruising speed), the
|
||||
cruising phase may be of zero duration (if the move immediately starts
|
||||
decelerating after acceleration), and/or the deceleration phase may be
|
||||
of zero duration (if the end speed is equal to the cruising speed).
|
||||
|
||||

|
||||
|
||||
## Look-ahead
|
||||
|
||||
The "look-ahead" system is used to determine cornering speeds between
|
||||
moves.
|
||||
|
||||
Consider the following two moves contained on an XY plane:
|
||||
|
||||

|
||||
|
||||
In the above situation it is possible to fully decelerate after the
|
||||
first move and then fully accelerate at the start of the next move,
|
||||
but that is not ideal as all that acceleration and deceleration would
|
||||
greatly increase the print time and the frequent changes in extruder
|
||||
flow would result in poor print quality.
|
||||
|
||||
To solve this, the "look-ahead" mechanism queues multiple incoming
|
||||
moves and analyzes the angles between moves to determine a reasonable
|
||||
speed that can be obtained during the "junction" between two moves. If
|
||||
the next move is nearly in the same direction then the head need only
|
||||
slow down a little (if at all).
|
||||
|
||||

|
||||
|
||||
However, if the next move forms an acute angle (the head is going to
|
||||
travel in nearly a reverse direction on the next move) then only a
|
||||
small junction speed is permitted.
|
||||
|
||||

|
||||
|
||||
The junction speeds are determined using "approximated centripetal
|
||||
acceleration". Best
|
||||
[described by the author](https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/).
|
||||
However, in Klipper, junction speeds are configured by specifying the
|
||||
desired speed that a 90° corner should have (the "square corner
|
||||
velocity"), and the junction speeds for other angles are derived from
|
||||
that.
|
||||
|
||||
Key formula for look-ahead:
|
||||
```
|
||||
end_velocity^2 = start_velocity^2 + 2*accel*move_distance
|
||||
```
|
||||
|
||||
### Smoothed look-ahead
|
||||
|
||||
Klipper also implements a mechanism for smoothing out the motions of
|
||||
short "zigzag" moves. Consider the following moves:
|
||||
|
||||

|
||||
|
||||
In the above, the frequent changes from acceleration to deceleration
|
||||
can cause the machine to vibrate which causes stress on the machine
|
||||
and increases the noise. To reduce this, Klipper tracks both regular
|
||||
move acceleration as well as a virtual "acceleration to deceleration"
|
||||
rate. Using this system, the top speed of these short "zigzag" moves
|
||||
are limited to smooth out the printer motion:
|
||||
|
||||

|
||||
|
||||
Specifically, the code calculates what the velocity of each move would
|
||||
be if it were limited to this virtual "acceleration to deceleration"
|
||||
rate (half the normal acceleration rate by default). In the above
|
||||
picture the dashed gray lines represent this virtual acceleration rate
|
||||
for the first move. If a move can not reach its full cruising speed
|
||||
using this virtual acceleration rate then its top speed is reduced to
|
||||
the maximum speed it could obtain at this virtual acceleration
|
||||
rate. For most moves the limit will be at or above the move's existing
|
||||
limits and no change in behavior is induced. For short zigzag moves,
|
||||
however, this limit reduces the top speed. Note that it does not
|
||||
change the actual acceleration within the move - the move continues to
|
||||
use the normal acceleration scheme up to its adjusted top-speed.
|
||||
|
||||
## Generating steps
|
||||
|
||||
Once the look-ahead process completes, the print head movement for the
|
||||
given move is fully known (time, start position, end position,
|
||||
velocity at each point) and it is possible to generate the step times
|
||||
for the move. This process is done within "kinematic classes" in the
|
||||
Klipper code. Outside of these kinematic classes, everything is
|
||||
tracked in millimeters, seconds, and in cartesian coordinate space.
|
||||
It's the task of the kinematic classes to convert from this generic
|
||||
coordinate system to the hardware specifics of the particular printer.
|
||||
|
||||
Klipper uses an
|
||||
[iterative solver](https://en.wikipedia.org/wiki/Root-finding_algorithm)
|
||||
to generate the step times for each stepper. The code contains the
|
||||
formulas to calculate the ideal cartesian coordinates of the head at
|
||||
each moment in time, and it has the kinematic formulas to calculate
|
||||
the ideal stepper positions based on those cartesian coordinates. With
|
||||
these formulas, Klipper can determine the ideal time that the stepper
|
||||
should be at each step position. The given steps are then scheduled at
|
||||
these calculated times.
|
||||
|
||||
The key formula to determine how far a move should travel under
|
||||
constant acceleration is:
|
||||
```
|
||||
move_distance = (start_velocity + .5 * accel * move_time) * move_time
|
||||
```
|
||||
and the key formula for movement with constant velocity is:
|
||||
```
|
||||
move_distance = cruise_velocity * move_time
|
||||
```
|
||||
|
||||
The key formulas for determining the cartesian coordinate of a move
|
||||
given a move distance is:
|
||||
```
|
||||
cartesian_x_position = start_x + move_distance * total_x_movement / total_movement
|
||||
cartesian_y_position = start_y + move_distance * total_y_movement / total_movement
|
||||
cartesian_z_position = start_z + move_distance * total_z_movement / total_movement
|
||||
```
|
||||
|
||||
### Cartesian Robots
|
||||
|
||||
Generating steps for cartesian printers is the simplest case. The
|
||||
movement on each axis is directly related to the movement in cartesian
|
||||
space.
|
||||
|
||||
Key formulas:
|
||||
```
|
||||
stepper_x_position = cartesian_x_position
|
||||
stepper_y_position = cartesian_y_position
|
||||
stepper_z_position = cartesian_z_position
|
||||
```
|
||||
|
||||
### CoreXY Robots
|
||||
|
||||
Generating steps on a CoreXY machine is only a little more complex
|
||||
than basic cartesian robots. The key formulas are:
|
||||
```
|
||||
stepper_a_position = cartesian_x_position + cartesian_y_position
|
||||
stepper_b_position = cartesian_x_position - cartesian_y_position
|
||||
stepper_z_position = cartesian_z_position
|
||||
```
|
||||
|
||||
### Delta Robots
|
||||
|
||||
Step generation on a delta robot is based on Pythagoras's theorem:
|
||||
```
|
||||
stepper_position = (sqrt(arm_length^2
|
||||
- (cartesian_x_position - tower_x_position)^2
|
||||
- (cartesian_y_position - tower_y_position)^2)
|
||||
+ cartesian_z_position)
|
||||
```
|
||||
|
||||
### Stepper motor acceleration limits
|
||||
|
||||
With delta kinematics it is possible for a move that is accelerating
|
||||
in cartesian space to require an acceleration on a particular stepper
|
||||
motor greater than the move's acceleration. This can occur when a
|
||||
stepper arm is more horizontal than vertical and the line of movement
|
||||
passes near that stepper's tower. Although these moves could require a
|
||||
stepper motor acceleration greater than the printer's maximum
|
||||
configured move acceleration, the effective mass moved by that stepper
|
||||
would be smaller. Thus the higher stepper acceleration does not result
|
||||
in significantly higher stepper torque and it is therefore considered
|
||||
harmless.
|
||||
|
||||
However, to avoid extreme cases, Klipper enforces a maximum ceiling on
|
||||
stepper acceleration of three times the printer's configured maximum
|
||||
move acceleration. (Similarly, the maximum velocity of the stepper is
|
||||
limited to three times the maximum move velocity.) In order to enforce
|
||||
this limit, moves at the extreme edge of the build envelope (where a
|
||||
stepper arm may be nearly horizontal) will have a lower maximum
|
||||
acceleration and velocity.
|
||||
|
||||
### Extruder kinematics
|
||||
|
||||
Klipper implements extruder motion in its own kinematic class. Since
|
||||
the timing and speed of each print head movement is fully known for
|
||||
each move, it's possible to calculate the step times for the extruder
|
||||
independently from the step time calculations of the print head
|
||||
movement.
|
||||
|
||||
Basic extruder movement is simple to calculate. The step time
|
||||
generation uses the same formulas that cartesian robots use:
|
||||
```
|
||||
stepper_position = requested_e_position
|
||||
```
|
||||
|
||||
### Pressure advance
|
||||
|
||||
Experimentation has shown that it's possible to improve the modeling
|
||||
of the extruder beyond the basic extruder formula. In the ideal case,
|
||||
as an extrusion move progresses, the same volume of filament should be
|
||||
deposited at each point along the move and there should be no volume
|
||||
extruded after the move. Unfortunately, it's common to find that the
|
||||
basic extrusion formulas cause too little filament to exit the
|
||||
extruder at the start of extrusion moves and for excess filament to
|
||||
extrude after extrusion ends. This is often referred to as "ooze".
|
||||
|
||||

|
||||
|
||||
The "pressure advance" system attempts to account for this by using a
|
||||
different model for the extruder. Instead of naively believing that
|
||||
each mm^3 of filament fed into the extruder will result in that amount
|
||||
of mm^3 immediately exiting the extruder, it uses a model based on
|
||||
pressure. Pressure increases when filament is pushed into the extruder
|
||||
(as in [Hooke's law](https://en.wikipedia.org/wiki/Hooke%27s_law)) and
|
||||
the pressure necessary to extrude is dominated by the flow rate
|
||||
through the nozzle orifice (as in
|
||||
[Poiseuille's law](https://en.wikipedia.org/wiki/Poiseuille_law)). The
|
||||
key idea is that the relationship between filament, pressure, and flow
|
||||
rate can be modeled using a linear coefficient:
|
||||
```
|
||||
pa_position = nominal_position + pressure_advance_coefficient * nominal_velocity
|
||||
```
|
||||
|
||||
See the [pressure advance](Pressure_Advance.md) document for
|
||||
information on how to find this pressure advance coefficient.
|
||||
|
||||
The basic pressure advance formula can cause the extruder motor to
|
||||
make sudden velocity changes. Klipper implements "smoothing" of the
|
||||
extruder movement to avoid this.
|
||||
|
||||

|
||||
|
||||
The above graph shows an example of two extrusion moves with a
|
||||
non-zero cornering velocity between them. Note that the pressure
|
||||
advance system causes additional filament to be pushed into the
|
||||
extruder during acceleration. The higher the desired filament flow
|
||||
rate, the more filament must be pushed in during acceleration to
|
||||
account for pressure. During head deceleration the extra filament is
|
||||
retracted (the extruder will have a negative velocity).
|
||||
|
||||
The "smoothing" is implemented using a weighted average of the
|
||||
extruder position over a small time period (as specified by the
|
||||
`pressure_advance_smooth_time` config parameter). This averaging can
|
||||
span multiple g-code moves. Note how the extruder motor will start
|
||||
moving prior to the nominal start of the first extrusion move and will
|
||||
continue to move after the nominal end of the last extrusion move.
|
||||
|
||||
Key formula for "smoothed pressure advance":
|
||||
```
|
||||
smooth_pa_position(t) =
|
||||
( definitive_integral(pa_position(x) * (smooth_time/2 - abs(t - x)) * dx,
|
||||
from=t-smooth_time/2, to=t+smooth_time/2)
|
||||
/ (smooth_time/2)^2 )
|
||||
```
|
||||
293
docs/MCU_Commands.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# MCU commands
|
||||
|
||||
This document provides information on the low-level micro-controller
|
||||
commands that are sent from the Klipper "host" software and processed
|
||||
by the Klipper micro-controller software. This document is not an
|
||||
authoritative reference for these commands, nor is it an exclusive
|
||||
list of all available commands.
|
||||
|
||||
This document may be useful for developers interested in understanding
|
||||
the low-level micro-controller commands.
|
||||
|
||||
See the [protocol](Protocol.md) document for more information on the
|
||||
format of commands and their transmission. The commands here are
|
||||
described using their "printf" style syntax - for those unfamiliar
|
||||
with that format, just note that where a '%...' sequence is seen it
|
||||
should be replaced with an actual integer. For example, a description
|
||||
with "count=%c" could be replaced with the text "count=10". Note that
|
||||
parameters that are considered "enumerations" (see the above protocol
|
||||
document) take a string value which is automatically converted to an
|
||||
integer value for the micro-controller. This is common with parameters
|
||||
named "pin" (or that have a suffix of "_pin").
|
||||
|
||||
## Startup Commands
|
||||
|
||||
It may be necessary to take certain one-time actions to configure the
|
||||
micro-controller and its peripherals. This section lists common
|
||||
commands available for that purpose. Unlike most micro-controller
|
||||
commands, these commands run as soon as they are received and they do
|
||||
not require any particular setup.
|
||||
|
||||
Common startup commands:
|
||||
|
||||
* `set_digital_out pin=%u value=%c` : This command immediately
|
||||
configures the given pin as a digital out GPIO and it sets it to
|
||||
either a low level (value=0) or a high level (value=1). This command
|
||||
may be useful for configuring the initial value of LEDs and for
|
||||
configuring the initial value of stepper driver micro-stepping pins.
|
||||
|
||||
* `set_pwm_out pin=%u cycle_ticks=%u value=%hu` : This command will
|
||||
immediately configure the given pin to use hardware based
|
||||
pulse-width-modulation (PWM) with the given number of
|
||||
cycle_ticks. The "cycle_ticks" is the number of MCU clock ticks each
|
||||
power on and power off cycle should last. A cycle_ticks value of 1
|
||||
can be used to request the fastest possible cycle time. The "value"
|
||||
parameter is between 0 and 255 with 0 indicating a full off state
|
||||
and 255 indicating a full on state. This command may be useful for
|
||||
enabling CPU and nozzle cooling fans.
|
||||
|
||||
## Low-level micro-controller configuration
|
||||
|
||||
Most commands in the micro-controller require an initial setup before
|
||||
they can be successfully invoked. This section provides an overview of
|
||||
the configuration process. This section and the following sections are
|
||||
likely only of interest to developers interested in the internal
|
||||
details of Klipper.
|
||||
|
||||
When the host first connects to the micro-controller it always starts
|
||||
by obtaining a data dictionary (see [protocol](Protocol.md) for more
|
||||
information). After the data dictionary is obtained the host will
|
||||
check if the micro-controller is in a "configured" state and configure
|
||||
it if not. Configuration involves the following phases:
|
||||
|
||||
* `get_config` : The host starts by checking if the micro-controller
|
||||
is already configured. The micro-controller responds to this command
|
||||
with a "config" response message. The micro-controller software
|
||||
always starts in an unconfigured state at power-on. It remains in
|
||||
this state until the host completes the configuration processes (by
|
||||
issuing a finalize_config command). If the micro-controller is
|
||||
already configured from a previous session (and is configured with
|
||||
the desired settings) then no further action is needed by the host
|
||||
and the configuration process ends successfully.
|
||||
|
||||
* `allocate_oids count=%c` : This command is issued to inform the
|
||||
micro-controller of the maximum number of object-ids (oid) that the
|
||||
host requires. It is only valid to issue this command once. An oid
|
||||
is an integer identifier allocated to each stepper, each endstop,
|
||||
and each schedulable gpio pin. The host determines in advance the
|
||||
number of oids it will require to operate the hardware and passes
|
||||
this to the micro-controller so that it may allocate sufficient
|
||||
memory to store a mapping from oid to internal object.
|
||||
|
||||
* `config_XXX oid=%c ...` : By convention any command starting with
|
||||
the "config_" prefix creates a new micro-controller object and
|
||||
assigns the given oid to it. For example, the config_digital_out
|
||||
command will configure the specified pin as a digital output GPIO
|
||||
and create an internal object that the host can use to schedule
|
||||
changes to the given GPIO. The oid parameter passed into the config
|
||||
command is selected by the host and must be between zero and the
|
||||
maximum count supplied in the allocate_oids command. The config
|
||||
commands may only be run when the micro-controller is not in a
|
||||
configured state (ie, prior to the host sending finalize_config) and
|
||||
after the allocate_oids command has been sent.
|
||||
|
||||
* `finalize_config crc=%u` : The finalize_config command transitions
|
||||
the micro-controller from an unconfigured state to a configured
|
||||
state. The crc parameter passed to the micro-controller is stored
|
||||
and provided back to the host in "config" response messages. By
|
||||
convention, the host takes a 32bit CRC of the configuration it will
|
||||
request and at the start of subsequent communication sessions it
|
||||
checks that the CRC stored in the micro-controller exactly matches
|
||||
its desired CRC. If the CRC does not match then the host knows the
|
||||
micro-controller has not been configured in the state desired by the
|
||||
host.
|
||||
|
||||
### Common micro-controller objects
|
||||
|
||||
This section lists some commonly used config commands.
|
||||
|
||||
* `config_digital_out oid=%c pin=%u value=%c default_value=%c
|
||||
max_duration=%u` : This command creates an internal micro-controller
|
||||
object for the given GPIO 'pin'. The pin will be configured in
|
||||
digital output mode and set to an initial value as specified by
|
||||
'value' (0 for low, 1 for high). Creating a digital_out object
|
||||
allows the host to schedule GPIO updates for the given pin at
|
||||
specified times (see the queue_digital_out command described below).
|
||||
Should the micro-controller software go into shutdown mode then all
|
||||
configured digital_out objects will be set to 'default_value'. The
|
||||
'max_duration' parameter is used to implement a safety check - if it
|
||||
is non-zero then it is the maximum number of clock ticks that the
|
||||
host may set the given GPIO to a non-default value without further
|
||||
updates. For example, if the default_value is zero and the
|
||||
max_duration is 16000 then if the host sets the gpio to a value of
|
||||
one then it must schedule another update to the gpio pin (to either
|
||||
zero or one) within 16000 clock ticks. This safety feature can be
|
||||
used with heater pins to ensure the host does not enable the heater
|
||||
and then go off-line.
|
||||
|
||||
* `config_pwm_out oid=%c pin=%u cycle_ticks=%u value=%hu
|
||||
default_value=%hu max_duration=%u` : This command creates an
|
||||
internal object for hardware based PWM pins that the host may
|
||||
schedule updates for. Its usage is analogous to config_digital_out -
|
||||
see the description of the 'set_pwm_out' and 'config_digital_out'
|
||||
commands for parameter description.
|
||||
|
||||
* `config_analog_in oid=%c pin=%u` : This command is used to configure
|
||||
a pin in analog input sampling mode. Once configured, the pin can be
|
||||
sampled at regular interval using the query_analog_in command (see
|
||||
below).
|
||||
|
||||
* `config_stepper oid=%c step_pin=%c dir_pin=%c invert_step=%c
|
||||
step_pulse_ticks=%u` : This command creates an internal stepper
|
||||
object. The 'step_pin' and 'dir_pin' parameters specify the step and
|
||||
direction pins respectively; this command will configure them in
|
||||
digital output mode. The 'invert_step' parameter specifies whether a
|
||||
step occurs on a rising edge (invert_step=0) or falling edge
|
||||
(invert_step=1). The 'step_pulse_ticks' parameter specifies the
|
||||
minimum duration of the step pulse. If the mcu exports the constant
|
||||
'STEPPER_BOTH_EDGE=1' then setting step_pulse_ticks=0 and
|
||||
invert_step=-1 will setup for stepping on both the rising and
|
||||
falling edges of the step pin.
|
||||
|
||||
* `config_endstop oid=%c pin=%c pull_up=%c stepper_count=%c` : This
|
||||
command creates an internal "endstop" object. It is used to specify
|
||||
the endstop pins and to enable "homing" operations (see the
|
||||
endstop_home command below). The command will configure the
|
||||
specified pin in digital input mode. The 'pull_up' parameter
|
||||
determines whether hardware provided pullup resistors for the pin
|
||||
(if available) will be enabled. The 'stepper_count' parameter
|
||||
specifies the maximum number of steppers that this endstop may need
|
||||
to halt during a homing operation (see endstop_home below).
|
||||
|
||||
* `config_spi oid=%c bus=%u pin=%u mode=%u rate=%u shutdown_msg=%*s` :
|
||||
This command creates an internal SPI object. It is used with
|
||||
spi_transfer and spi_send commands (see below). The "bus"
|
||||
identifies the SPI bus to use (if the micro-controller has more than
|
||||
one SPI bus available). The "pin" specifies the chip select (CS) pin
|
||||
for the device. The "mode" is the SPI mode (should be between 0 and
|
||||
3). The "rate" parameter specifies the SPI bus rate (in cycles per
|
||||
second). Finally, the "shutdown_msg" is an SPI command to send to
|
||||
the given device should the micro-controller go into a shutdown
|
||||
state.
|
||||
|
||||
* `config_spi_without_cs oid=%c bus=%u mode=%u rate=%u
|
||||
shutdown_msg=%*s` : This command is similar to config_spi, but
|
||||
without a CS pin definition. It is useful for SPI devices that do
|
||||
not have a chip select line.
|
||||
|
||||
## Common commands
|
||||
|
||||
This section lists some commonly used run-time commands. It is likely
|
||||
only of interest to developers looking to gain insight into Klipper.
|
||||
|
||||
* `set_digital_out_pwm_cycle oid=%c cycle_ticks=%u` : This command
|
||||
configures a digital output pin (as created by config_digital_out)
|
||||
to use "software PWM". The 'cycle_ticks' is the number of clock
|
||||
ticks for the PWM cycle. Because the output switching is implemented
|
||||
in the micro-controller software, it is recommended that
|
||||
'cycle_ticks' correspond to a time of 10ms or greater.
|
||||
|
||||
* `queue_digital_out oid=%c clock=%u on_ticks=%u` : This command will
|
||||
schedule a change to a digital output GPIO pin at the given clock
|
||||
time. To use this command a 'config_digital_out' command with the
|
||||
same 'oid' parameter must have been issued during micro-controller
|
||||
configuration. If 'set_digital_out_pwm_cycle' has been called then
|
||||
'on_ticks' is the on duration (in clock ticks) for the pwm cycle.
|
||||
Otherwise, 'on_ticks' should be either 0 (for low voltage) or 1 (for
|
||||
high voltage).
|
||||
|
||||
* `queue_pwm_out oid=%c clock=%u value=%hu` : Schedules a change to a
|
||||
hardware PWM output pin. See the 'queue_digital_out' and
|
||||
'config_pwm_out' commands for more info.
|
||||
|
||||
* `query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c
|
||||
rest_ticks=%u min_value=%hu max_value=%hu` : This command sets up a
|
||||
recurring schedule of analog input samples. To use this command a
|
||||
'config_analog_in' command with the same 'oid' parameter must have
|
||||
been issued during micro-controller configuration. The samples will
|
||||
start as of 'clock' time, it will report on the obtained value every
|
||||
'rest_ticks' clock ticks, it will over-sample 'sample_count' number
|
||||
of times, and it will pause 'sample_ticks' number of clock ticks
|
||||
between over-sample samples. The 'min_value' and 'max_value'
|
||||
parameters implement a safety feature - the micro-controller
|
||||
software will verify the sampled value (after any oversampling) is
|
||||
always between the supplied range. This is intended for use with
|
||||
pins attached to thermistors controlling heaters - it can be used to
|
||||
check that a heater is within a temperature range.
|
||||
|
||||
* `get_clock` : This command causes the micro-controller to generate a
|
||||
"clock" response message. The host sends this command once a second
|
||||
to obtain the value of the micro-controller clock and to estimate
|
||||
the drift between host and micro-controller clocks. It enables the
|
||||
host to accurately estimate the micro-controller clock.
|
||||
|
||||
### Stepper commands
|
||||
|
||||
* `queue_step oid=%c interval=%u count=%hu add=%hi` : This command
|
||||
schedules 'count' number of steps for the given stepper, with
|
||||
'interval' number of clock ticks between each step. The first step
|
||||
will be 'interval' number of clock ticks since the last scheduled
|
||||
step for the given stepper. If 'add' is non-zero then the interval
|
||||
will be adjusted by 'add' amount after each step. This command
|
||||
appends the given interval/count/add sequence to a per-stepper
|
||||
queue. There may be hundreds of these sequences queued during normal
|
||||
operation. New sequence are appended to the end of the queue and as
|
||||
each sequence completes its 'count' number of steps it is popped
|
||||
from the front of the queue. This system allows the micro-controller
|
||||
to queue potentially hundreds of thousands of steps - all with
|
||||
reliable and predictable schedule times.
|
||||
|
||||
* `set_next_step_dir oid=%c dir=%c` : This command specifies the value
|
||||
of the dir_pin that the next queue_step command will use.
|
||||
|
||||
* `reset_step_clock oid=%c clock=%u` : Normally, step timing is
|
||||
relative to the last step for a given stepper. This command resets
|
||||
the clock so that the next step is relative to the supplied 'clock'
|
||||
time. The host usually only sends this command at the start of a
|
||||
print.
|
||||
|
||||
* `stepper_get_position oid=%c` : This command causes the
|
||||
micro-controller to generate a "stepper_position" response message
|
||||
with the stepper's current position. The position is the total
|
||||
number of steps generated with dir=1 minus the total number of steps
|
||||
generated with dir=0.
|
||||
|
||||
* `endstop_home oid=%c clock=%u sample_ticks=%u sample_count=%c
|
||||
rest_ticks=%u pin_value=%c` : This command is used during stepper
|
||||
"homing" operations. To use this command a 'config_endstop' command
|
||||
with the same 'oid' parameter must have been issued during
|
||||
micro-controller configuration. When this command is invoked, the
|
||||
micro-controller will sample the endstop pin every 'rest_ticks'
|
||||
clock ticks and check if it has a value equal to 'pin_value'. If the
|
||||
value matches (and it continues to match for 'sample_count'
|
||||
additional samples spread 'sample_ticks' apart) then the movement
|
||||
queue for the associated stepper will be cleared and the stepper
|
||||
will come to an immediate halt. The host uses this command to
|
||||
implement homing - the host instructs the endstop to sample for the
|
||||
endstop trigger and then it issues a series of queue_step commands
|
||||
to move a stepper towards the endstop. Once the stepper hits the
|
||||
endstop, the trigger will be detected, the movement halted, and the
|
||||
host notified.
|
||||
|
||||
### Move queue
|
||||
|
||||
Each queue_step command utilizes an entry in the micro-controller
|
||||
"move queue". This queue is allocated when it receives the
|
||||
"finalize_config" command, and it reports the number of available
|
||||
queue entries in "config" response messages.
|
||||
|
||||
It is the responsibility of the host to ensure that there is available
|
||||
space in the queue before sending a queue_step command. The host does
|
||||
this by calculating when each queue_step command completes and
|
||||
scheduling new queue_step commands accordingly.
|
||||
|
||||
### SPI Commands
|
||||
|
||||
* `spi_transfer oid=%c data=%*s` : This command causes the
|
||||
micro-controller to send 'data' to the spi device specified by 'oid'
|
||||
and it generates a "spi_transfer_response" response message with the
|
||||
data returned during the transmission.
|
||||
|
||||
* `spi_send oid=%c data=%*s` : This command is similar to
|
||||
"spi_transfer", but it does not generate a "spi_transfer_response"
|
||||
message.
|
||||
215
docs/Manual_Level.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# Manual leveling
|
||||
|
||||
This document describes tools for calibrating a Z endstop and for
|
||||
performing adjustments to bed leveling screws.
|
||||
|
||||
## Calibrating a Z endstop
|
||||
|
||||
An accurate Z endstop position is critical to obtaining high quality
|
||||
prints.
|
||||
|
||||
Note, though, the accuracy of the Z endstop switch itself can be a
|
||||
limiting factor. If one is using Trinamic stepper motor drivers then
|
||||
consider enabling [endstop phase](Endstop_Phase.md) detection to
|
||||
improve the accuracy of the switch.
|
||||
|
||||
To perform a Z endstop calibration, home the printer, command the head
|
||||
to move to a Z position that is at least five millimeters above the
|
||||
bed (if it is not already), command the head to move to an XY position
|
||||
near the center of the bed, then navigate to the OctoPrint terminal
|
||||
tab and run:
|
||||
```
|
||||
Z_ENDSTOP_CALIBRATE
|
||||
```
|
||||
Then follow the steps described at
|
||||
["the paper test"](Bed_Level.md#the-paper-test) to determine the
|
||||
actual distance between the nozzle and bed at the given location. Once
|
||||
those steps are complete one can `ACCEPT` the position and save the
|
||||
results to the config file with:
|
||||
```
|
||||
SAVE_CONFIG
|
||||
```
|
||||
|
||||
It's preferable to use a Z endstop switch on the opposite end of the Z
|
||||
axis from the bed. (Homing away from the bed is more robust as then it
|
||||
is generally always safe to home the Z.) However, if one must home
|
||||
towards the bed it is recommended to adjust the endstop so that it
|
||||
triggers a small distance (eg, .5mm) above the bed. Almost all endstop
|
||||
switches can safely be depressed a small distance beyond their trigger
|
||||
point. When this is done, one should find that the
|
||||
`Z_ENDSTOP_CALIBRATE` command reports a small positive value (eg,
|
||||
.5mm) for the Z position_endstop. Triggering the endstop while it is
|
||||
still some distance from the bed reduces the risk of inadvertent bed
|
||||
crashes.
|
||||
|
||||
Some printers have the ability to manually adjust the location of the
|
||||
physical endstop switch. However, it's recommended to perform Z
|
||||
endstop positioning in software with Klipper - once the physical
|
||||
location of the endstop is in a convenient location, one can make any
|
||||
further adjustments by running Z_ENDSTOP_CALIBRATE or by manually
|
||||
updating the Z position_endstop in the configuration file.
|
||||
|
||||
## Adjusting bed leveling screws
|
||||
|
||||
The secret to getting good bed leveling with bed leveling screws is to
|
||||
utilize the printer's high precision motion system during the bed
|
||||
leveling process itself. This is done by commanding the nozzle to a
|
||||
position near each bed screw and then adjusting that screw until the
|
||||
bed is a set distance from the nozzle. Klipper has a tool to assist
|
||||
with this. In order to use the tool it is necessary to specify each
|
||||
screw XY location.
|
||||
|
||||
This is done by creating a `[bed_screws]` config section. For example,
|
||||
it might look something similar to:
|
||||
```
|
||||
[bed_screws]
|
||||
screw1: 100, 50
|
||||
screw2: 100, 150
|
||||
screw3: 150, 100
|
||||
```
|
||||
|
||||
If a bed screw is under the bed, then specify the XY position directly
|
||||
above the screw. If the screw is outside the bed then specify an XY
|
||||
position closest to the screw that is still within the range of the
|
||||
bed.
|
||||
|
||||
Once the config file is ready, run `RESTART` to load that config, and
|
||||
then one can start the tool by running:
|
||||
```
|
||||
BED_SCREWS_ADJUST
|
||||
```
|
||||
|
||||
This tool will move the printer's nozzle to each screw XY location
|
||||
and then move the nozzle to a Z=0 height. At this point one can use the
|
||||
"paper test" to adjust the bed screw directly under the nozzle. See
|
||||
the information described in
|
||||
["the paper test"](Bed_Level.md#the-paper-test), but adjust the bed
|
||||
screw instead of commanding the nozzle to different heights. Adjust
|
||||
the bed screw until there is a small amount of friction when pushing
|
||||
the paper back and forth.
|
||||
|
||||
Once the screw is adjusted so that a small amount of friction is felt,
|
||||
run either the `ACCEPT` or `ADJUSTED` command. Use the `ADJUSTED`
|
||||
command if the bed screw needed an adjustment (typically anything more
|
||||
than about 1/8th of a turn of the screw). Use the `ACCEPT` command if
|
||||
no significant adjustment is necessary. Both commands will cause the
|
||||
tool to proceed to the next screw. (When an `ADJUSTED` command is
|
||||
used, the tool will schedule an additional cycle of bed screw
|
||||
adjustments; the tool completes successfully when all bed screws are
|
||||
verified to not require any significant adjustments.) One can use the
|
||||
`ABORT` command to exit the tool early.
|
||||
|
||||
This system works best when the printer has a flat printing surface
|
||||
(such as glass) and has straight rails. Upon successful completion of
|
||||
the bed leveling tool the bed should be ready for printing.
|
||||
|
||||
### Fine grained bed screw adjustments
|
||||
|
||||
If the printer uses three bed screws and all three screws are under
|
||||
the bed, then it may be possible to perform a second "high precision"
|
||||
bed leveling step. This is done by commanding the nozzle to locations
|
||||
where the bed moves a larger distance with each bed screw adjustment.
|
||||
|
||||
For example, consider a bed with screws at locations A, B, and C:
|
||||
|
||||

|
||||
|
||||
For each adjustment made to the bed screw at location C, the bed will
|
||||
swing along a pendulum defined by the remaining two bed screws (shown
|
||||
here as a green line). In this situation, each adjustment to the bed
|
||||
screw at C will move the bed at position D a further amount than
|
||||
directly at C. It is thus possible to make an improved C screw
|
||||
adjustment when the nozzle is at position D.
|
||||
|
||||
To enable this feature, one would determine the additional nozzle
|
||||
coordinates and add them to the config file. For example, it might
|
||||
look like:
|
||||
```
|
||||
[bed_screws]
|
||||
screw1: 100, 50
|
||||
screw1_fine_adjust: 0, 0
|
||||
screw2: 100, 150
|
||||
screw2_fine_adjust: 300, 300
|
||||
screw3: 150, 100
|
||||
screw3_fine_adjust: 0, 100
|
||||
```
|
||||
|
||||
When this feature is enabled, the `BED_SCREWS_ADJUST` tool will first
|
||||
prompt for coarse adjustments directly above each screw position, and
|
||||
once those are accepted, it will prompt for fine adjustments at the
|
||||
additional locations. Continue to use `ACCEPT` and `ADJUSTED` at each
|
||||
position.
|
||||
|
||||
## Adjusting bed leveling screws using the bed probe
|
||||
|
||||
This is another way to calibrate the bed level using the bed probe. To
|
||||
use it you must have a Z probe (BL Touch, Inductive sensor, etc).
|
||||
|
||||
To enable this feature, one would determine the nozzle coordinates
|
||||
such that the Z probe is above the screws, and then add them to the
|
||||
config file. For example, it might look like:
|
||||
|
||||
```
|
||||
[screws_tilt_adjust]
|
||||
screw1: -5, 30
|
||||
screw1_name: front left screw
|
||||
screw2: 155, 30
|
||||
screw2_name: front right screw
|
||||
screw3: 155, 190
|
||||
screw3_name: rear right screw
|
||||
screw4: -5, 190
|
||||
screw4_name: rear left screw
|
||||
horizontal_move_z: 10.
|
||||
speed: 50.
|
||||
screw_thread: CW-M3
|
||||
```
|
||||
|
||||
The screw1 is always the reference point for the others, so the system
|
||||
assumes that screw1 is at the correct height. Always run `G28` first
|
||||
and then run `SCREWS_TILT_CALCULATE` - it should produce output
|
||||
similar to:
|
||||
```
|
||||
Send: G28
|
||||
Recv: ok
|
||||
Send: SCREWS_TILT_CALCULATE
|
||||
Recv: // 01:20 means 1 full turn and 20 minutes, CW=clockwise, CCW=counter-clockwise
|
||||
Recv: // front left screw (base) : x=-5.0, y=30.0, z=2.48750
|
||||
Recv: // front right screw : x=155.0, y=30.0, z=2.36000 : adjust CW 01:15
|
||||
Recv: // rear right screw : y=155.0, y=190.0, z=2.71500 : adjust CCW 00:50
|
||||
Recv: // read left screw : x=-5.0, y=190.0, z=2.47250 : adjust CW 00:02
|
||||
Recv: ok
|
||||
```
|
||||
|
||||
This means that:
|
||||
- front left screw is the reference point you must not change it.
|
||||
- front right screw must be turned clockwise 1 full turn and a quarter turn
|
||||
- rear right screw must be turned counter-clockwise 50 minutes
|
||||
- rear left screw must be turned clockwise 2 minutes (not need it's ok)
|
||||
|
||||
Note that "minutes" refers to "minutes of a clock face". So, for
|
||||
example, 15 minutes is a quarter of a full turn.
|
||||
|
||||
Repeat the process several times until you get a good level bed -
|
||||
normally when all adjustments are below 6 minutes.
|
||||
|
||||
If using a probe that is mounted on the side of the hotend (that is,
|
||||
it has an X or Y offset) then note that adjusting the bed tilt will
|
||||
invalidate any previous probe calibration that was performed with a
|
||||
tilted bed. Be sure to run [probe calibration](Probe_Calibrate.md)
|
||||
after the bed screws have been adjusted.
|
||||
|
||||
The `MAX_DEVIATION` parameter is useful when a saved bed mesh is used,
|
||||
to ensure that the bed level has not drifted too far from where it was when
|
||||
the mesh was created. For example, `SCREWS_TILT_CALCULATE MAX_DEVIATION=0.01`
|
||||
can be added to the custom start gcode of the slicer before the mesh is loaded.
|
||||
It will abort the print if the configured limit is exceeded (0.01mm in this
|
||||
example), giving the user a chance to adjust the screws and restart the print.
|
||||
|
||||
The `DIRECTION` parameter is useful if you can turn your bed adjustment
|
||||
screws in one direction only. For example, you might have screws that start
|
||||
tightened in their lowest (or highest) possible position, which can only be
|
||||
turned in a single direction, to raise (or lower) the bed. If you can only
|
||||
turn the screws clockwise, run `SCREWS_TILT_CALCULATE DIRECTION=CW`. If you can
|
||||
only turn them counter-clockwise, run `SCREWS_TILT_CALCULATE DIRECTION=CCW`.
|
||||
A suitable reference point will be chosen such that the bed can be leveled
|
||||
by turning all the screws in the given direction.
|
||||
560
docs/Measuring_Resonances.md
Normal file
@@ -0,0 +1,560 @@
|
||||
# Measuring Resonances
|
||||
|
||||
Klipper has built-in support for ADXL345 accelerometer, which can be used to
|
||||
measure resonance frequencies of the printer for different axes, and auto-tune
|
||||
[input shapers](Resonance_Compensation.md) to compensate for resonances.
|
||||
Note that using ADXL345 requires some soldering and crimping. ADXL345 can be
|
||||
connected to a Raspberry Pi directly, or to an SPI interface of an MCU
|
||||
board (it needs to be reasonably fast).
|
||||
|
||||
When sourcing ADXL345, be aware that there is a variety of different PCB
|
||||
board designs and different clones of them. Make sure that the board supports
|
||||
SPI mode (small number of boards appear to be hard-configured for I2C by
|
||||
pulling SDO to GND), and, if it is going to be connected to a 5V printer MCU,
|
||||
that it has a voltage regulator and a level shifter.
|
||||
|
||||
|
||||
## Installation instructions
|
||||
|
||||
### Wiring
|
||||
|
||||
You need to connect ADXL345 to your Raspberry Pi via SPI. Note that the I2C
|
||||
connection, which is suggested by ADXL345 documentation, has too low throughput
|
||||
and **will not work**. The recommended connection scheme:
|
||||
|
||||
| ADXL345 pin | RPi pin | RPi pin name |
|
||||
|:--:|:--:|:--:|
|
||||
| 3V3 (or VCC) | 01 | 3.3v DC power |
|
||||
| GND | 06 | Ground |
|
||||
| CS | 24 | GPIO08 (SPI0_CE0_N) |
|
||||
| SDO | 21 | GPIO09 (SPI0_MISO) |
|
||||
| SDA | 19 | GPIO10 (SPI0_MOSI) |
|
||||
| SCL | 23 | GPIO11 (SPI0_SCLK) |
|
||||
|
||||
An alternative to the ADXL345 is the MPU-9250 (or MPU-6050). This
|
||||
accelerometer has been tested to work over I2C on the RPi at 400kbaud.
|
||||
Recommended connection scheme for I2C:
|
||||
|
||||
| MPU-9250 pin | RPi pin | RPi pin name |
|
||||
|:--:|:--:|:--:|
|
||||
| 3V3 (or VCC) | 01 | 3.3v DC power |
|
||||
| GND | 09 | Ground |
|
||||
| SDA | 03 | GPIO02 (SDA1) |
|
||||
| SCL | 05 | GPIO03 (SCL1) |
|
||||
|
||||
|
||||
Fritzing wiring diagrams for some of the ADXL345 boards:
|
||||
|
||||

|
||||
|
||||
|
||||
Double-check your wiring before powering up the Raspberry Pi to prevent
|
||||
damaging it or the accelerometer.
|
||||
|
||||
### Mounting the accelerometer
|
||||
|
||||
The accelerometer must be attached to the toolhead. One needs to design a proper
|
||||
mount that fits their own 3D printer. It is better to align the axes of the
|
||||
accelerometer with the printer's axes (but if it makes it more convenient,
|
||||
axes can be swapped - i.e. no need to align X axis with X and so forth - it
|
||||
should be fine even if Z axis of accelerometer is X axis of the printer, etc.).
|
||||
|
||||
An example of mounting ADXL345 on the SmartEffector:
|
||||
|
||||

|
||||
|
||||
Note that on a bed slinger printer one must design 2 mounts: one for the
|
||||
toolhead and one for the bed, and run the measurements twice. See the
|
||||
corresponding [section](#bed-slinger-printers) for more details.
|
||||
|
||||
**Attention:** make sure the accelerometer and any screws that hold it in
|
||||
place do not touch any metal parts of the printer. Basically, the mount must
|
||||
be designed such as to ensure the electrical isolation of the accelerometer
|
||||
from the printer frame. Failing to ensure that can create a ground loop in
|
||||
the system that may damage the electronics.
|
||||
|
||||
### Software installation
|
||||
|
||||
Note that resonance measurements and shaper auto-calibration require additional
|
||||
software dependencies not installed by default. First, run on your Raspberry Pi
|
||||
the following commands:
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install python3-numpy python3-matplotlib libatlas-base-dev
|
||||
```
|
||||
|
||||
Next, in order to install NumPy in the Klipper environment, run the command:
|
||||
```
|
||||
~/klippy-env/bin/pip install -v numpy
|
||||
```
|
||||
Note that, depending on the performance of the CPU, it may take *a lot*
|
||||
of time, up to 10-20 minutes. Be patient and wait for the completion of
|
||||
the installation. On some occasions, if the board has too little RAM
|
||||
the installation may fail and you will need to enable swap.
|
||||
|
||||
Afterwards, check and follow the instructions in the
|
||||
[RPi Microcontroller document](RPi_microcontroller.md) to setup the
|
||||
"linux mcu" on the Raspberry Pi.
|
||||
|
||||
Make sure the Linux SPI driver is enabled by running `sudo
|
||||
raspi-config` and enabling SPI under the "Interfacing options" menu.
|
||||
|
||||
For the ADXL345, add the following to the printer.cfg file:
|
||||
```
|
||||
[mcu rpi]
|
||||
serial: /tmp/klipper_host_mcu
|
||||
|
||||
[adxl345]
|
||||
cs_pin: rpi:None
|
||||
|
||||
[resonance_tester]
|
||||
accel_chip: adxl345
|
||||
probe_points:
|
||||
100, 100, 20 # an example
|
||||
```
|
||||
It is advised to start with 1 probe point, in the middle of the print bed,
|
||||
slightly above it.
|
||||
|
||||
For the MPU-9250, make sure the Linux I2C driver is enabled and the baud rate is
|
||||
set to 400000 (see [Enabling I2C](RPi_microcontroller.md#optional-enabling-i2c)
|
||||
section for more details). Then, add the following to the printer.cfg:
|
||||
```
|
||||
[mcu rpi]
|
||||
serial: /tmp/klipper_host_mcu
|
||||
|
||||
[mpu9250]
|
||||
i2c_mcu: rpi
|
||||
i2c_bus: i2c.1
|
||||
|
||||
[resonance_tester]
|
||||
accel_chip: mpu9250
|
||||
probe_points:
|
||||
100, 100, 20 # an example
|
||||
```
|
||||
|
||||
Restart Klipper via the `RESTART` command.
|
||||
|
||||
## Measuring the resonances
|
||||
|
||||
### Checking the setup
|
||||
|
||||
Now you can test a connection.
|
||||
|
||||
- For "non bed-slingers" (e.g. one accelerometer), in Octoprint,
|
||||
enter `ACCELEROMETER_QUERY`
|
||||
- For "bed-slingers" (e.g. more than one accelerometer), enter
|
||||
`ACCELEROMETER_QUERY CHIP=<chip>` where `<chip>` is the name of the chip
|
||||
as-entered, e.g. `CHIP=bed` (see: [bed-slinger](#bed-slinger-printers))
|
||||
for all installed accelerometer chips.
|
||||
|
||||
You should see the current measurements from the accelerometer, including the
|
||||
free-fall acceleration, e.g.
|
||||
```
|
||||
Recv: // adxl345 values (x, y, z): 470.719200, 941.438400, 9728.196800
|
||||
```
|
||||
|
||||
If you get an error like `Invalid adxl345 id (got xx vs e5)`, where `xx`
|
||||
is some other ID, it is indicative of the connection problem with ADXL345,
|
||||
or the faulty sensor. Double-check the power, the wiring (that it matches
|
||||
the schematics, no wire is broken or loose, etc.), and soldering quality.
|
||||
|
||||
Next, try running `MEASURE_AXES_NOISE` in Octoprint, you should get some
|
||||
baseline numbers for the noise of accelerometer on the axes (should be
|
||||
somewhere in the range of ~1-100). Too high axes noise (e.g. 1000 and more)
|
||||
can be indicative of the sensor issues, problems with its power, or too
|
||||
noisy imbalanced fans on a 3D printer.
|
||||
|
||||
### Measuring the resonances
|
||||
|
||||
Now you can run some real-life tests. Run the following command:
|
||||
```
|
||||
TEST_RESONANCES AXIS=X
|
||||
```
|
||||
Note that it will create vibrations on X axis. It will also disable input
|
||||
shaping if it was enabled previously, as it is not valid to run the resonance
|
||||
testing with the input shaper enabled.
|
||||
|
||||
**Attention!** Be sure to observe the printer for the first time, to make sure
|
||||
the vibrations do not become too violent (`M112` command can be used to abort
|
||||
the test in case of emergency; hopefully it will not come to this though).
|
||||
If the vibrations do get too strong, you can attempt to specify a lower than the
|
||||
default value for `accel_per_hz` parameter in `[resonance_tester]` section, e.g.
|
||||
```
|
||||
[resonance_tester]
|
||||
accel_chip: adxl345
|
||||
accel_per_hz: 50 # default is 75
|
||||
probe_points: ...
|
||||
```
|
||||
|
||||
If it works for X axis, run for Y axis as well:
|
||||
```
|
||||
TEST_RESONANCES AXIS=Y
|
||||
```
|
||||
This will generate 2 CSV files (`/tmp/resonances_x_*.csv` and
|
||||
`/tmp/resonances_y_*.csv`). These files can be processed with the stand-alone
|
||||
script on a Raspberry Pi. To do that, run the following commands:
|
||||
```
|
||||
~/klipper/scripts/calibrate_shaper.py /tmp/resonances_x_*.csv -o /tmp/shaper_calibrate_x.png
|
||||
~/klipper/scripts/calibrate_shaper.py /tmp/resonances_y_*.csv -o /tmp/shaper_calibrate_y.png
|
||||
```
|
||||
This script will generate the charts `/tmp/shaper_calibrate_x.png` and
|
||||
`/tmp/shaper_calibrate_y.png` with frequency responses. You will also get the
|
||||
suggested frequencies for each input shaper, as well as which input shaper is
|
||||
recommended for your setup. For example:
|
||||
|
||||

|
||||
```
|
||||
Fitted shaper 'zv' frequency = 34.4 Hz (vibrations = 4.0%, smoothing ~= 0.132)
|
||||
To avoid too much smoothing with 'zv', suggested max_accel <= 4500 mm/sec^2
|
||||
Fitted shaper 'mzv' frequency = 34.6 Hz (vibrations = 0.0%, smoothing ~= 0.170)
|
||||
To avoid too much smoothing with 'mzv', suggested max_accel <= 3500 mm/sec^2
|
||||
Fitted shaper 'ei' frequency = 41.4 Hz (vibrations = 0.0%, smoothing ~= 0.188)
|
||||
To avoid too much smoothing with 'ei', suggested max_accel <= 3200 mm/sec^2
|
||||
Fitted shaper '2hump_ei' frequency = 51.8 Hz (vibrations = 0.0%, smoothing ~= 0.201)
|
||||
To avoid too much smoothing with '2hump_ei', suggested max_accel <= 3000 mm/sec^2
|
||||
Fitted shaper '3hump_ei' frequency = 61.8 Hz (vibrations = 0.0%, smoothing ~= 0.215)
|
||||
To avoid too much smoothing with '3hump_ei', suggested max_accel <= 2800 mm/sec^2
|
||||
Recommended shaper is mzv @ 34.6 Hz
|
||||
```
|
||||
|
||||
The suggested configuration can be added to `[input_shaper]` section of
|
||||
`printer.cfg`, e.g.:
|
||||
```
|
||||
[input_shaper]
|
||||
shaper_freq_x: ...
|
||||
shaper_type_x: ...
|
||||
shaper_freq_y: 34.6
|
||||
shaper_type_y: mzv
|
||||
|
||||
[printer]
|
||||
max_accel: 3000 # should not exceed the estimated max_accel for X and Y axes
|
||||
```
|
||||
or you can choose some other configuration yourself based on the generated
|
||||
charts: peaks in the power spectral density on the charts correspond to
|
||||
the resonance frequencies of the printer.
|
||||
|
||||
Note that alternatively you can run the input shaper autocalibration
|
||||
from Klipper [directly](#input-shaper-auto-calibration), which can be
|
||||
convenient, for example, for the input shaper
|
||||
[re-calibration](#input-shaper-re-calibration).
|
||||
|
||||
### Bed-slinger printers
|
||||
|
||||
If your printer is a bed slinger printer, you will need to change the location
|
||||
of the accelerometer between the measurements for X and Y axes: measure the
|
||||
resonances of X axis with the accelerometer attached to the toolhead and the
|
||||
resonances of Y axis - to the bed (the usual bed slinger setup).
|
||||
|
||||
However, you can also connect two accelerometers simultaneously, though they
|
||||
must be connected to different boards (say, to an RPi and printer MCU board), or
|
||||
to two different physical SPI interfaces on the same board (rarely available).
|
||||
Then they can be configured in the following manner:
|
||||
```
|
||||
[adxl345 hotend]
|
||||
# Assuming `hotend` chip is connected to an RPi
|
||||
cs_pin: rpi:None
|
||||
|
||||
[adxl345 bed]
|
||||
# Assuming `bed` chip is connected to a printer MCU board
|
||||
cs_pin: ... # Printer board SPI chip select (CS) pin
|
||||
|
||||
[resonance_tester]
|
||||
# Assuming the typical setup of the bed slinger printer
|
||||
accel_chip_x: adxl345 hotend
|
||||
accel_chip_y: adxl345 bed
|
||||
probe_points: ...
|
||||
```
|
||||
|
||||
Then the commands `TEST_RESONANCES AXIS=X` and `TEST_RESONANCES AXIS=Y`
|
||||
will use the correct accelerometer for each axis.
|
||||
|
||||
### Max smoothing
|
||||
|
||||
Keep in mind that the input shaper can create some smoothing in parts.
|
||||
Automatic tuning of the input shaper performed by `calibrate_shaper.py`
|
||||
script or `SHAPER_CALIBRATE` command tries not to exacerbate the smoothing,
|
||||
but at the same time they try to minimize the resulting vibrations.
|
||||
Sometimes they can make a sub-optimal choice of the shaper frequency, or
|
||||
maybe you simply prefer to have less smoothing in parts at the expense of
|
||||
a larger remaining vibrations. In these cases, you can request to limit
|
||||
the maximum smoothing from the input shaper.
|
||||
|
||||
Let's consider the following results from the automatic tuning:
|
||||
|
||||

|
||||
```
|
||||
Fitted shaper 'zv' frequency = 57.8 Hz (vibrations = 20.3%, smoothing ~= 0.053)
|
||||
To avoid too much smoothing with 'zv', suggested max_accel <= 13000 mm/sec^2
|
||||
Fitted shaper 'mzv' frequency = 34.8 Hz (vibrations = 3.6%, smoothing ~= 0.168)
|
||||
To avoid too much smoothing with 'mzv', suggested max_accel <= 3600 mm/sec^2
|
||||
Fitted shaper 'ei' frequency = 48.8 Hz (vibrations = 4.9%, smoothing ~= 0.135)
|
||||
To avoid too much smoothing with 'ei', suggested max_accel <= 4400 mm/sec^2
|
||||
Fitted shaper '2hump_ei' frequency = 45.2 Hz (vibrations = 0.1%, smoothing ~= 0.264)
|
||||
To avoid too much smoothing with '2hump_ei', suggested max_accel <= 2200 mm/sec^2
|
||||
Fitted shaper '3hump_ei' frequency = 48.0 Hz (vibrations = 0.0%, smoothing ~= 0.356)
|
||||
To avoid too much smoothing with '3hump_ei', suggested max_accel <= 1500 mm/sec^2
|
||||
Recommended shaper is 2hump_ei @ 45.2 Hz
|
||||
```
|
||||
Note that the reported `smoothing` values are some abstract projected values.
|
||||
These values can be used to compare different configurations: the higher the
|
||||
value, the more smoothing a shaper will create. However, these smoothing scores
|
||||
do not represent any real measure of smoothing, because the actual smoothing
|
||||
depends on [`max_accel`](#selecting-max-accel) and `square_corner_velocity`
|
||||
parameters. Therefore, you should print some test prints to see how much
|
||||
smoothing exactly a chosen configuration creates.
|
||||
|
||||
In the example above the suggested shaper parameters are not bad, but what if
|
||||
you want to get less smoothing on the X axis? You can try to limit the maximum
|
||||
shaper smoothing using the following command:
|
||||
```
|
||||
~/klipper/scripts/calibrate_shaper.py /tmp/resonances_x_*.csv -o /tmp/shaper_calibrate_x.png --max_smoothing=0.2
|
||||
```
|
||||
which limits the smoothing to 0.2 score. Now you can get the following result:
|
||||
|
||||

|
||||
```
|
||||
Fitted shaper 'zv' frequency = 55.4 Hz (vibrations = 19.7%, smoothing ~= 0.057)
|
||||
To avoid too much smoothing with 'zv', suggested max_accel <= 12000 mm/sec^2
|
||||
Fitted shaper 'mzv' frequency = 34.6 Hz (vibrations = 3.6%, smoothing ~= 0.170)
|
||||
To avoid too much smoothing with 'mzv', suggested max_accel <= 3500 mm/sec^2
|
||||
Fitted shaper 'ei' frequency = 48.2 Hz (vibrations = 4.8%, smoothing ~= 0.139)
|
||||
To avoid too much smoothing with 'ei', suggested max_accel <= 4300 mm/sec^2
|
||||
Fitted shaper '2hump_ei' frequency = 52.0 Hz (vibrations = 2.7%, smoothing ~= 0.200)
|
||||
To avoid too much smoothing with '2hump_ei', suggested max_accel <= 3000 mm/sec^2
|
||||
Fitted shaper '3hump_ei' frequency = 72.6 Hz (vibrations = 1.4%, smoothing ~= 0.155)
|
||||
To avoid too much smoothing with '3hump_ei', suggested max_accel <= 3900 mm/sec^2
|
||||
Recommended shaper is 3hump_ei @ 72.6 Hz
|
||||
```
|
||||
|
||||
If you compare to the previously suggested parameters, the vibrations are a bit
|
||||
larger, but the smoothing is significantly smaller than previously, allowing
|
||||
larger maximum acceleration.
|
||||
|
||||
When deciding which `max_smoothing` parameter to choose, you can use a
|
||||
trial-and-error approach. Try a few different values and see which results
|
||||
you get. Note that the actual smoothing produced by the input shaper depends,
|
||||
primarily, on the lowest resonance frequency of the printer: the higher
|
||||
the frequency of the lowest resonance - the smaller the smoothing. Therefore,
|
||||
if you request the script to find a configuration of the input shaper with the
|
||||
unrealistically small smoothing, it will be at the expense of increased ringing
|
||||
at the lowest resonance frequencies (which are, typically, also more prominently
|
||||
visible in prints). So, always double-check the projected remaining vibrations
|
||||
reported by the script and make sure they are not too high.
|
||||
|
||||
Note that if you chose a good `max_smoothing` value for both of your axes, you
|
||||
can store it in the `printer.cfg` as
|
||||
```
|
||||
[resonance_tester]
|
||||
accel_chip: ...
|
||||
probe_points: ...
|
||||
max_smoothing: 0.25 # an example
|
||||
```
|
||||
Then, if you [rerun](#input-shaper-re-calibration) the input shaper auto-tuning
|
||||
using `SHAPER_CALIBRATE` Klipper command in the future, it will use the stored
|
||||
`max_smoothing` value as a reference.
|
||||
|
||||
### Selecting max_accel
|
||||
|
||||
Since the input shaper can create some smoothing in parts, especially at high
|
||||
accelerations, you will still need to choose the `max_accel` value that
|
||||
does not create too much smoothing in the printed parts. A calibration script
|
||||
provides an estimate for `max_accel` parameter that should not create too much
|
||||
smoothing. Note that the `max_accel` as displayed by the calibration script is
|
||||
only a theoretical maximum at which the respective shaper is still able to work
|
||||
without producing too much smoothing. It is by no means a recommendation to set
|
||||
this acceleration for printing. The maximum acceleration your printer is able to
|
||||
sustain depends on its mechanical properties and the maximum torque of the used
|
||||
stepper motors. Therefore, it is suggested to set `max_accel` in `[printer]`
|
||||
section that does not exceed the estimated values for X and Y axes, likely with
|
||||
some conservative safety margin.
|
||||
|
||||
Alternatively, follow
|
||||
[this](Resonance_Compensation.md#selecting-max_accel) part of
|
||||
the input shaper tuning guide and print the test model to choose `max_accel`
|
||||
parameter experimentally.
|
||||
|
||||
The same notice applies to the input shaper
|
||||
[auto-calibration](#input-shaper-auto-calibration) with
|
||||
`SHAPER_CALIBRATE` command: it is still necessary to choose the right
|
||||
`max_accel` value after the auto-calibration, and the suggested acceleration
|
||||
limits will not be applied automatically.
|
||||
|
||||
If you are doing a shaper re-calibration and the reported smoothing for the
|
||||
suggested shaper configuration is almost the same as what you got during the
|
||||
previous calibration, this step can be skipped.
|
||||
|
||||
### Testing custom axes
|
||||
|
||||
`TEST_RESONANCES` command supports custom axes. While this is not really
|
||||
useful for input shaper calibration, it can be used to study printer
|
||||
resonances in-depth and to check, for example, belt tension.
|
||||
|
||||
To check the belt tension on CoreXY printers, execute
|
||||
```
|
||||
TEST_RESONANCES AXIS=1,1 OUTPUT=raw_data
|
||||
TEST_RESONANCES AXIS=1,-1 OUTPUT=raw_data
|
||||
```
|
||||
and use `graph_accelerometer.py` to process the generated files, e.g.
|
||||
```
|
||||
~/klipper/scripts/graph_accelerometer.py -c /tmp/raw_data_axis*.csv -o /tmp/resonances.png
|
||||
```
|
||||
which will generate `/tmp/resonances.png` comparing the resonances.
|
||||
|
||||
For Delta printers with the default tower placement
|
||||
(tower A ~= 210 degrees, B ~= 330 degrees, and C ~= 90 degrees), execute
|
||||
```
|
||||
TEST_RESONANCES AXIS=0,1 OUTPUT=raw_data
|
||||
TEST_RESONANCES AXIS=-0.866025404,-0.5 OUTPUT=raw_data
|
||||
TEST_RESONANCES AXIS=0.866025404,-0.5 OUTPUT=raw_data
|
||||
```
|
||||
and then use the same command
|
||||
```
|
||||
~/klipper/scripts/graph_accelerometer.py -c /tmp/raw_data_axis*.csv -o /tmp/resonances.png
|
||||
```
|
||||
to generate `/tmp/resonances.png` comparing the resonances.
|
||||
|
||||
## Input Shaper auto-calibration
|
||||
|
||||
Besides manually choosing the appropriate parameters for the input shaper
|
||||
feature, it is also possible to run the auto-tuning for the input shaper
|
||||
directly from Klipper. Run the following command via Octoprint terminal:
|
||||
```
|
||||
SHAPER_CALIBRATE
|
||||
```
|
||||
|
||||
This will run the full test for both axes and generate the csv output
|
||||
(`/tmp/calibration_data_*.csv` by default) for the frequency response
|
||||
and the suggested input shapers. You will also get the suggested
|
||||
frequencies for each input shaper, as well as which input shaper is
|
||||
recommended for your setup, on Octoprint console. For example:
|
||||
|
||||
```
|
||||
Calculating the best input shaper parameters for y axis
|
||||
Fitted shaper 'zv' frequency = 39.0 Hz (vibrations = 13.2%, smoothing ~= 0.105)
|
||||
To avoid too much smoothing with 'zv', suggested max_accel <= 5900 mm/sec^2
|
||||
Fitted shaper 'mzv' frequency = 36.8 Hz (vibrations = 1.7%, smoothing ~= 0.150)
|
||||
To avoid too much smoothing with 'mzv', suggested max_accel <= 4000 mm/sec^2
|
||||
Fitted shaper 'ei' frequency = 36.6 Hz (vibrations = 2.2%, smoothing ~= 0.240)
|
||||
To avoid too much smoothing with 'ei', suggested max_accel <= 2500 mm/sec^2
|
||||
Fitted shaper '2hump_ei' frequency = 48.0 Hz (vibrations = 0.0%, smoothing ~= 0.234)
|
||||
To avoid too much smoothing with '2hump_ei', suggested max_accel <= 2500 mm/sec^2
|
||||
Fitted shaper '3hump_ei' frequency = 59.0 Hz (vibrations = 0.0%, smoothing ~= 0.235)
|
||||
To avoid too much smoothing with '3hump_ei', suggested max_accel <= 2500 mm/sec^2
|
||||
Recommended shaper_type_y = mzv, shaper_freq_y = 36.8 Hz
|
||||
```
|
||||
If you agree with the suggested parameters, you can execute `SAVE_CONFIG`
|
||||
now to save them and restart the Klipper. Note that this will not update
|
||||
`max_accel` value in `[printer]` section. You should update it manually
|
||||
following the considerations in [Selecting max_accel](#selecting-max_accel)
|
||||
section.
|
||||
|
||||
|
||||
If your printer is a bed slinger printer, you can specify which axis
|
||||
to test, so that you can change the accelerometer mounting point between
|
||||
the tests (by default the test is performed for both axes):
|
||||
```
|
||||
SHAPER_CALIBRATE AXIS=Y
|
||||
```
|
||||
|
||||
You can execute `SAVE_CONFIG` twice - after calibrating each axis.
|
||||
|
||||
However, if you connected two accelerometers simultaneously, you simply run
|
||||
`SHAPER_CALIBRATE` without specifying an axis to calibrate the input shaper
|
||||
for both axes in one go.
|
||||
|
||||
### Input Shaper re-calibration
|
||||
|
||||
`SHAPER_CALIBRATE` command can be also used to re-calibrate the input shaper in
|
||||
the future, especially if some changes to the printer that can affect its
|
||||
kinematics are made. One can either re-run the full calibration using
|
||||
`SHAPER_CALIBRATE` command, or restrict the auto-calibration to a single axis by
|
||||
supplying `AXIS=` parameter, like
|
||||
```
|
||||
SHAPER_CALIBRATE AXIS=X
|
||||
```
|
||||
|
||||
**Warning!** It is not advisable to run the shaper autocalibration very
|
||||
frequently (e.g. before every print, or every day). In order to determine
|
||||
resonance frequencies, autocalibration creates intensive vibrations on each of
|
||||
the axes. Generally, 3D printers are not designed to withstand a prolonged
|
||||
exposure to vibrations near the resonance frequencies. Doing so may increase
|
||||
wear of the printer components and reduce their lifespan. There is also an
|
||||
increased risk of some parts unscrewing or becoming loose. Always check that
|
||||
all parts of the printer (including the ones that may normally not move) are
|
||||
securely fixed in place after each auto-tuning.
|
||||
|
||||
Also, due to some noise in measurements, it is possible that the tuning results
|
||||
will be slightly different from one calibration run to another one. Still, it
|
||||
is not expected that the noise will affect the print quality too much.
|
||||
However, it is still advised to double-check the suggested parameters, and
|
||||
print some test prints before using them to confirm they are good.
|
||||
|
||||
## Offline processing of the accelerometer data
|
||||
|
||||
It is possible to generate the raw accelerometer data and process it offline
|
||||
(e.g. on a host machine), for example to find resonances. In order to do so,
|
||||
run the following commands via Octoprint terminal:
|
||||
```
|
||||
SET_INPUT_SHAPER SHAPER_FREQ_X=0 SHAPER_FREQ_Y=0
|
||||
TEST_RESONANCES AXIS=X OUTPUT=raw_data
|
||||
```
|
||||
ignoring any errors for `SET_INPUT_SHAPER` command. For `TEST_RESONANCES`
|
||||
command, specify the desired test axis. The raw data will be written into
|
||||
`/tmp` directory on the RPi.
|
||||
|
||||
The raw data can also be obtained by running the command
|
||||
`ACCELEROMETER_MEASURE` command twice during some normal printer
|
||||
activity - first to start the measurements, and then to stop them and
|
||||
write the output file. Refer to [G-Codes](G-Codes.md#adxl345) for more
|
||||
details.
|
||||
|
||||
The data can be processed later by the following scripts:
|
||||
`scripts/graph_accelerometer.py` and `scripts/calibrate_shaper.py`. Both
|
||||
of them accept one or several raw csv files as the input depending on the
|
||||
mode. The graph_accelerometer.py script supports several modes of operation:
|
||||
|
||||
* plotting raw accelerometer data (use `-r` parameter), only 1 input is
|
||||
supported;
|
||||
* plotting a frequency response (no extra parameters required), if multiple
|
||||
inputs are specified, the average frequency response is computed;
|
||||
* comparison of the frequency response between several inputs (use `-c`
|
||||
parameter); you can additionally specify which accelerometer axis to
|
||||
consider via `-a x`, `-a y` or `-a z` parameter (if none specified,
|
||||
the sum of vibrations for all axes is used);
|
||||
* plotting the spectrogram (use `-s` parameter), only 1 input is supported;
|
||||
you can additionally specify which accelerometer axis to consider via
|
||||
`-a x`, `-a y` or `-a z` parameter (if none specified, the sum of vibrations
|
||||
for all axes is used).
|
||||
|
||||
Note that graph_accelerometer.py script supports only the raw_data\*.csv files
|
||||
and not resonances\*.csv or calibration_data\*.csv files.
|
||||
|
||||
For example,
|
||||
```
|
||||
~/klipper/scripts/graph_accelerometer.py /tmp/raw_data_x_*.csv -o /tmp/resonances_x.png -c -a z
|
||||
```
|
||||
will plot the comparison of several `/tmp/raw_data_x_*.csv` files for Z axis to
|
||||
`/tmp/resonances_x.png` file.
|
||||
|
||||
The shaper_calibrate.py script accepts 1 or several inputs and can run automatic
|
||||
tuning of the input shaper and suggest the best parameters that work well for
|
||||
all provided inputs. It prints the suggested parameters to the console, and can
|
||||
additionally generate the chart if `-o output.png` parameter is provided, or
|
||||
the CSV file if `-c output.csv` parameter is specified.
|
||||
|
||||
Providing several inputs to shaper_calibrate.py script can be useful if running
|
||||
some advanced tuning of the input shapers, for example:
|
||||
|
||||
* Running `TEST_RESONANCES AXIS=X OUTPUT=raw_data` (and `Y` axis) for a single
|
||||
axis twice on a bed slinger printer with the accelerometer attached to the
|
||||
toolhead the first time, and the accelerometer attached to the bed the
|
||||
second time in order to detect axes cross-resonances and attempt to cancel
|
||||
them with input shapers.
|
||||
* Running `TEST_RESONANCES AXIS=Y OUTPUT=raw_data` twice on a bed slinger with
|
||||
a glass bed and a magnetic surfaces (which is lighter) to find the input
|
||||
shaper parameters that work well for any print surface configuration.
|
||||
* Combining the resonance data from multiple test points.
|
||||
* Combining the resonance data from 2 axis (e.g. on a bed slinger printer
|
||||
to configure X-axis input_shaper from both X and Y axes resonances to
|
||||
cancel vibrations of the *bed* in case the nozzle 'catches' a print when
|
||||
moving in X axis direction).
|
||||
42
docs/Multi_MCU_Homing.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Multiple Micro-controller Homing and Probing
|
||||
|
||||
Klipper supports a mechanism for homing with an endstop attached to
|
||||
one micro-controller while its stepper motors are on a different
|
||||
micro-controller. This support is referred to as "multi-mcu
|
||||
homing". This feature is also used when a Z probe is on a different
|
||||
micro-controller than the Z stepper motors.
|
||||
|
||||
This feature can be useful to simplify wiring, as it may be more
|
||||
convenient to attach an endstop or probe to a closer micro-controller.
|
||||
However, using this feature may result in "overshoot" of the stepper
|
||||
motors during homing and probing operations.
|
||||
|
||||
The overshoot occurs due to possible message transmission delays
|
||||
between the micro-controller monitoring the endstop and the
|
||||
micro-controllers moving the stepper motors. The Klipper code is
|
||||
designed to limit this delay to no more than 25ms. (When multi-mcu
|
||||
homing is activated, the micro-controllers send periodic status
|
||||
messages and check that corresponding status messages are received
|
||||
within 25ms.)
|
||||
|
||||
So, for example, if homing at 10mm/s then it is possible for an
|
||||
overshoot of up to 0.250mm (10mm/s * .025s == 0.250mm). Care should be
|
||||
taken when configuring multi-mcu homing to account for this type of
|
||||
overshoot. Using slower homing or probing speeds can reduce the
|
||||
overshoot.
|
||||
|
||||
Stepper motor overshoot should not adversely impact the precision of
|
||||
the homing and probing procedure. The Klipper code will detect the
|
||||
overshoot and account for it in its calculations. However, it is
|
||||
important that the hardware design is capable of handling overshoot
|
||||
without causing damage to the machine.
|
||||
|
||||
Should Klipper detect a communication issue between micro-controllers
|
||||
during multi-mcu homing then it will raise a "Communication timeout
|
||||
during homing" error.
|
||||
|
||||
Note that an axis with multiple steppers (eg, `stepper_z` and
|
||||
`stepper_z1`) need to be on the same micro-controller in order to use
|
||||
multi-mcu homing. For example, if an endstop is on a separate
|
||||
micro-controller from `stepper_z` then `stepper_z1` must be on the
|
||||
same micro-controller as `stepper_z`.
|
||||
96
docs/Overview.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Overview
|
||||
|
||||
Welcome to the Klipper documentation. If new to Klipper, start with
|
||||
the [features](Features.md) and [installation](Installation.md)
|
||||
documents.
|
||||
|
||||
## Overview information
|
||||
|
||||
- [Features](Features.md): A high-level list of features in Klipper.
|
||||
- [FAQ](FAQ.md): Frequently asked questions.
|
||||
- [Releases](Releases.md): The history of Klipper releases.
|
||||
- [Config changes](Config_Changes.md): Recent software changes that
|
||||
may require users to update their printer config file.
|
||||
- [Contact](Contact.md): Information on bug reporting and general
|
||||
communication with the Klipper developers.
|
||||
|
||||
## Installation and Configuration
|
||||
|
||||
- [Installation](Installation.md): Guide to installing Klipper.
|
||||
- [Config Reference](Config_Reference.md): Description of config
|
||||
parameters.
|
||||
- [Rotation Distance](Rotation_Distance.md): Calculating the
|
||||
rotation_distance stepper parameter.
|
||||
- [Config checks](Config_checks.md): Verify basic pin settings in the
|
||||
config file.
|
||||
- [Bed level](Bed_Level.md): Information on "bed leveling" in Klipper.
|
||||
- [Delta calibrate](Delta_Calibrate.md): Calibration of delta
|
||||
kinematics.
|
||||
- [Probe calibrate](Probe_Calibrate.md): Calibration of automatic Z
|
||||
probes.
|
||||
- [BL-Touch](BLTouch.md): Configure a "BL-Touch" Z probe.
|
||||
- [Manual level](Manual_Level.md): Calibration of Z endstops (and
|
||||
similar).
|
||||
- [Bed Mesh](Bed_Mesh.md): Bed height correction based on XY
|
||||
locations.
|
||||
- [Endstop phase](Endstop_Phase.md): Stepper assisted Z endstop
|
||||
positioning.
|
||||
- [Resonance compensation](Resonance_Compensation.md): A tool to
|
||||
reduce ringing in prints.
|
||||
- [Measuring resonances](Measuring_Resonances.md): Information on
|
||||
using adxl345 accelerometer hardware to measure resonance.
|
||||
- [Pressure advance](Pressure_Advance.md): Calibrate extruder
|
||||
pressure.
|
||||
- [G-Codes](G-Codes.md): Information on commands supported by Klipper.
|
||||
- [Command Templates](Command_Templates.md): G-Code macros and
|
||||
conditional evaluation.
|
||||
- [Status Reference](Status_Reference.md): Information available to
|
||||
macros (and similar).
|
||||
- [TMC Drivers](TMC_Drivers.md): Using Trinamic stepper motor drivers
|
||||
with Klipper.
|
||||
- [Multi-MCU Homing](Multi_MCU_Homing.md): Homing and probing using multiple micro-controllers.
|
||||
- [Slicers](Slicers.md): Configure "slicer" software for Klipper.
|
||||
- [Skew correction](Skew_Correction.md): Adjustments for axes not
|
||||
perfectly square.
|
||||
- [PWM tools](Using_PWM_Tools.md): Guide on how to use PWM controlled
|
||||
tools such as lasers or spindles.
|
||||
- [Exclude Object](Exclude_Object.md): The guide to the Exclude Objecs
|
||||
implementation.
|
||||
|
||||
## Developer Documentation
|
||||
|
||||
- [Code overview](Code_Overview.md): Developers should read this
|
||||
first.
|
||||
- [Kinematics](Kinematics.md): Technical details on how Klipper
|
||||
implements motion.
|
||||
- [Protocol](Protocol.md): Information on the low-level messaging
|
||||
protocol between host and micro-controller.
|
||||
- [API Server](API_Server.md): Information on Klipper's command and
|
||||
control API.
|
||||
- [MCU commands](MCU_Commands.md): A description of low-level commands
|
||||
implemented in the micro-controller software.
|
||||
- [CAN bus protocol](CANBUS_protocol.md): Klipper CAN bus message
|
||||
format.
|
||||
- [Debugging](Debugging.md): Information on how to test and debug
|
||||
Klipper.
|
||||
- [Benchmarks](Benchmarks.md): Information on the Klipper benchmark
|
||||
method.
|
||||
- [Contributing](CONTRIBUTING.md): Information on how to submit
|
||||
improvements to Klipper.
|
||||
- [Packaging](Packaging.md): Information on building OS packages.
|
||||
|
||||
## Device Specific Documents
|
||||
|
||||
- [Example configs](Example_Configs.md): Information on adding an
|
||||
example config file to Klipper.
|
||||
- [SDCard Updates](SDCard_Updates.md): Flash a micro-controller by
|
||||
copying a binary to an sdcard in the micro-controller.
|
||||
- [Raspberry Pi as Micro-controller](RPi_microcontroller.md): Details
|
||||
for controlling devices wired to the GPIO pins of a Raspberry Pi.
|
||||
- [Beaglebone](Beaglebone.md): Details for running Klipper on the
|
||||
Beaglebone PRU.
|
||||
- [Bootloaders](Bootloaders.md): Developer information on
|
||||
micro-controller flashing.
|
||||
- [CAN bus](CANBUS.md): Information on using CAN bus with Klipper.
|
||||
- [TSL1401CL filament width sensor](TSL1401CL_Filament_Width_Sensor.md)
|
||||
- [Hall filament width sensor](Hall_Filament_Width_Sensor.md)
|
||||
30
docs/Packaging.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Packaging Klipper
|
||||
|
||||
Klipper is somewhat of a packaging anomaly among python programs, as it doesn't
|
||||
use setuptools to build and install. Some notes regarding how best to package it
|
||||
are as follows:
|
||||
|
||||
## C modules
|
||||
|
||||
Klipper uses a C module to handle some kinematics calculations more quickly.
|
||||
This module needs to be compiled at packaging time to avoid introducing a
|
||||
runtime dependency on a compiler. To compile the C module, run `python2
|
||||
klippy/chelper/__init__.py`.
|
||||
|
||||
## Compiling python code
|
||||
|
||||
Many distributions have a policy of compiling all python code before packaging
|
||||
to improve startup time. You can do this by running `python2 -m compileall
|
||||
klippy`.
|
||||
|
||||
## Versioning
|
||||
|
||||
If you are building a package of Klipper from git, it is usual practice not to
|
||||
ship a .git directory, so the versioning must be handled without git. To do
|
||||
this, use the script shipped in `scripts/make_version.py` which should be run as
|
||||
follows: `python2 scripts/make_version.py YOURDISTRONAME > klippy/.version`.
|
||||
|
||||
## Sample packaging script
|
||||
|
||||
klipper-git is packaged for Arch Linux, and has a PKGBUILD (package build
|
||||
script) available at [Arch User Repositiory](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=klipper-git).
|
||||
147
docs/Pressure_Advance.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Pressure advance
|
||||
|
||||
This document provides information on tuning the "pressure advance"
|
||||
configuration variable for a particular nozzle and filament. The
|
||||
pressure advance feature can be helpful in reducing ooze. For more
|
||||
information on how pressure advance is implemented see the
|
||||
[kinematics](Kinematics.md) document.
|
||||
|
||||
## Tuning pressure advance
|
||||
|
||||
Pressure advance does two useful things - it reduces ooze during
|
||||
non-extrude moves and it reduces blobbing during cornering. This guide
|
||||
uses the second feature (reducing blobbing during cornering) as a
|
||||
mechanism for tuning.
|
||||
|
||||
In order to calibrate pressure advance the printer must be configured
|
||||
and operational as the tuning test involves printing and inspecting a
|
||||
test object. It is a good idea to read this document in full prior to
|
||||
running the test.
|
||||
|
||||
Use a slicer to generate g-code for the large hollow square found in
|
||||
[docs/prints/square_tower.stl](prints/square_tower.stl). Use a high
|
||||
speed (eg, 100mm/s), zero infill, and a coarse layer height (the layer
|
||||
height should be around 75% of the nozzle diameter). Make sure any
|
||||
"dynamic acceleration control" is disabled in the slicer.
|
||||
|
||||
Prepare for the test by issuing the following G-Code command:
|
||||
```
|
||||
SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=1 ACCEL=500
|
||||
```
|
||||
This command makes the nozzle travel slower through corners to
|
||||
emphasize the effects of extruder pressure. Then for printers with a
|
||||
direct drive extruder run the command:
|
||||
```
|
||||
TUNING_TOWER COMMAND=SET_PRESSURE_ADVANCE PARAMETER=ADVANCE START=0 FACTOR=.005
|
||||
```
|
||||
For long bowden extruders use:
|
||||
```
|
||||
TUNING_TOWER COMMAND=SET_PRESSURE_ADVANCE PARAMETER=ADVANCE START=0 FACTOR=.020
|
||||
```
|
||||
Then print the object. When fully printed the test print looks like:
|
||||
|
||||

|
||||
|
||||
The above TUNING_TOWER command instructs Klipper to alter the
|
||||
pressure_advance setting on each layer of the print. Higher layers in
|
||||
the print will have a larger pressure advance value set. Layers below
|
||||
the ideal pressure_advance setting will have blobbing at the corners,
|
||||
and layers above the ideal setting can lead to rounded corners and
|
||||
poor extrusion leading up to the corner.
|
||||
|
||||
One can cancel the print early if one observes that the corners are no
|
||||
longer printing well (and thus one can avoid printing layers that are
|
||||
known to be above the ideal pressure_advance value).
|
||||
|
||||
Inspect the print and then use a digital calipers to find the height
|
||||
that has the best quality corners. When in doubt, prefer a lower
|
||||
height.
|
||||
|
||||

|
||||
|
||||
The pressure_advance value can then be calculated as `pressure_advance
|
||||
= <start> + <measured_height> * <factor>`. (For example, `0 + 12.90 *
|
||||
.020` would be `.258`.)
|
||||
|
||||
It is possible to choose custom settings for START and FACTOR if that
|
||||
helps identify the best pressure advance setting. When doing this, be
|
||||
sure to issue the TUNING_TOWER command at the start of each test
|
||||
print.
|
||||
|
||||
Typical pressure advance values are between 0.050 and 1.000 (the high
|
||||
end usually only with bowden extruders). If there is no significant
|
||||
improvement with a pressure advance up to 1.000, then pressure advance
|
||||
is unlikely to improve the quality of prints. Return to a default
|
||||
configuration with pressure advance disabled.
|
||||
|
||||
Although this tuning exercise directly improves the quality of
|
||||
corners, it's worth remembering that a good pressure advance
|
||||
configuration also reduces ooze throughout the print.
|
||||
|
||||
At the completion of this test, set
|
||||
`pressure_advance = <calculated_value>` in the `[extruder]` section of
|
||||
the configuration file and issue a RESTART command. The RESTART
|
||||
command will clear the test state and return the acceleration and
|
||||
cornering speeds to their normal values.
|
||||
|
||||
## Important Notes
|
||||
|
||||
* The pressure advance value is dependent on the extruder, the nozzle,
|
||||
and the filament. It is common for filament from different
|
||||
manufactures or with different pigments to require significantly
|
||||
different pressure advance values. Therefore, one should calibrate
|
||||
pressure advance on each printer and with each spool of filament.
|
||||
|
||||
* Printing temperature and extrusion rates can impact pressure
|
||||
advance. Be sure to tune the
|
||||
[extruder rotation_distance](Rotation_Distance.md#calibrating-rotation_distance-on-extruders)
|
||||
and
|
||||
[nozzle temperature](http://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide#Nozzle_Temperature)
|
||||
prior to tuning pressure advance.
|
||||
|
||||
* The test print is designed to run with a high extruder flow rate,
|
||||
but otherwise "normal" slicer settings. A high flow rate is obtained
|
||||
by using a high printing speed (eg, 100mm/s) and a coarse layer
|
||||
height (typically around 75% of the nozzle diameter). Other slicer
|
||||
settings should be similar to their defaults (eg, perimeters of 2 or
|
||||
3 lines, normal retraction amount). It can be useful to set the
|
||||
external perimeter speed to be the same speed as the rest of the
|
||||
print, but it is not a requirement.
|
||||
|
||||
* It is common for the test print to show different behavior on each
|
||||
corner. Often the slicer will arrange to change layers at one corner
|
||||
which can result in that corner being significantly different from
|
||||
the remaining three corners. If this occurs, then ignore that corner
|
||||
and tune pressure advance using the other three corners. It is also
|
||||
common for the remaining corners to vary slightly. (This can occur
|
||||
due to small differences in how the printer's frame reacts to
|
||||
cornering in certain directions.) Try to choose a value that works
|
||||
well for all the remaining corners. If in doubt, prefer a lower
|
||||
pressure advance value.
|
||||
|
||||
* If a high pressure advance value (eg, over 0.200) is used then one
|
||||
may find that the extruder skips when returning to the printer's
|
||||
normal acceleration. The pressure advance system accounts for
|
||||
pressure by pushing in extra filament during acceleration and
|
||||
retracting that filament during deceleration. With a high
|
||||
acceleration and high pressure advance the extruder may not have
|
||||
enough torque to push the required filament. If this occurs, either
|
||||
use a lower acceleration value or disable pressure advance.
|
||||
|
||||
* Once pressure advance is tuned in Klipper, it may still be useful to
|
||||
configure a small retract value in the slicer (eg, 0.75mm) and to
|
||||
utilize the slicer's "wipe on retract option" if available. These
|
||||
slicer settings may help counteract ooze caused by filament cohesion
|
||||
(filament pulled out of the nozzle due to the stickiness of the
|
||||
plastic). It is recommended to disable the slicer's "z-lift on
|
||||
retract" option.
|
||||
|
||||
* The pressure advance system does not change the timing or path of
|
||||
the toolhead. A print with pressure advance enabled will take the
|
||||
same amount of time as a print without pressure advance. Pressure
|
||||
advance also does not change the total amount of filament extruded
|
||||
during a print. Pressure advance results in extra extruder movement
|
||||
during move acceleration and deceleration. A very high pressure
|
||||
advance setting will result in a very large amount of extruder
|
||||
movement during acceleration and deceleration, and no configuration
|
||||
setting places a limit on the amount of that movement.
|
||||
203
docs/Probe_Calibrate.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Probe calibration
|
||||
|
||||
This document describes the method for calibrating the X, Y, and Z
|
||||
offsets of an "automatic z probe" in Klipper. This is useful for users
|
||||
that have a `[probe]` or `[bltouch]` section in their config file.
|
||||
|
||||
## Calibrating probe X and Y offsets
|
||||
|
||||
To calibrate the X and Y offset, navigate to the OctoPrint "Control"
|
||||
tab, home the printer, and then use the OctoPrint jogging buttons to
|
||||
move the head to a position near the center of the bed.
|
||||
|
||||
Place a piece of blue painters tape (or similar) on the bed underneath
|
||||
the probe. Navigate to the OctoPrint "Terminal" tab and issue a PROBE
|
||||
command:
|
||||
```
|
||||
PROBE
|
||||
```
|
||||
Place a mark on the tape directly under where the probe is (or use a
|
||||
similar method to note the location on the bed).
|
||||
|
||||
Issue a `GET_POSITION` command and record the toolhead XY location
|
||||
reported by that command. For example if one sees:
|
||||
```
|
||||
Recv: // toolhead: X:46.500000 Y:27.000000 Z:15.000000 E:0.000000
|
||||
```
|
||||
then one would record a probe X position of 46.5 and probe Y position
|
||||
of 27.
|
||||
|
||||
After recording the probe position, issue a series of G1 commands
|
||||
until the nozzle is directly above the mark on the bed. For example,
|
||||
one might issue:
|
||||
```
|
||||
G1 F300 X57 Y30 Z15
|
||||
```
|
||||
to move the nozzle to an X position of 57 and Y of 30. Once one finds
|
||||
the position directly above the mark, use the `GET_POSITION` command
|
||||
to report that position. This is the nozzle position.
|
||||
|
||||
The x_offset is then the `nozzle_x_position - probe_x_position` and
|
||||
y_offset is similarly the `nozzle_y_position - probe_y_position`.
|
||||
Update the printer.cfg file with the given values, remove the
|
||||
tape/marks from the bed, and then issue a `RESTART` command so that
|
||||
the new values take effect.
|
||||
|
||||
## Calibrating probe Z offset
|
||||
|
||||
Providing an accurate probe z_offset is critical to obtaining high
|
||||
quality prints. The z_offset is the distance between the nozzle and
|
||||
bed when the probe triggers. The Klipper `PROBE_CALIBRATE` tool can be
|
||||
used to obtain this value - it will run an automatic probe to measure
|
||||
the probe's Z trigger position and then start a manual probe to obtain
|
||||
the nozzle Z height. The probe z_offset will then be calculated from
|
||||
these measurements.
|
||||
|
||||
Start by homing the printer and then move the head to a position near
|
||||
the center of the bed. Navigate to the OctoPrint terminal tab and run
|
||||
the `PROBE_CALIBRATE` command to start the tool.
|
||||
|
||||
This tool will perform an automatic probe, then lift the head, move
|
||||
the nozzle over the location of the probe point, and start the manual
|
||||
probe tool. If the nozzle does not move to a position above the
|
||||
automatic probe point, then `ABORT` the manual probe tool and perform
|
||||
the XY probe offset calibration described above.
|
||||
|
||||
Once the manual probe tool starts, follow the steps described at
|
||||
["the paper test"](Bed_Level.md#the-paper-test)) to determine the
|
||||
actual distance between the nozzle and bed at the given location. Once
|
||||
those steps are complete one can `ACCEPT` the position and save the
|
||||
results to the config file with:
|
||||
```
|
||||
SAVE_CONFIG
|
||||
```
|
||||
|
||||
Note that if a change is made to the printer's motion system, hotend
|
||||
position, or probe location then it will invalidate the results of
|
||||
PROBE_CALIBRATE.
|
||||
|
||||
If the probe has an X or Y offset and the bed tilt is changed (eg, by
|
||||
adjusting bed screws, running DELTA_CALIBRATE, running Z_TILT_ADJUST,
|
||||
running QUAD_GANTRY_LEVEL, or similar) then it will invalidate the
|
||||
results of PROBE_CALIBRATE. After making any of the above adjustments
|
||||
it will be necessary to run PROBE_CALIBRATE again.
|
||||
|
||||
If the results of PROBE_CALIBRATE are invalidated, then any previous
|
||||
[bed mesh](Bed_Mesh.md) results that were obtained using the probe are
|
||||
also invalidated - it will be necessary to rerun BED_MESH_CALIBRATE
|
||||
after recalibrating the probe.
|
||||
|
||||
## Repeatability check
|
||||
|
||||
After calibrating the probe X, Y, and Z offsets it is a good idea to
|
||||
verify that the probe provides repeatable results. Start by homing the
|
||||
printer and then move the head to a position near the center of the
|
||||
bed. Navigate to the OctoPrint terminal tab and run the
|
||||
`PROBE_ACCURACY` command.
|
||||
|
||||
This command will run the probe ten times and produce output similar
|
||||
to the following:
|
||||
```
|
||||
Recv: // probe accuracy: at X:0.000 Y:0.000 Z:10.000
|
||||
Recv: // and read 10 times with speed of 5 mm/s
|
||||
Recv: // probe at -0.003,0.005 is z=2.506948
|
||||
Recv: // probe at -0.003,0.005 is z=2.519448
|
||||
Recv: // probe at -0.003,0.005 is z=2.519448
|
||||
Recv: // probe at -0.003,0.005 is z=2.506948
|
||||
Recv: // probe at -0.003,0.005 is z=2.519448
|
||||
Recv: // probe at -0.003,0.005 is z=2.519448
|
||||
Recv: // probe at -0.003,0.005 is z=2.506948
|
||||
Recv: // probe at -0.003,0.005 is z=2.506948
|
||||
Recv: // probe at -0.003,0.005 is z=2.519448
|
||||
Recv: // probe at -0.003,0.005 is z=2.506948
|
||||
Recv: // probe accuracy results: maximum 2.519448, minimum 2.506948, range 0.012500, average 2.513198, median 2.513198, standard deviation 0.006250
|
||||
```
|
||||
|
||||
Ideally the tool will report an identical maximum and minimum value.
|
||||
(That is, ideally the probe obtains an identical result on all ten
|
||||
probes.) However, it's normal for the minimum and maximum values to
|
||||
differ by one Z "step distance" or up to 5 microns (.005mm). A "step
|
||||
distance" is
|
||||
`rotation_distance/(full_steps_per_rotation*microsteps)`. The distance
|
||||
between the minimum and the maximum value is called the range. So, in
|
||||
the above example, since the printer uses a Z step distance of .0125,
|
||||
a range of 0.012500 would be considered normal.
|
||||
|
||||
If the results of the test show a range value that is greater than 25
|
||||
microns (.025mm) then the probe does not have sufficient accuracy for
|
||||
typical bed leveling procedures. It may be possible to tune the probe
|
||||
speed and/or probe start height to improve the repeatability of the
|
||||
probe. The `PROBE_ACCURACY` command allows one to run tests with
|
||||
different parameters to see their impact - see the
|
||||
[G-Codes document](G-Codes.md#probe_accuracy) for further details. If
|
||||
the probe generally obtains repeatable results but has an occasional
|
||||
outlier, then it may be possible to account for that by using multiple
|
||||
samples on each probe - read the description of the probe `samples`
|
||||
config parameters in the [config reference](Config_Reference.md#probe)
|
||||
for more details.
|
||||
|
||||
If new probe speed, samples count, or other settings are needed, then
|
||||
update the printer.cfg file and issue a `RESTART` command. If so, it
|
||||
is a good idea to
|
||||
[calibrate the z_offset](#calibrating-probe-z-offset) again. If
|
||||
repeatable results can not be obtained then don't use the probe for
|
||||
bed leveling. Klipper has several manual probing tools that can be
|
||||
used instead - see the [Bed Level document](Bed_Level.md) for further
|
||||
details.
|
||||
|
||||
## Location Bias Check
|
||||
|
||||
Some probes can have a systemic bias that corrupts the results of the
|
||||
probe at certain toolhead locations. For example, if the probe mount
|
||||
tilts slightly when moving along the Y axis then it could result in
|
||||
the probe reporting biased results at different Y positions.
|
||||
|
||||
This is a common issue with probes on delta printers, however it can
|
||||
occur on all printers.
|
||||
|
||||
One can check for a location bias by using the `PROBE_CALIBRATE`
|
||||
command to measuring the probe z_offset at various X and Y locations.
|
||||
Ideally, the probe z_offset would be a constant value at every printer
|
||||
location.
|
||||
|
||||
For delta printers, try measuring the z_offset at a position near the
|
||||
A tower, at a position near the B tower, and at a position near the C
|
||||
tower. For cartesian, corexy, and similar printers, try measuring the
|
||||
z_offset at positions near the four corners of the bed.
|
||||
|
||||
Before starting this test, first calibrate the probe X, Y, and Z
|
||||
offsets as described at the beginning of this document. Then home the
|
||||
printer and navigate to the first XY position. Follow the steps at
|
||||
[calibrating probe Z offset](#calibrating-probe-z-offset) to run the
|
||||
`PROBE_CALIBRATE` command, `TESTZ` commands, and `ACCEPT` command, but
|
||||
do not run `SAVE_CONFIG`. Note the reported z_offset found. Then
|
||||
navigate to the other XY positions, repeat these `PROBE_CALIBRATE`
|
||||
steps, and note the reported z_offset.
|
||||
|
||||
If the difference between the minimum reported z_offset and the
|
||||
maximum reported z_offset is greater than 25 microns (.025mm) then the
|
||||
probe is not suitable for typical bed leveling procedures. See the
|
||||
[Bed Level document](Bed_Level.md) for manual probe alternatives.
|
||||
|
||||
## Temperature Bias
|
||||
|
||||
Many probes have a systemic bias when probing at different
|
||||
temperatures. For example, the probe may consistently trigger at a
|
||||
lower height when the probe is at a higher temperature.
|
||||
|
||||
It is recommended to run the bed leveling tools at a consistent
|
||||
temperature to account for this bias. For example, either always run
|
||||
the tools when the printer is at room temperature, or always run the
|
||||
tools after the printer has obtained a consistent print temperature.
|
||||
In either case, it is a good idea to wait several minutes after the
|
||||
desired temperature is reached, so that the printer apparatus is
|
||||
consistently at the desired temperature.
|
||||
|
||||
To check for a temperature bias, start with the printer at room
|
||||
temperature and then home the printer, move the head to a position
|
||||
near the center of the bed, and run the `PROBE_ACCURACY` command. Note
|
||||
the results. Then, without homing or disabling the stepper motors,
|
||||
heat the printer nozzle and bed to printing temperature, and run the
|
||||
`PROBE_ACCURACY` command again. Ideally, the command will report
|
||||
identical results. As above, if the probe does have a temperature bias
|
||||
then be careful to always use the probe at a consistent temperature.
|
||||
350
docs/Protocol.md
Normal file
@@ -0,0 +1,350 @@
|
||||
# Protocol
|
||||
|
||||
The Klipper messaging protocol is used for low-level communication
|
||||
between the Klipper host software and the Klipper micro-controller
|
||||
software. At a high level the protocol can be thought of as a series
|
||||
of command and response strings that are compressed, transmitted, and
|
||||
then processed at the receiving side. An example series of commands in
|
||||
uncompressed human-readable format might look like:
|
||||
|
||||
```
|
||||
set_digital_out pin=PA3 value=1
|
||||
set_digital_out pin=PA7 value=1
|
||||
schedule_digital_out oid=8 clock=4000000 value=0
|
||||
queue_step oid=7 interval=7458 count=10 add=331
|
||||
queue_step oid=7 interval=11717 count=4 add=1281
|
||||
```
|
||||
|
||||
See the [mcu commands](MCU_Commands.md) document for information on
|
||||
available commands. See the [debugging](Debugging.md) document for
|
||||
information on how to translate a G-Code file into its corresponding
|
||||
human-readable micro-controller commands.
|
||||
|
||||
This page provides a high-level description of the Klipper messaging
|
||||
protocol itself. It describes how messages are declared, encoded in
|
||||
binary format (the "compression" scheme), and transmitted.
|
||||
|
||||
The goal of the protocol is to enable an error-free communication
|
||||
channel between the host and micro-controller that is low-latency,
|
||||
low-bandwidth, and low-complexity for the micro-controller.
|
||||
|
||||
## Micro-controller Interface
|
||||
|
||||
The Klipper transmission protocol can be thought of as a
|
||||
[RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) mechanism
|
||||
between micro-controller and host. The micro-controller software
|
||||
declares the commands that the host may invoke along with the response
|
||||
messages that it can generate. The host uses that information to
|
||||
command the micro-controller to perform actions and to interpret the
|
||||
results.
|
||||
|
||||
### Declaring commands
|
||||
|
||||
The micro-controller software declares a "command" by using the
|
||||
DECL_COMMAND() macro in the C code. For example:
|
||||
|
||||
```
|
||||
DECL_COMMAND(command_update_digital_out, "update_digital_out oid=%c value=%c");
|
||||
```
|
||||
|
||||
The above declares a command named "update_digital_out". This allows
|
||||
the host to "invoke" this command which would cause the
|
||||
command_update_digital_out() C function to be executed in the
|
||||
micro-controller. The above also indicates that the command takes two
|
||||
integer parameters. When the command_update_digital_out() C code is
|
||||
executed, it will be passed an array containing these two integers -
|
||||
the first corresponding to the 'oid' and the second corresponding to
|
||||
the 'value'.
|
||||
|
||||
In general, the parameters are described with printf() style syntax
|
||||
(eg, "%u"). The formatting directly corresponds to the human-readable
|
||||
view of commands (eg, "update_digital_out oid=7 value=1"). In the
|
||||
above example, "value=" is a parameter name and "%c" indicates the
|
||||
parameter is an integer. Internally, the parameter name is only used
|
||||
as documentation. In this example, the "%c" is also used as
|
||||
documentation to indicate the expected integer is 1 byte in size (the
|
||||
declared integer size does not impact the parsing or encoding).
|
||||
|
||||
The micro-controller build will collect all commands declared with
|
||||
DECL_COMMAND(), determine their parameters, and arrange for them to be
|
||||
callable.
|
||||
|
||||
### Declaring responses
|
||||
|
||||
To send information from the micro-controller to the host a "response"
|
||||
is generated. These are both declared and transmitted using the
|
||||
sendf() C macro. For example:
|
||||
|
||||
```
|
||||
sendf("status clock=%u status=%c", sched_read_time(), sched_is_shutdown());
|
||||
```
|
||||
|
||||
The above transmits a "status" response message that contains two
|
||||
integer parameters ("clock" and "status"). The micro-controller build
|
||||
automatically finds all sendf() calls and generates encoders for
|
||||
them. The first parameter of the sendf() function describes the
|
||||
response and it is in the same format as command declarations.
|
||||
|
||||
The host can arrange to register a callback function for each
|
||||
response. So, in effect, commands allow the host to invoke C functions
|
||||
in the micro-controller and responses allow the micro-controller
|
||||
software to invoke code in the host.
|
||||
|
||||
The sendf() macro should only be invoked from command or task
|
||||
handlers, and it should not be invoked from interrupts or timers. The
|
||||
code does not need to issue a sendf() in response to a received
|
||||
command, it is not limited in the number of times sendf() may be
|
||||
invoked, and it may invoke sendf() at any time from a task handler.
|
||||
|
||||
#### Output responses
|
||||
|
||||
To simplify debugging, there is also an output() C function. For
|
||||
example:
|
||||
|
||||
```
|
||||
output("The value of %u is %s with size %u.", x, buf, buf_len);
|
||||
```
|
||||
|
||||
The output() function is similar in usage to printf() - it is intended
|
||||
to generate and format arbitrary messages for human consumption.
|
||||
|
||||
### Declaring enumerations
|
||||
|
||||
Enumerations allow the host code to use string identifiers for
|
||||
parameters that the micro-controller handles as integers. They are
|
||||
declared in the micro-controller code - for example:
|
||||
|
||||
```
|
||||
DECL_ENUMERATION("spi_bus", "spi", 0);
|
||||
|
||||
DECL_ENUMERATION_RANGE("pin", "PC0", 16, 8);
|
||||
```
|
||||
|
||||
If the first example, the DECL_ENUMERATION() macro defines an
|
||||
enumeration for any command/response message with a parameter name of
|
||||
"spi_bus" or parameter name with a suffix of "_spi_bus". For those
|
||||
parameters the string "spi" is a valid value and it will be
|
||||
transmitted with an integer value of zero.
|
||||
|
||||
It's also possible to declare an enumeration range. In the second
|
||||
example, a "pin" parameter (or any parameter with a suffix of "_pin")
|
||||
would accept PC0, PC1, PC2, ..., PC7 as valid values. The strings will
|
||||
be transmitted with integers 16, 17, 18, ..., 23.
|
||||
|
||||
### Declaring constants
|
||||
|
||||
Constants can also be exported. For example, the following:
|
||||
|
||||
```
|
||||
DECL_CONSTANT("SERIAL_BAUD", 250000);
|
||||
```
|
||||
|
||||
would export a constant named "SERIAL_BAUD" with a value of 250000
|
||||
from the micro-controller to the host. It is also possible to declare
|
||||
a constant that is a string - for example:
|
||||
|
||||
```
|
||||
DECL_CONSTANT_STR("MCU", "pru");
|
||||
```
|
||||
|
||||
## Low-level message encoding
|
||||
|
||||
To accomplish the above RPC mechanism, each command and response is
|
||||
encoded into a binary format for transmission. This section describes
|
||||
the transmission system.
|
||||
|
||||
### Message Blocks
|
||||
|
||||
All data sent from host to micro-controller and vice-versa are
|
||||
contained in "message blocks". A message block has a two byte header
|
||||
and a three byte trailer. The format of a message block is:
|
||||
|
||||
```
|
||||
<1 byte length><1 byte sequence><n-byte content><2 byte crc><1 byte sync>
|
||||
```
|
||||
|
||||
The length byte contains the number of bytes in the message block
|
||||
including the header and trailer bytes (thus the minimum message
|
||||
length is 5 bytes). The maximum message block length is currently 64
|
||||
bytes. The sequence byte contains a 4 bit sequence number in the
|
||||
low-order bits and the high-order bits always contain 0x10 (the
|
||||
high-order bits are reserved for future use). The content bytes
|
||||
contain arbitrary data and its format is described in the following
|
||||
section. The crc bytes contain a 16bit CCITT
|
||||
[CRC](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) of the
|
||||
message block including the header bytes but excluding the trailer
|
||||
bytes. The sync byte is 0x7e.
|
||||
|
||||
The format of the message block is inspired by
|
||||
[HDLC](https://en.wikipedia.org/wiki/High-Level_Data_Link_Control)
|
||||
message frames. Like in HDLC, the message block may optionally contain
|
||||
an additional sync character at the start of the block. Unlike in
|
||||
HDLC, a sync character is not exclusive to the framing and may be
|
||||
present in the message block content.
|
||||
|
||||
### Message Block Contents
|
||||
|
||||
Each message block sent from host to micro-controller contains a
|
||||
series of zero or more message commands in its contents. Each command
|
||||
starts with a [Variable Length Quantity](#variable-length-quantities)
|
||||
(VLQ) encoded integer command-id followed by zero or more VLQ
|
||||
parameters for the given command.
|
||||
|
||||
As an example, the following four commands might be placed in a single
|
||||
message block:
|
||||
|
||||
```
|
||||
update_digital_out oid=6 value=1
|
||||
update_digital_out oid=5 value=0
|
||||
get_config
|
||||
get_clock
|
||||
```
|
||||
|
||||
and encoded into the following eight VLQ integers:
|
||||
|
||||
```
|
||||
<id_update_digital_out><6><1><id_update_digital_out><5><0><id_get_config><id_get_clock>
|
||||
```
|
||||
|
||||
In order to encode and parse the message contents, both the host and
|
||||
micro-controller must agree on the command ids and the number of
|
||||
parameters each command has. So, in the above example, both the host
|
||||
and micro-controller would know that "id_update_digital_out" is always
|
||||
followed by two parameters, and "id_get_config" and "id_get_clock"
|
||||
have zero parameters. The host and micro-controller share a "data
|
||||
dictionary" that maps the command descriptions (eg,
|
||||
"update_digital_out oid=%c value=%c") to their integer
|
||||
command-ids. When processing the data, the parser will know to expect
|
||||
a specific number of VLQ encoded parameters following a given command
|
||||
id.
|
||||
|
||||
The message contents for blocks sent from micro-controller to host
|
||||
follow the same format. The identifiers in these messages are
|
||||
"response ids", but they serve the same purpose and follow the same
|
||||
encoding rules. In practice, message blocks sent from the
|
||||
micro-controller to the host never contain more than one response in
|
||||
the message block contents.
|
||||
|
||||
#### Variable Length Quantities
|
||||
|
||||
See the [wikipedia article](https://en.wikipedia.org/wiki/Variable-length_quantity)
|
||||
for more information on the general format of VLQ encoded
|
||||
integers. Klipper uses an encoding scheme that supports both positive
|
||||
and negative integers. Integers close to zero use less bytes to encode
|
||||
and positive integers typically encode using less bytes than negative
|
||||
integers. The following table shows the number of bytes each integer
|
||||
takes to encode:
|
||||
|
||||
| Integer | Encoded size |
|
||||
|---------------------------|--------------|
|
||||
| -32 .. 95 | 1 |
|
||||
| -4096 .. 12287 | 2 |
|
||||
| -524288 .. 1572863 | 3 |
|
||||
| -67108864 .. 201326591 | 4 |
|
||||
| -2147483648 .. 4294967295 | 5 |
|
||||
|
||||
#### Variable length strings
|
||||
|
||||
As an exception to the above encoding rules, if a parameter to a
|
||||
command or response is a dynamic string then the parameter is not
|
||||
encoded as a simple VLQ integer. Instead it is encoded by transmitting
|
||||
the length as a VLQ encoded integer followed by the contents itself:
|
||||
|
||||
```
|
||||
<VLQ encoded length><n-byte contents>
|
||||
```
|
||||
|
||||
The command descriptions found in the data dictionary allow both the
|
||||
host and micro-controller to know which command parameters use simple
|
||||
VLQ encoding and which parameters use string encoding.
|
||||
|
||||
## Data Dictionary
|
||||
|
||||
In order for meaningful communications to be established between
|
||||
micro-controller and host, both sides must agree on a "data
|
||||
dictionary". This data dictionary contains the integer identifiers for
|
||||
commands and responses along with their descriptions.
|
||||
|
||||
The micro-controller build uses the contents of DECL_COMMAND() and
|
||||
sendf() macros to generate the data dictionary. The build
|
||||
automatically assigns unique identifiers to each command and
|
||||
response. This system allows both the host and micro-controller code
|
||||
to seamlessly use descriptive human-readable names while still using
|
||||
minimal bandwidth.
|
||||
|
||||
The host queries the data dictionary when it first connects to the
|
||||
micro-controller. Once the host downloads the data dictionary from the
|
||||
micro-controller, it uses that data dictionary to encode all commands
|
||||
and to parse all responses from the micro-controller. The host must
|
||||
therefore handle a dynamic data dictionary. However, to keep the
|
||||
micro-controller software simple, the micro-controller always uses its
|
||||
static (compiled in) data dictionary.
|
||||
|
||||
The data dictionary is queried by sending "identify" commands to the
|
||||
micro-controller. The micro-controller will respond to each identify
|
||||
command with an "identify_response" message. Since these two commands
|
||||
are needed prior to obtaining the data dictionary, their integer ids
|
||||
and parameter types are hard-coded in both the micro-controller and
|
||||
the host. The "identify_response" response id is 0, the "identify"
|
||||
command id is 1. Other than having hard-coded ids the identify command
|
||||
and its response are declared and transmitted the same way as other
|
||||
commands and responses. No other command or response is hard-coded.
|
||||
|
||||
The format of the transmitted data dictionary itself is a zlib
|
||||
compressed JSON string. The micro-controller build process generates
|
||||
the string, compresses it, and stores it in the text section of the
|
||||
micro-controller flash. The data dictionary can be much larger than
|
||||
the maximum message block size - the host downloads it by sending
|
||||
multiple identify commands requesting progressive chunks of the data
|
||||
dictionary. Once all chunks are obtained the host will assemble the
|
||||
chunks, uncompress the data, and parse the contents.
|
||||
|
||||
In addition to information on the communication protocol, the data
|
||||
dictionary also contains the software version, enumerations (as
|
||||
defined by DECL_ENUMERATION), and constants (as defined by
|
||||
DECL_CONSTANT).
|
||||
|
||||
## Message flow
|
||||
|
||||
Message commands sent from host to micro-controller are intended to be
|
||||
error-free. The micro-controller will check the CRC and sequence
|
||||
numbers in each message block to ensure the commands are accurate and
|
||||
in-order. The micro-controller always processes message blocks
|
||||
in-order - should it receive a block out-of-order it will discard it
|
||||
and any other out-of-order blocks until it receives blocks with the
|
||||
correct sequencing.
|
||||
|
||||
The low-level host code implements an automatic retransmission system
|
||||
for lost and corrupt message blocks sent to the micro-controller. To
|
||||
facilitate this, the micro-controller transmits an "ack message block"
|
||||
after each successfully received message block. The host schedules a
|
||||
timeout after sending each block and it will retransmit should the
|
||||
timeout expire without receiving a corresponding "ack". In addition,
|
||||
if the micro-controller detects a corrupt or out-of-order block it may
|
||||
transmit a "nak message block" to facilitate fast retransmission.
|
||||
|
||||
An "ack" is a message block with empty content (ie, a 5 byte message
|
||||
block) and a sequence number greater than the last received host
|
||||
sequence number. A "nak" is a message block with empty content and a
|
||||
sequence number less than the last received host sequence number.
|
||||
|
||||
The protocol facilitates a "window" transmission system so that the
|
||||
host can have many outstanding message blocks in-flight at a
|
||||
time. (This is in addition to the many commands that may be present in
|
||||
a given message block.) This allows maximum bandwidth utilization even
|
||||
in the event of transmission latency. The timeout, retransmit,
|
||||
windowing, and ack mechanism are inspired by similar mechanisms in
|
||||
[TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol).
|
||||
|
||||
In the other direction, message blocks sent from micro-controller to
|
||||
host are designed to be error-free, but they do not have assured
|
||||
transmission. (Responses should not be corrupt, but they may go
|
||||
missing.) This is done to keep the implementation in the
|
||||
micro-controller simple. There is no automatic retransmission system
|
||||
for responses - the high-level code is expected to be capable of
|
||||
handling an occasional missing response (usually by re-requesting the
|
||||
content or setting up a recurring schedule of response
|
||||
transmission). The sequence number field in message blocks sent to the
|
||||
host is always one greater than the last received sequence number of
|
||||
message blocks received from the host. It is not used to track
|
||||
sequences of response message blocks.
|
||||
2
docs/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Welcome to the Klipper documentation. The
|
||||
[overview document](Overview.md) is a good starting point.
|
||||
234
docs/RPi_microcontroller.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# RPi microcontroller
|
||||
|
||||
This document describes the process of running Klipper on a RPi and
|
||||
use the same RPi as secondary mcu.
|
||||
|
||||
## Why use RPi as a secondary MCU?
|
||||
|
||||
Often the MCUs dedicated to controlling 3D printers have a limited and
|
||||
pre-configured number of exposed pins to manage the main printing
|
||||
functions (thermal resistors, extruders, steppers ...). Using the RPi
|
||||
where Klipper is installed as a secondary MCU gives the possibility to
|
||||
directly use the GPIOs and the buses (i2c, spi) of the RPi inside
|
||||
klipper without using Octoprint plugins (if used) or external programs
|
||||
giving the ability to control everything within the print GCODE.
|
||||
|
||||
**Warning**: If your platform is a _Beaglebone_ and you have correctly
|
||||
followed the installation steps, the linux mcu is already installed
|
||||
and configured for your system.
|
||||
|
||||
## Install the rc script
|
||||
|
||||
If you want to use the host as a secondary MCU the klipper_mcu process
|
||||
must run before the klippy process.
|
||||
|
||||
After installing Klipper, install the script. run:
|
||||
```
|
||||
cd ~/klipper/
|
||||
sudo cp "./scripts/klipper-mcu-start.sh" /etc/init.d/klipper_mcu
|
||||
sudo update-rc.d klipper_mcu defaults
|
||||
```
|
||||
|
||||
## Building the micro-controller code
|
||||
|
||||
To compile the Klipper micro-controller code, start by configuring it
|
||||
for the "Linux process":
|
||||
```
|
||||
cd ~/klipper/
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
In the menu, set "Microcontroller Architecture" to "Linux process,"
|
||||
then save and exit.
|
||||
|
||||
To build and install the new micro-controller code, run:
|
||||
```
|
||||
sudo service klipper stop
|
||||
make flash
|
||||
sudo service klipper start
|
||||
```
|
||||
|
||||
If klippy.log reports a "Permission denied" error when attempting to
|
||||
connect to `/tmp/klipper_host_mcu` then you need to add your user to
|
||||
the tty group. The following command will add the "pi" user to the
|
||||
tty group:
|
||||
```
|
||||
sudo usermod -a -G tty pi
|
||||
```
|
||||
|
||||
## Remaining configuration
|
||||
|
||||
Complete the installation by configuring Klipper secondary MCU
|
||||
following the instructions in
|
||||
[RaspberryPi sample config](../config/sample-raspberry-pi.cfg) and
|
||||
[Multi MCU sample config](../config/sample-multi-mcu.cfg).
|
||||
|
||||
## Optional: Enabling SPI
|
||||
|
||||
Make sure the Linux SPI driver is enabled by running
|
||||
`sudo raspi-config` and enabling SPI under the "Interfacing options"
|
||||
menu.
|
||||
|
||||
## Optional: Enabling I2C
|
||||
|
||||
Make sure the Linux I2C driver is enabled by running `sudo raspi-config`
|
||||
and enabling I2C under the "Interfacing options" menu.
|
||||
If planning to use I2C for the MPU accelerometer, it is also required
|
||||
to set the baud rate to 400000 by: adding/uncommenting
|
||||
`dtparam=i2c_arm=on,i2c_arm_baudrate=400000` in `/boot/config.txt`
|
||||
(or `/boot/firmware/config.txt` in some distros).
|
||||
|
||||
## Optional: Identify the correct gpiochip
|
||||
|
||||
On Raspberry Pi and on many clones the pins exposed on the GPIO belong
|
||||
to the first gpiochip. They can therefore be used on klipper simply by
|
||||
referring them with the name `gpio0..n`. However, there are cases in
|
||||
which the exposed pins belong to gpiochips other than the first. For
|
||||
example in the case of some OrangePi models or if a Port Expander is
|
||||
used. In these cases it is useful to use the commands to access the
|
||||
_Linux GPIO character device_ to verify the configuration.
|
||||
|
||||
To install the _Linux GPIO character device - binary_ on a debian
|
||||
based distro like octopi run:
|
||||
```
|
||||
sudo apt-get install gpiod
|
||||
```
|
||||
|
||||
To check available gpiochip run:
|
||||
```
|
||||
gpiodetect
|
||||
```
|
||||
|
||||
To check the pin number and the pin availability tun:
|
||||
```
|
||||
gpioinfo
|
||||
```
|
||||
|
||||
The chosen pin can thus be used within the configuration as
|
||||
`gpiochip<n>/gpio<o>` where **n** is the chip number as seen by the
|
||||
`gpiodetect` command and **o** is the line number seen by the`
|
||||
gpioinfo` command.
|
||||
|
||||
***Warning:*** only gpio marked as `unused` can be used. It is not
|
||||
possible for a _line_ to be used by multiple processes simultaneously.
|
||||
|
||||
For example on a RPi 3B+ where klipper use the GPIO20 for a switch:
|
||||
```
|
||||
$ gpiodetect
|
||||
gpiochip0 [pinctrl-bcm2835] (54 lines)
|
||||
gpiochip1 [raspberrypi-exp-gpio] (8 lines)
|
||||
|
||||
$ gpioinfo
|
||||
gpiochip0 - 54 lines:
|
||||
line 0: unnamed unused input active-high
|
||||
line 1: unnamed unused input active-high
|
||||
line 2: unnamed unused input active-high
|
||||
line 3: unnamed unused input active-high
|
||||
line 4: unnamed unused input active-high
|
||||
line 5: unnamed unused input active-high
|
||||
line 6: unnamed unused input active-high
|
||||
line 7: unnamed unused input active-high
|
||||
line 8: unnamed unused input active-high
|
||||
line 9: unnamed unused input active-high
|
||||
line 10: unnamed unused input active-high
|
||||
line 11: unnamed unused input active-high
|
||||
line 12: unnamed unused input active-high
|
||||
line 13: unnamed unused input active-high
|
||||
line 14: unnamed unused input active-high
|
||||
line 15: unnamed unused input active-high
|
||||
line 16: unnamed unused input active-high
|
||||
line 17: unnamed unused input active-high
|
||||
line 18: unnamed unused input active-high
|
||||
line 19: unnamed unused input active-high
|
||||
line 20: unnamed "klipper" output active-high [used]
|
||||
line 21: unnamed unused input active-high
|
||||
line 22: unnamed unused input active-high
|
||||
line 23: unnamed unused input active-high
|
||||
line 24: unnamed unused input active-high
|
||||
line 25: unnamed unused input active-high
|
||||
line 26: unnamed unused input active-high
|
||||
line 27: unnamed unused input active-high
|
||||
line 28: unnamed unused input active-high
|
||||
line 29: unnamed "led0" output active-high [used]
|
||||
line 30: unnamed unused input active-high
|
||||
line 31: unnamed unused input active-high
|
||||
line 32: unnamed unused input active-high
|
||||
line 33: unnamed unused input active-high
|
||||
line 34: unnamed unused input active-high
|
||||
line 35: unnamed unused input active-high
|
||||
line 36: unnamed unused input active-high
|
||||
line 37: unnamed unused input active-high
|
||||
line 38: unnamed unused input active-high
|
||||
line 39: unnamed unused input active-high
|
||||
line 40: unnamed unused input active-high
|
||||
line 41: unnamed unused input active-high
|
||||
line 42: unnamed unused input active-high
|
||||
line 43: unnamed unused input active-high
|
||||
line 44: unnamed unused input active-high
|
||||
line 45: unnamed unused input active-high
|
||||
line 46: unnamed unused input active-high
|
||||
line 47: unnamed unused input active-high
|
||||
line 48: unnamed unused input active-high
|
||||
line 49: unnamed unused input active-high
|
||||
line 50: unnamed unused input active-high
|
||||
line 51: unnamed unused input active-high
|
||||
line 52: unnamed unused input active-high
|
||||
line 53: unnamed unused input active-high
|
||||
gpiochip1 - 8 lines:
|
||||
line 0: unnamed unused input active-high
|
||||
line 1: unnamed unused input active-high
|
||||
line 2: unnamed "led1" output active-low [used]
|
||||
line 3: unnamed unused input active-high
|
||||
line 4: unnamed unused input active-high
|
||||
line 5: unnamed unused input active-high
|
||||
line 6: unnamed unused input active-high
|
||||
line 7: unnamed unused input active-high
|
||||
```
|
||||
|
||||
## Optional: Hardware PWM
|
||||
|
||||
Raspberry Pi's have two PWM channels (PWM0 and PWM1) which are exposed
|
||||
on the header or if not, can be routed to existing gpio pins. The
|
||||
Linux mcu daemon uses the pwmchip sysfs interface to control hardware
|
||||
pwm devices on Linux hosts. The pwm sysfs interface is not exposed by
|
||||
default on a Raspberry and can be activated by adding a line to
|
||||
`/boot/config.txt`:
|
||||
```
|
||||
# Enable pwmchip sysfs interface
|
||||
dtoverlay=pwm,pin=12,func=4
|
||||
```
|
||||
This example enables only PWM0 and routes it to gpio12. If both PWM
|
||||
channels need to be enabled you can use `pwm-2chan`.
|
||||
|
||||
The overlay does not expose the pwm line on sysfs on boot and needs to
|
||||
be exported by echo'ing the number of the pwm channel to
|
||||
`/sys/class/pwm/pwmchip0/export`:
|
||||
```
|
||||
echo 0 > /sys/class/pwm/pwmchip0/export
|
||||
```
|
||||
|
||||
This will create device `/sys/class/pwm/pwmchip0/pwm0` in the
|
||||
filesystem. The easiest way to do this is by adding this to
|
||||
`/etc/rc.local` before the `exit 0` line.
|
||||
|
||||
With the sysfs in place, you can now use either the pwm channel(s) by
|
||||
adding the following piece of configuration to your `printer.cfg`:
|
||||
```
|
||||
[output_pin caselight]
|
||||
pin: host:pwmchip0/pwm0
|
||||
pwm: True
|
||||
hardware_pwm: True
|
||||
cycle_time: 0.000001
|
||||
```
|
||||
This will add hardware pwm control to gpio12 on the Pi (because the
|
||||
overlay was configured to route pwm0 to pin=12).
|
||||
|
||||
PWM0 can be routed to gpio12 and gpio18, PWM1 can be routed to gpio13
|
||||
and gpio19:
|
||||
|
||||
| PWM | gpio PIN | Func |
|
||||
| --- | -------- | ---- |
|
||||
| 0 | 12 | 4 |
|
||||
| 0 | 18 | 2 |
|
||||
| 1 | 13 | 4 |
|
||||
| 1 | 19 | 2 |
|
||||
248
docs/Releases.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# Releases
|
||||
|
||||
History of Klipper releases. Please see
|
||||
[installation](Installation.md) for information on installing Klipper.
|
||||
|
||||
## Klipper 0.10.0
|
||||
|
||||
Available on 20210929. Major changes in this release:
|
||||
* Support for "Multi-MCU Homing". It is now possible for a stepper
|
||||
motor and its endstop to be wired to separate micro-controllers.
|
||||
This simplifies wiring of Z probes on "toolhead boards".
|
||||
* Klipper now has a
|
||||
[Community Discord Server](https://discord.klipper3d.org)
|
||||
and a [Community Discourse Server](https://community.klipper3d.org).
|
||||
* The [Klipper website](https://www.klipper3d.org) now uses the
|
||||
"mkdocs" infrastructure. There is also a
|
||||
[Klipper Translations](https://github.com/Klipper3d/klipper-translations)
|
||||
project.
|
||||
* Automated support for flashing firmware via sdcard on many boards.
|
||||
* New kinematic support for "Hybrid CoreXY" and "Hybrid CoreXZ"
|
||||
printers.
|
||||
* Klipper now uses `rotation_distance` to configure stepper motor
|
||||
travel distances.
|
||||
* The main Klipper host code can now directly communicate with
|
||||
micro-controllers using CAN bus.
|
||||
* New "motion analysis" system. Klipper's internal motion updates and
|
||||
sensor results can be tracked and logged for analysis.
|
||||
* Trinamic stepper motor drivers are now continuously monitored for
|
||||
error conditions.
|
||||
* Support for the rp2040 micro-controller (Raspberry Pi Pico boards).
|
||||
* The "make menuconfig" system now utilizes kconfiglib.
|
||||
* Many additional modules added: ds18b20, duplicate_pin_override,
|
||||
filament_motion_sensor, palette2, motion_report, pca9533,
|
||||
pulse_counter, save_variables, sdcard_loop, temperature_host,
|
||||
temperature_mcu
|
||||
* Several bug fixes and code cleanups.
|
||||
|
||||
## Klipper 0.9.0
|
||||
|
||||
Available on 20201020. Major changes in this release:
|
||||
* Support for "Input Shaping" - a mechanism to counteract printer
|
||||
resonance. It can reduce or eliminate "ringing" in prints.
|
||||
* New "Smooth Pressure Advance" system. This implements "Pressure
|
||||
Advance" without introducing instantaneous velocity changes. It is
|
||||
also now possible to tune pressure advance using a "Tuning Tower"
|
||||
method.
|
||||
* New "webhooks" API server. This provides a programmable JSON
|
||||
interface to Klipper.
|
||||
* The LCD display and menu are now configurable using the Jinja2
|
||||
template language.
|
||||
* The TMC2208 stepper motor drivers can now be used in "standalone"
|
||||
mode with Klipper.
|
||||
* Improved BL-Touch v3 support.
|
||||
* Improved USB identification. Klipper now has its own USB
|
||||
identification code and micro-controllers can now report their
|
||||
unique serial numbers during USB identification.
|
||||
* New kinematic support for "Rotary Delta" and "CoreXZ" printers.
|
||||
* Micro-controller improvements: support for stm32f070, support for
|
||||
stm32f207, support for GPIO pins on "Linux MCU", stm32 "HID
|
||||
bootloader" support, Chitu bootloader support, MKS Robin bootloader
|
||||
support.
|
||||
* Improved handling of Python "garbage collection" events.
|
||||
* Many additional modules added: adc_scaled, adxl345, bme280,
|
||||
display_status, extruder_stepper, fan_generic,
|
||||
hall_filament_width_sensor, htu21d, homing_heaters, input_shaper,
|
||||
lm75, print_stats, resonance_tester, shaper_calibrate, query_adc,
|
||||
graph_accelerometer, graph_extruder, graph_motion, graph_shaper,
|
||||
graph_temp_sensor, whconsole
|
||||
* Several bug fixes and code cleanups.
|
||||
|
||||
### Klipper 0.9.1
|
||||
|
||||
Available on 20201028. Release containing only bug fixes.
|
||||
|
||||
## Klipper 0.8.0
|
||||
|
||||
Available on 20191021. Major changes in this release:
|
||||
* New G-Code command template support. G-Code in the config file is
|
||||
now evaluated with the Jinja2 template language.
|
||||
* Improvements to Trinamic stepper drivers:
|
||||
* New support for TMC2209 and TMC5160 drivers.
|
||||
* Improved DUMP_TMC, SET_TMC_CURRENT, and INIT_TMC G-Code commands.
|
||||
* Improved support for TMC UART handling with an analog mux.
|
||||
* Improved homing, probing, and bed leveling support:
|
||||
* New manual_probe, bed_screws, screws_tilt_adjust, skew_correction,
|
||||
safe_z_home modules added.
|
||||
* Enhanced multi-sample probing with median, average, and retry
|
||||
logic.
|
||||
* Improved documentation for BL-Touch, probe calibration, endstop
|
||||
calibration, delta calibration, sensorless homing, and endstop
|
||||
phase calibration.
|
||||
* Improved homing support on a large Z axis.
|
||||
* Many Klipper micro-controller improvements:
|
||||
* Klipper ported to: SAM3X8C, SAM4S8C, SAMD51, STM32F042, STM32F4
|
||||
* New USB CDC driver implementations on SAM3X, SAM4, STM32F4.
|
||||
* Enhanced support for flashing Klipper over USB.
|
||||
* Software SPI support.
|
||||
* Greatly improved temperature filtering on the LPC176x.
|
||||
* Early output pin settings can be configured in the
|
||||
micro-controller.
|
||||
* New website with the Klipper documentation: http://klipper3d.org/
|
||||
* Klipper now has a logo.
|
||||
* Experimental support for polar and "cable winch" kinematics.
|
||||
* The config file can now include other config files.
|
||||
* Many additional modules added: board_pins, controller_fan,
|
||||
delayed_gcode, dotstar, filament_switch_sensor, firmware_retraction,
|
||||
gcode_arcs, gcode_button, heater_generic, manual_stepper, mcp4018,
|
||||
mcp4728, neopixel, pause_resume, respond, temperature_sensor
|
||||
tsl1401cl_filament_width_sensor, tuning_tower
|
||||
* Many additional commands added: RESTORE_GCODE_STATE,
|
||||
SAVE_GCODE_STATE, SET_GCODE_VARIABLE, SET_HEATER_TEMPERATURE,
|
||||
SET_IDLE_TIMEOUT, SET_TEMPERATURE_FAN_TARGET
|
||||
* Several bug fixes and code cleanups.
|
||||
|
||||
## Klipper 0.7.0
|
||||
|
||||
Available on 20181220. Major changes in this release:
|
||||
* Klipper now supports "mesh" bed leveling
|
||||
* New support for "enhanced" delta calibration (calibrates print x/y
|
||||
dimensions on delta printers)
|
||||
* Support for run-time configuration of Trinamic stepper motor drivers
|
||||
(tmc2130, tmc2208, tmc2660)
|
||||
* Improved temperature sensor support: MAX6675, MAX31855, MAX31856,
|
||||
MAX31865, custom thermistors, common pt100 style sensors
|
||||
* Several new modules: temperature_fan, sx1509, force_move, mcp4451,
|
||||
z_tilt, quad_gantry_level, endstop_phase, bltouch
|
||||
* Several new commands added: SAVE_CONFIG, SET_PRESSURE_ADVANCE,
|
||||
SET_GCODE_OFFSET, SET_VELOCITY_LIMIT, STEPPER_BUZZ, TURN_OFF_HEATERS,
|
||||
M204, custom g-code macros
|
||||
* Expanded LCD display support:
|
||||
* Support for run-time menus
|
||||
* New display icons
|
||||
* Support for "uc1701" and "ssd1306" displays
|
||||
* Additional micro-controller support:
|
||||
* Klipper ported to: LPC176x (Smoothieboards), SAM4E8E (Duet2),
|
||||
SAMD21 (Arduino Zero), STM32F103 ("Blue pill" devices), atmega32u4
|
||||
* New Generic USB CDC driver implemented on AVR, LPC176x, SAMD21, and
|
||||
STM32F103
|
||||
* Performance improvements on ARM processors
|
||||
* The kinematics code was rewritten to use an "iterative solver"
|
||||
* New automatic test cases for the Klipper host software
|
||||
* Many new example config files for common off-the-shelf printers
|
||||
* Documentation updates for bootloaders, benchmarking,
|
||||
micro-controller porting, config checks, pin mapping, slicer
|
||||
settings, packaging, and more
|
||||
* Several bug fixes and code cleanups
|
||||
|
||||
## Klipper 0.6.0
|
||||
|
||||
Available on 20180331. Major changes in this release:
|
||||
* Enhanced heater and thermistor hardware failure checks
|
||||
* Support for Z probes
|
||||
* Initial support for automatic parameter calibration on deltas (via a
|
||||
new delta_calibrate command)
|
||||
* Initial support for bed tilt compensation (via bed_tilt_calibrate
|
||||
command)
|
||||
* Initial support for "safe homing" and homing overrides
|
||||
* Initial support for displaying status on RepRapDiscount style 2004
|
||||
and 12864 displays
|
||||
* New multi-extruder improvements:
|
||||
* Support for shared heaters
|
||||
* Initial support for dual carriages
|
||||
* Support for configuring multiple steppers per axis (eg, dual Z)
|
||||
* Support for custom digital and pwm output pins (with a new SET_PIN command)
|
||||
* Initial support for a "virtual sdcard" that allows printing directly
|
||||
from Klipper (helps on machines too slow to run OctoPrint well)
|
||||
* Support for setting different arm lengths on each tower of a delta
|
||||
* Support for G-Code M220/M221 commands (speed factor override /
|
||||
extrude factor override)
|
||||
* Several documentation updates:
|
||||
* Many new example config files for common off-the-shelf printers
|
||||
* New multiple MCU config example
|
||||
* New bltouch sensor config example
|
||||
* New FAQ, config check, and G-Code documents
|
||||
* Initial support for continuous integration testing on all github commits
|
||||
* Several bug fixes and code cleanups
|
||||
|
||||
## Klipper 0.5.0
|
||||
|
||||
Available on 20171025. Major changes in this release:
|
||||
|
||||
* Support for printers with multiple extruders.
|
||||
* Initial support for running on the Beaglebone PRU. Initial support
|
||||
for the Replicape board.
|
||||
* Initial support for running the micro-controller code in a real-time
|
||||
Linux process.
|
||||
* Support for multiple micro-controllers. (For example, one could
|
||||
control an extruder with one micro-controller and the rest of the
|
||||
printer with another.) Software clock synchronization is implemented
|
||||
to coordinate actions between micro-controllers.
|
||||
* Stepper performance improvements (20Mhz AVRs up to 189K steps per
|
||||
second).
|
||||
* Support for controlling servos and support for defining nozzle
|
||||
cooling fans.
|
||||
* Several bug fixes and code cleanups
|
||||
|
||||
## Klipper 0.4.0
|
||||
|
||||
Available on 20170503. Major changes in this release:
|
||||
|
||||
* Improved installation on Raspberry Pi machines. Most of the install
|
||||
is now scripted.
|
||||
* Support for corexy kinematics
|
||||
* Documentation updates: New Kinematics document, new Pressure Advance
|
||||
tuning guide, new example config files, and more
|
||||
* Stepper performance improvements (20Mhz AVRs over 175K steps per
|
||||
second, Arduino Due over 460K)
|
||||
* Support for automatic micro-controller resets. Support for resets
|
||||
via toggling USB power on Raspberry Pi.
|
||||
* The pressure advance algorithm now works with look-ahead to reduce
|
||||
pressure changes during cornering.
|
||||
* Support for limiting the top speed of short zigzag moves
|
||||
* Support for AD595 sensors
|
||||
* Several bug fixes and code cleanups
|
||||
|
||||
## Klipper 0.3.0
|
||||
|
||||
Available on 20161223. Major changes in this release:
|
||||
|
||||
* Improved documentation
|
||||
* Support for robots with delta kinematics
|
||||
* Support for Arduino Due micro-controller (ARM cortex-M3)
|
||||
* Support for USB based AVR micro-controllers
|
||||
* Support for "pressure advance" algorithm - it reduces ooze during
|
||||
prints.
|
||||
* New "stepper phased based endstop" feature - enables higher
|
||||
precision on endstop homing.
|
||||
* Support for "extended g-code" commands such as "help", "restart",
|
||||
and "status".
|
||||
* Support for reloading the Klipper config and restarting the host
|
||||
software by issuing a "restart" command from the terminal.
|
||||
* Stepper performance improvements (20Mhz AVRs up to 158K steps per
|
||||
second).
|
||||
* Improved error reporting. Most errors now shown via the terminal
|
||||
along with help on how to resolve.
|
||||
* Several bug fixes and code cleanups
|
||||
|
||||
## Klipper 0.2.0
|
||||
|
||||
Initial release of Klipper. Available on 20160525. Major features
|
||||
available in the initial release include:
|
||||
|
||||
* Basic support for cartesian printers (steppers, extruder, heated
|
||||
bed, cooling fan).
|
||||
* Support for common g-code commands. Support for interfacing with
|
||||
OctoPrint.
|
||||
* Acceleration and lookahead handling
|
||||
* Support for AVR micro-controllers via standard serial ports
|
||||
499
docs/Resonance_Compensation.md
Normal file
@@ -0,0 +1,499 @@
|
||||
# Resonance Compensation
|
||||
|
||||
Klipper supports Input Shaping - a technique that can be used to reduce ringing
|
||||
(also known as echoing, ghosting or rippling) in prints. Ringing is a surface
|
||||
printing defect when, typically, elements like edges repeat themselves on a
|
||||
printed surface as a subtle 'echo':
|
||||
|
||||
|||
|
||||
|
||||
Ringing is caused by mechanical vibrations in the printer due to quick changes
|
||||
of the printing direction. Note that ringing usually has mechanical origins:
|
||||
insufficiently rigid printer frame, non-tight or too springy belts, alignment
|
||||
issues of mechanical parts, heavy moving mass, etc. Those should be checked
|
||||
and fixed first, if possible.
|
||||
|
||||
|
||||
[Input shaping](https://en.wikipedia.org/wiki/Input_shaping) is an open-loop
|
||||
control technique which creates a commanding signal that cancels its
|
||||
own vibrations. Input shaping requires some tuning and measurements before it
|
||||
can be enabled. Besides ringing, Input Shaping typically reduces the vibrations
|
||||
and shaking of the printer in general, and may also improve the reliability
|
||||
of the stealthChop mode of Trinamic stepper drivers.
|
||||
|
||||
## Tuning
|
||||
|
||||
Basic tuning requires measuring the ringing frequencies of the printer
|
||||
by printing a test model.
|
||||
|
||||
Slice the ringing test model, which can be found in
|
||||
[docs/prints/ringing_tower.stl](prints/ringing_tower.stl), in the slicer:
|
||||
|
||||
* Suggested layer height is 0.2 or 0.25 mm.
|
||||
* Infill and top layers can be set to 0.
|
||||
* Use 1-2 perimeters, or even better the smooth vase mode with 1-2 mm base.
|
||||
* Use sufficiently high speed, around 80-100 mm/sec, for **external** perimeters.
|
||||
* Make sure that the minimum layer time is **at most** 3 seconds.
|
||||
* Make sure any "dynamic acceleration control" is disabled in the slicer.
|
||||
* Do not turn the model. The model has X and Y marks at the back of the model.
|
||||
Note the unusual location of the marks vs. the axes of the printer - it is
|
||||
not a mistake. The marks can be used later in the tuning process as a
|
||||
reference, because they show which axis the measurements correspond to.
|
||||
|
||||
### Ringing frequency
|
||||
|
||||
First, measure the **ringing frequency**.
|
||||
|
||||
1. If `square_corner_velocity` parameter was changed, revert it back
|
||||
to 5.0. It is not advised to increase it when using input shaper
|
||||
because it can cause more smoothing in parts - it is better to use
|
||||
higher acceleration value instead.
|
||||
2. Increase `max_accel_to_decel` by issuing the following command:
|
||||
`SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
|
||||
3. Disable Pressure Advance: `SET_PRESSURE_ADVANCE ADVANCE=0`
|
||||
4. If you have already added `[input_shaper]` section to the printer.cfg,
|
||||
execute `SET_INPUT_SHAPER SHAPER_FREQ_X=0 SHAPER_FREQ_Y=0` command. If you
|
||||
get "Unknown command" error, you can safely ignore it at this point and
|
||||
continue with the measurements.
|
||||
5. Execute the command:
|
||||
`TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
|
||||
Basically, we try to make ringing more pronounced by setting different large
|
||||
values for acceleration. This command will increase the acceleration every
|
||||
5 mm starting from 1500 mm/sec^2: 1500 mm/sec^2, 2000 mm/sec^2, 2500 mm/sec^2
|
||||
and so forth up until 7000 mm/sec^2 at the last band.
|
||||
6. Print the test model sliced with the suggested parameters.
|
||||
7. You can stop the print earlier if the ringing is clearly visible and you see
|
||||
that acceleration gets too high for your printer (e.g. printer shakes too
|
||||
much or starts skipping steps).
|
||||
8. Use X and Y marks at the back of the model for reference. The measurements
|
||||
from the side with X mark should be used for X axis *configuration*, and
|
||||
Y mark - for Y axis configuration. Measure the distance *D* (in mm) between
|
||||
several oscillations on the part with X mark, near the notches, preferably
|
||||
skipping the first oscillation or two. To measure the distance between
|
||||
oscillations more easily, mark the oscillations first, then measure the
|
||||
distance between the marks with a ruler or calipers:
|
||||
|
||||
|||
|
||||
|
||||
9. Count how many oscillations *N* the measured distance *D* corresponds to.
|
||||
If you are unsure how to count the oscillations, refer to the picture
|
||||
above, which shows *N* = 6 oscillations.
|
||||
10. Compute the ringing frequency of X axis as *V* · *N* / *D* (Hz),
|
||||
where *V* is the velocity for outer perimeters (mm/sec). For the example
|
||||
above, we marked 6 oscillations, and the test was printed at 100 mm/sec
|
||||
velocity, so the frequency is 100 * 6 / 12.14 ≈ 49.4 Hz.
|
||||
11. Do (8) - (10) for Y mark as well.
|
||||
|
||||
Note that ringing on the test print should follow the pattern of the curved
|
||||
notches, as in the picture above. If it doesn't, then this defect is not really
|
||||
a ringing and has a different origin - either mechanical, or an extruder issue.
|
||||
It should be fixed first before enabling and tuning input shapers.
|
||||
|
||||
If the measurements are not reliable because, say, the distance
|
||||
between the oscillations is not stable, it might mean that the printer has
|
||||
several resonance frequencies on the same axis. One may try to follow the
|
||||
tuning process described in
|
||||
[Unreliable measurements of ringing frequencies](#unreliable-measurements-of-ringing-frequencies)
|
||||
section instead and still get something out of the input shaping technique.
|
||||
|
||||
Ringing frequency can depend on the position of the model within the buildplate
|
||||
and Z height, *especially on delta printers*; you can check if you see the
|
||||
differences in frequencies at different positions along the sides of the test
|
||||
model and at different heights. You can calculate the average ringing
|
||||
frequencies over X and Y axes if that is the case.
|
||||
|
||||
If the measured ringing frequency is very low (below approx 20-25 Hz), it might
|
||||
be a good idea to invest into stiffening the printer or decreasing the moving
|
||||
mass - depending on what is applicable in your case - before proceeding with
|
||||
further input shaping tuning, and re-measuring the frequencies afterwards. For
|
||||
many popular printer models there are often some solutions available already.
|
||||
|
||||
Note that the ringing frequencies can change if the changes are made to the
|
||||
printer that affect the moving mass or change the stiffness of the system,
|
||||
for example:
|
||||
|
||||
* Some tools are installed, removed or replaced on the toolhead that change
|
||||
its mass, e.g. a new (heavier or lighter) stepper motor for direct extruder
|
||||
or a new hotend is installed, heavy fan with a duct is added, etc.
|
||||
* Belts are tightened.
|
||||
* Some addons to increase frame rigidity are installed.
|
||||
* Different bed is installed on a bed-slinger printer, or glass added, etc.
|
||||
|
||||
If such changes are made, it is a good idea to at least measure the ringing
|
||||
frequencies to see if they have changed.
|
||||
|
||||
### Input shaper configuration
|
||||
|
||||
After the ringing frequencies for X and Y axes are measured, you can add the
|
||||
following section to your `printer.cfg`:
|
||||
```
|
||||
[input_shaper]
|
||||
shaper_freq_x: ... # frequency for the X mark of the test model
|
||||
shaper_freq_y: ... # frequency for the Y mark of the test model
|
||||
```
|
||||
|
||||
For the example above, we get shaper_freq_x/y = 49.4.
|
||||
|
||||
### Choosing input shaper
|
||||
|
||||
Klipper supports several input shapers. They differ in their sensitivity to
|
||||
errors determining the resonance frequency and how much smoothing they cause
|
||||
in the printed parts. Also, some of the shapers like 2HUMP_EI and 3HUMP_EI
|
||||
should usually not be used with shaper_freq = resonance frequency - they are
|
||||
configured from different considerations to reduce several resonances at once.
|
||||
|
||||
For most of the printers, either MZV or EI shapers can be recommended. This
|
||||
section describes a testing process to choose between them, and figure out
|
||||
a few other related parameters.
|
||||
|
||||
Print the ringing test model as follows:
|
||||
|
||||
1. Restart the firmware: `RESTART`
|
||||
2. Prepare for test: `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
|
||||
3. Disable Pressure Advance: `SET_PRESSURE_ADVANCE ADVANCE=0`
|
||||
4. Execute: `SET_INPUT_SHAPER SHAPER_TYPE=MZV`
|
||||
5. Execute the command:
|
||||
`TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
|
||||
6. Print the test model sliced with the suggested parameters.
|
||||
|
||||
If you see no ringing at this point, then MZV shaper can be recommended for use.
|
||||
|
||||
If you do see some ringing, re-measure the frequencies using steps (8)-(10)
|
||||
described in [Ringing frequency](#ringing-frequency) section. If the frequencies
|
||||
differ significantly from the values you obtained earlier, a more complex input
|
||||
shaper configuration is needed. You can refer to Technical details of
|
||||
[Input shapers](#input-shapers) section. Otherwise, proceed to the next step.
|
||||
|
||||
Now try EI input shaper. To try it, repeat steps (1)-(6) from above, but
|
||||
executing at step 4 the following command instead:
|
||||
`SET_INPUT_SHAPER SHAPER_TYPE=EI`.
|
||||
|
||||
Compare two prints with MZV and EI input shaper. If EI shows noticeably better
|
||||
results than MZV, use EI shaper, otherwise prefer MZV. Note that EI shaper will
|
||||
cause more smoothing in printed parts (see the next section for further
|
||||
details). Add `shaper_type: mzv` (or ei) parameter to [input_shaper] section,
|
||||
e.g.:
|
||||
```
|
||||
[input_shaper]
|
||||
shaper_freq_x: ...
|
||||
shaper_freq_y: ...
|
||||
shaper_type: mzv
|
||||
```
|
||||
|
||||
A few notes on shaper selection:
|
||||
|
||||
* EI shaper may be more suited for bed slinger printers (if the resonance
|
||||
frequency and resulting smoothing allows): as more filament is deposited
|
||||
on the moving bed, the mass of the bed increases and the resonance frequency
|
||||
will decrease. Since EI shaper is more robust to resonance frequency
|
||||
changes, it may work better when printing large parts.
|
||||
* Due to the nature of delta kinematics, resonance frequencies can differ a
|
||||
lot in different parts of the build volume. Therefore, EI shaper can be a
|
||||
better fit for delta printers rather than MZV or ZV, and should be
|
||||
considered for the use. If the resonance frequency is sufficiently large
|
||||
(more than 50-60 Hz), then one can even attempt to test 2HUMP_EI shaper
|
||||
(by running the suggested test above with
|
||||
`SET_INPUT_SHAPER SHAPER_TYPE=2HUMP_EI`), but check the considerations in
|
||||
the [section below](#selecting-max_accel) before enabling it.
|
||||
|
||||
### Selecting max_accel
|
||||
|
||||
You should have a printed test for the shaper you chose from the previous step
|
||||
(if you don't, print the test model sliced with the
|
||||
[suggested parameters](#tuning) with the pressure advance disabled
|
||||
`SET_PRESSURE_ADVANCE ADVANCE=0` and with the tuning tower enabled as
|
||||
`TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`).
|
||||
Note that at very high accelerations, depending on the resonance frequency and
|
||||
the input shaper you chose (e.g. EI shaper creates more smoothing than MZV),
|
||||
input shaping may cause too much smoothing and rounding of the parts. So,
|
||||
max_accel should be chosen such as to prevent that. Another parameter that can
|
||||
impact smoothing is `square_corner_velocity`, so it is not advisable to increase
|
||||
it above the default 5 mm/sec to prevent increased smoothing.
|
||||
|
||||
In order to select a suitable max_accel value, inspect the model for the chosen
|
||||
input shaper. First, take a note at which acceleration ringing is still small -
|
||||
that you are comfortable with it.
|
||||
|
||||
Next, check the smoothing. To help with that, the test model has a small gap
|
||||
in the wall (0.15 mm):
|
||||
|
||||

|
||||
|
||||
As the acceleration increases, so does the smoothing, and the actual gap in
|
||||
the print widens:
|
||||
|
||||

|
||||
|
||||
In this picture, the acceleration increases left to right, and the gap starts
|
||||
to grow starting from 3500 mm/sec^2 (5-th band from the left). So the good
|
||||
value for max_accel = 3000 (mm/sec^2) in this case to avoid the excessive
|
||||
smoothing.
|
||||
|
||||
Note the acceleration when the gap is still very small in your test print.
|
||||
If you see bulges, but no gap in the wall at all, even at high accelerations,
|
||||
it may be due to disabled Pressure Advance, especially on Bowden extruders.
|
||||
If that is the case, you may need to repeat the print with the PA enabled.
|
||||
It may also be a result of a miscalibrated (too high) filament flow, so it is
|
||||
a good idea to check that too.
|
||||
|
||||
Choose the minimum out of the two acceleration values (from ringing and
|
||||
smoothing), and put it as `max_accel` into printer.cfg.
|
||||
|
||||
|
||||
As a note, it may happen - especially at low ringing frequencies - that EI
|
||||
shaper will cause too much smoothing even at lower accelerations. In this case,
|
||||
MZV may be a better choice, because it may allow higher acceleration values.
|
||||
|
||||
At very low ringing frequencies (~25 Hz and below) even MZV shaper may create
|
||||
too much smoothing. If that is the case, you can also try to repeat the
|
||||
steps in [Choosing input shaper](#choosing-input-shaper) section with ZV shaper,
|
||||
by using `SET_INPUT_SHAPER SHAPER_TYPE=ZV` command instead. ZV shaper should
|
||||
show even less smoothing than MZV, but is more sensitive to errors in measuring
|
||||
the ringing frequencies.
|
||||
|
||||
Another consideration is that if a resonance frequency is too low (below 20-25
|
||||
Hz), it might be a good idea to increase the printer stiffness or reduce the
|
||||
moving mass. Otherwise, acceleration and printing speed may be limited due too
|
||||
much smoothing now instead of ringing.
|
||||
|
||||
|
||||
### Fine-tuning resonance frequencies
|
||||
|
||||
Note that the precision of the resonance frequencies measurements using the
|
||||
ringing test model is sufficient for most purposes, so further tuning is not
|
||||
advised. If you still want to try to double-check your results (e.g. if you
|
||||
still see some ringing after printing a test model with an input shaper of
|
||||
your choice with the same frequencies as you have measured earlier), you can
|
||||
follow the steps in this section. Note that if you see ringing at different
|
||||
frequencies after enabling [input_shaper], this section will not help with that.
|
||||
|
||||
Assuming that you have sliced the ringing model with suggested
|
||||
parameters, complete the following steps for each of the axes X and Y:
|
||||
|
||||
1. Prepare for test: `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
|
||||
2. Make sure Pressure Advance is disabled: `SET_PRESSURE_ADVANCE ADVANCE=0`
|
||||
3. Execute: `SET_INPUT_SHAPER SHAPER_TYPE=ZV`
|
||||
4. From the existing ringing test model with your chosen input shaper select
|
||||
the acceleration that shows ringing sufficiently well, and set it with:
|
||||
`SET_VELOCITY_LIMIT ACCEL=...`
|
||||
5. Calculate the necessary parameters for the `TUNING_TOWER` command to tune
|
||||
`shaper_freq_x` parameter as follows: start = shaper_freq_x * 83 / 132 and
|
||||
factor = shaper_freq_x / 66, where `shaper_freq_x` here is the current value
|
||||
in `printer.cfg`.
|
||||
6. Execute the command:
|
||||
`TUNING_TOWER COMMAND=SET_INPUT_SHAPER PARAMETER=SHAPER_FREQ_X START=start FACTOR=factor BAND=5`
|
||||
using `start` and `factor` values calculated at step (5).
|
||||
7. Print the test model.
|
||||
8. Reset the original frequency value:
|
||||
`SET_INPUT_SHAPER SHAPER_FREQ_X=...`.
|
||||
9. Find the band which shows ringing the least and count its number from the
|
||||
bottom starting at 1.
|
||||
10. Calculate the new shaper_freq_x value via old
|
||||
shaper_freq_x * (39 + 5 * #band-number) / 66.
|
||||
|
||||
Repeat these steps for the Y axis in the same manner, replacing references to X
|
||||
axis with the axis Y (e.g. replace `shaper_freq_x` with `shaper_freq_y` in
|
||||
the formulae and in the `TUNING_TOWER` command).
|
||||
|
||||
As an example, let's assume you have had measured the ringing frequency for one
|
||||
of the axis equal to 45 Hz. This gives start = 45 * 83 / 132 = 28.30
|
||||
and factor = 45 / 66 = 0.6818 values for `TUNING_TOWER` command.
|
||||
Now let's assume that after printing the test model, the fourth band from the
|
||||
bottom gives the least ringing. This gives the updated shaper_freq_? value
|
||||
equal to 45 * (39 + 5 * 4) / 66 ≈ 40.23.
|
||||
|
||||
After both new `shaper_freq_x` and `shaper_freq_y` parameters have been
|
||||
calculated, you can update `[input_shaper]` section in `printer.cfg` with the
|
||||
new `shaper_freq_x` and `shaper_freq_y` values.
|
||||
|
||||
### Pressure Advance
|
||||
|
||||
If you use Pressure Advance, it may need to be re-tuned. Follow the
|
||||
[instructions](Pressure_Advance.md#tuning-pressure-advance) to find
|
||||
the new value, if it differs from the previous one. Make sure to
|
||||
restart Klipper before tuning Pressure Advance.
|
||||
|
||||
### Unreliable measurements of ringing frequencies
|
||||
|
||||
If you are unable to measure the ringing frequencies, e.g. if the distance
|
||||
between the oscillations is not stable, you may still be able to take advantage
|
||||
of input shaping techniques, but the results may not be as good as with proper
|
||||
measurements of the frequencies, and will require a bit more tuning and printing
|
||||
the test model. Note that another possibility is to purchase and install an
|
||||
accelerometer and measure the resonances with it (refer to the
|
||||
[docs](Measuring_Resonances.md) describing the required hardware and the setup
|
||||
process) - but this option requires some crimping and soldering.
|
||||
|
||||
|
||||
For tuning, add empty `[input_shaper]` section to your
|
||||
`printer.cfg`. Then, assuming that you have sliced the ringing model
|
||||
with suggested parameters, print the test model 3 times as
|
||||
follows. First time, prior to printing, run
|
||||
|
||||
1. `RESTART`
|
||||
2. `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
|
||||
3. `SET_PRESSURE_ADVANCE ADVANCE=0`
|
||||
4. `SET_INPUT_SHAPER SHAPER_TYPE=2HUMP_EI SHAPER_FREQ_X=60 SHAPER_FREQ_Y=60`
|
||||
5. `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
|
||||
|
||||
and print the model. Then print the model again, but before printing run instead
|
||||
|
||||
1. `SET_INPUT_SHAPER SHAPER_TYPE=2HUMP_EI SHAPER_FREQ_X=50 SHAPER_FREQ_Y=50`
|
||||
2. `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
|
||||
|
||||
Then print the model for the 3rd time, but now run
|
||||
|
||||
1. `SET_INPUT_SHAPER SHAPER_TYPE=2HUMP_EI SHAPER_FREQ_X=40 SHAPER_FREQ_Y=40`
|
||||
2. `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
|
||||
|
||||
Essentially, we are printing the ringing test model with TUNING_TOWER using
|
||||
2HUMP_EI shaper with shaper_freq = 60 Hz, 50 Hz, and 40 Hz.
|
||||
|
||||
If none of the models demonstrate improvements in ringing, then, unfortunately,
|
||||
it does not look like the input shaping techniques can help with your case.
|
||||
|
||||
Otherwise, it may be that all models show no ringing, or some show the ringing
|
||||
and some - not so much. Choose the test model with the highest frequency that
|
||||
still shows good improvements in ringing. For example, if 40 Hz and 50 Hz models
|
||||
show almost no ringing, and 60 Hz model already shows some more ringing, stick
|
||||
with 50 Hz.
|
||||
|
||||
Now check if EI shaper would be good enough in your case. Choose EI shaper
|
||||
frequency based on the frequency of 2HUMP_EI shaper you chose:
|
||||
|
||||
* For 2HUMP_EI 60 Hz shaper, use EI shaper with shaper_freq = 50 Hz.
|
||||
* For 2HUMP_EI 50 Hz shaper, use EI shaper with shaper_freq = 40 Hz.
|
||||
* For 2HUMP_EI 40 Hz shaper, use EI shaper with shaper_freq = 33 Hz.
|
||||
|
||||
Now print the test model one more time, running
|
||||
|
||||
1. `SET_INPUT_SHAPER SHAPER_TYPE=EI SHAPER_FREQ_X=... SHAPER_FREQ_Y=...`
|
||||
2. `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
|
||||
|
||||
providing the shaper_freq_x=... and shaper_freq_y=... as determined previously.
|
||||
|
||||
If EI shaper shows very comparable good results as 2HUMP_EI shaper, stick with
|
||||
EI shaper and the frequency determined earlier, otherwise use 2HUMP_EI shaper
|
||||
with the corresponding frequency. Add the results to `printer.cfg` as, e.g.
|
||||
```
|
||||
[input_shaper]
|
||||
shaper_freq_x: 50
|
||||
shaper_freq_y: 50
|
||||
shaper_type: 2hump_ei
|
||||
```
|
||||
|
||||
Continue the tuning with [Selecting max_accel](#selecting-max_accel) section.
|
||||
|
||||
|
||||
## Troubleshooting and FAQ
|
||||
|
||||
### I cannot get reliable measurements of resonance frequencies
|
||||
|
||||
First, make sure it is not some other problem with the printer instead of
|
||||
ringing. If the measurements are not reliable because, say, the distance
|
||||
between the oscillations is not stable, it might mean that the printer has
|
||||
several resonance frequencies on the same axis. One may try to follow the
|
||||
tuning process described in
|
||||
[Unreliable measurements of ringing frequencies](#unreliable-measurements-of-ringing-frequencies)
|
||||
section and still get something out of the input shaping technique. Another
|
||||
possibility is to install an accelerometer, [measure](Measuring_Resonances.md)
|
||||
the resonances with it, and auto-tune the input shaper using the results of
|
||||
those measurements.
|
||||
|
||||
### After enabling [input_shaper], I get too smoothed printed parts and fine details are lost
|
||||
|
||||
Check the considerations in [Selecting max_accel](#selecting-max_accel) section.
|
||||
If the resonance frequency is low, one should not set too high max_accel or
|
||||
increase square_corner_velocity parameters. It might also be better to choose
|
||||
MZV or even ZV input shapers over EI (or 2HUMP_EI and 3HUMP_EI shapers).
|
||||
|
||||
|
||||
### After successfully printing for some time without ringing, it appears to come back
|
||||
|
||||
It is possible that after some time the resonance frequencies have changed.
|
||||
E.g. maybe the belts tension has changed (belts got more loose), etc. It is a
|
||||
good idea to check and re-measure the ringing frequencies as described in
|
||||
[Ringing frequency](#ringing-frequency) section and update your config file
|
||||
if necessary.
|
||||
|
||||
### Is dual carriage setup supported with input shapers?
|
||||
|
||||
There is no dedicated support for dual carriages with input shapers, but it does
|
||||
not mean this setup will not work. One should run the tuning twice for each
|
||||
of the carriages, and calculate the ringing frequencies for X and Y axes for
|
||||
each of the carriages independently. Then put the values for carriage 0 into
|
||||
[input_shaper] section, and change the values on the fly when changing
|
||||
carriages, e.g. as a part of some macro:
|
||||
```
|
||||
SET_DUAL_CARRIAGE CARRIAGE=1
|
||||
SET_INPUT_SHAPER SHAPER_FREQ_X=... SHAPER_FREQ_Y=...
|
||||
```
|
||||
|
||||
And similarly when switching back to carriage 0.
|
||||
|
||||
### Does input_shaper affect print time?
|
||||
|
||||
No, `input_shaper` feature has pretty much no impact on the print times by
|
||||
itself. However, the value of `max_accel` certainly does (tuning of this
|
||||
parameter described in [this section](#selecting-max_accel)).
|
||||
|
||||
## Technical details
|
||||
|
||||
### Input shapers
|
||||
|
||||
Input shapers used in Klipper are rather standard, and one can find more
|
||||
in-depth overview in the articles describing the corresponding shapers.
|
||||
This section contains a brief overview of some technical aspects of the
|
||||
supported input shapers. The table below shows some (usually approximate)
|
||||
parameters of each shaper.
|
||||
|
||||
| Input <br> shaper | Shaper <br> duration | Vibration reduction 20x <br> (5% vibration tolerance) | Vibration reduction 10x <br> (10% vibration tolerance) |
|
||||
|:--:|:--:|:--:|:--:|
|
||||
| ZV | 0.5 / shaper_freq | N/A | ± 5% shaper_freq |
|
||||
| MZV | 0.75 / shaper_freq | ± 4% shaper_freq | -10%...+15% shaper_freq |
|
||||
| ZVD | 1 / shaper_freq | ± 15% shaper_freq | ± 22% shaper_freq |
|
||||
| EI | 1 / shaper_freq | ± 20% shaper_freq | ± 25% shaper_freq |
|
||||
| 2HUMP_EI | 1.5 / shaper_freq | ± 35% shaper_freq | ± 40 shaper_freq |
|
||||
| 3HUMP_EI | 2 / shaper_freq | -45...+50% shaper_freq | -50%...+55% shaper_freq |
|
||||
|
||||
A note on vibration reduction: the values in the table above are approximate.
|
||||
If the damping ratio of the printer is known for each axis, the shaper can be
|
||||
configured more precisely and it will then reduce the resonances in a bit wider
|
||||
range of frequencies. However, the damping ratio is usually unknown and is hard
|
||||
to estimate without a special equipment, so Klipper uses 0.1 value by default,
|
||||
which is a good all-round value. The frequency ranges in the table cover a
|
||||
number of different possible damping ratios around that value (approx. from 0.05
|
||||
to 0.2).
|
||||
|
||||
Also note that EI, 2HUMP_EI, and 3HUMP_EI are tuned to reduce vibrations to 5%,
|
||||
so the values for 10% vibration tolerance are provided only for the reference.
|
||||
|
||||
**How to use this table:**
|
||||
|
||||
* Shaper duration affects the smoothing in parts - the larger it is, the more
|
||||
smooth the parts are. This dependency is not linear, but can give a sense of
|
||||
which shapers 'smooth' more for the same frequency. The ordering by
|
||||
smoothing is like this: ZV < MZV < ZVD ≈ EI < 2HUMP_EI < 3HUMP_EI. Also,
|
||||
it is rarely practical to set shaper_freq = resonance freq for shapers
|
||||
2HUMP_EI and 3HUMP_EI (they should be used to reduce vibrations for several
|
||||
frequencies).
|
||||
* One can estimate a range of frequencies in which the shaper reduces
|
||||
vibrations. For example, MZV with shaper_freq = 35 Hz reduces vibrations
|
||||
to 5% for frequencies [33.6, 36.4] Hz. 3HUMP_EI with shaper_freq = 50 Hz
|
||||
reduces vibrations to 5% in range [27.5, 75] Hz.
|
||||
* One can use this table to check which shaper they should be using if they
|
||||
need to reduce vibrations at several frequencies. For example, if one has
|
||||
resonances at 35 Hz and 60 Hz on the same axis: a) EI shaper needs to have
|
||||
shaper_freq = 35 / (1 - 0.2) = 43.75 Hz, and it will reduce resonances
|
||||
until 43.75 * (1 + 0.2) = 52.5 Hz, so it is not sufficient; b) 2HUMP_EI
|
||||
shaper needs to have shaper_freq = 35 / (1 - 0.35) = 53.85 Hz and will
|
||||
reduce vibrations until 53.85 * (1 + 0.35) = 72.7 Hz - so this is an
|
||||
acceptable configuration. Always try to use as high shaper_freq as possible
|
||||
for a given shaper (perhaps with some safety margin, so in this example
|
||||
shaper_freq ≈ 50-52 Hz would work best), and try to use a shaper with as
|
||||
small shaper duration as possible.
|
||||
* If one needs to reduce vibrations at several very different frequencies
|
||||
(say, 30 Hz and 100 Hz), they may see that the table above does not provide
|
||||
enough information. In this case one may have more luck with
|
||||
[scripts/graph_shaper.py](../scripts/graph_shaper.py)
|
||||
script, which is more flexible.
|
||||
182
docs/Rotation_Distance.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Rotation distance
|
||||
|
||||
Stepper motor drivers on Klipper require a `rotation_distance`
|
||||
parameter in each
|
||||
[stepper config section](Config_Reference.md#stepper). The
|
||||
`rotation_distance` is the amount of distance that the axis moves with
|
||||
one full revolution of the stepper motor. This document describes how
|
||||
one can configure this value.
|
||||
|
||||
## Obtaining rotation_distance from steps_per_mm (or step_distance)
|
||||
|
||||
The designers of your 3d printer originally calculated `steps_per_mm`
|
||||
from a rotation distance. If you know the steps_per_mm then it is
|
||||
possible to use this general formula to obtain that original rotation
|
||||
distance:
|
||||
```
|
||||
rotation_distance = <full_steps_per_rotation> * <microsteps> / <steps_per_mm>
|
||||
```
|
||||
|
||||
Or, if you have an older Klipper configuration and know the
|
||||
`step_distance` parameter you can use this formula:
|
||||
```
|
||||
rotation_distance = <full_steps_per_rotation> * <microsteps> * <step_distance>
|
||||
```
|
||||
|
||||
The `<full_steps_per_rotation>` setting is determined from the type of
|
||||
stepper motor. Most stepper motors are "1.8 degree steppers" and
|
||||
therefore have 200 full steps per rotation (360 divided by 1.8 is
|
||||
200). Some stepper motors are "0.9 degree steppers" and thus have 400
|
||||
full steps per rotation. Other stepper motors are rare. If unsure, do
|
||||
not set full_steps_per_rotation in the config file and use 200 in the
|
||||
formula above.
|
||||
|
||||
The `<microsteps>` setting is determined by the stepper motor driver.
|
||||
Most drivers use 16 microsteps. If unsure, set `microsteps: 16` in the
|
||||
config and use 16 in the formula above.
|
||||
|
||||
Almost all printers should have a whole number for `rotation_distance`
|
||||
on X, Y, and Z type axes. If the above formula results in a
|
||||
rotation_distance that is within .01 of a whole number then round the
|
||||
final value to that whole_number.
|
||||
|
||||
## Calibrating rotation_distance on extruders
|
||||
|
||||
On an extruder, the `rotation_distance` is the amount of distance the
|
||||
filament travels for one full rotation of the stepper motor. The best
|
||||
way to get an accurate value for this setting is to use a "measure and
|
||||
trim" procedure.
|
||||
|
||||
First start with an initial guess for the rotation distance. This may
|
||||
be obtained from
|
||||
[steps_per_mm](#obtaining-rotation_distance-from-steps_per_mm-or-step_distance)
|
||||
or by [inspecting the hardware](#extruder).
|
||||
|
||||
Then use the following procedure to "measure and trim":
|
||||
1. Make sure the extruder has filament in it, the hotend is heated to
|
||||
an appropriate temperature, and the printer is ready to extrude.
|
||||
2. Use a marker to place a mark on the filament around 70mm from the
|
||||
intake of the extruder body. Then use a digital calipers to measure
|
||||
the actual distance of that mark as precisely as one can. Note this
|
||||
as `<initial_mark_distance>`.
|
||||
3. Extrude 50mm of filament with the following command sequence: `G91`
|
||||
followed by `G1 E50 F60`. Note 50mm as
|
||||
`<requested_extrude_distance>`. Wait for the extruder to finish the
|
||||
move (it will take about 50 seconds). It is important to use the
|
||||
slow extrusion rate for this test as a faster rate can cause high
|
||||
pressure in the extruder which will skew the results. (Do not use
|
||||
the "extrude button" on graphical front-ends for this test as they
|
||||
extrude at a fast rate.)
|
||||
4. Use the digital calipers to measure the new distance between the
|
||||
extruder body and the mark on the filament. Note this as
|
||||
`<subsequent_mark_distance>`. Then calculate:
|
||||
`actual_extrude_distance = <initial_mark_distance> - <subsequent_mark_distance>`
|
||||
5. Calculate rotation_distance as:
|
||||
`rotation_distance = <previous_rotation_distance> * <actual_extrude_distance> / <requested_extrude_distance>`
|
||||
Round the new rotation_distance to three decimal places.
|
||||
|
||||
If the actual_extrude_distance differs from requested_extrude_distance
|
||||
by more than about 2mm then it is a good idea to perform the steps
|
||||
above a second time.
|
||||
|
||||
Note: Do *not* use a "measure and trim" type of method to calibrate x,
|
||||
y, or z type axes. The "measure and trim" method is not accurate
|
||||
enough for those axes and will likely lead to a worse configuration.
|
||||
Instead, if needed, those axes can be determined by
|
||||
[measuring the belts, pulleys, and lead screw hardware](#obtaining-rotation_distance-by-inspecting-the-hardware).
|
||||
|
||||
## Obtaining rotation_distance by inspecting the hardware
|
||||
|
||||
It's possible to calculate rotation_distance with knowledge of the
|
||||
stepper motors and printer kinematics. This may be useful if the
|
||||
steps_per_mm is not known or if designing a new printer.
|
||||
|
||||
### Belt driven axes
|
||||
|
||||
It is easy to calculate rotation_distance for a linear axis that uses
|
||||
a belt and pulley.
|
||||
|
||||
First determine the type of belt. Most printers use a 2mm belt pitch
|
||||
(that is, each tooth on the belt is 2mm apart). Then count the number
|
||||
of teeth on the stepper motor pulley. The rotation_distance is then
|
||||
calculated as:
|
||||
```
|
||||
rotation_distance = <belt_pitch> * <number_of_teeth_on_pulley>
|
||||
```
|
||||
|
||||
For example, if a printer has a 2mm belt and uses a pulley with 20
|
||||
teeth, then the rotation distance is 40.
|
||||
|
||||
### Axes with a lead screw
|
||||
|
||||
It is easy to calculate the rotation_distance for common lead screws
|
||||
using the following formula:
|
||||
```
|
||||
rotation_distance = <screw_pitch> * <number_of_separate_threads>
|
||||
```
|
||||
|
||||
For example, the common "T8 leadscrew" has a rotation distance of 8
|
||||
(it has a pitch of 2mm and has 4 separate threads).
|
||||
|
||||
Older printers with "threaded rods" have only one "thread" on the lead
|
||||
screw and thus the rotation distance is the pitch of the screw. (The
|
||||
screw pitch is the distance between each groove on the screw.) So, for
|
||||
example, an M6 metric rod has a rotation distance of 1 and an M8 rod
|
||||
has a rotation distance of 1.25.
|
||||
|
||||
### Extruder
|
||||
|
||||
It's possible to obtain an initial rotation distance for extruders by
|
||||
measuring the diameter of the "hobbed bolt" that pushes the filament
|
||||
and using the following formula: `rotation_distance = <diameter> * 3.14`
|
||||
|
||||
If the extruder uses gears then it will also be necessary to
|
||||
[determine and set the gear_ratio](#using-a-gear_ratio) for the
|
||||
extruder.
|
||||
|
||||
The actual rotation distance on an extruder will vary from printer to
|
||||
printer, because the grip of the "hobbed bolt" that engages the
|
||||
filament can vary. It can even vary between filament spools. After
|
||||
obtaining an initial rotation_distance, use the
|
||||
[measure and trim procedure](#calibrating-rotation_distance-on-extruders)
|
||||
to obtain a more accurate setting.
|
||||
|
||||
## Using a gear_ratio
|
||||
|
||||
Setting a `gear_ratio` can make it easier to configure the
|
||||
`rotation_distance` on steppers that have a gear box (or similar)
|
||||
attached to it. Most steppers do not have a gear box - if unsure then
|
||||
do not set `gear_ratio` in the config.
|
||||
|
||||
When `gear_ratio` is set, the `rotation_distance` represents the
|
||||
distance the axis moves with one full rotation of the final gear on
|
||||
the gear box. If, for example, one is using a gearbox with a "5:1"
|
||||
ratio, then one could calculate the rotation_distance with
|
||||
[knowledge of the hardware](#obtaining-rotation_distance-by-inspecting-the-hardware)
|
||||
and then add `gear_ratio: 5:1` to the config.
|
||||
|
||||
For gearing implemented with belts and pulleys, it is possible to
|
||||
determine the gear_ratio by counting the teeth on the pulleys. For
|
||||
example, if a stepper with a 16 toothed pulley drives the next pulley
|
||||
with 80 teeth then one would use `gear_ratio: 80:16`. Indeed, one
|
||||
could open a common off the shelf "gear box" and count the teeth in it
|
||||
to confirm its gear ratio.
|
||||
|
||||
Note that sometimes a gearbox will have a slightly different gear
|
||||
ratio than what it is advertised as. The common BMG extruder motor
|
||||
gears are an example of this - they are advertised as "3:1" but
|
||||
actually use "50:17" gearing. (Using teeth numbers without a common
|
||||
denominator may improve overall gear wear as the teeth don't always
|
||||
mesh the same way with each revolution.) The common "5.18:1 planetary
|
||||
gearbox", is more accurately configured with `gear_ratio: 57:11`.
|
||||
|
||||
If several gears are used on an axis then it is possible to provide a
|
||||
comma separated list to gear_ratio. For example, a "5:1" gear box
|
||||
driving a 16 toothed to 80 toothed pulley could use
|
||||
`gear_ratio: 5:1, 80:16`.
|
||||
|
||||
In most cases, gear_ratio should be defined with whole numbers as
|
||||
common gears and pulleys have a whole number of teeth on them.
|
||||
However, in cases where a belt drives a pulley using friction instead
|
||||
of teeth, it may make sense to use a floating point number in the gear
|
||||
ratio (eg, `gear_ratio: 107.237:16`).
|
||||
147
docs/SDCard_Updates.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# SDCard updates
|
||||
|
||||
Many of today's popular controller boards ship with a bootloader capable of
|
||||
updating firmware via SD Card. While this is convenient in many
|
||||
circumstances, these bootloaders typically provide no other way to update
|
||||
firmware. This can be a nuisance if your board is mounted in a location
|
||||
that is difficult to access or if you need to update firmware often.
|
||||
After Klipper has been initially flashed to a controller it is possible to
|
||||
transfer new firmware to the SD Card and initiate the flashing procedure
|
||||
via ssh.
|
||||
|
||||
## Typical Upgrade Procedure
|
||||
|
||||
The procedure for updating MCU firmware using the SD Card is similar to that
|
||||
of other methods. Instead of using `make flash` it is necessary to run a
|
||||
helper script, `flash-sdcard.sh`. Updating a BigTreeTech SKR 1.3 might look
|
||||
like the following:
|
||||
```
|
||||
sudo service klipper stop
|
||||
cd ~/klipper
|
||||
git pull
|
||||
make clean
|
||||
make menuconfig
|
||||
make
|
||||
./scripts/flash-sdcard.sh /dev/ttyACM0 btt-skr-v1.3
|
||||
sudo service klipper start
|
||||
```
|
||||
|
||||
It is up to the user to determine the device location and board name.
|
||||
If a user needs to flash multiple boards, `flash-sdcard.sh` (or
|
||||
`make flash` if appropriate) should be run for each board prior to
|
||||
restarting the Klipper service.
|
||||
|
||||
Supported boards can be listed with the following command:
|
||||
```
|
||||
./scripts/flash-sdcard.sh -l
|
||||
```
|
||||
If you do not see your board listed it may be necessary to add a new
|
||||
board definition as [described below](#board-definitions).
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
The above commands assume that your MCU connects at the default baud rate
|
||||
of 250000 and the firmware is located at `~/klipper/out/klipper.bin`. The
|
||||
`flash-sdcard.sh` script provides options for changing these defaults.
|
||||
All options can be viewed by the help screen:
|
||||
```
|
||||
./scripts/flash-sdcard.sh -h
|
||||
SD Card upload utility for Klipper
|
||||
|
||||
usage: flash_sdcard.sh [-h] [-l] [-b <baud>] [-f <firmware>]
|
||||
<device> <board>
|
||||
|
||||
positional arguments:
|
||||
<device> device serial port
|
||||
<board> board type
|
||||
|
||||
optional arguments:
|
||||
-h show this message
|
||||
-l list available boards
|
||||
-b <baud> serial baud rate (default is 250000)
|
||||
-f <firmware> path to klipper.bin
|
||||
```
|
||||
|
||||
If your board is flashed with firmware that connects at a custom baud
|
||||
rate it is possible to upgrade by specifying the `-b` option:
|
||||
```
|
||||
./scripts/flash-sdcard.sh -b 115200 /dev/ttyAMA0 btt-skr-v1.3
|
||||
```
|
||||
|
||||
If you wish to flash a build of Klipper located somewhere other than
|
||||
the default location it can be done by specifying the `-f` option:
|
||||
```
|
||||
./scripts/flash-sdcard.sh -f ~/downloads/klipper.bin /dev/ttyAMA0 btt-skr-v1.3
|
||||
```
|
||||
|
||||
Note that when upgrading a MKS Robin E3 it is not necessary to manually run
|
||||
`update_mks_robin.py` and supply the resulting binary to `flash-sdcard.sh`.
|
||||
This procedure is automated during the upload process.
|
||||
|
||||
## Caveats
|
||||
|
||||
- As mentioned in the introduction, this method only works for upgrading
|
||||
firmware. The initial flashing procedure must be done manually per the
|
||||
instructions that apply to your controller board.
|
||||
- While it is possible to flash a build that changes the Serial Baud or
|
||||
connection interface (ie: from USB to UART), verification will always
|
||||
fail as the script will be unable to reconnect to the MCU to verify
|
||||
the current version.
|
||||
- Only boards that use SPI for SD Card communication are supported.
|
||||
Boards that use SDIO, such as the Flymaker Flyboard and MKS Robin Nano
|
||||
V1/V2, will not work.
|
||||
|
||||
## Board Definitions
|
||||
|
||||
Most common boards should be available, however it is possible to add a new
|
||||
board definition if necessary. Board definitions are located in
|
||||
`~/klipper/scripts/spi_flash/board_defs.py`. The definitions are stored
|
||||
in dictionary, for example:
|
||||
```python
|
||||
BOARD_DEFS = {
|
||||
'generic-lpc1768': {
|
||||
'mcu': "lpc1768",
|
||||
'spi_bus': "ssp1",
|
||||
"cs_pin": "P0.6"
|
||||
},
|
||||
...<further definitions>
|
||||
}
|
||||
```
|
||||
|
||||
The following fields may be specified:
|
||||
- `mcu`: The mcu type. This can be retrevied after configuring the build
|
||||
via `make menuconfig` by running `cat .config | grep CONFIG_MCU`. This
|
||||
field is required.
|
||||
- `spi_bus`: The SPI bus connected to the SD Card. This should be retreived
|
||||
from the board's schematic. This field is required.
|
||||
- `cs_pin`: The Chip Select Pin connected to the SD Card. This should be
|
||||
retreived from the board schematic. This field is required.
|
||||
- `firmware_path`: The path on the SD Card where firmware should be
|
||||
transferred. The default is `firmware.bin`.
|
||||
- `current_firmware_path` The path on the SD Card where the renamed firmware
|
||||
file is located after a successful flash. The default is `firmware.cur`.
|
||||
|
||||
If software SPI is required the `spi_bus` field should be set to `swspi`
|
||||
and the following additional field should be specified:
|
||||
- `spi_pins`: This should be 3 comma separated pins that are connected to
|
||||
the SD Card in the format of `miso,mosi,sclk`.
|
||||
|
||||
It should be exceedingly rare that Software SPI is necessary, typically only
|
||||
boards with design errors will require it. The `btt-skr-pro` board definition
|
||||
provides an example.
|
||||
|
||||
Prior to creating a new board definition one should check to see if an
|
||||
existing board definition meets the criteria necessary for the new board.
|
||||
If this is the case, a `BOARD_ALIAS` may be specified. For example, the
|
||||
following alias may be added to specify `my-new-board` as an alias for
|
||||
`generic-lpc1768`:
|
||||
```python
|
||||
BOARD_ALIASES = {
|
||||
...<previous aliases>,
|
||||
'my-new-board': BOARD_DEFS['generic-lpc1768'],
|
||||
}
|
||||
```
|
||||
|
||||
If you need a new board definition and you are uncomfortable with the
|
||||
procedure outlined above it is recommended that you request one in
|
||||
the [Klipper Community Discord](Contact.md#discord).
|
||||
100
docs/Skew_Correction.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Skew correction
|
||||
|
||||
Software based skew correction can help resolve dimensional inaccuracies
|
||||
resulting from a printer assembly that is not perfectly square. Note
|
||||
that if your printer is significantly skewed it is strongly recommended to
|
||||
first use mechanical means to get your printer as square as possible prior
|
||||
to applying software based correction.
|
||||
|
||||
## Print a Calibration Object
|
||||
|
||||
The first step in correcting skew is to print a
|
||||
[calibration object](https://www.thingiverse.com/thing:2563185/files)
|
||||
along the plane you want to correct. There is also a
|
||||
[calibration object](https://www.thingiverse.com/thing:2972743)
|
||||
that includes all planes in one model. You want the object oriented
|
||||
so that corner A is toward the origin of the plane.
|
||||
|
||||
Make sure that no skew correction is applied during this print. You may
|
||||
do this by either removing the `[skew_correction]` module from printer.cfg
|
||||
or by issuing a `SET_SKEW CLEAR=1` gcode.
|
||||
|
||||
## Take your measurements
|
||||
|
||||
The `[skew_correcton]` module requires 3 measurements for each plane you want
|
||||
to correct; the length from Corner A to Corner C, the length from Corner B
|
||||
to Corner D, and the length from Corner A to Corner D. When measuring length
|
||||
AD do not include the flats on the corners that some test objects provide.
|
||||
|
||||

|
||||
|
||||
## Configure your skew
|
||||
|
||||
Make sure `[skew_correction]` is in printer.cfg. You may now use the `SET_SKEW`
|
||||
gcode to configure skew_correcton. For example, if your measured lengths
|
||||
along XY are as follows:
|
||||
|
||||
```
|
||||
Length AC = 140.4
|
||||
Length BD = 142.8
|
||||
Length AD = 99.8
|
||||
```
|
||||
|
||||
`SET_SKEW` can be used to configure skew correction for the XY plane.
|
||||
|
||||
```
|
||||
SET_SKEW XY=140.4,142.8,99.8
|
||||
```
|
||||
You may also add measurements for XZ and YZ to the gcode:
|
||||
|
||||
```
|
||||
SET_SKEW XY=140.4,142.8,99.8 XZ=141.6,141.4,99.8 YZ=142.4,140.5,99.5
|
||||
```
|
||||
|
||||
The `[skew_correction]` module also supports profile management in a manner
|
||||
similar to `[bed_mesh]`. After setting skew using the `SET_SKEW` gcode,
|
||||
you may use the `SKEW_PROFILE` gcode to save it:
|
||||
|
||||
```
|
||||
SKEW_PROFILE SAVE=my_skew_profile
|
||||
```
|
||||
After this command you will be prompted to issue a `SAVE_CONFIG` gcode to
|
||||
save the profile to persistent storage. If no profile is named
|
||||
`my_skew_profile` then a new profile will be created. If the named profile
|
||||
exists it will be overwritten.
|
||||
|
||||
Once you have a saved profile, you may load it:
|
||||
```
|
||||
SKEW_PROFILE LOAD=my_skew_profile
|
||||
```
|
||||
|
||||
It is also possible to remove an old or out of date profile:
|
||||
```
|
||||
SKEW_PROFILE REMOVE=my_skew_profile
|
||||
```
|
||||
After removing a profile you will be prompted to issue a `SAVE_CONFIG` to
|
||||
make this change persist.
|
||||
|
||||
## Verifying your correction
|
||||
|
||||
After skew_correction has been configured you may reprint the calibration
|
||||
part with correction enabled. Use the following gcode to check your
|
||||
skew on each plane. The results should be lower than those reported via
|
||||
`GET_CURRENT_SKEW`.
|
||||
|
||||
```
|
||||
CALC_MEASURED_SKEW AC=<ac_length> BD=<bd_length> AD=<ad_length>
|
||||
```
|
||||
|
||||
## Caveats
|
||||
|
||||
Due to the nature of skew correction it is recommended to configure skew
|
||||
in your start gcode, after homing and any kind of movement that travels
|
||||
near the edge of the print area such as a purge or nozzle wipe. You may
|
||||
use use the `SET_SKEW` or `SKEW_PROFILE` gcodes to accomplish this. It is
|
||||
also recommended to issue a `SET_SKEW CLEAR=1` in your end gcode.
|
||||
|
||||
Keep in mind that it is possible for `[skew_correction]` to generate a correction
|
||||
that moves the tool beyond the printer's boundaries on the X and/or Y axes. It
|
||||
is recommended to arrange parts away from the edges when using
|
||||
`[skew_correction]`.
|
||||
89
docs/Slicers.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Slicers
|
||||
|
||||
This document provides some tips for configuring a "slicer"
|
||||
application for use with Klipper. Common slicers used with Klipper are
|
||||
Slic3r, Cura, Simplify3D, etc.
|
||||
|
||||
## Set the G-Code flavor to Marlin
|
||||
|
||||
Many slicers have an option to configure the "G-Code flavor". The
|
||||
default is frequently "Marlin" and that works well with Klipper. The
|
||||
"Smoothieware" setting also works well with Klipper.
|
||||
|
||||
## Klipper gcode_macro
|
||||
|
||||
Slicers will often allow one to configure "Start G-Code" and "End
|
||||
G-Code" sequences. It is often convenient to define custom macros in
|
||||
the Klipper config file instead - such as: `[gcode_macro START_PRINT]`
|
||||
and `[gcode_macro END_PRINT]`. Then one can just run START_PRINT and
|
||||
END_PRINT in the slicer's configuration. Defining these actions in the
|
||||
Klipper configuration may make it easier to tweak the printer's start
|
||||
and end steps as changes do not require re-slicing.
|
||||
|
||||
See [sample-macros.cfg](../config/sample-macros.cfg) for example
|
||||
START_PRINT and END_PRINT macros.
|
||||
|
||||
See the [config reference](Config_Reference.md#gcode_macro) for
|
||||
details on defining a gcode_macro.
|
||||
|
||||
## Large retraction settings may require tuning Klipper
|
||||
|
||||
The maximum speed and acceleration of retraction moves are controlled
|
||||
in Klipper by the `max_extrude_only_velocity` and
|
||||
`max_extrude_only_accel` config settings. These settings have a
|
||||
default value that should work well on many printers. However, if one
|
||||
has configured a large retraction in the slicer (eg, 5mm or greater)
|
||||
then one may find they limit the desired speed of retractions.
|
||||
|
||||
If using a large retraction, consider tuning Klipper's
|
||||
[pressure advance](Pressure_Advance.md) instead. Otherwise, if one
|
||||
finds the toolhead seems to "pause" during retraction and priming,
|
||||
then consider explicitly defining `max_extrude_only_velocity` and
|
||||
`max_extrude_only_accel` in the Klipper config file.
|
||||
|
||||
## Do not enable "coasting"
|
||||
|
||||
The "coasting" feature is likely to result in poor quality prints with
|
||||
Klipper. Consider using Klipper's
|
||||
[pressure advance](Pressure_Advance.md) instead.
|
||||
|
||||
Specifically, if the slicer dramatically changes the extrusion rate
|
||||
between moves then Klipper will perform deceleration and acceleration
|
||||
between moves. This is likely to make blobbing worse, not better.
|
||||
|
||||
In contrast, it is okay (and often helpful) to use a slicer's
|
||||
"retract" setting, "wipe" setting, and/or "wipe on retract" setting.
|
||||
|
||||
## Do not use "extra restart distance" on Simplify3d
|
||||
|
||||
This setting can cause dramatic changes to extrusion rates which can
|
||||
trigger Klipper's maximum extrusion cross-section check. Consider
|
||||
using Klipper's [pressure advance](Pressure_Advance.md) or the regular
|
||||
Simplify3d retract setting instead.
|
||||
|
||||
## Disable "PreloadVE" on KISSlicer
|
||||
|
||||
If using KISSlicer slicing software then set "PreloadVE" to
|
||||
zero. Consider using Klipper's [pressure advance](Pressure_Advance.md)
|
||||
instead.
|
||||
|
||||
## Disable any "advanced extruder pressure" settings
|
||||
|
||||
Some slicers advertise an "advanced extruder pressure" capability. It
|
||||
is recommended to keep these options disabled when using Klipper as
|
||||
they are likely to result in poor quality prints. Consider using
|
||||
Klipper's [pressure advance](Pressure_Advance.md) instead.
|
||||
|
||||
Specifically, these slicer settings can instruct the firmware to make
|
||||
wild changes to the extrusion rate in the hope that the firmware will
|
||||
approximate those requests and the printer will roughly obtain a
|
||||
desirable extruder pressure. Klipper, however, utilizes precise
|
||||
kinematic calculations and timing. When Klipper is commanded to make
|
||||
significant changes to the extrusion rate it will plan out the
|
||||
corresponding changes to velocity, acceleration, and extruder
|
||||
movement - which is not the slicer's intent. The slicer may even
|
||||
command excessive extrusion rates to the point that it triggers
|
||||
Klipper's maximum extrusion cross-section check.
|
||||
|
||||
In contrast, it is okay (and often helpful) to use a slicer's
|
||||
"retract" setting, "wipe" setting, and/or "wipe on retract" setting.
|
||||
40
docs/Sponsors.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Sponsors
|
||||
|
||||
Klipper is Free Software. We depend on the generous support from
|
||||
sponsors. Please consider sponsoring Klipper or supporting our
|
||||
sponsors.
|
||||
|
||||
## BIGTREETECH
|
||||
|
||||
[<img src="./img/sponsors/BTT_BTT.png" width="200" />](https://bigtree-tech.com/collections/all-products)
|
||||
|
||||
BIGTREETECH is the official mainboard sponsor of Klipper. BIGTREETECH
|
||||
is committed to developing innovative and competitive products to
|
||||
serve the 3D printing community better. Follow them on
|
||||
[Facebook](https://www.facebook.com/BIGTREETECH) or
|
||||
[Twitter](https://twitter.com/BigTreeTech).
|
||||
|
||||
## Klipper Developers
|
||||
|
||||
### Kevin O'Connor
|
||||
|
||||
Kevin is the original author and current maintainer of Klipper. Kevin
|
||||
has a Patreon page at:
|
||||
[https://www.patreon.com/koconnor](https://www.patreon.com/koconnor)
|
||||
|
||||
### Eric Callahan
|
||||
|
||||
Eric is the author of bed_mesh, spi_flash, and several other Klipper
|
||||
modules. Eric has a donations page at:
|
||||
[https://ko-fi.com/arksine](https://ko-fi.com/arksine)
|
||||
|
||||
## Related Klipper Projects
|
||||
|
||||
Klipper is frequently used with other Free Software. Consider using or
|
||||
supporting these projects.
|
||||
|
||||
* [Moonraker](https://github.com/Arksine/moonraker)
|
||||
* [Mainsail](https://github.com/mainsail-crew/mainsail)
|
||||
* [Fluidd](https://github.com/fluidd-core/fluidd)
|
||||
* [OctoPrint](https://octoprint.org/)
|
||||
* [KlipperScreen](https://github.com/jordanruthe/KlipperScreen)
|
||||
472
docs/Status_Reference.md
Normal file
@@ -0,0 +1,472 @@
|
||||
# Status reference
|
||||
|
||||
This document is a reference of printer status information available
|
||||
in Klipper [macros](Command_Templates.md),
|
||||
[display fields](Config_Reference.md#display), and via the
|
||||
[API Server](API_Server.md).
|
||||
|
||||
The fields in this document are subject to change - if using an
|
||||
attribute be sure to review the
|
||||
[Config Changes document](Config_Changes.md) when upgrading the
|
||||
Klipper software.
|
||||
|
||||
## angle
|
||||
|
||||
The following information is available in
|
||||
[angle some_name](Config_Reference.md#angle) objects:
|
||||
- `temperature`: The last temperature reading (in Celsius) from a
|
||||
tle5012b magnetic hall sensor. This value is only available if the
|
||||
angle sensor is a tle5012b chip and if measurements are in progress
|
||||
(otherwise it reports `None`).
|
||||
|
||||
## bed_mesh
|
||||
|
||||
The following information is available in the
|
||||
[bed_mesh](Config_Reference.md#bed_mesh) object:
|
||||
- `profile_name`, `mesh_min`, `mesh_max`, `probed_matrix`,
|
||||
`mesh_matrix`: Information on the currently active bed_mesh.
|
||||
- `profiles`: The set of currently defined profiles as setup
|
||||
using BED_MESH_PROFILE.
|
||||
|
||||
## configfile
|
||||
|
||||
The following information is available in the `configfile` object
|
||||
(this object is always available):
|
||||
- `settings.<section>.<option>`: Returns the given config file setting
|
||||
(or default value) during the last software start or restart. (Any
|
||||
settings changed at run-time will not be reflected here.)
|
||||
- `config.<section>.<option>`: Returns the given raw config file
|
||||
setting as read by Klipper during the last software start or
|
||||
restart. (Any settings changed at run-time will not be reflected
|
||||
here.) All values are returned as strings.
|
||||
- `save_config_pending`: Returns true if there are updates that a
|
||||
`SAVE_CONFIG` command may persist to disk.
|
||||
- `save_config_pending_items`: Contains the sections and options that
|
||||
were changed and would be persisted by a `SAVE_CONFIG`.
|
||||
- `warnings`: A list of warnings about config options. Each entry in
|
||||
the list will be a dictionary containing a `type` and `message`
|
||||
field (both strings). Additional fields may be available depending
|
||||
on the type of warning.
|
||||
|
||||
## display_status
|
||||
|
||||
The following information is available in the `display_status` object
|
||||
(this object is automatically available if a
|
||||
[display](Config_Reference.md#display) config section is defined):
|
||||
- `progress`: The progress value of the last `M73` G-Code command (or
|
||||
`virtual_sdcard.progress` if no recent `M73` received).
|
||||
- `message`: The message contained in the last `M117` G-Code command.
|
||||
|
||||
## endstop_phase
|
||||
|
||||
The following information is available in the
|
||||
[endstop_phase](Config_Reference.md#endstop_phase) object:
|
||||
- `last_home.<stepper name>.phase`: The phase of the stepper motor at
|
||||
the end of the last home attempt.
|
||||
- `last_home.<stepper name>.phases`: The total number of phases
|
||||
available on the stepper motor.
|
||||
- `last_home.<stepper name>.mcu_position`: The position (as tracked by
|
||||
the micro-controller) of the stepper motor at the end of the last
|
||||
home attempt. The position is the total number of steps taken in a
|
||||
forward direction minus the total number of steps taken in the
|
||||
reverse direction since the micro-controller was last restarted.
|
||||
|
||||
## exclude_object
|
||||
|
||||
The following information is available in the
|
||||
[exclude_object](Exclude_Object.md) object:
|
||||
|
||||
- `objects`: An array of the known objects as provided by the
|
||||
`EXCLUDE_OBJECT_DEFINE` command. This is the same information provided by
|
||||
the `EXCLUDE_OBJECT VERBOSE=1` command. The `center` and `polygon` fields will
|
||||
only be present if provided in the original `EXCLUDE_OBJECT_DEFINE`
|
||||
|
||||
Here is a JSON sample:
|
||||
```
|
||||
[
|
||||
{
|
||||
"polygon": [
|
||||
[ 156.25, 146.2511675 ],
|
||||
[ 156.25, 153.7488325 ],
|
||||
[ 163.75, 153.7488325 ],
|
||||
[ 163.75, 146.2511675 ]
|
||||
],
|
||||
"name": "CYLINDER_2_STL_ID_2_COPY_0",
|
||||
"center": [ 160, 150 ]
|
||||
},
|
||||
{
|
||||
"polygon": [
|
||||
[ 146.25, 146.2511675 ],
|
||||
[ 146.25, 153.7488325 ],
|
||||
[ 153.75, 153.7488325 ],
|
||||
[ 153.75, 146.2511675 ]
|
||||
],
|
||||
"name": "CYLINDER_2_STL_ID_1_COPY_0",
|
||||
"center": [ 150, 150 ]
|
||||
}
|
||||
]
|
||||
```
|
||||
- `excluded_objects`: An array of strings listing the names of excluded objects.
|
||||
- `current_object`: The name of the object currently being printed.
|
||||
|
||||
## fan
|
||||
|
||||
The following information is available in
|
||||
[fan](Config_Reference.md#fan),
|
||||
[heater_fan some_name](Config_Reference.md#heater_fan) and
|
||||
[controller_fan some_name](Config_Reference.md#controller_fan)
|
||||
objects:
|
||||
- `speed`: The fan speed as a float between 0.0 and 1.0.
|
||||
- `rpm`: The measured fan speed in rotations per minute if the fan has
|
||||
a tachometer_pin defined.
|
||||
|
||||
## filament_switch_sensor
|
||||
|
||||
The following information is available in
|
||||
[filament_switch_sensor some_name](Config_Reference.md#filament_switch_sensor)
|
||||
objects:
|
||||
- `enabled`: Returns True if the switch sensor is currently enabled.
|
||||
- `filament_detected`: Returns True if the sensor is in a triggered
|
||||
state.
|
||||
|
||||
## filament_motion_sensor
|
||||
|
||||
The following information is available in
|
||||
[filament_motion_sensor some_name](Config_Reference.md#filament_motion_sensor)
|
||||
objects:
|
||||
- `enabled`: Returns True if the motion sensor is currently enabled.
|
||||
- `filament_detected`: Returns True if the sensor is in a triggered
|
||||
state.
|
||||
|
||||
## firmware_retraction
|
||||
|
||||
The following information is available in the
|
||||
[firmware_retraction](Config_Reference.md#firmware_retraction) object:
|
||||
- `retract_length`, `retract_speed`, `unretract_extra_length`,
|
||||
`unretract_speed`: The current settings for the firmware_retraction
|
||||
module. These settings may differ from the config file if a
|
||||
`SET_RETRACTION` command alters them.
|
||||
|
||||
## gcode_macro
|
||||
|
||||
The following information is available in
|
||||
[gcode_macro some_name](Config_Reference.md#gcode_macro) objects:
|
||||
- `<variable>`: The current value of a
|
||||
[gcode_macro variable](Command_Templates.md#variables).
|
||||
|
||||
## gcode_move
|
||||
|
||||
The following information is available in the `gcode_move` object
|
||||
(this object is always available):
|
||||
- `gcode_position`: The current position of the toolhead relative to
|
||||
the current G-Code origin. That is, positions that one might
|
||||
directly send to a `G1` command. It is possible to access the x, y,
|
||||
z, and e components of this position (eg, `gcode_position.x`).
|
||||
- `position`: The last commanded position of the toolhead using the
|
||||
coordinate system specified in the config file. It is possible to
|
||||
access the x, y, z, and e components of this position (eg,
|
||||
`position.x`).
|
||||
- `homing_origin`: The origin of the gcode coordinate system (relative
|
||||
to the coordinate system specified in the config file) to use after
|
||||
a `G28` command. The `SET_GCODE_OFFSET` command can alter this
|
||||
position. It is possible to access the x, y, and z components of
|
||||
this position (eg, `homing_origin.x`).
|
||||
- `speed`: The last speed set in a `G1` command (in mm/s).
|
||||
- `speed_factor`: The "speed factor override" as set by an `M220`
|
||||
command. This is a floating point value such that 1.0 means no
|
||||
override and, for example, 2.0 would double requested speed.
|
||||
- `extrude_factor`: The "extrude factor override" as set by an `M221`
|
||||
command. This is a floating point value such that 1.0 means no
|
||||
override and, for example, 2.0 would double requested extrusions.
|
||||
- `absolute_coordinates`: This returns True if in `G90` absolute
|
||||
coordinate mode or False if in `G91` relative mode.
|
||||
- `absolute_extrude`: This returns True if in `M82` absolute extrude
|
||||
mode or False if in `M83` relative mode.
|
||||
|
||||
## hall_filament_width_sensor
|
||||
|
||||
The following information is available in the
|
||||
[hall_filament_width_sensor](Config_Reference.md#hall_filament_width_sensor)
|
||||
object:
|
||||
- `is_active`: Returns True if the sensor is currently active.
|
||||
- `Diameter`: The last reading from the sensor in mm.
|
||||
- `Raw`: The last raw ADC reading from the sensor.
|
||||
|
||||
## heater
|
||||
|
||||
The following information is available for heater objects such as
|
||||
[extruder](Config_Reference.md#extruder),
|
||||
[heater_bed](Config_Reference.md#heater_bed), and
|
||||
[heater_generic](Config_Reference.md#heater_generic):
|
||||
- `temperature`: The last reported temperature (in Celsius as a float)
|
||||
for the given heater.
|
||||
- `target`: The current target temperature (in Celsius as a float) for
|
||||
the given heater.
|
||||
- `power`: The last setting of the PWM pin (a value between 0.0 and
|
||||
1.0) associated with the heater.
|
||||
- `can_extrude`: If extruder can extrude (defined by `min_extrude_temp`),
|
||||
available only for [extruder](Config_Reference.md#extruder)
|
||||
|
||||
## heaters
|
||||
|
||||
The following information is available in the `heaters` object (this
|
||||
object is available if any heater is defined):
|
||||
- `available_heaters`: Returns a list of all currently available
|
||||
heaters by their full config section names, e.g. `["extruder",
|
||||
"heater_bed", "heater_generic my_custom_heater"]`.
|
||||
- `available_sensors`: Returns a list of all currently available
|
||||
temperature sensors by their full config section names,
|
||||
e.g. `["extruder", "heater_bed", "heater_generic my_custom_heater",
|
||||
"temperature_sensor electronics_temp"]`.
|
||||
|
||||
## idle_timeout
|
||||
|
||||
The following information is available in the
|
||||
[idle_timeout](Config_Reference.md#idle_timeout) object (this object
|
||||
is always available):
|
||||
- `state`: The current state of the printer as tracked by the
|
||||
idle_timeout module. It is one of the following strings: "Idle",
|
||||
"Printing", "Ready".
|
||||
- `printing_time`: The amount of time (in seconds) the printer has
|
||||
been in the "Printing" state (as tracked by the idle_timeout
|
||||
module).
|
||||
|
||||
## led
|
||||
|
||||
The following information is available for each `[led led_name]`,
|
||||
`[neopixel led_name]`, `[dotstar led_name]`, `[pca9533 led_name]`, and
|
||||
`[pca9632 led_name]` config section defined in printer.cfg:
|
||||
- `color_data`: A list of color lists containing the RGBW values for a
|
||||
led in the chain. Each value is represented as a float from 0.0 to
|
||||
1.0. Each color list contains 4 items (red, green, blue, white) even
|
||||
if the underyling LED supports fewer color channels. For example,
|
||||
the blue value (3rd item in color list) of the second neopixel in a
|
||||
chain could be accessed at
|
||||
`printer["neopixel <config_name>"].color_data[1][2]`.
|
||||
|
||||
## manual_probe
|
||||
|
||||
The following information is available in the
|
||||
`manual_probe` object:
|
||||
- `is_active`: Returns True if a manual probing helper script is currently
|
||||
active.
|
||||
- `z_position`: The current height of the nozzle (as the printer currently
|
||||
understands it).
|
||||
- `z_position_lower`: Last probe attempt just lower than the current height.
|
||||
- `z_position_upper`: Last probe attempt just greater than the current height.
|
||||
|
||||
## mcu
|
||||
|
||||
The following information is available in
|
||||
[mcu](Config_Reference.md#mcu) and
|
||||
[mcu some_name](Config_Reference.md#mcu-my_extra_mcu) objects:
|
||||
- `mcu_version`: The Klipper code version reported by the
|
||||
micro-controller.
|
||||
- `mcu_build_versions`: Information on the build tools used to
|
||||
generate the micro-controller code (as reported by the
|
||||
micro-controller).
|
||||
- `mcu_constants.<constant_name>`: Compile time constants reported by
|
||||
the micro-controller. The available constants may differ between
|
||||
micro-controller architectures and with each code revision.
|
||||
- `last_stats.<statistics_name>`: Statistics information on the
|
||||
micro-controller connection.
|
||||
|
||||
## motion_report
|
||||
|
||||
The following information is available in the `motion_report` object
|
||||
(this object is automatically available if any stepper config section
|
||||
is defined):
|
||||
- `live_position`: The requested toolhead position interpolated to the
|
||||
current time.
|
||||
- `live_velocity`: The requested toolhead velocity (in mm/s) at the
|
||||
current time.
|
||||
- `live_extruder_velocity`: The requested extruder velocity (in mm/s)
|
||||
at the current time.
|
||||
|
||||
## output_pin
|
||||
|
||||
The following information is available in
|
||||
[output_pin some_name](Config_Reference.md#output_pin) objects:
|
||||
- `value`: The "value" of the pin, as set by a `SET_PIN` command.
|
||||
|
||||
## palette2
|
||||
|
||||
The following information is available in the
|
||||
[palette2](Config_Reference.md#palette2) object:
|
||||
- `ping`: Amount of the last reported Palette 2 ping in percent.
|
||||
- `remaining_load_length`: When starting a Palette 2 print, this will
|
||||
be the amount of filament to load into the extruder.
|
||||
- `is_splicing`: True when the Palette 2 is splicing filament.
|
||||
|
||||
## pause_resume
|
||||
|
||||
The following information is available in the
|
||||
[pause_resume](Config_Reference.md#pause_resume) object:
|
||||
- `is_paused`: Returns true if a PAUSE command has been executed
|
||||
without a corresponding RESUME.
|
||||
|
||||
## print_stats
|
||||
|
||||
The following information is available in the `print_stats` object
|
||||
(this object is automatically available if a
|
||||
[virtual_sdcard](Config_Reference.md#virtual_sdcard) config section is
|
||||
defined):
|
||||
- `filename`, `total_duration`, `print_duration`, `filament_used`,
|
||||
`state`, `message`: Estimated information about the current print
|
||||
when a virtual_sdcard print is active.
|
||||
|
||||
## probe
|
||||
|
||||
The following information is available in the
|
||||
[probe](Config_Reference.md#probe) object (this object is also
|
||||
available if a [bltouch](Config_Reference.md#bltouch) config section
|
||||
is defined):
|
||||
- `last_query`: Returns True if the probe was reported as "triggered"
|
||||
during the last QUERY_PROBE command. Note, if this is used in a
|
||||
macro, due to the order of template expansion, the QUERY_PROBE
|
||||
command must be run prior to the macro containing this reference.
|
||||
- `last_z_result`: Returns the Z result value of the last PROBE
|
||||
command. Note, if this is used in a macro, due to the order of
|
||||
template expansion, the PROBE (or similar) command must be run prior
|
||||
to the macro containing this reference.
|
||||
|
||||
## quad_gantry_level
|
||||
|
||||
The following information is available in the `quad_gantry_level` object
|
||||
(this object is available if quad_gantry_level is defined):
|
||||
- `applied`: True if the gantry leveling process has been run and completed
|
||||
successfully.
|
||||
|
||||
## query_endstops
|
||||
|
||||
The following information is available in the `query_endstops` object
|
||||
(this object is available if any endstop is defined):
|
||||
- `last_query["<endstop>"]`: Returns True if the given endstop was
|
||||
reported as "triggered" during the last QUERY_ENDSTOP command. Note,
|
||||
if this is used in a macro, due to the order of template expansion,
|
||||
the QUERY_ENDSTOP command must be run prior to the macro containing
|
||||
this reference.
|
||||
|
||||
## servo
|
||||
|
||||
The following information is available in
|
||||
[servo some_name](Config_Reference.md#servo) objects:
|
||||
- `printer["servo <config_name>"].value`: The last setting of the PWM
|
||||
pin (a value between 0.0 and 1.0) associated with the servo.
|
||||
|
||||
## system_stats
|
||||
|
||||
The following information is available in the `system_stats` object
|
||||
(this object is always available):
|
||||
- `sysload`, `cputime`, `memavail`: Information on the host operating
|
||||
system and process load.
|
||||
|
||||
## temperature sensors
|
||||
|
||||
The following information is available in
|
||||
|
||||
[bme280 config_section_name](Config_Reference.md#bmp280bme280bme680-temperature-sensor),
|
||||
[htu21d config_section_name](Config_Reference.md#htu21d-sensor),
|
||||
[lm75 config_section_name](Config_Reference.md#lm75-temperature-sensor),
|
||||
and
|
||||
[temperature_host config_section_name](Config_Reference.md#host-temperature-sensor)
|
||||
objects:
|
||||
- `temperature`: The last read temperature from the sensor.
|
||||
- `humidity`, `pressure`, `gas`: The last read values from the sensor
|
||||
(only on bme280, htu21d, and lm75 sensors).
|
||||
|
||||
## temperature_fan
|
||||
|
||||
The following information is available in
|
||||
[temperature_fan some_name](Config_Reference.md#temperature_fan)
|
||||
objects:
|
||||
- `temperature`: The last read temperature from the sensor.
|
||||
- `target`: The target temperature for the fan.
|
||||
|
||||
## temperature_sensor
|
||||
|
||||
The following information is available in
|
||||
[temperature_sensor some_name](Config_Reference.md#temperature_sensor)
|
||||
objects:
|
||||
- `temperature`: The last read temperature from the sensor.
|
||||
- `measured_min_temp`, `measured_max_temp`: The lowest and highest
|
||||
temperature seen by the sensor since the Klipper host software was
|
||||
last restarted.
|
||||
|
||||
## tmc drivers
|
||||
|
||||
The following information is available in
|
||||
[TMC stepper driver](Config_Reference.md#tmc-stepper-driver-configuration)
|
||||
objects (eg, `[tmc2208 stepper_x]`):
|
||||
- `mcu_phase_offset`: The micro-controller stepper position
|
||||
corresponding with the driver's "zero" phase. This field may be null
|
||||
if the phase offset is not known.
|
||||
- `phase_offset_position`: The "commanded position" corresponding to
|
||||
the driver's "zero" phase. This field may be null if the phase
|
||||
offset is not known.
|
||||
- `drv_status`: The results of the last driver status query. (Only
|
||||
non-zero fields are reported.) This field will be null if the driver
|
||||
is not enabled (and thus is not periodically queried).
|
||||
- `run_current`: The currently set run current.
|
||||
- `hold_current`: The currently set hold current.
|
||||
|
||||
## toolhead
|
||||
|
||||
The following information is available in the `toolhead` object
|
||||
(this object is always available):
|
||||
- `position`: The last commanded position of the toolhead relative to
|
||||
the coordinate system specified in the config file. It is possible
|
||||
to access the x, y, z, and e components of this position (eg,
|
||||
`position.x`).
|
||||
- `extruder`: The name of the currently active extruder. For example,
|
||||
in a macro one could use `printer[printer.toolhead.extruder].target`
|
||||
to get the target temperature of the current extruder.
|
||||
- `homed_axes`: The current cartesian axes considered to be in a
|
||||
"homed" state. This is a string containing one or more of "x", "y",
|
||||
"z".
|
||||
- `axis_minimum`, `axis_maximum`: The axis travel limits (mm) after
|
||||
homing. It is possible to access the x, y, z components of this
|
||||
limit value (eg, `axis_minimum.x`, `axis_maximum.z`).
|
||||
- `max_velocity`, `max_accel`, `max_accel_to_decel`,
|
||||
`square_corner_velocity`: The current printing limits that are in
|
||||
effect. This may differ from the config file settings if a
|
||||
`SET_VELOCITY_LIMIT` (or `M204`) command alters them at run-time.
|
||||
- `stalls`: The total number of times (since the last restart) that
|
||||
the printer had to be paused because the toolhead moved faster than
|
||||
moves could be read from the G-Code input.
|
||||
|
||||
## dual_carriage
|
||||
|
||||
The following information is available in
|
||||
[dual_carriage](Config_Reference.md#dual_carriage)
|
||||
on a hybrid_corexy or hybrid_corexz robot
|
||||
- `mode`: The current mode. Possible values are: "FULL_CONTROL"
|
||||
- `active_carriage`: The current active carriage.
|
||||
Possible values are: "CARRIAGE_0", "CARRIAGE_1"
|
||||
|
||||
## virtual_sdcard
|
||||
|
||||
The following information is available in the
|
||||
[virtual_sdcard](Config_Reference.md#virtual_sdcard) object:
|
||||
- `is_active`: Returns True if a print from file is currently active.
|
||||
- `progress`: An estimate of the current print progress (based of file
|
||||
size and file position).
|
||||
- `file_path`: A full path to the file of currently loaded file.
|
||||
- `file_position`: The current position (in bytes) of an active print.
|
||||
- `file_size`: The file size (in bytes) of currently loaded file.
|
||||
|
||||
## webhooks
|
||||
|
||||
The following information is available in the `webhooks` object (this
|
||||
object is always available):
|
||||
- `state`: Returns a string indicating the current Klipper
|
||||
state. Possible values are: "ready", "startup", "shutdown", "error".
|
||||
- `state_message`: A human readable string giving additional context
|
||||
on the current Klipper state.
|
||||
|
||||
## z_tilt
|
||||
|
||||
The following information is available in the `z_tilt` object (this
|
||||
object is available if z_tilt is defined):
|
||||
- `applied`: True if the z-tilt leveling process has been run and completed
|
||||
successfully.
|
||||
557
docs/TMC_Drivers.md
Normal file
@@ -0,0 +1,557 @@
|
||||
# TMC drivers
|
||||
|
||||
This document provides information on using Trinamic stepper motor
|
||||
drivers in SPI/UART mode on Klipper.
|
||||
|
||||
Klipper can also use Trinamic drivers in their "standalone mode".
|
||||
However, when the drivers are in this mode, no special Klipper
|
||||
configuration is needed and the advanced Klipper features discussed in
|
||||
this document are not available.
|
||||
|
||||
In addition to this document, be sure to review the
|
||||
[TMC driver config reference](Config_Reference.md#tmc-stepper-driver-configuration).
|
||||
|
||||
## Tuning motor current
|
||||
|
||||
A higher driver current increases positional accuracy and torque.
|
||||
However, a higher current also increases the heat produced by the
|
||||
stepper motor and the stepper motor driver. If the stepper motor
|
||||
driver gets too hot it will disable itself and Klipper will report an
|
||||
error. If the stepper motor gets too hot, it loses torque and
|
||||
positional accuracy. (If it gets very hot it may also melt plastic
|
||||
parts attached to it or near it.)
|
||||
|
||||
As a general tuning tip, prefer higher current values as long as the
|
||||
stepper motor does not get too hot and the stepper motor driver does
|
||||
not report warnings or errors. In general, it is okay for the stepper
|
||||
motor to feel warm, but it should not become so hot that it is painful
|
||||
to touch.
|
||||
|
||||
## Prefer to not specify a hold_current
|
||||
|
||||
If one configures a `hold_current` then the TMC driver can reduce
|
||||
current to the stepper motor when it detects that the stepper is not
|
||||
moving. However, changing motor current may itself introduce motor
|
||||
movement. This may occur due to "detent forces" within the stepper
|
||||
motor (the permanent magnet in the rotor pulls towards the iron teeth
|
||||
in the stator) or due to external forces on the axis carriage.
|
||||
|
||||
Most stepper motors will not obtain a significant benefit to reducing
|
||||
current during normal prints, because few printing moves will leave a
|
||||
stepper motor idle for sufficiently long to activate the
|
||||
`hold_current` feature. And, it is unlikely that one would want to
|
||||
introduce subtle print artifacts to the few printing moves that do
|
||||
leave a stepper idle sufficiently long.
|
||||
|
||||
If one wishes to reduce current to motors during print start routines,
|
||||
then consider issuing
|
||||
[SET_TMC_CURRENT](G-Codes.md#set_tmc_current) commands in a
|
||||
[START_PRINT macro](Slicers.md#klipper-gcode_macro) to adjust the
|
||||
current before and after normal printing moves.
|
||||
|
||||
Some printers with dedicated Z motors that are idle during normal
|
||||
printing moves (no bed_mesh, no bed_tilt, no Z skew_correction, no
|
||||
"vase mode" prints, etc.) may find that Z motors do run cooler with a
|
||||
`hold_current`. If implementing this then be sure to take into account
|
||||
this type of uncommanded Z axis movement during bed leveling, bed
|
||||
probing, probe calibration, and similar. The `driver_TPOWERDOWN` and
|
||||
`driver_IHOLDDELAY` should also be calibrated accordingly. If unsure,
|
||||
prefer to not specify a `hold_current`.
|
||||
|
||||
## Setting "spreadCycle" vs "stealthChop" Mode
|
||||
|
||||
By default, Klipper places the TMC drivers in "spreadCycle" mode. If
|
||||
the driver supports "stealthChop" then it can be enabled by adding
|
||||
`stealthchop_threshold: 999999` to the TMC config section.
|
||||
|
||||
In general, spreadCycle mode provides greater torque and greater
|
||||
positional accuracy than stealthChop mode. However, stealthChop mode
|
||||
may produce significantly lower audible noise on some printers.
|
||||
|
||||
Tests comparing modes have shown an increased "positional lag" of
|
||||
around 75% of a full-step during constant velocity moves when using
|
||||
stealthChop mode (for example, on a printer with 40mm
|
||||
rotation_distance and 200 steps_per_rotation, position deviation of
|
||||
constant speed moves increased by ~0.150mm). However, this "delay in
|
||||
obtaining the requested position" may not manifest as a significant
|
||||
print defect and one may prefer the quieter behavior of stealthChop
|
||||
mode.
|
||||
|
||||
It is recommended to always use "spreadCycle" mode (by not specifying
|
||||
`stealthchop_threshold`) or to always use "stealthChop" mode (by
|
||||
setting `stealthchop_threshold` to 999999). Unfortunately, the drivers
|
||||
often produce poor and confusing results if the mode changes while the
|
||||
motor is at a non-zero velocity.
|
||||
|
||||
## TMC interpolate setting introduces small position deviation
|
||||
|
||||
The TMC driver `interpolate` setting may reduce the audible noise of
|
||||
printer movement at the cost of introducing a small systemic
|
||||
positional error. This systemic positional error results from the
|
||||
driver's delay in executing "steps" that Klipper sends it. During
|
||||
constant velocity moves, this delay results in a positional error of
|
||||
nearly half a configured microstep (more precisely, the error is half
|
||||
a microstep distance minus a 512th of a full step distance). For
|
||||
example, on an axis with a 40mm rotation_distance, 200
|
||||
steps_per_rotation, and 16 microsteps, the systemic error introduced
|
||||
during constant velocity moves is ~0.006mm.
|
||||
|
||||
For best positional accuracy consider using spreadCycle mode and
|
||||
disable interpolation (set `interpolate: False` in the TMC driver
|
||||
config). When configured this way, one may increase the `microstep`
|
||||
setting to reduce audible noise during stepper movement. Typically, a
|
||||
microstep setting of `64` or `128` will have similar audible noise as
|
||||
interpolation, and do so without introducing a systemic positional
|
||||
error.
|
||||
|
||||
If using stealthChop mode then the positional inaccuracy from
|
||||
interpolation is small relative to the positional inaccuracy
|
||||
introduced from stealthChop mode. Therefore tuning interpolation is
|
||||
not considered useful when in stealthChop mode, and one can leave
|
||||
interpolation in its default state.
|
||||
|
||||
## Sensorless Homing
|
||||
|
||||
Sensorless homing allows to home an axis without the need for a
|
||||
physical limit switch. Instead, the carriage on the axis is moved into
|
||||
the mechanical limit making the stepper motor lose steps. The stepper
|
||||
driver senses the lost steps and indicates this to the controlling MCU
|
||||
(Klipper) by toggling a pin. This information can be used by Klipper
|
||||
as end stop for the axis.
|
||||
|
||||
This guide covers the setup of sensorless homing for the X axis of
|
||||
your (cartesian) printer. However, it works the same with all other
|
||||
axes (that require an end stop). You should configure and tune it for
|
||||
one axis at a time.
|
||||
|
||||
### Limitations
|
||||
|
||||
Be sure that your mechanical components are able to handle the load of
|
||||
the carriage bumping into the limit of the axis repeatedly. Especially
|
||||
leadscrews might generate a lot of force. Homing a Z axis by bumping
|
||||
the nozzle into the printing surface might not be a good idea. For
|
||||
best results, verify that the axis carriage will make a firm contact
|
||||
with the axis limit.
|
||||
|
||||
Further, sensorless homing might not be accurate enough for your
|
||||
printer. While homing X and Y axes on a cartesian machine can work
|
||||
well, homing the Z axis is generally not accurate enough and may
|
||||
result in an inconsistent first layer height. Homing a delta printer
|
||||
sensorless is not advisable due to missing accuracy.
|
||||
|
||||
Further, the stall detection of the stepper driver is dependent on the
|
||||
mechanical load on the motor, the motor current and the motor
|
||||
temperature (coil resistance).
|
||||
|
||||
Sensorless homing works best at medium motor speeds. For very slow
|
||||
speeds (less than 10 RPM) the motor does not generate significant back
|
||||
EMF and the TMC cannot reliably detect motor stalls. Further, at very
|
||||
high speeds, the back EMF of the motor approaches the supply voltage
|
||||
of the motor, so the TMC cannot detect stalls anymore. It is advised
|
||||
to have a look in the datasheet of your specific TMCs. There you can
|
||||
also find more details on limitations of this setup.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
A few prerequisites are needed to use sensorless homing:
|
||||
|
||||
1. A stallGuard capable TMC stepper driver (tmc2130, tmc2209, tmc2660,
|
||||
or tmc5160).
|
||||
2. SPI / UART interface of the TMC driver wired to micro-controller
|
||||
(stand-alone mode does not work).
|
||||
3. The appropriate "DIAG" or "SG_TST" pin of TMC driver connected to
|
||||
the micro-controller.
|
||||
4. The steps in the [config checks](Config_checks.md) document must be
|
||||
run to confirm the stepper motors are configured and working
|
||||
properly.
|
||||
|
||||
### Tuning
|
||||
|
||||
The procedure described here has six major steps:
|
||||
|
||||
1. Choose a homing speed.
|
||||
2. Configure the `printer.cfg` file to enable sensorless homing.
|
||||
3. Find the stallguard setting with highest sensitivity that
|
||||
successfully homes.
|
||||
4. Find the stallguard setting with lowest sensitivity that
|
||||
successfully homes with a single touch.
|
||||
5. Update the `printer.cfg` with the desired stallguard setting.
|
||||
6. Create or update `printer.cfg` macros to home consistently.
|
||||
|
||||
#### Choose homing speed
|
||||
|
||||
The homing speed is an important choice when performing sensorless
|
||||
homing. It's desirable to use a slow homing speed so that the carriage
|
||||
does not exert excessive force on the frame when making contact with
|
||||
the end of the rail. However, the TMC drivers can't reliably detect a
|
||||
stall at very slow speeds.
|
||||
|
||||
A good starting point for the homing speed is for the stepper motor to
|
||||
make a full rotation every two seconds. For many axes this will be the
|
||||
`rotation_distance` divided by two. For example:
|
||||
```
|
||||
[stepper_x]
|
||||
rotation_distance: 40
|
||||
homing_speed: 20
|
||||
...
|
||||
```
|
||||
|
||||
#### Configure printer.cfg for sensorless homing
|
||||
|
||||
The `homing_retract_dist` setting must be set to zero in the
|
||||
`stepper_x` config section to disable the second homing move. The
|
||||
second homing attempt does not add value when using sensorless homing,
|
||||
it will not work reliably, and it will confuse the tuning process.
|
||||
|
||||
Be sure that a `hold_current` setting is not specified in the TMC
|
||||
driver section of the config. (If a hold_current is set then after
|
||||
contact is made, the motor stops while the carriage is pressed against
|
||||
the end of the rail, and reducing the current while in that position
|
||||
may cause the carriage to move - that results in poor performance and
|
||||
will confuse the tuning process.)
|
||||
|
||||
It is necessary to configure the sensorless homing pins and to
|
||||
configure initial "stallguard" settings. A tmc2209 example
|
||||
configuration for an X axis might look like:
|
||||
```
|
||||
[tmc2209 stepper_x]
|
||||
diag_pin: ^PA1 # Set to MCU pin connected to TMC DIAG pin
|
||||
driver_SGTHRS: 255 # 255 is most sensitive value, 0 is least sensitive
|
||||
...
|
||||
|
||||
[stepper_x]
|
||||
endstop_pin: tmc2209_stepper_x:virtual_endstop
|
||||
homing_retract_dist: 0
|
||||
...
|
||||
```
|
||||
|
||||
An example tmc2130 or tmc5160 config might look like:
|
||||
```
|
||||
[tmc2130 stepper_x]
|
||||
diag1_pin: ^!PA1 # Pin connected to TMC DIAG1 pin (or use diag0_pin / DIAG0 pin)
|
||||
driver_SGT: -64 # -64 is most sensitive value, 63 is least sensitive
|
||||
...
|
||||
|
||||
[stepper_x]
|
||||
endstop_pin: tmc2130_stepper_x:virtual_endstop
|
||||
homing_retract_dist: 0
|
||||
...
|
||||
```
|
||||
|
||||
An example tmc2660 config might look like:
|
||||
```
|
||||
[tmc2660 stepper_x]
|
||||
driver_SGT: -64 # -64 is most sensitive value, 63 is least sensitive
|
||||
...
|
||||
|
||||
[stepper_x]
|
||||
endstop_pin: ^PA1 # Pin connected to TMC SG_TST pin
|
||||
homing_retract_dist: 0
|
||||
...
|
||||
```
|
||||
|
||||
The examples above only show settings specific to sensorless
|
||||
homing. See the
|
||||
[config reference](Config_Reference.md#tmc-stepper-driver-configuration)
|
||||
for all the available options.
|
||||
|
||||
#### Find highest sensitivity that successfully homes
|
||||
|
||||
Place the carriage near the center of the rail. Use the SET_TMC_FIELD
|
||||
command to set the highest sensitivity. For tmc2209:
|
||||
```
|
||||
SET_TMC_FIELD STEPPER=stepper_x FIELD=SGTHRS VALUE=255
|
||||
```
|
||||
For tmc2130, tmc5160, and tmc2660:
|
||||
```
|
||||
SET_TMC_FIELD STEPPER=stepper_x FIELD=sgt VALUE=-64
|
||||
```
|
||||
|
||||
Then issue a `G28 X0` command and verify the axis does not move at
|
||||
all. If the axis does move, then issue an `M112` to halt the printer -
|
||||
something is not correct with the diag/sg_tst pin wiring or
|
||||
configuration and it must be corrected before continuing.
|
||||
|
||||
Next, continually decrease the sensitivity of the `VALUE` setting and
|
||||
run the `SET_TMC_FIELD` `G28 X0` commands again to find the highest
|
||||
sensitivity that results in the carriage successfully moving all the
|
||||
way to the endstop and halting. (For tmc2209 drivers this will be
|
||||
decreasing SGTHRS, for other drivers it will be increasing sgt.) Be
|
||||
sure to start each attempt with the carriage near the center of the
|
||||
rail (if needed issue `M84` and then manually move the carriage to the
|
||||
center). It should be possible to find the highest sensitivity that
|
||||
homes reliably (settings with higher sensitivity result in small or no
|
||||
movement). Note the found value as *maximum_sensitivity*. (If the
|
||||
minimum possible sensitivity (SGTHRS=0 or sgt=63) is obtained without
|
||||
any carriage movement then something is not correct with the
|
||||
diag/sg_tst pin wiring or configuration and it must be corrected
|
||||
before continuing.)
|
||||
|
||||
When searching for maximum_sensitivity, it may be convenient to jump
|
||||
to different VALUE settings (so as to bisect the VALUE parameter). If
|
||||
doing this then be prepared to issue an `M112` command to halt the
|
||||
printer, as a setting with a very low sensitivity may cause the axis
|
||||
to repeatedly "bang" into the end of the rail.
|
||||
|
||||
Be sure to wait a couple of seconds between each homing attempt. After
|
||||
the TMC driver detects a stall it may take a little time for it to
|
||||
clear its internal indicator and be capable of detecting another
|
||||
stall.
|
||||
|
||||
During these tuning tests, if a `G28 X0` command does not move all the
|
||||
way to the axis limit, then be careful with issuing any regular
|
||||
movement commands (eg, `G1`). Klipper will not have a correct
|
||||
understanding of the carriage position and a move command may cause
|
||||
undesirable and confusing results.
|
||||
|
||||
#### Find lowest sensitivity that homes with one touch
|
||||
|
||||
When homing with the found *maximum_sensitivity* value, the axis
|
||||
should move to the end of the rail and stop with a "single touch" -
|
||||
that is, there should not be a "clicking" or "banging" sound. (If
|
||||
there is a banging or clicking sound at maximum_sensitivity then the
|
||||
homing_speed may be too low, the driver current may be too low, or
|
||||
sensorless homing may not be a good choice for the axis.)
|
||||
|
||||
The next step is to again continually move the carriage to a position
|
||||
near the center of the rail, decrease the sensitivity, and run the
|
||||
`SET_TMC_FIELD` `G28 X0` commands - the goal is now to find the lowest
|
||||
sensitivity that still results in the carriage successfully homing
|
||||
with a "single touch". That is, it does not "bang" or "click" when
|
||||
contacting the end of the rail. Note the found value as
|
||||
*minimum_sensitivity*.
|
||||
|
||||
#### Update printer.cfg with sensitivity value
|
||||
|
||||
After finding *maximum_sensitivity* and *minimum_sensitivity*, use a
|
||||
calculator to obtain the recommend sensitivity as
|
||||
*minimum_sensitivity + (maximum_sensitivity - minimum_sensitivity)/3*.
|
||||
The recommended sensitivity should be in the range between the minimum
|
||||
and maximum, but slightly closer to the minimum. Round the final value
|
||||
to the nearest integer value.
|
||||
|
||||
For tmc2209 set this in the config as `driver_SGTHRS`, for other TMC
|
||||
drivers set this in the config as `driver_SGT`.
|
||||
|
||||
If the range between *maximum_sensitivity* and *minimum_sensitivity*
|
||||
is small (eg, less than 5) then it may result in unstable homing. A
|
||||
faster homing speed may increase the range and make the operation more
|
||||
stable.
|
||||
|
||||
Note that if any change is made to driver current, homing speed, or a
|
||||
notable change is made to the printer hardware, then it will be
|
||||
necessary to run the tuning process again.
|
||||
|
||||
#### Using Macros when Homing
|
||||
|
||||
After sensorless homing completes the carriage will be pressed against
|
||||
the end of the rail and the stepper will exert a force on the frame
|
||||
until the carriage is moved away. It is a good idea to create a macro
|
||||
to home the axis and immediately move the carriage away from the end
|
||||
of the rail.
|
||||
|
||||
It is a good idea for the macro to pause at least 2 seconds prior to
|
||||
starting sensorless homing (or otherwise ensure that there has been no
|
||||
movement on the stepper for 2 seconds). Without a delay it is possible
|
||||
for the driver's internal stall flag to still be set from a previous
|
||||
move.
|
||||
|
||||
It can also be useful to have that macro set the driver current before
|
||||
homing and set a new current after the carriage has moved away.
|
||||
|
||||
An example macro might look something like:
|
||||
```
|
||||
[gcode_macro SENSORLESS_HOME_X]
|
||||
gcode:
|
||||
{% set HOME_CUR = 0.700 %}
|
||||
{% set driver_config = printer.configfile.settings['tmc2209 stepper_x'] %}
|
||||
{% set RUN_CUR = driver_config.run_current %}
|
||||
# Set current for sensorless homing
|
||||
SET_TMC_CURRENT STEPPER=stepper_x CURRENT={HOME_CUR}
|
||||
# Pause to ensure driver stall flag is clear
|
||||
G4 P2000
|
||||
# Home
|
||||
G28 X0
|
||||
# Move away
|
||||
G90
|
||||
G1 X5 F1200
|
||||
# Set current during print
|
||||
SET_TMC_CURRENT STEPPER=stepper_x CURRENT={RUN_CUR}
|
||||
```
|
||||
|
||||
The resulting macro can be called from a
|
||||
[homing_override config section](Config_Reference.md#homing_override)
|
||||
or from a [START_PRINT macro](Slicers.md#klipper-gcode_macro).
|
||||
|
||||
Note that if the driver current during homing is changed, then the
|
||||
tuning process should be run again.
|
||||
|
||||
### Tips for sensorless homing on CoreXY
|
||||
|
||||
It is possible to use sensorless homing on the X and Y carriages of a
|
||||
CoreXY printer. Klipper uses the `[stepper_x]` stepper to detect
|
||||
stalls when homing the X carriage and uses the `[stepper_y]` stepper
|
||||
to detect stalls when homing the Y carriage.
|
||||
|
||||
Use the tuning guide described above to find the appropriate "stall
|
||||
sensitivity" for each carriage, but be aware of the following
|
||||
restrictions:
|
||||
1. When using sensorless homing on CoreXY, make sure there is no
|
||||
`hold_current` configured for either stepper.
|
||||
2. While tuning, make sure both the X and Y carriages are near the
|
||||
center of their rails before each home attempt.
|
||||
3. After tuning is complete, when homing both X and Y, use macros to
|
||||
ensure that one axis is homed first, then move that carriage away
|
||||
from the axis limit, pause for at least 2 seconds, and then start
|
||||
the homing of the other carriage. The move away from the axis
|
||||
avoids homing one axis while the other is pressed against the axis
|
||||
limit (which may skew the stall detection). The pause is necessary
|
||||
to ensure the driver's stall flag is cleared prior to homing again.
|
||||
|
||||
## Querying and diagnosing driver settings
|
||||
|
||||
The `[DUMP_TMC command](G-Codes.md#dump_tmc) is a useful tool when
|
||||
configuring and diagnosing the drivers. It will report all fields
|
||||
configured by Klipper as well as all fields that can be queried from
|
||||
the driver.
|
||||
|
||||
All of the reported fields are defined in the Trinamic datasheet for
|
||||
each driver. These datasheets can be found on the
|
||||
[Trinamic website](https://www.trinamic.com/). Obtain and review the
|
||||
Trinamic datasheet for the driver to interpret the results of
|
||||
DUMP_TMC.
|
||||
|
||||
## Configuring driver_XXX settings
|
||||
|
||||
Klipper supports configuring many low-level driver fields using
|
||||
`driver_XXX` settings. The
|
||||
[TMC driver config reference](Config_Reference.md#tmc-stepper-driver-configuration)
|
||||
has the full list of fields available for each type of driver.
|
||||
|
||||
In addition, almost all fields can be modified at run-time using the
|
||||
[SET_TMC_FIELD command](G-Codes.md#set_tmc_field).
|
||||
|
||||
Each of these fields is defined in the Trinamic datasheet for each
|
||||
driver. These datasheets can be found on the
|
||||
[Trinamic website](https://www.trinamic.com/).
|
||||
|
||||
Note that the Trinamic datasheets sometime use wording that can
|
||||
confuse a high-level setting (such as "hysteresis end") with a
|
||||
low-level field value (eg, "HEND"). In Klipper, `driver_XXX` and
|
||||
SET_TMC_FIELD always set the low-level field value that is actually
|
||||
written to the driver. So, for example, if the Trinamic datasheet
|
||||
states that a value of 3 must be written to the HEND field to obtain a
|
||||
"hysteresis end" of 0, then set `driver_HEND=3` to obtain the
|
||||
high-level value of 0.
|
||||
|
||||
## Common Questions
|
||||
|
||||
### Can I use stealthChop mode on an extruder with pressure advance?
|
||||
|
||||
Many people successfully use "stealthChop" mode with Klipper's
|
||||
pressure advance. Klipper implements
|
||||
[smooth pressure advance](Kinematics.md#pressure-advance) which does
|
||||
not introduce any instantaneous velocity changes.
|
||||
|
||||
However, "stealthChop" mode may produce lower motor torque and/or
|
||||
produce higher motor heat. It may or may not be an adequate mode for
|
||||
your particular printer.
|
||||
|
||||
### I keep getting "Unable to read tmc uart 'stepper_x' register IFCNT" errors?
|
||||
|
||||
This occurs when Klipper is unable to communicate with a tmc2208 or
|
||||
tmc2209 driver.
|
||||
|
||||
Make sure that the motor power is enabled, as the stepper motor driver
|
||||
generally needs motor power before it can communicate with the
|
||||
micro-controller.
|
||||
|
||||
If this error occurs after flashing Klipper for the first time, then
|
||||
the stepper driver may have been previously programmed in a state that
|
||||
is not compatible with Klipper. To reset the state, remove all power
|
||||
from the printer for several seconds (physically unplug both USB and
|
||||
power plugs).
|
||||
|
||||
Otherwise, this error is typically the result of incorrect UART pin
|
||||
wiring or an incorrect Klipper configuration of the UART pin settings.
|
||||
|
||||
### I keep getting "Unable to write tmc spi 'stepper_x' register ..." errors?
|
||||
|
||||
This occurs when Klipper is unable to communicate with a tmc2130 or
|
||||
tmc5160 driver.
|
||||
|
||||
Make sure that the motor power is enabled, as the stepper motor driver
|
||||
generally needs motor power before it can communicate with the
|
||||
micro-controller.
|
||||
|
||||
Otherwise, this error is typically the result of incorrect SPI wiring,
|
||||
an incorrect Klipper configuration of the SPI settings, or an
|
||||
incomplete configuration of devices on an SPI bus.
|
||||
|
||||
Note that if the driver is on a shared SPI bus with multiple devices
|
||||
then be sure to fully configure every device on that shared SPI bus in
|
||||
Klipper. If a device on a shared SPI bus is not configured, then it
|
||||
may incorrectly respond to commands not intended for it and corrupt
|
||||
the communication to the intended device. If there is a device on a
|
||||
shared SPI bus that can not be configured in Klipper, then use a
|
||||
[static_digital_output config section](Config_Reference.md#static_digital_output)
|
||||
to set the CS pin of the unused device high (so that it will not
|
||||
attempt to use the SPI bus). The board's schematic is often a useful
|
||||
reference for finding which devices are on an SPI bus and their
|
||||
associated pins.
|
||||
|
||||
### Why did I get a "TMC reports error: ..." error?
|
||||
|
||||
This type of error indicates the TMC driver detected a problem and has
|
||||
disabled itself. That is, the driver stopped holding its position and
|
||||
ignored movement commands. If Klipper detects that an active driver
|
||||
has disabled itself, it will transition the printer into a "shutdown"
|
||||
state.
|
||||
|
||||
It's also possible that a **TMC reports error** shutdown occurs due to
|
||||
SPI errors that prevent communication with the driver (on tmc2130,
|
||||
tmc5160, or tmc2660). If this occurs, it's common for the reported
|
||||
driver status to show `00000000` or `ffffffff` - for example: `TMC
|
||||
reports error: DRV_STATUS: ffffffff ...` OR `TMC reports error:
|
||||
READRSP@RDSEL2: 00000000 ...`. Such a failure may be due to an SPI
|
||||
wiring problem or may be due to a self-reset or failure of the TMC
|
||||
driver.
|
||||
|
||||
Some common errors and tips for diagnosing them:
|
||||
|
||||
#### TMC reports error: `... ot=1(OvertempError!)`
|
||||
|
||||
This indicates the motor driver disabled itself because it became too
|
||||
hot. Typical solutions are to decrease the stepper motor current,
|
||||
increase cooling on the stepper motor driver, and/or increase cooling
|
||||
on the stepper motor.
|
||||
|
||||
#### TMC reports error: `... ShortToGND` OR `LowSideShort`
|
||||
|
||||
This indicates the driver has disabled itself because it detected very
|
||||
high current passing through the driver. This may indicate a loose or
|
||||
shorted wire to the stepper motor or within the stepper motor itself.
|
||||
|
||||
This error may also occur if using stealthChop mode and the TMC driver
|
||||
is not able to accurately predict the mechanical load of the motor.
|
||||
(If the driver makes a poor prediction then it may send too much
|
||||
current through the motor and trigger its own over-current detection.)
|
||||
To test this, disable stealthChop mode and check if the errors
|
||||
continue to occur.
|
||||
|
||||
#### TMC reports error: `... reset=1(Reset)` OR `CS_ACTUAL=0(Reset?)` OR `SE=0(Reset?)`
|
||||
|
||||
This indicates that the driver has reset itself mid-print. This may be
|
||||
due to voltage or wiring issues.
|
||||
|
||||
#### TMC reports error: `... uv_cp=1(Undervoltage!)`
|
||||
|
||||
This indicates the driver has detected a low-voltage event and has
|
||||
disabled itself. This may be due to wiring or power supply issues.
|
||||
|
||||
### How do I tune spreadCycle/coolStep/etc. mode on my drivers?
|
||||
|
||||
The [Trinamic website](https://www.trinamic.com/) has guides on
|
||||
configuring the drivers. These guides are often technical, low-level,
|
||||
and may require specialized hardware. Regardless, they are the best
|
||||
source of information.
|
||||
22
docs/TSL1401CL_Filament_Width_Sensor.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# TSL1401CL filament width sensor
|
||||
|
||||
This document describes Filament Width Sensor host module. Hardware used
|
||||
for developing this host module is based on TSL1401CL linear sensor array
|
||||
but it can work with any sensor array that has analog output. You can find
|
||||
designs at [Thingiverse](https://www.thingiverse.com/search?q=filament%20width%20sensor).
|
||||
|
||||
To use a sensor array as a filament width sensor, read
|
||||
[Config Reference](Config_Reference.md#tsl1401cl_filament_width_sensor) and
|
||||
[G-Code documentation](G-Codes.md#hall_filament_width_sensor).
|
||||
|
||||
## How does it work?
|
||||
|
||||
Sensor generates analog output based on calculated filament width. Output
|
||||
voltage always equals to detected filament width (Ex. 1.65v, 1.70v, 3.0v).
|
||||
Host module monitors voltage changes and adjusts extrusion multiplier.
|
||||
|
||||
## Note:
|
||||
|
||||
Sensor readings done with 10 mm intervals by default. If necessary you are
|
||||
free to change this setting by editing ***MEASUREMENT_INTERVAL_MM*** parameter
|
||||
in **filament_width_sensor.py** file.
|
||||
69
docs/Using_PWM_Tools.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Using PWM tools
|
||||
|
||||
This document describes how to setup a PWM-controlled laser or spindle
|
||||
using `output_pin` and some macros.
|
||||
|
||||
## How does it work?
|
||||
|
||||
With re-purposing the printhead's fan pwm output, you can control
|
||||
lasers or spindles.
|
||||
This is useful if you use switchable print heads, for example
|
||||
the E3D toolchanger or a DIY solution.
|
||||
Usually, cam-tools such as LaserWeb can be configured to use `M3-M5`
|
||||
commands, which stand for _spindle speed CW_ (`M3 S[0-255]`),
|
||||
_spindle speed CCW_ (`M4 S[0-255]`) and _spindle stop_ (`M5`).
|
||||
|
||||
|
||||
**Warning:** When driving a laser, keep all security precautions
|
||||
that you can think of! Diode lasers are usually inverted.
|
||||
This means, that when the MCU restarts, the laser will be
|
||||
_fully on_ for the time it takes the MCU to start up again.
|
||||
For good measure, it is recommended to _always_ wear appropriate
|
||||
laser-goggles of the right wavelength if the laser is powered;
|
||||
and to disconnect the laser when it is not needed.
|
||||
Also, you should configure a safety timeout,
|
||||
so that when your host or MCU encounters an error, the tool will stop.
|
||||
|
||||
For an example configuration, see [config/sample-pwm-tool.cfg](/config/sample-pwm-tool.cfg).
|
||||
|
||||
## Current Limitations
|
||||
|
||||
There is a limitation of how frequent PWM updates may occur.
|
||||
While being very precise, a PWM update may only occur every 0.1 seconds,
|
||||
rendering it almost useless for raster engraving.
|
||||
However, there exists an [experimental branch](https://github.com/Cirromulus/klipper/tree/laser_tool) with its own tradeoffs.
|
||||
In long term, it is planned to add this functionality to main-line klipper.
|
||||
|
||||
## Commands
|
||||
|
||||
`M3/M4 S<value>` : Set PWM duty-cycle. Values between 0 and 255.
|
||||
`M5` : Stop PWM output to shutdown value.
|
||||
|
||||
## Laserweb Configuration
|
||||
|
||||
If you use Laserweb, a working configuration would be:
|
||||
|
||||
GCODE START:
|
||||
M5 ; Disable Laser
|
||||
G21 ; Set units to mm
|
||||
G90 ; Absolute positioning
|
||||
G0 Z0 F7000 ; Set Non-Cutting speed
|
||||
|
||||
GCODE END:
|
||||
M5 ; Disable Laser
|
||||
G91 ; relative
|
||||
G0 Z+20 F4000 ;
|
||||
G90 ; absolute
|
||||
|
||||
GCODE HOMING:
|
||||
M5 ; Disable Laser
|
||||
G28 ; Home all axis
|
||||
|
||||
TOOL ON:
|
||||
M3 $INTENSITY
|
||||
|
||||
TOOL OFF:
|
||||
M5 ; Disable Laser
|
||||
|
||||
LASER INTENSITY:
|
||||
S
|
||||
20
docs/_klipper3d/README
Normal file
@@ -0,0 +1,20 @@
|
||||
This directory defines the https://www.klipper3d.org/ website. The
|
||||
site is hosted using "github pages". The
|
||||
.github/workflows/klipper3d-deploy.yaml tool uses mkdocs (
|
||||
https://www.mkdocs.org/ ) to automatically convert the markdown files
|
||||
in the docs/ directory to html. In addition to the files in this
|
||||
directory, the docs/CNAME file also controls the website generation.
|
||||
|
||||
To test deploy the main English site locally one can use commands
|
||||
similar to the following:
|
||||
|
||||
virtualenv ~/mkdocs-env && ~/python-env/bin/pip install -r ~/klipper/docs/_klipper3d/mkdocs-requirements.txt
|
||||
cd ~/klipper && ~/mkdocs-env/bin/mkdocs serve --config-file ~/klipper/docs/_klipper3d/mkdocs.yml -a 0.0.0.0:8000
|
||||
|
||||
To test deploy the multi-language site locally one can use commands
|
||||
similar to the following:
|
||||
|
||||
virtualenv ~/mkdocs-env && ~/python-env/bin/pip install -r ~/klipper/docs/_klipper3d/mkdocs-requirements.txt
|
||||
source ~/mkdocs-env/bin/activate
|
||||
cd ~/klipper && ./docs/_klipper3d/build-translations.sh
|
||||
cd ~/klipper/site/ && python3 -m http.server 8000
|
||||
84
docs/_klipper3d/build-translations.sh
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# This script extracts the Klipper translations and builds multiple
|
||||
# mdocs sites - one for each supported language. See the README file
|
||||
# for additional details.
|
||||
|
||||
MKDOCS_DIR="docs/_klipper3d/"
|
||||
WORK_DIR="work/"
|
||||
TRANS_DIR="${WORK_DIR}klipper-translations/"
|
||||
TRANS_FILE="${TRANS_DIR}active_translations"
|
||||
MKDOCS_MAIN="${MKDOCS_DIR}mkdocs-main.yml"
|
||||
|
||||
# Fetch translations
|
||||
git clone --depth 1 https://github.com/Klipper3d/klipper-translations ${TRANS_DIR}
|
||||
|
||||
# Create new mkdocs-main.yml with language links
|
||||
cp ${MKDOCS_DIR}mkdocs.yml ${MKDOCS_MAIN}
|
||||
while IFS="," read dirname langsite langdesc langsearch; do
|
||||
sed -i "s%^.*# Alternate language links automatically added here$% - name: ${langdesc}\n link: /${langsite}/\n lang: ${langsite}\n\0%" ${MKDOCS_MAIN}
|
||||
done < <(egrep -v '^ *(#|$)' ${TRANS_FILE})
|
||||
|
||||
# Build main English website
|
||||
echo "building site for en"
|
||||
mkdocs build -f ${MKDOCS_MAIN}
|
||||
|
||||
# Build each additional language website
|
||||
while IFS="," read dirname langsite langdesc langsearch; do
|
||||
new_docs_dir="${WORK_DIR}lang/${langsite}/docs/"
|
||||
locale_dir="${TRANS_DIR}/docs/locales/${dirname}"
|
||||
|
||||
# read toc
|
||||
title=$(sed -n '1p' ${locale_dir}/Navigation.md)
|
||||
installation_and_configuration=$(sed -n '3p' ${locale_dir}/Navigation.md)
|
||||
configuration_reference=$(sed -n '5p' ${locale_dir}/Navigation.md)
|
||||
bed_level=$(sed -n '7p' ${locale_dir}/Navigation.md)
|
||||
resonance_compensation=$(sed -n '9p' ${locale_dir}/Navigation.md)
|
||||
command_template=$(sed -n '11p' ${locale_dir}/Navigation.md)
|
||||
developer_documentation=$(sed -n '13p' ${locale_dir}/Navigation.md)
|
||||
device_specific_documents=$(sed -n '15p' ${locale_dir}/Navigation.md)
|
||||
|
||||
# Copy markdown files to new_docs_dir
|
||||
echo "Copying $dirname to $langsite"
|
||||
mkdir -p "${new_docs_dir}"
|
||||
cp "${locale_dir}"/*.md "${new_docs_dir}"
|
||||
echo "copy resources"
|
||||
cp -r docs/img "${new_docs_dir}"
|
||||
cp -r docs/prints "${new_docs_dir}"
|
||||
cp -r docs/_klipper3d "${new_docs_dir}"
|
||||
|
||||
# manually replace index.md if a manual-index.md exist
|
||||
manual_index="${new_docs_dir}manual-index.md"
|
||||
if [[ -f "${manual_index}" ]]; then
|
||||
mv -f "${manual_index}" "${new_docs_dir}index.md"
|
||||
echo "replaced index.md with manual_index.md for $langsite"
|
||||
else
|
||||
echo "Manually translated index file for $langsite not found!"
|
||||
fi
|
||||
|
||||
# Create language specific mkdocs-lang-xxx.yml file
|
||||
echo "create language specific mkdocs configurations for ${langsite}"
|
||||
new_mkdocs_file="${new_docs_dir}_klipper3d/mkdocs-lang-${langsite}.yml"
|
||||
cp "${MKDOCS_MAIN}" "${new_mkdocs_file}"
|
||||
|
||||
echo "replace search language"
|
||||
sed -i "s%^ lang: en$% lang: ${langsearch}%" "${new_mkdocs_file}"
|
||||
|
||||
echo "replace site language"
|
||||
sed -i "s%^ language: en$% language: ${langsite}%" "${new_mkdocs_file}"
|
||||
|
||||
echo "replace toc"
|
||||
sed -i "s%Klipper documentation$%${title}%" "${new_mkdocs_file}"
|
||||
sed -i "s%Installation and Configuration:$%${installation_and_configuration}:%" "${new_mkdocs_file}"
|
||||
sed -i "s%Configuration Reference:$%${configuration_reference}:%" "${new_mkdocs_file}"
|
||||
sed -i "s%Bed Level:$%${bed_level}:%" "${new_mkdocs_file}"
|
||||
sed -i "s%Resonance Compensation:$%${resonance_compensation}:%" "${new_mkdocs_file}"
|
||||
sed -i "s%Command templates:$%${command_template}:%" "${new_mkdocs_file}"
|
||||
sed -i "s%Developer Documentation:$%${developer_documentation}:%" "${new_mkdocs_file}"
|
||||
sed -i "s%Device Specific Documents:$%${device_specific_documents}:%" "${new_mkdocs_file}"
|
||||
|
||||
# Build site
|
||||
echo "building site for ${langsite}"
|
||||
mkdir -p "${PWD}/site/${langsite}/"
|
||||
ln -sf "${PWD}/site/${langsite}/" "${WORK_DIR}lang/${langsite}/site"
|
||||
mkdocs build -f "${new_mkdocs_file}"
|
||||
done < <(egrep -v '^ *(#|$)' ${TRANS_FILE})
|
||||
16
docs/_klipper3d/css/extra.css
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Customization of mkdocs generated site */
|
||||
[data-md-color-scheme="slate"] {
|
||||
--md-primary-fg-color: hsla(var(--md-hue),15%,12%,1);
|
||||
--md-default-bg-color: hsla(var(--md-hue),17%,17%,1);
|
||||
--md-typeset-a-color: steelblue;
|
||||
--md-accent-fg-color: lightblue;
|
||||
}
|
||||
|
||||
img {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.center-image {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
10
docs/_klipper3d/mkdocs-requirements.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# Python virtualenv module requirements for mkdocs
|
||||
jinja2==3.0.3
|
||||
mkdocs==1.2.3
|
||||
mkdocs-material==8.1.3
|
||||
mkdocs-simple-hooks==0.1.3
|
||||
mkdocs-exclude==1.0.2
|
||||
mdx-truly-sane-lists==1.2
|
||||
mdx-breakless-lists==1.0.1
|
||||
py-gfm==1.0.2
|
||||
markdown==3.3.7
|
||||
138
docs/_klipper3d/mkdocs.yml
Normal file
@@ -0,0 +1,138 @@
|
||||
# Main configuration file for mkdocs generation of klipper3d.org website
|
||||
|
||||
# Note that the build-translations.sh script expects a certain file
|
||||
# layout. See that script and the README file for more details.
|
||||
|
||||
# Site and directory configuration
|
||||
site_name: Klipper documentation
|
||||
repo_url: https://github.com/Klipper3d/klipper
|
||||
repo_name: Klipper3d/klipper
|
||||
edit_uri: blob/master/docs/
|
||||
use_directory_urls: False
|
||||
docs_dir: '../'
|
||||
site_dir: '../../site/'
|
||||
|
||||
# Custom markdown dialect settings
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
permalink: True
|
||||
toc_depth: 6
|
||||
- attr_list
|
||||
- mdx_partial_gfm
|
||||
- mdx_truly_sane_lists
|
||||
- mdx_breakless_lists
|
||||
plugins:
|
||||
search:
|
||||
lang: en
|
||||
mkdocs-simple-hooks:
|
||||
hooks:
|
||||
on_page_markdown: "docs._klipper3d.mkdocs_hooks:transform"
|
||||
exclude:
|
||||
glob: "README.md"
|
||||
|
||||
# Website layout configuration (using mkdocs-material theme)
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: default
|
||||
primary: white
|
||||
accent: blue
|
||||
toggle:
|
||||
icon: material/lightbulb
|
||||
name: Switch to dark mode
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: slate
|
||||
primary: grey
|
||||
accent: light blue
|
||||
toggle:
|
||||
icon: material/lightbulb-outline
|
||||
name: Switch to light mode
|
||||
logo: img/klipper.svg
|
||||
favicon: img/favicon.ico
|
||||
icon:
|
||||
repo: fontawesome/brands/github
|
||||
alternate: material/web
|
||||
features:
|
||||
#- navigation.tabs
|
||||
#- navigation.expand
|
||||
- navigation.top
|
||||
# if enabled, the TOC doesn't work for some pages
|
||||
# - toc.integrate
|
||||
- search.suggest
|
||||
- search.highlight
|
||||
- search.share
|
||||
language: en
|
||||
extra_css:
|
||||
- _klipper3d/css/extra.css
|
||||
|
||||
# Site usage statistics
|
||||
extra:
|
||||
# https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-analytics/#site-search-tracking
|
||||
analytics:
|
||||
provider: google
|
||||
property: UA-138371409-1
|
||||
# Language Selection
|
||||
alternate:
|
||||
- name: English
|
||||
link: /
|
||||
lang: en
|
||||
# Alternate language links automatically added here
|
||||
|
||||
# Navigation hierarchy (this should mimic the layout of Overview.md)
|
||||
nav:
|
||||
- Overview.md
|
||||
- Features.md
|
||||
- FAQ.md
|
||||
- Releases.md
|
||||
- Config_Changes.md
|
||||
- Contact.md
|
||||
- Installation and Configuration:
|
||||
- Installation.md
|
||||
- Configuration Reference:
|
||||
- Config_Reference.md
|
||||
- Rotation_Distance.md
|
||||
- Config_checks.md
|
||||
- Bed Level:
|
||||
- Bed_Level.md
|
||||
- Delta_Calibrate.md
|
||||
- Probe_Calibrate.md
|
||||
- BLTouch.md
|
||||
- Manual_Level.md
|
||||
- Bed_Mesh.md
|
||||
- Endstop_Phase.md
|
||||
- Resonance Compensation:
|
||||
- Resonance_Compensation.md
|
||||
- Measuring_Resonances.md
|
||||
- Pressure_Advance.md
|
||||
- G-Codes.md
|
||||
- Command templates:
|
||||
- Command_Templates.md
|
||||
- Status_Reference.md
|
||||
- TMC_Drivers.md
|
||||
- Multi_MCU_Homing.md
|
||||
- Slicers.md
|
||||
- Skew_Correction.md
|
||||
- Exclude_Object.md
|
||||
- Using_PWM_Tools.md
|
||||
- Developer Documentation:
|
||||
- Code_Overview.md
|
||||
- Kinematics.md
|
||||
- Protocol.md
|
||||
- API_Server.md
|
||||
- MCU_Commands.md
|
||||
- CANBUS_protocol.md
|
||||
- Debugging.md
|
||||
- Benchmarks.md
|
||||
- CONTRIBUTING.md
|
||||
- Packaging.md
|
||||
- Device Specific Documents:
|
||||
- Example_Configs.md
|
||||
- SDCard_Updates.md
|
||||
- RPi_microcontroller.md
|
||||
- Beaglebone.md
|
||||
- Bootloaders.md
|
||||
- CANBUS.md
|
||||
- TSL1401CL_Filament_Width_Sensor.md
|
||||
- Hall_Filament_Width_Sensor.md
|
||||
- Sponsors.md
|
||||
42
docs/_klipper3d/mkdocs_hooks.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# Tool to customize conversion of markdown files during mkdocs site generation
|
||||
import re
|
||||
import logging
|
||||
|
||||
# This script translates some github specific markdown formatting to
|
||||
# improve rendering with mkdocs. The goal is for pages to render
|
||||
# similarly on both github and the web site. It has three main tasks:
|
||||
# 1. Convert links outside of the docs directory (any reference
|
||||
# starting with "../") to an absolute link to the raw file on
|
||||
# github.
|
||||
# 2. Convert a trailing backslash on a text line to a "<br>".
|
||||
# 3. Remove leading spaces from top-level lists so that those lists
|
||||
# are rendered correctly.
|
||||
|
||||
logger = logging.getLogger('mkdocs.mkdocs_hooks.transform')
|
||||
|
||||
def transform(markdown: str, page, config, files):
|
||||
in_code_block = 0
|
||||
in_list = False
|
||||
lines = markdown.splitlines()
|
||||
for i in range(len(lines)):
|
||||
line_out = lines[i]
|
||||
in_code_block = (in_code_block +
|
||||
len(re.findall("\s*[`]{3,}", line_out))) % 2
|
||||
if not in_code_block:
|
||||
line_out = line_out.replace('](../',
|
||||
f"]({config['repo_url']}blob/master/")
|
||||
line_out = re.sub("\\\s*$", "<br>", line_out)
|
||||
# check that lists at level 0 are not indented
|
||||
# (no space before *|-|1.)
|
||||
if re.match(r"^[^-*0-9 ]", line_out):
|
||||
in_list = False
|
||||
elif re.match(r"^(\*|-|\d+\.) ", line_out):
|
||||
in_list = True
|
||||
if not in_list:
|
||||
line_out = re.sub(r"^\s+(\*|-|\d+\.) ", r"\1 ", line_out)
|
||||
if line_out != lines[i]:
|
||||
logger.debug((f'[mkdocs_hooks] rewrite line {i+1}: '
|
||||
f'"{lines[i]}" -> "{line_out}"'))
|
||||
lines[i] = line_out
|
||||
output = "\n".join(lines)
|
||||
return output
|
||||
37
docs/developer-certificate-of-origin
Normal file
@@ -0,0 +1,37 @@
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
1 Letterman Drive
|
||||
Suite D4700
|
||||
San Francisco, CA, 94129
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
BIN
docs/img/adxl345-fritzing.png
Normal file
|
After Width: | Height: | Size: 207 KiB |
BIN
docs/img/adxl345-mount.jpg
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
docs/img/attach-issue.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
202
docs/img/bed_screws.svg
Normal file
@@ -0,0 +1,202 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="bed_screws.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/bed_screws.svg.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.0149341"
|
||||
inkscape:cx="209.05542"
|
||||
inkscape:cy="598.47875"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1030"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:0.96456695;stroke:#ffffff;stroke-width:0.39099997;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect928"
|
||||
width="74.716049"
|
||||
height="98.089432"
|
||||
x="70.776711"
|
||||
y="87.033455"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96" />
|
||||
<rect
|
||||
style="opacity:1;fill:#c8c8c8;fill-opacity:1;stroke:#030000;stroke-width:0.39099997;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect815"
|
||||
width="65.011902"
|
||||
height="88.446426"
|
||||
x="75.595238"
|
||||
y="91.380951"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96" />
|
||||
<rect
|
||||
style="opacity:1;fill:#00ff00;fill-opacity:0;stroke:#00ff00;stroke-width:0.39099997;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect844"
|
||||
width="0.22808908"
|
||||
height="92.832253"
|
||||
x="103.55245"
|
||||
y="89.324898" />
|
||||
<g
|
||||
id="g947"
|
||||
transform="translate(0,4.4645794)">
|
||||
<g
|
||||
transform="translate(8.8954742,-0.79831178)"
|
||||
id="g848">
|
||||
<ellipse
|
||||
style="opacity:1;fill:#fd0000;fill-opacity:0;stroke:#ff0000;stroke-width:0.39099997;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path817"
|
||||
cx="94.828026"
|
||||
cy="114.18661"
|
||||
rx="0.85533404"
|
||||
ry="0.79831177" />
|
||||
<ellipse
|
||||
style="opacity:1;fill:#000000;fill-opacity:0;stroke:#ff0000;stroke-width:0.391;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path817-3"
|
||||
cx="94.771011"
|
||||
cy="144.97864"
|
||||
rx="0.85533404"
|
||||
ry="0.79831183" />
|
||||
</g>
|
||||
<text
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
id="text858"
|
||||
y="112.47593"
|
||||
x="105.26311"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px"
|
||||
y="112.47593"
|
||||
x="105.26311"
|
||||
id="tspan856"
|
||||
sodipodi:role="line">A</tspan><tspan
|
||||
id="tspan860"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px"
|
||||
y="116.00371"
|
||||
x="105.26311"
|
||||
sodipodi:role="line" /></text>
|
||||
<text
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
id="text864"
|
||||
y="142.81177"
|
||||
x="105.14907"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px"
|
||||
y="142.81177"
|
||||
x="105.14907"
|
||||
id="tspan862"
|
||||
sodipodi:role="line">B</tspan></text>
|
||||
<g
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
transform="translate(-42.652658,1.5966236)"
|
||||
id="g876">
|
||||
<ellipse
|
||||
style="opacity:1;fill:#000000;fill-opacity:0;stroke:#ff0000;stroke-width:0.391;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path817-6"
|
||||
cx="125.56304"
|
||||
cy="127.41576"
|
||||
rx="0.85533404"
|
||||
ry="0.79831183" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="126.93158"
|
||||
y="126.5034"
|
||||
id="text868"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan866"
|
||||
x="126.93158"
|
||||
y="126.5034"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px">C</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="126.93158"
|
||||
y="130.03117"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px"
|
||||
id="tspan870" /></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g952"
|
||||
transform="translate(-0.26262232,4.2019571)">
|
||||
<path
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:transform-center-y="-0.024320163"
|
||||
inkscape:transform-center-x="-0.059466795"
|
||||
d="m 138.45007,129.24048 -0.43835,-0.37484 -0.55729,0.14861 0.22103,-0.53273 -0.31355,-0.4841 0.57496,0.0456 0.36351,-0.44779 0.13432,0.56091 0.53821,0.20734 -0.49196,0.30107 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:arg2="1.7942231"
|
||||
sodipodi:arg1="1.1659045"
|
||||
sodipodi:r2="0.43426865"
|
||||
sodipodi:r1="0.86853731"
|
||||
sodipodi:cy="128.44217"
|
||||
sodipodi:cx="138.10794"
|
||||
sodipodi:sides="5"
|
||||
id="path878"
|
||||
style="opacity:1;fill:#00ff00;fill-opacity:0;stroke:#0000ff;stroke-width:0.39099997;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
sodipodi:type="star" />
|
||||
<text
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:export-xdpi="96"
|
||||
id="text882"
|
||||
y="126.33394"
|
||||
x="137.52043"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px"
|
||||
y="126.33394"
|
||||
x="137.52043"
|
||||
id="tspan880"
|
||||
sodipodi:role="line">D</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/img/bed_screws.svg.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
3
docs/img/bedmesh_faulty_regions.svg
Normal file
|
After Width: | Height: | Size: 33 KiB |
4
docs/img/bedmesh_interpolated.svg
Normal file
|
After Width: | Height: | Size: 38 KiB |
4
docs/img/bedmesh_rect_basic.svg
Normal file
|
After Width: | Height: | Size: 23 KiB |
4
docs/img/bedmesh_round_basic.svg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/img/calibrate-x-max-smoothing.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
docs/img/calibrate-x.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
docs/img/calibrate-y.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
docs/img/corner-blob.jpg
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
docs/img/corner-dimple.jpg
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
docs/img/corner-good.jpg
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
187
docs/img/corner.svg
Normal file
@@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="54.904114mm"
|
||||
height="6.0860338mm"
|
||||
viewBox="0 0 194.54213 21.564687"
|
||||
id="svg3506"
|
||||
version="1.1"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
sodipodi:docname="corner.svg"
|
||||
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/corner.svg.png"
|
||||
inkscape:export-xdpi="89.734001"
|
||||
inkscape:export-ydpi="89.734001"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs3508">
|
||||
<marker
|
||||
inkscape:stockid="DiamondL"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DiamondL"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4399"
|
||||
d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="scale(0.8,0.8)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow2Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4341"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker4596"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4598"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4329"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-1"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4329-1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.49"
|
||||
inkscape:cx="94.97992"
|
||||
inkscape:cy="0"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
showborder="false"
|
||||
inkscape:window-width="1068"
|
||||
inkscape:window-height="487"
|
||||
inkscape:window-x="378"
|
||||
inkscape:window-y="113"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:pagecheckerboard="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6021"
|
||||
spacingx="9.9999997"
|
||||
spacingy="10.000001"
|
||||
originx="0.89299989"
|
||||
originy="-30.954583" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata3511">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-253.40821,-436.43703)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
|
||||
d="m 345.38554,440.31401 96.88541,12.96764"
|
||||
id="path3514"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend-1)"
|
||||
d="m 253.63788,454.62572 89.78715,-13.91164"
|
||||
id="path3514-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="189.09824"
|
||||
y="482.48389"
|
||||
id="text12656-9"
|
||||
transform="rotate(-9.0348846)"
|
||||
inkscape:transform-center-x="1.3563414"
|
||||
inkscape:transform-center-y="-5.7099754"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5552"
|
||||
x="189.09824"
|
||||
y="482.48389"
|
||||
style="font-size:11.25px;line-height:1.25">move 1</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="427.95532"
|
||||
y="379.5321"
|
||||
id="text12656-9-8"
|
||||
transform="rotate(8.3123803)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5554"
|
||||
x="427.95532"
|
||||
y="379.5321"
|
||||
style="font-size:11.25px;line-height:1.25">move 2</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
BIN
docs/img/corner.svg.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
docs/img/delta-a-distance.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/delta-a-pillar.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
docs/img/delta-outer-distance.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/delta-outer-pillar.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/delta_cal_e_step1.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/delta_cal_e_step2.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/delta_cal_e_step3.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
docs/img/delta_cal_e_step4.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/img/favicon.ico
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
docs/img/klipper-logo-small.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
docs/img/klipper-logo.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
113
docs/img/klipper.svg
Normal file
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100%"
|
||||
height="100%"
|
||||
viewBox="0 0 768 624"
|
||||
version="1.1"
|
||||
xml:space="preserve"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"
|
||||
id="svg40"
|
||||
sodipodi:docname="klipper.svg"
|
||||
inkscape:version="0.92.4 (unknown)"
|
||||
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/logs/logo-20190416/klipper6.svg.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"><metadata
|
||||
id="metadata46"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs44">
|
||||
</defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1030"
|
||||
id="namedview42"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.95"
|
||||
inkscape:cx="327.89418"
|
||||
inkscape:cy="289.76441"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg40"
|
||||
showguides="false"
|
||||
showborder="false"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid905" /></sodipodi:namedview>
|
||||
<path
|
||||
style="fill:#3c4b5a"
|
||||
d="m 30,34 v 140 l 260,255 115,-5 h 80 L 730,174 V 34 H 720 L 385,374 40,34 Z"
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" /><path
|
||||
style="fill:#3c4b5a;stroke-width:1.03280997"
|
||||
d="m 140,418 -58,57 1,25 v 19 l 57,57 h 27 v -1 L 91,496.5 167,419 v -1 z"
|
||||
id="path8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" /><g
|
||||
transform="translate(-1.08348e-4,0.048)"
|
||||
id="g17">
|
||||
<path
|
||||
d="m 83.041215,464.92108 h 0.001 l -0.04211,27.03092 h 11 l 73.000005,-74 v 14.301 l -63,64.199 63,65.5 v 14 l -73.000002,-75 h -13 c -2,0 -4,-2 -4,-4 h -2 v -33 h 2 c 0,-1 1,-2 3.00004,-2 1.99996,0 2.99996,1 2.99996,2 z"
|
||||
style="fill:#b12f35"
|
||||
id="path15"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccccccc" />
|
||||
</g><g
|
||||
id="path839"
|
||||
transform="matrix(1.03281,0,0,1.0326797,24.31099,-21.921569)">
|
||||
<rect
|
||||
x="21"
|
||||
y="426"
|
||||
width="30.015202"
|
||||
height="153"
|
||||
style="fill:#3c4b5a;fill-rule:nonzero"
|
||||
id="rect12" />
|
||||
</g><rect
|
||||
x="247"
|
||||
y="469"
|
||||
width="24"
|
||||
height="107"
|
||||
style="fill:#3c4b5a;stroke-width:1.19609642"
|
||||
id="rect23" /><path
|
||||
d="m 371.98888,521.45953 c 0,-10.8903 -2.45322,-19.36013 -7.36207,-25.4107 -4.90765,-6.05057 -12.80741,-9.07465 -23.69929,-9.07465 -2.28639,0 -4.6724,0.10081 -7.16044,0.30241 -2.48802,0.20161 -4.94125,0.63842 -7.36207,1.31044 v 60.29926 c 2.15197,1.47844 5.00967,2.85727 8.57188,4.13411 3.56342,1.27684 7.36208,1.91526 11.39597,1.91526 8.87554,0 15.36385,-3.02409 19.46496,-9.07465 4.10111,-6.05057 6.15106,-14.18439 6.15106,-24.40148 z M 397,521.05632 c 0,8.06663 -1.04178,15.46123 -3.12654,22.18261 -2.08476,6.72259 -5.07568,12.50434 -8.97515,17.34409 -3.89947,4.83973 -8.77472,8.60423 -14.62333,11.29351 -5.8498,2.68927 -12.47254,4.0333 -19.86702,4.0333 -4.97606,0 -9.54765,-0.60481 -13.71597,-1.81445 -4.16832,-1.21082 -7.59731,-2.55487 -10.28698,-4.03451 V 611 H 302 V 471.64736 c 4.97486,-1.34524 11.09352,-2.62207 18.35477,-3.83171 C 327.61602,466.60482 335.28055,466 343.34834,466 c 8.33664,0 15.79953,1.27684 22.38866,3.83171 6.58794,2.55487 12.20251,6.21857 16.84131,10.9911 4.6388,4.77253 8.20221,10.5543 10.69024,17.34408 2.48684,6.78859 3.73145,14.4184 3.73145,22.88943 z"
|
||||
style="fill:#3c4b5a;fill-rule:nonzero;stroke-width:1.20011997"
|
||||
id="path25"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 492.9892,521.45953 c 0,-10.8903 -2.4544,-19.36013 -7.36198,-25.4107 -4.90759,-6.05057 -12.80725,-9.07465 -23.699,-9.07465 -2.28636,0 -4.67354,0.10081 -7.16034,0.30241 -2.488,0.20161 -4.94119,0.63842 -7.36197,1.31044 v 60.29926 c 2.15074,1.47844 5.00839,2.85727 8.57176,4.13411 3.56337,1.27684 7.36198,1.91526 11.39582,1.91526 8.87423,0 15.36246,-3.02409 19.46352,-9.07465 4.10106,-6.05057 6.15219,-14.18439 6.15219,-24.40148 z M 518,521.05632 c 0,8.06663 -1.04297,15.46123 -3.1265,22.18261 -2.08474,6.72259 -5.07681,12.50434 -8.97624,17.34409 -3.89942,4.83973 -8.77341,8.60423 -14.62314,11.29351 -5.84854,2.68927 -12.47119,4.0333 -19.86677,4.0333 -4.9748,0 -9.54633,-0.60481 -13.7146,-1.81445 -4.16827,-1.21082 -7.59722,-2.55487 -10.28684,-4.03451 V 611 H 423 V 471.64736 c 4.97599,-1.34524 11.09337,-2.62207 18.35454,-3.83171 C 448.61569,466.60482 456.28012,466 464.34782,466 c 8.33773,0 15.80052,1.27684 22.38838,3.83171 6.58905,2.55487 12.20235,6.21857 16.84229,10.9911 4.63875,4.77253 8.20211,10.5543 10.69012,17.34408 2.48679,6.78859 3.73139,14.4184 3.73139,22.88943 z"
|
||||
style="fill:#3c4b5a;fill-rule:nonzero;stroke-width:1.20011246"
|
||||
id="path27"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 537,521.00591 c 0,-9.30123 1.37492,-17.45591 4.12595,-24.46521 2.74984,-7.00931 6.40632,-12.83838 10.96942,-17.48839 4.56191,-4.65121 9.79451,-8.15587 15.699,-10.51396 5.90328,-2.3593 11.94191,-3.53835 18.11469,-3.53835 14.49054,0 25.79531,4.51527 33.91308,13.5458 8.11897,9.03174 12.17786,22.51016 12.17786,40.43768 0,1.34749 -0.0335,2.8646 -0.1006,4.54896 -0.0671,1.68555 -0.16768,3.20147 -0.30182,4.55015 h -69.43942 c 0.67068,8.49155 3.65646,15.06171 8.95733,19.71294 5.29967,4.65001 12.98149,6.97562 23.04547,6.97562 5.9033,0 11.30477,-0.5402 16.20202,-1.61818 4.89726,-1.07799 8.75493,-2.22335 11.57304,-3.43729 l 3.22052,20.01612 c -1.34138,0.67495 -3.18699,1.38237 -5.53561,2.12349 -2.34742,0.74112 -5.03139,1.41485 -8.05071,2.02242 -3.01811,0.60637 -6.27217,1.11168 -9.76096,1.51592 -3.4888,0.40425 -7.04467,0.60637 -10.66761,0.60637 -9.25915,0 -17.30985,-1.38116 -24.15211,-4.14471 -6.84346,-2.76354 -12.47968,-6.60507 -16.90744,-11.52457 -4.42778,-4.91951 -7.71537,-10.7161 -9.86278,-17.38854 C 538.0731,536.27095 537,528.95845 537,521.00591 Z m 70.64548,-10.91821 c 0,-3.36991 -0.46948,-6.57138 -1.40846,-9.60442 -0.93897,-3.03303 -2.31508,-5.66063 -4.12595,-7.88517 -1.81207,-2.22335 -4.02535,-3.97627 -6.64226,-5.25638 -2.61689,-1.28131 -5.73561,-1.92137 -9.35855,-1.92137 -3.75708,0 -7.04466,0.70743 -9.86278,2.1235 -2.8181,1.41484 -5.19906,3.26883 -7.14527,5.55956 -1.94501,2.29192 -3.45526,4.92071 -4.52837,7.88516 -1.0731,2.96567 -1.81206,5.99871 -2.21447,9.09912 z"
|
||||
style="fill:#3c4b5a;fill-rule:nonzero;stroke-width:1.20038378"
|
||||
id="path29"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 717.7869,492.26931 c -2.00567,-0.67394 -4.78138,-1.38159 -8.32593,-2.12292 -3.54453,-0.74135 -7.65736,-1.11202 -12.33845,-1.11202 -2.67542,0 -5.51799,0.26957 -8.52649,0.80874 -3.0097,0.53915 -5.11684,1.01091 -6.32025,1.41528 V 576 H 658 V 475.28104 c 4.68109,-1.75347 10.53216,-3.40464 17.55439,-4.95472 C 682.57663,468.77504 690.36771,468 698.92762,468 c 1.60574,0 3.47769,0.10109 5.61827,0.30328 2.13938,0.20218 4.27996,0.47176 6.42053,0.80873 2.13939,0.33697 4.2131,0.74255 6.21878,1.21431 2.00687,0.47176 3.6114,0.90983 4.8148,1.3142 z"
|
||||
style="fill:#3c4b5a;fill-rule:nonzero;stroke-width:1.19865453"
|
||||
id="path31"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
sodipodi:nodetypes="cccccccccccccc"
|
||||
d="M 259,424 H 360 V 359 L 30,34 H 90 L 385,324 670,34 h 60 L 410,359 v 84.99783 C 410,449 405,454 400,454 H 259 c -12,0 -14,-10 -14,-15 0,-5 2,-15 14,-15 z"
|
||||
style="fill:#b12f35"
|
||||
id="path35"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
id="rect12-6"
|
||||
style="clip-rule:evenodd;fill:#3c4b5a;fill-rule:nonzero;stroke-width:1.03280997;stroke-linejoin:round;stroke-miterlimit:1.41420996"
|
||||
height="158"
|
||||
width="24"
|
||||
y="418"
|
||||
x="191" /></svg>
|
||||
|
After Width: | Height: | Size: 8.0 KiB |
208
docs/img/lookahead-slow.svg
Normal file
@@ -0,0 +1,208 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="97.22496mm"
|
||||
height="32.550285mm"
|
||||
viewBox="0 0 344.49789 115.33566"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
sodipodi:docname="lookahead-slow.svg"
|
||||
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/lookahead-slow.svg.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend-1"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4329-1"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Mend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Mend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4329"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.4,0,0,-0.4,-4,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.15"
|
||||
inkscape:cx="3.4782609"
|
||||
inkscape:cy="101.30435"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1091"
|
||||
inkscape:window-height="588"
|
||||
inkscape:window-x="149"
|
||||
inkscape:window-y="422"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
showborder="false"
|
||||
inkscape:snap-global="false"
|
||||
showguides="false"
|
||||
inkscape:pagecheckerboard="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3436" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-135.22429,-249.96955)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150,250.23455 1.06383,102.12765 327.12765,-0.53192 -7.97871,5.85107"
|
||||
id="path3347"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="434.04257"
|
||||
y="365.1282"
|
||||
id="text3349"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3351"
|
||||
x="434.04257"
|
||||
y="365.1282"
|
||||
style="font-size:12.5px;line-height:1">time</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-313.86618"
|
||||
y="140.27856"
|
||||
id="text3353"
|
||||
transform="rotate(-90.917558)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3355"
|
||||
x="-313.86618"
|
||||
y="140.27856"
|
||||
style="font-size:12.5px;line-height:1.25">velocity</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150,250.23455 -5.31915,8.51063"
|
||||
id="path3359"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.62366331px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 179.63013,351.45141 16.05677,-60.94328 43.25999,0 16.53759,47.11348"
|
||||
id="path3361"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.7558428px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 254.72406,337.27551 22.65101,-77.77178 43.89917,0 24.69858,91.73948"
|
||||
id="path3361-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="195.45749"
|
||||
y="286.52051"
|
||||
id="text12656-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan7078"
|
||||
x="195.45749"
|
||||
y="286.52051"
|
||||
style="font-size:11.25px;line-height:1.25">move A</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="280.5639"
|
||||
y="254.60564"
|
||||
id="text12656-9-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan7080"
|
||||
x="280.5639"
|
||||
y="254.60564"
|
||||
style="font-size:11.25px;line-height:1.25">move B</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
|
||||
d="m 74.333855,283.02668 -147.83244,52.19984"
|
||||
id="path3514"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend-1)"
|
||||
d="m -79.633985,251.6122 154.13499,31.81455"
|
||||
id="path3514-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="36.7374"
|
||||
y="252.31848"
|
||||
id="text12656-9-1"
|
||||
transform="rotate(14.638795)"
|
||||
inkscape:transform-center-x="-0.91382951"
|
||||
inkscape:transform-center-y="-4.9145266"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan7074"
|
||||
x="36.7374"
|
||||
y="252.31848"
|
||||
style="font-size:11.25px;line-height:1.25">move A</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-126.26086"
|
||||
y="304.35226"
|
||||
id="text12656-9-8"
|
||||
transform="rotate(-20.215565)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan7076"
|
||||
x="-126.26086"
|
||||
y="304.35226"
|
||||
style="font-size:11.25px;line-height:1.25">move B</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.1 KiB |
BIN
docs/img/lookahead-slow.svg.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
139
docs/img/lookahead.svg
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="97.22496mm"
|
||||
height="32.550285mm"
|
||||
viewBox="0 0 344.49789 115.33566"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
sodipodi:docname="lookahead.svg"
|
||||
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/lookahead.svg.png"
|
||||
inkscape:export-xdpi="89.734001"
|
||||
inkscape:export-ydpi="89.734001"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.94"
|
||||
inkscape:cx="117.02128"
|
||||
inkscape:cy="46.276596"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1091"
|
||||
inkscape:window-height="588"
|
||||
inkscape:window-x="149"
|
||||
inkscape:window-y="422"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
showborder="false"
|
||||
inkscape:snap-global="false"
|
||||
showguides="false"
|
||||
inkscape:pagecheckerboard="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3436" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-135.22429,-249.96955)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150,250.23455 1.06383,102.12765 327.12765,-0.53192 -7.97871,5.85107"
|
||||
id="path3347"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="434.04257"
|
||||
y="365.1282"
|
||||
id="text3349"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3351"
|
||||
x="434.04257"
|
||||
y="365.1282"
|
||||
style="font-size:12.5px;line-height:1">time</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-313.86618"
|
||||
y="140.27856"
|
||||
id="text3353"
|
||||
transform="rotate(-90.917558)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3355"
|
||||
x="-313.86618"
|
||||
y="140.27856"
|
||||
style="font-size:12.5px;line-height:1.25">velocity</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150,250.23455 -5.31915,8.51063"
|
||||
id="path3359"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.62366331px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 179.63013,351.45141 16.05677,-60.94328 61.3451,0 4.83546,8.81561"
|
||||
id="path3361"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.7558428px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 261.70791,300.17937 13.5395,-40.67564 59.85662,0 24.69858,91.73948"
|
||||
id="path3361-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="200.77664"
|
||||
y="286.52051"
|
||||
id="text12656-9"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5532"
|
||||
x="200.77664"
|
||||
y="286.52051"
|
||||
style="font-size:11.25px;line-height:1.25">move 1</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="280.5639"
|
||||
y="255.66946"
|
||||
id="text12656-9-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan5534"
|
||||
x="280.5639"
|
||||
y="255.66946"
|
||||
style="font-size:11.25px;line-height:1.25">move 2</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.9 KiB |
BIN
docs/img/lookahead.svg.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
docs/img/octoprint-temperature.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
209
docs/img/ooze.svg
Normal file
@@ -0,0 +1,209 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="98.140816mm"
|
||||
height="63.537022mm"
|
||||
viewBox="0 0 347.74305 225.13119"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
sodipodi:docname="ooze.svg"
|
||||
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/ooze.svg.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.94"
|
||||
inkscape:cx="198.93617"
|
||||
inkscape:cy="59.042553"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1091"
|
||||
inkscape:window-height="588"
|
||||
inkscape:window-x="266"
|
||||
inkscape:window-y="106"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
showborder="false"
|
||||
inkscape:snap-global="false"
|
||||
showguides="false"
|
||||
inkscape:pagecheckerboard="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3436"
|
||||
originx="-1.5695746e-05"
|
||||
originy="109.79552" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-135.22431,-249.96955)">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150,250.23455 1.06383,102.12765 327.12765,-0.53192 -7.97871,5.85107"
|
||||
id="path3347"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-346.84067"
|
||||
y="139.75046"
|
||||
id="text3353"
|
||||
transform="rotate(-90.917558)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan12733"
|
||||
x="-346.84067"
|
||||
y="139.75046"
|
||||
style="font-size:12.5px;line-height:1.25">head velocity</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150,250.23455 -5.31915,8.51063"
|
||||
id="path3359"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 179.63013,351.45141 16.05677,-60.94328 120.91957,-1.06383 16.53759,62.00711"
|
||||
id="path3361"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.78742969px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 332.99641,351.24986 16.72764,-63.00287 133.24331,0"
|
||||
id="path3361-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="200.11789"
|
||||
y="284.45413"
|
||||
id="text12656"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan12658"
|
||||
x="200.11789"
|
||||
y="284.45413"
|
||||
style="font-size:11.25px;line-height:1.25">extrude move</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="356.50089"
|
||||
y="283.39032"
|
||||
id="text12660"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan12662"
|
||||
x="356.50089"
|
||||
y="283.39032"
|
||||
style="font-size:11.25px;line-height:1.25">non-extrude move</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 152.72419,471.73218 1.06383,102.12766 327.12768,-0.53192 -7.97872,5.85107"
|
||||
id="path3347-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="436.76678"
|
||||
y="586.62585"
|
||||
id="text3349-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3351-4"
|
||||
x="436.76678"
|
||||
y="586.62585"
|
||||
style="font-size:12.5px;line-height:1">time</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-551.11292"
|
||||
y="125.37186"
|
||||
id="text3353-0"
|
||||
transform="rotate(-90.917558)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4197"
|
||||
x="-551.11292"
|
||||
y="125.37186"
|
||||
style="font-size:12.5px;line-height:1.25">actual</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4199"
|
||||
x="-551.11292"
|
||||
y="140.99686"
|
||||
style="font-size:12.5px;line-height:1.25">filament</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 152.72419,471.73218 -5.31915,8.51063"
|
||||
id="path3359-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 182.35432,572.94905 c 17.46262,-43.80215 52.67413,-56.54375 92.65253,-60.94329 l 48.57915,-1.06383 c 24.916,55.4715 110.00504,59.23318 151.64398,62.00712"
|
||||
id="path3361-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150.87843,360.66993 1.06383,102.12766 327.12768,-0.53192 -7.97872,5.85107"
|
||||
id="path3347-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-444.27307"
|
||||
y="124.17301"
|
||||
id="text3353-6"
|
||||
transform="rotate(-90.917558)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4193"
|
||||
x="-444.27307"
|
||||
y="124.17301"
|
||||
style="font-size:12.5px;line-height:1.25">desired</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4195"
|
||||
x="-444.27307"
|
||||
y="139.79802"
|
||||
style="font-size:12.5px;line-height:1.25">filament</tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 150.87843,360.66993 -5.31915,8.51063"
|
||||
id="path3359-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 180.50856,461.8868 16.05678,-60.94329 120.91958,-1.06383 16.53759,62.00712"
|
||||
id="path3361-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.7 KiB |
BIN
docs/img/ooze.svg.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/img/paper-test.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
docs/img/pressure-velocity.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/ringing-3dbenchy.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
docs/img/ringing-mark.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/img/ringing-measure.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
docs/img/ringing-test.jpg
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
docs/img/shaper-smoothing.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |