722 Commits

Author SHA1 Message Date
Kevin O'Connor
bee179eab4 docs: Update release notes for v0.6.0 release
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-31 14:04:39 -04:00
Kevin O'Connor
039bb9f10f docs: Add Patreon link to FAQ page
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-31 13:55:41 -04:00
Kevin O'Connor
b0b4bc8958 heater: Add some comments to the thermistor math
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-29 16:40:26 -04:00
Kevin O'Connor
a6553538e6 docs: Update G-Codes.md with recent output_pin changes
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-28 15:11:10 -04:00
Kevin O'Connor
019666a6f6 docs: Add a section on adding new host modules to Code_Overview.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-28 13:12:41 -04:00
Kevin O'Connor
7579b9671b stepstats: Add documentation clarification
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-23 10:51:11 -04:00
Kevin O'Connor
99f3c99238 display: Round temperature and position to nearest whole number
The "%d" formatting truncates a floating point number - use "%.0f" to
show a rounded number.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-19 15:17:53 -04:00
Kevin O'Connor
aba04bf3bd display: Remove unneeded semicolons from file
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-19 15:16:01 -04:00
Kevin O'Connor
f5c67baac2 docs: Recommend running PID_CALIBRATE in Config_checks.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-18 12:43:41 -04:00
Kevin O'Connor
973ef97143 pid_calibrate: Move PID calibration logic from heater.py to new file
Drop support for M303 and PID_TUNE, and replace it with a new
PID_CALIBRATE command.  Move the logic for this command from heater.py
to a new pid_calibrate.py file in the extras/ directory.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-18 12:02:30 -04:00
Kevin O'Connor
310cdf88cc config: Remove tabs from printer-wanhao-duplicator-i3-v2.1-2017.cfg
Remove tabs from example config file and replace with spaces.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-18 11:44:56 -04:00
Kevin O'Connor
5c05a24947 docs: Fix typo in M220 description in G-Codes.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-18 11:44:56 -04:00
Kevin O'Connor
c93dad8eba config: Update generic-cramps.cfg with P9_23 machine enable
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-18 10:33:40 -04:00
Kevin O'Connor
fb3065cfa7 config: Change pullup_resistor to 2000 in generic-cramps.cfg
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 14:18:49 -04:00
Kevin O'Connor
e3f9ff6701 probe: Add z_offset parameter
Move the probe_z_offset parameter from delta_calibrate and
bed_tilt_calibrate to a z_offset parameter within the probe config
section.  It's easier to understand the z offset setting when it is in
the probe config section.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 14:07:15 -04:00
Kevin O'Connor
c95cc3fb66 bed_tilt: Take into account the XY position used with z_virtual_endstop
If a z_virtual_endstop is in use, then record the last XY position
that is used when the Z is homed.  Use that XY position to report what
change is needed to the z position_endstop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 13:47:31 -04:00
Kevin O'Connor
1dda4628a0 bed_tilt: Require at least 3 probing points for bed_tilt_calibrate
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 13:47:31 -04:00
Kevin O'Connor
36612fd544 probe: Default z_position to the configured minimum position on Z axis
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 13:47:31 -04:00
Kevin O'Connor
ef8c464d97 output_pin: Move pwm and digital output pins to new module in extras/
Rename the digital_output, pwm_output, and static_pwm_output config
sections to output_pin and move to a new module in the extras/
directory.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 13:46:36 -04:00
Kevin O'Connor
66eefa1da8 static_digital_output: Add static_digital_output section to extras/
Move the code for the static_digital_output config section from
chipmisc.py to a new file in the extras/ directory.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 13:06:51 -04:00
Kevin O'Connor
e78377eebd replicape: Add config controls for the servo[01]_enable lines
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-17 12:55:48 -04:00
Kevin O'Connor
451f7d5672 gcode: Position returned by M114 should be relative to last G92
It looks like OctoPrint is expecting the result from M114 to be
relative to the last G92 command.  Also, introduce GET_POSITION to
report the actual location that the printer is at.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-15 20:00:51 -04:00
Kevin O'Connor
ef820d98f6 docs: Add "will heaters be turned off on a crash" item to FAQ
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-13 11:36:45 -04:00
Kevin O'Connor
9dfe612516 verify_heater: Provide additional information on a heater error
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 23:31:17 -04:00
Kevin O'Connor
830cfc5414 klippy: Rework starting error message
Commit 9bc4239e now emphasizes the first line of a multi-line error
message, so rework startup_message to conform to that.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 23:15:22 -04:00
Kevin O'Connor
45afa04578 probe: Add some hints for common errors during PROBE
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 23:00:50 -04:00
Kevin O'Connor
9bc4239e9c gcode: On a multi-line error message, report the first line twice
Report the first line of a multi-line error message twice - once as
part of the informational content, and once with the "!!" error
prefix.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 22:56:31 -04:00
Kevin O'Connor
3a1cdc7d70 virtual_sdcard: Fix typo in seek error handling
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 22:36:39 -04:00
Kevin O'Connor
3a75748762 config: Reword the min_temp/max_temp description in example.cfg
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 14:37:02 -04:00
Kevin O'Connor
e336c24665 heater: Allow min_temp to go below zero
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-12 14:36:45 -04:00
Kevin O'Connor
849f4ed25f verify_heater: Scale hysteresis duration check
If a heater falls out of the target range, accumulate the temperature
differences to determine if an error should be raised.  This should
make it less likely to report an error for heaters that drift slightly
out of range, and it should make error reporting faster for heaters
that rapidly fall out of range.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-11 19:21:32 -04:00
Kevin O'Connor
57d342b455 verify_heater: Change default hysteresis to 10 degrees
A default of 4 degrees and 10 seconds may be too aggressive - change
the default to 10 degrees and 15 seconds.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-11 13:29:28 -04:00
Kevin O'Connor
5208fc38ed verify_heater: Add initial support for verifying heaters and sensors
Add runtime checks to heaters and temperature sensors to check for
possible hardware faults.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-11 00:49:11 -05:00
Kevin O'Connor
b549c3927e klippy: Allow external callers of try_load_module()
It can be useful to automatically pull in a module in the extras/
directory.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-11 00:04:30 -05:00
Kevin O'Connor
e53a589ac3 docs: Add SET_DUAL_CARRIAGE command to G-Codes.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-10 20:22:13 -05:00
Kevin O'Connor
4d48c111d8 cartesian: Initial support for dual carriages
Add support for additional carriages on cartesian printers.  This is
used by some printers to handle multiple extruders.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-09 10:26:21 -05:00
Kevin O'Connor
6c1e1dcc8d display: Use separate hd44780 screen drawing
Separate out the hd44780 screen drawing from the st7920 code.  Use a
layout that takes advantage of the 20 columns.  Add custom hd44780
fonts.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-08 22:44:40 -05:00
Kevin O'Connor
ddcf9a7ff7 docs: Add Tx command to G-Codes.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-08 14:40:26 -05:00
Kevin O'Connor
05ec7ca7ff docs: Add a G-Codes.md file with the list of available commands
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-08 14:11:20 -05:00
ghandye
ef0c80af51 config: Add working printer configuration for Wanhao Duplicator i3 v2.1
Working printer configuration for a Wanhao Duplicator i3 v2.1 and its
clones, including Monoprice Maker Select and Cocoon Create. Includes a
working config for the st7920-based front panel LCD.

Signed-off-by: Andy Ellsworth <andy+github@dar.net>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-08 10:26:21 -05:00
christian mock
d997821e58 config: Add LCD configuration to printer-trony-x5s-2017.cfg
I've added the LCD configuration for the Tronxy X5S printer and its
Melzi board and 128x64 LCD. This is tested and works.

I've also added the pins for the encoder, but that is untested.

Signed-off-by: christian mock <cm@tahina.priv.at>
2018-03-07 15:56:07 -05:00
Kevin O'Connor
385e6b67d9 config: Add display section to creality cr10 config
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-07 13:40:33 -05:00
Marcio Teixeira
04602b2470 display: Choose arrow character based on display
Choose the arrow character based on whether the display is ST7920 or
HD44780.

Signed-off-by: Marcio Teixeira <marcio@alephobjects.com>
2018-03-06 14:01:10 -05:00
cruwaller
923954772f homing: allow to disable homing retract
Homing retract can be disabled by setting homing_retract_dist to 0.

Signed-off-by: Petri Honkala <cruwaller@gmail.com>
2018-03-06 13:45:48 -05:00
Kevin O'Connor
5a16863465 config: Fix hd44780 typo in rambo and ramps example configs
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-06 13:15:09 -05:00
Kevin O'Connor
08a5f8a5ff display: Add initial support for LCD screens attached to an MCU
Add support for displaying basic status information on ST7920 and
HD44780 based LCDs that are attached directly to a micro-controller.

Signed-off-by: Marcio Teixeira <marcio@alephobjects.com>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-06 11:30:46 -05:00
Kevin O'Connor
43ac56766e serialqueue: Support sending messages at a background priority
Support low-priority message transmits.  This may be useful for bulk
commands that should be delayed util the comms are otherwise idle.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-06 11:30:41 -05:00
Kevin O'Connor
afc9bcf27b lcd_hd44780: Add micro-controller code for the HD44780 LCD chip
Add support for passing messages to an HD44780 chip via a 4-bit
bit-banging interface.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-06 11:30:34 -05:00
Kevin O'Connor
9140f36d99 lcd_st7920: Add micro-controller code for the ST7920 LCD chip
Add support for passing messages to an ST7920 chip via a SPI
bit-banging interface.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-06 11:30:30 -05:00
Kevin O'Connor
fa07be9346 mathutil: Move coordinate_descent() to new file
Add a new python file (mathutil.py) and move the coordinate_descent()
code to it.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-04 09:56:50 -05:00
Kevin O'Connor
7290ed5f73 clocksync: Fix multi-mcu frequency adjustments with long moves
Commit 02ae2ab9 had a typo causing the new long move handling logic to
not take effect.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-03 21:54:25 -05:00
Kevin O'Connor
fc60bda4d1 virtual_sdcard: Remove trailing '*' checksum indicator from M23 command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-02 11:58:00 -05:00
Kevin O'Connor
82a65e9f4a docs: Note the use of the virtual_sdcard feature
Note that virtual_sdcard helps on slower machines.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-03-02 11:28:01 -05:00
Kevin O'Connor
b139a8561f serialhdl: Add a wrapper around the results of lookup_command()
Add a lookup_command() method to the SerialReader class that provides
a wrapper that stores the serial and commandqueue references.  This
makes it easier to run the send() method.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-27 21:06:16 -05:00
Kevin O'Connor
8518da9824 config: Move description of phase adjusted endstops to config-extra.cfg
Move the description of stepper phase adjusted endstops to a new
section in config-extra.cfg.  This keeps the main example config file
a little more concise.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-27 09:34:25 -05:00
Kevin O'Connor
656cb2c417 build: Use git describe --always
Add --always flag to "git describe" command to get a build identifier
even if one checks out the repo with a depth parameter that prunes out
the last tagged version.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-26 21:50:05 -05:00
Kevin O'Connor
239c1ad5c9 serialqueue: Don't clear must_exit flag at start of pollreactor_run()
Avoid a timing race where must_exit is set before pollreactor_run() is
started.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-26 16:21:10 -05:00
Kevin O'Connor
7733e1d832 test: Add travis_fold markers to build output
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-26 15:21:39 -05:00
Kevin O'Connor
99b4122901 test: Add compile tests for at90usb1286 and atmega1284p chips
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-26 15:03:05 -05:00
Kevin O'Connor
28d70eaf0c test: Update travis build to include a basic klippy host test
Move the travis installation steps from the travis-build.sh script to
a new script (scripts/travis-install.sh).  Move the travis-build.sh
script to the scripts/ directory as well.

The data dictionaries built in the compile tests are useful during
host software testing, so run all the compile tests sequentially in a
single VM and save the data dictionaries after each build.  Also,
build all the config files found in the test/configs/ directory.

Create the python virtualenv environment during the install phase and
invoke the klippy.py host software in the build phase to perform a
basic host software sanity check.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-26 14:58:49 -05:00
Kevin O'Connor
5d635c5252 config: Use .0025 as the default z step_distance in sample configs
Don't use tiny step distances on the Z as that could cause a surprise
to users that copy the config without updating all the settings.  (A Z
step distance that is too small would cause a high motor velocity.)  A
step distance of .0025 is very popular in practice, so change the
default example configs to use that.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-25 16:00:55 -05:00
Kevin O'Connor
22d7e48aa2 config: Add an example config file that uses multiple MCUs
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-25 12:59:09 -05:00
Sebastian Meyer
a6b0649cb1 test: Add travis CI
Signed-off-by: Sebastian Meyer <ich@sebmeyer.de>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-25 10:54:59 -05:00
Sebastian Meyer
58dd6d9106 build: Link objects ahead of libraries to avoid failures on some platforms
Signed-off-by: Sebastian Meyer <ich@sebmeyer.de>
2018-02-25 10:39:06 -05:00
Douglas Hammond
d139389267 avr: Add at90usb646 support
Signed-off-by: Douglas Hammond wizhippo@gmail.com
2018-02-25 10:23:00 -05:00
Kevin O'Connor
e99c0f53f8 graphstats: Support selecting an mcu to graph from the command-line
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-19 23:12:14 -05:00
Kevin O'Connor
02ae2ab984 clocksync: Rework multi-mcu adjust to better handle long moves
The multi-mcu clock syncing code relies on the ability to periodically
update the mcu clock adjustments.  If a series of very long moves are
submitted then it is possible the adjustments could become unstable.
For example, if an adjustment is made to reduce a clock error over the
next couple of seconds, but it is applied to a longer period because
the next move lasts many seconds, then this would result in a bigger
adjustment for the following move, which would result in an even
bigger error when that move lasts many seconds.  This can repeat until
the system destabilizes.

Check for cases where the print_time is far in the future of the
current estimated print time and average over a longer period in that
case.  That should reduce the possibility of the adjustment code
becoming unstable.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-19 22:13:28 -05:00
Kevin O'Connor
97f7735c6a graphstats: Set size on frequency graph
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-18 20:42:28 -05:00
Kevin O'Connor
69486e45c1 ad5206: Warn if ad5206 enable pin is inverted
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-17 23:18:10 -05:00
Kevin O'Connor
5e8aaed41f docs: Add tips for porting to new kinematics to Code_Overview.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-17 13:48:53 -05:00
Kevin O'Connor
c128a9dfd5 probe: Increase calibration log level from debug to info
Output more information by default from the bed_tilt and
delta_calibrate commands.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-16 13:30:49 -05:00
Kevin O'Connor
6dc623b35d config: Expand homing_override description in sample-bltouch.cfg
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-13 15:29:49 -05:00
Kevin O'Connor
8fc3487a8a config: Reword description of set_position_x paramter in homing_override
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-11 15:35:10 -05:00
Kevin O'Connor
82db072151 config: Add a config snippet for the BLTouch probe
Add an example to help users with a BLTouch probe.  This is based on
information from @mediumo and @riddlez666.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-11 15:11:11 -05:00
Kevin O'Connor
41f73d0c8c config: Add a "printer-" prefix to example printer config files
Add a prefix to the example printer config files so that a sorted
directory listing shows all the samples bundled together.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-11 14:58:48 -05:00
Kevin O'Connor
08a1183a01 virtual_sdcard: Initial support for virtual sdcard
Add support for directly printing from a local file on the host.  This
may be useful if the host cpu is not fast enough to run OctoPrint
well.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-11 14:13:12 -05:00
Kevin O'Connor
f77e1b67f6 gcode: Introduce request_restart() method
Use request_restart() method instead of prep_restart() and
motor_heater_off().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-11 14:11:33 -05:00
Kevin O'Connor
11c7c110a1 gcode: Extract special cases from process_data()
Handle the unlikely case of pending commands in a new method
process_pending().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-11 14:10:09 -05:00
Dave Bacon
5abea041b4 mcu: Fix PWM static start value setup
config_setup uses ._start_value instead of ._static_value which isn't defined.

Signed-off-by: Dave Bacon <drb.github@mrbacon.com>
2018-02-10 13:00:22 -05:00
Dave Bacon
268d1cb27c docs: Update Config_checks.md
Navigation should be to the temperature tab to find the Tool temperature box.

Signed-off-by: Dave Bacon <drb.github@mrbacon.com>
2018-02-07 22:24:32 -05:00
Kevin O'Connor
561c84dd93 pins: Warn on invalid pin format
Raise an error if a pin description isn't formatted correctly.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-07 16:09:25 -05:00
Kevin O'Connor
955d940b60 bed_tilt: Negate parameters reported by bed_tilt_calibrate
The bed_tilt_calibrate command determines the tilt of the bed.
However, we need to report the tilt compensation which is the negative
of the bed tilt.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-05 14:52:38 -05:00
Kevin O'Connor
6ea36de9f2 config: Add a pointer to example-extras.cfg at the end of example.cfg
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-05 14:34:05 -05:00
Kevin O'Connor
e0cedfb853 heater: Report stats whenever the heater is active
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-05 13:55:59 -05:00
Kevin O'Connor
0a5b07f9da klippy: Allow any stats producer to determine when stats are needed
Instead of using the toolhead class to determine if stats should be
reported, allow every printer object with a stats() callback to
determine if stats are needed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-05 13:52:05 -05:00
Kevin O'Connor
08874b9c91 clocksync: Respond faster to clock changes
Average clock sync times over approximately 30 seconds instead of 120
seconds so that the clock prediction responds to changes faster.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-05 12:33:29 -05:00
Kevin O'Connor
8121a4a29f avrsim: Rework pacing mechanism
Rework the pacing mechanism to make it more stable.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-05 11:38:13 -05:00
Kevin O'Connor
d1c209c689 graphstats: Fix multi-mcu parsing with reordered stats
The mcu stats (that contain a prefix) may occur before some other
stats - make sure to only apply the stats prefix to those stats that
need it.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-03 18:43:52 -05:00
Kevin O'Connor
f4bfce260a klippy: Introduce load_config_prefix() for modules that take parameters
Use both load_config() and load_config_prefix() functions when
dynamically loading a module from the extras directory - if the config
section name has parameters in it then use load_config_prefix().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-03 12:53:11 -05:00
Kevin O'Connor
7e3adde542 klippy: No need to store fileconfig in main printer object
Just pass the fileconfig reference to the ConfigWrapper instances.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-03 12:17:42 -05:00
Kevin O'Connor
33bdc2fc32 util: Call set_nonblock() in create_pty()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-02 18:32:03 -05:00
Kevin O'Connor
0b76864453 gcode: Make sure need_ack is always restored on run_script()
Restore need_ack even on a G-Code exception.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-02 18:32:03 -05:00
Kevin O'Connor
56bfb3280a gcode: Keep reading input to check for M112 (emergency stop)
OctoPrint (and other software) will sometimes send additional commands
even if the previous command has not yet responded with an "ok".
Change the g-code input reading code to keep reading input so that an
M112 can be detected (and processed out-of-order).  To avoid the
extreme case where one writes an entire g-code file to the input
without any pacing, disable the input reading if more than 20 commands
are pending.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-02 11:00:46 -05:00
Kevin O'Connor
3ddbd34a7c gcode: Propagate errors from run_script()
If the script being run raises an error, then stop running that script
and return the error to the caller.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-01 12:18:47 -05:00
Kevin O'Connor
67f9c4948d gcode: Ack even empty lines
An empty input line should still return an "ok" message.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-02-01 11:03:49 -05:00
Kevin O'Connor
7d3600f918 docs: Add github issue template
Add an issue template requesting the klippy log file.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-31 14:30:05 -05:00
Kevin O'Connor
21df21b7af fan: Clarify hardware_pwm and allow cycle_time to be set on software pwm
Specify hardware pwm cycle times using the same method as software pwm
(in seconds, not clock ticks).  Allow the fan code to be configured
with an explicit cycle time even when using software pwm.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-29 13:08:15 -05:00
Kevin O'Connor
b7b216af7f avr: Round hardware pwm clock ticks to nearest divisor
Instead of rounding down to the nearest supported pwm divisor, round
to the nearest divisor.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-29 11:54:15 -05:00
Kevin O'Connor
077a56c2ca mcu: Default the restart method to 'command' on non-serial ports
If the mcu supports command restarts and it does not appear to use a
real serial port, then default the restart method to 'command'.  This
is a better default on boards with native USB support.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-29 10:25:25 -05:00
Kevin O'Connor
a67306c76b msgproto: Support default values in get_constant() calls
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-29 10:10:27 -05:00
Kevin O'Connor
6eefbe5e30 heater: Add stats reporting
Report the current temperature, current pwm setting, and target
temperature as statistics in the log.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 23:37:56 -05:00
Kevin O'Connor
650d55d7b2 docs: Remove bed level probe from todo
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 20:36:04 -05:00
Kevin O'Connor
03bcae8a98 config: Add SeeMeCNC Rostock Max V2 Delta Printer Config
As provided by @FEsmondeWhite

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 20:31:15 -05:00
Kevin O'Connor
1a67902858 homing_override: Allow moves prior to homing an axis
Add support for disabling homing checks via the homing_override
mechanism.  This may be useful to move an axis prior to homing it.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
01bb4b291e probe: Create a probe:z_virtual_endstop pin
Create a virtual pin that may be used as the z endstop pin on
cartesian printers that use the probe in place of a z endstop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
e38c7df064 probe: Support activate/deactivate scripts on each probe
Allow a set of g-code scripts to be run on each probe invocation.
This may be useful for probes that need to be setup before they are
useful (eg, with servo actuated probes).

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
3001a089c0 homing_override: Add basic support for running custom g-code on G28
Allow users to override the behavior of G28 using a new
"homing_override" config section.  This may be used on printers that
require specific steps during the homing process.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
39d62556b1 bed_tilt: Add support for automatic bed tilt move transformation
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
434341d074 delta_calibrate: Add initial support for a DELTA_CALIBRATE command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
ce9db609ad probe: Initial support for Z-Probe hardware
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
6c252d30f5 delta: Allow the user to specify a minimum z position
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
978777f09f replicape: Move the replicape code from chipmisc.py to extras directory
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
5db84779c6 ad5206: Move the ad5206 code from chipmisc.py to extras directory
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
1e3a03fbee servo: Move the servo code from chipmisc.py to extras directory
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
01a89b951a multi_pin: Move the multi_pin code from chipmisc.py to extras directory
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
d166d1f692 fan: Move fan code to extras directory
The print cooling fan and printer heater_fan are independent modules
that can reside in the extras directory.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
9399911490 klippy: Add support for dynamic loading of python modules
Check if a config section matches a python filename in the
klippy/extras/ directory.  If it does, load that python code to handle
the config section.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
d3665699f1 klippy: Support generic printer_state() and stats() callbacks
Instead of hardcoding which objects are called on state transitions,
allow any "printer object" to be invoked if it has a printer_state()
method.  Convert connect, ready, shutdown, and disconnect callbacks to
this mechanism.

Similarly, allow all printer objects to provide a stats() callback.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
81013ba5c8 klippy: Add access methods and avoid peeking into the printer classes
Add get_reactor(), lookup_object(), lookup_module_objects(), and
set_rollover_info() to the main Printer class so that callers do not
need to peek into the class' members.  Similarly, add get_printer()
and get_name() methods to the ConfigWrapper class.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
f0a754e496 gcode: Add a run_script() helper method to run g-code scripts
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
51e1085dbc gcode: Extend register_command() so that it can also unregister a command
If register_command() is passed None as the function to call, then
treat it as an unregister command request.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 12:19:26 -05:00
Kevin O'Connor
47bb8b7cc2 graphstats: Fix for print_stall detection
The print_stall logic could cause large portions of the graph to show
up as 100% host utilized.  Rework the logic to avoid that.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 10:50:52 -05:00
Kevin O'Connor
33893ece1d logextract: Fix error in config file name print
Fix typo causing an error during the printing of the config file name.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-28 10:50:43 -05:00
Kevin O'Connor
1b3ef8a8fb config: Update anycubic-i3-mega-2017.cfg with stepstick fan
Based on conversation with Marcin Jedliński.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-22 11:28:20 -05:00
Kevin O'Connor
09eec3710d extruder: Add support for extruders sharing the same heater
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-21 23:25:11 -05:00
Kevin O'Connor
6fa95e12ea config: Update wanhao-duplicator-i3-plus-2017.cfg heater settings
Update config based on discussion with Max Holden and Josh Sutinen.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-21 18:52:14 -05:00
Kevin O'Connor
7a11b78fd4 config: Update anycubic-i3-mega-2017.cfg heater settings
Updates to heater settings.  Based on discussion with @bartolomeus and
Marcin Jedliński.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-21 18:47:34 -05:00
Kevin O'Connor
3d26bf6635 logextract: Better handle the case of a missing config section
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-21 15:56:13 -05:00
Kevin O'Connor
08444a8b89 docs: Try to make the klippy.log bug reporting more clear
Emphasize that the log file needs to be attached to the issue.
Encourage M112 to be issued on every bug report.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-21 13:08:31 -05:00
Kevin O'Connor
84c623e705 config: Add example generic-mini-rambo.cfg config file
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-17 01:00:20 -05:00
Douglas Hammond
72074078f9 config: Add tronxy x5s config
Signed-off-by: Douglas Hammond <wizhippo@gmail.com>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-16 22:20:55 -05:00
Kevin O'Connor
1d11c4e74d gcode: Use reset_last_position() from cmd_G28()
Use the existing reset_last_position() code in cmd_G28() instead of
manually implementing the logic.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-16 21:46:42 -05:00
Kevin O'Connor
f8bb383e9a extruder: Remove unused variable self.config
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-16 21:40:53 -05:00
Cymen Vig
8e5d228555 Add a CR-10S configuration file.
Signed-off-by: Cymen Vig <cymenvig@gmail.com>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-16 18:29:45 -05:00
Kevin O'Connor
6770aa96c9 graphstats: Use alpha transparency when plotting the stats
Use an alpha transparency on each of the stats, so that it is possible
to see how the values overlap.

Also, always enable the "awake time" stat - just use a lower alpha
transparency for it.

Also, explicitly set the graph size as some version of matplotlib have
a different default.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-14 10:46:48 -05:00
Kevin O'Connor
896c31fd05 graphstats: Fix filtering of normal buffer_time runoff stats
Update the mechanism to filter out cases where buffer_time is below
MAXBUFFER so that it works with the statistics currently generated.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-14 10:16:16 -05:00
Kevin O'Connor
054cbbe094 docs: Add a FAQ item on steps to upgrade the software
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-12 18:38:49 -05:00
Kevin O'Connor
0d8ddcadbb toolhead: Improve tracking of print_stall
The previous code increases print_stall if a move is proactively
flushed due to buffer_time_low and a follow up move is ready to send
before the existing moves are fully retired.  However, this would not
track the case where a move is proactively flushed and it takes an
extended amount of time to get sufficient moves to refill the queue.

Change the code so that print_stall increases anytime a new move is
queued after a proactive flush and there are existing moves not yet
fully retired.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-12 16:56:31 -05:00
Kevin O'Connor
d3eda337a9 logextract: Fix parsing of "is_shutdown" messages
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-12 16:44:21 -05:00
Kevin O'Connor
138f3c2646 config: Update avrsim.cfg to use unique pins
Commit 3833669c added checking that each pin is used once in the
config.  This exposed an error in the avrsim.cfg testing config -
analog1 conflicts with ar25.  Use analog7 to avoid this.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-12 16:44:21 -05:00
Kevin O'Connor
f1222565b8 docs: Update Debugging.md with information on logextract
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-11 13:48:40 -05:00
Kevin O'Connor
5caff594c5 heater: Report PID tuning results via the g-code terminal
Determine the median period from the pin tuning tests and use that to
recommend a set of PID parameters.  Report the results over the g-code
terminal.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 22:58:12 -05:00
Kevin O'Connor
5a68c636da chipmisc: Enable replicape steppers dynamically
Enable all the steppers via the shift registers when the first stepper
is enabled, and disable all the steppers once all steppers are
disabled.  This avoids having to enable all the steppers all of the
time.  Note that, this support is independent from the current control
for each stepper, which is still done individually.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 19:30:57 -05:00
Kevin O'Connor
02b141ac43 chipmisc: Fix replicape enable line setup
The enable lines are not one per stepper - instead there are 5
distinct enable settings.  Handle them properly.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 19:30:51 -05:00
Kevin O'Connor
47e458210e chipmisc: Support start values on pca9685 pins
Default the pca9685 enable line on if any of the pins attached to it
have a non-zero start value.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 19:30:47 -05:00
Kevin O'Connor
3833669c3a pins: Check if the same pin is referenced via different aliases
Change the update_command() call to use a new PinResolver class.  In
that new class, verify that the same pin isn't referenced in two
different parts of the config using different aliases for the pin.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 19:26:06 -05:00
Kevin O'Connor
df6528715e stepper: Automatically detect and handle shared stepper enable lines
It's common for multiple steppers to use the same stepper enable
line.  Detect this and only create a single digital_out oid on the
micro-controller.

Also, prohibit any other pin from being used multiple times in the
config file.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 19:10:26 -05:00
Kevin O'Connor
265b9097d5 pins: Rename parse_pin_desc() to lookup_pin()
Always set the pin_params['type'] field on a pin lookup.  Rename
parse_pin_desc() to lookup_pin() to make the change more clear.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-10 14:21:25 -05:00
mjedlinski
a6025686b6 config: Config file for Anycubic i3 Mega
Signed-off-by: Marcin Jedliński <mjedlinski@gmail.com>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-08 23:11:41 -05:00
Kevin O'Connor
ed80b92b59 mcu: Setup static values via setup_start_value() call
Add an "is_static" setting to setup_start_value() and remove the
setup_static() method.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-08 21:21:30 -05:00
nerobot
45e65580f7 config: Create creality-cr10
Signed-off-by: Steven Daglish <s.c.daglish@gmail.com>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-08 18:48:03 -05:00
Kevin O'Connor
f6f174ab36 extruder: Fix pressure advance on tiny moves with over extrusions
The extruder check_move() code will permit moves with huge extrusion
ratios if the amount extruded is tiny.  (Some slicers emit these silly
moves - they are allowed because they are harmless.)  Unfortunately,
the pressure advance code did not handle the huge extrusion ratios -
it would result in a massive, near instantaneous, extruder move in an
attempt to build pressure in the extruder.  Catch this case and limit
the impact to the pressure advance code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-08 14:39:19 -05:00
Kevin O'Connor
0cf06ee69a docs: Note pressure_advance over 0.20 is unlikely to improve quality
Update the pressure advance tuning document to note that 0.20 is
likely the ceiling of a useful pressure advance setting.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-08 11:07:26 -05:00
Kevin O'Connor
ed9dee4602 mcu: Only report an MCU timeout once
Don't flood the log with timeout messages.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-08 10:55:37 -05:00
tilsonm
f183871e28 config: Adopt Anet A8 cfg, Anet v1.0-1.5 Boards
This configuration file should work as a base for Anet A8 printers
using the stock Anet v1.0-1.5 boards from late 2016-2017, which are
based around the AVR atmega1284p. Minor tweaks may be required to such
things as /dev/serial/by-id/, thermistor sensor types, and offsets for
carriage and bed.

Signed-off-by: Matt Tilson <tilsonm09@gmail.com>
2018-01-07 22:22:08 -05:00
Kevin O'Connor
d891baa860 avr: Clear the TCNT1 register on timer startup
Just to be safe, clear the TCNT1 register during init.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-07 22:22:08 -05:00
Kevin O'Connor
f6cd51bfb7 avr: Clear the ADCSRA/ADCSRB registers on ADC init
When initializing the ADC, explicitly clear the registers (instead of
logically or'ing them with their previous values).

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-07 22:13:39 -05:00
Kevin O'Connor
83e9e92b9a docs: Add a table of contents to the FAQ
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-05 11:42:00 -05:00
Kevin O'Connor
9e4eb050f9 config: Note the need to flash a bootloader on the Melzi
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-05 10:23:58 -05:00
Kevin O'Connor
5a86391f78 avr: Only use the avrdude "wiring" protocol on atmega2560 devices
It appears the most common type of avrdude protocol for devices other
than the atmega2560 is the "arduino" protocol.  Update the build to
select a different protocol based on the avr processor type.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-05 10:02:15 -05:00
Kevin O'Connor
29c83cec22 docs: Update installation document with pointers to FAQ
Add some pointers to the FAQ for common pitfalls during installation.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-04 13:29:17 -05:00
Josh Sutinen
db927bd822 config: Added Wanhao Duplicator i3 Plus configuration
The Wanhao Duplicator i3 Plus (aka Maker Select Plus,
Microcenter Powerspec Plus, and others) uses an
atmega2560 AVR. The config is based on generic-ramps.cfg
with pin numbers updated from the official Wanhao Marlin
sources at https://github.com/garychen99/Duplicator-i3-plus

Signed-off-by: Josh Sutinen <josh@damagedgoodz.net>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-04 12:10:01 -05:00
Chris Lee
cb969527bc config: Update TAZ6 defaults for hotend
Use values from Lulzbot fork of Marlin.

Signed-off-by: Chris Lee <clee@mg8.org>
2018-01-04 10:58:47 -05:00
Kevin O'Connor
3ab9a8d26c gcode: Add support for M221 (set extrude factor) g-code command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-03 17:12:31 -05:00
Kevin O'Connor
5db4886c9c gcode: Add support for M220 (set speed factor) g-code command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-03 17:12:26 -05:00
Andy Silverman
b22a81cd34 heater: Added config for heater PWM cycle time.
Added the pwm_cycle_time option for heater config sections.  Defaults
to previous value of 0.100 seconds, but may be reduced to shorter times
at the expense of MCU workload and possible MOSFET heating, depending on
controller design.  Some printers that need bed PID to be enabled,
notably the Felixprinters series, are known to benefit from shorter
cycle times, as the default 10hz rate results in excessive voltage
supply droop.

While this option can be used on extruder heaters as well, there
is not expected to be any particular benefit from doing so unless
the extruder heater presents a particularly large load.

Signed-off-by: Andy Silverman <andrewsi@outlook.com>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-03 12:32:11 -05:00
Chris Lee
9fc5506c83 config: Add Lulzbot TAZ6 printer configuration
Signed-off-by: Chris Lee <clee@mg8.org>
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-03 12:10:40 -05:00
Kevin O'Connor
bba22ab7f0 heater: Provide symbolic names for pid check_busy (aka M109 / M190)
Add PID_SETTLE_DELTA and PID_SETTLE_SLOPE constants to the code to try
and make it a little more clear how the wait for temperature code
works.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-03 10:44:01 -05:00
Kevin O'Connor
a0b4cdb5c4 gcode: Don't wait for temperature if the temperature is disabled
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-03 10:33:10 -05:00
Kevin O'Connor
e4129a7e53 docs: Minor update to square.scad
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-02 21:56:29 -05:00
Kevin O'Connor
00ea3934ee logextract: Add support for extracting shutdown info on multiple mcus
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2018-01-02 21:48:25 -05:00
Kevin O'Connor
cf4c31cb88 graphstats: Add support for generating a graph of mcu frequency
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-30 18:29:58 -05:00
Kevin O'Connor
f10bd5726d graphstats: Use a smaller font in the graph legend
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-30 18:27:44 -05:00
Kevin O'Connor
7db6fa7bfc graphstats: Fix case where an Xwindows display may not be available
Matplotlib will try to open a display by default - tell it not to do
that so that it can run in batch mode on headless machines.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-30 18:26:49 -05:00
Kevin O'Connor
b05eb1e8e3 logextract: Fix handling of messages with retransmits
Properly handle the case where the original sequence number of a
message is not known.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-29 15:25:39 -05:00
Kevin O'Connor
1bdebeaebf docs: Add an initial configuration checklist document
Provide a document with basic steps that a user can run to verify that
the pins in the configuration file are set correctly.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-26 20:54:37 -05:00
Kevin O'Connor
479772ca00 docs: Add a CONTRIBUTING document
Add an initial document detailing best practices for contributing to
the document.  Add the "developer certificate of origin" document.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-24 12:33:01 -05:00
Kevin O'Connor
1d276d160f gcode: Dump internal g-code state in dump_debug()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-21 22:27:49 -05:00
Kevin O'Connor
9313e58123 gcode: Group similar G-Code commands together
Group commands by category instead of listing them in numerical
order.  This is just code movement; no code changes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-21 20:58:25 -05:00
Kevin O'Connor
d778ae1846 build: Add gcc and binutils version to mcu data dictionary
Store the gcc and binutils versions used in the compilation of the
firmware in the firmware data dictionary.  Forward that information to
the log so it is available during debugging.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-21 20:32:10 -05:00
Kevin O'Connor
522093ef00 docs: Offer alternatives to ssh/scp/sftp
Try to make the Installation document more friendly to users not
familiar with the Linux command-line.  Offer some hints on how to
obtain ssh and how to edit the config file remotely.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-21 17:34:35 -05:00
Kevin O'Connor
d303e556ad sched: Interrupts must be disabled during setjmp() call
On the AVR platform (and possibly others) the longjmp() call will
restore the interrupt state saved during the setjmp() call.  So, the
setjmp() call must be invoked with interrupts disabled to ensure that
shutdown handling is run with interrupts disabled.  This fixes
potential corruption of the shutdown processing on AVR.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-21 12:54:33 -05:00
Kevin O'Connor
1d21bf66c6 homing: Handle speed rounding when homing speed greater than max_velocity
Commit 002dc0df added rounding to the homing speed, but it did not
work if the configured homing speed was less than the printer's
maximum velocity.  Move the speed rounding from stepper.py to
homing.py and make sure the rounded speed is less than the maximum
speed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-20 14:41:20 -05:00
Kevin O'Connor
1b07505973 chipmisc: Add multi_pin capability
Add the ability to alias multiple output pins from a single pin alias.
This makes it possible to support some cases where a single logical
output is driven by multiple output pins.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-18 21:00:06 -05:00
Kevin O'Connor
3c5649219f chipmisc: Add support for output pins set at runtime
Add the ability to define output pins that may be set at runtime with
a new SET_PIN extended g-code command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-18 20:59:07 -05:00
Kevin O'Connor
68d03e4a3e mcu: Allow both shutdown and startup values to be set for output pins
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-18 20:45:00 -05:00
Kevin O'Connor
e6e0a21b06 toolhead: Allow junction_deviation to be set to zero
Allow lookahead to be effectively disabled by setting
junction_deviation to zero.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-18 20:44:59 -05:00
Kevin O'Connor
0e0780a460 logextract: Update file comment
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-18 12:14:10 -05:00
Kevin O'Connor
9a4425c85a docs: Update square test print to contain notches on inside of square
Add additional notches and move them to the inside of the square where
they will not impact the outside perimeter test.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-17 12:18:25 -05:00
Kevin O'Connor
57c27f75ae gpiocmds: Clear SPF_NEXT_* flags on new schedule_soft_pwm_out
Properly handle the (unlikely) case that a schedule_soft_pwm_out
command is received before a previous command is fully processed,

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-16 20:21:38 -05:00
Kevin O'Connor
8d62318c5f clocksync: The clock estimate should add the rtt time not subtract it
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-16 20:21:38 -05:00
Kevin O'Connor
add528532e logextract: Rename extractconfig.py to logextract.py and add shutdown parsing
Add initial support for extracting out shutdown information from a
klippy.log file.  The shutdown dump will be reordered into the
sequence that they occurred, and timestamps/sequence numbers in the
mcu message dump will be expanded.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-16 20:21:34 -05:00
Kevin O'Connor
8944e2104d docs: Add FAQ item on AVR watchdog restart failures
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-11 18:17:14 -05:00
Kevin O'Connor
319221ee23 docs: Provide additional information on "make flash" failures
Add some additional information on "make flash" problems.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-11 17:33:29 -05:00
Kevin O'Connor
4a5801bb2e pins: Fix atmega168/328 mappings
The atmega168 and atmega328 need to define PE0 and PE1 in order to
support the 2 extra analog pins.

Also, support the arduino mappings for the atmega328.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-09 11:48:26 -05:00
Kevin O'Connor
f8acf0f54f delta: Default stepper_b/c position_endstop to stepper_a's
If the position_endstop is not set for stepper_b or stepper_c then use
the value from stepper_a.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-08 18:20:04 -05:00
Kevin O'Connor
bc5d900e61 delta: Support different arm lengths for each tower
Change the config file so that the delta arm length is specified
per-tower.  This makes it possible to support advanced calibration.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-08 18:20:04 -05:00
Kevin O'Connor
efb4a5daa1 delta: Rework actuator_to_cartesian() using trilateration
Use the formulas for trilateration (instead of the circumcenter
formulas) when calculating the position of the nozzle from the
position of the carriages.  The trilateration formula is more general
and it allows each tower to have a different arm length.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-08 18:09:19 -05:00
Kevin O'Connor
e0c947e188 mcu: Store MCU_stepper commanded_pos as a float
It's valid to consider the stepper at a position that is not on a step
interval - only the "mcu position" needs to be an integer.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-07 18:14:50 -05:00
Kevin O'Connor
3ffab763c0 stepper: Only align the stepper motor to a full step when requested
Add a new config option 'homing_endstop_align_zero' to enable the
alignment of the endstop to a stepper full step.  It's possible one
may wish to specify a homing_endstop_phase while not aligning the
endstop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-07 17:35:19 -05:00
Kevin O'Connor
ef09ac5a7f extractconfig: Add helper script that extracts config files from a log
Add a helper script that can read a klippy.log file and extract the
printer.cfg files from it.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 21:23:24 -05:00
Kevin O'Connor
f6d4284d5c homing: Directly interact with the kinematic class on query_endstops()
Move the query_endstop logic out of toolhead.py and into homing.py.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 19:13:54 -05:00
Kevin O'Connor
8d9ca6f2dd homing: Directly interact with the kinematic class when homing
Move the homing logic out of toolhead.py and into homing.py.  This
simplifies the toolhead logic and centralizes the homing code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 19:13:54 -05:00
Kevin O'Connor
1d6af72de5 mcu: Remove unneeded MCU_digital_out.get_last_setting() method
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 19:13:54 -05:00
Kevin O'Connor
2a8dd5c51f mcu: Reset the stepper step clock on init - not after each motor on
Reset the last step clock during the init phase and after each home -
this simplifies the runtime code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 19:13:54 -05:00
Kevin O'Connor
c78f66b8e8 mcu: Be sure all moves are completed before raising a home timeout
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 19:13:54 -05:00
Kevin O'Connor
b340fdcc4a homing: Make sure to clean up homing state even if homing fails
Make sure to always call MCU_endstop.home_wait() if
MCU_endstop.home_start() is invoked.  Rename
MCU_stepper.note_homing_triggered() to note_homing_end() and make sure
it is always called if MCU_stepper.note_homing_start() is invoked.

With these changes, MCU_endstop.home_finalize() is no longer needed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 19:13:53 -05:00
Kevin O'Connor
7785d3a87d homing: Pass list of endstops (not steppers) to the homing code
The homing code wants the list of endstops to enable during a homing
operation - it's confusing to pass the steppers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:49:14 -05:00
Kevin O'Connor
31db4cc772 mcu: Make sure steppers added to an endstop are on the same mcu
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:51 -05:00
Kevin O'Connor
7932de11a7 mcu: Make sure all endstop objects are disabled on a reconnect
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:51 -05:00
Kevin O'Connor
bc9cbc8133 gcode: Move SET_SERVO command from gcode.py to chipmisc.py
Now that commands can be registered dynamically, move the code for
SET_SERVO from gcode.py to the PrinterServo() class in chipmisc.py.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:51 -05:00
Kevin O'Connor
b5a41d0dd1 gcode: Rework gcode handler setup to allow dynamic command registration
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:51 -05:00
Kevin O'Connor
64a091fb98 gcode: Add a get_str() method
Add a get_str() method that can extract a required parameter from a
g-code command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:51 -05:00
Kevin O'Connor
80f23441dd gcode: Simplify exception handling
Translate caught exceptions into a gcode.error() exception.  This way
there is one standard place to invoke respond_error().  Also, always
reset the last_position on a handled error.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:51 -05:00
Kevin O'Connor
3a2d16abb3 gcode: Always allow M112 command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-06 18:35:49 -05:00
Kevin O'Connor
c70cc8fadb klippy: Always recommend a FIRMWARE_RESTART on a shutdown event
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-03 19:52:25 -05:00
Kevin O'Connor
10e11950ae stepper: get_homed_offset() should return a float
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-12-03 19:48:47 -05:00
Kevin O'Connor
37788c1e55 docs: Add a FAQ document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-30 15:19:40 -05:00
Kevin O'Connor
6d6638826c stepcompress: Fix proactive queue flushing on move with 64K+ steps
Commit e05c6354 changed the internal step compress queue from 64bit
integers to 32bit integers.  However, that commit broke the proactive
flushing of moves that could produce more than 64K steps.  This could
lead to large memory allocations and cpu slow downs on printers that
had a very large Z axis - possibly leading to a "Timer too close" mcu
shutdown.  Correct the code so that it properly generates a 64bit
flush clock.

Also, be sure to only expand / memmove the queue when there is no room
for a new element at the end.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-29 20:24:50 -05:00
Kevin O'Connor
6930a7de8d homing: Base homing cpu delay on estimated number of steps needed
Instead of adding 250ms to each homing operation add a time relative
to the number of estimated steps that are to be generated.  This
scales the delay to really large axes without adding a delay for
normal users.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-29 19:55:25 -05:00
Kevin O'Connor
6bbb84326d docs: Add further details on how to report a bug
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-21 18:27:22 -05:00
Kevin O'Connor
8c2fa2e2d6 stepper: Support for multiple steppers controlling a single axis
Allow multiple steppers to be defined for a single cartesian axis.
This adds support for dual-z setups.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-18 17:37:04 -05:00
Kevin O'Connor
38643f52c9 stepper: Add get_endstops() / set_position wrappers
Add wrappers around mcu_endstop and mcu_stepper so that the kinematic
classes do not need to directly access these low-level classes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-18 17:36:45 -05:00
Kevin O'Connor
eecf3b6ea8 stepper: Store pointers to step_const and step_delta in PrinterStepper
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-18 17:29:23 -05:00
Kevin O'Connor
fc1d690d75 stepper: Remove unused variables from PrinterStepper class
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-18 17:29:23 -05:00
Kevin O'Connor
d10380e73f stepper: Additional code comments
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-18 17:29:23 -05:00
Kevin O'Connor
aaeda540b6 stepper: Calculate the stepper name directly from the config section
There is no need to pass the name to the PrinterStepper class as it
can determine the name itself.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-18 17:29:22 -05:00
Kevin O'Connor
fda988889b heater: Avoid math errors on extreme ADC readings
Avoid log(0) and divide by zero errors in the thermistor calc_temp()
method.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-13 11:07:20 -05:00
Kevin O'Connor
b58a897b70 config: List E1 micro-step pins in order in generic-rambo.cfg
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-11-08 11:14:37 -05:00
Kevin O'Connor
84d8cf9b7e config: Add a generic-printrboard.cfg file
Add an example config file for the Printrboard board.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-30 10:56:08 -04:00
Kevin O'Connor
8463a83324 graphstats: Fix graphing script
Update the graphstats.py graphing script so that it works with recent
stats changes - the stats can now contain groups that end with a ':'
and the print_time is no longer reset to zero on a new print.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-29 20:36:33 -04:00
Kevin O'Connor
fc0e016a6d docs: Note version 0.5.0 release
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-25 11:27:20 -04:00
Kevin O'Connor
f5c0148665 config: Warn Beaglebone PRU users that pinmux settings are not updated
The Beaglebone hardware prevents the PRU from updating the pinmux
board settings.  As a result, the PRU can't directly change the pin
direction or change the pullup resistor settings.  Warn the Beaglebone
users of this limitation.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-25 11:01:36 -04:00
Kevin O'Connor
3d78a99758 docs: Update Installation document to recommend latest octoprint version
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-25 10:44:49 -04:00
Kevin O'Connor
03e97c2d95 linux: Remove unneeded includes from timer.c
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-23 22:20:53 -04:00
Kevin O'Connor
eaacb928fc pru: Force load the ADC module during PRU startup
Make sure the ADC module gets loaded during startup - it's normally
loaded by the cape manager eeprom, but there's no harm in requesting
it explicitly.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-18 13:23:10 -04:00
Kevin O'Connor
75ba375b8a pru: Don't reset the ADC reset complete flag if a shutdown occurs
Only set the have_done_reset flag if the reset completes successfully.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-18 13:05:36 -04:00
Kevin O'Connor
cbd06f1433 linux: Fix typo causing config_reset to not fully restart
A typo in the code caused the wrong config_reset code to be run.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-15 21:05:08 -04:00
Kevin O'Connor
1c59a0d30a linux: Open watchdog device after console
Only open the watchdog device after the console has been opened.  The
machine should not reboot in the unlikely event the console can't be
opened.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-15 21:05:08 -04:00
Kevin O'Connor
d222ec1024 linux: Make sure to close fd on analog/pca9685 init failure
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-14 00:22:21 -04:00
Kevin O'Connor
674f584190 pca9685: Fix missing devices_count increment
The devices_count was not being incremented on each device add.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-13 22:05:19 -04:00
Kevin O'Connor
77fea562c4 clocksync: Start with adjusted_freq of 1.0
Avoid setting adjusted_freq to 0.0 as that can cause divide by zero
failures at startup.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-13 21:07:32 -04:00
Kevin O'Connor
e0f275cddf serialhdl: Don't open port at 1200 baud
The 1200 baud trick on the Arduino Due does both a reset and an
erase.  The erase is not desired.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 21:46:09 -04:00
Kevin O'Connor
07a69df62f mcu: Fix command restart
Fix omission in commit f8750b14 that broke restarts via Klipper
command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 21:43:33 -04:00
Kevin O'Connor
f8750b142f klippy: Rework shutdown handling
If an MCU signals a shutdown from the background thread, notify the
main thread and handle the shutdown there.  Dispatch shutdown handling
from the main Printer() class instead of from the Toolhead class.
This simplifies the shutdown logic.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 16:28:53 -04:00
Kevin O'Connor
3033b03789 config: Add generic-melzi.cfg file for Melzi boards
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 12:43:13 -04:00
Kevin O'Connor
3506d1e994 fan: Enable heater_fan objects on an MCU shutdown event
Should the MCU go into an error state, set the heater_fan to
max_power.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
3c4d14bfa9 pca9685: Support default values
Allow the pwm pin to have a non-zero default value.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
db97f36631 gpiocmds: Allow the start value for a pin to differ from the default_value
Allow the start value to be different from the default/shutdown value
for the pin.  This will be useful for "heater fans" that should
startup in the off state, and transition to full on in a shutdown
state.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
d03cf2b83f adccmds: Continue to query analog inputs after a shutdown
Continue to sample the ADC input pins even if the MCU goes into a
shutdown state.  This enables the printer to continue reporting
temperatures even on an mcu error.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
744c6d114e sched: Don't shutdown on a "timer in the past" if already shutdown
A shutdown will not help if the mcu is already in a shutdown state.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
3b9b4e4d6f endstop: Eliminate end_stop_set_oversample command
Pass the sample_ticks and sample_count parameters directly in the
end_stop_home command instead.  This simplifies the code.

Also, simplify calculation of next wakeup time in
end_stop_oversample_event().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
78ba7064a7 clocksync: Initialize clock_est in connect_file()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 11:59:27 -04:00
Kevin O'Connor
cc7c99a4a4 cartesian: Fix min_stop_interval calculation error
It is possible to have an acceleration greater than max_z_accel on
XY+Z moves.  That needs to be taken into account when calculating the
min_stop_interval.  This prevents spurious "No next step" MCU errors.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-12 01:16:11 -04:00
Kevin O'Connor
d3eb148cfa docs: Point to beaglebone.md from the main installation document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-11 21:03:13 -04:00
Kevin O'Connor
00d541b767 docs: Octoprint should not run at a higher priority than Klipper on beaglebone
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-11 20:23:58 -04:00
Kevin O'Connor
ecf2596469 gcode: Don't warn on fan not present if input is from a file
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-11 14:28:19 -04:00
Kevin O'Connor
6a2eaeae40 docs: Add mailing list to Contact.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-10 14:24:04 -04:00
Kevin O'Connor
ce7cc798dc docs: Add Contact.md file with developer contact information
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-10 12:43:44 -04:00
Kevin O'Connor
0ec7eda11b pins: Add pin mapping for atmega1284p
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-05 16:57:44 -04:00
Kevin O'Connor
fb0f344346 avr: Add support for atmega1284p
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-05 13:51:05 -04:00
Kevin O'Connor
afac81c161 pru: Update start script to always unbind the PRU before binding it
It appears some versions of Debian will load the PRU with firmware on
boot, so make sure to always deactivate the PRU before attempting to
activate it with new firmware.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-05 13:50:12 -04:00
Kevin O'Connor
5c982c90f3 docs: Add a notch to the default square.stl test object
Place a small notch on one side of the square.  The notch provides
interesting information on the extruder performance, and it makes it
easier to compare with previous prints of the object.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-03 22:08:36 -04:00
Kevin O'Connor
381304aa6f stepper: If homing_endstop_phase is configured, make 0.0 be at a full step
If the stepper phases are known then it is possible to arrange for the
0.0 position to occur at a full step.  On cartesian style printer,
this makes it possible for the Z levels to occur at full steps (which
may help reduce "Z ribbing").

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-03 22:06:51 -04:00
Kevin O'Connor
ce9523fb90 gcode: Report the raw MCU position from the M114 command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-03 22:03:52 -04:00
Kevin O'Connor
06420b0ddf gcode: Carry over #original and #command in get_extended_params()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-02 22:06:43 -04:00
Kevin O'Connor
c2e1c53356 clocksync: Implement a floor on the prediction filter
Don't discard samples that are less than 500us from the prediction
regardless of the prediction variance.  Also, don't use the prediction
variance in the external time estimate.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-02 11:00:24 -04:00
Kevin O'Connor
eaeb831107 endstop: Fix typo in comment
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-02 11:00:23 -04:00
Kevin O'Connor
459695e9d7 docs: Remove items from Todo.md
Several items were recently implemented.  Remove the "cubic vs
quadratic" item as investigations into cubic compression weren't
promising.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-01 19:34:00 -04:00
Kevin O'Connor
ece1f71c64 endstop: Support oversampling of the endstop
Some printers can show occasional noise on the endstop pin.  Support
sampling the endstop pin multiple times to attempt to filter out this
noise.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-10-01 19:15:55 -04:00
Kevin O'Connor
776d8f9f79 clocksync: Update clock synchronization code to use a linear regression
Implement a "moving" linear regression between the reported mcu clock
and the sent_time of the get_status message that generated that
report.  Use this linear regression to make predictions on the
relationship between the system time and the mcu clock.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-30 19:37:37 -04:00
Kevin O'Connor
61ee63f358 serialqueue: Don't report sent_time on responses that are retransmitted
On a retransmit, the sent_time of the command associated with the
given response message isn't accurate.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-30 19:37:20 -04:00
Kevin O'Connor
6f65ba9214 clocksync: Don't update prev_est on min rtt updates
Average frequency changes over the longer interval on a sample that
causes a minimum rtt update.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-28 01:09:18 -04:00
Kevin O'Connor
ba837c2641 clocksync: Fix serialqueue.set_clock_est() - don't track min_freq
Revert commit f37fc775.  It is not valid to pass a conservative
frequency to serialqueue.set_clock_est() as that function may not be
called for extended periods - a too low frequency would eventually
lead to "Timer too close" mcu errors.

Instead, increase the 1ms time offset to 5ms to avoid corner cases
that could lead to a message arriving too soon.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-28 00:51:48 -04:00
Kevin O'Connor
1518032606 clocksync: Default mcu_freq to 1 instead of 0
This prevents divide by zero errors during stats output if the stats
are generated before a connection completes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 20:07:46 -04:00
Kevin O'Connor
6469cce2bc toolhead: Make sure reset_print_time() doesn't go backwards in time
Update the homing code to pass in the start of the homing operation to
toolhead.reset_print_time().  This prevents an error when batch
processing gcode files that contain multiple homing operations.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 19:21:26 -04:00
Kevin O'Connor
4c40b50fb5 docs: Add a section on time handling to Code_Overview.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 15:11:15 -04:00
Kevin O'Connor
a0f0911a95 docs: Reword performance paragraph in Features.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 13:59:47 -04:00
Kevin O'Connor
f658819862 clocksync: Add support for dumping internal state for debugging
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 13:13:38 -04:00
Kevin O'Connor
8d5a9143bb klippy: Avoid using '%' syntax when calling logging module
The logging module can build strings directly from printf syntax - no
need to build the string first.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 12:38:20 -04:00
Kevin O'Connor
8f8951b4c1 serialhdl: Make dump_debug() output atomic
Build a single (very large) logging message with the debug state.
This prevents the output from being fragmented.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 12:38:20 -04:00
Kevin O'Connor
6e5bcc69bc gcode: Make dump_debug() output atomic
Build a single (very large) logging message with the debug state.
This prevents the output from being fragmented.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 11:58:21 -04:00
Kevin O'Connor
8d04d3d8fd gcode: Exit if a shutdown occurs while running in batch mode
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 10:05:11 -04:00
Kevin O'Connor
f37fc775e5 clocksync: Be conservative when setting serialqueue.set_clock_est()
Accuracy is not as important as ensuring a message is never sent
before it can be received in the serialqueue code.  So, use the
smallest frequency ever seen and add the minimum rtt time when setting
set_clock_est().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-27 09:10:41 -04:00
Kevin O'Connor
ead99cf647 docs: Update Features.md document for multiple micro-controllers
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-26 22:27:25 -04:00
Kevin O'Connor
3982b5030e serialqueue: Take baud_adjust into account when calculating receive_time
Use baud_adjust when determining the receive_time of a message read
from the serial port.  This improves the accuracy of the clock
synchronization code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-26 22:27:25 -04:00
Kevin O'Connor
d9fe4b6944 clocksync: Rework clock synchronization algorithm
Instead of tracking the minimum frequency ever observed, attempt to
track the actual frequency of the micro-controller (relative to the
host clock).  This improves the stability of the secondary mcu clocks
when multiple mcus are configured.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-26 22:27:25 -04:00
Kevin O'Connor
387cab27bd mcu: Separate restart_microcontroller() into multiple functions
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 16:04:41 -04:00
Kevin O'Connor
6dcc44ce2d chipmisc: Add initial support for servos
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 14:21:36 -04:00
Kevin O'Connor
3b4088c23f chipmisc: Add support for Replicape board
Add support for configuring and controlling the hardware specific to
the revision "B3" Replicape board.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 13:18:07 -04:00
Kevin O'Connor
5a85c1667a pru: Update installation and flash scripts
Update the scripts used to install and "flash" the pru
micro-controller code.  Also, add a "flash" script for the linux
micro-controller code.  This makes it easier to install Klipper on a
Beaglebone board that uses a Replicape.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 12:55:28 -04:00
Kevin O'Connor
16d2ec3a90 linux: Add support for analog IIO devices
Add support for reading analog values via the standard Linux IIO
interface.  This can be used on Replicape boards to sample analog
input pins.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 12:55:28 -04:00
Kevin O'Connor
4d60567bc6 linux: Add support for spidev devices
Add support for sending SPI messages to devices via the standard Linux
SPI interface.  This can be used to configure the shift registers on
Replicape boards.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 12:55:28 -04:00
Kevin O'Connor
73a1c9d249 linux: Add support for pca9685 i2c pwm devices
Add support for controlling pca9685 PWM drivers using the standard
Linux I2C interface.  The pca9685 device is found on Replicape boards.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 12:55:28 -04:00
Kevin O'Connor
d851882278 linux: Initial support for running Klipper in a Linux real-time process
Add support for compiling the Klipper micro-controller code as a
real-time process capable of running on standard Linux systems.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 12:55:28 -04:00
Kevin O'Connor
3ccecc568d mcu: Initial support for multiple micro-controllers
Add initial support for controlling multiple independent
micro-controllers from a single Klippy host instance.  Add basic
support for synchronizing the clocks of the additional mcus to the
main mcu's clock.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-20 12:45:00 -04:00
Kevin O'Connor
cee200e509 mcu: Move code around in MCU class to keep like code together
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:27:18 -04:00
Kevin O'Connor
f1b315e04f mcu: Move print_time to clock conversion code to clocksync.py
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:27:18 -04:00
Kevin O'Connor
94bcd9735a mcu: Add mcu wrapper functions and avoid direct acccess to mcu variables
Don't directly access any of the mcu class variables externally from
the class.  Add wrapper functions for those external callers that need
access to some internal state.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:43 -04:00
Kevin O'Connor
f662445766 stepcompress: Implement print time to clock conversion in C code
Implement the conversion from print_time to the local mcu's clock
within the C code.  This simplifies the python code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:43 -04:00
Kevin O'Connor
008be18f41 clocksync: Don't export get_last_clock()
Everywhere the data in get_last_clock() is used can be done just as
easily with estimated_print_time().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:43 -04:00
Kevin O'Connor
13812aa1c9 clocksync: Move clock synchronization code into new file
Move the low-level clock synchronization code from serialhdl.py to a
new file clocksync.py.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:42 -04:00
Kevin O'Connor
2089f19670 toolhead: Separate is_active() code from stats() code
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:42 -04:00
Kevin O'Connor
593741919f mcu: Update file purpose comment
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:42 -04:00
Kevin O'Connor
9d0fcca8a9 serialhdl: Reduce calculations done while holding the lock
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:42 -04:00
Kevin O'Connor
857eb01bfa homing: Move query_endstop() code from kinematic classes to homing.py
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:42 -04:00
Kevin O'Connor
a100f174f9 mcu: Pass print_time directly to MCU calls
Now that the print_time is always synchronized with the mcu_time,
there is no longer a need to track mcu_time as a separate quantity.
Eliminate references to mcu_time from the code and pass print_time
directly in its place.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:42 -04:00
Kevin O'Connor
5dfe4e1eb9 toolhead: Synchronize print_time to main mcu's time
Instead of starting the print_time at zero, start it at the estimated
time of the main mcu's clock.  This simplifies the code and it ensures
that print_time never goes backwards.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:25:38 -04:00
Kevin O'Connor
b9586bad18 mcu: Use is_fileoutput() externally
Use mcu.is_fileoutput() instead of looking up the "debugoutput" flag
in the start args.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:22:29 -04:00
Kevin O'Connor
f1c2f789b6 klippy: Do not start stats timer until after connect completes
Generating stats during connect leads to potential use of not yet
initialized variables.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:22:29 -04:00
Kevin O'Connor
123719bf92 stepper: Fix bug causing 'enable_pin' to be required
Make sure to initialize mcu_enable to None so that it is initialized
if no 'enable_pin' config value is provided.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-19 17:20:41 -04:00
Kevin O'Connor
14810d7e80 stepcompress: Return number of steps traveled from stepcompress_push()
Return the same information from stepcompress_push() that is returned
from stepcompress_push_const() and stpcompress_push_delta().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-13 09:24:27 -04:00
Kevin O'Connor
52156d2c41 pins: Don't pass mcu_freq to update_command()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-13 09:16:58 -04:00
Kevin O'Connor
2a6a9eb52f pru: Avoid calling "slp" instruction on pru0
If pru0 waits in sleep mode then a full beaglebone reboot is needed to
reprogram the pru0 firmware.  For now, avoid using the "slp"
instruction as a workaround.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-11 13:12:18 -04:00
Kevin O'Connor
bf85c61b48 corexy: Fix max_xy_halt_velocity calculation on corexy
On corexy, the stepper velocity of a diagonal move could be greater
than the maximum printer velocity.  Account for that when setting the
maximum xy halt velocity in the mcu stepper config.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-09 14:45:10 -04:00
Kevin O'Connor
dba488f30a extruder: Remove unused set_max_jerk() call
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-08 19:34:30 -04:00
Kevin O'Connor
d618affd63 pru: Batch outgoing writes
Allow pru0 to gather multiple outgoing message blocks into a single
rpmsg.  This can reduce communication overhead.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-08 11:50:21 -04:00
Kevin O'Connor
121c747cc8 pru: Fix race condition in clearing of irq flags
Each irq flag must only be cleared after it has been serviced.  This
fixes a race condition that could cause incoming commands to be
delayed for extended period.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-08 11:50:21 -04:00
Kevin O'Connor
91b9634198 serialqueue: Fix off-by-one error in retransmit sequence number tracking
Commit 4655a6bf allowed naks to be honored if receive_seq was greater
than the last retransmitted sequence.  However, receive_seq is the
receiver's next sequence number, so a nak should only be processed if
it is one greater than that.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-08 11:50:21 -04:00
Kevin O'Connor
7d17002b33 fan: Allow heater_fan to work with heater_bed
Fix order of init error preventing heater_fan from being used with
heater_bed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-07 11:19:27 -04:00
Kevin O'Connor
477b3941a6 console: Add support for SUPPRESS command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-07 11:19:27 -04:00
Kevin O'Connor
36dd7e7609 console: Add support for a FLOOD command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-07 11:19:27 -04:00
Kevin O'Connor
167a65d826 util: Fix reporting of git version of klippy code
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-07 11:19:27 -04:00
Kevin O'Connor
c9cd8cea66 mcu: Limit value range of PWM and digital outputs prior to transmission
Make sure schedule_digital_out and schedule_pwm_out commands always go
out with a value that is in range for the particular command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-06 12:04:05 -04:00
Kevin O'Connor
dfdcbece53 mcu: Improve error descriptions in Common_MCU_errors
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-06 12:03:49 -04:00
Kevin O'Connor
5b62f15c6d extruder: Provide more details on extruder errors
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-05 22:12:15 -04:00
Kevin O'Connor
09e32d1b84 mcu: Provide some further help on common MCU shutdown errors
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-05 22:12:15 -04:00
Kevin O'Connor
68fc6abf74 avr: Check that FLASH_DEVICE is set on "make flash" command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-05 22:12:15 -04:00
Kevin O'Connor
ff56c0fb74 extruder: Fix typo in init
Commit 7a81bfc4 broke extrude only moves due to a typo in the commit.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-05 22:12:15 -04:00
Kevin O'Connor
36de6118c1 mcu: Limit ADC min/max range to a 16bit integer
Make sure the ADC range sent to the MCU can be encoded into a 16bit
integer.  Otherwise, if the provided min_temp/max_temp was outside the
range of possible values it could result in a spurious mcu shutdown.
In particular, the AD595 could not properly encode a min_temp of zero.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-05 18:22:21 -04:00
Kevin O'Connor
7083a33ecd pru: Support config_reset command to manually reset mcu
Add support for resetting the MCU via a software only mechanism.  This
is useful on the PRU.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-03 23:16:38 -04:00
Kevin O'Connor
7b7f57e01c pru: Only sleep the pru0 if the incoming queue is fully empty
It's possible for multiple blocks to be pending on the incoming
"rpmsg" stream.  Don't sleep unless the input is confirmed to be
empty.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-03 23:15:49 -04:00
Kevin O'Connor
8d0ef49e8f toolhead: Permit look-ahead between Z moves
Extend the look-ahead mechanism to work between moves that contain Z
movement.  This improves Klipper's handling of g-code produced in
"vase mode".

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-03 15:46:48 -04:00
Kevin O'Connor
7a81bfc4a4 toolhead: Eliminate set_max_jerk() from kinematic classes
Allow the kinematic classes to query the max velocity, max accel, and
max halt velocity from the toolhead class instead of having the
toolhead class call into the kinematic classes with those values.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-03 15:45:04 -04:00
Kevin O'Connor
0d13834293 gcode: Fix error that could cause commands to be processed out of order
Commit d0932009 changed the way command handling was performed, and
commit 95950949 fixed a defect in that commit.  Unfortunately, the fix
was incomplete.

If multiple commands were sent to Klippy without waiting for an "ok"
response from Klippy, then it was possible for those additional
commands to be queued and processed after subsequent commands.  This
would result in commands being processed out of order.

Fix this by only reregistering the input fd in the greenlet that
performs the unregistration of the fd.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-02 12:05:51 -04:00
Kevin O'Connor
ac53806e04 gcode: Add an ECHO command for debugging purposes
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-09-02 12:05:51 -04:00
Kevin O'Connor
026b9c336c stepcompress: Minor performance tweaks for rpi
Invert the if conditional in queue_append() and change the order of
reads in minmax_point() - gcc on the rpi seems to do generate better
code this way.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-31 10:17:01 -04:00
Kevin O'Connor
60c77fff06 docs: Update Code_Overview.md - step compress queue no longer 64 bit
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-31 10:07:17 -04:00
Kevin O'Connor
588ecbe868 stepcompress: Use addition instead of multiplication on queue add
Replace multiplication with addition where possible.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-31 02:15:32 -04:00
Kevin O'Connor
e05c635489 stepcompreses: Change the step queue to use 32bit integers
The RaspberryPi processor implements 'double to int32' conversions
much faster than 'double to int64' conversions.  Rework the code so
that steps stored in the queue are always a small offset from the last
sent step time.  (In the unlikely event that a step is far from the
last step time, then the queue is flushed to maintain this invariant.)

This simplifies the step compression code as well - it no longer needs
to check for integer overflows.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-31 00:27:43 -04:00
Kevin O'Connor
f5cc355044 stepcompress: Refactor queue insertion to use a cursor
Create an insertion "cursor" for adding items to the step compression
queue.  This makes the calling code simpler and it makes it easier to
update the queue memory management in the future.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-31 00:15:03 -04:00
Kevin O'Connor
78f4c25a14 homing: Add a small delay before each homing operation
The homing operation can be cpu intensive for the host software.  Add
a small (250ms) delay before homing so that the host has additional
time to process the command before it is due on the mcu.  This is
intended to work around some reports of "timer too close" errors
during Z homing on RPi2 hosts and printers with high precision Z
positioning.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-29 18:02:36 -04:00
Kevin O'Connor
002dc0dfaf stepper: Adjust homing_speed so that it's an even number of ticks per step
Adjust the configured homing speed so that it always results in a
speed that is an even number of mcu ticks per step.  This ensures that
the code can always get good step compression during homing, which is
important as the entire homing operation must be able to fit within
the mcu's move queue.  This fixes some "move queue empty" mcu shutdown
errors that could occur when the Z step distance was an unusual size.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-29 18:00:17 -04:00
Kevin O'Connor
68d6788413 mcu: Add get_mcu() call to the mcu oid objects
Allow external code to obtain the mcu object that controls a pin setup
with setup_pin().  Also, don't bother defining print_to_mcu_time() and
system_to_mcu_time() on each pin object as they can be obtained via
the new get_mcu() method.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-29 17:59:27 -04:00
Kevin O'Connor
c7c551369f mcu: Fix bug causing corexy to not work (introduced in 9d75c3b0)
Commit 9d75c3b0 changed the order of allocation for mcu oid integer
ids.  However, the stepper oids must always be allocated before
endstop oids so that corexy can register multiple steppers on a single
endstop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-29 17:59:15 -04:00
Kevin O'Connor
0c2919b534 klippy: Move restart logic into Printer() class
Move the restart logic out of main() and into Printer.run().  This
simplifies the code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:21 -04:00
Kevin O'Connor
d8c75fc608 klippy: Rename internal functions so that they are prefaced with "_"
Preface the internal functions to make it more clear which functions
are interfaces to external code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:21 -04:00
Kevin O'Connor
a42cb4fecf toolhead: Avoid directly accessing the printer.mcu field
Lookup the mcu object from the printer objects and store it locally in
the toolhead class.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:21 -04:00
Kevin O'Connor
68ba3d5106 mcu: Drop support for TICKS() expansion in mcu config commands
It's no longer necessary to use the TICKS() hack as the config
commands are now all generated after the mcu speed is known.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:21 -04:00
Kevin O'Connor
80dc1dfcc1 docs: Remove documentation for "custom" command blocks
It should no longer be necessary to configure "custom" commands during
mcu setup.  The ad5206 and static_digital_output config sections
should provide similar functionality.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:21 -04:00
Kevin O'Connor
931811ab59 chipmisc: Add support for configuring ad5206 digipots
Support an "ad5206" config section so that one can configure the
digipots found on Reprap "RAMBo" boards.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:21 -04:00
Kevin O'Connor
9d75c3b0ca chipmisc: Add support for statically configured output pins
Allow digital and PWM output pins to be setup via new config
sections.  This makes it easier to setup pin configurations.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-26 18:27:20 -04:00
Kevin O'Connor
6ab8567d51 mcu: Track stepqueues separately from steppers
The MCU() class needs to track the stepqueues so that it can
initialize the steppersync object.  Track the stepqueues directly
instead of via the list of steppers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-25 20:45:54 -04:00
Kevin O'Connor
c727ed3592 mcu: Track oids separately from objects requiring a build_config() callback
Track the oid count separately from the configurable object count -
this way it is possible to have internal objects that don't require an
oid in the mcu.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-25 20:44:51 -04:00
Kevin O'Connor
c72ca983ba mcu: Eliminate "init callback" phase during connect
It's not necessary to register and execute "init callbacks" when
configuring the mcu.  Instead, have each mcu object produce its init
messages in the build_config() callback.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-25 20:41:09 -04:00
Kevin O'Connor
ec7990796a pins: Support registering arbitrary chips that supply configurable pins
Allow multiple chips to provide pin mappings (not just the main mcu
chip).  Move the pin parsing from the mcu.py code to pins.py and
support mapping from pin descriptions to their corresponding chips and
parameters.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-25 20:38:55 -04:00
Kevin O'Connor
268834e4ae klippy: Store printer startup parameters in new "start_args" dictionary
Store pertinent information from the software startup in a dictionary
that the various printer components can access instead of in
individual variables in the Printer() class.  This makes it easier to
add future command-line options.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-25 19:27:05 -04:00
Kevin O'Connor
b80c488d36 heater: Another minor cleanup to Steinhart-Hart math
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-20 12:42:50 -04:00
Kevin O'Connor
f25cb33367 heater: Minor cleanup to Steinhart-Hart math
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-18 13:28:04 -04:00
Kevin O'Connor
4b5f3bec4b heater: Add support for a generic "NTC 100K beta 3950" thermistor
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-17 15:12:51 -04:00
Kevin O'Connor
1f4c6443ef heater: Calibrate thermistor directly from temperature and resistance
Store the underlying temperature and resistance values instead of the
Steinhart-Hart coefficents obtained from them.  This makes it easier
to add new thermistors.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-17 13:26:51 -04:00
Kevin O'Connor
0adea120cd pru: Compile the irq_poll() function with -O2 optimization
Compile the PRU binary with -Os optimization, but request that the
timer dispatch code be compiled with -O2 optimization.  This improves
the performance of timers slightly.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-15 11:05:30 -04:00
Kevin O'Connor
71bb7acb8e pru: Compile with -Os instead of -O2
The gcc -Os option significantly reduces the size of the PRU binary
and it has little impact on performance.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-14 21:08:28 -04:00
Kevin O'Connor
4b5109c1b9 serialqueue: Make sure fds are in non-blocking mode
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-14 21:08:28 -04:00
Kevin O'Connor
085817d332 serialhdl: Sometimes we get an IOError when serial port not found
Catch IOError when opening the serial port.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-14 21:07:26 -04:00
Kevin O'Connor
f8bd8b97be command: Don't pass max_size to command_encodef()
The command_encodef() can read the max_size parameter directly from
the 'struct command_encoder' passed into it.  Also, there is no need
to check that a message will fit in a buffer if the buffer is declared
to be MESSAGE_MAX in size.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-14 18:32:15 -04:00
Kevin O'Connor
f3da473285 docs: Update Code_Overview.md with PRU and command_dispatch() changes
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-11 12:06:19 -04:00
Kevin O'Connor
f0f4ab7abe docs: Update benchmarks in Features document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-11 11:40:54 -04:00
Kevin O'Connor
d8225642fa stepper: Revert f8b0c884
Go back to scheduling the unstep time instead of busy waiting in the
timer dispatch.  With the unstep time increased to 2us, it no longer
makes sense to spin while waiting for the unstep.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-11 10:36:02 -04:00
Kevin O'Connor
8ebba6d27a avr: Make sure timer_high and timer_event() stay in sync
Schedule the next wakeup time of timer_event() using timer_high.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-11 09:32:06 -04:00
Kevin O'Connor
1051a52755 timer_irq: Rework timer irq handler to check for tasks pending
Allow timer_dispatch_many() to run for extended periods if there are
no tasks pending.  This reduces the amount of lost cpu time spent
entering and exiting the irq handler.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-09 21:08:40 -04:00
Kevin O'Connor
5583b050a0 graphstats: Increase maximum expected task duration
Now that tasks are only run when needed it's common for there to be a
larger variation in task execution time.  When graphing load, consider
a 99-percentile task duration of 2.5ms to be 100% loaded (up from
1ms).

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-09 19:12:27 -04:00
Kevin O'Connor
a38082016d sched: Reduce the amount of time irqs are disabled in sleep check
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-09 12:55:44 -04:00
Kevin O'Connor
156e9b7556 sched: Write out a message on startup
Send a "startup" message after completing the mcu init functions.
This may help detect mcu reboots during debugging.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
5e6acf7dbc console: Add support for a STATS command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
58811b5c44 console: Add LIST command that shows available commands and variables
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
86a762b2b7 console: Add a HELP command
Show available features at startup.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
f886212b44 avr: Rework timer irq handler to check for tasks pending
Allow the timer dispatch irq handler to run for extended periods if
there are no tasks pending.  This reduces the amount of lost cpu time
spent entering and exiting the irq handler.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
2c272f99a3 sched: Implement generic sleep mechanism based on tasks pending
Track when tasks are pending and spin in irq_wait() when no tasks are
pending.  This improves the mechanism for sleeping the processor -
it's simpler for the board specific code and it reduces the
possibility of the processor sleeping when tasks are busy.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
a9982beacf sched: Introduce sched_wake_tasks() function to wake up tasks
Add function to indicate when tasks need to be run.  This will allow
the scheduler code to know if there are any tasks that need to be
processed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
e9d2ec7c41 avr: Tune the low-level timer entry and exit heuristics
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
78982ebb51 avr: Implement internal avr specific timer to handle 16bit overflows
Don't rely on the generic scheduler code to always have a timer no
more than 1ms in the future.  Instead, create an avr specific timer
that will be called every 0x8000 ticks.  This simplifies the generic
code and it reduces the amount of code that needs to be run every
millisecond.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:28 -04:00
Kevin O'Connor
6a63c27542 sched: Support adding timers to the start of timer_list
If sched_add_timer() is called on a timer that would make it the new
head of the list, then add it and signal the board code that the timer
should be rescheduled.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:27 -04:00
Kevin O'Connor
62f77f6bc5 sched: Don't count milliseconds in the periodic timer
It's not necessary to keep a millisecond counter.  Replace the two
users of sched_check_periodic() with explicit task wakeup flags.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:27 -04:00
Kevin O'Connor
88a10fb31c sam3x8e: Fix watchdog timeout calculation
Fix error causing the watchdog to be set to an ~4ms timeout instead of
500ms.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-08 00:27:27 -04:00
Kevin O'Connor
e12527b895 avr: Move prescaler and sleep initialization from timer.c to main.c
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-07 19:39:57 -04:00
Kevin O'Connor
114c8c5b6d avr: Enable watchdog code even on simulavr
The simulavr simulator will warn when writing to the watchdog
registers, but running code closer to what real hardware runs is worth
a few extra warnings.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-07 19:39:57 -04:00
Kevin O'Connor
d50f4e23e0 pwmcmds: Update event prototypes to use uint_fast8_t
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-06 20:24:22 -04:00
Kevin O'Connor
dca0fc91ea pru: Improve comments in pru0.c
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-08-02 11:02:45 -04:00
Kevin O'Connor
981c53682f stepper: Use a sane default for homing_positive_dir
Use the endstop position to determine a sane default for
homing_positive_dir.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-24 14:31:46 -04:00
Kevin O'Connor
143b7cccf4 stepper: Separate out homing code to its own PrinterHomingStepper class
Keep the homing code separate from the main stepper class.  This makes
it easier to verify the correct config parameters are provided.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-24 13:54:46 -04:00
Kevin O'Connor
8ce042bf04 config: Add additional pin definitions to ramps and rambo configs
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-24 13:18:45 -04:00
Kevin O'Connor
85a1e1118f config: Change default pins defined in example.cfg to use RAMPS pins
Change the example.cfg file to use the pins of a RAMPS config as that
is a very common setup.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-24 13:05:00 -04:00
Kevin O'Connor
51baeb3c2c config: Reduce max_z_velocity in example-delta.cfg to 150
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-24 11:47:25 -04:00
Kevin O'Connor
959a20888c serialhdl: Dump serial stats in dump_debug()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-24 11:43:54 -04:00
Kevin O'Connor
7bf0ec2fe7 gcode: Don't wait for moves to finish if both debug input and output
Don't wait for moves to finish if the output is going to a debug file.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-23 21:32:26 -04:00
Kevin O'Connor
c6231a16e3 serialqueue: Improve limit on number of in-flight bytes
Instead of limiting the amount of non-acked messages to 50ms, limit
the amount to one round-trip-time.  This should make it less likely
that the mcu will be overloaded and it should make retransmits faster.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-23 20:47:08 -04:00
Kevin O'Connor
a619aacfc6 serialqueue: Further retransmit timing fixes
The first message always has a sync byte with it, so its size should
be one larger.  Also, the idle_time should always be the minimum time
that the message could be received, so it should always be reset to
eventtime on a retransmit.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-23 19:32:42 -04:00
Kevin O'Connor
d469db84ee serialqueue: Allow a second nak after a retransmit
If a nak message causes a retransmission then also accept a second nak
message as long as it is for a sequence greater than the first nak.
This should allow faster retransmits when there are multiple
transmission errors in a small time period.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-21 23:49:44 -04:00
Kevin O'Connor
4655a6bfef serialqueue: Fix off-by-one error in retransmit sequence number tracking
Track the sequence number of the message last retransmitted (not the
sequence number of the next message to be transmitted).  This fixes a
small possibility of a valid nak not being honored.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-21 23:43:48 -04:00
Kevin O'Connor
61325c0a14 serialqueue: Improve timing of multiple retransmits
If a retransmit is triggered by a nak, then it is not necessary to
increase the rto.  The next retransmit time should be based on the
expected reception of the first retransmitted message, not the last.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-21 21:26:14 -04:00
Kevin O'Connor
7faa5fe233 gcode: Improve end-of-file handling when input is a debug file
Wait for any pending moves to be fully handled before exiting.  Make
sure the wait is done inside the "self.is_processing_data" check to
avoid infinite recursion.  Don't keep reading from the file while
waiting to exit.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-21 21:22:12 -04:00
Kevin O'Connor
19090bdd5b graphstats: Fix so that older files (predating mcu_awake) still work
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-21 14:19:59 -04:00
Kevin O'Connor
4a6254fac3 build: Allow boards to disable digital input/output support
Allow the micro-controller code to be built without support for
regular gpio pins.  In this case, the code for endstops, steppers, and
gpiocmds will be disabled.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-20 10:44:31 -04:00
Kevin O'Connor
649d26e093 basecmd: Move low-level alloc code into basecmd.c
Implement new dynmem_start() and dynmem_end() functions instead of
alloc_chunk() and alloc_chunks() in the board code.  This simplifies
the board code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-20 10:44:31 -04:00
Kevin O'Connor
2ee42997e4 docs: Update Kinematics.md with regards to stepper torque limits
It is not necessary to limit stepper acceleration - only the limiting
of stepper torque is important.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-19 19:09:14 -04:00
Kevin O'Connor
17a3e25036 docs: Improve description of delta stepper acceleration limits
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-19 14:14:01 -04:00
Kevin O'Connor
c4b8d3ea8b graphstats: Support graphing "mcu_awake" statistic
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-19 14:14:01 -04:00
Kevin O'Connor
118fd21cb8 irq: Support sleeping when mcu is idle
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-17 15:02:43 -04:00
Kevin O'Connor
969485c754 fan: Add support for heater_fan objects
Add support for fans designed to cool the components of an extruder or
heater.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-17 11:35:52 -04:00
Kevin O'Connor
519e81d0fa mcu: Support converting from a system time to an mcu time
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-17 11:35:48 -04:00
Kevin O'Connor
12ca45a264 gcode: Log g-code error responses
Be sure to log g-code errors even if debug logging is not enabled.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-17 11:24:15 -04:00
Kevin O'Connor
3ac60b31a2 pru: Move peripheral init from pru0 to pru1
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-17 11:16:55 -04:00
Kevin O'Connor
c105ff1c51 pru: Move ADC code from gpio.c to new file adc.c
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-12 23:03:14 -04:00
Kevin O'Connor
ae9bc93ccc avr: Fix readl() typo in serial.c
The code should have used a readb() call instead of readl().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-12 23:03:12 -04:00
Kevin O'Connor
afc665d7c8 config: Update PRU based configs to use the correct serial device
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-06 12:04:26 -04:00
Kevin O'Connor
2d173f51b1 pru: Add documentation and install scripts for running on the PRU
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-05 14:21:32 -04:00
Kevin O'Connor
b32ba3727b pru: Add support for "make flash" rule
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-05 12:50:54 -04:00
Kevin O'Connor
5793271308 fan: Support setting a max_power attribute for the print cooling fan
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-05 10:43:34 -04:00
Kevin O'Connor
09140a51d5 sched: Pass shutdown reason code via longjmp() parameter
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-04 12:49:58 -04:00
Kevin O'Connor
cf662b842b msgproto: Catch exceptions during identify data parsing
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-04 12:49:58 -04:00
Kevin O'Connor
0ac518040b msgproto: Export static_strings from mcu to host as a dictionary
Export the static strings as a dictionary instead of as a list.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-07-02 14:11:10 -04:00
Kevin O'Connor
067fac05a8 serialqueue: Rename clock estimation variable names
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-30 20:15:36 -04:00
Kevin O'Connor
c7d0358c41 serialhdl: Rework mcu clock synchronization
The existing clock synchronization code has two flaws: intermittent
transmission latency during get_status requests can cause the
estimated clock to be too low, and the estimated clock calculation did
not take into account possible clock drift between samples.  The
former could potentially lead to "Timer too close" errors and the
latter could potentially lead to "Move queue empty" errors.

Rework the code to avoid the above problems.  It's not necessary to
estimate the micro-controller clock as an excellent estimate is
reported by the micro-controller (via the CLOCK_FREQ constant).
Account for a small drift from the reported value, and check on each
sample if the drift exceeds the expected limits.  With a good starting
estimated clock, only the offset needs to be calculated.  Use previous
offsets (and the estimated clock) in calculation of new offsets to
avoid intermittent latency from badly skewing the results.  Finally,
add an additional time offset of one millisecond to account for any
minor inaccuracies.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-30 20:15:36 -04:00
Kevin O'Connor
c957e4ba86 serialqueue: Clarify code that associates sent messages to received messages
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-30 20:15:36 -04:00
Kevin O'Connor
c8dca0a56c pru: Use a pointer when working with send_data array items
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-30 19:54:40 -04:00
Kevin O'Connor
da3569c490 pru: Add hack to shutdown the PRU from a simple command request
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-30 19:54:33 -04:00
Kevin O'Connor
e8356afa26 pru: Rework command processing so that most of it is done on pru0
Change the command dispatch and response generation so that most of
the work is done on pru0 instead of pru1.  This allows more code to
fit into the limited space on pru1.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-30 19:53:04 -04:00
Kevin O'Connor
c1bd628ce5 command: Directly call command_sendf() for ack/nak messages
Don't use the sendf() macro for ack and nak messages - directly call
the command_sendf() code instead.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:59 -04:00
Kevin O'Connor
849096d5f3 sam3x8e: Integrate serial console functions
Now that console_get_input(), console_pop_input(),
console_get_output() and console_push_output() are local functions,
integrate them into their callers.  This simplifies the code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:59 -04:00
Kevin O'Connor
e681369a1a avr: Integrate usb serial console functions
Now that console_get_input(), console_pop_input(),
console_get_output() and console_push_output() are local functions,
integrate them into their callers.  This simplifies the code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:59 -04:00
Kevin O'Connor
faa29c8062 avr: Integrate serial console functions
Now that console_get_input(), console_pop_input(),
console_get_output() and console_push_output() are local functions,
integrate them into their callers.  This simplifies the code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:58 -04:00
Kevin O'Connor
44f2a2a952 command: Move low-level sendf transmission into board code
Export a new console_sendf() function from the board code instead of
console_get_output() and console_push_output().  This enables more
flexibility in how the board specific code produces output.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:58 -04:00
Kevin O'Connor
292453d306 command: Move command_task() to board specific code
Move the command_task() code from the generic code to the board
specific code.  This enables more flexibility in how the board
specific code processes input.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:58 -04:00
Kevin O'Connor
1ae78d08e9 command: Encode MESSAGE_MIN in command_parser->max_size
Add the message minimum into the stored constant so it does not need
to be added at run-time.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:58 -04:00
Kevin O'Connor
1c3cbe9456 command: Refactor message block generation
Separate out the buffer management, message encoding, and message
framing code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:58 -04:00
Kevin O'Connor
88f4c38dca command: Refactor the command reading task
Refactor the code so that message block framing, command parsing, and
command dispatch are distinct.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-29 13:33:58 -04:00
Kevin O'Connor
b7b368a1ed build: Default to python2 in the Makefile
Set PYTHON=python2 instead of python as some systems point python to
python3.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-28 10:52:05 -04:00
Kevin O'Connor
d2fafbdd9e build: Request python2 for all directly executed python binaries
Some systems point python to python3 instead of python2 - explicitly
request python2 to avoid conflicts.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-27 20:26:02 -04:00
Kevin O'Connor
d981973096 heater: Fix auto-tune code
Make sure the heater.target_temp is set during the auto-tune test so
that the heater.set_pwm() command will allow the heater to be turned
on.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-22 12:09:55 -04:00
Kevin O'Connor
b310501970 sam3x8e: Use readl/writel instead of readb/writeb() in serial.c
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-22 10:51:49 -04:00
Kevin O'Connor
e92ce565dd console: Support new artificial DELAY command
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-22 10:51:49 -04:00
Kevin O'Connor
da4f2c5ea0 checkstack: Continue to accumulate stack usage on misc instructions
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-22 10:51:49 -04:00
Kevin O'Connor
bd48c3a083 pru: Remove unnecessary barrier() calls
The writel() call already implements a barrier() internally.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-16 14:26:37 -04:00
Kevin O'Connor
ba58e0446d install-octopi: Add python-virtualdev to package list
Add python-virtualdev to the list of system packages to be installed -
it's usually already installed, but it doesn't hurt to add it to the
list in case it isn't already installed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-15 10:41:21 -04:00
Kevin O'Connor
c03b4921c3 klippy: Make sure to always sleep before retrying next stats() call
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-15 09:37:57 -04:00
Kevin O'Connor
c60e4aceed stepper: Increase the step delay time from 1us to 2us
Increase the step delay time so that it works with the common DRV8825
stepper drivers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-13 11:53:10 -04:00
Kevin O'Connor
156de2e4c2 delta: Fix support for different endstop_position settings on each stepper
The endstop_position is intended to support different values for each
stepper so that the individual tower heights can be configured.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-11 12:48:51 -04:00
Kevin O'Connor
959509496a gcode: Fix regression causing lost asynchronous commands
Commit d0932009 introduced an error that could cause lost input in
cases where the sender did not wait for an "ok" message before sending
the next command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-11 12:42:11 -04:00
Kevin O'Connor
8419e152bb klippy: Remove some obscure python2 dependencies
Don't modify dictionaries while iterating them and be careful to use
// when doing an integer divide.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-10 00:12:14 -04:00
Kevin O'Connor
1bc3e0a678 klippy: Use newer "except XYZError as e" python syntax
Use the newer syntax for python exceptions.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-10 00:08:06 -04:00
Kevin O'Connor
d093200966 gcode: Support running arbitrary gcode on extruder change
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-09 18:55:33 -04:00
Kevin O'Connor
72dc21fb1a gcode: Support for querying and setting multiple extruder heaters
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-09 18:55:30 -04:00
Kevin O'Connor
24b8f4ebc1 extruder: Add initial support for multi-extruders
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-09 18:54:38 -04:00
Kevin O'Connor
136dccbcdf klippy: Allow each module to define their config sections
Create add_printer_objects() functions in the fan, heater, extruder,
and toolhead modules.  Create the necessary printer component objects
from this call instead of placing the code directly in klippy.py.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-09 18:54:34 -04:00
Kevin O'Connor
d0e6a0928b pins: Fix typo in at90usb1286 support so PF0-7 pins are defined
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-09 18:46:07 -04:00
Kevin O'Connor
46846d4297 avr: Enable CLEAR_PRESCALER by default on at90usb1286
It appears this option is commonly needed on the at90usb1286 avr chip
(the printrboard requires it), so default it on.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-09 18:42:40 -04:00
Kevin O'Connor
01ee9e16c5 klippy: Prefer python dictionary comprehension to dict() call
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-06 12:35:13 -04:00
Kevin O'Connor
38411fd2e7 delta: Add support for specifying the angle each tower is at
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-05 18:05:45 -04:00
Kevin O'Connor
b8094de129 avr: Support using serial instead of usb on AT90USB1286
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-06-05 12:30:49 -04:00
Kevin O'Connor
73207a12ba avr: Allow atmega328 to select a cpu speed of 20Mhz
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-29 14:24:18 -04:00
Kevin O'Connor
3af87e1c42 avr: Add SIMULAVR build option; don't show WATCHDOG or SERIAL_BAUD_U2X
Add a CONFIG_SIMULAVR option to the Kbuild menus and don't directly
prompt users for CONFIG_WATCHDOG or CONFIG_SERIAL_BAUD_U2X.  The only
reason to disable these options would be if one were running on
simulavr.  This simplifies the user visible menu options.

Also, only show CONFIG_CLEAR_PRESCALER for at90usb1286 chips.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-28 11:04:59 -04:00
Kevin O'Connor
d2547ce6b0 avr: Add support for atmega328 chip
The atmega328 is basically the same as the atmega168 - it just adds
some additional memory.  Allow the chip to be selected during the
build.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-28 10:45:32 -04:00
Kevin O'Connor
7e3d7e071f avr: Reorder Kconfig entries so that atmega2560 at 16mhz is default
Reorder the MCU list so that newer chips are at the top of the list.
This causes the very popular atmega2560 to be the default chip
selected.

Reorder the frequency list so that higher frequencies are at the top
of the list.  Restrict the 20Mhz frequency to only chips that support
that speed.  This causes the popular 16Mhz frequency to be the default
speed on AVR.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-28 09:59:51 -04:00
Kevin O'Connor
d4bed025ed command: Store the command parsing information directly in array
Instead of defining an array of pointers, just define the array
directly.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-26 13:25:51 -04:00
Kevin O'Connor
a82e949c00 build: Use compile_time_request system for init, tasks, and shutdown
Avoid using linker magic to define the init, task, and shutdown
functions.  Instead, use the compile_time_request system.  This
simplifies the build and produces more efficient code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-26 12:39:34 -04:00
Kevin O'Connor
ca9756413f sched: Allow shutdown_reason to be uint8
Store the shutdown_reason code in an 8-bit integer - this produces
better code on AVR.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-26 12:32:05 -04:00
Kevin O'Connor
b9940f0e0d build: Avoid linker magic in compile_time_request.c unique id generation
Avoid generating unique ids via memory locations and linker scripts.
Instead, generate them using code produced by buildcommands.py.
Utilize gcc's ability to perform static string comparisons at compile
time to produce a unique id for each unique string.

This fixes a build failure on ARM introduced in 142b92b8.  It also
reduces the complexity of the build.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-26 12:32:02 -04:00
Kevin O'Connor
f91a49c65d docs: Note how to handle odd corner in Pressure_Advance.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-25 13:39:16 -04:00
Kevin O'Connor
4b8ad3fc03 docs: Add a prerequisites section to Pressure_advance.md
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-22 12:32:20 -04:00
Kevin O'Connor
e8aabbb40b docs: Add Todo item for supporting custom fan and pin config sections
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-22 11:55:41 -04:00
Kevin O'Connor
02a5fa2c79 config: Make it clear the "fan" section represents the print cooling fan
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-21 11:52:02 -04:00
Kevin O'Connor
944c121a00 config: Add periods to end of sentences in example configs
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-21 11:51:58 -04:00
Kevin O'Connor
c9b6662138 pru: Add support for ADC input
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-17 19:46:12 -04:00
Kevin O'Connor
b85755c0ff pru: Move communication code to second PRU
Perform input and output in the second PRU so that more space is
available in the primary PRU.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-17 10:46:38 -04:00
Kevin O'Connor
b6f24e78ac pyhelper: Fix GETHEX() macro used in dump_string() debugging
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-17 09:57:09 -04:00
Kevin O'Connor
fc24aa041b pins: Add pin mappings for Beaglebone boards
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 15:15:52 -04:00
Kevin O'Connor
c9b44b5bb6 serialhdl: Support working with pseudo serial devices
Support working with devices that aren't really serial ports and thus
do not have a baud rate.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 15:15:52 -04:00
Kevin O'Connor
2255176228 pru: Initial support for the Beaglebone PRU
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 15:15:52 -04:00
Kevin O'Connor
ccaa25eaa5 pru: Add initial pru_rpmsg library code for Beaglebone PRU
Add external code for using RPMsg on the Beaglebone PRU.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 15:00:52 -04:00
Kevin O'Connor
969ee4c8f9 irq: Add an irq_poll() stub for board code
Allow the board specific code to run checks prior to running each
task.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 15:00:45 -04:00
Kevin O'Connor
c35278e217 build: Avoid using noinline in common code
It's not necessary to use noinline for parsef() and stop_steppers().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
039d3f0523 stepper: It is not necessary to ensure gpio_out_write value is 0 or 1
The gpio_out_write() and gpio_out_setup() calls will check for zero
and non-zero, so it is not necessary to explicitly convert to 0/1 in
the stepper.c code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
d56f8407a5 debugcmds: Move debugging commands from basecmd.c to new file
Move the implementation of debug commands to their own file.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
142b92b883 command: Use "i" instead of "m" constraint in _DECL_REQUEST_ID
On some architectures, gcc will allocate a register for inline
assembler with an "m" constraint.  Use "i" to avoid that.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
c292006421 gpiocmds: Change MAX_SOFT_PWM from 255 to 256
Change the range of values used for software PWM to avoid doing an
integer division in the main code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
5c4cc0d646 pwmcmds: Export the maximum PWM value
Instead of assuming the maximum PWM value is 255, export a constant
from the firmware to the host with the maximum value.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
a361b92184 gpio: Fix off-by-one in declaration of ADC_MAX
The maximum value for the ADC is 1023 for 10bit samples and 4095 for
12bit samples.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:59 -04:00
Kevin O'Connor
37572bc217 command: Only implement 16bit signed conversion on AVR
On regular 32bit machines there is no need to implement explicit
signed conversion on 16bit integers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:04 -04:00
Kevin O'Connor
233adfe660 build: Add __visible to variables in compile_time_request.c
Add __visible to generated code in compile_time_request.c so that the
main code can be compiled with -fwhole-program.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:02:04 -04:00
Kevin O'Connor
450c14b286 build: Rename makefile CFLAGS-y to CFLAGS and LDFLAGS-y to CFLAGS_klipper.elf
Rename some makefile variables.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-15 14:01:56 -04:00
Kevin O'Connor
33dfc386c9 avr: Merge misc.c into main.c
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-11 13:56:21 -04:00
Kevin O'Connor
f331936969 basecmd: Avoid calling malloc() from main code
Introduce a new board function alloc_chunk() to allocate dynamic
memory.  This allows the board code to implement memory allocations
without using the standard malloc() interface.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-11 13:56:21 -04:00
Kevin O'Connor
8f1d0c2a7c docs: Note version 0.4.0 release
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-03 14:32:36 -04:00
Kevin O'Connor
02549c9299 docs: Make it clear a RESTART is likely needed in Installation document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-03 11:15:27 -04:00
Kevin O'Connor
98f2adbcb5 extruder: Rework maximum retraction check
On a retract move (which are common during "wipe" operations), treat
the move as if it were an extrude only move.  It's valid for a retract
move to reverse more filament then it would be practical to push.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-02 08:57:38 -04:00
Kevin O'Connor
c9d21574d8 gcode: Check for invalid speeds
Raise an error if the move speed is set to a zero or negative value.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-02 07:54:48 -04:00
Kevin O'Connor
253517096e extruder: Extend over extrusion checks to retractions
Ensure a move with a retraction (negative extrude) is also checked for
sane extrusion rates.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-02 07:54:48 -04:00
Kevin O'Connor
0fa35254c6 msgproto: Wrap strings passed via output() in repr()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-02 07:54:48 -04:00
Kevin O'Connor
fc9fb7473c gcode: Don't report an error if turning off an unknown fan or heater
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-01 15:02:27 -04:00
Kevin O'Connor
31ca2331d2 queuelogger: Add critical information to each logfile on rollover
When the log file does a rollover, start the top of the log with
critical system information (eg, software versions).

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-01 14:48:44 -04:00
Kevin O'Connor
b5062a07d1 docs: Recommend users stop klipper before flashing the micro-controller
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-01 12:08:45 -04:00
Kevin O'Connor
4112007314 docs: Reword XY+Z delta moves in Kinematics
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-01 11:58:32 -04:00
Kevin O'Connor
a3162b17d9 docs: Use only single space at start of new sentence
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-01 11:58:32 -04:00
Kevin O'Connor
e177d4f70d docs: Reword smoothed look-ahead description in Kinematics
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-05-01 11:58:32 -04:00
Kevin O'Connor
631b0e6c37 docs: Improve wording of slow lookahead description
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 16:05:26 -04:00
Kevin O'Connor
a7f339ad1c docs: Improve documentation for those starting in docs/
Those that reach Klipper via github may jump directly to the docs/
directory in search of documentation.  Add README.md and rework
Overview.md with that in mind.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 16:05:26 -04:00
Kevin O'Connor
c1c0b2dd38 docs: Avoid using "firmware" in the documentation
The term "firmware" is ambiguous - it could refer to the entire
project (host and micro-controller software) or to just the
micro-controller software.  Avoid the term in the documentation.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 15:59:33 -04:00
Kevin O'Connor
d7a1111955 docs: Add backticks around commands in Firmware Commands
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 12:10:38 -04:00
Kevin O'Connor
d73340474b docs: Use "look-ahead" instead of "lookahead" in Code Overview
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 12:02:15 -04:00
Kevin O'Connor
4f7237de44 docs: Update Firmware Commands document with an integer example
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 12:00:10 -04:00
Kevin O'Connor
4096745a58 docs: Use a markdown link to docs/prints/square.stl
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 12:00:09 -04:00
Kevin O'Connor
a97e074022 docs: Kinematics document image updates
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 12:00:09 -04:00
Kevin O'Connor
917c6aa94a docs: Todo updates
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-27 09:52:38 -04:00
Kevin O'Connor
05bd6fda7e config: Add a sample config file for RAMBo boards
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-26 11:51:40 -04:00
Kevin O'Connor
7c78de989d config: Add a sample config file for RAMPS boards
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-26 11:48:35 -04:00
Kevin O'Connor
35a6d9ba87 gcode: Sort the order of commands in HELP
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-26 10:44:22 -04:00
Kevin O'Connor
c63754fc32 gcode: Limit build_handlers() method to just building available commands
The set_printer_ready() can be called from a background thread on a
shutdown event, so don't try to lookup the printer components in that
case.  Simplify build_handlers() so that it no longer tests for
components being available - test for component availability in the
command handlers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-26 10:31:58 -04:00
Kevin O'Connor
ccb93068fe msgproto: Rework dump() so it also works with params
Always call the regular .parse() method for each message type during
dump() - add a new .format_params() method for dumping a verbose
representation of the parsed message.  This allows the new
format_params() to also be used with data already parsed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-25 13:58:13 -04:00
Kevin O'Connor
a6fe355801 console: Automatically convert float values to int during evaluation
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-25 12:26:13 -04:00
Kevin O'Connor
fe11c3e348 console: Use stdout.write() instead of print
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-25 12:26:13 -04:00
Kevin O'Connor
56d4422d31 docs: Reword alternate linux machine in installation instructions
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-24 09:39:40 -04:00
Kevin O'Connor
e507848a8f docs: Remove "experimental" from descriptions
The Klipper software has progressed to the point where it does not
need to be described as "experimental" software.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-24 09:31:39 -04:00
Kevin O'Connor
70599667cb docs: Installation updates
Recommend using 'make flash' and clean up the octoprint instructions.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-24 09:21:21 -04:00
Kevin O'Connor
1878da228d build: Add workaround to suppress broken avr-gcc "misspelled" warnings
Detect avr gcc v4.8.1 and then disable warnings during the klipper.o
linking to suppress bogus "misspelled signal handler" warnings.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-24 08:54:10 -04:00
Kevin O'Connor
37865d69a2 basecmd: Add debugging commands for testing communication
Add "debug_ping" and "debug_nop" testing commands.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-23 13:37:49 -04:00
Kevin O'Connor
83eba902a3 build: Support makefile rule with default flashing commands
Support a "make flash FLASH_DEVICE=/dev/ttyACM0" rule with the default
commands for flashing a device.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-21 11:01:07 -04:00
Kevin O'Connor
ec805aee2e scripts: Add octopi installation scripts
Add a system startup script so that Klipper can automatically start at
boot time.  Create an installation script that will install the system
dependencies and the startup script.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-21 10:14:27 -04:00
Kevin O'Connor
167b18b58f gcode: Ignore M21 command
No need to recommend users disable "SD card support" in octoprint -
instead, just ignore the M21 command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-20 10:11:10 -04:00
Kevin O'Connor
4b1a530330 stepcompress: Simplify delta Z only move calculations
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-20 00:56:18 -04:00
Kevin O'Connor
19ffaa9ff0 docs: Reword parts of the pressure advance kinematics description.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-19 20:48:23 -04:00
Kevin O'Connor
0f5167a407 docs: Misc image updates
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-19 19:55:50 -04:00
Kevin O'Connor
563ab5caa5 docs: Add info on delta acceleration limits
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-19 19:54:48 -04:00
Kevin O'Connor
db5b5f121c docs: Add initial Pressure Advance tuning document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-19 16:02:11 -04:00
Kevin O'Connor
1f417a8441 docs: Update Todo - initial kinematic document written
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-15 22:59:34 -04:00
Kevin O'Connor
b74b09ea7a docs: Updates to Features document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-15 22:52:36 -04:00
Kevin O'Connor
2cce67ad84 docs: Add initial Kinematics document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-15 22:26:03 -04:00
Kevin O'Connor
2cb935c300 mcu: No need to log mcu_stats debugging
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-14 10:43:14 -04:00
Kevin O'Connor
b9623c1128 klippy: Don't log stats when the printer is idle
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-14 10:38:37 -04:00
Kevin O'Connor
7a386cff7d mcu: Change "Synchronizing mcu clock" logging to debug
Always log the last synchronized clock during a shutdown event, and
use debug level for normal reports.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-14 10:06:11 -04:00
Kevin O'Connor
839725e3c5 queuelogger: Automatically roll log file
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-14 09:58:34 -04:00
Kevin O'Connor
8920479f85 klippy: Remove CLEAR_SHUTDOWN command
Advice users to issue a FIRMWARE_RESTART command on a printer shutdown
event, and remove support for CLEAR_SHUTDOWN.  A full mcu reset is
preferable and it simplifies the interface.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 14:53:41 -04:00
Kevin O'Connor
4c25eae9b4 mcu: Make sure a FIRMWARE_RESTART actually resets the mcu
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 14:29:18 -04:00
Kevin O'Connor
a3a45b5037 docs: Update Todo - RPi power over USB now implemented
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 14:18:48 -04:00
Kevin O'Connor
dc645d76b4 docs: Reword and reformat parts of move code flow in Code_Overview
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 14:08:02 -04:00
Kevin O'Connor
daff83ee9a hub-ctrl: Add support for micro-controller reset via RPi usb power toggling
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 13:20:13 -04:00
Kevin O'Connor
9f9e3e61d6 mcu: Support reset command
Extend the FIRMWARE_RESTART command so that it can use the firmware
"reset" command instead of the "arduino" mechanism.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 13:20:13 -04:00
Kevin O'Connor
1592395036 reactor: Fix bug causing end() to not always work
Only set the self._process flag in run() not _dispatch_loop().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-13 13:20:13 -04:00
Kevin O'Connor
8491b1f86a docs: Update Features document with latest performance benchmarks
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 13:53:33 -04:00
Kevin O'Connor
a7b4d70cc6 docs: Add documentation on how to run the graphstats.py script
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 13:41:11 -04:00
Kevin O'Connor
fa193e9618 graphstats: The times are no longer in UTC time
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 13:40:25 -04:00
Kevin O'Connor
050008f3c8 docs: Update Debugging.md file with python virtual env setup
Direct readers to the main Installation file to setup the python
virtual environment and remove the outdated instructions in the
Debugging file.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 12:49:12 -04:00
Kevin O'Connor
70e53cb080 docs: Update Firmware_Commands with recent end stop changes
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 12:36:29 -04:00
Kevin O'Connor
7b03b04c78 klippy: Support minimum/maximum value checks on configuration variables
Verify that numeric parameters are in a sane range when reading the
config.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 11:42:55 -04:00
Kevin O'Connor
7a7b98cc31 sam3x8e: Rework adc pin search to be more clear
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 10:01:22 -04:00
Kevin O'Connor
15d5837322 avr: Rework adc and pwm pin search to be more clear
Rework the pin search loop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 10:01:22 -04:00
Kevin O'Connor
f9ebb8b23e avr: Move code around in gpio.c
Move the PWM, ADC, and SPI pin tables closer to their corresponding
code.  This is code movement only - no code changes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 10:00:54 -04:00
Kevin O'Connor
77b94451de avr: Fix irqstatus_t typo in gpio_pwm_setup
The flags and cs variables should be uint8_t not irqstatus_t.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-11 09:49:35 -04:00
Kevin O'Connor
ca6245e974 docs: Update Code Overview document with code flow for a typical move
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-10 22:10:49 -04:00
Kevin O'Connor
1cdddeec30 stepcompress: Add comment on common suffixes and units
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 20:22:32 -04:00
Kevin O'Connor
657c908f88 stepcompress: Modify check_expand() into check_push()
Add the new item at the same time as checking if there is space in the
queue.

Also, update the default optimization level of c_helper.so to O2 to
improve the compiled code layout.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 19:05:04 -04:00
Kevin O'Connor
d7a0e22d59 stepcompress: Remove step_dist from stepcompress_push_delta()
Pass the step direction explicitly to the low-level delta kinematic C
code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 15:08:42 -04:00
Kevin O'Connor
33b809714f delta: Do reverse direction checking in C code
Calculate where a tower must reverse direction during a move in the C
code instead of the delta.py kinematic code.  This simplifies the
python code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 15:05:41 -04:00
Kevin O'Connor
b915a2ad7d delta: Make it clear that a "virtual tower" is created
The delta code calculates a "virtual tower" along the line of
movement.  Rework the variable names and comments to make it clear
that this is occurring.

It is not necessary to pass the start_pos variable to the C code as it
is simple to update the start_pos at the start of each movement.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 15:05:41 -04:00
Kevin O'Connor
85ed5cef7f stepcompress: Merge stepcompress_delta_const and stepcompress_delta_accel
It's not necessary to have separate C delta kinematic functions for
constant acceleration and constant velocity as constant velocity can
be obtained by using a constant acceleration of zero.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 14:47:00 -04:00
Kevin O'Connor
df42b0d1ac stepcompress: Pass delta velocity and acceleration directly to C code
Update the C delta kinematic code to take velocity and acceleration
directly in step distances and clock ticks.  This simplifies the
mcu.py python code as it only needs to do unit and axis conversion.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 14:43:48 -04:00
Kevin O'Connor
98add22891 stepcompress: Merge stepcompress_push_accel() and stepcompress_push_const()
It's not necessary to have separate C functions for constant
acceleration and constant velocity as constant velocity can be
obtained by using a constant acceleration of zero.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 14:43:25 -04:00
Kevin O'Connor
1d81bf5596 stepcompress: Pass constant velocity and acceleration directly to C code
Update the C code to take velocity and acceleration directly in step
distances and clock ticks.  This simplifies the mcu.py python code as
it only needs to do unit and axis conversion.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 13:57:24 -04:00
Kevin O'Connor
e4153a536f mcu: Change mcu_stepper.set_position() to take a location in millimeters
Update the set_position() method to convert from millimeters to
absolute step position.

Also, update PrinterStepper.get_homed_offset() and
mcu_stepper.get_commanded_position() to return millimeters.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 13:44:17 -04:00
Kevin O'Connor
79f31238b0 mcu: Don't export the commanded_position variable from mcu_stepper
Now that the kinematic classes call the mcu_stepper with millimeters
and seconds it is no longer necessary for them to directly access the
stepper's position in absolute steps.  Rename
mcu_stepper.commanded_position to mcu_stepper._commanded_pos to make
clear it is not a variable intended to be externally accessed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 13:44:17 -04:00
Kevin O'Connor
8c712d959d mcu: Pass delta velocity and acceleration directly to mcu_stepper
Rework the parameters of step_delta_const() and step_delta_accel() so
that they take velocity and acceleration directly in millimeters and
seconds.  This simplifies the delta.py kinematic code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 13:44:04 -04:00
Kevin O'Connor
c4b1a79db2 mcu: Pass constant velocity and acceleration directly to mcu_stepper
Rename step_sqrt/step_factor to step_accel/step_const and have them
directly take the velocity and acceleration in millimeters and
seconds.  This simplifies the kinematic classes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 13:43:56 -04:00
Kevin O'Connor
47f12f107d stepcompress: Move stepcompress_push_* functions to their own section
This is only code movement; no code changes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-07 13:26:39 -04:00
Kevin O'Connor
bfad970e4d mcu: Rename self.ffi_lib to self._ffi_lib
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-04 10:13:02 -04:00
Kevin O'Connor
49bdc6fbd1 corexy: Initial corexy kinematic implementation
Add initial support for corexy kinematics.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-03 17:27:14 -04:00
Kevin O'Connor
57f279677f endstop: Support halting more than one stepper on trigger
Extend the endstop code so that more than one stepper can be halted
during endstop homing.  Some kinematic setups (eg, corexy) require an
endstop to support this.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-03 17:27:10 -04:00
Kevin O'Connor
fff73c7735 avr: Invert diff in timer checks
Minor optimization on avr.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-03 10:39:49 -04:00
Kevin O'Connor
e44678ceba avr: Implement reset command
Support restarting the mcu using the watchdog feature of AVR chips via
a new reset command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-02 23:19:29 -04:00
Kevin O'Connor
85c0e9c574 sam3x8e: Implement reset command
Support restarting the mcu via a new reset command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-02 23:19:25 -04:00
Kevin O'Connor
0c3ec7f9a5 avr: Do not use --relax linker option
The relax option corrupts the compilation on at least some versions of
gcc/binutils (eg, on fedora's avr-gcc 6.2.0 / binutils 2.27) due to
corruption of switch tables that use jump offsets.  This issue is also
the root cause that resulted in commit d67f962a.  Since the --relax
option provides minimal size / performance improvements it can simply
be dropped.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-02 23:19:19 -04:00
Kevin O'Connor
74e15b2eb5 checkstack: Be more flexible in finding the timer irq function
If __vector_13 doesn't exist then try __vector_17.  If neither exists
then handle that gracefully.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-02 23:19:02 -04:00
Kevin O'Connor
565861f680 reactor: Support pause() command even when the reactor is not running
If the reactor isn't running then implement pause using the system
sleep command.  This simplifies the users of pause().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-04-01 12:26:24 -04:00
Kevin O'Connor
7c991399ac timer: Remove dup timer_shutdown code
Commmit a1c61563 renamed timer_shutdown() to timer_reset() but
neglected to delete timer_shutdown().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-31 19:20:45 -04:00
Kevin O'Connor
384c853a39 docs: Update benchmark results in Features document
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-31 17:50:36 -04:00
Kevin O'Connor
c0380d0280 stepper: Disable homing_endstop_accuracy errors on debug runs
If klippy is started in file output debugging, disable the
homing_endstop_accuracy error check.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-31 14:38:09 -04:00
Kevin O'Connor
a1c61563a0 avr: Fix bug causing timer_read_time() to not be in sync with scheduler
Commit 16e3dbb1 changed the avr implementation of timer_read_time().
Unfortunately, it raised the possibility for timer_read_time() to be
out of sync with the scheduler's understanding of the current time.
In particular, it was common for the timer irq to overflow the 16bit
hardware counter once at startup, and this would lead to
timer_read_time() always returning a time ~4ms ahead of the scheduler
on 16Mhz chips.  This resulted in "Move queue empty" errors.

To resolve this issue, only increment timer_high from timer_periodic()
and make sure the timer irqs start immediately after timer_init().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-31 14:36:57 -04:00
Kevin O'Connor
aa0f1aaeb2 toolhead: Increase the motor_off_time default to 10 minutes
Increase the default motor_off_time from 1 minute to 10 minutes.  The
small value is a common source of confusion.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 14:09:17 -04:00
Kevin O'Connor
03ddd64b93 config: Decrease example max_z_velocity to 25mm/s
Change the example files for cartesian printers to have a 25mm/s
maximum Z velocity.  It's common to use lead screws for the Z axis on
cartesians and it is unlikely one would want to drive them at 250mm/s.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 14:05:05 -04:00
Kevin O'Connor
7fc9ba7d3a mcu: Log the mcu clock each time print_time is synchronized
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 12:51:10 -04:00
Kevin O'Connor
63b6bab5c3 sam3x8e: Align the TC0_Handler timer irq handler
The code alignment of the TC0_Handler function seems to noticeably
impact performance benchmarks.  Set the function alignment to 16 bytes
to improve testing consistency.  An alignment of 16 doesn't
necessarily improve performance, but it seems to improve testing
consistency on code changes unrelated to timer dispatch.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 12:04:08 -04:00
Kevin O'Connor
eb4eeb6f73 timer_irq: Integrate timer_try_set_next() into timer_dispatch_many()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 11:25:23 -04:00
Kevin O'Connor
6988507998 timer_irq: Rename generic/timer.c to generic/timer_irq.c
Rename the file to make it clear that the code is helper functions for
boards with irq based timers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 11:24:44 -04:00
Kevin O'Connor
65be6d5146 avr: Integrate timer_try_set_next() into the irq handler
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 11:24:44 -04:00
Kevin O'Connor
6d05dd07f5 sched: Move timer dispatch loop to board code
Rename sched_timer_kick() to sched_timer_dispatch() and move its loop
into its callers in the board code.  This eliminates the need to
export timer_try_set_next() from the board code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 11:24:42 -04:00
Kevin O'Connor
7436ec093a sched: Rename reschedule_timer() to insert_timer() and use in sched_add_timer()
Use the same code in both rescheduling of a timer and adding a new
timer.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 10:57:35 -04:00
Kevin O'Connor
2b735daae5 timer: Make sure to reset the timer repeat checks on a shutdown
Reset the timer repeat checks on shutdown, otherwise it is possible to
get into an infinite shutdown loop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 10:57:35 -04:00
Kevin O'Connor
f8b0c884b0 stepper: Improve performance of scheduled unsteps
On faster MCUs where a delay is needed between step and unstep use a
"busy loop" in the scheduler instead of trying to schedule to the
unstep time.  This reduces the chance of jitter in the scheduler
accumulating.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 10:57:35 -04:00
Kevin O'Connor
18f4d343f5 avr: Remove F_CPU compile time definition
Directly use the Kconfig defined CONFIG_CLOCK_FREQ in the code and
avoid defining F_CPU.  Also, remove the unnecessary O2 option - that
is already the default from the main makefile.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-30 10:56:17 -04:00
Kevin O'Connor
31e78c90e2 avr: Minor optimization for timer_read_time() / timer_periodic()
Tell the compiler that the TOV1 bit is rarely set.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-27 13:37:20 -04:00
Kevin O'Connor
3238256b79 docs: Update benchmark results in Features document
Some additional tweeks to the scheduler has resulted in minor
improvements to the stepper benchmarks.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 23:31:33 -04:00
Kevin O'Connor
59b71d5d05 sched: Be explicit with loading of the waketime variable
Explicilty load the timer waketime variable into local variables in
sched_timer_kick().  Change the optimization level from Os to O2.
This helps gcc to avoid unnecessary reloads from memory in the common
stepper_event() case.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 22:45:58 -04:00
Kevin O'Connor
4dfa6c6ee4 avr: Introduce optimized timer_is_before()
Provide hand-coded assembler for timer_is_before() on AVR as that code
is used frequently in the time-critical timer dispatch loop and gcc
doesn't do a good job at compiling that comparison code.  Remove the
no longer needed waketime+1 hack from reschedule_timer().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 22:45:58 -04:00
Kevin O'Connor
60e488eb17 timer: Allow board code to define its own timer_is_before implementation
Move sched_is_before() from sched.c to timer_is_before() in the board
specific timer code.  This allows the board code to provide its own
definition.

Also, remove the sched_from_us() and sched_read_time() wrapper
functions and change the callers to directly invoke timer_from_us() /
timer_read_time().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 22:45:58 -04:00
Kevin O'Connor
14340ac4df timer: Organize timer_try_set_next() with priority for repeat timers
Organize the code flow to optimize for repeat timers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 22:01:07 -04:00
Kevin O'Connor
efbfc2b1ab avrsim: Catch simulation errors
Request that simulavr throw an exception on a fatal emulation error
instead of exiting the process.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 22:01:07 -04:00
Kevin O'Connor
d4f09bc20d checkstack: Updates for newer binutils
Newer versions of binutils report the variable name on memory
accesses.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 21:55:24 -04:00
Kevin O'Connor
d67f962a38 command: Simplify sendf() switch
Commit f28eb902 reworked the switch to fix int16 encoding.  However,
at least one version of avr gcc doesn't like that switch layout (it
uses a jump table).  Reorg the switch to avoid that issue.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-26 21:55:24 -04:00
Kevin O'Connor
6de85d02ae serialqueue: Message receive_time must be taken after read()
The est_clock calculation code requires timestamps on status messages
to never be prior to the reception of the message.  The eventtime of
handle_message() is taken before the read() and there is a small
possibility that it could be inaccurate enough to corrupt the
est_clock calculation.  Take a new timestamp when storing receive_time
to prevent this.  This fix prevents some firmware "Move queue empty"
shutdowns.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 19:16:33 -04:00
Kevin O'Connor
f28eb902df command: Fix encoding of 16bit signed integers
The code wasn't properly sign-extending 16bit integers which caused
int16_t reports in output() to appear as uint16_t.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 15:31:26 -04:00
Kevin O'Connor
9702d522a4 sched: Report the time of a shutdown
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 15:05:52 -04:00
Kevin O'Connor
4f710b0470 avrsim: Support pacing the simulation
Support timing the simulation scaled to the system clock.  This can be
used to make the host estimation of the mcu clock more accurate.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 13:55:55 -04:00
Kevin O'Connor
5f29787dc7 avrsim: Do IO directly from simulavr callbacks
Don't start/stop the simulavr simulation loop to do IO - instead
implement the IO directly in the serial callback handlers.  This
improves the speed and consistency of the simulation.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 11:58:32 -04:00
Kevin O'Connor
1fbb36fa87 serialhdl: Make sure to calculate est_clock before connect() finishes
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 11:13:55 -04:00
Kevin O'Connor
3cafcc2bc7 serialqueue: Don't retransmit on a NAK if no sent data is pending
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-24 11:13:55 -04:00
Kevin O'Connor
8d92c898ee stepcompress: Always return 0 on negative number in safe_sqrt()
sqrt() of a negative number in the C code returns NaN.  This value
results in behavior that is difficult to debug.  Always return 0.0
instead as this results in better behavior that is easier to track
down.  Also, on some code paths, safe_sqrt is called on numbers that
are multiplied by very large amounts (eg, 16000000**2) and thus
distinguishing between large and small negative numbers is difficult.
For now, report in the log if the value is below -0.001.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-22 10:54:53 -04:00
Kevin O'Connor
9bf73cd72d extruder: Make sure EXTRUDE_DIFF_IGNORE doesn't trigger due to rounding
The code disables lookahead between two extruding moves with
significantly different extrude ratios.  Unfortunately, it was
possible for very tiny moves to show different extrude ratios just due
to how the slicer implements rounding when it produces the gcode.
Allow lookahead to be enabled between moves with extrude ratios that
are different if they don't noticeably produce more or less extrusion.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-20 14:39:06 -04:00
Kevin O'Connor
f97cf5c3b6 extruder: Avoid maximum extrude cross section errors on infinitesimal moves
Be less likely to raise a "Move exceeds maximum extrusion cross
section" error on very short moves.  It's okay to extrude a little
extra plastic on moves shorter than the nozzle diameter.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-19 21:38:59 -04:00
Kevin O'Connor
5ff2d5aee6 mcu: Defer MCU_adc register_msg until ready to receive messages
Register the callback handler only after it's required state is setup.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 14:41:26 -04:00
Kevin O'Connor
1f474742eb klippy: Log python info at start of log
Log the python version and startup command parameters to the log.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 14:41:25 -04:00
Kevin O'Connor
0041a0079d stepcompress: Improve check_line() error messages
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 13:15:25 -04:00
Kevin O'Connor
9bb8b0c622 toolhead: Don't raise exception from force_shutdown
Catch and ignore any exceptions when trying to shutdown the printer in
toolhead.force_shutdown() - there's a good chance an exception will be
raised as this method is often called after an invalid internal state
is found.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 13:15:25 -04:00
Kevin O'Connor
df6d3107f2 stepper: Fix set_min_stop_interval() calculation
The previous calculation was only valid if the stepper is always
commanded to a position that is an exact multiple of the
step_distance.  The safety check was programmed with a value too large
for other commanded positions, which could result in "No next step"
errors.  Fix by changing the calculation to use the worst case
scenario.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 13:15:09 -04:00
Kevin O'Connor
cbdc54843d gcode: Catch common gcode parameter errors
Don't force a firmware shutdown on a simple gcode parse error.
Instead, report the error back to the user and otherwise ignore the
command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 13:13:36 -04:00
Kevin O'Connor
d2027cb4a9 serialhdl: Catch SerialException as well as OSError on serial open
Catch the right exceptions so that a retry is possible when attempting
to open the serial port.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 12:49:15 -04:00
Kevin O'Connor
e60779bfe1 heater: Force set_pwm of zero when target_temp is zero
Fix a corner case where a residual in the PID could cause a non-zero
pwm request even when the target_temp is zero.  (Which could lead to a
firmware "Missed scheduling of next pwm event" shutdown.)

Simplify the logic for suppressing duplicate pwm updates and make sure
a zero target_temp always results in a zero pwm update on the
following set_pwm calculation.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-16 12:49:15 -04:00
Kevin O'Connor
f66b1ac450 heater: Add support for AD595 type sensors
Add support for sensor chips that produce a voltage that linearly
scales with temperature.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:48:30 -04:00
Kevin O'Connor
ff6a96665a heater: Rename thermistor_type config name to sensor_type
Rename the thermistor_type and thermistor_pin config variables to
sensor_type and sensor_pin.  This is in preparation for support of
sensors beyond thermistors.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:46:33 -04:00
Kevin O'Connor
4388a294a4 heater: Handle case where min adc value is less than max adc value
When using a sensor that isn't a thermisistor, the maximum and minimum
adc values may be swapped - handle that case.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:44:53 -04:00
Kevin O'Connor
d21b9280f0 klippy: Eliminate high-level build_config phase
Now that the mcu objects can be created prior to connecting to the
mcu, it is no longer necessary to separate the init and build_config
phases in the high-level code.  Move the mcu objection creation from
the build_config phase to the init phase and eliminate the
build_config phase.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:38:17 -04:00
Kevin O'Connor
92649332ce mcu: Delay setting of mcu_stepper.min_stop_interval
Create a separate callback for setting the min_stop_interval.

Also, move the setting of the stepper max_error from the stepper
configs to the mcu config and rename it to max_stepper_error.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:38:17 -04:00
Kevin O'Connor
be91c1229f gcode: Eliminate build_config() method
Lookup the printer components during the set_printer_ready() callback.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:38:17 -04:00
Kevin O'Connor
168cb95bd5 mcu: Allow each oid object to define its own build_config() method
Create a build_config() method on each oid object and call it just
after connecting to the MCU.  Move code that requires a connected
state from the oid init to its new build_config method.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:38:17 -04:00
Kevin O'Connor
1d796a4e24 mcu: Support config mechanism for translating seconds to clock ticks
Introduce a TICKS() macro during config parsing that will translate
time in seconds to time in clock ticks.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:38:17 -04:00
Kevin O'Connor
8e6d5efdac pins: Simplify pin map alias setup
Use map_pins() to obtain the pin mapping - don't export
mcu_to_pins().  The functionality of mcu_to_pins() can be obtained by
calling map_pins() with name=None.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-13 00:38:15 -04:00
Kevin O'Connor
0f2478b62f docs: Update benchmark results in Features document
Recent scheduler optimizations have made a minor improvement to the
stepper benchmarks.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-11 12:23:24 -05:00
Kevin O'Connor
e5d7e593ec generic: Move generic parts of sam3x8e timer.c to generic directory
Most of sam3x8e/timer.c is going to be platform agnostic for any board
with standard irq handling.  Move the generic code into a new file
generic/timer.c.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-11 12:15:07 -05:00
Kevin O'Connor
69b927bfe9 sched: Move functions within sched.c
Just code movement - no code changes.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-11 11:14:06 -05:00
Kevin O'Connor
944d176856 sched: Rename sched_timer() to sched_add_timer()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-11 11:14:06 -05:00
Kevin O'Connor
cdd5a772e8 sched: Don't overwrite shutdown reason if shutdown called while shutdown
If a shutdown occurs while the machine is already shutdown, then keep
the original shutdown reason code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-10 23:24:20 -05:00
Kevin O'Connor
0a3c23bcf6 sched: Avoid rescheduling the currently active timer
It's tricky to reschedule the timer irq correctly (due to race
conditions with the irq) and in practice it's very rarely needed.
Handle the special cases in the generic sched.c code so that the board
code doesn't have to handle it.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-10 23:24:15 -05:00
Kevin O'Connor
cb286ede9d sched: Use a sentinel timer at the end of the timer_list
Introduce a dummy sentinel timer object that is always the last item
on timer_list.  This optimizes the timer_list walking code as it no
longer needs to check for NULL when traversing the list.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-10 16:14:49 -05:00
Kevin O'Connor
16e3dbb18c avr: Optimize 16bit timer upscaling
The hardware timer overflow bit can be used to optimize the conversion
from 16bit timers to 32bit timers.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-10 13:31:38 -05:00
Kevin O'Connor
a38437f378 stepper: Introduce stepper_get_position command and remove from endstop.c
Move the logic to calculate and report the stepper's current position
from endstop.c to stepper.c.  This localizes the stepper code into
stepper.c.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-09 14:54:52 -05:00
Kevin O'Connor
8d6ecd9af8 endstop: No need to store pin_value
The pin_value can be stored in the existing flags variable.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-09 14:50:40 -05:00
Kevin O'Connor
342a7096ea basecmd: Remove unimplemented command_reset()
It's better to not have the unimplemented command defined so that the
host can detect when it is actually implemented.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-09 14:18:24 -05:00
Kevin O'Connor
60a4bda9d4 basecmd: Use oid_ prefix for the oid manipulation functions
Consistently use an "oid_" prefix on the oid functions - this makes
them similar to other functions with a common prefix.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-09 13:49:03 -05:00
Kevin O'Connor
d5fc594317 mcu: Support inverted PWM pins
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-09 00:46:53 -05:00
Kevin O'Connor
64407dc5d2 klippy: Support FIRMWARE_RESTART command
Add initial support for micro-controller resets via the Arduino reset
mechanism.  Also, automatically attempt a firmware restart if the
printer CRC does not match.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 23:02:31 -05:00
Kevin O'Connor
b0329465ec serialhdl: Make sure to close the serial port on disconnect()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 23:02:31 -05:00
Kevin O'Connor
0f70b420f2 mcu: Improve error messages on failure to config printer
Don't report a CRC mismatch if a shutdown or other failure occurs
during config - instead report the appropriate details.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 21:44:17 -05:00
Kevin O'Connor
21c4dea0e6 serialhdl: Detect timeout in SerialReader.send_with_response()
Raise an error if the response is never received.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 21:25:54 -05:00
Kevin O'Connor
bcaf818c0e fan: Default to using software PWM
Not all hardware has PWM support and there is no compelling reason to
use hardware PWM for fans.  Change the default to use software PWM.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 20:23:09 -05:00
Kevin O'Connor
37bac916e7 basecmd: Generalize the "move queue" runtime storage
Detect the maximum size of each "move queue" item during the
configuration phase instead of using the stepper move struct.  This
allows the stepper code to be contained entirely in stepper.c and it
allows for future run time allocations from other types of objects.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 13:37:51 -05:00
Kevin O'Connor
affdbbf9ca sam3x8e: Fix typo in gpio_in_setup() shutdown message
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-08 13:17:45 -05:00
Kevin O'Connor
4fcf0ff2ac docs: Fix typo in description of fan pin.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-07 19:13:37 -05:00
Kevin O'Connor
c19af4fb2b serialhdl: Load the mcu's 64bit clock at start of connection
Store a full 64bit uptime in the mcu and query it at the start of each
connection.  This ensures the host's 64bit clock is always in synch
with the mcu's clock.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-03 22:02:27 -05:00
Kevin O'Connor
f53897758d heater: Support max_power setting for heaters
Change the mcu PWM value from an integer (0-255) to a float (0. - 1.).
Add support for limiting the maximum power (as measured over a
sufficiently long duration) to a particular heater.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-03 20:00:16 -05:00
Kevin O'Connor
54002c4391 extruder: Pressure advance lookahead time should start after decel
The pressure advance lookahead time should start after any full
deceleration moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-03-03 14:20:41 -05:00
Kevin O'Connor
6a53eaefc0 extruder: Allow configuration of pressure advance lookahead time
Instead of defaulting the pressure advance lookahead time to be the
same as the pressure_advance variable, allow it to be configured.
Default the new config setting (pressure_advance_lookahead_time) to
10ms.

Also, make the setting more accurate if a future move is accelerating
in the middle of the lookahead window.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-22 15:20:22 -05:00
Kevin O'Connor
4bc114336c delta: Simplify maximum stepper velocity and accel checks
Simplify the mechanism for limiting stepper speed (introduced in
commit bdfdf7ef) - split the extreme end of the build envelope into
two zones and use the same speeds for all moves that traverse any part
of one of those zones.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-21 11:18:56 -05:00
Kevin O'Connor
47f1d377f5 heater: Enforce min/max_temp in heater.set_temp()
Raise an error if the user requests a temperate outside the configured
min/max_temp range.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-21 10:48:42 -05:00
Kevin O'Connor
566699f68a toolhead: Fix error in lookahead logic
Commit c24b7a7e reworked the way lookahead was done and it introduced
a bug when a full acceleration move is immiedietly followed by a full
deceleration move.  In that situation, depending on when the lookahead
queue was flushed, it was possible to call move.move() without calling
move.set_junction().  This resulted in a "Move instance has no
attribute 'accel_t'" internal error.

Simplify and fix the logic for checking full accel moves followed by
full decel moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-20 12:50:12 -05:00
Kevin O'Connor
29ba92a551 delta: Use position_endstop for position_max
There's no reason for the user to specify position_max - it can be
inferred on deltas from the endstop positions.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-19 11:00:46 -05:00
Kevin O'Connor
38e9484f9f armcm_irq: Move ARM Cortex-M irq handling to new file
The irq handling in sam3x8e isn't specific to the sam3x8e proccessor -
it's generic for all armcm type machines.  So, move the definitions
into a new file generic/armcm-irq.c

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-19 11:00:46 -05:00
Kevin O'Connor
fec12030a9 sam3x8e/timer: Be careful of races in timer_set_next()
It's possible for sched_del_timer() to be called on a timer that fires
just after sched_del_timer disables irqs but before the next timer is
scheduled.  In this case be sure to clear the irq pending status flag
after scheduling the next timer so that a delayed irq doesn't cause
the wrong timer to be run.  For the same reason, make sure to check
the irq pending status flag at the start of the timer irq.

Also, as a safety check, make sure timer_set_next() isn't called from
within the timer irq dispatch loop.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-14 22:15:51 -05:00
Kevin O'Connor
bdfdf7ef55 delta: Cap maximum stepper velocity and acceleration
Some XY moves at the extreme end of the build envelope could cause
excessive axis stepper movement.  Check for any moves that could
possibly result in a stepper movement of more than 3 times the XY
movement and cap the move's acceleration and speed.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-13 21:47:10 -05:00
Kevin O'Connor
9f65ae72c3 delta: Rework boundary checks
Calculate and store the maximum xy2 value for the given z level each
time the head moves to a new z level.  This simplifies the boundary
check for common XY moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-13 17:51:13 -05:00
Kevin O'Connor
3434ea540c klippy: Log the type of cpu the host is running on
Report in the log the host CPU type and count.  This helps distinguish
between different rpi versions when debugging the log from a problem
report.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 19:14:26 -05:00
Kevin O'Connor
29131c873a gcode: Attempt to shutdown heaters and fans prior to a RESTART
If the user requests a restart and the machine appears to be otherwise
functioning normally, then attempt to stop the heaters and fans prior
to restarting the host.  This prevents the firmware from going into a
shutdown state when the heater is on and the host restarts.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 18:48:21 -05:00
Kevin O'Connor
ab1eb70d1c toolhead: Rework lookahead flush to be more stable during high cpu
Change the lookahead queue so that it attempts to buffer at least
buffer_time_high amount of moves when first starting a print.  This
helps ensure the buffer is normally always full.

If the buffer falls below buffer_time_low then it is either due to the
end of a print or because octoprint/klippy is unable to keep up.
Change the code so that in this case the lookahead queue will attempt
to gather buffer_time_high amount of moves before restarting movement.

Update the default buffer_time_low to 1 second and buffer_time_high to
2 seconds.  With the above changes a smaller buffer_time_high and a
larger buffer_time_low are more practical.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 17:20:40 -05:00
Kevin O'Connor
71256f9456 toolhead: Flush lookahead buffer by time
Use a minimum time window as a heuristic for determining when to try
to lazily flush the lookahead buffer.  In the common case this will
result in more moves processed for each flush and thus reduce the
overall cost of the lookahead processing.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 17:20:40 -05:00
Kevin O'Connor
6179839215 toolhead: Separate motor off timer from main flush timer
Move the motor off time checking to its own code.  This simplifies the
main flush handler.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 17:20:40 -05:00
Kevin O'Connor
0ca96e543c toolhead: Increase maximum stepper halt velocity
Do a better job of calculating the maximum halt velocity for the
stepper motors.  The maximum cornering velocity is related to both the
maximum acceleration and the junction_deviation, so both should be in
the formula.  Tests show that "math.sqrt(8. * self.junction_deviation
* self.max_accel)" very closely fits the maximum on cartesian robots.

This fixes potential "no next step" shutdowns that could occur on
some print moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 17:20:40 -05:00
Kevin O'Connor
acb0b8f599 klippy: Fix omission causing gcode dump to not function
Fix bug that broke the gcode command dump after a shutdown.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-12 17:19:58 -05:00
Kevin O'Connor
20d0936fa2 reactor: Use the system monotonic clock instead of the normal system clock
The normal system clock can have sudden jumps if the system clock is
changed.  Use the system monotonic clock to avoid these sudden changes
in time.

It appears the Raspbian OS (which is used by OctoPi) is setup to
update the system clock upon network connectivity.  This could cause
sudden system clock changes which could lead to Klippy processing
errors.  Using the monotonic clock eliminates these issues.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 13:31:34 -05:00
Kevin O'Connor
c24b7a7ef9 toolhead: Introduce "smoothed" acceleration during lookahead
Update the lookahead code to track both normal toolhead acceleration
as well as a pseudo acceleration to the point of deceleration.  This
reduces the top speed of small zig-zag moves and it reduces printer
vibration during these moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
074495a13a toolhead: Remove unneeded forward pass in MoveQueue.flush()
Simplify the code now that the extruder lookahead is separate from the
main lookahead code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
e14d86d8b8 toolhead: Remove the do_calc_junction flag
It is not necessary to track the do_calc_junction flag as it can just
as easily be determined at the top of the calc_junction() method.
This simplifies the code.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
528c29c01c extruder: Do extruder lookahead based on time instead of cornering
When calculating the extruder lookahead, determine how far to
lookahead by the amount of elapsed time each move takes.  This makes
the extruder lookahead code more flexible as it is no longer limited
to the next immediate cornering moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
1bb7a22115 extruder: Move extruder specific lookahead into extruder class
Instead of calculating min/max_corner_v in the toolhead class,
calculate it in the extruder class.  This keeps the extruder specific
code together.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
19ed67331d stepcompress: Propagate errors back to python code
Propagate error codes back to the python code and raise an exception
on an error.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
667b72870f gcode: Exit on an unhandled exception when reading from a file
When testing via a gcode input file, it's easier to debug problems if
the program exits upon the first exception.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-06 12:17:50 -05:00
Kevin O'Connor
4194ebf9df graphstats: Display host buffer stats in graph
Prune host buffer stats near the start and end of the print.  Graph
the remaining buffer stats.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-02 10:46:48 -05:00
Kevin O'Connor
5beceaae5c io.h: read/write[bwl] should use barrier
Add barrier() calls to low-level read/write io calls so that their
callers don't need to.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-02-02 10:46:42 -05:00
Kevin O'Connor
9c1bf1387c toolhead: Make sure max_corner_v2 is fully calculated on a lazy flush
Make sure max_corner_v2 is fully calculated before proactively
flushing moves from the lookahead queue.  Without this, some moves
would do unnecessary pressure advance during cornering.

Also, handle the min/max_corner_v2 calculations correctly in the rare
case where a move that does only acceleration is immediately followed
by a move that does only deceleration.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-16 15:32:35 -05:00
Kevin O'Connor
fc6a31eac8 toolhead: Change variables to use suffix "_v2" instead of prefix "junction_"
The junction speeds are tracked in velocity squared - introduce the
common suffix "_v2" to track that instead of using a prefix of
"junction_".

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-16 15:32:35 -05:00
Kevin O'Connor
064e8bdd84 toolhead: Clear do_calc_junction if using non-default accel
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-14 12:48:16 -05:00
Kevin O'Connor
262ccbcf30 serial: Be careful with comparison of transmit_max to transmit_pos
There is a small possibility that a shutdown could occur between
clearing transmit_max and clearing transmit_pos - so make sure to
handle the case where transmit_pos > transmit_max.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-14 12:11:30 -05:00
Kevin O'Connor
7567885115 sched: Minor change - remove unneeded header files
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-14 11:32:27 -05:00
Kevin O'Connor
ed715ec437 command: No need to disable irqs in sendf reentrant check
As long as the code is careful when writing the in_sendf variable it
should be safe to update it without having to disable irqs.

Also, make sure in_sendf is cleared on shutdown.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-14 11:32:27 -05:00
Kevin O'Connor
9a44a20a9d command: Check for reentrant calls to sendf()
Allow sendf() to be called from irq and timer context - check for the
case where sendf() is called while already in sendf() and simply
discard those messages.  This makes it safe to use output() debugging
calls even in irq and timer context.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-13 12:10:00 -05:00
Kevin O'Connor
f335045273 heater: Resend PWM values even if last value was zero
Continue to resend the pwm value even if the last value was zero -
this extends the debugging info.

Also, add the target temperature to the pwm debugging.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-12 15:13:41 -05:00
Kevin O'Connor
4ea091339e heater: Only create a soft PWM object for PID heaters
The "watermark" style heater only needs a digital_out pin - not a
software PWM pin.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-10 18:36:43 -05:00
Kevin O'Connor
8378b7345b toolhead: Change cornering_min/max variable name to junction_corner_min/max
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-10 18:35:52 -05:00
Kevin O'Connor
4a71c7a2bd heater: Report last temperature in PWM debugging
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-10 12:36:51 -05:00
Kevin O'Connor
b2885a53cb klippy: Increase precision of reported statistics timestamp
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-10 12:35:30 -05:00
Kevin O'Connor
46b6b4037d reactor: Reload eventtime if a greenlet is reactivated
Fix a bug causing timers to be delayed when pause() is called from a
fd event.  The eventtime needs to be reloaded when an old greenlet is
reactivated.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-10 11:19:39 -05:00
Kevin O'Connor
93d3a6e1d1 klippy: Warn the user on common errors due to old firmware
Check for msgproto.error and warn the user about version firmware
version mismatch.  Raise msgproto.error when extracting firmware
constants.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-10 00:13:28 -05:00
Kevin O'Connor
eebaeeff96 util: Use path of script instead of current directory for git version
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-09 23:33:23 -05:00
Kevin O'Connor
3a7a77d49e basecmd: Improve accuracy of stats "sumsq" variable
Use a base of 256 instead of 65536 when calculating the sum of the
square of the clock differences in the stats.  This makes the
calculation more accurate.  Export the new base via DECL_CONSTANT for
the host to access.  Use DIV_ROUND_UP() when adjusting for the base to
ensure no lost ticks.  Do the division after multiplication in the
common case where the time between stats_task() invocations is less
than 64K ticks.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-09 23:08:23 -05:00
Kevin O'Connor
c87c090264 extruder: Calculate sane defaults for extrude only velocity and accel
Instead of requiring the user enter velocity and accel parameters for
extrude only moves, calculate sane defaults from the printer's maximum
velocity and accel.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-03 18:18:30 -05:00
Kevin O'Connor
b26922978a extruder: Do sanity checks on extrusion rates
Add a run-time check to ensure the incoming g-code doesn't have a
ridiculously large e move.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-03 18:17:43 -05:00
Kevin O'Connor
5a5bd2596a extruder: Add nozzle and filament diameter config settings
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-03 18:12:51 -05:00
Kevin O'Connor
38ca051381 config: Update example config files to be more clear on default values
Be more clear on which parameters have defaults and which parameters
must be specified in the config.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-02 13:22:20 -05:00
Kevin O'Connor
91056809dd mcu: Change the default baud rate to 250000
Update the default baud rate in mcu.py to 250000 (as that is the
default in all other places).

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-02 12:22:43 -05:00
Kevin O'Connor
f75430e95f gpio: Fix sam38xe ADC startup check
The status register needs to be inspected, not the enable register.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2017-01-01 22:10:24 -05:00
Kevin O'Connor
8e797e6830 stepcompress: Flush periodically if adding more than 64K steps in a move
It's possible for a printer with very fine resolution to require a
large number of steps for a homing operation.  Instead of storing all
of those steps in memory, periodically flush the queue should more
than 64K steps be present.  This keeps a reasonable limit on the
amount of ram needed to store steps.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-31 13:21:53 -05:00
Kevin O'Connor
73c4be3fd3 docs: Update protocol document with internal VLQ link
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-31 11:30:50 -05:00
Kevin O'Connor
c552ba06b4 serialqueue: Remove serialqueue_flush_ready()
The serialqueue_flush_ready() code was used to flush queue_step
commands during a homing operation.  It's no longer necessary now that
moves during a homing operation use the normal message priority
system.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-30 20:15:05 -05:00
Kevin O'Connor
6bd5f4e44e stepcompress: Using normal message priority system during homing
The endstop homing system requires all queue_step commands be in the
MCU's 'move queue' before endstop checking starts.  Use the normal
message priority system to request that stepper queue_step commands
are received prior to the start of the end_stop_home command.  This
simplifies the code and removes the need for special serial queue
flushing.

This also fixes a bug in homing operations that take longer than 2^31
clock ticks.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-30 20:14:48 -05:00
Kevin O'Connor
6138d18f4b toolhead: Also call reset_print_time() on force_shutdown()
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-28 22:38:29 -05:00
Kevin O'Connor
d028f42e99 mcu: Don't call steppersync_flush if steppersync not created
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-28 22:38:29 -05:00
Kevin O'Connor
860fc3e91d gcode: Add support for M115 command
Support querying the firmware type and version.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-28 22:38:29 -05:00
Kevin O'Connor
2e03d84755 gcode: Add support for M400 command
Add ability to fully stall the input until all moves are complete.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-28 22:38:28 -05:00
Kevin O'Connor
f2b406fc5e toolhead: Don't call into kinematic class on extrude only moves
Add a is_kinematic_move flag to the Move class and clear it on extrude
only moves.  Don't call the kinematic check_move() or move() methods
for extrude only moves.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-28 22:38:28 -05:00
Kevin O'Connor
f46bc0ef04 stepper: Change default max_error from 50us to 25us
Change the default compression error window (max_error) from 50us to
25us - it's common for stepper motor drivers to have 30us for their
"pwm fixed off time" and it would be good for the steps to be
scheduled within that time.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-28 22:38:27 -05:00
Kevin O'Connor
800d53db6a stepcompress: Rework addfactor integer overflow check
Revert 4a16053c and avoid integer overflows in the addfactor
calculation by exiting the loop early if count > 0x200.  This provides
stronger protection against overflows.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-26 12:47:17 -05:00
Kevin O'Connor
a9444d3399 mcu: Log the MCU configuration during connect phase
Log the constants reported by the MCU and log the number of move items
allocated after configuration.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-24 12:33:56 -05:00
Kevin O'Connor
4a16053c00 stepcompress: Fix integer overflow leading to infinite loop
Commit a217c0f3 changed the way the "addfactor" was calculated.
Unfortunately, it was possible for the updated method to cause an
integer overflow and have a negative addfactor.  Fix this by
explicitly casting the addfactor calculation to uint32_t.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-24 12:02:37 -05:00
Kevin O'Connor
d0c61f0f76 klippy: Log the contents of the config file at startup
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-24 10:18:41 -05:00
Kevin O'Connor
451ffd567d klippy: Log the host software git version at startup
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-24 10:17:48 -05:00
Kevin O'Connor
f3a49604f1 stepcompress: Increase check on max count to 10000000
Some motors have very small step distances and they can generate over
a million steps during a homing operation.  Increase the maximum count
to ten million to avoid triggering the internal sanity check.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
2016-12-23 23:13:35 -05:00
235 changed files with 24069 additions and 4724 deletions

13
.travis.yml Normal file
View File

@@ -0,0 +1,13 @@
# This is a travis-ci.org continuous integration configuration file.
language: c
addons:
apt:
packages:
- gcc-avr
- avr-libc
- wget
install: ./scripts/travis-install.sh
script: ./scripts/travis-build.sh

View File

@@ -1,6 +1,6 @@
# Klipper build system
#
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
@@ -22,7 +22,7 @@ OBJCOPY=$(CROSS_PREFIX)objcopy
OBJDUMP=$(CROSS_PREFIX)objdump
STRIP=$(CROSS_PREFIX)strip
CPP=cpp
PYTHON=python
PYTHON=python2
# Source files
src-y =
@@ -32,18 +32,15 @@ dirs-y = src
cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
CFLAGS-y := -I$(OUT) -Isrc -I$(OUT)board-generic/ -O2 -MD -g \
CFLAGS := -I$(OUT) -Isrc -I$(OUT)board-generic/ -O2 -MD -g \
-Wall -Wold-style-definition $(call cc-option,$(CC),-Wtype-limits,) \
-ffunction-sections -fdata-sections
CFLAGS-y += -flto -fwhole-program -fno-use-linker-plugin
CFLAGS += -flto -fwhole-program -fno-use-linker-plugin
LDFLAGS-y := -Wl,--gc-sections -fno-whole-program
CFLAGS_klipper.elf = $(CFLAGS) -Wl,--gc-sections
CPPFLAGS = -I$(OUT) -P -MD -MT $@
CFLAGS = $(CFLAGS-y)
LDFLAGS = $(LDFLAGS-y)
# Default targets
target-y := $(OUT)klipper.elf
@@ -77,23 +74,18 @@ $(OUT)board-link: $(KCONFIG_CONFIG)
$(Q)mkdir -p $(OUT)board-generic
$(Q)ln -Tsf $(PWD)/src/generic $(OUT)board-generic/board
$(OUT)declfunc.lds: src/declfunc.lds.S
@echo " Precompiling $@"
$(Q)$(CPP) $(CPPFLAGS) -D__ASSEMBLY__ $< -o $@
$(OUT)%.o.ctr: $(OUT)%.o
$(Q)$(OBJCOPY) -j '.compile_time_request' -O binary $^ $@
$(OUT)klipper.o: $(patsubst %.c, $(OUT)src/%.o,$(src-y)) $(OUT)declfunc.lds
@echo " Linking $@"
$(Q)$(CC) $(CFLAGS) -Wl,-r -Wl,-T,$(OUT)declfunc.lds -nostdlib $(patsubst %.c, $(OUT)src/%.o,$(src-y)) -o $@
$(OUT)compile_time_request.o: $(OUT)klipper.o ./scripts/buildcommands.py
$(OUT)compile_time_request.o: $(patsubst %.c, $(OUT)src/%.o.ctr,$(src-y)) ./scripts/buildcommands.py
@echo " Building $@"
$(Q)$(OBJCOPY) -j '.compile_time_request' -O binary $< $(OUT)klipper.o.compile_time_request
$(Q)$(PYTHON) ./scripts/buildcommands.py -d $(OUT)klipper.dict $(OUT)klipper.o.compile_time_request $(OUT)compile_time_request.c
$(Q)cat $(patsubst %.c, $(OUT)src/%.o.ctr,$(src-y)) > $(OUT)klipper.compile_time_request
$(Q)$(PYTHON) ./scripts/buildcommands.py -d $(OUT)klipper.dict -t "$(CC);$(AS);$(LD);$(OBJCOPY);$(OBJDUMP);$(STRIP)" $(OUT)klipper.compile_time_request $(OUT)compile_time_request.c
$(Q)$(CC) $(CFLAGS) -c $(OUT)compile_time_request.c -o $@
$(OUT)klipper.elf: $(OUT)klipper.o $(OUT)compile_time_request.o
$(OUT)klipper.elf: $(patsubst %.c, $(OUT)src/%.o,$(src-y)) $(OUT)compile_time_request.o
@echo " Linking $@"
$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
$(Q)$(CC) $^ $(CFLAGS_klipper.elf) -o $@
################ Kconfig rules

View File

@@ -1,7 +1,7 @@
# Support for internal testing with the "simulavr" program. To use
# this config, compile the firmware for an AVR atmega644p, disable the
# AVR watchdog timer, set the MCU frequency to 20000000, and set the
# serial baud rate to 115200.
# serial baud rate to 250000.
[stepper_x]
# Pins: PA5, PA4, PA1
@@ -42,11 +42,11 @@ step_pin: ar19
dir_pin: ar18
enable_pin: ar25
step_distance: .004242
max_velocity: 200000
max_accel: 3000
nozzle_diameter: 0.500
filament_diameter: 3.500
heater_pin: ar4
thermistor_pin: analog1
thermistor_type: EPCOS 100K B57560G104F
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog7
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
@@ -57,19 +57,17 @@ max_temp: 210
[heater_bed]
heater_pin: ar3
thermistor_pin: analog0
thermistor_type: EPCOS 100K B57560G104F
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog0
control: watermark
min_temp: 0
max_temp: 110
[fan]
pin: ar14
hard_pwm: 1
[mcu]
serial: /tmp/pseudoserial
baud: 250000
pin_map: arduino
[printer]

81
config/example-corexy.cfg Normal file
View File

@@ -0,0 +1,81 @@
# This file serves as documentation for config parameters of corexy
# style printers. One may copy and edit this file to configure a new
# corexy printer. Only parameters unique to corexy printers are
# described here - see the "example.cfg" file for description of
# common config parameters.
# DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT
# FIRST. Incorrectly configured parameters may cause damage.
# The stepper_x section is used to describe the X axis as well as the
# stepper controlling the X+Y movement.
[stepper_x]
step_pin: ar54
dir_pin: ar55
enable_pin: !ar38
step_distance: .01
endstop_pin: ^ar3
position_endstop: 0
position_max: 200
homing_speed: 50
# The stepper_y section is used to describe the Y axis as well as the
# stepper controlling the X-Y movement.
[stepper_y]
step_pin: ar60
dir_pin: ar61
enable_pin: !ar56
step_distance: .01
endstop_pin: ^ar14
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: ar46
dir_pin: ar48
enable_pin: !ar62
step_distance: .0025
endstop_pin: ^ar18
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: ar26
dir_pin: ar28
enable_pin: !ar24
step_distance: .0022
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: ar10
sensor_type: ATC Semitec 104GT-2
sensor_pin: analog13
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: ar8
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog14
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: ar9
[mcu]
serial: /dev/ttyACM0
pin_map: arduino
[printer]
kinematics: corexy
# This option must be "corexy" for corexy printers.
max_velocity: 300
max_accel: 3000
max_z_velocity: 25
max_z_accel: 30

View File

@@ -9,48 +9,58 @@
# The stepper_a section describes the stepper controlling the front
# left tower (at 210 degrees). This section also controls the homing
# parameters (homing_speed, homing_retract_dist) and maximum tower
# length (position_max) for all towers.
# parameters (homing_speed, homing_retract_dist) for all towers.
[stepper_a]
step_pin: ar54
dir_pin: ar55
enable_pin: !ar38
step_distance: .01
endstop_pin: ^ar2
homing_speed: 50.0
homing_speed: 50
position_endstop: 297.05
position_max: 297.55
# Distance (in mm) between the nozzle and the bed when the nozzle is
# in the center of the build area and the endstop triggers. This
# parameter must be provided for stepper_a; for stepper_b and
# stepper_c this parameter defaults to the value specified for
# stepper_a.
arm_length: 333.0
# Length (in mm) of the diagonal rod that connects this tower to the
# print head. This parameter must be provided for stepper_a; for
# stepper_b and stepper_c this parameter defaults to the value
# specified for stepper_a.
#angle:
# This option specifies the angle (in degrees) that the tower is
# at. The default is 210 for stepper_a, 330 for stepper_b, and 90
# for stepper_c.
# The stepper_b section describes the stepper controlling the front
# right tower (at 330 degrees)
# right tower (at 330 degrees).
[stepper_b]
step_pin: ar60
dir_pin: ar61
enable_pin: !ar56
step_distance: .01
endstop_pin: ^ar15
position_endstop: 297.05
# The stepper_c section describes the stepper controlling the rear
# tower (at 90 degrees)
# tower (at 90 degrees).
[stepper_c]
step_pin: ar46
dir_pin: ar48
enable_pin: !ar62
step_distance: .01
endstop_pin: ^ar19
position_endstop: 297.05
[extruder]
step_pin: ar26
dir_pin: ar28
enable_pin: !ar24
step_distance: .0022
max_velocity: 200
max_accel: 3000
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: ar10
thermistor_pin: analog13
thermistor_type: ATC Semitec 104GT-2
sensor_type: ATC Semitec 104GT-2
sensor_pin: analog13
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
@@ -60,36 +70,62 @@ max_temp: 250
[heater_bed]
heater_pin: ar8
thermistor_pin: analog14
thermistor_type: EPCOS 100K B57560G104F
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog14
control: watermark
min_temp: 0
max_temp: 130
# Extruder print fan (omit section if fan not present)
# Print cooling fan (omit section if fan not present).
#[fan]
#pin: ar9
#hard_pwm: 1
[mcu]
serial: /dev/ttyACM0
baud: 250000
pin_map: arduino
[printer]
kinematics: delta
# This option must be "delta" for linear delta printers
# This option must be "delta" for linear delta printers.
max_velocity: 300
# Maximum velocity (in mm/s) of the toolhead relative to the
# print. This parameter must be specified.
max_accel: 3000
max_z_velocity: 200
# Maximum acceleration (in mm/s^2) of the toolhead relative to the
# print. This parameter must be specified.
max_z_velocity: 150
# For delta printers this limits the maximum velocity (in mm/s) of
# moves with z axis movement. This setting can be used to reduce the
# maximum speed of up/down moves (which require a higher step rate
# than other moves on a delta printer).
delta_arm_length: 333.0
# Length (in mm) of the diagonal rods that connect the linear axes
# to the print head
# than other moves on a delta printer). The default is to use
# max_velocity for max_z_velocity.
#minimum_z_position: 0
# The minimum Z position that the user may command the head to move
# to. The default is 0.
delta_radius: 174.75
# Radius (in mm) of the horizontal circle formed by the three linear
# axis towers. This parameter may also be calculated as:
# delta_radius = smooth_rod_offset - effector_offset - carriage_offset
# This parameter must be provided.
# The delta_calibrate section enables a DELTA_CALIBRATE extended
# g-code command that can calibrate the tower endstop positions and
# angles.
[delta_calibrate]
radius: 50
# Radius (in mm) of the area that may be probed. This is typically
# the size of the printer bed. This parameter must be provided.
#speed: 50
# The speed (in mm/s) of non-probing moves during the
# calibration. The default is 50.
#horizontal_move_z: 5
# The height (in mm) that the head should be commanded to move to
# just prior to starting a probe operation. The default is 5.
#manual_probe:
# If true, then DELTA_CALIBRATE will perform manual probing. If
# false, then a PROBE command will be run at each probe
# point. Manual probing is accomplished by manually jogging the Z
# position of the print head at each probe point and then issuing a
# NEXT extended g-code command to record the position at that
# point. The default is false if a [probe] config section is present
# and true otherwise.

400
config/example-extras.cfg Normal file
View File

@@ -0,0 +1,400 @@
# This file serves as documentation for config parameters of
# additional devices that may be configured on a printer. The snippets
# in this file may be copied into the main printer.cfg file. See the
# "example.cfg" file for description of common config parameters.
#
# Note, where an extra config section creates additional pins, the
# section defining the pins must be listed in the config file before
# any sections using those pins.
# Z height probe. One may define this section to enable Z height
# probing hardware. When this section is enabled, PROBE and
# QUERY_PROBE extended g-code commands become available. The probe
# section also creates a virtual probe:z_virtual_endstop pin. One may
# set the stepper_z endstop_pin to this virtual pin on cartesian style
# printers that use the probe in place of a z endstop.
#[probe]
#pin: ar15
# Probe detection pin. This parameter must be provided.
#z_offset:
# The distance (in mm) between the bed and the nozzle when the probe
# triggers. This parameter must be provided.
#speed: 5.0
# Speed (in mm/s) of the Z axis when probing. The default is 5mm/s.
#activate_gcode:
# A list of G-Code commands (one per line) to execute prior to each
# probe attempt. This may be useful if the probe needs to be
# activated in some way. The default is to not run any special
# G-Code commands on activation.
#deactivate_gcode:
# A list of G-Code commands (one per line) to execute after each
# probe attempt completes. The default is to not run any special
# G-Code commands on deactivation.
# Bed tilt compensation. One may define a [bed_tilt] config section to
# enable move transformations that account for a tilted bed.
#[bed_tilt]
#x_adjust: 0
# The amount to add to each move's Z height for each mm on the X
# axis. The default is 0.
#y_adjust: 0
# The amount to add to each move's Z height for each mm on the Y
# axis. The default is 0.
# The remaining parameters control a BED_TILT_CALIBRATE extended
# g-code command that may be used to calibrate appropriate x and y
# adjustment parameters.
#points:
# A newline separated list of X,Y points that should be probed
# during a BED_TILT_CALIBRATE command. The default is to not enable
# the command.
#speed: 50
# The speed (in mm/s) of non-probing moves during the
# calibration. The default is 50.
#horizontal_move_z: 5
# The height (in mm) that the head should be commanded to move to
# just prior to starting a probe operation. The default is 5.
#manual_probe:
# If true, then BED_TILT_CALIBRATE will perform manual probing. If
# false, then a PROBE command will be run at each probe
# point. Manual probing is accomplished by manually jogging the Z
# position of the print head at each probe point and then issuing a
# NEXT extended g-code command to record the position at that
# point. The default is false if a [probe] config section is present
# and true otherwise.
# In a multi-extruder printer add an additional extruder section for
# each additional extruder. The additional extruder sections should be
# named "extruder1", "extruder2", "extruder3", and so on. See the
# "extruder" section in example.cfg for a description of available
# parameters.
#[extruder1]
#step_pin: ar36
#dir_pin: ar34
#...
#shared_heater:
# If this extruder uses the same heater already defined for another
# extruder then place the name of that extruder here. For example,
# should extruder3 and extruder4 share a heater then the extruder3
# config section should define the heater and the extruder4 section
# should specify "shared_heater: extruder3". The default is to not
# reuse an existing heater.
#deactivate_gcode:
# A list of G-Code commands (one per line) to execute on a G-Code
# tool change command (eg, "T1") that deactivates this extruder and
# activates some other extruder. It only makes sense to define this
# section on multi-extruder printers. The default is to not run any
# special G-Code commands on deactivation.
#activate_gcode:
# A list of G-Code commands (one per line) to execute on a G-Code
# tool change command (eg, "T0") that activates this extruder. It
# only makes sense to define this section on multi-extruder
# printers. The default is to not run any special G-Code commands on
# activation.
# Support for cartesian printers with dual carriages on a single
# axis. The active carriage is set via the SET_DUAL_CARRIAGE extended
# g-code command. The "SET_DUAL_CARRIAGE CARRIAGE=1" command will
# activate the carriage defined in this section (CARRIAGE=0 will
# return activation to the primary carriage). Dual carriage support is
# typically combined with extra extruders - use the SET_DUAL_CARRIAGE
# command in the activate_gcode / deactivate_gcode section of the
# appropriate extruder. Be sure to also use that mechanism to park the
# carriages during deactivation.
#[dual_carriage]
#axis:
# The axis this extra carriage is on (either x or y). This parameter
# must be provided.
#step_pin:
#dir_pin:
#enable_pin:
#step_distance:
#endstop_pin:
#position_endstop:
#position_min:
#position_max:
# See the example.cfg for the definition of the above parameters.
# Heater and temperature sensor verification. Heater verification is
# automatically enabled for each heater that is configured on the
# printer. Use verify_heater sections to change the default settings.
#[verify_heater heater_config_name]
#heating_gain: 2
# The minimum temperature (in Celsius) that the heater must increase
# by when approaching a new target temperature. The default is 2.
#check_gain_time:
# The amount of time (in seconds) that the heating_gain must be met
# in before an error is raised. The default is 20 seconds for
# extruders and 60 seconds for heater_bed.
#hysteresis: 5
# The difference between the target temperature and the current
# temperature for the heater to be considered within range of the
# target temperature. The default is 5.
#max_error: 120
# The maximum temperature difference a heater that falls outside the
# target temperature range may accumulate before an error is
# raised. For example, if the target temperature is 200, the
# hysteresis is 5, the max_error is 120, and the temperature is
# reported at 185 degrees for 12 seconds then an error would be
# raised (or 24 seconds at 190, or 120 seconds at 194, etc.). The
# default is 120.
# Multi-stepper axes. On a cartesian style printer, the stepper
# controlling a given axis may have additional config blocks defining
# steppers that should be stepped in concert with the primary
# stepper. One may define any number of sections with a numeric suffix
# starting at 1 (for example, "stepper_z1", "stepper_z2", etc.).
#[stepper_z1]
#step_pin: ar36
#dir_pin: ar34
#enable_pin: !ar30
#step_distance: .005
# See the example.cfg for the definition of the above parameters.
#endstop_pin: ^ar19
# If an endstop_pin is defined for the additional stepper then the
# stepper will home until the endstop is triggered. Otherwise, the
# endstop will home until the endstop on the primary stepper for the
# axis is triggered.
# Stepper phase adjusted endstops. The following additional parameters
# may be added to a stepper axis definition to improve the accuracy of
# endstop switches.
#[stepper_z]
#homing_stepper_phases:
# One may set this to the number of phases of the stepper motor
# driver (which is the number of micro-steps multiplied by
# four). This parameter must be provided if using stepper phase
# adjustments.
#homing_endstop_accuracy: 0.200
# Sets the expected accuracy (in mm) of the endstop. This represents
# the maximum error distance the endstop may trigger (eg, if an
# endstop may occasionally trigger 100um early or up to 100um late
# then set this to 0.200 for 200um). The default is
# homing_stepper_phases*step_distance.
#homing_endstop_phase:
# This specifies the phase of the stepper motor driver to expect
# when hitting the endstop. Only set this value if one is sure the
# stepper motor driver is reset every time the mcu is reset. If this
# is not set, then the stepper phase will be detected on the first
# home and that phase will be used on all subsequent homes.
#homing_endstop_align_zero: False
# If true then the code will arrange for the zero position on the
# axis to occur at a full step on the stepper motor. (If used on the
# Z axis and the print layer height is a multiple of a full step
# distance then every layer will occur on a full step.) The default
# is False.
# Heater cooling fans (one may define any number of sections with a
# "heater_fan" prefix). A "heater fan" is a fan that will be enabled
# whenever its associated heater is active. In the event of an MCU
# software error the heater_fan will be set to its max_power.
#[heater_fan my_nozzle_fan]
# See the "fan" section for fan configuration parameters.
#pin: ar4
# The remaining variables are specific to heater_fan.
#heater: extruder
# Name of the config section defining the heater that this fan is
# associated with. The default is "extruder".
#heater_temp: 50.0
# A temperature (in Celsius) that the heater must drop below before
# the fan is disabled. The default is 50 Celsius.
#fan_speed:
# The fan speed (expressed as a value from 0.0 to 1.0) that the fan
# will be set to when its associated heater is enabled. The default
# is max_power.
# Additional micro-controllers (one may define any number of sections
# with an "mcu" prefix). Additional micro-controllers introduce
# additional pins that may be configured as heaters, steppers, fans,
# etc.. For example, if an "[mcu extra_mcu]" section is introduced,
# then pins such as "extra_mcu:ar9" may then be used elsewhere in the
# config (where "ar9" is a hardware pin name or alias name on the
# given mcu).
#[mcu my_extra_mcu]
# See the "mcu" section in example.cfg for configuration parameters.
# Servos (one may define any number of sections with a "servo"
# prefix). The servos may be controlled using the SET_SERVO g-code
# command. For example: SET_SERVO SERVO=my_servo ANGLE=180
#[servo my_servo]
#pin: ar7
# PWM output pin controlling the servo. This parameter must be
# provided.
#maximum_servo_angle: 180
# The maximum angle (in degrees) that this servo can be set to. The
# default is 180 degrees.
#minimum_pulse_width: 0.001
# The minimum pulse width time (in seconds). This should correspond
# with an angle of 0 degrees. The default is 0.001 seconds.
#maximum_pulse_width: 0.002
# The maximum pulse width time (in seconds). This should correspond
# with an angle of maximum_servo_angle. The default is 0.002
# seconds.
# Statically configured digital output pins (one may define any number
# of sections with a "static_digital_output" prefix). Pins configured
# here will be setup as a GPIO output during MCU configuration. They
# can not be changed at run-time.
#[static_digital_output my_output_pins]
#pins:
# A comma separated list of pins to be set as GPIO output pins. The
# pin will be set to a high level unless the pin name is prefaced
# with "!". This parameter must be provided.
# Run-time configurable output pins (one may define any number of
# sections with an "output_pin" prefix). Pins configured here will be
# setup as output pins and one may modify them at run-time using the
# "SET_PIN PIN=my_pin VALUE=.1" extended g-code command.
#[output_pin my_pin]
#pin:
# The pin to configure as an output. This parameter must be
# provided.
#pwm: False
# Set if the output pin should be capable of
# pulse-width-modulation. If this is true, the value fields should
# be between 0 and 1; if it is false the value fields should be
# either 0 or 1. The default is False.
#static_value:
# If this is set, then the pin is assigned to this value at startup
# and the pin can not be changed during runtime. A static pin uses
# slightly less ram in the micro-controller. The default is to use
# runtime configuration of pins.
#value:
# The value to initially set the pin to during MCU
# configuration. The default is 0 (for low voltage).
#shutdown_value:
# The value to set the pin to on an MCU shutdown event. The default
# is 0 (for low voltage).
#cycle_time: 0.100
# The amount of time (in seconds) per PWM cycle. It is recommended
# this be 10 milliseconds or greater when using software based
# PWM. The default is 0.100 seconds for pwm pins.
#hardware_pwm: False
# Enable this to use hardware PWM instead of software PWM. The
# default is False.
#scale:
# This parameter can be used to alter how the 'value' and
# 'shutdown_value' parameters are interpreted for pwm pins. If
# provided, then the 'value' parameter should be between 0.0 and
# 'scale'. This may be useful when configuring a PWM pin that
# controls a stepper voltage reference. The 'scale' can be set to
# the equivalent stepper amperage if the PWM were fully enabled, and
# then the 'value' parameter can be specified using the desired
# amperage for the stepper. The default is to not scale the 'value'
# parameter.
# Multiple pin outputs (one may define any number of sections with a
# "multi_pin" prefix). A multi_pin output creates an internal pin
# alias that can modify multiple output pins each time the alias pin
# is set. For example, one could define a "[multi_pin my_fan]" object
# containing two pins and then set "pin=multi_pin:my_fan" in the
# "[fan]" section - on each fan change both output pins would be
# updated. These aliases may not be used with stepper motor pins.
#[multi_pin my_multi_pin]
#pins:
# A comma separated list of pins associated with this alias. This
# parameter must be provided.
# Statically configured AD5206 digipots connected via SPI bus (one may
# define any number of sections with an "ad5206" prefix).
#[ad5206 my_digipot]
#enable_pin:
# The pin corresponding to the AD5206 chip select line. This pin
# will be set to low at the start of SPI messages and raised to high
# after the message completes. This parameter must be provided.
#channel_1:
#channel_2:
#channel_3:
#channel_4:
#channel_5:
#channel_6:
# The value to statically set the given AD5206 channel to. This is
# typically set to a number between 0.0 and 1.0 with 1.0 being the
# highest resistance and 0.0 being the lowest resistance. However,
# the range may be changed with the 'scale' parameter (see
# below). If a channel is not specified then it is left
# unconfigured.
#scale:
# This parameter can be used to alter how the 'channel_x' parameters
# are interpreted. If provided, then the 'channel_x' parameters
# should be between 0.0 and 'scale'. This may be useful when the
# AD5206 is used to set stepper voltage references. The 'scale' can
# be set to the equivalent stepper amperage if the AD5206 were at
# its highest resistance, and then the 'channel_x' parameters can be
# specified using the desired amperage value for the stepper. The
# default is to not scale the 'channel_x' parameters.
# Homing override. One may use this mechanism to run a series of
# g-code commands in place of a G28 found in the normal g-code input.
# This may be useful on printers that require a specific procedure to
# home the machine.
#[homing_override]
#gcode:
# A list of G-Code commands (one per line) to execute in place of
# all G28 commands found in the normal g-code input. If a G28 is
# contained in this list of commands then it will invoke the normal
# homing procedure for the printer. The commands listed here must
# home all axes. This parameter must be provided.
#set_position_x:
#set_position_y:
#set_position_z:
# If specified, the printer will assume the axis is at the specified
# position prior to running the above g-code commands. Setting this
# disables homing checks for that axis. This may be useful if the
# head must move prior to invoking the normal G28 mechanism for an
# axis. The default is to not force a position for an axis.
# A virtual sdcard may be useful if the host machine is not fast
# enough to run OctoPrint well. It allows the Klipper host software to
# directly print gcode files stored in a directory on the host using
# standard sdcard G-Code commands (eg, M24).
#[virtual_sdcard]
#path: ~/.octoprint/uploads/
# The path of the local directory on the host machine to look for
# g-code files. This is a read-only directory (sdcard file writes
# are not supported). One may point this to OctoPrint's upload
# directory (generally ~/.octoprint/uploads/ ). This parameter must
# be provided.
# Support for a display attached to the micro-controller.
#[display]
#lcd_type:
# The type of LCD chip in use. This may be either "hd44780" (which
# is used in "RepRapDiscount 2004 Smart Controller" type displays)
# or "st7920" (which is used in "RepRapDiscount 12864 Full Graphic
# Smart Controller" type displays). This parameter must be
# provided.
#rs_pin:
#e_pin:
#d4_pin:
#d5_pin:
#d6_pin:
#d7_pin:
# The pins connected to an hd44780 type lcd. These parameters must
# be provided when using an hd44780 display.
#cs_pin:
#sclk_pin:
#sid_pin:
# The pins connected to an st7920 type lcd. These parameters must
# be provided when using an st7920 display.
# Replicape support - see the generic-replicape.cfg file for further
# details.
#[replicape]

View File

@@ -0,0 +1,87 @@
# This file contains an example configuration with three
# micro-controllers simultaneously controlling a single printer.
# See both the example.cfg and example-extras.cfg file for a
# description of available parameters.
# The main micro-controller is used as the timing source for all the
# micro-controllers on the printer. Typically, both the X and Y axes
# are connected to the main micro-controller.
[mcu]
serial: /dev/ttyACM0
pin_map: arduino
# The "zboard" micro-controller will be used to control the Z axis.
[mcu zboard]
serial: /dev/ttyACM1
pin_map: arduino
# The "auxboard" micro-controller will be used to control the heaters.
[mcu auxboard]
serial: /dev/ttyACM2
pin_map: arduino
[stepper_x]
step_pin: ar54
dir_pin: ar55
enable_pin: !ar38
step_distance: .0125
endstop_pin: ^ar3
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: ar60
dir_pin: !ar61
enable_pin: !ar56
step_distance: .0125
endstop_pin: ^ar14
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: zboard:ar46
dir_pin: zboard:ar48
enable_pin: !zboard:ar62
step_distance: .0025
endstop_pin: ^zboard:ar18
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: auxboard:ar26
dir_pin: auxboard:ar28
enable_pin: !auxboard:ar24
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: auxboard:ar10
sensor_type: EPCOS 100K B57560G104F
sensor_pin: auxboard:analog13
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: auxboard:ar8
sensor_type: EPCOS 100K B57560G104F
sensor_pin: auxboard:analog14
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: auxboard:ar9
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100

View File

@@ -1,6 +1,9 @@
# This file serves as documentation for config parameters. One may
# copy and edit this file to configure a new cartesian style
# printer. For delta style printers, see the "example-delta.cfg" file.
# printer. For delta style printers, see the "example-delta.cfg"
# file. For corexy/h-bot style printers, see the "example-corexy.cfg"
# file. Only common config sections are described here - see the
# "example-extras.cfg" file for configuring less common devices.
# DO NOT COPY THIS FILE WITHOUT CAREFULLY READING AND UPDATING IT
# FIRST. Incorrectly configured parameters may cause damage.
@@ -16,76 +19,66 @@
# The stepper_x section is used to describe the stepper controlling
# the X axis in a cartesian robot
# the X axis in a cartesian robot.
[stepper_x]
step_pin: ar29
# Step GPIO pin (triggered high)
dir_pin: !ar28
# Direction GPIO pin (high indicates positive direction)
enable_pin: !ar25
# Enable pin (default is enable high; use ! to indicate enable low)
step_pin: ar54
# Step GPIO pin (triggered high). This parameter must be provided.
dir_pin: ar55
# Direction GPIO pin (high indicates positive direction). This
# parameter must be provided.
enable_pin: !ar38
# Enable pin (default is enable high; use ! to indicate enable
# low). If this parameter is not provided then the stepper motor
# driver must always be enabled.
step_distance: .0225
# Distance in mm that each step causes the axis to travel
endstop_pin: ^ar0
# Endstop switch detection pin
homing_speed: 50.0
# Maximum velocity (in mm/s) of the stepper when homing
homing_retract_dist: 5.0
# Distance to backoff (in mm) before homing a second time during homing
homing_positive_dir: False
# If true, homes in a positive direction (away from zero)
homing_stepper_phases: 0
# One may optionally set this to the number of phases of the stepper
# motor driver (which is the number of micro-steps multiplied by
# four). When set, the phase of the stepper driver will be used
# during homing to improve the accuracy of the endstop switch.
homing_endstop_accuracy: 0.200
# Sets the expected accuracy (in mm) of the endstop. This represents
# the maximum error distance the endstop may trigger (eg, if an
# endstop may occasionally trigger 100um early or up to 100um late
# then set this to 0.200 for 200um). This setting is used with
# homing_stepper_phases and is only useful if that parameter is also
# configured.
#homing_endstop_phase: 0
# This specifies the phase of the stepper motor driver to expect
# when hitting the endstop. This setting is only meaningful if
# homing_stepper_phases is also set. Only set this value if one is
# sure the stepper motor driver is reset every time the mcu is
# reset. If this is not set, but homing_stepper_phases is set, then
# the stepper phase will be detected on the first home and that
# phase will be used on all subsequent homes.
position_min: -0.25
# Distance in mm that each step causes the axis to travel. This
# parameter must be provided.
endstop_pin: ^ar3
# Endstop switch detection pin. This parameter must be provided for
# the X, Y, and Z steppers on cartesian style printers.
#position_min: 0
# Minimum valid distance (in mm) the user may command the stepper to
# move to
# move to. The default is 0mm.
position_endstop: 0
# Location of the endstop (in mm)
# Location of the endstop (in mm). This parameter must be provided
# for the X, Y, and Z steppers on cartesian style printers.
position_max: 200
# Maximum valid distance (in mm) the user may command the stepper to
# move to
# move to. This parameter must be provided for the X, Y, and Z
# steppers on cartesian style printers.
#homing_speed: 5.0
# Maximum velocity (in mm/s) of the stepper when homing. The default
# is 5mm/s.
#homing_retract_dist: 5.0
# Distance to backoff (in mm) before homing a second time during
# homing. The default is 5mm.
#homing_positive_dir:
# If true, homing will cause the stepper to move in a positive
# direction (away from zero); if false, home towards zero. The
# default is true if position_endstop is near position_max and false
# if near position_min.
# The stepper_y section is used to describe the stepper controlling
# the Y axis in a cartesian robot. It has the same settings as the
# stepper_x section
# stepper_x section.
[stepper_y]
step_pin: ar27
dir_pin: ar26
enable_pin: !ar25
step_pin: ar60
dir_pin: !ar61
enable_pin: !ar56
step_distance: .0225
endstop_pin: ^ar1
position_min: -0.25
endstop_pin: ^ar14
position_endstop: 0
position_max: 200
# The stepper_z section is used to describe the stepper controlling
# the Z axis in a cartesian robot. It has the same settings as the
# stepper_x section
# stepper_x section.
[stepper_z]
step_pin: ar23
dir_pin: !ar22
enable_pin: !ar25
step_pin: ar46
dir_pin: ar48
enable_pin: !ar62
step_distance: .005
endstop_pin: ^ar2
position_min: 0.1
endstop_pin: ^ar18
position_endstop: 0.5
position_max: 200
@@ -93,119 +86,209 @@ position_max: 200
# controlling the printer extruder and the heater parameters for the
# nozzle. The stepper configuration has the same settings as the
# stepper_x section and the heater configuration has the same settings
# as the heater_bed section
# as the heater_bed section (described below).
[extruder]
step_pin: ar19
dir_pin: ar18
enable_pin: !ar25
step_pin: ar26
dir_pin: ar28
enable_pin: !ar24
step_distance: .004242
max_velocity: 200000
nozzle_diameter: 0.500
# Diameter of the nozzle orifice (in mm). This parameter must be
# provided.
filament_diameter: 3.500
# Diameter of the raw filament (in mm) as it enters the
# extruder. This parameter must be provided.
#max_extrude_cross_section:
# Maximum area of the cross section of an extrusion line (in
# mm^2). This setting prevents excessive amounts of extrusion during
# relatively small XY moves. If a move requests an extrusion rate
# that would exceed this value it will cause an error to be
# returned. The default is: 4.0 * nozzle_diameter^2
#max_extrude_only_distance: 50.0
# Maximum length (in mm of raw filament) that an extrude only move
# may be. If an extrude only move requests a distance greater than
# this value it will cause an error to be returned. The default is
# 50mm.
#max_extrude_only_velocity:
# Maximum velocity (in mm/s) of the extruder motor for extrude only
# moves.
max_accel: 3000
# moves. If this is not specified then it is calculated to match the
# limit an XY printing move with a max_extrude_cross_section
# extrusion would have.
#max_extrude_only_accel:
# Maximum acceleration (in mm/s^2) of the extruder motor for extrude
# only moves.
#
# The remaining variables describe the extruder heater
pressure_advance: 0.0
# only moves. If this is not specified then it is calculated to
# match the limit an XY printing move with a
# max_extrude_cross_section extrusion would have.
#pressure_advance: 0.0
# The amount of raw filament to push into the extruder during
# extruder acceleration. An equal amount of filament is retracted
# during deceleration. It is measured in millimeters per
# millimeter/second
heater_pin: ar4
# PWM output pin controlling the heater
thermistor_pin: analog1
# Analog input pin connected to thermistor
thermistor_type: EPCOS 100K B57560G104F
# Type of thermistor (see klippy/heater.py for available types)
pullup_resistor: 4700
# The resistance (in ohms) of the pullup attached to the thermistor
# millimeter/second. The default is 0, which disables pressure
# advance.
#pressure_advance_lookahead_time: 0.010
# A time (in seconds) to "look ahead" at future extrusion moves when
# calculating pressure advance. This is used to reduce the
# application of pressure advance during cornering moves that would
# otherwise cause retraction followed immediately by pressure
# buildup. This setting only applies if pressure_advance is
# non-zero. The default is 0.010 (10 milliseconds).
#
# The remaining variables describe the extruder heater.
heater_pin: ar10
# PWM output pin controlling the heater. This parameter must be
# provided.
#max_power: 1.0
# The maximum power (expressed as a value from 0.0 to 1.0) that the
# heater_pin may be set to. The value 1.0 allows the pin to be set
# fully enabled for extended periods, while a value of 0.5 would
# allow the pin to be enabled for no more than half the time. This
# setting may be used to limit the total power output (over extended
# periods) to the heater. The default is 1.0.
sensor_type: EPCOS 100K B57560G104F
# Type of sensor - this may be "EPCOS 100K B57560G104F", "ATC
# Semitec 104GT-2", "NTC 100K beta 3950", or "AD595". This parameter
# must be provided.
sensor_pin: analog13
# Analog input pin connected to the sensor. This parameter must be
# provided.
#pullup_resistor: 4700
# The resistance (in ohms) of the pullup attached to the
# thermistor. This parameter is only valid when the sensor is a
# thermistor. The default is 4700 ohms.
#adc_voltage: 5.0
# The ADC comparison voltage. This parameter is only valid when the
# sensor is an AD595. The default is 5 volts.
control: pid
# Control algorithm (either pid or watermark)
# Control algorithm (either pid or watermark). This parameter must
# be provided.
pid_Kp: 22.2
# Kp is the "proportional" constant for the pid
# Kp is the "proportional" constant for the pid. This parameter must
# be provided for PID heaters.
pid_Ki: 1.08
# Ki is the "integral" constant for the pid
# Ki is the "integral" constant for the pid. This parameter must be
# provided for PID heaters.
pid_Kd: 114
# Kd is the "derivative" constant for the pid
pid_deriv_time: 2.0
# Kd is the "derivative" constant for the pid. This parameter must
# be provided for PID heaters.
#pid_deriv_time: 2.0
# A time value (in seconds) over which the derivative in the pid
# will be smoothed to reduce the impact of measurement noise
pid_integral_max: 255
# The maximum "windup" the integral term may accumulate
min_extrude_temp: 170
# will be smoothed to reduce the impact of measurement noise. The
# default is 2 seconds.
#pid_integral_max:
# The maximum "windup" the integral term may accumulate. The default
# is to use the same value as max_power.
#pwm_cycle_time: 0.100
# Time in seconds for each software PWM cycle of the heater. It is
# not recommended to set this unless there is an electrical
# requirement to switch the heater faster than 10 times a second.
# The default is 0.100 seconds.
#min_extrude_temp: 170
# The minimum temperature (in Celsius) at which extruder move
# commands may be issued
# commands may be issued. The default is 170 Celsius.
min_temp: 0
# Minimum temperature in Celsius (mcu will shutdown if not met)
max_temp: 210
# Maximum temperature (mcu will shutdown if temperature is above
# this value)
# The maximum range of valid temperatures (in Celsius) that the
# heater must remain within. This controls a safety feature
# implemented in the micro-controller code - should the measured
# temperature ever fall outside this range then the micro-controller
# will go into a shutdown state. This check can help detect some
# heater and sensor hardware failures. Set this range just wide
# enough so that reasonable temperatures do not result in an
# error. These parameters must be provided.
# The heater_bed section describes a heated bed (if present - omit
# section if not present).
[heater_bed]
heater_pin: ar3
thermistor_pin: analog0
thermistor_type: EPCOS 100K B57560G104F
heater_pin: ar8
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog14
control: watermark
max_delta: 2.0
# The number of degrees in Celsius above the target temperature
# before disabling the heater as well as the number of degrees below
# the target before re-enabling the heater.
#max_delta: 2.0
# On 'watermark' controlled heaters this is the number of degrees in
# Celsius above the target temperature before disabling the heater
# as well as the number of degrees below the target before
# re-enabling the heater. The default is 2 degrees Celsius.
min_temp: 0
max_temp: 110
# Extruder print fan (omit section if fan not present)
# Print cooling fan (omit section if fan not present).
[fan]
pin: ar14
# PWM output pin controlling the heater
hard_pwm: 1
# Set this value to force hardware PWM instead of software PWM. Set
# to 1 to force a hardware PWM at the fastest rate; set to a higher
# number (eg, 1024) to force hardware PWM with the given cycle time
# in clock ticks.
kick_start_time: 0.100
pin: ar9
# PWM output pin controlling the fan. This parameter must be
# provided.
#max_power: 1.0
# The maximum power (expressed as a value from 0.0 to 1.0) that the
# pin may be set to. The value 1.0 allows the pin to be set fully
# enabled for extended periods, while a value of 0.5 would allow the
# pin to be enabled for no more than half the time. This setting may
# be used to limit the total power output (over extended periods) to
# the fan. The default is 1.0.
#cycle_time: 0.010
# The amount of time (in seconds) for each PWM power cycle to the
# fan. It is recommended this be 10 milliseconds or greater when
# using software based PWM. The default is 0.010 seconds.
#hardware_pwm: False
# Enable this to use hardware PWM instead of software PWM. The
# default is False.
#kick_start_time: 0.100
# Time (in seconds) to run the fan at full speed when first enabling
# it (helps get the fan spinning)
# it (helps get the fan spinning). The default is 0.100 seconds.
# Micro-controller information
# Micro-controller information.
[mcu]
serial: /dev/ttyACM0
# The serial port to connect to the MCU
baud: 250000
# The baud rate to use
# The serial port to connect to the MCU. The default is /dev/ttyS0
#baud: 250000
# The baud rate to use. The default is 250000.
pin_map: arduino
# This option may be used to enable Arduino pin name aliases
custom:
# This option may be used to specify a set of custom
# micro-controller commands to be sent at the start of the
# connection. It may be used to configure the initial settings of
# LEDs, to configure micro-stepping pins, to configure a digipot,
# etc.
# This option may be used to enable Arduino pin name aliases. The
# default is to not enable the aliases.
#restart_method:
# This controls the mechanism the host will use to reset the
# micro-controller. The choices are 'arduino', 'rpi_usb', and
# 'command'. The 'arduino' method (toggle DTR) is common on Arduino
# boards and clones. The 'rpi_usb' method is useful on Raspberry Pi
# boards with micro-controllers powered over USB - it briefly
# disables power to all USB ports to accomplish a micro-controller
# reset. The 'command' method involves sending a Klipper command to
# the micro-controller so that it can reset itself. The default is
# 'arduino' if the micro-controller communicates over a serial port,
# 'command' otherwise.
# The printer section controls high level printer settings
# The printer section controls high level printer settings.
[printer]
kinematics: cartesian
# This option must be "cartesian" for cartesian printers
# This option must be "cartesian" for cartesian printers.
max_velocity: 500
# Maximum velocity (in mm/s) of the toolhead (relative to the
# print)
# print). This parameter must be specified.
max_accel: 3000
# Maximum acceleration (in mm/s^2) of the toolhead (relative to the
# print)
max_z_velocity: 250
# print). This parameter must be specified.
#max_accel_to_decel:
# A pseudo acceleration (in mm/s^2) controlling how fast the
# toolhead may go from acceleration to deceleration. It is used to
# reduce the top speed of short zig-zag moves (and thus reduce
# printer vibration from these moves). The default is half of
# max_accel.
max_z_velocity: 25
# For cartesian printers this sets the maximum velocity (in mm/s) of
# movement along the z axis. This setting can be used to restrict
# the maximum speed of the z stepper motor on cartesian printers.
# the maximum speed of the z stepper motor on cartesian
# printers. The default is to use max_velocity for max_z_velocity.
max_z_accel: 30
# For cartesian printers this sets the maximum acceleration (in
# mm/s^2) of movement along the z axis. It limits the acceleration
# of the z stepper motor on cartesian printers.
motor_off_time: 60
# of the z stepper motor on cartesian printers. The default is to
# use max_accel for max_z_accel.
#motor_off_time: 600
# Time (in seconds) of idle time before the printer will try to
# disable active motors.
junction_deviation: 0.02
# disable active motors. The default is 600 seconds.
#junction_deviation: 0.02
# Distance (in mm) used to control the internal approximated
# centripetal velocity cornering algorithm. A larger number will
# permit higher "cornering speeds" at the junction of two moves.
# permit higher "cornering speeds" at the junction of two moves. The
# default is 0.02mm.
# Looking for more options? Check the example-extras.cfg file.

86
config/generic-cramps.cfg Normal file
View File

@@ -0,0 +1,86 @@
# This file contains an example configuration for a Beaglebone PRU
# micro-controller attached to a CRAMPS board.
# THIS FILE HAS NOT BEEN TESTED - PROCEED WITH CAUTION!
# NOTE: Klipper does not alter the input/output state of the
# Beaglebone pins and it does not control their pull-up resistors. In
# order to set the pin state one must use a "device tree overlay" or
# use the config-pin program.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: P8_13
dir_pin: P8_12
enable_pin: !P9_14
step_distance: .0125
endstop_pin: ^P8_8
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: P8_15
dir_pin: P8_14
enable_pin: !P9_14
step_distance: .0125
endstop_pin: ^P8_10
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: P8_19
dir_pin: P8_18
enable_pin: !P9_14
step_distance: .0025
endstop_pin: ^P9_13
position_endstop: 0
position_max: 200
[extruder]
step_pin: P9_16
dir_pin: P9_12
enable_pin: !P9_14
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: P9_15
sensor_type: EPCOS 100K B57560G104F
pullup_resistor: 2000
sensor_pin: P9_36
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: P8_11
sensor_type: EPCOS 100K B57560G104F
pullup_resistor: 2000
sensor_pin: P9_33
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: P9_41
[mcu]
serial: /dev/rpmsg_pru30
pin_map: beaglebone
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100
[output_pin machine_enable]
pin: P9_23
value: 1
shutdown_value: 0

79
config/generic-melzi.cfg Normal file
View File

@@ -0,0 +1,79 @@
# This file contains common pin mappings for Melzi v2.0 boards. To use
# this config, the firmware should be compiled for the AVR
# atmega1284p.
# Note, a number of Melzi boards are shipped without a bootloader. In
# that case, an external programmer will be needed to flash a
# bootloader to the board (for example, see
# http://www.instructables.com/id/Flashing-a-Bootloader-to-the-CR-10/
# ). Once that is done, one should be able to use the standard "make
# flash" command to flash Klipper.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PD7
dir_pin: PC5
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^!PC2
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: PC6
dir_pin: PC7
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^!PC3
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: PB3
dir_pin: !PB2
enable_pin: !PA5
step_distance: .0025
endstop_pin: ^!PC4
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: PB1
dir_pin: PB0
enable_pin: !PD6
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PD5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA7
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: PD2
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA6
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: PB4
[mcu]
serial: /dev/ttyUSB0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100

View File

@@ -0,0 +1,109 @@
# This file contains common pin mappings for Mini-RAMBo boards. To use
# this config, the firmware should be compiled for the AVR atmega2560.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PC0
dir_pin: PL1
enable_pin: !PA7
step_distance: .005
endstop_pin: ^PB6
#endstop_pin: ^PC7
position_endstop: 0
position_max: 250
[stepper_y]
step_pin: PC1
dir_pin: !PL0
enable_pin: !PA6
step_distance: .005
endstop_pin: ^PB5
#endstop_pin: ^PA2
position_endstop: 0
position_max: 210
[stepper_z]
step_pin: PC2
dir_pin: PL2
enable_pin: !PA5
step_distance: .0025
endstop_pin: ^PB4
#endstop_pin: ^PA1
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: PC3
dir_pin: PL6
enable_pin: !PA4
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PE5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF0
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: PG5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF2
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: PH5
#[heater_fan nozzle_cooling_fan]
#pin: PH3
[mcu]
serial: /dev/ttyACM0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100
[output_pin stepper_xy_current]
pin: PL3
pwm: True
scale: 2.0
cycle_time: .002
hardware_pwm: True
static_value: 1.3
[output_pin stepper_z_current]
pin: PL4
pwm: True
scale: 2.0
cycle_time: .002
hardware_pwm: True
static_value: 1.3
[output_pin stepper_e_current]
pin: PL5
pwm: True
scale: 2.0
cycle_time: .002
hardware_pwm: True
static_value: 1.25
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4
[static_digital_output yellow_led]
pins: !PB7

View File

@@ -0,0 +1,76 @@
# This file contains common pin mappings for Printrboard boards (rev B
# through D). To use this config the firmware should be compiled for
# the AVR at90usb1286.
# Note that the "make flash" command is unlikely to work on the
# Printrboard. See the RepRap Printrboard wiki page for instructions
# on flashing.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PA0
dir_pin: !PA1
enable_pin: !PE7
step_distance: .0125
endstop_pin: ^PE3
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: PA2
dir_pin: PA3
enable_pin: !PE6
step_distance: .0125
endstop_pin: ^PB0
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: PA4
dir_pin: !PA5
enable_pin: !PC7
step_distance: .0025
endstop_pin: ^PE4
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: PA6
dir_pin: PA7
enable_pin: !PC3
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PC5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF1
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: PC4
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF0
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: PC6
[mcu]
serial: /dev/ttyACM0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100

126
config/generic-rambo.cfg Normal file
View File

@@ -0,0 +1,126 @@
# This file contains common pin mappings for RAMBo boards. To use this
# config, the firmware should be compiled for the AVR atmega2560.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PC0
dir_pin: PL1
enable_pin: !PA7
step_distance: .0125
endstop_pin: ^PB6
#endstop_pin: ^PA2
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: PC1
dir_pin: !PL0
enable_pin: !PA6
step_distance: .0125
endstop_pin: ^PB5
#endstop_pin: ^PA1
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: PC2
dir_pin: PL2
enable_pin: !PA5
step_distance: .0025
endstop_pin: ^PB4
#endstop_pin: ^PC7
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: PC3
dir_pin: PL6
enable_pin: !PA4
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PH6
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF0
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
#[extruder1]
#step_pin: PC4
#dir_pin: PL7
#enable_pin: !PA3
#heater_pin: PH4
#sensor_pin: PF1
#...
[heater_bed]
heater_pin: PE5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF2
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: PH5
#[heater_fan nozzle_cooling_fan]
#pin: PH3
[mcu]
serial: /dev/ttyACM0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100
[ad5206 stepper_digipot]
enable_pin: PD7
# Scale the config so that the channel value can be specified in amps.
# (For Rambo v1.0d boards, use 1.56 instead.)
scale: 2.08
# Channel 1 is E0, 2 is E1, 3 is unused, 4 is Z, 5 is X, 6 is Y
channel_1: 1.34
channel_2: 1.0
channel_4: 1.1
channel_5: 1.1
channel_6: 1.1
# Enable 16 micro-steps on steppers X, Y, Z, E0, E1
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4,
PK1, PK2
[static_digital_output yellow_led]
pins: !PB7
# "RepRapDiscount 2004 Smart Controller" type displays
#[display]
#lcd_type: hd44780
#rs_pin: PG4
#e_pin: PG3
#d4_pin: PJ2
#d5_pin: PJ3
#d6_pin: PJ7
#d7_pin: PJ4
# "RepRapDiscount 128x64 Full Graphic Smart Controller" type displays
#[display]
#lcd_type: st7920
#cs_pin: PG4
#sclk_pin: PJ2
#sid_pin: PG3

101
config/generic-ramps.cfg Normal file
View File

@@ -0,0 +1,101 @@
# This file contains common pin mappings for RAMPS (v1.3 and later)
# boards. RAMPS boards typically use a firmware compiled for the AVR
# atmega2560 (though other AVR chips are also possible).
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: ar54
dir_pin: ar55
enable_pin: !ar38
step_distance: .0125
endstop_pin: ^ar3
#endstop_pin: ^ar2
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: ar60
dir_pin: !ar61
enable_pin: !ar56
step_distance: .0125
endstop_pin: ^ar14
#endstop_pin: ^ar15
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: ar46
dir_pin: ar48
enable_pin: !ar62
step_distance: .0025
endstop_pin: ^ar18
#endstop_pin: ^ar19
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: ar26
dir_pin: ar28
enable_pin: !ar24
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: ar10
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog13
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
#[extruder1]
#step_pin: ar36
#dir_pin: ar34
#enable_pin: !ar30
#heater_pin: ar9
#sensor_pin: analog15
#...
[heater_bed]
heater_pin: ar8
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog14
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: ar9
[mcu]
serial: /dev/ttyACM0
pin_map: arduino
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100
# "RepRapDiscount 2004 Smart Controller" type displays
#[display]
#lcd_type: hd44780
#rs_pin: ar16
#e_pin: ar17
#d4_pin: ar23
#d5_pin: ar25
#d6_pin: ar27
#d7_pin: ar29
# "RepRapDiscount 128x64 Full Graphic Smart Controller" type displays
#[display]
#lcd_type: st7920
#cs_pin: ar16
#sclk_pin: ar23
#sid_pin: ar17

View File

@@ -0,0 +1,134 @@
# This file contains an example configuration for the Replicape rev B3
# board. To use this config, one must compile and install the
# micro-controller code for the "Beaglebone PRU", and then compile and
# install the micro-controller code a second time for a "Linux
# process".
# NOTE: Klipper does not alter the input/output state of the
# Beaglebone pins and it does not control their pull-up resistors.
# Typically the correct settings are automatically applied when the
# Beaglebone detects the Replicape board, but if changes are needed
# they must be specified in a "device tree overlay" or via the
# config-pin program.
# See the example.cfg file for a description of available parameters.
[mcu]
serial: /dev/rpmsg_pru30
pin_map: beaglebone
[mcu host]
serial: /tmp/klipper_host_mcu
# The "replicape" config section adds "replicape:stepper_x_enable"
# virtual stepper enable pins (for steppers x, y, z, e, and h) and
# "replicape:power_x" PWM output pins (for hotbed, e, h, fan0, fan1,
# fan2, and fan3) that may then be used elsewhere in the config file.
[replicape]
revision: B3
# The replicape hardware revision. Currently only revision "B3" is
# supported. This parameter must be provided.
#enable_pin: !P9_41
# The replicape global enable pin. The default is !P9_41.
host_mcu: host
# The name of the mcu config section that communicates with the
# Klipper "linux process" mcu instance. This parameter must be
# provided.
#standstill_power_down: False
# This parameter controls the CFG6_ENN line on all stepper
# motors. True sets the enable lines to "open". The default is
# False.
#servo0_enable: False
# This parameter controls whether end_stop_X_2 is used for endstops
# (via P9_11) or for servo_0 (via P9_14). The default is False.
#servo1_enable: False
# This parameter controls whether end_stop_Y_2 is used for endstops
# (via P9_28) or for servo_1 (via P9_16). The default is False.
stepper_x_microstep_mode: spread16
# This parameter controls the CFG1 and CFG2 pins of the given
# stepper motor driver. Available options are: disable, 1, 2,
# spread2, 4, 16, spread4, spread16, stealth4, and stealth16. The
# default is disable.
stepper_x_current: 0.5
# The configured maximum current (in Amps) of the stepper motor
# driver. This parameter must be provided if the stepper is not in a
# disable mode.
#stepper_x_chopper_off_time_high: False
# This parameter controls the CFG0 pin of the stepper motor driver
# (True sets CFG0 high, False sets it low). The default is False.
#stepper_x_chopper_hysteresis_high: False
# This parameter controls the CFG4 pin of the stepper motor driver
# (True sets CFG4 high, False sets it low). The default is False.
#stepper_x_chopper_blank_time_high: True
# This parameter controls the CFG5 pin of the stepper motor driver
# (True sets CFG5 high, False sets it low). The default is True.
stepper_y_microstep_mode: spread16
stepper_y_current: 0.5
stepper_z_microstep_mode: spread16
stepper_z_current: 0.5
stepper_e_microstep_mode: 16
stepper_e_current: 0.5
[stepper_x]
step_pin: P8_17
dir_pin: P8_26
enable_pin: replicape:stepper_x_enable
step_distance: .0125
endstop_pin: ^P9_25
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_y]
step_pin: P8_12
dir_pin: P8_19
enable_pin: replicape:stepper_y_enable
step_distance: .0125
endstop_pin: ^P9_23
position_endstop: 0
position_max: 200
homing_speed: 50
[stepper_z]
step_pin: P8_13
dir_pin: P8_14
enable_pin: replicape:stepper_z_enable
step_distance: .0025
endstop_pin: ^P9_13
position_endstop: 0
position_max: 200
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 25
max_z_accel: 30
[extruder]
step_pin: P9_12
dir_pin: P8_15
enable_pin: replicape:stepper_e_enable
step_distance: .002
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: replicape:power_e
sensor_type: EPCOS 100K B57560G104F
sensor_pin: host:analog4
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: replicape:power_hotbed
sensor_type: EPCOS 100K B57560G104F
sensor_pin: host:analog6
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: replicape:power_fan0

View File

@@ -0,0 +1,79 @@
# This file contains common pin mappings for Anet A8 printer from 2016
# and 2017. To use this config, the firmware should be compiled for
# the AVR atmega1284p.
# Note that the "make flash" command does not work with Anet boards -
# the boards are typically flashed with this command:
# avrdude -p atmega1284p -c arduino -b 57600 -P /dev/ttyUSB0 -U out/klipper.elf.hex
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PD7
dir_pin: PC5
enable_pin: !PD6
step_distance: .01
endstop_pin: ^!PC2
position_endstop: -30
position_max: 220
position_min: -30
homing_speed: 50
[stepper_y]
step_pin: PC6
dir_pin: PC7
enable_pin: !PD6
step_distance: .01
endstop_pin: ^!PC3
position_endstop: -8
position_min: -8
position_max: 220
homing_speed: 50
[stepper_z]
step_pin: PB3
dir_pin: !PB2
enable_pin: !PA5
step_distance: .0025
endstop_pin: ^!PC4
position_endstop: 0.5
position_max: 240
homing_speed: 20
[extruder]
step_pin: PB1
dir_pin: PB0
enable_pin: !PD6
step_distance: .0105
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PD5
sensor_type: ATC Semitec 104GT-2
sensor_pin: PA7
control: pid
pid_Kp: 2.151492
pid_Ki: 0.633897
pid_Kd: 230.042965
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: PD4
sensor_type: ATC Semitec 104GT-2
sensor_pin: PA6
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: PB4
[mcu]
serial: /dev/ttyUSB0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 1000
max_z_velocity: 20
max_z_accel: 100

View File

@@ -0,0 +1,93 @@
# This file contains pin mappings for the Anycubic i3 Mega with
# Ultrabase from 2017. (This config may work on an Anycubic i3 Mega v1
# prior to the Ultrabase if you comment out the definition of the
# endstop_pin in the stepper_z1 section.) To use this config, the
# firmware should be compiled for the AVR atmega2560.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: ar54
dir_pin: !ar55
enable_pin: !ar38
step_distance: .0125
endstop_pin: ^!ar3
position_min: -5
position_endstop: -5
position_max: 210
homing_speed: 30.0
[stepper_y]
step_pin: ar60
dir_pin: ar61
enable_pin: !ar56
step_distance: .0125
endstop_pin: ^!ar42
position_endstop: 0
position_max: 210
homing_speed: 30.0
[stepper_z]
step_pin: ar46
dir_pin: ar48
enable_pin: !ar62
step_distance: .0025
endstop_pin: ^!ar18
position_endstop: 0.0
position_max: 205
homing_speed: 5.0
[stepper_z1]
step_pin: ar36
dir_pin: ar34
enable_pin: !ar30
step_distance: .0025
endstop_pin: ^!ar43
[extruder]
step_pin: ar26
dir_pin: ar28
enable_pin: !ar24
step_distance: .010799
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: ar10
sensor_type: ATC Semitec 104GT-2
sensor_pin: analog13
control: pid
pid_Kp: 15.717
pid_Ki: 0.569
pid_Kd: 108.451
min_temp: 0
max_temp: 245
[heater_fan extruder_fan]
pin: ar44
[heater_bed]
heater_pin: ar8
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog14
control: pid
pid_Kp: 74.883
pid_Ki: 1.809
pid_Kd: 775.038
min_temp: 0
max_temp: 110
[fan]
pin: ar9
[mcu]
serial: /dev/ttyUSB0
pin_map: arduino
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 10
max_z_accel: 60
[heater_fan stepstick_fan]
pin: ar7

View File

@@ -0,0 +1,88 @@
# This file contains common pin mappings for the 2017 Creality
# CR-10. To use this config, the firmware should be compiled for the
# AVR atmega1284p.
# Note, a number of Melzi boards are shipped without a bootloader. In
# that case, an external programmer will be needed to flash a
# bootloader to the board (for example, see
# http://www.instructables.com/id/Flashing-a-Bootloader-to-the-CR-10/
# ). Once that is done, one should be able to use the standard "make
# flash" command to flash Klipper.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PD7
dir_pin: !PC5
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^PC2
position_endstop: 0
position_max: 300
homing_speed: 50
[stepper_y]
step_pin: PC6
dir_pin: !PC7
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^PC3
position_endstop: 0
position_max: 300
homing_speed: 50
[stepper_z]
step_pin: PB3
dir_pin: PB2
enable_pin: !PA5
step_distance: .0025
endstop_pin: ^PC4
position_endstop: 0.0
position_max: 400
[extruder]
step_pin: PB1
dir_pin: !PB0
enable_pin: !PD6
step_distance: 0.010526
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PD5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA7
control: pid
pid_Kp: 22.57
pid_Ki: 1.72
pid_Kd: 73.96
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: PD4
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA6
control: pid
pid_Kp: 426.68
pid_Ki: 78.92
pid_Kd: 576.71
min_temp: 0
max_temp: 130
[fan]
pin: PB4
[mcu]
serial: /dev/ttyUSB0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100
[display]
lcd_type: st7920
cs_pin: PA3
sclk_pin: PA1
sid_pin: PC1

View File

@@ -0,0 +1,75 @@
# This file contains pin mappings for the 2017 Creality CR-10S. To use
# this config, the firmware should be compiled for the AVR atmega2560.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: ar54
dir_pin: ar55
enable_pin: !ar38
step_distance: .0125
endstop_pin: ^ar3
position_endstop: 0
position_max: 300
homing_speed: 50
[stepper_y]
step_pin: ar60
dir_pin: ar61
enable_pin: !ar56
step_distance: .0125
endstop_pin: ^ar14
position_endstop: 0
position_max: 300
homing_speed: 50
[stepper_z]
step_pin: ar46
dir_pin: !ar48
enable_pin: !ar62
step_distance: .0025
endstop_pin: ^ar18
position_endstop: 0.5
position_max: 200
[extruder]
step_pin: ar26
dir_pin: ar28
enable_pin: !ar24
step_distance: .010526
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: ar10
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog13
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250
[heater_bed]
heater_pin: ar8
sensor_type: EPCOS 100K B57560G104F
sensor_pin: analog14
control: pid
pid_Kp: 690.34
pid_Ki: 111.47
pid_Kd: 1068.83
min_temp: 0
max_temp: 130
[fan]
pin: ar9
[mcu]
serial: /dev/ttyUSB0
pin_map: arduino
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 5
max_z_accel: 100

View File

@@ -0,0 +1,116 @@
# This file contains pin mappings for the Lulzbot TAZ 6 circa 2017. To
# use this config, the firmware should be compiled for the AVR
# atmega2560.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PC0
dir_pin: PL1
enable_pin: !PA7
step_distance: .010000
endstop_pin: ^PB6
position_endstop: -20
position_min: -20
position_max: 300
homing_speed: 50
[stepper_y]
step_pin: PC1
dir_pin: !PL0
enable_pin: !PA6
step_distance: .010000
endstop_pin: ^PA1
position_endstop: 306
position_min: -20
position_max: 306
homing_speed: 50
[stepper_z]
step_pin: PC2
dir_pin: PL2
enable_pin: !PA5
step_distance: 0.000625
endstop_pin: ^!PB4
position_endstop: -0.7
position_min: -1.5
position_max: 270
homing_speed: 1
[extruder]
step_pin: PC3
dir_pin: !PL6
enable_pin: !PA4
step_distance: 0.001182
nozzle_diameter: 0.400
filament_diameter: 2.920
heater_pin: PH6
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF0
control: pid
pid_Kp: 28.79
pid_Ki: 1.91
pid_Kd: 108.51
min_temp: 0
max_temp: 300
min_extrude_temp: 140
#[extruder1]
#step_pin: PC4
#dir_pin: PL7
#enable_pin: !PA3
#heater_pin: PH4
#sensor_pin: PF1
#...
[heater_bed]
heater_pin: PE5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF2
control: watermark
min_temp: 0
max_temp: 130
[fan]
pin: PH5
[heater_fan nozzle_cooling_fan]
pin: PH3
[mcu]
serial: /dev/ttyACM0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 3000
max_z_velocity: 2
max_z_accel: 10
[ad5206 stepper_digipot]
enable_pin: PD7
scale: 2.08
# Channel 1 is E0, 2 is E1, 3 is unused, 4 is Z, 5 is X, 6 is Y
channel_1: 1.34
channel_2: 1.0
channel_4: 1.1
channel_5: 1.1
channel_6: 1.1
# Enable 16 micro-steps on steppers X, Y, Z, E0, E1
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4,
PK1, PK2
[static_digital_output yellow_led]
pins: !PB7
[display]
lcd_type: st7920
cs_pin: PG4
sclk_pin: PJ2
sid_pin: PG3

View File

@@ -9,12 +9,11 @@ dir_pin: !PL1
enable_pin: !PA7
step_distance: .0225
endstop_pin: ^!PB6
homing_speed: 50.0
homing_stepper_phases: 32
homing_endstop_accuracy: .200
position_min: -0.25
position_endstop: 0.0
position_max: 200
homing_speed: 50
homing_stepper_phases: 32
homing_endstop_accuracy: .200
[stepper_y]
step_pin: PC1
@@ -22,12 +21,11 @@ dir_pin: PL0
enable_pin: !PA6
step_distance: .0225
endstop_pin: ^!PB5
homing_speed: 50.0
homing_stepper_phases: 32
homing_endstop_accuracy: .200
position_min: -0.25
position_endstop: 0.0
position_max: 250
homing_speed: 50
homing_stepper_phases: 32
homing_endstop_accuracy: .200
[stepper_z]
step_pin: PC2
@@ -35,25 +33,24 @@ dir_pin: !PL2
enable_pin: !PA5
step_distance: .005
endstop_pin: ^!PB4
homing_speed: 4.0
homing_retract_dist: 2.0
homing_stepper_phases: 32
homing_endstop_accuracy: .050
position_min: 0.1
position_endstop: 0.7
position_max: 200
homing_retract_dist: 2.0
homing_stepper_phases: 32
homing_endstop_accuracy: .070
[extruder]
step_pin: PC3
dir_pin: PL6
enable_pin: !PA4
step_distance: .004242
max_velocity: 200000
max_accel: 3000
nozzle_diameter: 0.350
filament_diameter: 1.750
pressure_advance: 0.07
heater_pin: PH6
thermistor_pin: PF0
thermistor_type: EPCOS 100K B57560G104F
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF0
control: pid
pid_Kp: 7.0
pid_Ki: 0.1
@@ -63,44 +60,49 @@ max_temp: 210
[heater_bed]
heater_pin: PE5
thermistor_pin: PF2
thermistor_type: EPCOS 100K B57560G104F
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF2
control: watermark
min_temp: 0
max_temp: 100
[fan]
pin: PH5
hard_pwm: 1
[heater_fan nozzle_fan]
pin: PH3
max_power: 0.61
cycle_time: .000030
hardware_pwm: True
[mcu]
serial: /dev/ttyACM0
baud: 250000
custom:
# Nozzle fan
set_pwm_out pin=PH3 cycle_ticks=1 value=155
# Turn off yellow led
set_digital_out pin=PB7 value=0
# Stepper micro-step pins
set_digital_out pin=PG1 value=1
set_digital_out pin=PG0 value=1
set_digital_out pin=PK7 value=1
set_digital_out pin=PG2 value=1
set_digital_out pin=PK6 value=1
set_digital_out pin=PK5 value=1
set_digital_out pin=PK3 value=1
set_digital_out pin=PK4 value=1
# Initialize digipot
send_spi_message pin=PD7 msg=0487 # X = ~0.75A
send_spi_message pin=PD7 msg=0587 # Y = ~0.75A
send_spi_message pin=PD7 msg=0387 # Z = ~0.75A
send_spi_message pin=PD7 msg=00A5 # E0
send_spi_message pin=PD7 msg=017D # E1
[printer]
kinematics: cartesian
max_velocity: 500
max_accel: 3000
max_z_velocity: 250
max_z_velocity: 25
max_z_accel: 30
motor_off_time: 600
[ad5206 stepper_digipot]
enable_pin: PD7
# Scale the config so that the channel value can be specified in amps
scale: 1.56
# Channel 1 is E0, 2 is E1, 3 is unused, 4 is Z, 5 is X, 6 is Y
channel_1: 1.0
channel_2: 0.75
channel_4: 0.82
channel_5: 0.82
channel_6: 0.82
# Enable 8 micro-steps on steppers X, Y, Z, E0
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4
[static_digital_output yellow_led]
pins: !PB7

View File

@@ -0,0 +1,94 @@
# This file constains the pin mappings for the SeeMeCNC Rostock Max
# (version 2) delta printer from 2015. To use this config, the
# firmware should be compiled for the AVR atmega2560.
# See the example.cfg file for a description of available parameters.
[stepper_a]
step_pin: PC0
dir_pin: !PL1
enable_pin: !PA7
step_distance: .0125
endstop_pin: ^PA2
homing_speed: 50
position_endstop: 380
arm_length: 290.800
[stepper_b]
step_pin: PC1
dir_pin: PL0
enable_pin: !PA6
step_distance: .0125
endstop_pin: ^PA1
[stepper_c]
step_pin: PC2
dir_pin: !PL2
enable_pin: !PA5
step_distance: .0125
endstop_pin: ^PC7
[extruder]
step_pin: PC3
dir_pin: !PL6
enable_pin: !PA4
step_distance: .010793
nozzle_diameter: 0.500
filament_diameter: 1.750
heater_pin: PH6
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF0
control: pid
pid_Kp: 20.9700
pid_Ki: 1.3400
pid_Kd: 80.5600
min_temp: 0
max_temp: 300
[heater_bed]
heater_pin: PE5
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF2
control: pid
pid_Kp: 46.510
pid_Ki: 1.040
pid_Kd: 500.000
min_temp: 0
max_temp: 300
[fan]
pin: PH5
[heater_fan nozzle_cooling_fan]
pin: PH4
heater: extruder
[mcu]
serial: /dev/ttyACM0
[printer]
kinematics: delta
max_velocity: 300
max_accel: 3000
max_z_velocity: 150
delta_radius: 174.75
[ad5206 stepper_digipot]
enable_pin: PD7
scale: 2.08
channel_1: 1.34
channel_2: 1.0
channel_4: 1.1
channel_5: 1.1
channel_6: 1.1
[static_digital_output stepper_config]
pins:
PG1, PG0,
PK7, PG2,
PK6, PK5,
PK3, PK4,
PK1, PK2
[static_digital_output yellow_led]
pins: !PB7

View File

@@ -0,0 +1,89 @@
# This file contains pin mappings for the Tronxy X5S (circa 2017). To
# use this config, the firmware should be compiled for the AVR
# atmega1284p.
# Note, a number of Melzi boards are shipped without a bootloader. In
# that case, an external programmer will be needed to flash a
# bootloader to the board (for example, see
# http://www.instructables.com/id/Flashing-a-Bootloader-to-the-CR-10/
# ). Once that is done, one should be able to use the standard "make
# flash" command to flash Klipper.
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PD7
dir_pin: !PC5
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^!PC2
position_endstop: 0
position_max: 330
homing_speed: 50
[stepper_y]
step_pin: PC6
dir_pin: !PC7
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^!PC3
position_endstop: 0
position_max: 310
homing_speed: 50
[stepper_z]
step_pin: PB3
dir_pin: PB2
enable_pin: !PD6
step_distance: .0025
endstop_pin: ^!PC4
position_endstop: 0.5
position_max: 400
[extruder]
step_pin: PB1
dir_pin: PB0
enable_pin: !PD6
step_distance: .0111
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PD5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA7
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 275
[heater_bed]
heater_pin: PD4
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA6
control: watermark
min_temp: 0
max_temp: 150
[fan]
pin: PB4
[mcu]
serial: /dev/ttyUSB0
[printer]
kinematics: corexy
max_velocity: 300
max_accel: 1000
max_z_velocity: 20
max_z_accel: 100
[display]
lcd_type: st7920
cs_pin: PA1
sclk_pin: PC0
sid_pin: PA3
# buttons are:
# PD2, PD3: encoder
# PA5: click

View File

@@ -0,0 +1,78 @@
# This file contains pin mappings for the Wanhao Duplicator i3 Plus
# (circa 2017). To use this config, the firmware should be compiled
# for the AVR atmega2560.
# Pin numbers and other parameters were extracted from the
# official Marlin source available at:
# https://github.com/garychen99/Duplicator-i3-plus
# See the example.cfg file for a description of available parameters.
[stepper_x]
step_pin: PF7
dir_pin: !PK0
enable_pin: !PF6
step_distance: .0125
endstop_pin: ^!PF0
position_endstop: 0
position_max: 200
homing_speed: 30.0
[stepper_y]
step_pin: PK2
dir_pin: !PK3
enable_pin: !PK1
step_distance: .0125
endstop_pin: ^!PA2
position_endstop: 0
position_max: 200
homing_speed: 30.0
[stepper_z]
step_pin: PK5
dir_pin: PK7
enable_pin: !PK4
step_distance: .0025
endstop_pin: ^!PA1
position_endstop: 0.5
position_max: 180
[extruder]
step_pin: PF4
dir_pin: PF5
enable_pin: !PF3
step_distance: 0.010417
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PG5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PF1
control: pid
pid_Kp: 30.850721
pid_Ki: .208175
pid_Kd: 192.298728
min_temp: 0
max_temp: 260
[heater_bed]
heater_pin: PE5
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PK6
control: pid
pid_Kp: 64.095903
pid_Ki: 1.649830
pid_Kd: 622.531455
min_temp: 0
max_temp: 110
[fan]
pin: PE3
[mcu]
serial: /dev/ttyUSB0
[printer]
kinematics: cartesian
max_velocity: 300
max_accel: 800
max_z_velocity: 5
max_z_accel: 100

View File

@@ -0,0 +1,159 @@
# This file contains pin mappings and other appropriate default parameters
# for a Wanhao Duplicator i3 v2.1 and its clones
# (Monoprice Maker Select, Cocoon Create, etc.)
# See the files example.cfg and example-extras.cfg for a description of available parameters.
#
# This will probably work on older revisions (v1.0, v2.0) of the printer
# but is untested on those versions.
#
# For best results with klipper and the Wanhao Duplicator i3, follow these
# guidelines:
#
# - Flash a bootloader to the Melzi board in the printer
# See http://www.instructables.com/id/Using-an-Arduino-to-Flash-the-Melzi-Board-Wanhao-I/
#
# - Make sure the auto-reset jumper is *enabled* on the Melzi board
# (See step 1 in the bootloader tutorial above)
#
# - Locate the USB serial port for your printer in /dev/serial/by-id/ format.
# See https://github.com/KevinOConnor/klipper/blob/master/docs/FAQ.md#wheres-my-serial-port
# It will be something like:
# /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_ABCD1234-if00-port0
#
# - Configure klipper to compile firmware for the AVR atmega1284p
#
# - At this point, "make flash FLASH_DEVICE=..." should successfully
# flash your printer board. Use the /dev/serial/by-id/ format for
# FLASH_DEVICE to ensure consistent results.
# See https://github.com/KevinOConnor/klipper/blob/master/docs/FAQ.md#the-make-flash-command-doesnt-work
# if you have problems.
#
# - Copy this sample file you are currently reading to ~/printer.cfg,
# and customize the following parameters:
# * [extruder] > step_distance
#
# This is the inverse of "E steps" (extruder steps per mm) from the stock
# Wanhao Repetier-based firmware.
# (See https://3dprinterwiki.info/extruder-steps/ )
#
# For example, if your E-steps are set to 107.0 steps per mm,
# then step_distance should be (1 / 107.0) ~= .009346
#
# * [extruder] > PID parameters (pid_Kp, pid_Ki, pid_Kd)
# * [heater_bed] > PID parameters (pid_Kp, pid_Ki, pid_Kd)
#
# PID values from stock Wanhao firmware (Repetier) do not
# translate directly to klipper. You will need to run klipper's
# PID autotune function for the extruder and bed. After getting the
# klipper firmware up and running, run the PID_CALIBRATE procedures
# by sending these commands via octoprint terminal (one per autotune):
#
# extruder: PID_CALIBRATE HEATER=extruder TARGET=<temp>
# heated bed: PID_CALIBRATE HEATER=heater_bed TARGET=<temp>
#
# After the autotune process completes, PID parameter results
# can be found in the Octoprint terminal tab (if you're quick)
# or in /tmp/klippy.log.
#
# Enter the PID parameters into the appropriate sections of ~/printer.cfg .
#
# * [extruder] > max_temp
# * [heater_bed] > max_temp
#
# The max temps included in this printer config are limited to 230 for extruder
# and 70 for heated bed. If your printer has been modified to handle higher temps
# (like an upgraded hot end or a separate MOSFET for your heated bed), you may
# want to increase these values.
#
# * [mcu] > serial
#
# Enter the USB serial port of the printer in /dev/serial/by-id/ format
# for best results.
#
# - Power cycle the Wanhao Duplicator i3
#
# - Issue the command "RESTART" via the Octoprint terminal tab (similar to
# how you would send a manual gcode command, but send the word RESTART).
# This tells klipper to reload its config file and do an internal reset.
# You should then see a status screen appear on the printer's LCD.
#
# - Be sure to follow these instructions before attempting any prints:
# https://github.com/KevinOConnor/klipper/blob/master/docs/Config_checks.md
[stepper_x]
step_pin: PD7
dir_pin: PC5
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^!PC2
position_endstop: 0
position_max: 200
homing_speed: 40
[stepper_y]
step_pin: PC6
dir_pin: PC7
enable_pin: !PD6
step_distance: .0125
endstop_pin: ^!PC3
position_endstop: 0
position_max: 200
homing_speed: 40
[stepper_z]
step_pin: PB3
dir_pin: !PB2
enable_pin: !PA5
step_distance: 0.0025
endstop_pin: ^!PC4
position_endstop: 0.5
position_max: 180
homing_speed: 2
[extruder]
step_pin: PB1
dir_pin: !PB0
enable_pin: !PD6
step_distance: .009346
nozzle_diameter: 0.400
filament_diameter: 1.750
heater_pin: PD5
sensor_type: NTC 100K beta 3950
sensor_pin: PA7
control: pid
pid_Kp: 18.214030
pid_Ki: 0.616380
pid_Kd: 134.556146
min_temp: 0
max_temp: 230
[heater_bed]
heater_pin: PD4
sensor_type: NTC 100K beta 3950
sensor_pin: PA6
control: pid
pid_Kp: 71.321
pid_Ki: 1.989
pid_Kd: 639.210
min_temp: 0
max_temp: 70
[fan]
pin: PB4
[mcu]
serial: /dev/ttyUSB0
restart_method: command
[printer]
kinematics: cartesian
max_velocity: 200
max_accel: 1000
max_z_velocity: 2
max_z_accel: 100
[display]
lcd_type: st7920
cs_pin: PC1
sclk_pin: PD3
sid_pin: PC0

56
config/sample-bltouch.cfg Normal file
View File

@@ -0,0 +1,56 @@
# This file provides example config file settings for the BLTouch
# automatic bed leveling sensor. This file is just a "snippet" of
# sections specific to the BLTouch - it must be added to a config file
# containing the configuration of the rest of the printer.
# Be sure to review and update this config with the appropriate pins
# and coordinates for your printer.
# See the "example.cfg" and "example-extras.cfg" files for a
# description of config parameters.
# Define the BLTouch servo
[servo bltouch]
pin: ar32
maximum_servo_angle: 180
minimum_pulse_width: 0.0006
maximum_pulse_width: 0.0024
# Define a probe using the BLTouch
[probe]
pin: ar30
activate_gcode:
SET_SERVO SERVO=bltouch ANGLE=10
SET_SERVO SERVO=bltouch ANGLE=60
G4 P200
deactivate_gcode:
SET_SERVO SERVO=bltouch ANGLE=90
# Example bed_tilt config section
[bed_tilt]
#x_adjust:
#y_adjust:
points:
100,100
10,10
10,100
10,190
100,10
100,190
190,10
190,100
190,190
probe_z_offset: 2.345
# If the BLTouch is used to home the Z axis, then define a
# homing_override section, use probe:z_virtual_endstop as the
# endstop_pin in the stepper_z section, and set the endstop_position
# in the stepper_z section to match the probe's probe_z_offset.
#[homing_override]
#set_position_z: 5
#gcode:
# ; G90 ; Uncomment these 2 lines to blindly lift the Z 2mm at start
# ; G1 Z7 F600
# G28 X0 Y0
# G1 X100 Y100 F3600
# G28 Z0

38
docs/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,38 @@
# Contributing to Klipper
Thank you for contributing to Klipper! Please take a moment to read
this document.
## Creating a new issue
Please see the [contact page](Contact.md) for information on creating
an issue. In particular, **we need the klippy.log file** attached to
bug reports. Also, be sure to read the [FAQ](FAQ.md) to see if a
similar issue has already been raised.
## Submitting a pull request
Contributions of Code and documentation are managed through github
pull requests. 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>
```
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.

View File

@@ -8,16 +8,17 @@ The **src/** directory contains the C source for the micro-controller
code. The **src/avr/** directory contains specific code for Atmel
ATmega micro-controllers. The **src/sam3x8e/** directory contains code
specific to the Arduino Due style ARM micro-controllers. 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
host 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).
**src/pru/** directory contains code specific to the Beaglebone's
on-board PRU micro-controller. 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 host 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 C and Python source for the
host part of the firmware.
host part of the software.
The **lib/** directory contains external 3rd-party library code that
is necessary to build some targets.
@@ -28,6 +29,8 @@ 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
@@ -43,10 +46,12 @@ 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_task() located in
**src/command.c**. This function processes incoming serial commands
and runs the associated command function for them. Command functions
are declared using the DECL_COMMAND() 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**) 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
@@ -54,13 +59,13 @@ functions should never pause, delay, or do any work that lasts more
than a few micro-seconds. These functions schedule work at specific
times by scheduling timers.
Timer functions are scheduled by calling sched_timer() (located in
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**), but this just calls sched_timer_kick()
located in **src/sched.c**. The timer interrupt leads to execution of
schedule timer functions. Timer functions always run with interrupts
(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.
@@ -74,7 +79,7 @@ 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 architectures specific
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
@@ -92,8 +97,8 @@ 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 gcode commands is in the process_commands() method in
**klippy/gcode.py**. This code translates the gcode commands into
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).
@@ -106,3 +111,325 @@ 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. Changes in
origin (eg, G92), changes in relative vs absolute positions (eg,
G90), and unit changes (eg, F6000=100mm/s) are handled here. 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 codepath for a move is:
`ToolHead.move() -> MoveQueue.add_move() -> MoveQueue.flush() ->
Move.set_junction() -> Move.move()`.
* ToolHead.move() creates a Move() object with the parameters of the
move (in cartesian space and in units of seconds and millimeters).
* 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 Move.move() is called, everything about the move is known -
its start location, its end location, its acceleration, its
start/crusing/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.
The move is then handed off to the kinematics classes: `Move.move()
-> kin.move()`
* The goal of the kinematics classes is to translate the movement in
cartesian space to movement on each stepper. The kinematics classes
are in cartesian.py, corexy.py, delta.py, and extruder.py. The
kinematic class is given a chance to audit the move
(`ToolHead.move() -> kin.check_move()`) before it goes on the
look-ahead queue, but once the move arrives in *kin*.move() the
kinematic class is required to handle the move as specified. The
kinematic classes translate the three parts of each move
(acceleration, constant "cruising" velocity, and deceleration) to
the associated movement on each stepper. Note that the extruder is
handled in its own kinematic class. 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.
* For efficiency reasons, the stepper pulse times are generated in C
code. The code flow is: `kin.move() -> MCU_Stepper.step_const() ->
stepcompress_push_const()`, or for delta kinematics:
`DeltaKinematics.move() -> MCU_Stepper.step_delta() ->
stepcompress_push_delta()`. The MCU_Stepper code just performs unit
and axis transformation (millimeters to step distances), and calls
the C code. The C code calculates the stepper step times for each
movement and fills an array (struct stepcompress.queue) with 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 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 command.c which parses the command and calls
`command_queue_step()`. The command_queue_step() code (in 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.
* Define a `printer_state()` method if the code needs to be called
during printer setup and/or shutdown. This method is called twice
during setup (with "connect" and then "ready") and may also be
called at run-time (with "shutdown" or "disconnect"). It is common
to perform "printer object" lookup during the "connect" and "ready"
phases.
* If there is an error in the user's config, be sure to raise it
during the `load_config()` or `printer_state("connect")` 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 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 close them from the
`printer_state("disconnect")` 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.
* 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 (which is written in
Python).
Useful steps:
1. Start by studying the [above section](#code-flow-of-a-move-command)
and the [Kinematics document](Kinematics.md).
2. Review the existing kinematic classes in cartesian.py, corexy.py,
and delta.py. 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 `get_postion()` method in the new kinematics
class. This method converts the current stepper position of each
stepper axis (stored in millimeters) to a position in cartesian
space (also in millimeters).
4. Implement the `set_postion()` method. This is the inverse of
get_position() - it sets each axis position (in millimeters) given
a position in cartesian coordinates.
5. Implement the `move()` method. The goal of the move() method is to
convert a move defined in cartesian space to a series of stepper
step times that implement the requested movement.
* The `move()` method is passed a "print_time" parameter (which
stores a time in seconds) and a "move" class instance that fully
defines the movement. The goal is to repeatedly invoke the
`stepper.step()` method with the time (relative to print_time)
that each stepper should step at to obtain the desired motion.
* One "trick" to help with the movement calculations is to imagine
there is a physical rail between `move.start_pos` and
`move.end_pos` that confines the print head so that it can only
move along this straight line of motion. Then, if the head is
confined to that imaginary rail, the head is at `move.start_pos`,
only one stepper is enabled (all other steppers can move freely),
and the given stepper is stepped a single step, then one can
imagine that the head will move along the line of movement some
distance. Determine the formula converting this step distance to
distance along the line of movement. Once one has the distance
along the line of movement, one can figure out the time that the
head should be at that position (using the standard formulas for
velocity and acceleration). This time is the ideal step time for
the given stepper and it can be passed to the `stepper.step()`
method.
* The `stepper.step()` method must always be called with an
increasing time for a given stepper (steps must be scheduled in
the order they are to be executed). A common error during
kinematic development is to receive an "Internal error in
stepcompress" failure - this is generally due to the step()
method being invoked with a time earlier than the last scheduled
step. For example, if the last step in move1 is scheduled at a
time greater than the first step in move2 it will generally
result in the above error.
* Fractional steps. Be aware that a move request is given in
cartesian space and it is not confined to discreet
locations. Thus a move's start and end locations may translate to
a location on a stepper axis that is between two steps (a
fractional step). The code must handle this. The preferred
approach is to schedule the next step at the time a move would
position the stepper axis at least half way towards the next
possible step location. Incorrect handling of fractional steps is
a common cause of "Internal error in stepcompress" failures.
6. Other methods. The `home()`, `check_move()`, and other methods
should also be implemented. However, at the start of development
one can use empty code here.
7. 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.
8. Optimize if needed. One may notice that the existing kinematic
classes do not call `stepper.step()`. This is purely an
optimization - the inner loop of the kinematic calculations were
moved to C to reduce load on the host cpu. All of the existing
kinematic classes started development using `stepper.step()` and
then were later optimized. The g-code to mcu command translation
(described in the previous step) is a useful tool during
optimization - if a code change is purely an optimization then it
should not impact the resulting text representation of the mcu
commands (though minor changes in output due to floating point
rounding are possible). So, one can use this system to detect
regressions.
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 calculates 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/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.

147
docs/Config_checks.md Normal file
View File

@@ -0,0 +1,147 @@
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.
![octoprint-temperature](img/octoprint-temperature.png)
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 motor direction
Make sure the printer.cfg file does not have "homing_speed" set for
any axis (or set it to a value of 5 or less).
On cartesian style printers, manually move the X axis to a midway
point, issue a G28X0 command, and verify that the X motor moves slowly
towards the endstop defined for that axis. If the motor moves in the
wrong direction issue an M112 command to abort the move. A wrong
direction 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). For
example, change "dir_pin: xyz" to "dir_pin: !xyz". Then RESTART and
retest the axis. If the axis does not move at all, then verify the
"enable_pin" and "step_pin" settings for the axis. For cartesian style
printers, repeat the test for the Y and Z axis with G28Y0 and G28Z0.
For delta style printers, manually move all three carriages to a
midway point and then issue a G28 command. Verify all three motors
move simultaneously upwards. If not, issue an M112 command and follow
the troubleshooting steps in the preceding paragraph.
### 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, update the printer.cfg file with
the recommended pid_Kp, pid_Ki, and pid_Kd values.
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. It may be necessary to perform
detailed printer calibration - a number of guides are available online
to help with this (for example, do a web search for "3d printer
calibration").

51
docs/Contact.md Normal file
View File

@@ -0,0 +1,51 @@
This page provides information on how to contact the Klipper
developers.
Issue reporting
===============
In order to report a problem or request a change in behavior, it is
necessary to collect the Klipper log file. The first step is to
**issue 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.
Issue requests are submitted through Github. **All issues must
include the full /tmp/klippy.log log file from the session that
produced the error.** An "scp" and/or "sftp" utility is needed to
acquire this log file. The "scp" utility comes standard with Linux and
MacOS desktops. There are freely available scp utilities for other
desktops (eg, WinSCP).
Use the scp utility to copy the `/tmp/klippy.log` file from the host
machine to your desktop. It is a good idea to compress the klippy.log
file before posting it (eg, using zip or gzip). Open a new issue at
https://github.com/KevinOConnor/klipper/issues , provide a description
of the problem, and **attach the `klippy.log` file to the issue**:
![attach-issue](img/attach-issue.png)
Mailing list
============
There is a mailing list for general discussions on Klipper. In order
to send am email to the list, one must first subscribe:
https://www.freelists.org/list/klipper . Once subscribed, emails may
be sent to `klipper@freelists.org`.
Archives of the mailing list are available at:
https://www.freelists.org/archive/klipper/
IRC
===
One may join the #klipper channel on freenode.net (
irc://chat.freenode.net:6667 ).
To communicate in this IRC channel one will need an IRC
client. Configure it to connect to chat.freenode.net on port 6667 and
join the #klipper channel (`/join #klipper`).
If asking a question on IRC, be sure to ask the question and then stay
connected to the channel to receive responses. Due to timezone
differences, it may take several hours before receiving a response.

View File

@@ -1,17 +1,18 @@
The Klippy host code has some tools to help in debugging the firmware.
The Klippy host code has some tools to help in debugging.
Translating gcode files to firmware commands
============================================
Translating gcode files to micro-controller commands
====================================================
The Klippy host code can run in a batch mode to produce the low-level
firmware commands associated with a gcode file. Inspecting these
low-level firmware commands is useful when trying to understand the
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 firmware commands after a code change.
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 firmware "data dictionary". This is done by compiling
the firmware code to obtain the **out/klipper.dict** file:
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
@@ -34,13 +35,13 @@ output. This output can be translated to readable text with:
```
The resulting file **test.txt** contains a human readable list of
firmware commands.
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 firmware 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.
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.
Testing with simulavr
=====================
@@ -74,25 +75,20 @@ cd /patch/to/klipper
make menuconfig
```
and compile the firmware for an AVR atmega644p, disable the AVR
watchdog timer, and set the MCU frequency to 20000000. Then one can
compile Klipper (run `make`) and then start the simulation with:
and compile the micro-controller software for an AVR atmega644p, set
the MCU frequency to 20Mhz, and select SIMULAVR software emulation
support. Then one can compile Klipper (run `make`) and then start the
simulation with:
```
PYTHONPATH=/path/to/simulavr/src/python/ ./scripts/avrsim.py -m atmega644 -s 20000000 -b 250000 out/klipper.elf
```
It may be necessary to create a python virtual environment to run
Klippy on the target machine. To do so, run:
```
virtualenv ~/klippy-env
~/klippy-env/bin/pip install cffi==1.6.0 pyserial==2.7
```
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:
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/avrsim.cfg -i test.gcode -v
@@ -119,13 +115,59 @@ gtkwave avrsim.vcd
```
Manually sending commands to the micro-controller
-------------------------------------------------
=================================================
Normally, Klippy would be used to translate gcode commands to Klipper
commands. However, it's also possible to manually send Klipper
commands (functions marked with the DECL_COMMAND() macro in the
Klipper source code). To do so, run:
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 250000
```
See the "HELP" command within the tool for more information on its
functionality.
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 loadgraph.png
```
One can then view the resulting **loadgraph.png** file.
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.

252
docs/FAQ.md Normal file
View File

@@ -0,0 +1,252 @@
Frequently asked questions
==========================
1. [How can I donate to the project?](#how-can-i-donate-to-the-project)
2. [How do I calculate the step_distance parameter in the printer config file?](#how-do-i-calculate-the-step_distance-parameter-in-the-printer-config-file)
3. [Where's my serial port?](#wheres-my-serial-port)
4. [The "make flash" command doesn't work](#the-make-flash-command-doesnt-work)
5. [How do I change the serial baud rate?](#how-do-i-change-the-serial-baud-rate)
6. [Can I run Klipper on something other than a Raspberry Pi 3?](#can-i-run-klipper-on-something-other-than-a-raspberry-pi-3)
7. [Why can't I move the stepper before homing the printer?](#why-cant-i-move-the-stepper-before-homing-the-printer)
8. [Why is the Z position_endstop set to 0.5 in the default configs?](#why-is-the-z-position_endstop-set-to-05-in-the-default-configs)
9. [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](#i-converted-my-config-from-marlin-and-the-xy-axes-work-fine-but-i-just-get-a-screeching-noise-when-homing-the-z-axis)
10. [When I set "restart_method=command" my AVR device just hangs on a restart](#when-i-set-restart_methodcommand-my-avr-device-just-hangs-on-a-restart)
11. [Will the heaters be left on if the Raspberry Pi crashes?](#will-the-heaters-be-left-on-if-the-raspberry-pi-crashes)
12. [How do I upgrade to the latest software?](#how-do-i-upgrade-to-the-latest-software)
### How can I donate to the project?
Thanks. Kevin has a Patreon page at: https://www.patreon.com/koconnor
### How do I calculate the step_distance parameter in the printer config file?
If you know the steps per millimeter for the axis then use a
calculator to divide 1.0 by steps_per_mm. Then round this number to
six decimal places and place it in the config (six decimal places is
nano-meter precision).
The step_distance defines the distance that the axis will travel on
each motor driver pulse. It can also be calculated from the axis
pitch, motor step angle, and driver microstepping. If unsure, do a web
search for "calculate steps per mm" to find an online calculator.
### Where's my serial port?
The general way to find a USB serial port is to run `ls -l
/dev/serial/by-id/` from an ssh terminal on the host machine. It will
likely produce output similar to the following:
```
lrwxrwxrwx 1 root root 13 Jan 3 22:15 usb-UltiMachine__ultimachine.com__RAMBo_12345678912345678912-if00 -> ../../ttyACM0
```
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-UltiMachine__ultimachine.com__RAMBo_12345678912345678912-if00
sudo service klipper start
```
and the updated config might look like:
```
[mcu]
serial: /dev/serial/by-id/usb-UltiMachine__ultimachine.com__RAMBo_12345678912345678912-if00
```
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.
### 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, on AVR devices, it
may be possible to manually flash the device using
[avrdude](http://www.nongnu.org/avrdude/) with custom command-line
parameters - see the avrdude documentation for further information.
### How do I change the serial baud rate?
The default baud rate is 250000 in both the Klipper micro-controller
configuration and in the Klipper host software. This works on almost
all micro-controllers and it is the recommended setting. (Most online
guides that refer to a baud rate of 115200 are outdated.)
If you need to change the baud rate, then the new rate will need to be
configured in the micro-controller (during **make menuconfig**) and
that updated code will need to be flashed to the micro-controller. The
Klipper printer.cfg file will also need to be updated to match that
baud rate (see the example.cfg file 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.
### Can I run Klipper on something other than a Raspberry Pi 3?
The recommended hardware is a Raspberry Pi 2 or a Raspberry
Pi 3.
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's not uncommon for print stalls to occur on these slower
machines (the printer may move faster than OctoPrint can send movement
commands) when printing directly from OctoPrint. If you wish to run on
one one of these slower boards anyway, consider using the
"virtual_sdcard" feature (see
[config/example-extras.cfg](../config/example-extras.cfg) for details)
when printing.
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.
### 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.
### 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.
Almost all mechanical switches can still move a small distance
(eg, 0.5mm) after they are triggered. So, for example, if the
position_endstop is set to 0.5mm then one may still command the
printer to move to Z0.2. The position_min config setting (which
defaults to 0) is used to specify the minimum Z position one may
command the printer to move to.
Note, the Z position_endstop specifies the distance from the nozzle to
the bed when the nozzle and bed (if applicable) are hot. It is typical
for thermal expansion to cause nozzle expansion of around .1mm, which
is also the typical thickness of a sheet of printer paper. Thus, it is
common to use the "paper test" to confirm calibration of the Z
height - check that the bed and nozzle are at room temperature, check
that there is no plastic on the head or bed, home the printer, place a
piece of paper between the nozzle and bed, and repeatedly command the
head to move closer to the bed checking each time if you feel a small
amount of friction when sliding the paper between bed and nozzle - if
all is calibrated well a small amount of friction would be felt when
the height is at Z0.
### 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: Try reducing the max_z_velocity setting in the printer
config. Also, if the Z stepper is moving in the wrong direction, try
inverting the dir_pin setting in the config (eg, "dir_pin: !xyz"
instead of "dir_pin: xyz").
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 very precise step_distance the
actual obtainable max_z_velocity may be smaller than what is
configured in Marlin.
### 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 - search the web to find the instructions for your
particular device.
### 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.
### How do I upgrade to the latest software?
The general way to upgrade 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:
```
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. 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.

View File

@@ -1,26 +1,24 @@
Klipper is an experimental 3d printer firmware. It has several
compelling 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 no less than 50 micro-seconds. 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.
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 an old 8bit AVR
micro-controller can obtain rates up to 150K steps per second. On
more recent ARM micro-controllers, rates over 350K 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.
micro-controller can obtain rates over 175K steps per second. On
more recent micro-controllers, rates over 500K 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.
* Configuration via simple config file. There's no need to reflash the
micro-controller to change a setting. All of Klipper's configuration
@@ -34,16 +32,29 @@ compelling features:
micro-controller architectures as well.
* Simpler code. Klipper uses a very high level language (Python) for
most code. The kinematics algorithms, the gcode parsing, the heating
and thermistor algorithms, etc. are all written in Python. This
makes it easier to develop new functionality.
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.
* Advanced features. Klipper implements the "pressure advance"
algorithm for extruders. When properly tuned, pressure advance
reduces extruder ooze. Klipper also implements a novel "stepper
phase endstop" algorithm that can dramatically improve the accuracy
of typical endstop switches. When properly tuned it can improve a
print's first layer bed adhesion.
* Advanced features:
* Klipper implements the "pressure advance" algorithm for
extruders. When properly tuned, pressure advance reduces extruder
ooze.
* Klipper supports printers with multiple micro-controllers. For
example, one micro-controller could be used to control an
extruder, while another could control 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.
* Klipper also implements a novel "stepper phase endstop" algorithm
that can dramatically improve the accuracy of typical endstop
switches. When properly tuned it can improve a print's first layer
bed adhesion.
* 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.
To get started with Klipper, read the [installation](Installation.md)
guide.
@@ -65,12 +76,12 @@ Klipper supports many standard 3d printer features:
gradually accelerate from standstill to cruising speed and then
decelerate back to a standstill.
* "Lookahead" support. 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.
* "Look-ahead" support. 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.
* Support for both delta printers and cartesian style printers.
* Support for cartesian, delta, and corexy style printers.
Step Benchmarks
===============
@@ -78,8 +89,14 @@ 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 |
| ----------------- | ---------------- | ----------------- |
| 20Mhz AVR | 158.7K | 103K |
| 16Mhz AVR | 126.9K | 82K |
| Arduino Due (ARM) | 352.9K | 288K |
| Micro-controller | Fastest step rate | 3 steppers active |
| ----------------- | ----------------- | ----------------- |
| 20Mhz AVR | 189K | 125K |
| 16Mhz AVR | 151K | 100K |
| Arduino Due (ARM) | 382K | 337K |
| Beaglebone PRU | 689K | 689K |
On AVR platforms, the highest achievable step rate is with just one
stepper stepping. On the Due, the highest step rate is with two
simultaneous steppers stepping. On the PRU, the highest step rate is
with three simultaneous steppers.

View File

@@ -1,278 +0,0 @@
This document provides high-level information on common firmware
commands. It is not an authoritative reference for these commands, nor
is it an exclusive list of all available firmware commands.
This document may be useful for users needing to configure a set of
hardware actions that their printer may require at startup (via the
"custom" field in the printer config file), and it may be useful for
developers wishing to obtain a high-level feel for available firmware
commands.
See the [protocol](Protocol.md) document for more information on the
format of commands and their low-level 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.
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 other firmware commands,
these commands run as soon as they are received by the firmware and
they do not require any particular setup.
These commands are most useful in the "custom" block of the "mcu"
section of the printer configuration file. This feature is typically
used to configure the initial settings of LEDs, to configure
micro-stepping pins, to configure a digipot, etc.
Several of these commands will take a "pin=%u" parameter. The
low-level firmware uses integer encodings of the hardware pin numbers,
but to make things more readable the host will translate human
readable pin names (eg, "PA3") to their equivalent integer
encodings. By convention, any parameter named "pin" or that has a
"_pin" suffix will use pin name translation by the host.
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=%c : 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.
* send_spi_message pin=%u msg=%*s : This command can be used to
transmit messages to a serial-peripheral-interface (SPI) component
connected to the micro-controller. It has been used to configure the
startup settings of AD5206 digipots. The 'pin' parameter specifies
the chip select line to use during the transmission. The 'msg'
indicates the binary message to transmit to the given chip.
Firmware configuration
======================
Most commands in the firmware require an initial setup before they can
be successfully invoked. This section provides a high-level overview
of the micro-controller 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 firmware it always starts by
obtaining the firmware's data dictionary (see [protocol](Protocol.md)
for more information). After the data dictionary is obtained the host
will check if the firmware is in a "configured" state and configure it
if not. Configuration involves the following phases:
* get_config : The host starts by checking if the firmware is already
configured. The firmware responds to this command with a "config"
response message. At micro-controller power-on the firmware always
starts in an unconfigured state. It remains in this state until the
host completes the configuration processes (by issuing a
finalize_config command). If the firmware is already configured (and
is configured with the desired settings) from a previous
host/firmware session 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
firmware 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
firmware so that the firmware may allocate sufficient memory to
store a mapping from oid to internal firmware object.
* config_XXX oid=%c ... : By convention any command starting with the
"config_" prefix creates a new firmware 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 firmware 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
firmware from an unconfigured state to a configured state. The crc
parameter passed to the firmware is stored in the firmware and
provided back to the host in "config" response messages. By
convention, the host takes a 32bit CRC of the firmware configuration
it will request and at the start of subsequent host/firmware
communication sessions it checks that the CRC stored in the firmware
exactly matches its desired CRC. If the CRC does not match then the
host knows the firmware has not been configured in the state desired
by the host.
Common firmware objects
-----------------------
This section lists some commonly used config commands.
* config_digital_out oid=%c pin=%u default_value=%c max_duration=%u :
This command creates an internal firmware object for the given GPIO
'pin'. The pin will be configured in digital output mode and set to
an initial value as specified by 'default_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
schedule_digital_out command described below). Should the firmware
go into shutdown mode then all configured digital_out objects will
be set back to their default values. 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 set the heater to a value of one and then go
off-line.
* config_pwm_out oid=%c pin=%u cycle_ticks=%u default_value=%c
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_soft_pwm_out oid=%c pin=%u cycle_ticks=%u default_value=%c
max_duration=%u : This command creates an internal firmware object
for software implemented PWM. Unlike hardware pwm pins, a software
pwm object does not require any special hardware support (other than
the ability to configure the pin as a digital output GPIO). Because
the output switching is implemented in the software of the firmware,
it is recommended that the cycle_ticks parameter correspond to a
time of 10ms or greater. 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 min_stop_interval=%u
invert_step=%c : 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 'min_stop_interval' implements a safety
feature - it is checked when the firmware finishes all moves for a
stepper - if it is non-zero it specifies the minimum number of clock
ticks since the last step. It is used as a check on the maximum
stepper velocity that a stepper may have before stopping.
* config_end_stop oid=%c pin=%c pull_up=%c stepper_oid=%c : This
command creates an internal "endstop" object. It is used to specify
the endstop pins and to enable "homing" operations (see the
end_stop_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_oid' parameter
specifies the oid of an associated stepper for the given endstop -
it is used during homing operations.
Common commands
===============
This section lists some commonly used run-time commands. It is likely
only of interest to developers looking to gain insight into Klippy.
* schedule_digital_out oid=%c clock=%u value=%c : 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 firmware
configuration.
* schedule_pwm_out oid=%c clock=%u value=%c : Schedules a change to a
hardware PWM output pin. See the 'schedule_digital_out' and
'config_pwm_out' commands for more info.
* schedule_soft_pwm_out oid=%c clock=%u value=%c : Schedules a change
to a software PWM output pin. See the 'schedule_digital_out' and
'config_soft_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 firmware 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 firmware 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_status : This command causes the firmware to generate a "status"
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 firmware 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.
* end_stop_home oid=%c clock=%u rest_ticks=%u pin_value=%c : This
command is used during stepper "homing" operations. To use this
command a 'config_end_stop' command with the same 'oid' parameter
must have been issued during firmware configuration. When invoked,
the firmware 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 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 the stepper to move it 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 firmware "move
queue". The firmware allocates this queue 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.

131
docs/G-Codes.md Normal file
View File

@@ -0,0 +1,131 @@
This document describes the commands that Klipper supports. These are
commands that one may enter into the OctoPrint terminal tab.
# G-Code commands
Klipper supports the following standard G-Code commands:
- Move (G0 or G1): `G1 [X<pos>] [Y<pos>] [Z<pos>] [E<pos>] [F<speed>]`
- Dwell: `G4 P<milliseconds>`
- Move to origin: `G28 [X] [Y] [Z]`
- Turn off motors: `M18` or `M84`
- Wait for current moves to finish: `M400`
- Select tool: `T<index>`
- Use absolute/relative distances for extrusion: `M82`, `M83`
- Use absolute/relative coordinates: `G90`, `G91`
- Set position: `G92 [X<pos>] [Y<pos>] [Z<pos>] [E<pos>]`
- Set speed factor override percentage: `M220 S<percent>`
- Set extrude factor override percentage: `M221 S<percent>`
- Get extruder temperature: `M105`
- Set extruder temperature: `M104 [T<index>] [S<temperature>]`
- Set extruder temperature and wait: `M109 [T<index>] S<temperature>`
- Set bed temperature: `M140 [S<temperature>]`
- Set bed temperature and wait: `M190 S<temperature>`
- Set fan speed: `M106 S<value>`
- Turn fan off: `M107`
- Emergency stop: `M112`
- Get current position: `M114`
- Get firmware version: `M115`
- Set home offset: `M206 [X<pos>] [Y<pos>] [Z<pos>]`
For further details on the above commands see the
[RepRap G-Code documentation](http://reprap.org/wiki/G-code).
Klipper's goal is to support the G-Code commands produced by common
3rd party software (eg, OctoPrint, Printrun, Slic3r, Cura, etc.) in
their standard configurations. It is not a goal to support every
possible G-Code command. Instead, Klipper prefers human readable
["extended G-Code commands"](#extended-g-code-commands).
## G-Code SD card commands
Klipper also supports the following standard G-Code commands if the
"virtual_sdcard" config section is enabled:
- List SD card: `M20`
- Initialize SD card: `M21`
- Select SD file: `M23 <filename>`
- Start/resume SD print: `M24`
- Pause SD print: `M25`
- Set SD position: `M26 S<offset>`
- Report SD print status: `M27`
# Extended G-Code Commands
Klipper uses "extended" G-Code commands for general configuration and
status. These extended commands all follow a similar format - they
start with a command name and may be followed by one or more
parameters. For example: `SET_SERVO SERVO=myservo ANGLE=5.3`. In this
document, the commands and parameters are shown in uppercase, however
they are not case sensitive. (So, "SET_SERVO" and "set_servo" both run
the same command.)
The following standard commands are supported:
- `QUERY_ENDSTOPS`: Probe the axis endstops and report if they are
"triggered" or in an "open" state. This command is typically used to
verify that an endstop is working correctly.
- `GET_POSITION`: Return information on the current location of the
toolhead.
- `PID_CALIBRATE HEATER=<config_name> TARGET=<temperature>
[WRITE_FILE=1]`: Perform a PID calibration test. The specified
heater will be enabled until the specified target temperature is
reached, and then the heater will be turned off and on for several
cycles. If the WRITE_FILE parameter is enabled, then the file
/tmp/heattest.txt will be created with a log of all temperature
samples taken during the test.
- `RESTART`: This will cause the host software to reload its config
and perform an internal reset. This command will not clear error
state from the micro-controller (see FIRMWARE_RESTART) nor will it
load new software (see
[the FAQ](FAQ.md#how-do-i-upgrade-to-the-latest-software)).
- `FIRMWARE_RESTART`: This is similar to a RESTART command, but it
also clears any error state from the micro-controller.
- `STATUS`: Report the Klipper host software status.
- `HELP`: Report the list of available extended G-Code commands.
## Custom Pin Commands
The following command is available when an "output_pin" config section
is enabled:
- `SET_PIN PIN=config_name VALUE=<value>`
## Servo Commands
The following commands are available when a "servo" config section is
enabled:
- `SET_SERVO SERVO=config_name WIDTH=<seconds>`
- `SET_SERVO SERVO=config_name ANGLE=<degrees>`
## Probe
The following commands are available when a "probe" config section is
enabled:
- `PROBE`: Move the nozzle downwards until the probe triggers.
- `QUERY_PROBE`: Report the current status of the probe ("triggered"
or "open").
## Delta Calibration
The following commands are available when the "delta_calibrate" config
section is enabled:
- `DELTA_CALIBRATE`: This command will probe seven points on the bed
and recommend updated endstop positions, tower angles, and radius.
- `NEXT`: If manual bed probing is enabled, then one can use this
command to move to the next probing point during a DELTA_CALIBRATE
operation.
## Bed Tilt
The following commands are available when the "bed_tilt" config
section is enabled:
- `BED_TILT_CALIBRATE`: This command will probe the points specified
in the config and then recommend updated x and y tilt adjustments.
- `NEXT`: If manual bed probing is enabled, then one can use this
command to move to the next probing point during a
BED_TILT_CALIBRATE operation.
## Dual Carriages
The following command is available when the "dual_carriage" config
section is enabled:
- `SET_DUAL_CARRIAGE CARRIAGE=[0|1]`: This command will set the active
carriage. It is typically invoked from the activate_gcode and
deactivate_gcode fields in a multiple extruder configuration.

View File

@@ -1,113 +1,82 @@
Klipper is currently in an experimental state. These instructions
assume the software will run on a Raspberry Pi computer in conjunction
with OctoPrint. Klipper supports Atmel ATmega based micro-controllers
and Arduino Due (Atmel SAM3x8e ARM micro-controllers) printers.
These instructions assume the software will run on a Raspberry Pi
computer in conjunction with OctoPrint. It is recommended that a
Raspberry Pi 2 or Raspberry Pi 3 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).
It is recommended that a Raspberry Pi 2 or Raspberry Pi 3 computer be
used as the host. The software will run on a first generation
Raspberry Pi, but the combined load of OctoPrint, Klipper, and a web
cam (if applicable) can overwhelm its CPU leading to print stalls.
Klipper currently supports Atmel ATmega based micro-controllers,
Arduino Due (Atmel SAM3x8e ARM micro-controller), and
[Beaglebone PRU](beaglebone.md) based printers.
Prepping an OS image
====================
Start by installing [OctoPi](https://github.com/guysoft/OctoPi) on the
Raspberry Pi computer. Use OctoPi v0.13.0 or later - see the
Raspberry Pi computer. Use OctoPi v0.14.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.3.0 or later.
page, follow the prompt to upgrade OctoPrint to v1.3.5 or later.
After installing OctoPi and upgrading OctoPrint, ssh into the target
machine (ssh pi@octopi -- password is "raspberry") and run the
following commands:
```
sudo apt-get update
sudo apt-get install libncurses-dev
sudo apt-get install avrdude gcc-avr binutils-avr avr-libc # AVR toolchain
sudo apt-get install bossa-cli libnewlib-arm-none-eabi # ARM toolchain
```
The host software (Klippy) requires a one-time setup - run as the
regular "pi" user:
```
virtualenv ~/klippy-env
~/klippy-env/bin/pip install cffi==1.6.0 pyserial==3.2.1 greenlet==0.4.10
```
Building Klipper
================
To obtain Klipper, run the following command on the target machine:
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/KevinOConnor/klipper
cd klipper/
./klipper/scripts/install-octopi.sh
```
To compile the micro-controller code, start by configuring it:
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
```
Select the appropriate micro-controller and serial baud rate. Once
configured, run:
Select the appropriate micro-controller and review any other options
provided. For boards with serial ports, the default baud rate is
250000 (see the [FAQ](FAQ.md#how-do-i-change-the-serial-baud-rate) if
changing). Once configured, run:
```
make
```
Ignore any warnings you may see about "misspelled signal handler" (it
is due to a bug fixed in gcc v4.8.3).
Installing Klipper on an AVR micro-controller
---------------------------------------------
The avrdude package can be used to install the micro-controller code
on an AVR ATmega chip. The exact syntax of the avrdude command is
different for each micro-controller. The following is an example
command for atmega2560 chips:
Finally, for common micro-controllers, the code can be flashed with:
```
example-only$ avrdude -C/etc/avrdude.conf -v -patmega2560 -cwiring -P/dev/ttyACM0 -b115200 -D -Uflash:w:/home/pi/klipper/out/klipper.elf.hex:i
sudo service klipper stop
make flash FLASH_DEVICE=/dev/ttyACM0
sudo service klipper start
```
Installing Klipper on an Arduino Due
------------------------------------
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"). The most common
communication device is **/dev/ttyACM0** - see the
[FAQ](FAQ.md#wheres-my-serial-port) for other possibilities.
Klipper currently uses the Arduino Due USB programming port (it will
not work when connected to the application USB port). The programming
port is the USB port closest to the power supply. To flash Klipper to
the Due connect it to the host machine and run:
```
stty -F /dev/ttyACM0 1200
bossac -i -p ttyACM0 -R -e -w -v -b ~/klipper/out/klipper.bin
```
Setting up the printer configuration
Configuring OctoPrint to use Klipper
====================================
It is necessary to configure the printer. This is done by modifying a
configuration file that resides on the host. Start by copying an
example configuration and editing it. For example:
```
cp ~/klipper/config/example.cfg ~/printer.cfg
nano printer.cfg
```
Make sure to look at and update each setting that is appropriate for
the hardware.
Configuring OctoPrint to use Klippy
===================================
The OctoPrint web server needs to be configured to communicate with
the Klippy host software. Using a web-browser, login to the OctoPrint
the Klipper host software. Using a web browser, login to the OctoPrint
web page, and navigate to the Settings tab. Then configure the
following items:
@@ -115,40 +84,75 @@ 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". Change the Baudrate field to
250000 (this buad rate field is not related to the firmware baudrate
and may be safely left at 250000). Unselect the "Not only cancel
ongoing prints but also disconnect..." checkbox.
"Serial Port" setting to "/tmp/printer". Unselect the "Not only cancel
ongoing prints but also disconnect..." checkbox. Click "Save".
Under the "Features" tab, unselect "Enable SD support". Then click
"Save".
Running the host software
=========================
The host software is executed by running the following as the regular
"pi" user:
```
~/klippy-env/bin/python ~/klipper/klippy/klippy.py ~/printer.cfg -l /tmp/klippy.log < /dev/null > /dev/null 2>&1 &
```
Once Klippy is running, use a web-browser and navigate to the
OctoPrint web site. Under the "Connection" tab (on the left of the
main page) make sure the "Serial Port" is set to "/tmp/printer" and
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". If
the Klippy config file was successfully read, and the micro-controller
was successfully found and configured, then this command will report
that the printer is ready. Klippy reports error messages via this
terminal tab. The "status" command can be used to re-report error
messages.
(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.
In addition to common g-code commands, Klippy supports a few extended
commands - "status" is an example of one of these commands. Use the
"help" command to get a list of other extended commands. In
particular, note the "restart" command - use this command to reload
the Klippy config file after any changes.
Configuring Klipper
===================
The Klipper configuration is stored in a text file on the Raspberry
Pi. Take a look at the example config files in the
[config directory](../config/). The
[example.cfg](../config/example.cfg) file contains documentation on
command parameters and it can also be used as an initial config file
template. However, for most printers, one of the other config files
may be a more concise starting point.
Arguably the easiest way to update 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). Use one of the example
config files as a starting point and 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 - for example:
```
cp ~/klipper/config/example.cfg ~/printer.cfg
nano ~/printer.cfg
```
Make sure to review and update each setting that is appropriate for
the hardware.
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. It is not unusual to have
configuration errors during the initial setup - update 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.
In addition to common g-code commands, Klipper supports a few extended
commands - "status" and "restart" are examples of these commands. Use
the "help" command to get a list of other extended commands.
After Klipper reports that the "printer is ready" go on to the
[config check document](Config_checks.md) to perform some basic checks
on the pin definitions in the config file.
Contacting the developers
=========================
Be sure to see the [FAQ](FAQ.md) for answers to some common questions.
See the [contact page](Contact.md) to report a bug or to contact the
developers.

298
docs/Kinematics.md Normal file
View File

@@ -0,0 +1,298 @@
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.
![trapezoid](img/trapezoid.svg.png)
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).
![trapezoids](img/trapezoids.svg.png)
Look-ahead
==========
The "look-ahead" system is used to determine cornering speeds between
moves.
Consider the following two moves contained on an XY plane:
![corner](img/corner.svg.png)
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).
![lookahead](img/lookahead.svg.png)
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.
![lookahead](img/lookahead-slow.svg.png)
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/).
Klipper implements look-ahead between moves that have similar extruder
flow rates. Other moves are relatively rare and implementing
look-ahead between them is unnecessary.
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:
![zigzag](img/zigzag.svg.png)
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:
![smoothed](img/smoothed.svg.png)
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.
In general, the code determines each step time by first calculating
where along the line of movement the head would be if a step is
taken. It then calculates what time the head should be at that
position. Determining the time along the line of movement can be done
using the formulas for constant acceleration and constant velocity:
```
time = sqrt(2*distance/accel + (start_velocity/accel)^2) - start_velocity/accel
time = distance/cruise_velocity
```
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.
Delta Robots
------------
To generate step times on Delta printers it is necessary to correlate
the movement in cartesian space with the movement on each stepper
tower.
To simplify the math, for each stepper tower, the code calculates the
location of a "virtual tower" that is along the line of movement.
This virtual tower is chosen at the point where the line of movement
(extended infinitely in both directions) would be closest to the
actual tower.
![delta-tower](img/delta-tower.svg.png)
It is then possible to calculate where the head will be along the line
of movement after each step is taken on the virtual tower.
![virtual-tower](img/virtual-tower.svg.png)
The key formula is Pythagoras's theorem:
```
distance_to_tower^2 = arm_length^2 - tower_height^2
```
One complexity is that if the print head passes the virtual tower
location then the stepper direction must be reversed. In this case
forward steps will be taken at the start of the move and reverse steps
will be taken at the end of the move.
### Delta movements beyond simple XY plane ###
Movement calculation is more complicated if a single move contains
both XY movement and Z movement. These moves are rare, but they must
still be handled correctly. A virtual tower along the line of movement
is still calculated, but in this case the tower is not at a 90 degree
angle relative to the line of movement:
![xy+z-tower](img/xy+z-tower.svg.png)
The code continues to calculate step times using the same general
scheme as delta moves within an XY plane, but the slope of the tower
must also be used in the calculations.
Should the move contain only Z movement (ie, no XY movement at all)
then the same math is used - just in this case the tower is parallel
to the line of movement.
### 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 constant acceleration and constant velocity
formulas that cartesian robots use.
### 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".
![ooze](img/ooze.svg.png)
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:
```
extra_filament = pressure_advance_coefficient * extruder_velocity
```
See the [pressure advance](Pressure_Advance.md) document for
information on how to find this pressure advance coefficient.
Once configured, Klipper will push in an additional amount of filament
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).
![pressure-advance](img/pressure-advance.svg.png)
One may notice that the pressure advance algorithm can cause the
extruder motor to make sudden velocity changes. This is tolerated
based on the idea that the majority of the inertia in the system is in
changing the extruder pressure. As long as the extruder pressure does
not change rapidly the sudden changes in extruder motor velocity are
tolerated.
One area where sudden velocity changes become problematic is during
small changes in head speed due to cornering.
![pressure-cornering](img/pressure-cornering.svg.png)
To prevent this, the Klipper pressure advance code utilizes the move
look-ahead queue to detect intermittent speed changes. During a
deceleration event the code finds the maximum upcoming head speed
within a configurable time window. The pressure is then only adjusted
to this found maximum. This can greatly reduce (or even completely
eliminate) pressure changes during cornering.

285
docs/MCU_Commands.md Normal file
View File

@@ -0,0 +1,285 @@
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".
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.
Several of these commands will take a "pin=%u" parameter. The
low-level micro-controller software uses integer encodings of the
hardware pin numbers, but to make things more readable the host will
translate human readable pin names (eg, "PA3") to their equivalent
integer encodings. By convention, any parameter named "pin" or that
has a "_pin" suffix will use pin name translation by the
host.
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.
* `send_spi_message pin=%u msg=%*s` : This command can be used to
transmit messages to a serial-peripheral-interface (SPI) component
connected to the micro-controller. It has been used to configure the
startup settings of AD5206 digipots. The 'pin' parameter specifies
the chip select line to use during the transmission. The 'msg'
indicates the binary message to transmit to the given chip.
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 schedule_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_soft_pwm_out oid=%c pin=%u cycle_ticks=%u value=%c
default_value=%c max_duration=%u` : This command creates an internal
micro-controller object for software implemented PWM. Unlike
hardware pwm pins, a software pwm object does not require any
special hardware support (other than the ability to configure the
pin as a digital output GPIO). Because the output switching is
implemented in the micro-controller software, it is recommended that
the cycle_ticks parameter correspond to a time of 10ms or
greater. 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 min_stop_interval=%u
invert_step=%c` : 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 'min_stop_interval' implements a safety
feature - it is checked when the micro-controller finishes all moves
for a stepper - if it is non-zero it specifies the minimum number of
clock ticks since the last step. It is used as a check on the
maximum stepper velocity that a stepper may have before stopping.
* `config_end_stop 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
end_stop_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 end_stop_home below).
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.
* `schedule_digital_out oid=%c clock=%u value=%c` : 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.
* `schedule_pwm_out oid=%c clock=%u value=%hu` : Schedules a change to
a hardware PWM output pin. See the 'schedule_digital_out' and
'config_pwm_out' commands for more info.
* `schedule_soft_pwm_out oid=%c clock=%u value=%hu` : Schedules a
change to a software PWM output pin. See the 'schedule_digital_out'
and 'config_soft_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_status` : This command causes the micro-controller to generate
a "status" 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.
* `end_stop_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_end_stop' 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.

View File

@@ -1,18 +1,41 @@
See [installation](Installation.md) for information on compiling,
installing, and running Klipper. Read [features](Features.md) for a
high-level description of useful capabilities. The history of releases
is available at [releases](Releases.md).
Welcome to the Klipper documentation. There are two parts to Klipper -
code that runs on a micro-controller and code that runs on a "host"
machine. The host code is intended to run on a low-cost
general-purpose machine such as a Raspberry Pi, while the
micro-controller code is intended to run on commodity micro-controller
chips. Read [features](Features.md) for reasons to use Klipper. See
[installation](Installation.md) to get started with Klipper. See
[config checks](Config_checks.md) for a guide to verify basic pin
settings in the config file.
The Klipper configuration is stored in a simple text file on the host
machine. The [config/example.cfg](../config/example.cfg) file serves
as a reference for the config file. The
[Pressure Advance](Pressure_Advance.md) document contains information
on tuning the pressure advance config.
The [kinematics](Kinematics.md) document provides some technical
details on how Klipper implements motion. The [FAQ](FAQ.md) answers
some common questions. The [G-Codes](G-Codes.md) document lists
currently supported run-time commands.
The history of Klipper releases is available at
[releases](Releases.md). See [contact](Contact.md) for information on
bug reporting and general communication with the developers.
Developer Documentation
=======================
There are also several documents available for developers interested
in understanding how Klipper works:
in understanding how Klipper works. Start with the
[code overview](Code_Overview.md) document - it provides information
on the structure and layout of the Klipper code. See the
[contributing](CONTRIBUTING.md) document to submit improvements to Klipper.
See [code overview](Code_Overview.md) for information on the structure
and layout of the Klipper code.
See [protocol](Protocol.md) for information on the messaging protocol
between host and firmware. See also
[firmware commands](Firmware_Commands.md) for a high-level description
of common commands implemented in the firmware.
See [protocol](Protocol.md) for information on the low-level messaging
protocol between host and micro-controller. See also
[MCU commands](MCU_Commands.md) for a description of low-level
commands implemented in the micro-controller software.
See [debugging](Debugging.md) for information on how to test and debug
Klipper.

97
docs/Pressure_Advance.md Normal file
View File

@@ -0,0 +1,97 @@
This document provides information on tuning the "pressure advance"
configuration variables 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.
Prerequisites
=============
In order to tune the pressure advance setting the printer must be
configured and operational. The tuning test involves printing objects
and inspecting the differences between objects. In particular, the
extruder
[E steps](http://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide#E_steps)
and
[nozzle temperature](http://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide#Nozzle_Temperature)
should be tuned prior to tuning pressure advance.
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 measuring and tuning the pressure advance configuration.
Start by changing the extruder section of the config file so that
pressure_advance is set to 0.0. (Make sure to issue a RESTART command
after each update to the config file so that the new configuration
takes effect.) Then print at least 10 layers of a large hollow square
at high speed (eg, 100mm/s). See
[docs/prints/square.stl](prints/square.stl) file for an STL file that
one may use. While the object is printing, make a note of which
direction the head is moving during external perimeters. What many
people see here is blobbing occurring at the corners - extra filament
at the corner in the direction the head travels followed by a possible
lack of filament on the side immediately after that corner:
![corner-blob](img/corner-blob.jpg)
This blobbing is the result of pressure in the extruder being released
as a blob when the head slows down to corner.
The next step is to set pressure_advance_lookahead_time to 0.0, slowly
increase pressure_advance (eg, start with 0.05), and reprint the test
object. (Be sure to issue RESTART between each config change.) The
goal is to attempt to eliminate the blobbing during cornering. (With
pressure advance, the extruder will retract when the head slows down,
thus countering the pressure buildup and ideally eliminate the
blobbing.)
If a test run is done with a pressure_advance setting that is too
high, one typically sees a dimple in the corner followed by possible
blobbing after the corner (too much filament is retracted during slow
down and then too much filament is extruded during the following speed
up after cornering):
![corner-dimple](img/corner-dimple.jpg)
The goal is to find the smallest pressure_advance value that results
in good quality corners:
![corner-good](img/corner-good.jpg)
Typical pressure_advance values are between 0.05 and 0.20 (the high
end usually only with bowden extruders). If there is no significant
improvement seen after increasing pressure_advance to 0.20, then
pressure advance is unlikely to improve the quality of prints. Return
to a default configuration with pressure_advance disabled.
It is not unusual for one corner of the test print to be consistently
different than the other three corners. This typically occurs when the
slicer arranges to always change Z height at that corner. If this
occurs, then ignore that corner and tune pressure_advance using the
other three corners.
Once a good pressure_advance value is found, return
pressure_advance_lookahead_time to its default (0.010). This parameter
controls how far in advance to check if a head slow-down is
immediately followed by a speed-up - it reduces pointless pressure
changes in the head. It's possible to tune this - higher values will
decrease the number of pressure changes in the nozzle at the expense
of permitting more blobbing during cornering. (Tuning this value is
unlikely to impact ooze.) The default of 10ms should work well on most
printers.
Although this tuning exercise directly improves the quality of
corners, it's worth remembering that a good pressure advance
configuration can reduce ooze throughout the print.
Finally, 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.

View File

@@ -1,8 +1,9 @@
The Klipper transmission protocol can be thought of, at a high level,
as a series of command and response strings that are compressed,
transmitted over a serial line, and then processed at the receiving
side. An example series of commands in uncompressed human-readable
format might look like:
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=86 value=1
@@ -12,34 +13,35 @@ queue_step oid=7 interval=7458 count=10 add=331
queue_step oid=7 interval=11717 count=4 add=1281
```
See the [firmware commands](Firmware_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 firmware commands.
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
transmission protocol itself. It describes how messages are declared,
encoded in binary format (the "compression" scheme), and transmitted.
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 firmware that is low-latency,
low-bandwidth, and low-complexity for the firmware.
channel between the host and micro-controller that is low-latency,
low-bandwidth, and low-complexity for the micro-controller.
Firmware Interface
==================
Micro-controller Interface
==========================
The Klipper transmission protocol can be thought of as a
[RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) mechanism
between firmware and host. The firmware 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 firmware to
perform actions and to interpret the results.
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 firmware declares a "command" by using the DECL_COMMAND() macro in
the C code. For example:
The micro-controller software declares a "command" by using the
DECL_COMMAND() macro in the C code. For example:
```
DECL_COMMAND(command_set_digital_out, "set_digital_out pin=%u value=%c");
@@ -48,11 +50,11 @@ DECL_COMMAND(command_set_digital_out, "set_digital_out pin=%u value=%c");
The above declares a command named "set_digital_out". This allows the
host to "invoke" this command which would cause the
command_set_digital_out() C function to be executed in the
firmware. The above also indicates that the command takes two integer
parameters. When the command_set_digital_out() C code is executed, it
will be passed an array containing these two integers - the first
corresponding to the 'pin' and the second corresponding to the
'value'.
micro-controller. The above also indicates that the command takes two
integer parameters. When the command_set_digital_out() C code is
executed, it will be passed an array containing these two integers -
the first corresponding to the 'pin' 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
@@ -63,64 +65,61 @@ 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).
At firmware compile time, the build will collect all commands declared
with DECL_COMMAND(), determine their parameters, and arrange for them
to be callable.
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 firmware to the host a "response" is
generated. These are both declared and transmitted using the sendf() C
macro. For example:
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"). At firmware compile time
the build automatically finds all sendf() calls and generates encoders
for them. The first parameter of the sendf() function describes the
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 firmware and responses allow the firmware to invoke code in the
host.
in the micro-controller and responses allow the micro-controller
software to invoke code in the host.
The firmware should only invoke sendf() from command or task handlers,
and it should not be invoked from interrupts or timers. The firmware
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.
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, the firmware also has an output() C
function. For example:
To simplify debugging, there is also has 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. It is
a wrapper around sendf() and as with sendf() it should not be called
from interrupts or timers.
to generate and format arbitrary messages for human consumption.
Declaring constants
-------------------
The firmware can also define constants to be exported. For example,
the following:
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 firmware to the host.
from the micro-controller to the host.
Low-level message encoding
==========================
@@ -132,9 +131,9 @@ the transmission system.
Message Blocks
--------------
All data sent from host to firmware 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:
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>
@@ -162,10 +161,11 @@ present in the message block content.
Message Block Contents
----------------------
Each message block sent from host to firmware contains a series of
zero or more message commands in its contents. Each command starts
with a Variable Length Quantity (VLQ) encoded integer command-id
followed by zero or more VLQ parameters for the given command.
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:
@@ -184,21 +184,22 @@ and encoded into the following eight VLQ integers:
```
In order to encode and parse the message contents, both the host and
firmware must agree on the command ids and the number of parameters
each command has. So, in the above example, both the host and firmware
would know that "id_set_digital_out" is always followed by two
parameters, and "id_get_config" and "id_get_status" have zero
parameters. The host and firmware share a "data dictionary" that maps
the command descriptions (eg, "set_digital_out pin=%u 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.
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_set_digital_out" is always
followed by two parameters, and "id_get_config" and "id_get_status"
have zero parameters. The host and micro-controller share a "data
dictionary" that maps the command descriptions (eg, "set_digital_out
pin=%u 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 firmware 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 firmware to the host never
contain more than one response in the message block contents.
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
@@ -230,60 +231,62 @@ the length as a VLQ encoded integer followed by the contents itself:
```
The command descriptions found in the data dictionary allow both the
host and firmware to know which command parameters use simple VLQ
encoding and which parameters use string encoding.
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
firmware 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.
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.
At compile time the firmware build uses the contents of DECL_COMMAND()
and sendf() macros to generate the data dictionary. The build
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 firmware code to
seamlessly use descriptive human-readable names while still using
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
firmware. Once the host downloads the data dictionary from the
firmware, it uses that data dictionary to encode all commands and to
parse all responses from the firmware. The host must therefore handle
a dynamic data dictionary. However, to keep the firmware simple, the
firmware always uses its static (compiled in) data dictionary.
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
firmware. The firmware 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 firmware 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.
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 firmware compile process generates the
string, compresses it, and stores it in the text section of the
firmware. 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
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 firmware version, constants (as defined by
DECL_CONSTANT), and static strings.
dictionary also contains the software version, constants (as defined
by DECL_CONSTANT), and static strings.
Static Strings
--------------
To reduce bandwidth the data dictionary also contains a set of static
strings known to the firmware. This is useful when sending messages
from firmware to host. For example, if the firmware were to run:
strings known to the micro-controller. This is useful when sending
messages from micro-controller to host. For example, if the
micro-controller were to run:
```
shutdown("Unable to handle command");
@@ -296,22 +299,22 @@ to their associated human-readable strings.
Message flow
============
Message commands sent from host to firmware are intended to be
error-free. The firmware will check the CRC and sequence numbers in
each message block to ensure the commands are accurate and
in-order. The firmware 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.
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 firmware. To
facilitate this, the firmware 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
firmware detects a corrupt or out-of-order block it may transmit a
"nak message block" to facilitate fast retransmission.
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
@@ -326,15 +329,15 @@ 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 firmware to host are
designed to be error-free, but they do not have assured
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 firmware
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.
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
View File

@@ -0,0 +1,2 @@
Welcome to the Klipper documentation. The
[overview document](Overview.md) is a good starting point.

View File

@@ -1,6 +1,77 @@
History of Klipper releases. Please see
[installation](Installation.md) for information on installing Klipper.
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
=============

View File

@@ -1,5 +1,5 @@
Klipper is currently in an experimental state. There are several
features still to be implemented. In no particular order:
There are several features still to be implemented in Klipper. In no
particular order:
Host user interaction
=====================
@@ -9,13 +9,6 @@ Host user interaction
find the error) and errors written to the log can be non-obvious to
a user.
* Improve startup:
* Provide startup scripts so that Klippy can startup at system
bootup.
* Allow loading of a new config without having to restart the mcu.
* Improve gcode interface:
* Provide a better way to handle print nozzle z offsets. The M206
@@ -28,12 +21,6 @@ Host user interaction
* Improve logging:
* Automatically roll Klippy log files. The default log file should
have the current date in the log file name.
* Report the Klippy git version in log file. Log the contents of the
config file at startup.
* Possibly collate and report the statistics messages in the log in a
more friendly way.
@@ -44,12 +31,12 @@ Host user interaction
Safety features
===============
* Support loading a valid step range into the firmware after
homing. This would provide a sanity check in the firmware that would
reduce the risk of the host commanding a stepper motor past its
valid step range. To maintain high efficiency in the firmware, the
firmware would only need to check periodically (eg, every 100ms)
that the stepper is in range.
* Support loading a valid step range into the micro-controller
software after homing. This would provide a sanity check in the
micro-controller that would reduce the risk of the host commanding a
stepper motor past its valid step range. To maintain high
efficiency, the micro-controller would only need to check
periodically (eg, every 100ms) that the stepper is in range.
* Possibly support periodically querying the endstop switches and use
multiple step ranges depending on the switch state. This would
@@ -57,50 +44,28 @@ Safety features
endstop detection is a good idea because of spurious signals caused
by electrical noise.)
* Support validating that heaters are heating at expected rates. This
can be useful to detect a sensor failure (eg, thermistor short) that
could otherwise cause the PID to command excessive heating.
* Possibly implement host based checking on the ratio between extrude
amount and head movement.
* Enforce acceleration and speed limits on extruder stepper motor.
Testing features
================
* Complete the host based simulator. It's possible to compile the
firmware for a "host simulator", but that simulator doesn't do
anything currently. It would be useful to expand the code to support
more error checks, kinematic simulations, and improved logging.
micro-controller for a "host simulator", but that simulator doesn't
do anything currently. It would be useful to expand the code to
support more error checks, kinematic simulations, and improved
logging.
Documentation
=============
* Document and test running the host software on a Beagle Bone Black.
* Add documentation describing how to perform bed-leveling accurately
in Klipper. Improve description of stepper phase based bed leveling.
* Document the kinematic formulas in Klippy. Document how acceleration
and jerk limits are enforced.
* Document how one can tune the pressure advance setting.
Hardware features
=================
* Port firmware to more architectures:
* Beagle Bone Black PRU
* Port to additional micro-controller architectures:
* Smoothieboard / NXP LPC1769 (ARM cortex-M3)
* Unix based scheduling; Unix based real-time scheduling
* Support for additional kinematics: scara, corexy, etc.
* Support shared motor enable GPIO lines.
* Support for multiple extruders.
* Support for bed-level probes.
* Support for additional kinematics: scara, etc.
* Possible support for touch panels attached to the micro-controller.
(In general, it would be preferable to attach touch panels to the
@@ -108,19 +73,9 @@ Hardware features
it would also be useful to handle panels already hardwired to the
micro-controller.)
* The raspberry pi has the ability to cut power to its USB ports. This
feature is useful for resetting micro-controllers that are powered
over USB. It would be useful to have a high-level command interface
in Klippy to request a micro-controller reset via this mechanism.
* Possibly support printers using multiple micro-controllers.
Misc features
=============
* Possibly use cubic functions instead of quadratic functions in step
compression code.
* Possibly support a "feed forward PID" that takes into account the
amount of plastic being extruded. If the extrude rate changes
significantly during a print it can cause heating bumps that the PID

103
docs/beaglebone.md Normal file
View File

@@ -0,0 +1,103 @@
This document describes the process of running Klipper on a Beaglebone
PRU.
Building an OS image
====================
Start by installing the
[latest Jessie IoT](https://beagleboard.org/latest-images) image
(2017-03-19 or later). 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/KevinOConnor/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
```
For the Replicape, it is also necessary to compile and install the
micro-controller code for a Linux host process. Run "make menuconfig"
a second time and configure it 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 document](Installation.md#configuring-klipper).
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/example-extras.cfg](../config/example-extras.cfg) for
details) to print directly from Klipper.

View 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/attach-issue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/img/corner-blob.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
docs/img/corner-dimple.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
docs/img/corner-good.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

184
docs/img/corner.svg Normal file
View File

@@ -0,0 +1,184 @@
<?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="54.904114mm"
height="6.0860338mm"
viewBox="0 0 194.54213 21.564687"
id="svg3506"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="corner.svg">
<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="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.49"
inkscape:cx="95.030833"
inkscape:cy="-0.17370789"
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="478"
inkscape:window-x="378"
inkscape:window-y="113"
inkscape:window-maximized="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" />
<dc:title />
</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;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(0.98759291,-0.15703579,0.15703579,0.98759291,0,0)"
inkscape:transform-center-x="1.3563414"
inkscape:transform-center-y="-5.7099754"><tspan
sodipodi:role="line"
id="tspan5552"
x="189.09824"
y="482.48389">move 1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(0.98949457,0.14457001,-0.14457001,0.98949457,0,0)"><tspan
sodipodi:role="line"
id="tspan5554"
x="427.95532"
y="379.5321">move 2</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
docs/img/corner.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

273
docs/img/delta-tower.svg Normal file
View File

@@ -0,0 +1,273 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="delta-tower.svg">
<defs
id="defs4">
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker6618"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path6620"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker6500"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path6502"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1;fill:#4b4b4b;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker6082"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
transform="scale(0.4) rotate(180) translate(10,0)"
style="fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1;fill:#4b4b4b;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path6084" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path5747"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1;fill:#4b4b4b;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path5744"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1;fill:#4b4b4b;fill-opacity:1"
transform="scale(0.4) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend-1"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<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:isstock="true"
style="overflow:visible"
id="marker6082-9"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path6084-2" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.75"
inkscape:cx="172.24895"
inkscape:cy="45.708959"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="928"
inkscape:window-height="628"
inkscape:window-x="162"
inkscape:window-y="50"
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: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" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-135.22429,-249.96955)">
<ellipse
style="fill:#4d4d4d;stroke:#4b4b4b;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:2, 1, 0.5, 1;stroke-dashoffset:0;stroke-opacity:1"
id="path4255"
cx="353.79568"
cy="327.87662"
rx="4.2857141"
ry="4.8571429" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000006;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)"
d="M 181.50998,381.87664 359.22427,275.01949"
id="path5510"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="371.22427"
y="354.44806"
id="text6058"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6060"
x="371.22427"
y="354.44806">stepper</tspan><tspan
sodipodi:role="line"
x="371.22427"
y="366.94806"
id="tspan9337">tower</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="166.65283"
y="304.16235"
id="text6062"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6064"
x="166.65283"
y="304.16235">line of movement</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:10.0000006px;line-height:125%;font-family:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;-inkscape-font-specification:'DejaVu Sans, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;"
x="252.93855"
y="384.16235"
id="text6066"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6068"
x="252.93855"
y="384.16235">move</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000006;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#marker6618)"
d="m 382.65284,344.73378 c -0.19273,-13.52091 -9.87887,-14.83602 -20.57143,-14.85715"
id="path6070"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker6500)"
d="m 254.65284,374.44806 c 3.39239,-12.86009 -2.06023,-20.09154 -15.42857,-22.28571"
id="path6072"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6082)"
d="m 257.50997,296.16234 c 31.05376,-3.13332 32.38959,-1.23784 42.28572,10.28572"
id="path6074"
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 219.61431,358.80126 57.78715,-34.48307"
id="path3514-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:0.50000003;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 351.22427,323.59092 -20.57143,-32"
id="path3358"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="244.36713"
y="257.30521"
id="text4460"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4462"
x="244.36713"
y="257.30521">virtual tower</tspan><tspan
sodipodi:role="line"
x="244.36713"
y="269.80521"
id="tspan5867">location</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6082-9)"
d="m 310.90661,257.14111 c 21.29088,8.40268 18.35244,16.28958 20.57143,29.7143"
id="path6074-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

208
docs/img/lookahead-slow.svg Normal file
View File

@@ -0,0 +1,208 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
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">
<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="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.15"
inkscape:cx="3.4198125"
inkscape:cy="101.26451"
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: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" />
<dc:title></dc:title>
</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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="434.04257"
y="365.1282">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan3355"
x="-313.86618"
y="140.27856">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;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7078"
x="195.45749"
y="286.52051">move A</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan7080"
x="280.5639"
y="254.60564">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;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(0.96753827,0.25272454,-0.25272454,0.96753827,0,0)"
inkscape:transform-center-x="-0.91382951"
inkscape:transform-center-y="-4.9145266"><tspan
sodipodi:role="line"
id="tspan7074"
x="36.7374"
y="252.31848">move A</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(0.93839918,-0.34555314,0.34555314,0.93839918,0,0)"><tspan
sodipodi:role="line"
id="tspan7076"
x="-126.26086"
y="304.35226">move B</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

136
docs/img/lookahead.svg Normal file
View File

@@ -0,0 +1,136 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="lookahead.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.94"
inkscape:cx="116.54041"
inkscape:cy="45.708959"
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: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" />
<dc:title />
</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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="434.04257"
y="365.1282">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan3355"
x="-313.86618"
y="140.27856">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;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5532"
x="200.77664"
y="286.52051">move 1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5534"
x="280.5639"
y="255.66946">move 2</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
docs/img/lookahead.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

207
docs/img/ooze.svg Normal file
View File

@@ -0,0 +1,207 @@
<?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="98.140816mm"
height="63.537022mm"
viewBox="0 0 347.74305 225.13119"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
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">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.94"
inkscape:cx="199.68782"
inkscape:cy="58.510649"
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: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" />
<dc:title />
</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;font-size:12.50000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12733"
x="-346.84067"
y="139.75046">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;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12658"
x="200.11789"
y="284.45413">extrude move</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12662"
x="356.50089"
y="283.39032">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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351-4"
x="436.76678"
y="586.62585">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan4197"
x="-551.11292"
y="125.37186">actual</tspan><tspan
sodipodi:role="line"
id="tspan4199"
x="-551.11292"
y="140.99686">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;font-size:12.50000095px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan4193"
x="-444.27307"
y="124.17301">desired</tspan><tspan
sodipodi:role="line"
id="tspan4195"
x="-444.27307"
y="139.79802">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.8 KiB

BIN
docs/img/ooze.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,207 @@
<?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="102.61139mm"
height="99.266594mm"
viewBox="0 0 363.58366 351.73204"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="pressure-advance.svg"
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/pressure-advance.svg.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.97968464"
inkscape:cx="147.06528"
inkscape:cy="169.55487"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="588"
inkscape:window-x="419"
inkscape:window-y="273"
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:grid
type="xygrid"
id="grid3436"
originx="17.089787"
originy="126.61899" />
</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" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-118.13451,-140.19216)">
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 150.47693,249.82417 0.58688,123.9666 m 0,-21.42857 327.12765,-0.53192 -7.97871,5.85107"
id="path3347"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;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="-334.86746"
y="122.91875"
id="text3353"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12816"
x="-334.86746"
y="122.91875">extruder</tspan><tspan
sodipodi:role="line"
id="tspan12818"
x="-334.86746"
y="138.54375">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 316.60647,311.78473 16.53759,62.00711 m -154.57776,-52.12767 16.05677,-60.94328 1.06383,29.78724 m 0,0 120.91957,-1.06383 0,22.34043"
id="path3361"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 148.75077,140.45716 1.06383,102.12766 327.12769,-0.53192 -7.97872,5.85107"
id="path3347-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;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="-237.05733"
y="140.25932"
id="text3353-2"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12733-6"
x="-237.05733"
y="140.25932">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 148.75077,140.45716 -5.31915,8.51063"
id="path3359-7"
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 178.3809,241.67403 16.05679,-60.94329 120.91958,-1.06383 16.53759,62.00712"
id="path3361-5"
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 331.74721,241.47248 16.72764,-63.00288 133.24332,0"
id="path3361-7-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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="198.86868"
y="174.67674"
id="text12656-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12658-8"
x="198.86868"
y="174.67674">extrude move</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25000095px;line-height:125%;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="355.25165"
y="173.61293"
id="text12660-7"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12662-2"
x="355.25165"
y="173.61293">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 151.94226,384.0742 1.06383,102.12766 327.12769,-0.53192 -7.97872,5.85107"
id="path3347-2"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;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="-467.65732"
y="122.73453"
id="text3353-1"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12868"
x="-467.65732"
y="122.73453">extruder</tspan><tspan
sodipodi:role="line"
id="tspan12870"
x="-467.65732"
y="138.35953">pressure</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 151.94226,384.0742 -5.31915,8.51063"
id="path3359-5"
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 181.57239,485.29107 16.05679,-60.94329 120.91958,-1.06383 16.53759,62.00712"
id="path3361-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:100%;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="438.03586"
y="499.53384"
id="text3349"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="438.03586"
y="499.53384">time</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,180 @@
<?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="102.04809mm"
height="61.494076mm"
viewBox="0 0 361.58771 217.8924"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="pressure-cornering.svg"
inkscape:export-filename="/home/kevin/src/reprap/firmware/klipper/docs/img/pressure-cornering.svg.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98"
inkscape:cx="110.74341"
inkscape:cy="35.715236"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="588"
inkscape:window-x="656"
inkscape:window-y="0"
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:grid
type="xygrid"
id="grid3436"
originx="17.089805"
originy="-7.2206491" />
</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" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-118.13449,-140.19216)">
<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;font-size:12.50000095px;line-height:125%;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="-334.86746"
y="122.91875"
id="text3353"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12816"
x="-334.86746"
y="122.91875">extruder</tspan><tspan
sodipodi:role="line"
id="tspan12818"
x="-334.86746"
y="138.54375">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 178.5663,321.66417 16.05677,-60.94328 1.06383,29.78724 m 0,0 117.21969,-0.77616 5.99519,7.3871 5.9952,-6.89861 131.50541,-0.77616"
id="path3361"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 148.75077,140.45716 1.06383,102.12766 327.12769,-0.53192 -7.97872,5.85107"
id="path3347-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.50000095px;line-height:125%;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="-237.05733"
y="140.25932"
id="text3353-2"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan12733-6"
x="-237.05733"
y="140.25932">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 148.75077,140.45716 -5.31915,8.51063"
id="path3359-7"
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 178.3809,241.67403 16.05679,-60.94329 120.91958,-1.06383 4.29269,10.98671"
id="path3361-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 319.50231,193.5133 4.48274,-15.0437 133.24332,0"
id="path3361-7-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25px;line-height:125%;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="198.86868"
y="174.67674"
id="text12656-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12891"
x="198.86868"
y="174.67674">first extrude</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.25px;line-height:125%;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="355.25165"
y="173.61293"
id="text12660-7"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan12893"
x="355.25165"
y="173.61293">second extrude</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4, 2, 1, 2;stroke-dashoffset:0;stroke-opacity:1"
d="m 314.05288,288.86296 0,17.34694 5.10204,17.34694 -1.02041,-48.97959 7.14286,-17.34694 0,31.63265"
id="path12895"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:100%;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="435.80841"
y="366.8262"
id="text3349"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="435.80841"
y="366.8262">time</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

132
docs/img/smoothed.svg Normal file
View File

@@ -0,0 +1,132 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="smoothed.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.75"
inkscape:cx="167.32577"
inkscape:cy="45.708959"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="840"
inkscape:window-height="628"
inkscape:window-x="162"
inkscape:window-y="50"
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: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" />
<dc:title></dc:title>
</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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="434.04257"
y="365.1282">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan3355"
x="-313.86618"
y="140.27856">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:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 165.50998,351.59092 15.42857,-35.42857 35.71428,0 11.71429,36.57143"
id="path3362"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.07142997px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 227.83578,352.85633 15.76217,-47.37239 22.00135,0 5.58242,17.6933"
id="path3362-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.21482575px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 271.35434,323.73296 11.15454,-30.54076 19.27119,-0.11152 8.73883,29.51288"
id="path3362-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.01949775px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 311.26144,322.49329 11.63197,-21.06975 15.33656,0 13.51652,50.22357"
id="path3362-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.00000012, 1.00000006, 0.50000003, 1.00000006;stroke-dashoffset:0;stroke-opacity:1"
d="m 165.50999,351.59092 33.14285,-34.28571 29.14286,34.28571"
id="path3426"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
docs/img/smoothed.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

102
docs/img/trapezoid.svg Normal file
View File

@@ -0,0 +1,102 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="trapezoid.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.94"
inkscape:cx="294.7319"
inkscape:cy="45.708959"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="588"
inkscape:window-x="113"
inkscape:window-y="31"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
showborder="false" />
<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" />
<dc:title></dc:title>
</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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="434.04257"
y="365.1282">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan3355"
x="-313.86618"
y="140.27856">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:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179.78723,351.29837 41.48937,-60.63829 158.51063,0 37.23405,60.63829"
id="path3361"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
docs/img/trapezoid.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

182
docs/img/trapezoids.svg Normal file
View File

@@ -0,0 +1,182 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="trapezoids.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.67"
inkscape:cx="164.48301"
inkscape:cy="76.011989"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1091"
inkscape:window-height="588"
inkscape:window-x="113"
inkscape:window-y="31"
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: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" />
<dc:title />
</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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="434.04257"
y="365.1282">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan3355"
x="-313.86618"
y="140.27856">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 6.96312,32.21987"
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 263.83557,321.45597 11.41184,-61.95224 59.85662,0 9.80496,29.88826"
id="path3361-7"
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 344.93248,289.80297 59.85663,0 15.12411,61.95225"
id="path3361-7-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 263.86975,321.69491 0.37453,30.52957"
id="path3412"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 345.25947,289.31929 0.14909,62.46104"
id="path3414"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 222.45831,289.77329 -0.0598,62.07666"
id="path3416"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:20.00000119px;line-height:125%;font-family:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;-inkscape-font-specification:'DejaVu Sans, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;"
x="193.73491"
y="338.70944"
id="text3418"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3420"
x="193.73491"
y="338.70944">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20.00000191px;line-height:125%;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="236.28812"
y="338.70947"
id="text3422"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3434"
x="236.28812"
y="338.70947">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:20.00000191px;line-height:125%;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="294.79874"
y="335.51794"
id="text3426"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3428"
x="294.79874"
y="335.51794">3</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:20.00000119px;line-height:125%;font-family:'DejaVu Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;-inkscape-font-specification:'DejaVu Sans, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;"
x="367.13916"
y="337.6456"
id="text3430"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3432"
x="367.13916"
y="337.6456">4</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
docs/img/trapezoids.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

241
docs/img/virtual-tower.svg Normal file
View File

@@ -0,0 +1,241 @@
<?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="64.619751mm"
height="27.45583mm"
viewBox="0 0 228.96762 97.284438"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="virtual-tower.svg">
<defs
id="defs4">
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker6618"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path6620"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="marker6500"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6502"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;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"
inkscape:collect="always">
<path
id="path5747"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path5744"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;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"
inkscape:collect="always">
<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:isstock="true"
style="overflow:visible"
id="marker6082"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path6084" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.75"
inkscape:cx="169.7719"
inkscape:cy="-4.0565054"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="922"
inkscape:window-height="628"
inkscape:window-x="162"
inkscape:window-y="50"
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:grid
type="xygrid"
id="grid3436"
originx="-14.085234"
originy="-95.286988" />
</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" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-149.30952,-172.73378)">
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)"
d="m 176.36712,256.16235 200.00001,-0.57143"
id="path5510"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="-254.01012"
y="369.20834"
id="text6058"
sodipodi:linespacing="125%"
transform="matrix(-0.01833576,-0.99983189,0.99983189,-0.01833576,0,0)"
inkscape:transform-center-x="-8.0000002"
inkscape:transform-center-y="12.571429"><tspan
sodipodi:role="line"
id="tspan10365"
x="-254.01012"
y="369.20834">virtual tower</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="148.36713"
y="269.87662"
id="text6062"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6064"
x="148.36713"
y="269.87662">line of movement</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="237.50998"
y="251.01949"
id="text6066"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6068"
x="237.50998"
y="251.01949">move</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:7.00000048;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 358.08141,255.01949 0,-82.28571"
id="path10351"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 220.36713,255.01949 357.50998,173.30521"
id="path10373"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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.36713"
y="187.59093"
id="text10375"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10377"
x="200.36713"
y="187.59093">virtual arm</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6082)"
d="m 261.76375,182.85539 c 22.73118,-0.70136 26.45506,3.7437 40.00001,18.28573"
id="path6074"
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 219.61431,255.37268 70.93001,0.37408"
id="path3514-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

241
docs/img/xy+z-tower.svg Normal file
View File

@@ -0,0 +1,241 @@
<?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="64.619751mm"
height="27.45583mm"
viewBox="0 0 228.96762 97.284438"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="xy+z-tower.svg">
<defs
id="defs4">
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker6618"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path6620"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="marker6500"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6502"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;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"
inkscape:collect="always">
<path
id="path5747"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path5744"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;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"
inkscape:collect="always">
<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:isstock="true"
style="overflow:visible"
id="marker6082"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend"
inkscape:collect="always">
<path
inkscape:connector-curvature="0"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#4b4b4b;fill-opacity:1;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path6084" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.75"
inkscape:cx="169.7719"
inkscape:cy="-4.0565054"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="922"
inkscape:window-height="628"
inkscape:window-x="162"
inkscape:window-y="50"
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:grid
type="xygrid"
id="grid3436"
originx="-14.085234"
originy="-95.286988" />
</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" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-149.30952,-172.73378)">
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)"
d="m 176.36712,256.16235 200.00001,-0.57143"
id="path5510"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="-119.27526"
y="434.37329"
id="text6058"
sodipodi:linespacing="125%"
transform="matrix(0.32454206,-0.94587127,0.94587127,0.32454206,0,0)"
inkscape:transform-center-x="-3.9400734"
inkscape:transform-center-y="14.789029"><tspan
sodipodi:role="line"
id="tspan10365"
x="-119.27526"
y="434.37329">virtual tower</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="148.36713"
y="269.87662"
id="text6062"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6064"
x="148.36713"
y="269.87662">line of movement</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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="237.50998"
y="251.01949"
id="text6066"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6068"
x="237.50998"
y="251.01949">move</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:7.00000048;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 354.70239,255.76769 28.12779,-77.32895"
id="path10351"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 220.36713,255.01949 380.93855,178.44807"
id="path10373"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.00000095px;line-height:125%;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.36713"
y="187.59093"
id="text10375"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10377"
x="200.36713"
y="187.59093">virtual arm</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#4b4b4b;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker6082)"
d="m 261.76375,182.85539 c 22.73118,-0.70136 26.45506,3.7437 40.00001,18.28573"
id="path6074"
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 219.61431,255.37268 70.93001,0.37408"
id="path3514-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
docs/img/xy+z-tower.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

126
docs/img/zigzag.svg Normal file
View File

@@ -0,0 +1,126 @@
<?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="97.22496mm"
height="32.550285mm"
viewBox="0 0 344.49789 115.33566"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="zigzag.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.75"
inkscape:cx="167.32577"
inkscape:cy="45.708959"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="840"
inkscape:window-height="628"
inkscape:window-x="160"
inkscape:window-y="35"
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: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" />
<dc:title></dc:title>
</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;font-size:12.5px;line-height:100%;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"
sodipodi:linespacing="100%"><tspan
sodipodi:role="line"
id="tspan3351"
x="434.04257"
y="365.1282">time</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.5px;line-height:125%;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"
sodipodi:linespacing="125%"
transform="matrix(-0.01601372,-0.99987177,0.99987177,-0.01601372,0,0)"><tspan
sodipodi:role="line"
id="tspan3355"
x="-313.86618"
y="140.27856">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:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 165.50998,351.59092 24.57143,-73.14286 23.42857,73.14286"
id="path3362"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 214.08032,352.31321 24.57144,-73.14287 13.14286,43.42858"
id="path3362-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.09757805px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 252.42963,323.78006 17.64919,-60.34771 14.22362,59.20485"
id="path3362-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 284.36604,322.59892 14.85715,-44.00001 3.71429,0 16.85715,73.14287"
id="path3362-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
docs/img/zigzag.svg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

2
docs/issue_template.md Normal file
View File

@@ -0,0 +1,2 @@
<!-- Klipper do something undesirable? YOU MUST ATTACH THE KLIPPER LOG FILE.
See: https://github.com/KevinOConnor/klipper/blob/master/docs/Contact.md -->

45
docs/prints/square.scad Normal file
View File

@@ -0,0 +1,45 @@
// Test square
//
// Generate STL using OpenSCAD:
// openscad square.scad -o square.stl
square_width = 5;
square_size = 60;
square_height = 5;
module hollow_square() {
difference() {
cube([square_size, square_size, square_height]);
translate([square_width, square_width, -1])
cube([square_size-2*square_width, square_size-2*square_width,
square_height+2]);
}
}
module notch() {
CUT = 0.01;
depth = .5;
width = 1;
translate([-depth, -width, -CUT])
cube([2*depth, 2*width, square_height + 2*CUT]);
}
module square_with_notches() {
difference() {
// Start with initial square
hollow_square();
// Remove four notches on inside perimeter
translate([square_width, square_size/2 - 4, 0])
notch();
translate([square_size/2, square_size - square_width, 0])
rotate([0, 0, 90])
notch();
translate([square_size - square_width, square_size/2, 0])
notch();
translate([square_size/2, square_width, 0])
rotate([0, 0, 90])
notch();
}
}
square_with_notches();

674
docs/prints/square.stl Normal file
View File

@@ -0,0 +1,674 @@
solid OpenSCAD_Model
facet normal -1 0 0
outer loop
vertex 0 0 0
vertex 0 60 5
vertex 0 60 0
endloop
endfacet
facet normal -1 -0 0
outer loop
vertex 0 60 5
vertex 0 0 0
vertex 0 0 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 5 25 5
vertex 4.5 25 5
vertex 5 5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 29 5 5
vertex 5 5 5
vertex 29 4.5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 60 60 5
vertex 55.5 31 5
vertex 60 0 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 60 60 5
vertex 55 55 5
vertex 55.5 31 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 60 60 5
vertex 31 55.5 5
vertex 55 55 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 60 60 5
vertex 29 55.5 5
vertex 31 55.5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 29 55.5 5
vertex 5 55 5
vertex 29 55 5
endloop
endfacet
facet normal -0 0 1
outer loop
vertex 0 60 5
vertex 29 55.5 5
vertex 60 60 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 5 55 5
vertex 4.5 27 5
vertex 5 27 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 0 0 5
vertex 4.5 27 5
vertex 0 60 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 5 55 5
vertex 0 60 5
vertex 4.5 27 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 29 55.5 5
vertex 0 60 5
vertex 5 55 5
endloop
endfacet
facet normal -0 0 1
outer loop
vertex 55.5 29 5
vertex 60 0 5
vertex 55.5 31 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 55 5 5
vertex 55.5 29 5
vertex 55 29 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 55.5 29 5
vertex 55 5 5
vertex 60 0 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 31 4.5 5
vertex 55 5 5
vertex 31 5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 55 5 5
vertex 31 4.5 5
vertex 60 0 5
endloop
endfacet
facet normal -0 0 1
outer loop
vertex 29 4.5 5
vertex 60 0 5
vertex 31 4.5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 0 0 5
vertex 29 4.5 5
vertex 5 5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 4.5 27 5
vertex 0 0 5
vertex 4.5 25 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 29 4.5 5
vertex 0 0 5
vertex 60 0 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 4.5 25 5
vertex 0 0 5
vertex 5 5 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 55.5 31 5
vertex 55 55 5
vertex 55 31 5
endloop
endfacet
facet normal 0 0 1
outer loop
vertex 55 55 5
vertex 31 55.5 5
vertex 31 55 5
endloop
endfacet
facet normal 1 -0 0
outer loop
vertex 60 0 5
vertex 60 60 0
vertex 60 60 5
endloop
endfacet
facet normal 1 0 0
outer loop
vertex 60 60 0
vertex 60 0 5
vertex 60 0 0
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 60 60 0
vertex 0 60 5
vertex 60 60 5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 0 60 5
vertex 60 60 0
vertex 0 60 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 5 27 0
vertex 4.5 27 0
vertex 5 55 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 29 55 0
vertex 5 55 0
vertex 29 55.5 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 60 0 0
vertex 55.5 29 0
vertex 60 60 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 60 0 0
vertex 55 5 0
vertex 55.5 29 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 60 0 0
vertex 31 4.5 0
vertex 55 5 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 60 0 0
vertex 29 4.5 0
vertex 31 4.5 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 29 4.5 0
vertex 5 5 0
vertex 29 5 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 0 0 0
vertex 29 4.5 0
vertex 60 0 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 5 5 0
vertex 4.5 25 0
vertex 5 25 0
endloop
endfacet
facet normal -0 0 -1
outer loop
vertex 4.5 25 0
vertex 0 0 0
vertex 4.5 27 0
endloop
endfacet
facet normal -0 0 -1
outer loop
vertex 5 5 0
vertex 0 0 0
vertex 4.5 25 0
endloop
endfacet
facet normal -0 0 -1
outer loop
vertex 29 4.5 0
vertex 0 0 0
vertex 5 5 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 55.5 31 0
vertex 60 60 0
vertex 55.5 29 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 55 55 0
vertex 55.5 31 0
vertex 55 31 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 55.5 31 0
vertex 55 55 0
vertex 60 60 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 31 55.5 0
vertex 55 55 0
vertex 31 55 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 55 55 0
vertex 31 55.5 0
vertex 60 60 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 29 55.5 0
vertex 60 60 0
vertex 31 55.5 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 0 60 0
vertex 29 55.5 0
vertex 5 55 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 0 60 0
vertex 4.5 27 0
vertex 0 0 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 29 55.5 0
vertex 0 60 0
vertex 60 60 0
endloop
endfacet
facet normal 0 0 -1
outer loop
vertex 4.5 27 0
vertex 0 60 0
vertex 5 55 0
endloop
endfacet
facet normal -0 0 -1
outer loop
vertex 55.5 29 0
vertex 55 5 0
vertex 55 29 0
endloop
endfacet
facet normal -0 0 -1
outer loop
vertex 55 5 0
vertex 31 4.5 0
vertex 31 5 0
endloop
endfacet
facet normal 0 -1 0
outer loop
vertex 0 0 0
vertex 60 0 5
vertex 0 0 5
endloop
endfacet
facet normal 0 -1 -0
outer loop
vertex 60 0 5
vertex 0 0 0
vertex 60 0 0
endloop
endfacet
facet normal 1 -0 0
outer loop
vertex 5 5 5
vertex 5 25 0
vertex 5 25 5
endloop
endfacet
facet normal 1 0 0
outer loop
vertex 5 25 0
vertex 5 5 5
vertex 5 5 0
endloop
endfacet
facet normal 1 -0 0
outer loop
vertex 5 27 5
vertex 5 55 0
vertex 5 55 5
endloop
endfacet
facet normal 1 0 0
outer loop
vertex 5 55 0
vertex 5 27 5
vertex 5 27 0
endloop
endfacet
facet normal -1 0 0
outer loop
vertex 55 5 0
vertex 55 29 5
vertex 55 29 0
endloop
endfacet
facet normal -1 -0 0
outer loop
vertex 55 29 5
vertex 55 5 0
vertex 55 5 5
endloop
endfacet
facet normal -1 0 0
outer loop
vertex 55 31 0
vertex 55 55 5
vertex 55 55 0
endloop
endfacet
facet normal -1 -0 0
outer loop
vertex 55 55 5
vertex 55 31 0
vertex 55 31 5
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 29 5 0
vertex 5 5 5
vertex 29 5 5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 5 5 5
vertex 29 5 0
vertex 5 5 0
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 55 5 0
vertex 31 5 5
vertex 55 5 5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 31 5 5
vertex 55 5 0
vertex 31 5 0
endloop
endfacet
facet normal 0 -1 0
outer loop
vertex 5 55 0
vertex 29 55 5
vertex 5 55 5
endloop
endfacet
facet normal 0 -1 -0
outer loop
vertex 29 55 5
vertex 5 55 0
vertex 29 55 0
endloop
endfacet
facet normal 0 -1 0
outer loop
vertex 31 55 0
vertex 55 55 5
vertex 31 55 5
endloop
endfacet
facet normal 0 -1 -0
outer loop
vertex 55 55 5
vertex 31 55 0
vertex 55 55 0
endloop
endfacet
facet normal 1 -0 0
outer loop
vertex 4.5 25 5
vertex 4.5 27 0
vertex 4.5 27 5
endloop
endfacet
facet normal 1 0 0
outer loop
vertex 4.5 27 0
vertex 4.5 25 5
vertex 4.5 25 0
endloop
endfacet
facet normal 0 -1 0
outer loop
vertex 4.5 27 0
vertex 5 27 5
vertex 4.5 27 5
endloop
endfacet
facet normal 0 -1 -0
outer loop
vertex 5 27 5
vertex 4.5 27 0
vertex 5 27 0
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 5 25 0
vertex 4.5 25 5
vertex 5 25 5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 4.5 25 5
vertex 5 25 0
vertex 4.5 25 0
endloop
endfacet
facet normal 0 -1 0
outer loop
vertex 29 55.5 0
vertex 31 55.5 5
vertex 29 55.5 5
endloop
endfacet
facet normal 0 -1 -0
outer loop
vertex 31 55.5 5
vertex 29 55.5 0
vertex 31 55.5 0
endloop
endfacet
facet normal 1 -0 0
outer loop
vertex 29 55 5
vertex 29 55.5 0
vertex 29 55.5 5
endloop
endfacet
facet normal 1 0 0
outer loop
vertex 29 55.5 0
vertex 29 55 5
vertex 29 55 0
endloop
endfacet
facet normal -1 0 0
outer loop
vertex 31 55 0
vertex 31 55.5 5
vertex 31 55.5 0
endloop
endfacet
facet normal -1 -0 0
outer loop
vertex 31 55.5 5
vertex 31 55 0
vertex 31 55 5
endloop
endfacet
facet normal -1 0 0
outer loop
vertex 55.5 29 0
vertex 55.5 31 5
vertex 55.5 31 0
endloop
endfacet
facet normal -1 -0 0
outer loop
vertex 55.5 31 5
vertex 55.5 29 0
vertex 55.5 29 5
endloop
endfacet
facet normal 0 -1 0
outer loop
vertex 55 31 0
vertex 55.5 31 5
vertex 55 31 5
endloop
endfacet
facet normal 0 -1 -0
outer loop
vertex 55.5 31 5
vertex 55 31 0
vertex 55.5 31 0
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 55.5 29 0
vertex 55 29 5
vertex 55.5 29 5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 55 29 5
vertex 55.5 29 0
vertex 55 29 0
endloop
endfacet
facet normal 0 1 -0
outer loop
vertex 31 4.5 0
vertex 29 4.5 5
vertex 31 4.5 5
endloop
endfacet
facet normal 0 1 0
outer loop
vertex 29 4.5 5
vertex 31 4.5 0
vertex 29 4.5 0
endloop
endfacet
facet normal -1 0 0
outer loop
vertex 31 4.5 0
vertex 31 5 5
vertex 31 5 0
endloop
endfacet
facet normal -1 -0 0
outer loop
vertex 31 5 5
vertex 31 4.5 0
vertex 31 4.5 5
endloop
endfacet
facet normal 1 -0 0
outer loop
vertex 29 4.5 5
vertex 29 5 0
vertex 29 5 5
endloop
endfacet
facet normal 1 0 0
outer loop
vertex 29 5 0
vertex 29 4.5 5
vertex 29 4.5 0
endloop
endfacet
endsolid OpenSCAD_Model

View File

@@ -9,72 +9,109 @@ import stepper, homing
StepList = (0, 1, 2)
class CartKinematics:
def __init__(self, printer, config):
self.steppers = [stepper.PrinterStepper(
printer, config.getsection('stepper_' + n), n)
def __init__(self, toolhead, printer, config):
self.printer = printer
self.steppers = [stepper.LookupMultiHomingStepper(
printer, config.getsection('stepper_' + n))
for n in ['x', 'y', 'z']]
self.max_z_velocity = config.getfloat('max_z_velocity', 9999999.9)
self.max_z_accel = config.getfloat('max_z_accel', 9999999.9)
max_velocity, max_accel = toolhead.get_max_velocity()
self.max_z_velocity = config.getfloat(
'max_z_velocity', max_velocity, above=0., maxval=max_velocity)
self.max_z_accel = config.getfloat(
'max_z_accel', max_accel, above=0., maxval=max_accel)
self.need_motor_enable = True
self.limits = [(1.0, -1.0)] * 3
def set_max_jerk(self, max_xy_halt_velocity, max_accel):
self.steppers[0].set_max_jerk(max_xy_halt_velocity, max_accel)
self.steppers[1].set_max_jerk(max_xy_halt_velocity, max_accel)
self.steppers[2].set_max_jerk(0., self.max_z_accel)
def build_config(self):
for stepper in self.steppers:
stepper.build_config()
def set_position(self, newpos):
# Setup stepper max halt velocity
max_halt_velocity = toolhead.get_max_axis_halt()
self.steppers[0].set_max_jerk(max_halt_velocity, max_accel)
self.steppers[1].set_max_jerk(max_halt_velocity, max_accel)
self.steppers[2].set_max_jerk(
min(max_halt_velocity, self.max_z_velocity), max_accel)
# Check for dual carriage support
self.dual_carriage_axis = None
self.dual_carriage_steppers = []
if config.has_section('dual_carriage'):
dc_config = config.getsection('dual_carriage')
self.dual_carriage_axis = dc_config.getchoice(
'axis', {'x': 0, 'y': 1})
dc_stepper = stepper.LookupMultiHomingStepper(printer, dc_config)
dc_stepper.set_max_jerk(max_halt_velocity, max_accel)
self.dual_carriage_steppers = [
self.steppers[self.dual_carriage_axis], dc_stepper]
printer.lookup_object('gcode').register_command(
'SET_DUAL_CARRIAGE', self.cmd_SET_DUAL_CARRIAGE,
desc=self.cmd_SET_DUAL_CARRIAGE_help)
def get_steppers(self, flags=""):
if flags == "Z":
return [self.steppers[2]]
return list(self.steppers)
def get_position(self):
return [s.mcu_stepper.get_commanded_position() for s in self.steppers]
def set_position(self, newpos, homing_axes):
for i in StepList:
s = self.steppers[i]
s.mcu_stepper.set_position(int(newpos[i]*s.inv_step_dist + 0.5))
s.set_position(newpos[i])
if i in homing_axes:
self.limits[i] = (s.position_min, s.position_max)
def _home_axis(self, homing_state, axis, stepper):
s = stepper
# Determine moves
if s.homing_positive_dir:
pos = s.position_endstop - 1.5*(
s.position_endstop - s.position_min)
rpos = s.position_endstop - s.homing_retract_dist
r2pos = rpos - s.homing_retract_dist
else:
pos = s.position_endstop + 1.5*(
s.position_max - s.position_endstop)
rpos = s.position_endstop + s.homing_retract_dist
r2pos = rpos + s.homing_retract_dist
# Initial homing
homing_speed = s.homing_speed
if axis == 2:
homing_speed = min(homing_speed, self.max_z_velocity)
homepos = [None, None, None, None]
homepos[axis] = s.position_endstop
coord = [None, None, None, None]
coord[axis] = pos
homing_state.home(coord, homepos, s.get_endstops(), homing_speed)
# Retract
coord[axis] = rpos
homing_state.retract(coord, homing_speed)
# Home again
coord[axis] = r2pos
homing_state.home(coord, homepos, s.get_endstops(),
homing_speed/2.0, second_home=True)
# Set final homed position
coord[axis] = s.position_endstop + s.get_homed_offset()
homing_state.set_homed_position(coord)
def home(self, homing_state):
# Each axis is homed independently and in order
for axis in homing_state.get_axes():
s = self.steppers[axis]
self.limits[axis] = (s.position_min, s.position_max)
# Determine moves
if s.homing_positive_dir:
pos = s.position_endstop - 1.5*(
s.position_endstop - s.position_min)
rpos = s.position_endstop - s.homing_retract_dist
r2pos = rpos - s.homing_retract_dist
if axis == self.dual_carriage_axis:
dc1, dc2 = self.dual_carriage_steppers
altc = self.steppers[axis] == dc2
self._activate_carriage(0)
self._home_axis(homing_state, axis, dc1)
self._activate_carriage(1)
self._home_axis(homing_state, axis, dc2)
self._activate_carriage(altc)
else:
pos = s.position_endstop + 1.5*(
s.position_max - s.position_endstop)
rpos = s.position_endstop + s.homing_retract_dist
r2pos = rpos + s.homing_retract_dist
# Initial homing
homepos = [None, None, None, None]
homepos[axis] = s.position_endstop
coord = [None, None, None, None]
coord[axis] = pos
homing_state.home(list(coord), homepos, [s], s.homing_speed)
# Retract
coord[axis] = rpos
homing_state.retract(list(coord), s.homing_speed)
# Home again
coord[axis] = r2pos
homing_state.home(
list(coord), homepos, [s], s.homing_speed/2.0, second_home=True)
# Set final homed position
coord[axis] = s.position_endstop + s.get_homed_offset()*s.step_dist
homing_state.set_homed_position(coord)
def motor_off(self, move_time):
self._home_axis(homing_state, axis, self.steppers[axis])
def motor_off(self, print_time):
self.limits = [(1.0, -1.0)] * 3
for stepper in self.steppers:
stepper.motor_enable(move_time, 0)
stepper.motor_enable(print_time, 0)
for stepper in self.dual_carriage_steppers:
stepper.motor_enable(print_time, 0)
self.need_motor_enable = True
def _check_motor_enable(self, move_time, move):
def _check_motor_enable(self, print_time, move):
need_motor_enable = False
for i in StepList:
if move.axes_d[i]:
self.steppers[i].motor_enable(move_time, 1)
self.steppers[i].motor_enable(print_time, 1)
need_motor_enable |= self.steppers[i].need_motor_enable
self.need_motor_enable = need_motor_enable
def query_endstops(self, print_time):
endstops = [(s, s.query_endstop(print_time)) for s in self.steppers]
return [(s.name, es.query_endstop_wait()) for s, es in endstops]
def _check_endstops(self, move):
end_pos = move.end_pos
for i in StepList:
@@ -99,49 +136,55 @@ class CartKinematics:
z_ratio = move.move_d / abs(move.axes_d[2])
move.limit_speed(
self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio)
def move(self, move_time, move):
def move(self, print_time, move):
if self.need_motor_enable:
self._check_motor_enable(move_time, move)
inv_accel = 1. / move.accel
inv_cruise_v = 1. / move.cruise_v
self._check_motor_enable(print_time, move)
for i in StepList:
if not move.axes_d[i]:
axis_d = move.axes_d[i]
if not axis_d:
continue
mcu_stepper = self.steppers[i].mcu_stepper
mcu_time = mcu_stepper.print_to_mcu_time(move_time)
step_pos = mcu_stepper.commanded_position
inv_step_dist = self.steppers[i].inv_step_dist
step_offset = step_pos - move.start_pos[i] * inv_step_dist
steps = move.axes_d[i] * inv_step_dist
move_step_d = move.move_d / abs(steps)
step_const = self.steppers[i].step_const
move_time = print_time
start_pos = move.start_pos[i]
axis_r = abs(axis_d) / move.move_d
accel = move.accel * axis_r
cruise_v = move.cruise_v * axis_r
# Acceleration steps
accel_multiplier = 2.0 * move_step_d * inv_accel
if move.accel_r:
#t = sqrt(2*pos/accel + (start_v/accel)**2) - start_v/accel
accel_time_offset = move.start_v * inv_accel
accel_sqrt_offset = accel_time_offset**2
accel_steps = move.accel_r * steps
count = mcu_stepper.step_sqrt(
mcu_time - accel_time_offset, accel_steps, step_offset
, accel_sqrt_offset, accel_multiplier)
step_offset += count - accel_steps
mcu_time += move.accel_t
accel_d = move.accel_r * axis_d
step_const(move_time, start_pos, accel_d,
move.start_v * axis_r, accel)
start_pos += accel_d
move_time += move.accel_t
# Cruising steps
if move.cruise_r:
#t = pos/cruise_v
cruise_multiplier = move_step_d * inv_cruise_v
cruise_steps = move.cruise_r * steps
count = mcu_stepper.step_factor(
mcu_time, cruise_steps, step_offset, cruise_multiplier)
step_offset += count - cruise_steps
mcu_time += move.cruise_t
cruise_d = move.cruise_r * axis_d
step_const(move_time, start_pos, cruise_d, cruise_v, 0.)
start_pos += cruise_d
move_time += move.cruise_t
# Deceleration steps
if move.decel_r:
#t = cruise_v/accel - sqrt((cruise_v/accel)**2 - 2*pos/accel)
decel_time_offset = move.cruise_v * inv_accel
decel_sqrt_offset = decel_time_offset**2
decel_steps = move.decel_r * steps
count = mcu_stepper.step_sqrt(
mcu_time + decel_time_offset, decel_steps, step_offset
, decel_sqrt_offset, -accel_multiplier)
decel_d = move.decel_r * axis_d
step_const(move_time, start_pos, decel_d, cruise_v, -accel)
# Dual carriage support
def _activate_carriage(self, carriage):
toolhead = self.printer.lookup_object('toolhead')
toolhead.get_last_move_time()
dc_stepper = self.dual_carriage_steppers[carriage]
dc_axis = self.dual_carriage_axis
self.steppers[dc_axis] = dc_stepper
extruder_pos = toolhead.get_position()[3]
toolhead.set_position(self.get_position() + [extruder_pos])
if self.limits[dc_axis][0] <= self.limits[dc_axis][1]:
self.limits[dc_axis] = (
dc_stepper.position_min, dc_stepper.position_max)
self.need_motor_enable = True
cmd_SET_DUAL_CARRIAGE_help = "Set which carriage is active"
def cmd_SET_DUAL_CARRIAGE(self, params):
gcode = self.printer.lookup_object('gcode')
carriage = gcode.get_int('CARRIAGE', params)
if carriage not in (0, 1):
raise gcode.error("Invalid carriage")
self._activate_carriage(carriage)
gcode.reset_last_position()

View File

@@ -1,12 +1,17 @@
# Wrapper around C helper code
#
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import os, logging
import cffi
COMPILE_CMD = "gcc -Wall -g -O -shared -fPIC -o %s %s"
######################################################################
# c_helper.so compiling
######################################################################
COMPILE_CMD = "gcc -Wall -g -O2 -shared -fPIC -o %s %s"
SOURCE_FILES = ['stepcompress.c', 'serialqueue.c', 'pyhelper.c']
DEST_LIB = "c_helper.so"
OTHER_FILES = ['list.h', 'serialqueue.h', 'pyhelper.h']
@@ -16,31 +21,24 @@ defs_stepcompress = """
, uint32_t queue_step_msgid, uint32_t set_next_step_dir_msgid
, uint32_t invert_sdir, uint32_t oid);
void stepcompress_free(struct stepcompress *sc);
void stepcompress_push(struct stepcompress *sc, double step_clock
int stepcompress_reset(struct stepcompress *sc, uint64_t last_step_clock);
int stepcompress_set_homing(struct stepcompress *sc, uint64_t homing_clock);
int stepcompress_queue_msg(struct stepcompress *sc, uint32_t *data, int len);
int32_t stepcompress_push(struct stepcompress *sc, double step_clock
, int32_t sdir);
int32_t stepcompress_push_factor(struct stepcompress *sc
, double steps, double step_offset
, double clock_offset, double factor);
int32_t stepcompress_push_sqrt(struct stepcompress *sc
, double steps, double step_offset
, double clock_offset, double sqrt_offset, double factor);
int32_t stepcompress_push_delta_const(struct stepcompress *sc
, double clock_offset, double dist, double start_pos
, double inv_velocity, double step_dist, double height
, double closestxy_d, double closest_height2, double movez_r);
int32_t stepcompress_push_delta_accel(struct stepcompress *sc
, double clock_offset, double dist, double start_pos
, double accel_multiplier, double step_dist, double height
, double closestxy_d, double closest_height2, double movez_r);
void stepcompress_reset(struct stepcompress *sc, uint64_t last_step_clock);
void stepcompress_queue_msg(struct stepcompress *sc
, uint32_t *data, int len);
uint32_t stepcompress_get_errors(struct stepcompress *sc);
int32_t stepcompress_push_const(struct stepcompress *sc, double clock_offset
, double step_offset, double steps, double start_sv, double accel);
int32_t stepcompress_push_delta(struct stepcompress *sc
, double clock_offset, double move_sd, double start_sv, double accel
, double height, double startxy_sd, double arm_d, double movez_r);
struct steppersync *steppersync_alloc(struct serialqueue *sq
, struct stepcompress **sc_list, int sc_num, int move_num);
void steppersync_free(struct steppersync *ss);
void steppersync_flush(struct steppersync *ss, uint64_t move_clock);
void steppersync_set_time(struct steppersync *ss
, double time_offset, double mcu_freq);
int steppersync_flush(struct steppersync *ss, uint64_t move_clock);
"""
defs_serialqueue = """
@@ -63,9 +61,8 @@ defs_serialqueue = """
, uint64_t min_clock, uint64_t req_clock);
void serialqueue_pull(struct serialqueue *sq, struct pull_queue_message *pqm);
void serialqueue_set_baud_adjust(struct serialqueue *sq, double baud_adjust);
void serialqueue_set_clock_est(struct serialqueue *sq, double est_clock
, double last_ack_time, uint64_t last_ack_clock);
void serialqueue_flush_ready(struct serialqueue *sq);
void serialqueue_set_clock_est(struct serialqueue *sq, double est_freq
, double last_clock_time, uint64_t last_clock);
void serialqueue_get_stats(struct serialqueue *sq, char *buf, int len);
int serialqueue_extract_old(struct serialqueue *sq, int sentq
, struct pull_queue_message *q, int max);
@@ -73,6 +70,7 @@ defs_serialqueue = """
defs_pyhelper = """
void set_python_logging_callback(void (*func)(const char *));
double get_monotonic(void);
"""
# Return the list of file modification times
@@ -88,14 +86,14 @@ def get_mtimes(srcdir, filelist):
return out
# Check if the code needs to be compiled
def check_build_code(srcdir):
src_times = get_mtimes(srcdir, SOURCE_FILES + OTHER_FILES)
obj_times = get_mtimes(srcdir, [DEST_LIB])
def check_build_code(srcdir, target, sources, cmd, other_files=[]):
src_times = get_mtimes(srcdir, sources + other_files)
obj_times = get_mtimes(srcdir, [target])
if not obj_times or max(src_times) > min(obj_times):
logging.info("Building C code module")
srcfiles = [os.path.join(srcdir, fname) for fname in SOURCE_FILES]
destlib = os.path.join(srcdir, DEST_LIB)
os.system(COMPILE_CMD % (destlib, ' '.join(srcfiles)))
logging.info("Building C code module %s", target)
srcfiles = [os.path.join(srcdir, fname) for fname in sources]
destlib = os.path.join(srcdir, target)
os.system(cmd % (destlib, ' '.join(srcfiles)))
FFI_main = None
FFI_lib = None
@@ -106,7 +104,8 @@ def get_ffi():
global FFI_main, FFI_lib, pyhelper_logging_callback
if FFI_lib is None:
srcdir = os.path.dirname(os.path.realpath(__file__))
check_build_code(srcdir)
check_build_code(srcdir, DEST_LIB, SOURCE_FILES, COMPILE_CMD
, OTHER_FILES)
FFI_main = cffi.FFI()
FFI_main.cdef(defs_stepcompress)
FFI_main.cdef(defs_serialqueue)
@@ -119,3 +118,20 @@ def get_ffi():
"void(const char *)", logging_callback)
FFI_lib.set_python_logging_callback(pyhelper_logging_callback)
return FFI_main, FFI_lib
######################################################################
# hub-ctrl hub power controller
######################################################################
HC_COMPILE_CMD = "gcc -Wall -g -O2 -o %s %s -lusb"
HC_SOURCE_FILES = ['hub-ctrl.c']
HC_SOURCE_DIR = '../lib/hub-ctrl'
HC_TARGET = "hub-ctrl"
HC_CMD = "sudo %s/hub-ctrl -h 0 -P 2 -p %d"
def run_hub_ctrl(enable_power):
srcdir = os.path.dirname(os.path.realpath(__file__))
hubdir = os.path.join(srcdir, HC_SOURCE_DIR)
check_build_code(hubdir, HC_TARGET, HC_SOURCE_FILES, HC_COMPILE_CMD)
os.system(HC_CMD % (hubdir, enable_power))

219
klippy/clocksync.py Normal file
View File

@@ -0,0 +1,219 @@
# Micro-controller clock synchronization
#
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging, threading, math
COMM_TIMEOUT = 3.5
RTT_AGE = .000010 / (60. * 60.)
DECAY = 1. / 30.
TRANSMIT_EXTRA = .001
class ClockSync:
def __init__(self, reactor):
self.reactor = reactor
self.serial = None
self.status_timer = self.reactor.register_timer(self._status_event)
self.status_cmd = None
self.mcu_freq = 1.
self.last_clock = 0
self.clock_est = (0., 0., 0.)
# Minimum round-trip-time tracking
self.min_half_rtt = 999999999.9
self.min_rtt_time = 0.
# Linear regression of mcu clock and system sent_time
self.time_avg = self.time_variance = 0.
self.clock_avg = self.clock_covariance = 0.
self.prediction_variance = 0.
self.last_prediction_time = 0.
def connect(self, serial):
self.serial = serial
self.mcu_freq = serial.msgparser.get_constant_float('CLOCK_FREQ')
# Load initial clock and frequency
get_uptime_cmd = serial.lookup_command('get_uptime')
params = get_uptime_cmd.send_with_response(response='uptime')
self.last_clock = (params['high'] << 32) | params['clock']
self.clock_avg = self.last_clock
self.time_avg = params['#sent_time']
self.clock_est = (self.time_avg, self.clock_avg, self.mcu_freq)
self.prediction_variance = (.001 * self.mcu_freq)**2
# Enable periodic get_status timer
self.status_cmd = serial.lookup_command('get_status')
for i in range(8):
params = self.status_cmd.send_with_response(response='status')
self._handle_status(params)
self.reactor.pause(0.100)
serial.register_callback(self._handle_status, 'status')
self.reactor.update_timer(self.status_timer, self.reactor.NOW)
def connect_file(self, serial, pace=False):
self.serial = serial
self.mcu_freq = serial.msgparser.get_constant_float('CLOCK_FREQ')
self.clock_est = (0., 0., self.mcu_freq)
freq = 1000000000000.
if pace:
freq = self.mcu_freq
serial.set_clock_est(freq, self.reactor.monotonic(), 0)
# MCU clock querying (status callback invoked from background thread)
def _status_event(self, eventtime):
self.status_cmd.send()
return eventtime + 1.0
def _handle_status(self, params):
# Extend clock to 64bit
last_clock = self.last_clock
clock = (last_clock & ~0xffffffff) | params['clock']
if clock < last_clock:
clock += 0x100000000
self.last_clock = clock
# Check if this is the best round-trip-time seen so far
sent_time = params['#sent_time']
if not sent_time:
return
receive_time = params['#receive_time']
half_rtt = .5 * (receive_time - sent_time)
aged_rtt = (sent_time - self.min_rtt_time) * RTT_AGE
if half_rtt < self.min_half_rtt + aged_rtt:
self.min_half_rtt = half_rtt
self.min_rtt_time = sent_time
logging.debug("new minimum rtt %.3f: hrtt=%.6f freq=%d",
sent_time, half_rtt, self.clock_est[2])
# Filter out samples that are extreme outliers
exp_clock = ((sent_time - self.time_avg) * self.clock_est[2]
+ self.clock_avg)
clock_diff2 = (clock - exp_clock)**2
if (clock_diff2 > 25. * self.prediction_variance
and clock_diff2 > (.000500 * self.mcu_freq)**2):
if clock > exp_clock and sent_time < self.last_prediction_time + 10.:
logging.debug("Ignoring clock sample %.3f:"
" freq=%d diff=%d stddev=%.3f",
sent_time, self.clock_est[2], clock - exp_clock,
math.sqrt(self.prediction_variance))
return
logging.info("Resetting prediction variance %.3f:"
" freq=%d diff=%d stddev=%.3f",
sent_time, self.clock_est[2], clock - exp_clock,
math.sqrt(self.prediction_variance))
self.prediction_variance = (.001 * self.mcu_freq)**2
else:
self.last_prediction_time = sent_time
self.prediction_variance = (
(1. - DECAY) * (self.prediction_variance + clock_diff2 * DECAY))
# Add clock and sent_time to linear regression
diff_sent_time = sent_time - self.time_avg
self.time_avg += DECAY * diff_sent_time
self.time_variance = (1. - DECAY) * (
self.time_variance + diff_sent_time**2 * DECAY)
diff_clock = clock - self.clock_avg
self.clock_avg += DECAY * diff_clock
self.clock_covariance = (1. - DECAY) * (
self.clock_covariance + diff_sent_time * diff_clock * DECAY)
# Update prediction from linear regression
new_freq = self.clock_covariance / self.time_variance
pred_stddev = math.sqrt(self.prediction_variance)
self.serial.set_clock_est(new_freq, self.time_avg + TRANSMIT_EXTRA,
int(self.clock_avg - 3. * pred_stddev))
self.clock_est = (self.time_avg + self.min_half_rtt,
self.clock_avg, new_freq)
#logging.debug("regr %.3f: freq=%.3f d=%d(%.3f)",
# sent_time, new_freq, clock - exp_clock, pred_stddev)
# clock frequency conversions
def print_time_to_clock(self, print_time):
return int(print_time * self.mcu_freq)
def clock_to_print_time(self, clock):
return clock / self.mcu_freq
def get_adjusted_freq(self):
return self.mcu_freq
# system time conversions
def get_clock(self, eventtime):
sample_time, clock, freq = self.clock_est
return int(clock + (eventtime - sample_time) * freq)
def estimated_print_time(self, eventtime):
return self.clock_to_print_time(self.get_clock(eventtime))
# misc commands
def clock32_to_clock64(self, clock32):
last_clock = self.last_clock
clock_diff = (last_clock - clock32) & 0xffffffff
if clock_diff & 0x80000000:
return last_clock + 0x100000000 - clock_diff
return last_clock - clock_diff
def is_active(self, eventtime):
print_time = self.estimated_print_time(eventtime)
last_clock_print_time = self.clock_to_print_time(self.last_clock)
return print_time < last_clock_print_time + COMM_TIMEOUT
def dump_debug(self):
sample_time, clock, freq = self.clock_est
return ("clocksync state: mcu_freq=%d last_clock=%d"
" clock_est=(%.3f %d %.3f) min_half_rtt=%.6f min_rtt_time=%.3f"
" time_avg=%.3f(%.3f) clock_avg=%.3f(%.3f)"
" pred_variance=%.3f" % (
self.mcu_freq, self.last_clock, sample_time, clock, freq,
self.min_half_rtt, self.min_rtt_time,
self.time_avg, self.time_variance,
self.clock_avg, self.clock_covariance,
self.prediction_variance))
def stats(self, eventtime):
sample_time, clock, freq = self.clock_est
return "freq=%d" % (freq,)
def calibrate_clock(self, print_time, eventtime):
return (0., self.mcu_freq)
# Clock syncing code for secondary MCUs (whose clocks are sync'ed to a
# primary MCU)
class SecondarySync(ClockSync):
def __init__(self, reactor, main_sync):
ClockSync.__init__(self, reactor)
self.main_sync = main_sync
self.clock_adj = (0., 1.)
self.last_sync_time = 0.
def connect(self, serial):
ClockSync.connect(self, serial)
self.clock_adj = (0., self.mcu_freq)
curtime = self.reactor.monotonic()
main_print_time = self.main_sync.estimated_print_time(curtime)
local_print_time = self.estimated_print_time(curtime)
self.clock_adj = (main_print_time - local_print_time, self.mcu_freq)
self.calibrate_clock(0., curtime)
def connect_file(self, serial, pace=False):
ClockSync.connect_file(self, serial, pace)
self.clock_adj = (0., self.mcu_freq)
# clock frequency conversions
def print_time_to_clock(self, print_time):
adjusted_offset, adjusted_freq = self.clock_adj
return int((print_time - adjusted_offset) * adjusted_freq)
def clock_to_print_time(self, clock):
adjusted_offset, adjusted_freq = self.clock_adj
return clock / adjusted_freq + adjusted_offset
def get_adjusted_freq(self):
adjusted_offset, adjusted_freq = self.clock_adj
return adjusted_freq
# misc commands
def dump_debug(self):
adjusted_offset, adjusted_freq = self.clock_adj
return "%s clock_adj=(%.3f %.3f)" % (
ClockSync.dump_debug(self), adjusted_offset, adjusted_freq)
def stats(self, eventtime):
adjusted_offset, adjusted_freq = self.clock_adj
return "%s adj=%d" % (ClockSync.stats(self, eventtime), adjusted_freq)
def calibrate_clock(self, print_time, eventtime):
# Calculate: est_print_time = main_sync.estimatated_print_time()
ser_time, ser_clock, ser_freq = self.main_sync.clock_est
main_mcu_freq = self.main_sync.mcu_freq
est_main_clock = (eventtime - ser_time) * ser_freq + ser_clock
est_print_time = est_main_clock / main_mcu_freq
# Determine sync1_print_time and sync2_print_time
sync1_print_time = max(print_time, est_print_time)
sync2_print_time = max(sync1_print_time + 4., self.last_sync_time,
print_time + 2.5 * (print_time - est_print_time))
# Calc sync2_sys_time (inverse of main_sync.estimatated_print_time)
sync2_main_clock = sync2_print_time * main_mcu_freq
sync2_sys_time = ser_time + (sync2_main_clock - ser_clock) / ser_freq
# Adjust freq so estimated print_time will match at sync2_print_time
sync1_clock = self.print_time_to_clock(sync1_print_time)
sync2_clock = self.get_clock(sync2_sys_time)
adjusted_freq = ((sync2_clock - sync1_clock)
/ (sync2_print_time - sync1_print_time))
adjusted_offset = sync1_print_time - sync1_clock / adjusted_freq
# Apply new values
self.clock_adj = (adjusted_offset, adjusted_freq)
self.last_sync_time = sync2_print_time
return self.clock_adj

View File

@@ -1,12 +1,31 @@
#!/usr/bin/env python
#!/usr/bin/env python2
# Script to implement a test console with firmware over serial port
#
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys, optparse, os, re, logging
import reactor, serialhdl, pins, util, msgproto, clocksync
import reactor, serialhdl, pins, util, msgproto
help_txt = """
This is a debugging console for the Klipper micro-controller.
In addition to mcu commands, the following artificial commands are
available:
PINS : Load pin name aliases (eg, "PINS arduino")
DELAY : Send a command at a clock time (eg, "DELAY 9999 get_uptime")
FLOOD : Send a command many times (eg, "FLOOD 22 .01 get_uptime")
SUPPRESS : Suppress a response message (eg, "SUPPRESS stats")
SET : Create a local variable (eg, "SET myvar 123.4")
STATS : Report serial statistics
LIST : List available mcu commands, local commands, and local variables
HELP : Show this text
All commands also support evaluation by enclosing an expression in { }.
For example, "reset_step_clock oid=4 clock={clock + freq}". In addition
to user defined variables (via the SET command) the following builtin
variables may be used in expressions:
clock : The current mcu clock time (as estimated by the host)
freq : The mcu clock frequency
"""
re_eval = re.compile(r'\{(?P<eval>[^}]*)\}')
@@ -14,71 +33,137 @@ class KeyboardReader:
def __init__(self, ser, reactor):
self.ser = ser
self.reactor = reactor
self.clocksync = clocksync.ClockSync(self.reactor)
self.fd = sys.stdin.fileno()
util.set_nonblock(self.fd)
self.mcu_freq = 0
self.pins = None
self.data = ""
reactor.register_fd(self.fd, self.process_kbd)
self.connect_timer = reactor.register_timer(self.connect, reactor.NOW)
self.local_commands = { "PINS": self.set_pin_map, "SET": self.set_var }
self.local_commands = {
"PINS": self.command_PINS, "SET": self.command_SET,
"DELAY": self.command_DELAY, "FLOOD": self.command_FLOOD,
"SUPPRESS": self.command_SUPPRESS, "STATS": self.command_STATS,
"LIST": self.command_LIST, "HELP": self.command_HELP,
}
self.eval_globals = {}
def connect(self, eventtime):
self.output(help_txt)
self.output("="*20 + " attempting to connect " + "="*20)
self.ser.connect()
self.clocksync.connect(self.ser)
self.ser.handle_default = self.handle_default
self.mcu_freq = self.ser.msgparser.get_constant_float('CLOCK_FREQ')
mcu_type = self.ser.msgparser.get_constant('MCU')
self.pins = pins.PinResolver(mcu_type, validate_aliases=False)
self.reactor.unregister_timer(self.connect_timer)
self.output("="*20 + " connected " + "="*20)
return self.reactor.NEVER
def output(self, msg):
sys.stdout.write("%s\n" % (msg,))
sys.stdout.flush()
def handle_default(self, params):
self.output(self.ser.msgparser.format_params(params))
def handle_suppress(self, params):
pass
def update_evals(self, eventtime):
f = int(self.ser.msgparser.config.get('CLOCK_FREQ', 1))
c = self.ser.get_clock(eventtime)
self.eval_globals['freq'] = f
self.eval_globals['clock'] = int(c)
def set_pin_map(self, parts):
mcu = self.ser.msgparser.config['MCU']
self.pins = pins.map_pins(parts[1], mcu)
def set_var(self, parts):
self.eval_globals['freq'] = self.mcu_freq
self.eval_globals['clock'] = self.clocksync.get_clock(eventtime)
def command_PINS(self, parts):
self.pins.update_aliases(parts[1])
def command_SET(self, parts):
val = parts[2]
try:
val = int(val)
val = float(val)
except ValueError:
try:
val = float(val)
except ValueError:
pass
pass
self.eval_globals[parts[1]] = val
def lookup_pin(self, value):
if self.pins is None:
self.pins = pins.mcu_to_pins(self.ser.msgparser.config['MCU'])
return self.pins[value]
def command_DELAY(self, parts):
try:
val = int(parts[1])
except ValueError as e:
self.output("Error: %s" % (str(e),))
return
try:
self.ser.send(' '.join(parts[2:]), minclock=val)
except msgproto.error as e:
self.output("Error: %s" % (str(e),))
return
def command_FLOOD(self, parts):
try:
count = int(parts[1])
delay = float(parts[2])
except ValueError as e:
self.output("Error: %s" % (str(e),))
return
msg = ' '.join(parts[3:])
delay_clock = int(delay * self.mcu_freq)
msg_clock = int(self.clocksync.get_clock(self.reactor.monotonic())
+ self.mcu_freq * .200)
try:
for i in range(count):
next_clock = msg_clock + delay_clock
self.ser.send(msg, minclock=msg_clock, reqclock=next_clock)
msg_clock = next_clock
except msgproto.error as e:
self.output("Error: %s" % (str(e),))
return
def command_SUPPRESS(self, parts):
oid = None
try:
name = parts[1]
if len(parts) > 2:
oid = int(parts[2])
except ValueError as e:
self.output("Error: %s" % (str(e),))
return
self.ser.register_callback(self.handle_suppress, name, oid)
def command_STATS(self, parts):
curtime = self.reactor.monotonic()
self.output(' '.join([self.ser.stats(curtime),
self.clocksync.stats(curtime)]))
def command_LIST(self, parts):
self.update_evals(self.reactor.monotonic())
mp = self.ser.msgparser
out = "Available mcu commands:"
out += "\n ".join([""] + sorted([
mp.messages_by_id[i].msgformat for i in mp.command_ids]))
out += "\nAvailable artificial commands:"
out += "\n ".join([""] + [n for n in sorted(self.local_commands)])
out += "\nAvailable local variables:"
out += "\n ".join([""] + ["%s: %s" % (k, v)
for k, v in sorted(self.eval_globals.items())])
self.output(out)
def command_HELP(self, parts):
self.output(help_txt)
def translate(self, line, eventtime):
evalparts = re_eval.split(line)
if len(evalparts) > 1:
self.update_evals(eventtime)
try:
for i in range(1, len(evalparts), 2):
evalparts[i] = str(eval(evalparts[i], self.eval_globals))
e = eval(evalparts[i], dict(self.eval_globals))
if type(e) == type(0.):
e = int(e)
evalparts[i] = str(e)
except:
print "Unable to evaluate: ", line
self.output("Unable to evaluate: %s" % (line,))
return None
line = ''.join(evalparts)
print "Eval:", line
if self.pins is None and self.ser.msgparser.config:
self.pins = pins.mcu_to_pins(self.ser.msgparser.config['MCU'])
self.output("Eval: %s" % (line,))
if self.pins is not None:
try:
line = pins.update_command(line, self.pins).strip()
line = self.pins.update_command(line).strip()
except:
print "Unable to map pin: ", line
self.output("Unable to map pin: %s" % (line,))
return None
if line:
parts = line.split()
if parts[0] in self.local_commands:
self.local_commands[parts[0]](parts)
return None
try:
msg = self.ser.msgparser.create_command(line)
except msgproto.error, e:
print "Error:", e
return None
return msg
return line
def process_kbd(self, eventtime):
self.data += os.read(self.fd, 4096)
@@ -93,7 +178,11 @@ class KeyboardReader:
msg = self.translate(line.strip(), eventtime)
if msg is None:
continue
self.ser.send(msg)
try:
self.ser.send(msg)
except msgproto.error as e:
self.output("Error: %s" % (str(e),))
return None
self.data = kbdlines[-1]
def main():

161
klippy/corexy.py Normal file
View File

@@ -0,0 +1,161 @@
# Code for handling the kinematics of corexy robots
#
# Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging, math
import stepper, homing
StepList = (0, 1, 2)
class CoreXYKinematics:
def __init__(self, toolhead, printer, config):
self.steppers = [
stepper.PrinterHomingStepper(
printer, config.getsection('stepper_x')),
stepper.PrinterHomingStepper(
printer, config.getsection('stepper_y')),
stepper.LookupMultiHomingStepper(
printer, config.getsection('stepper_z'))]
self.steppers[0].mcu_endstop.add_stepper(self.steppers[1].mcu_stepper)
self.steppers[1].mcu_endstop.add_stepper(self.steppers[0].mcu_stepper)
max_velocity, max_accel = toolhead.get_max_velocity()
self.max_z_velocity = config.getfloat(
'max_z_velocity', max_velocity, above=0., maxval=max_velocity)
self.max_z_accel = config.getfloat(
'max_z_accel', max_accel, above=0., maxval=max_accel)
self.need_motor_enable = True
self.limits = [(1.0, -1.0)] * 3
# Setup stepper max halt velocity
max_halt_velocity = toolhead.get_max_axis_halt()
max_xy_halt_velocity = max_halt_velocity * math.sqrt(2.)
self.steppers[0].set_max_jerk(max_xy_halt_velocity, max_accel)
self.steppers[1].set_max_jerk(max_xy_halt_velocity, max_accel)
self.steppers[2].set_max_jerk(
min(max_halt_velocity, self.max_z_velocity), self.max_z_accel)
def get_steppers(self, flags=""):
if flags == "Z":
return [self.steppers[2]]
return list(self.steppers)
def get_position(self):
pos = [s.mcu_stepper.get_commanded_position() for s in self.steppers]
return [0.5 * (pos[0] + pos[1]), 0.5 * (pos[0] - pos[1]), pos[2]]
def set_position(self, newpos, homing_axes):
pos = (newpos[0] + newpos[1], newpos[0] - newpos[1], newpos[2])
for i in StepList:
s = self.steppers[i]
s.set_position(pos[i])
if i in homing_axes:
self.limits[i] = (s.position_min, s.position_max)
def home(self, homing_state):
# Each axis is homed independently and in order
for axis in homing_state.get_axes():
s = self.steppers[axis]
# Determine moves
if s.homing_positive_dir:
pos = s.position_endstop - 1.5*(
s.position_endstop - s.position_min)
rpos = s.position_endstop - s.homing_retract_dist
r2pos = rpos - s.homing_retract_dist
else:
pos = s.position_endstop + 1.5*(
s.position_max - s.position_endstop)
rpos = s.position_endstop + s.homing_retract_dist
r2pos = rpos + s.homing_retract_dist
# Initial homing
homing_speed = s.homing_speed
if axis == 2:
homing_speed = min(homing_speed, self.max_z_velocity)
homepos = [None, None, None, None]
homepos[axis] = s.position_endstop
coord = [None, None, None, None]
coord[axis] = pos
homing_state.home(coord, homepos, s.get_endstops(), homing_speed)
# Retract
coord[axis] = rpos
homing_state.retract(coord, homing_speed)
# Home again
coord[axis] = r2pos
homing_state.home(coord, homepos, s.get_endstops(),
homing_speed/2.0, second_home=True)
if axis == 2:
# Support endstop phase detection on Z axis
coord[axis] = s.position_endstop + s.get_homed_offset()
homing_state.set_homed_position(coord)
def motor_off(self, print_time):
self.limits = [(1.0, -1.0)] * 3
for stepper in self.steppers:
stepper.motor_enable(print_time, 0)
self.need_motor_enable = True
def _check_motor_enable(self, print_time, move):
if move.axes_d[0] or move.axes_d[1]:
self.steppers[0].motor_enable(print_time, 1)
self.steppers[1].motor_enable(print_time, 1)
if move.axes_d[2]:
self.steppers[2].motor_enable(print_time, 1)
need_motor_enable = False
for i in StepList:
need_motor_enable |= self.steppers[i].need_motor_enable
self.need_motor_enable = need_motor_enable
def _check_endstops(self, move):
end_pos = move.end_pos
for i in StepList:
if (move.axes_d[i]
and (end_pos[i] < self.limits[i][0]
or end_pos[i] > self.limits[i][1])):
if self.limits[i][0] > self.limits[i][1]:
raise homing.EndstopMoveError(
end_pos, "Must home axis first")
raise homing.EndstopMoveError(end_pos)
def check_move(self, move):
limits = self.limits
xpos, ypos = move.end_pos[:2]
if (xpos < limits[0][0] or xpos > limits[0][1]
or ypos < limits[1][0] or ypos > limits[1][1]):
self._check_endstops(move)
if not move.axes_d[2]:
# Normal XY move - use defaults
return
# Move with Z - update velocity and accel for slower Z axis
self._check_endstops(move)
z_ratio = move.move_d / abs(move.axes_d[2])
move.limit_speed(
self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio)
def move(self, print_time, move):
if self.need_motor_enable:
self._check_motor_enable(print_time, move)
sxp = move.start_pos[0]
syp = move.start_pos[1]
move_start_pos = (sxp + syp, sxp - syp, move.start_pos[2])
exp = move.end_pos[0]
eyp = move.end_pos[1]
axes_d = ((exp + eyp) - move_start_pos[0],
(exp - eyp) - move_start_pos[1], move.axes_d[2])
for i in StepList:
axis_d = axes_d[i]
if not axis_d:
continue
step_const = self.steppers[i].step_const
move_time = print_time
start_pos = move_start_pos[i]
axis_r = abs(axis_d) / move.move_d
accel = move.accel * axis_r
cruise_v = move.cruise_v * axis_r
# Acceleration steps
if move.accel_r:
accel_d = move.accel_r * axis_d
step_const(move_time, start_pos, accel_d,
move.start_v * axis_r, accel)
start_pos += accel_d
move_time += move.accel_t
# Cruising steps
if move.cruise_r:
cruise_d = move.cruise_r * axis_d
step_const(move_time, start_pos, cruise_d, cruise_v, 0.)
start_pos += cruise_d
move_time += move.cruise_t
# Deceleration steps
if move.decel_r:
decel_d = move.decel_r * axis_d
step_const(move_time, start_pos, decel_d, cruise_v, -accel)

View File

@@ -1,6 +1,6 @@
# Code for handling the kinematics of linear delta robots
#
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import math, logging
@@ -8,234 +8,218 @@ import stepper, homing
StepList = (0, 1, 2)
# Slow moves once the ratio of tower to XY movement exceeds SLOW_RATIO
SLOW_RATIO = 3.
class DeltaKinematics:
def __init__(self, printer, config):
self.steppers = [stepper.PrinterStepper(
printer, config.getsection('stepper_' + n), n)
for n in ['a', 'b', 'c']]
self.need_motor_enable = True
self.max_z_velocity = config.getfloat('max_z_velocity', 9999999.9)
radius = config.getfloat('delta_radius')
arm_length = config.getfloat('delta_arm_length')
self.arm_length2 = arm_length**2
self.max_xy2 = min(radius, arm_length - radius)**2
def __init__(self, toolhead, printer, config):
stepper_configs = [config.getsection('stepper_' + n)
for n in ['a', 'b', 'c']]
stepper_a = stepper.PrinterHomingStepper(printer, stepper_configs[0])
stepper_b = stepper.PrinterHomingStepper(
printer, stepper_configs[1],
default_position=stepper_a.position_endstop)
stepper_c = stepper.PrinterHomingStepper(
printer, stepper_configs[2],
default_position=stepper_a.position_endstop)
self.steppers = [stepper_a, stepper_b, stepper_c]
self.need_motor_enable = self.need_home = True
self.radius = radius = config.getfloat('delta_radius', above=0.)
arm_length_a = stepper_configs[0].getfloat('arm_length', above=radius)
self.arm_lengths = arm_lengths = [
sconfig.getfloat('arm_length', arm_length_a, above=radius)
for sconfig in stepper_configs]
self.arm2 = [arm**2 for arm in arm_lengths]
self.endstops = [s.position_endstop + math.sqrt(arm2 - radius**2)
for s, arm2 in zip(self.steppers, self.arm2)]
self.limit_xy2 = -1.
tower_height_at_zeros = math.sqrt(self.arm_length2 - radius**2)
self.max_z = self.steppers[0].position_max
self.limit_z = self.max_z - (arm_length - tower_height_at_zeros)
sin = lambda angle: math.sin(math.radians(angle))
cos = lambda angle: math.cos(math.radians(angle))
self.towers = [
(cos(210.)*radius, sin(210.)*radius),
(cos(330.)*radius, sin(330.)*radius),
(cos(90.)*radius, sin(90.)*radius)]
def set_max_jerk(self, max_xy_halt_velocity, max_accel):
# XXX - this sets conservative values
for stepper in self.steppers:
stepper.set_max_jerk(max_xy_halt_velocity, max_accel)
def build_config(self):
for stepper in self.steppers:
stepper.build_config()
self.set_position([0., 0., 0.])
self.max_z = min([s.position_endstop for s in self.steppers])
self.min_z = config.getfloat('minimum_z_position', 0, maxval=self.max_z)
self.limit_z = min([ep - arm
for ep, arm in zip(self.endstops, arm_lengths)])
logging.info(
"Delta max build height %.2fmm (radius tapered above %.2fmm)" % (
self.max_z, self.limit_z))
# Setup stepper max halt velocity
self.max_velocity, self.max_accel = toolhead.get_max_velocity()
self.max_z_velocity = config.getfloat(
'max_z_velocity', self.max_velocity,
above=0., maxval=self.max_velocity)
max_halt_velocity = toolhead.get_max_axis_halt()
for s in self.steppers:
s.set_max_jerk(max_halt_velocity, self.max_accel)
# Determine tower locations in cartesian space
self.angles = [sconfig.getfloat('angle', angle)
for sconfig, angle in zip(stepper_configs,
[210., 330., 90.])]
self.towers = [(math.cos(math.radians(angle)) * radius,
math.sin(math.radians(angle)) * radius)
for angle in self.angles]
# Find the point where an XY move could result in excessive
# tower movement
half_min_step_dist = min([s.step_dist for s in self.steppers]) * .5
min_arm_length = min(arm_lengths)
def ratio_to_dist(ratio):
return (ratio * math.sqrt(min_arm_length**2 / (ratio**2 + 1.)
- half_min_step_dist**2)
+ half_min_step_dist)
self.slow_xy2 = (ratio_to_dist(SLOW_RATIO) - radius)**2
self.very_slow_xy2 = (ratio_to_dist(2. * SLOW_RATIO) - radius)**2
self.max_xy2 = min(radius, min_arm_length - radius,
ratio_to_dist(4. * SLOW_RATIO) - radius)**2
logging.info(
"Delta max build radius %.2fmm (moves slowed past %.2fmm and %.2fmm)"
% (math.sqrt(self.max_xy2), math.sqrt(self.slow_xy2),
math.sqrt(self.very_slow_xy2)))
self.set_position([0., 0., 0.], ())
def get_steppers(self, flags=""):
return list(self.steppers)
def _cartesian_to_actuator(self, coord):
return [int((math.sqrt(self.arm_length2
- (self.towers[i][0] - coord[0])**2
- (self.towers[i][1] - coord[1])**2) + coord[2])
* self.steppers[i].inv_step_dist + 0.5)
return [math.sqrt(self.arm2[i] - (self.towers[i][0] - coord[0])**2
- (self.towers[i][1] - coord[1])**2) + coord[2]
for i in StepList]
def _actuator_to_cartesian(self, pos):
# Based on code from Smoothieware
tower1 = list(self.towers[0]) + [pos[0]]
tower2 = list(self.towers[1]) + [pos[1]]
tower3 = list(self.towers[2]) + [pos[2]]
s12 = matrix_sub(tower1, tower2)
s23 = matrix_sub(tower2, tower3)
s13 = matrix_sub(tower1, tower3)
normal = matrix_cross(s12, s23)
magsq_s12 = matrix_magsq(s12)
magsq_s23 = matrix_magsq(s23)
magsq_s13 = matrix_magsq(s13)
inv_nmag_sq = 1.0 / matrix_magsq(normal)
q = 0.5 * inv_nmag_sq
a = q * magsq_s23 * matrix_dot(s12, s13)
b = -q * magsq_s13 * matrix_dot(s12, s23) # negate because we use s12 instead of s21
c = q * magsq_s12 * matrix_dot(s13, s23)
circumcenter = [tower1[0] * a + tower2[0] * b + tower3[0] * c,
tower1[1] * a + tower2[1] * b + tower3[1] * c,
tower1[2] * a + tower2[2] * b + tower3[2] * c]
r_sq = 0.5 * q * magsq_s12 * magsq_s23 * magsq_s13
dist = math.sqrt(inv_nmag_sq * (self.arm_length2 - r_sq))
return matrix_sub(circumcenter, matrix_mul(normal, dist))
def set_position(self, newpos):
return actuator_to_cartesian(self.towers, self.arm2, pos)
def get_position(self):
spos = [s.mcu_stepper.get_commanded_position() for s in self.steppers]
return self._actuator_to_cartesian(spos)
def set_position(self, newpos, homing_axes):
pos = self._cartesian_to_actuator(newpos)
for i in StepList:
self.steppers[i].mcu_stepper.set_position(pos[i])
self.steppers[i].set_position(pos[i])
self.limit_xy2 = -1.
if tuple(homing_axes) == StepList:
self.need_home = False
def home(self, homing_state):
# All axes are homed simultaneously
homing_state.set_axes([0, 1, 2])
s = self.steppers[0] # Assume homing parameters same for all steppers
self.limit_xy2 = self.max_xy2
endstops = [es for s in self.steppers for es in s.get_endstops()]
s = self.steppers[0] # Assume homing speed same for all steppers
# Initial homing
homepos = [0., 0., s.position_endstop, None]
homing_speed = min(s.homing_speed, self.max_z_velocity)
homepos = [0., 0., self.max_z, None]
coord = list(homepos)
coord[2] = -1.5 * math.sqrt(self.arm_length2-self.max_xy2)
homing_state.home(list(coord), homepos, self.steppers, s.homing_speed)
coord[2] = -1.5 * math.sqrt(max(self.arm2)-self.max_xy2)
homing_state.home(coord, homepos, endstops, homing_speed)
# Retract
coord[2] = homepos[2] - s.homing_retract_dist
homing_state.retract(list(coord), s.homing_speed)
homing_state.retract(coord, homing_speed)
# Home again
coord[2] -= s.homing_retract_dist
homing_state.home(list(coord), homepos, self.steppers
, s.homing_speed/2.0, second_home=True)
homing_state.home(coord, homepos, endstops,
homing_speed/2.0, second_home=True)
# Set final homed position
coord = [(s.mcu_stepper.commanded_position + s.get_homed_offset())
* s.step_dist
for s in self.steppers]
homing_state.set_homed_position(self._actuator_to_cartesian(coord))
def motor_off(self, move_time):
spos = [ep + s.get_homed_offset()
for ep, s in zip(self.endstops, self.steppers)]
homing_state.set_homed_position(self._actuator_to_cartesian(spos))
def motor_off(self, print_time):
self.limit_xy2 = -1.
for stepper in self.steppers:
stepper.motor_enable(move_time, 0)
self.need_motor_enable = True
def _check_motor_enable(self, move_time):
stepper.motor_enable(print_time, 0)
self.need_motor_enable = self.need_home = True
def _check_motor_enable(self, print_time):
for i in StepList:
self.steppers[i].motor_enable(move_time, 1)
self.steppers[i].motor_enable(print_time, 1)
self.need_motor_enable = False
def query_endstops(self, print_time):
endstops = [(s, s.query_endstop(print_time)) for s in self.steppers]
return [(s.name, es.query_endstop_wait()) for s, es in endstops]
def check_move(self, move):
end_pos = move.end_pos
xy2 = end_pos[0]**2 + end_pos[1]**2
if xy2 > self.limit_xy2 or end_pos[2] < 0.:
if self.limit_xy2 < 0.:
raise homing.EndstopMoveError(end_pos, "Must home first")
raise homing.EndstopMoveError(end_pos)
if xy2 <= self.limit_xy2 and not move.axes_d[2]:
# Normal XY move
return
if self.need_home:
raise homing.EndstopMoveError(end_pos, "Must home first")
limit_xy2 = self.max_xy2
if end_pos[2] > self.limit_z:
if end_pos[2] > self.max_z or xy2 > (self.max_z - end_pos[2])**2:
raise homing.EndstopMoveError(end_pos)
limit_xy2 = min(limit_xy2, (self.max_z - end_pos[2])**2)
if xy2 > limit_xy2 or end_pos[2] < self.min_z or end_pos[2] > self.max_z:
raise homing.EndstopMoveError(end_pos)
if move.axes_d[2]:
move.limit_speed(self.max_z_velocity, 9999999.9)
def move(self, move_time, move):
move.limit_speed(self.max_z_velocity, move.accel)
limit_xy2 = -1.
# Limit the speed/accel of this move if is is at the extreme
# end of the build envelope
extreme_xy2 = max(xy2, move.start_pos[0]**2 + move.start_pos[1]**2)
if extreme_xy2 > self.slow_xy2:
r = 0.5
if extreme_xy2 > self.very_slow_xy2:
r = 0.25
max_velocity = self.max_velocity
if move.axes_d[2]:
max_velocity = self.max_z_velocity
move.limit_speed(max_velocity * r, self.max_accel * r)
limit_xy2 = -1.
self.limit_xy2 = min(limit_xy2, self.slow_xy2)
def move(self, print_time, move):
if self.need_motor_enable:
self._check_motor_enable(print_time)
axes_d = move.axes_d
move_d = movexy_d = move.move_d
move_d = move.move_d
movexy_r = 1.
movez_r = 0.
inv_movexy_d = 1. / movexy_d
inv_movexy_d = 1. / move_d
if not axes_d[0] and not axes_d[1]:
if not axes_d[2]:
return
# Z only move
movez_r = axes_d[2] * inv_movexy_d
movexy_d = movexy_r = inv_movexy_d = 0.
movexy_r = inv_movexy_d = 0.
elif axes_d[2]:
# XY+Z move
movexy_d = math.sqrt(axes_d[0]**2 + axes_d[1]**2)
movexy_r = movexy_d * inv_movexy_d
movez_r = axes_d[2] * inv_movexy_d
inv_movexy_d = 1. / movexy_d
if self.need_motor_enable:
self._check_motor_enable(move_time)
origx, origy, origz = move.start_pos[:3]
accel_t = move.accel_t
cruise_end_t = accel_t + move.cruise_t
accel = move.accel
cruise_v = move.cruise_v
accel_d = move.accel_r * move_d
cruise_end_d = accel_d + move.cruise_r * move_d
inv_cruise_v = 1. / move.cruise_v
inv_accel = 1. / move.accel
accel_time_offset = move.start_v * inv_accel
accel_multiplier = 2.0 * inv_accel
accel_offset = move.start_v**2 * 0.5 * inv_accel
decel_time_offset = move.cruise_v * inv_accel + cruise_end_t
decel_offset = move.cruise_v**2 * 0.5 * inv_accel + cruise_end_d
cruise_d = move.cruise_r * move_d
decel_d = move.decel_r * move_d
for i in StepList:
# Find point on line of movement closest to tower
# Calculate a virtual tower along the line of movement at
# the point closest to this stepper's tower.
towerx_d = self.towers[i][0] - origx
towery_d = self.towers[i][1] - origy
closestxy_d = (towerx_d*axes_d[0] + towery_d*axes_d[1])*inv_movexy_d
tangentxy_d2 = towerx_d**2 + towery_d**2 - closestxy_d**2
closest_height2 = self.arm_length2 - tangentxy_d2
# Calculate accel/cruise/decel portions of move
reversexy_d = closestxy_d + math.sqrt(closest_height2)*movez_r
accel_up_d = cruise_up_d = decel_up_d = 0.
accel_down_d = cruise_down_d = decel_down_d = 0.
if reversexy_d <= 0.:
accel_down_d = accel_d
cruise_down_d = cruise_end_d
decel_down_d = move_d
elif reversexy_d >= movexy_d:
accel_up_d = accel_d
cruise_up_d = cruise_end_d
decel_up_d = move_d
elif reversexy_d < accel_d * movexy_r:
accel_up_d = reversexy_d * move_d * inv_movexy_d
accel_down_d = accel_d
cruise_down_d = cruise_end_d
decel_down_d = move_d
elif reversexy_d < cruise_end_d * movexy_r:
accel_up_d = accel_d
cruise_up_d = reversexy_d * move_d * inv_movexy_d
cruise_down_d = cruise_end_d
decel_down_d = move_d
else:
accel_up_d = accel_d
cruise_up_d = cruise_end_d
decel_up_d = reversexy_d * move_d * inv_movexy_d
decel_down_d = move_d
vt_startxy_d = (towerx_d*axes_d[0] + towery_d*axes_d[1])*inv_movexy_d
tangentxy_d2 = towerx_d**2 + towery_d**2 - vt_startxy_d**2
vt_arm_d = math.sqrt(self.arm2[i] - tangentxy_d2)
vt_startz = origz
# Generate steps
mcu_stepper = self.steppers[i].mcu_stepper
mcu_time = mcu_stepper.print_to_mcu_time(move_time)
step_pos = mcu_stepper.commanded_position
step_dist = self.steppers[i].step_dist
height = step_pos*step_dist - origz
if accel_up_d > 0.:
count = mcu_stepper.step_delta_accel(
mcu_time - accel_time_offset, accel_up_d,
accel_offset, accel_multiplier, step_dist,
height, closestxy_d, closest_height2, movez_r)
height += count * step_dist
if cruise_up_d > 0.:
count = mcu_stepper.step_delta_const(
mcu_time + accel_t, cruise_up_d,
-accel_d, inv_cruise_v, step_dist,
height, closestxy_d, closest_height2, movez_r)
height += count * step_dist
if decel_up_d > 0.:
count = mcu_stepper.step_delta_accel(
mcu_time + decel_time_offset, decel_up_d,
-decel_offset, -accel_multiplier, step_dist,
height, closestxy_d, closest_height2, movez_r)
height += count * step_dist
if accel_down_d > 0.:
count = mcu_stepper.step_delta_accel(
mcu_time - accel_time_offset, accel_down_d,
accel_offset, accel_multiplier, -step_dist,
height, closestxy_d, closest_height2, movez_r)
height += count * step_dist
if cruise_down_d > 0.:
count = mcu_stepper.step_delta_const(
mcu_time + accel_t, cruise_down_d,
-accel_d, inv_cruise_v, -step_dist,
height, closestxy_d, closest_height2, movez_r)
height += count * step_dist
if decel_down_d > 0.:
count = mcu_stepper.step_delta_accel(
mcu_time + decel_time_offset, decel_down_d,
-decel_offset, -accel_multiplier, -step_dist,
height, closestxy_d, closest_height2, movez_r)
step_delta = self.steppers[i].step_delta
move_time = print_time
if accel_d:
step_delta(move_time, accel_d, move.start_v, accel,
vt_startz, vt_startxy_d, vt_arm_d, movez_r)
vt_startz += accel_d * movez_r
vt_startxy_d -= accel_d * movexy_r
move_time += move.accel_t
if cruise_d:
step_delta(move_time, cruise_d, cruise_v, 0.,
vt_startz, vt_startxy_d, vt_arm_d, movez_r)
vt_startz += cruise_d * movez_r
vt_startxy_d -= cruise_d * movexy_r
move_time += move.cruise_t
if decel_d:
step_delta(move_time, decel_d, cruise_v, -accel,
vt_startz, vt_startxy_d, vt_arm_d, movez_r)
# Helper functions for DELTA_CALIBRATE script
def get_stable_position(self):
return [int((ep - s.mcu_stepper.get_commanded_position())
/ s.mcu_stepper.get_step_dist() + .5)
* s.mcu_stepper.get_step_dist()
for ep, s in zip(self.endstops, self.steppers)]
def get_calibrate_params(self):
return {
'endstop_a': self.steppers[0].position_endstop,
'endstop_b': self.steppers[1].position_endstop,
'endstop_c': self.steppers[2].position_endstop,
'angle_a': self.angles[0], 'angle_b': self.angles[1],
'angle_c': self.angles[2], 'radius': self.radius,
'arm_a': self.arm_lengths[0], 'arm_b': self.arm_lengths[1],
'arm_c': self.arm_lengths[2] }
######################################################################
@@ -253,8 +237,49 @@ def matrix_dot(m1, m2):
def matrix_magsq(m1):
return m1[0]**2 + m1[1]**2 + m1[2]**2
def matrix_add(m1, m2):
return [m1[0] + m2[0], m1[1] + m2[1], m1[2] + m2[2]]
def matrix_sub(m1, m2):
return [m1[0] - m2[0], m1[1] - m2[1], m1[2] - m2[2]]
def matrix_mul(m1, s):
return [m1[0]*s, m1[1]*s, m1[2]*s]
def actuator_to_cartesian(towers, arm2, pos):
# Find nozzle position using trilateration (see wikipedia)
carriage1 = list(towers[0]) + [pos[0]]
carriage2 = list(towers[1]) + [pos[1]]
carriage3 = list(towers[2]) + [pos[2]]
s21 = matrix_sub(carriage2, carriage1)
s31 = matrix_sub(carriage3, carriage1)
d = math.sqrt(matrix_magsq(s21))
ex = matrix_mul(s21, 1. / d)
i = matrix_dot(ex, s31)
vect_ey = matrix_sub(s31, matrix_mul(ex, i))
ey = matrix_mul(vect_ey, 1. / math.sqrt(matrix_magsq(vect_ey)))
ez = matrix_cross(ex, ey)
j = matrix_dot(ey, s31)
x = (arm2[0] - arm2[1] + d**2) / (2. * d)
y = (arm2[0] - arm2[2] - x**2 + (x-i)**2 + j**2) / (2. * j)
z = -math.sqrt(arm2[0] - x**2 - y**2)
ex_x = matrix_mul(ex, x)
ey_y = matrix_mul(ey, y)
ez_z = matrix_mul(ez, z)
return matrix_add(carriage1, matrix_add(ex_x, matrix_add(ey_y, ez_z)))
def get_position_from_stable(spos, params):
angles = [params['angle_a'], params['angle_b'], params['angle_c']]
radius = params['radius']
radius2 = radius**2
towers = [(math.cos(angle) * radius, math.sin(angle) * radius)
for angle in map(math.radians, angles)]
arm2 = [a**2 for a in [params['arm_a'], params['arm_b'], params['arm_c']]]
endstops = [params['endstop_a'], params['endstop_b'], params['endstop_c']]
pos = [es + math.sqrt(a2 - radius2) - p
for es, a2, p in zip(endstops, arm2, spos)]
return actuator_to_cartesian(towers, arm2, pos)

View File

@@ -0,0 +1,5 @@
# Package definition for the extras directory
#
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.

32
klippy/extras/ad5206.py Normal file
View File

@@ -0,0 +1,32 @@
# AD5206 digipot code
#
# Copyright (C) 2017,2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import pins
class ad5206:
def __init__(self, config):
printer = config.get_printer()
enable_pin_params = pins.get_printer_pins(printer).lookup_pin(
'digital_out', config.get('enable_pin'))
if enable_pin_params['invert']:
raise pins.error("ad5206 can not invert pin")
self.mcu = enable_pin_params['chip']
self.pin = enable_pin_params['pin']
self.mcu.add_config_object(self)
scale = config.getfloat('scale', 1., above=0.)
self.channels = [None] * 6
for i in range(len(self.channels)):
val = config.getfloat('channel_%d' % (i+1,), None,
minval=0., maxval=scale)
if val is not None:
self.channels[i] = int(val * 256. / scale + .5)
def build_config(self):
for i, val in enumerate(self.channels):
if val is not None:
self.mcu.add_config_cmd(
"send_spi_message pin=%s msg=%02x%02x" % (self.pin, i, val))
def load_config_prefix(config):
return ad5206(config)

113
klippy/extras/bed_tilt.py Normal file
View File

@@ -0,0 +1,113 @@
# Bed tilt compensation
#
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging
import probe, mathutil
class BedTilt:
def __init__(self, config):
self.printer = config.get_printer()
self.x_adjust = config.getfloat('x_adjust', 0.)
self.y_adjust = config.getfloat('y_adjust', 0.)
if config.get('points', None) is not None:
BedTiltCalibrate(config, self)
self.toolhead = None
gcode = self.printer.lookup_object('gcode')
gcode.set_move_transform(self)
def printer_state(self, state):
if state == 'connect':
self.toolhead = self.printer.lookup_object('toolhead')
def get_position(self):
x, y, z, e = self.toolhead.get_position()
return [x, y, z - x*self.x_adjust - y*self.y_adjust, e]
def move(self, newpos, speed):
x, y, z, e = newpos
self.toolhead.move([x, y, z + x*self.x_adjust + y*self.y_adjust, e],
speed)
# Helper script to calibrate the bed tilt
class BedTiltCalibrate:
def __init__(self, config, bedtilt):
self.bedtilt = bedtilt
self.printer = config.get_printer()
points = config.get('points').split('\n')
try:
points = [line.split(',', 1) for line in points if line.strip()]
self.points = [(float(p[0].strip()), float(p[1].strip()))
for p in points]
except:
raise config.error("Unable to parse bed tilt points")
if len(self.points) < 3:
raise config.error("Need at least 3 points for bed_tilt_calibrate")
self.speed = config.getfloat('speed', 50., above=0.)
self.horizontal_move_z = config.getfloat('horizontal_move_z', 5.)
self.z_position_endstop = None
if config.has_section('stepper_z'):
zconfig = config.getsection('stepper_z')
self.z_position_endstop = zconfig.getfloat('position_endstop', None)
self.manual_probe = config.getboolean('manual_probe', None)
if self.manual_probe is None:
self.manual_probe = not config.has_section('probe')
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command(
'BED_TILT_CALIBRATE', self.cmd_BED_TILT_CALIBRATE,
desc=self.cmd_BED_TILT_CALIBRATE_help)
cmd_BED_TILT_CALIBRATE_help = "Bed tilt calibration script"
def cmd_BED_TILT_CALIBRATE(self, params):
self.gcode.run_script("G28")
probe.ProbePointsHelper(
self.printer, self.points, self.horizontal_move_z,
self.speed, self.manual_probe, self)
def get_position(self):
kin = self.printer.lookup_object('toolhead').get_kinematics()
return kin.get_position()
def finalize(self, z_offset, positions):
logging.info("Calculating bed_tilt with: %s", positions)
params = { 'x_adjust': self.bedtilt.x_adjust,
'y_adjust': self.bedtilt.y_adjust,
'z_adjust': z_offset }
logging.info("Initial bed_tilt parameters: %s", params)
def adjusted_height(pos, params):
x, y, z = pos
return (z - x*params['x_adjust'] - y*params['y_adjust']
- params['z_adjust'])
def errorfunc(params):
total_error = 0.
for pos in positions:
total_error += adjusted_height(pos, params)**2
return total_error
new_params = mathutil.coordinate_descent(
params.keys(), params, errorfunc)
logging.info("Calculated bed_tilt parameters: %s", new_params)
for pos in positions:
logging.info("orig: %s new: %s", adjusted_height(pos, params),
adjusted_height(pos, new_params))
z_diff = new_params['z_adjust'] - z_offset
if self.z_position_endstop is not None:
# Cartesian style robot
z_extra = ""
probe = self.printer.lookup_object('probe', None)
if probe is not None:
last_home_position = probe.last_home_position()
if last_home_position is not None:
# Using z_virtual_endstop
home_x, home_y = last_home_position[:2]
z_diff -= home_x * new_params['x_adjust']
z_diff -= home_y * new_params['y_adjust']
z_extra = " (when Z homing at %.3f,%.3f)" % (home_x, home_y)
z_adjust = "stepper_z position_endstop: %.6f%s\n" % (
self.z_position_endstop - z_diff, z_extra)
else:
# Delta (or other) style robot
z_adjust = "Add %.6f to endstop position\n" % (-z_diff,)
msg = "%sx_adjust: %.6f y_adjust: %.6f" % (
z_adjust, new_params['x_adjust'], new_params['y_adjust'])
logging.info("bed_tilt_calibrate: %s", msg)
self.gcode.respond_info(
"%s\nTo use these parameters, update the printer config file with\n"
"the above and then issue a RESTART command" % (msg,))
def load_config(config):
return BedTilt(config)

View File

@@ -0,0 +1,73 @@
# Delta calibration support
#
# Copyright (C) 2017-2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import math, logging
import probe, delta, mathutil
class DeltaCalibrate:
def __init__(self, config):
self.printer = config.get_printer()
if config.getsection('printer').get('kinematics') != 'delta':
raise config.error("Delta calibrate is only for delta printers")
self.radius = config.getfloat('radius', above=0.)
self.speed = config.getfloat('speed', 50., above=0.)
self.horizontal_move_z = config.getfloat('horizontal_move_z', 5.)
self.manual_probe = config.getboolean('manual_probe', None)
if self.manual_probe is None:
self.manual_probe = not config.has_section('probe')
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command(
'DELTA_CALIBRATE', self.cmd_DELTA_CALIBRATE,
desc=self.cmd_DELTA_CALIBRATE_help)
cmd_DELTA_CALIBRATE_help = "Delta calibration script"
def cmd_DELTA_CALIBRATE(self, params):
# Setup probe points
points = [(0., 0.)]
scatter = [.95, .90, .85, .70, .75, .80]
for i in range(6):
r = math.radians(90. + 60. * i)
dist = self.radius * scatter[i]
points.append((math.cos(r) * dist, math.sin(r) * dist))
# Probe them
self.gcode.run_script("G28")
probe.ProbePointsHelper(self.printer, points, self.horizontal_move_z,
self.speed, self.manual_probe, self)
def get_position(self):
kin = self.printer.lookup_object('toolhead').get_kinematics()
return kin.get_stable_position()
def finalize(self, z_offset, positions):
kin = self.printer.lookup_object('toolhead').get_kinematics()
logging.info("Calculating delta_calibrate with: %s", positions)
params = kin.get_calibrate_params()
logging.info("Initial delta_calibrate parameters: %s", params)
adj_params = ('endstop_a', 'endstop_b', 'endstop_c', 'radius',
'angle_a', 'angle_b')
def delta_errorfunc(params):
total_error = 0.
for spos in positions:
x, y, z = delta.get_position_from_stable(spos, params)
total_error += (z - z_offset)**2
return total_error
new_params = mathutil.coordinate_descent(
adj_params, params, delta_errorfunc)
logging.info("Calculated delta_calibrate parameters: %s", new_params)
for spos in positions:
logging.info("orig: %s new: %s",
delta.get_position_from_stable(spos, params),
delta.get_position_from_stable(spos, new_params))
self.gcode.respond_info(
"stepper_a: position_endstop: %.6f angle: %.6f\n"
"stepper_b: position_endstop: %.6f angle: %.6f\n"
"stepper_c: position_endstop: %.6f angle: %.6f\n"
"radius: %.6f\n"
"To use these parameters, update the printer config file with\n"
"the above and then issue a RESTART command" % (
new_params['endstop_a'], new_params['angle_a'],
new_params['endstop_b'], new_params['angle_b'],
new_params['endstop_c'], new_params['angle_c'],
new_params['radius']))
def load_config(config):
return DeltaCalibrate(config)

602
klippy/extras/display.py Normal file
View File

@@ -0,0 +1,602 @@
# Basic LCD display support
#
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
# Copyright (C) 2018 Aleph Objects, Inc <marcio@alephobjects.com>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
######################################################################
# HD44780 (20x4 text) lcd chip
######################################################################
HD44780_DELAY = .000037
class HD44780:
char_right_arrow = '\x7e'
char_thermometer = '\x00'
char_heater_bed = '\x01'
char_speed_factor = '\x02'
char_clock = '\x03'
char_degrees = '\x04'
def __init__(self, config):
self.printer = config.get_printer()
# pin config
ppins = self.printer.lookup_object('pins')
pins = [ppins.lookup_pin('digital_out', config.get(name + '_pin'))
for name in ['rs', 'e', 'd4', 'd5', 'd6', 'd7']]
mcu = None
for pin_params in pins:
if mcu is not None and pin_params['chip'] != mcu:
raise ppins.error("hd44780 all pins must be on same mcu")
mcu = pin_params['chip']
if pin_params['invert']:
raise ppins.error("hd44780 can not invert pin")
self.pins = [pin_params['pin'] for pin_params in pins]
self.mcu = mcu
self.oid = self.mcu.create_oid()
self.mcu.add_config_object(self)
self.send_data_cmd = self.send_cmds_cmd = None
# framebuffers
self.text_framebuffer = (bytearray(' '*80), bytearray('~'*80), 0x80)
self.glyph_framebuffer = (bytearray(64), bytearray('~'*64), 0x40)
self.framebuffers = [self.text_framebuffer, self.glyph_framebuffer]
def build_config(self):
self.mcu.add_config_cmd(
"config_hd44780 oid=%d rs_pin=%s e_pin=%s"
" d4_pin=%s d5_pin=%s d6_pin=%s d7_pin=%s delay_ticks=%d" % (
self.oid, self.pins[0], self.pins[1],
self.pins[2], self.pins[3], self.pins[4], self.pins[5],
self.mcu.seconds_to_clock(HD44780_DELAY)))
cmd_queue = self.mcu.alloc_command_queue()
self.send_cmds_cmd = self.mcu.lookup_command(
"hd44780_send_cmds oid=%c cmds=%*s", cq=cmd_queue)
self.send_data_cmd = self.mcu.lookup_command(
"hd44780_send_data oid=%c data=%*s", cq=cmd_queue)
def send(self, cmds, is_data=False):
cmd_type = self.send_cmds_cmd
if is_data:
cmd_type = self.send_data_cmd
cmd_type.send([self.oid, cmds], reqclock=BACKGROUND_PRIORITY_CLOCK)
#logging.debug("hd44780 %d %s", is_data, repr(cmds))
def flush(self):
# Find all differences in the framebuffers and send them to the chip
for new_data, old_data, fb_id in self.framebuffers:
if new_data == old_data:
continue
# Find the position of all changed bytes in this framebuffer
diffs = [[i, 1] for i, (nd, od) in enumerate(zip(new_data, old_data))
if nd != od]
# Batch together changes that are close to each other
for i in range(len(diffs)-2, -1, -1):
pos, count = diffs[i]
nextpos, nextcount = diffs[i+1]
if pos + 4 >= nextpos and nextcount < 16:
diffs[i][1] = nextcount + (nextpos - pos)
del diffs[i+1]
# Transmit changes
for pos, count in diffs:
chip_pos = pos
if fb_id == 0x80 and pos >= 40:
chip_pos += 0x40 - 40
self.send([fb_id + chip_pos])
self.send(new_data[pos:pos+count], is_data=True)
old_data[:] = new_data
def init(self):
curtime = self.printer.get_reactor().monotonic()
print_time = self.mcu.estimated_print_time(curtime)
# Program 4bit / 2-line mode and then issue 0x02 "Home" command
init = [[0x33], [0x33], [0x33, 0x22, 0x28, 0x02]]
# Reset (set positive direction ; enable display and hide cursor)
init.append([0x06, 0x0c])
for i, cmds in enumerate(init):
minclock = self.mcu.print_time_to_clock(print_time + i * .100)
self.send_cmds_cmd.send([self.oid, cmds], minclock=minclock)
# Add custom fonts
self.glyph_framebuffer[0][:len(HD44780_chars)] = HD44780_chars
for i in range(len(self.glyph_framebuffer[0])):
self.glyph_framebuffer[1][i] = self.glyph_framebuffer[0][i] ^ 1
self.flush()
def write_text(self, x, y, data):
if x + len(data) > 20:
data = data[:20 - min(x, 20)]
pos = [0, 40, 20, 60][y] + x
self.text_framebuffer[0][pos:pos+len(data)] = data
def clear(self):
self.text_framebuffer[0][:] = ' '*80
HD44780_chars = [
# Thermometer
0b00100,
0b01010,
0b01010,
0b01010,
0b01010,
0b10001,
0b10001,
0b01110,
# Heated bed
0b00000,
0b11111,
0b10101,
0b10001,
0b10101,
0b11111,
0b00000,
0b00000,
# Speed factor
0b11100,
0b10000,
0b11000,
0b10111,
0b00101,
0b00110,
0b00101,
0b00000,
# Clock
0b00000,
0b01110,
0b10011,
0b10101,
0b10001,
0b01110,
0b00000,
0b00000,
# Degrees
0b01100,
0b10010,
0b10010,
0b01100,
0b00000,
0b00000,
0b00000,
0b00000,
]
######################################################################
# ST7920 (128x64 graphics) lcd chip
######################################################################
ST7920_DELAY = .000020 # Spec says 72us, but faster is possible in practice
class ST7920:
char_right_arrow = '\x1a'
def __init__(self, config):
printer = config.get_printer()
# pin config
ppins = printer.lookup_object('pins')
pins = [ppins.lookup_pin('digital_out', config.get(name + '_pin'))
for name in ['cs', 'sclk', 'sid']]
mcu = None
for pin_params in pins:
if mcu is not None and pin_params['chip'] != mcu:
raise ppins.error("st7920 all pins must be on same mcu")
mcu = pin_params['chip']
if pin_params['invert']:
raise ppins.error("st7920 can not invert pin")
self.pins = [pin_params['pin'] for pin_params in pins]
self.mcu = mcu
self.oid = self.mcu.create_oid()
self.mcu.add_config_object(self)
self.send_data_cmd = self.send_cmds_cmd = None
self.is_extended = False
# framebuffers
self.text_framebuffer = (bytearray(' '*64), bytearray('~'*64), 0x80)
self.glyph_framebuffer = (bytearray(128), bytearray('~'*128), 0x40)
self.graphics_framebuffers = [(bytearray(32), bytearray('~'*32), i)
for i in range(32)]
self.framebuffers = ([self.text_framebuffer, self.glyph_framebuffer]
+ self.graphics_framebuffers)
def build_config(self):
self.mcu.add_config_cmd(
"config_st7920 oid=%u cs_pin=%s sclk_pin=%s sid_pin=%s"
" delay_ticks=%d" % (
self.oid, self.pins[0], self.pins[1], self.pins[2],
self.mcu.seconds_to_clock(ST7920_DELAY)))
cmd_queue = self.mcu.alloc_command_queue()
self.send_cmds_cmd = self.mcu.lookup_command(
"st7920_send_cmds oid=%c cmds=%*s", cq=cmd_queue)
self.send_data_cmd = self.mcu.lookup_command(
"st7920_send_data oid=%c data=%*s", cq=cmd_queue)
def send(self, cmds, is_data=False, is_extended=False):
cmd_type = self.send_cmds_cmd
if is_data:
cmd_type = self.send_data_cmd
elif self.is_extended != is_extended:
add_cmd = 0x22
if is_extended:
add_cmd = 0x26
cmds = [add_cmd] + cmds
self.is_extended = is_extended
cmd_type.send([self.oid, cmds], reqclock=BACKGROUND_PRIORITY_CLOCK)
#logging.debug("st7920 %d %s", is_data, repr(cmds))
def flush(self):
# Find all differences in the framebuffers and send them to the chip
for new_data, old_data, fb_id in self.framebuffers:
if new_data == old_data:
continue
# Find the position of all changed bytes in this framebuffer
diffs = [[i, 1] for i, (nd, od) in enumerate(zip(new_data, old_data))
if nd != od]
# Batch together changes that are close to each other
for i in range(len(diffs)-2, -1, -1):
pos, count = diffs[i]
nextpos, nextcount = diffs[i+1]
if pos + 5 >= nextpos and nextcount < 16:
diffs[i][1] = nextcount + (nextpos - pos)
del diffs[i+1]
# Transmit changes
for pos, count in diffs:
count += pos & 0x01
count += count & 0x01
pos = pos & ~0x01
chip_pos = pos >> 1
if fb_id < 0x40:
# Graphics framebuffer update
self.send([0x80 + fb_id, 0x80 + chip_pos], is_extended=True)
else:
self.send([fb_id + chip_pos])
self.send(new_data[pos:pos+count], is_data=True)
old_data[:] = new_data
def init(self):
cmds = [0x24, # Enter extended mode
0x40, # Clear vertical scroll address
0x02, # Enable CGRAM access
0x26, # Enable graphics
0x22, # Leave extended mode
0x02, # Home the display
0x06, # Set positive update direction
0x0c] # Enable display and hide cursor
self.send(cmds)
self.flush()
def load_glyph(self, glyph_id, data):
if len(data) > 32:
data = data[:32]
pos = min(glyph_id * 32, 96)
self.glyph_framebuffer[0][pos:pos+len(data)] = data
def write_text(self, x, y, data):
if x + len(data) > 16:
data = data[:16 - min(x, 16)]
pos = [0, 32, 16, 48][y] + x
self.text_framebuffer[0][pos:pos+len(data)] = data
def write_graphics(self, x, y, row, data):
if x + len(data) > 16:
data = data[:16 - min(x, 16)]
gfx_fb = y * 16 + row
if gfx_fb >= 32:
gfx_fb -= 32
x += 16
self.graphics_framebuffers[gfx_fb][0][x:x+len(data)] = data
def clear(self):
self.text_framebuffer[0][:] = ' '*64
zeros = bytearray(32)
for new_data, old_data, fb_id in self.graphics_framebuffers:
new_data[:] = zeros
######################################################################
# Icons
######################################################################
nozzle_icon = [
0b0000000000000000,
0b0000000000000000,
0b0000111111110000,
0b0001111111111000,
0b0001111111111000,
0b0001111111111000,
0b0000111111110000,
0b0000111111110000,
0b0001111111111000,
0b0001111111111000,
0b0001111111111000,
0b0000011111100000,
0b0000001111000000,
0b0000000110000000,
0b0000000000000000,
0b0000000000000000
]
bed_icon = [
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0111111111111110,
0b0111111111111110,
0b0000000000000000,
0b0000000000000000
]
heat1_icon = [
0b0000000000000000,
0b0000000000000000,
0b0010001000100000,
0b0001000100010000,
0b0000100010001000,
0b0000100010001000,
0b0001000100010000,
0b0010001000100000,
0b0010001000100000,
0b0001000100010000,
0b0000100010001000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000
]
heat2_icon = [
0b0000000000000000,
0b0000000000000000,
0b0000100010001000,
0b0000100010001000,
0b0001000100010000,
0b0010001000100000,
0b0010001000100000,
0b0001000100010000,
0b0000100010001000,
0b0000100010001000,
0b0001000100010000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000
]
fan1_icon = [
0b0000000000000000,
0b0111111111111110,
0b0111000000001110,
0b0110001111000110,
0b0100001111000010,
0b0100000110000010,
0b0101100000011010,
0b0101110110111010,
0b0101100000011010,
0b0100000110000010,
0b0100001111000010,
0b0110001111000110,
0b0111000000001110,
0b0111111111111110,
0b0000000000000000,
0b0000000000000000
]
fan2_icon = [
0b0000000000000000,
0b0111111111111110,
0b0111000000001110,
0b0110010000100110,
0b0100111001110010,
0b0101111001111010,
0b0100110000110010,
0b0100000110000010,
0b0100110000110010,
0b0101111001111010,
0b0100111001110010,
0b0110010000100110,
0b0111000000001110,
0b0111111111111110,
0b0000000000000000,
0b0000000000000000
]
feedrate_icon = [
0b0000000000000000,
0b0111111000000000,
0b0100000000000000,
0b0100000000000000,
0b0100000000000000,
0b0111111011111000,
0b0100000010000100,
0b0100000010000100,
0b0100000010000100,
0b0100000011111000,
0b0000000010001000,
0b0000000010000100,
0b0000000010000100,
0b0000000010000010,
0b0000000000000000,
0b0000000000000000
]
######################################################################
# LCD screen updates
######################################################################
LCD_chips = { 'st7920': ST7920, 'hd44780': HD44780 }
class PrinterLCD:
def __init__(self, config):
self.printer = config.get_printer()
self.reactor = self.printer.get_reactor()
self.lcd_chip = config.getchoice('lcd_type', LCD_chips)(config)
self.lcd_type = config.get('lcd_type')
# printer objects
self.gcode = self.toolhead = self.sdcard = None
self.fan = self.extruder0 = self.extruder1 = self.heater_bed = None
# screen updating
self.screen_update_timer = self.reactor.register_timer(
self.screen_update_event)
# Initialization
FAN1_GLYPH, FAN2_GLYPH, BED1_GLYPH, BED2_GLYPH = 0, 1, 2, 3
def printer_state(self, state):
if state == 'ready':
self.lcd_chip.init()
# Load printer objects
self.gcode = self.printer.lookup_object('gcode')
self.toolhead = self.printer.lookup_object('toolhead')
self.sdcard = self.printer.lookup_object('virtual_sdcard', None)
self.fan = self.printer.lookup_object('fan', None)
self.extruder0 = self.printer.lookup_object('extruder0', None)
self.extruder1 = self.printer.lookup_object('extruder1', None)
self.heater_bed = self.printer.lookup_object('heater_bed', None)
# Load glyphs
self.load_glyph(self.BED1_GLYPH, heat1_icon)
self.load_glyph(self.BED2_GLYPH, heat2_icon)
self.load_glyph(self.FAN1_GLYPH, fan1_icon)
self.load_glyph(self.FAN2_GLYPH, fan2_icon)
# Start screen update timer
self.reactor.update_timer(self.screen_update_timer, self.reactor.NOW)
# ST7920 Glyphs
def load_glyph(self, glyph_id, data):
if self.lcd_type != 'st7920':
return
glyph = [0x00] * (len(data) * 2)
for i, bits in enumerate(data):
glyph[i*2] = (bits >> 8) & 0xff
glyph[i*2 + 1] = bits & 0xff
return self.lcd_chip.load_glyph(glyph_id, glyph)
def animate_glyphs(self, eventtime, x, y, glyph_id, do_animate):
frame = do_animate and int(eventtime) & 1
self.lcd_chip.write_text(x, y, (0, (glyph_id + frame)*2))
# Graphics drawing
def draw_icon(self, x, y, data):
for i, bits in enumerate(data):
self.lcd_chip.write_graphics(
x, y, i, [(bits >> 8) & 0xff, bits & 0xff])
def draw_progress_bar(self, x, y, width, value):
value = int(value * 100.)
data = [0x00] * width
char_pcnt = int(100/width)
for i in range(width):
if (i+1)*char_pcnt <= value:
# Draw completely filled bytes
data[i] |= 0xFF
elif (i*char_pcnt) < value:
# Draw partially filled bytes
data[i] |= (-1 << 8-((value % char_pcnt)*8/char_pcnt)) & 0xff
data[0] |= 0x80
data[-1] |= 0x01
self.lcd_chip.write_graphics(x, y, 0, [0xff]*width)
for i in range(1, 15):
self.lcd_chip.write_graphics(x, y, i, data)
self.lcd_chip.write_graphics(x, y, 15, [0xff]*width)
# Screen updating
def screen_update_event(self, eventtime):
self.lcd_chip.clear()
if self.lcd_type == 'hd44780':
self.screen_update_hd44780(eventtime)
else:
self.screen_update_st7920(eventtime)
self.lcd_chip.flush()
return eventtime + .500
def screen_update_hd44780(self, eventtime):
lcd_chip = self.lcd_chip
# Heaters
if self.extruder0 is not None:
info = self.extruder0.get_heater().get_status(eventtime)
lcd_chip.write_text(0, 0, lcd_chip.char_thermometer)
self.draw_heater(1, 0, info)
if self.extruder1 is not None:
info = self.extruder1.get_heater().get_status(eventtime)
lcd_chip.write_text(0, 1, lcd_chip.char_thermometer)
self.draw_heater(1, 1, info)
if self.heater_bed is not None:
info = self.heater_bed.get_status(eventtime)
lcd_chip.write_text(10, 0, lcd_chip.char_heater_bed)
self.draw_heater(11, 0, info)
# Fan speed
if self.fan is not None:
info = self.fan.get_status(eventtime)
lcd_chip.write_text(10, 1, "Fan")
self.draw_percent(14, 1, 4, info['speed'])
# G-Code speed factor
gcode_info = self.gcode.get_status(eventtime)
lcd_chip.write_text(0, 2, lcd_chip.char_speed_factor)
self.draw_percent(1, 2, 4, gcode_info['speed_factor'])
# SD card print progress
if self.sdcard is not None:
info = self.sdcard.get_status(eventtime)
lcd_chip.write_text(7, 2, "SD")
self.draw_percent(9, 2, 4, info['progress'])
# Printing time and status
toolhead_info = self.toolhead.get_status(eventtime)
lcd_chip.write_text(14, 2, lcd_chip.char_clock)
self.draw_time(15, 2, toolhead_info['printing_time'])
self.draw_status(0, 3, gcode_info, toolhead_info)
def screen_update_st7920(self, eventtime):
# Heaters
if self.extruder0 is not None:
info = self.extruder0.get_heater().get_status(eventtime)
self.draw_icon(0, 0, nozzle_icon)
self.draw_heater(2, 0, info)
extruder_count = 1
if self.extruder1 is not None:
info = self.extruder1.get_heater().get_status(eventtime)
self.draw_icon(0, 1, nozzle_icon)
self.draw_heater(2, 1, info)
extruder_count = 2
if self.heater_bed is not None:
info = self.heater_bed.get_status(eventtime)
self.draw_icon(0, extruder_count, bed_icon)
if info['target']:
self.animate_glyphs(eventtime, 0, extruder_count,
self.BED1_GLYPH, True)
self.draw_heater(2, extruder_count, info)
# Fan speed
if self.fan is not None:
info = self.fan.get_status(eventtime)
self.animate_glyphs(eventtime, 10, 0, self.FAN1_GLYPH,
info['speed'] != 0.)
self.draw_percent(12, 0, 4, info['speed'])
# SD card print progress
if self.sdcard is not None:
info = self.sdcard.get_status(eventtime)
if extruder_count == 1:
x, y, width = 0, 2, 10
else:
x, y, width = 10, 1, 6
self.draw_percent(x, y, width, info['progress'])
self.draw_progress_bar(x, y, width, info['progress'])
# G-Code speed factor
gcode_info = self.gcode.get_status(eventtime)
if extruder_count == 1:
self.draw_icon(10, 1, feedrate_icon)
self.draw_percent(12, 1, 4, gcode_info['speed_factor'])
# Printing time and status
toolhead_info = self.toolhead.get_status(eventtime)
self.draw_time(10, 2, toolhead_info['printing_time'])
self.draw_status(0, 3, gcode_info, toolhead_info)
# Screen update helpers
def draw_heater(self, x, y, info):
temperature, target = info['temperature'], info['target']
if target and abs(temperature - target) > 2.:
s = "%3.0f%s%.0f" % (
temperature, self.lcd_chip.char_right_arrow, target)
else:
s = "%3.0f" % (temperature,)
if self.lcd_type == 'hd44780':
s += self.lcd_chip.char_degrees
self.lcd_chip.write_text(x, y, s)
def draw_percent(self, x, y, width, value):
self.lcd_chip.write_text(x, y, ("%d%%" % (value * 100.,)).center(width))
def draw_time(self, x, y, seconds):
seconds = int(seconds)
self.lcd_chip.write_text(x, y, "%02d:%02d" % (
seconds // (60 * 60), (seconds // 60) % 60))
def draw_status(self, x, y, gcode_info, toolhead_info):
status = toolhead_info['status']
if status == 'Printing' or gcode_info['busy']:
pos = self.toolhead.get_position()
status = "X%-4.0fY%-4.0fZ%-5.2f" % (pos[0], pos[1], pos[2])
self.lcd_chip.write_text(x, y, status)
def load_config(config):
return PrinterLCD(config)

39
klippy/extras/fan.py Normal file
View File

@@ -0,0 +1,39 @@
# Printer cooling fan
#
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import pins
FAN_MIN_TIME = 0.100
class PrinterFan:
def __init__(self, config):
self.last_fan_value = 0.
self.last_fan_time = 0.
self.max_power = config.getfloat('max_power', 1., above=0., maxval=1.)
self.kick_start_time = config.getfloat('kick_start_time', 0.1, minval=0.)
printer = config.get_printer()
self.mcu_fan = pins.setup_pin(printer, 'pwm', config.get('pin'))
self.mcu_fan.setup_max_duration(0.)
cycle_time = config.getfloat('cycle_time', 0.010, above=0.)
hardware_pwm = config.getboolean('hardware_pwm', False)
self.mcu_fan.setup_cycle_time(cycle_time, hardware_pwm)
def set_speed(self, print_time, value):
value = max(0., min(self.max_power, value))
if value == self.last_fan_value:
return
print_time = max(self.last_fan_time + FAN_MIN_TIME, print_time)
if (value and value < self.max_power
and not self.last_fan_value and self.kick_start_time):
# Run fan at full speed for specified kick_start_time
self.mcu_fan.set_pwm(print_time, self.max_power)
print_time += self.kick_start_time
self.mcu_fan.set_pwm(print_time, value)
self.last_fan_time = print_time
self.last_fan_value = value
def get_status(self, eventtime):
return {'speed': self.last_fan_value}
def load_config(config):
return PrinterFan(config)

View File

@@ -0,0 +1,37 @@
# Support fans that are enabled when a heater is on
#
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import fan, extruder
PIN_MIN_TIME = 0.100
class PrinterHeaterFan:
def __init__(self, config):
self.printer = config.get_printer()
self.heater_name = config.get("heater", "extruder0")
self.heater_temp = config.getfloat("heater_temp", 50.0)
self.fan = fan.PrinterFan(config)
self.mcu = self.fan.mcu_fan.get_mcu()
max_power = self.fan.max_power
self.fan_speed = config.getfloat(
"fan_speed", max_power, minval=0., maxval=max_power)
self.fan.mcu_fan.setup_start_value(0., max_power)
def printer_state(self, state):
if state == 'ready':
self.heater = extruder.get_printer_heater(
self.printer, self.heater_name)
reactor = self.printer.get_reactor()
reactor.register_timer(self.callback, reactor.NOW)
def callback(self, eventtime):
current_temp, target_temp = self.heater.get_temp(eventtime)
power = 0.
if target_temp or current_temp > self.heater_temp:
power = self.fan_speed
print_time = self.mcu.estimated_print_time(eventtime) + PIN_MIN_TIME
self.fan.set_speed(print_time, power)
return eventtime + 1.
def load_config_prefix(config):
return PrinterHeaterFan(config)

View File

@@ -0,0 +1,39 @@
# Run user defined actions in place of a normal G28 homing command
#
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
class HomingOverride:
def __init__(self, config):
self.printer = config.get_printer()
self.start_pos = [config.getfloat('set_position_' + a, None)
for a in 'xyz']
self.script = config.get('gcode')
self.in_script = False
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command("G28", self.cmd_G28)
def cmd_G28(self, params):
if self.in_script:
# Was called recursively - invoke the real G28 command
self.gcode.cmd_G28(params)
return
# Calculate forced position (if configured)
toolhead = self.printer.lookup_object('toolhead')
pos = toolhead.get_position()
homing_axes = []
for axis, loc in enumerate(self.start_pos):
if loc is not None:
pos[axis] = loc
homing_axes.append(axis)
toolhead.set_position(pos, homing_axes=homing_axes)
self.gcode.reset_last_position()
# Perform homing
try:
self.in_script = True
self.gcode.run_script(self.script)
finally:
self.in_script = False
def load_config(config):
return HomingOverride(config)

View File

@@ -0,0 +1,54 @@
# Virtual pin that propagates its changes to multiple output pins
#
# Copyright (C) 2017,2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import pins
class PrinterMultiPin:
def __init__(self, config):
self.printer = config.get_printer()
try:
pins.get_printer_pins(self.printer).register_chip('multi_pin', self)
except pins.error:
pass
self.pin_type = None
self.pin_list = [pin.strip() for pin in config.get('pins').split(',')]
self.mcu_pins = []
def setup_pin(self, pin_params):
pin_name = pin_params['pin']
pin = self.printer.lookup_object('multi_pin ' + pin_name, None)
if pin is not self:
if pin is None:
raise pins.error("multi_pin %s not configured" % (pin_name,))
return pin.setup_pin(pin_params)
if self.pin_type is not None:
raise pins.error("Can't setup multi_pin %s twice" % (pin_name,))
self.pin_type = pin_params['type']
invert = ""
if pin_params['invert']:
invert = "!"
self.mcu_pins = [
pins.setup_pin(self.printer, self.pin_type, invert + pin_desc)
for pin_desc in self.pin_list]
return self
def get_mcu(self):
return self.mcu_pins[0].get_mcu()
def setup_max_duration(self, max_duration):
for mcu_pin in self.mcu_pins:
mcu_pin.setup_max_duration(max_duration)
def setup_start_value(self, start_value, shutdown_value):
for mcu_pin in self.mcu_pins:
mcu_pin.setup_start_value(start_value, shutdown_value)
def setup_cycle_time(self, cycle_time, hardware_pwm=False):
for mcu_pin in self.mcu_pins:
mcu_pin.setup_cycle_time(cycle_time, hardware_pwm)
def set_digital(self, print_time, value):
for mcu_pin in self.mcu_pins:
mcu_pin.set_digital(print_time, value)
def set_pwm(self, print_time, value):
for mcu_pin in self.mcu_pins:
mcu_pin.set_pwm(print_time, value)
def load_config_prefix(config):
return PrinterMultiPin(config)

View File

@@ -0,0 +1,69 @@
# Code to configure miscellaneous chips
#
# Copyright (C) 2017,2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
PIN_MIN_TIME = 0.100
class PrinterOutputPin:
def __init__(self, config):
self.printer = config.get_printer()
ppins = self.printer.lookup_object('pins')
self.is_pwm = config.getboolean('pwm', False)
if self.is_pwm:
self.mcu_pin = ppins.setup_pin('pwm', config.get('pin'))
cycle_time = config.getfloat('cycle_time', 0.100, above=0.)
hardware_pwm = config.getboolean('hardware_pwm', False)
self.mcu_pin.setup_cycle_time(cycle_time, hardware_pwm)
self.scale = config.getfloat('scale', 1., above=0.)
else:
self.mcu_pin = ppins.setup_pin('digital_out', config.get('pin'))
self.scale = 1.
self.mcu_pin.setup_max_duration(0.)
self.last_value_time = 0.
static_value = config.getfloat('static_value', None,
minval=0., maxval=self.scale)
if static_value is not None:
self.is_static = True
self.last_value = static_value / self.scale
self.mcu_pin.setup_start_value(
self.last_value, self.last_value, True)
else:
self.is_static = False
self.last_value = config.getfloat(
'value', 0., minval=0., maxval=self.scale) / self.scale
shutdown_value = config.getfloat(
'shutdown_value', 0., minval=0., maxval=self.scale) / self.scale
self.mcu_pin.setup_start_value(self.last_value, shutdown_value)
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command("SET_PIN", self.cmd_SET_PIN,
desc=self.cmd_SET_PIN_help)
cmd_SET_PIN_help = "Set the value of an output pin"
def cmd_SET_PIN(self, params):
pin_name = self.gcode.get_str('PIN', params)
pin = self.printer.lookup_object('output_pin ' + pin_name, None)
if pin is not self:
if pin is None:
raise self.gcode.error("Pin not configured")
return pin.cmd_SET_PIN(params)
if self.is_static:
raise self.gcode.error("Static pin can not be changed at run-time")
value = self.gcode.get_float('VALUE', params) / self.scale
if value == self.last_value:
return
print_time = self.printer.lookup_object('toolhead').get_last_move_time()
print_time = max(print_time, self.last_value_time + PIN_MIN_TIME)
if self.is_pwm:
if value < 0. or value > 1.:
raise self.gcode.error("Invalid pin value")
self.mcu_pin.set_pwm(print_time, value)
else:
if value not in [0., 1.]:
raise self.gcode.error("Invalid pin value")
self.mcu_pin.set_digital(print_time, value)
self.last_value = value
self.last_value_time = print_time
def load_config_prefix(config):
return PrinterOutputPin(config)

View File

@@ -0,0 +1,127 @@
# Calibration of heater PID settings
#
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import math, logging
import extruder, heater
class PIDCalibrate:
def __init__(self, config):
self.printer = config.get_printer()
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command(
'PID_CALIBRATE', self.cmd_PID_CALIBRATE,
desc=self.cmd_PID_CALIBRATE_help)
cmd_PID_CALIBRATE_help = "Run PID calibration test"
def cmd_PID_CALIBRATE(self, params):
heater_name = self.gcode.get_str('HEATER', params)
target = self.gcode.get_float('TARGET', params)
write_file = self.gcode.get_int('WRITE_FILE', params, 0)
try:
heater = extruder.get_printer_heater(self.printer, heater_name)
except self.printer.config_error as e:
raise self.gcode.error(str(e))
print_time = self.printer.lookup_object('toolhead').get_last_move_time()
calibrate = ControlAutoTune(heater)
old_control = heater.set_control(calibrate)
try:
heater.set_temp(print_time, target)
except heater.error as e:
raise self.gcode.error(str(e))
self.gcode.bg_temp(heater)
heater.set_control(old_control)
if write_file:
calibrate.write_file('/tmp/heattest.txt')
Kp, Ki, Kd = calibrate.calc_final_pid()
logging.info("Autotune: final: Kp=%f Ki=%f Kd=%f", Kp, Ki, Kd)
self.gcode.respond_info(
"PID parameters: pid_Kp=%.3f pid_Ki=%.3f pid_Kd=%.3f\n"
"To use these parameters, update the printer config file with\n"
"the above and then issue a RESTART command" % (Kp, Ki, Kd))
TUNE_PID_DELTA = 5.0
class ControlAutoTune:
def __init__(self, heater):
self.heater = heater
# Heating control
self.heating = False
self.peak = 0.
self.peak_time = 0.
# Peak recording
self.peaks = []
# Sample recording
self.last_pwm = 0.
self.pwm_samples = []
self.temp_samples = []
# Heater control
def set_pwm(self, read_time, value):
if value != self.last_pwm:
self.pwm_samples.append((read_time + heater.PWM_DELAY, value))
self.last_pwm = value
self.heater.set_pwm(read_time, value)
def adc_callback(self, read_time, temp):
self.temp_samples.append((read_time, temp))
if self.heating and temp >= self.heater.target_temp:
self.heating = False
self.check_peaks()
elif (not self.heating
and temp <= self.heater.target_temp - TUNE_PID_DELTA):
self.heating = True
self.check_peaks()
if self.heating:
self.set_pwm(read_time, self.heater.max_power)
if temp < self.peak:
self.peak = temp
self.peak_time = read_time
else:
self.set_pwm(read_time, 0.)
if temp > self.peak:
self.peak = temp
self.peak_time = read_time
def check_busy(self, eventtime):
if self.heating or len(self.peaks) < 12:
return True
return False
# Analysis
def check_peaks(self):
self.peaks.append((self.peak, self.peak_time))
if self.heating:
self.peak = 9999999.
else:
self.peak = -9999999.
if len(self.peaks) < 4:
return
self.calc_pid(len(self.peaks)-1)
def calc_pid(self, pos):
temp_diff = self.peaks[pos][0] - self.peaks[pos-1][0]
time_diff = self.peaks[pos][1] - self.peaks[pos-2][1]
max_power = self.heater.max_power
Ku = 4. * (2. * max_power) / (abs(temp_diff) * math.pi)
Tu = time_diff
Ti = 0.5 * Tu
Td = 0.125 * Tu
Kp = 0.6 * Ku * heater.PID_PARAM_BASE
Ki = Kp / Ti
Kd = Kp * Td
logging.info("Autotune: raw=%f/%f Ku=%f Tu=%f Kp=%f Ki=%f Kd=%f",
temp_diff, max_power, Ku, Tu, Kp, Ki, Kd)
return Kp, Ki, Kd
def calc_final_pid(self):
cycle_times = [(self.peaks[pos][1] - self.peaks[pos-2][1], pos)
for pos in range(4, len(self.peaks))]
midpoint_pos = sorted(cycle_times)[len(cycle_times)/2][1]
return self.calc_pid(midpoint_pos)
# Offline analysis helper
def write_file(self, filename):
pwm = ["pwm: %.3f %.3f" % (time, value)
for time, value in self.pwm_samples]
out = ["%.3f %.3f" % (time, temp) for time, temp in self.temp_samples]
f = open(filename, "wb")
f.write('\n'.join(pwm + out))
f.close()
def load_config(config):
return PIDCalibrate(config)

189
klippy/extras/probe.py Normal file
View File

@@ -0,0 +1,189 @@
# Z-Probe support
#
# Copyright (C) 2017-2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import pins, homing
HINT_TIMEOUT = """
Make sure to home the printer before probing. If the probe
did not move far enough to trigger, then consider reducing
the Z axis minimum position so the probe can travel further
(the Z minimum position can be negative).
"""
class PrinterProbe:
def __init__(self, config):
self.printer = config.get_printer()
self.speed = config.getfloat('speed', 5.0)
self.z_offset = config.getfloat('z_offset')
# Infer Z position to move to during a probe
if config.has_section('stepper_z'):
zconfig = config.getsection('stepper_z')
self.z_position = zconfig.getfloat('position_min', 0.)
else:
pconfig = config.getsection('printer')
self.z_position = pconfig.getfloat('minimum_z_position', 0.)
# Create an "endstop" object to handle the probe pin
ppins = self.printer.lookup_object('pins')
pin_params = ppins.lookup_pin('endstop', config.get('pin'))
mcu = pin_params['chip']
mcu.add_config_object(self)
self.mcu_probe = mcu.setup_pin(pin_params)
if (config.get('activate_gcode', None) is not None or
config.get('deactivate_gcode', None) is not None):
self.mcu_probe = ProbeEndstopWrapper(config, self.mcu_probe)
# Create z_virtual_endstop pin
ppins.register_chip('probe', self)
self.z_virtual_endstop = None
# Register PROBE/QUERY_PROBE commands
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command(
'PROBE', self.cmd_PROBE, desc=self.cmd_PROBE_help)
self.gcode.register_command(
'QUERY_PROBE', self.cmd_QUERY_PROBE, desc=self.cmd_QUERY_PROBE_help)
def build_config(self):
toolhead = self.printer.lookup_object('toolhead')
z_steppers = toolhead.get_kinematics().get_steppers("Z")
for s in z_steppers:
for mcu_endstop, name in s.get_endstops():
for mcu_stepper in mcu_endstop.get_steppers():
self.mcu_probe.add_stepper(mcu_stepper)
def setup_pin(self, pin_params):
if (pin_params['pin'] != 'z_virtual_endstop'
or pin_params['type'] != 'endstop'):
raise pins.error("Probe virtual endstop only useful as endstop pin")
if pin_params['invert'] or pin_params['pullup']:
raise pins.error("Can not pullup/invert probe virtual endstop")
self.z_virtual_endstop = ProbeVirtualEndstop(
self.printer, self.mcu_probe)
return self.z_virtual_endstop
def last_home_position(self):
if self.z_virtual_endstop is None:
return None
return self.z_virtual_endstop.position
cmd_PROBE_help = "Probe Z-height at current XY position"
def cmd_PROBE(self, params):
toolhead = self.printer.lookup_object('toolhead')
homing_state = homing.Homing(toolhead)
pos = toolhead.get_position()
pos[2] = self.z_position
try:
homing_state.homing_move(
pos, [(self.mcu_probe, "probe")], self.speed, probe_pos=True)
except homing.EndstopError as e:
reason = str(e)
if "Timeout during endstop homing" in reason:
reason += HINT_TIMEOUT
raise self.gcode.error(reason)
self.gcode.reset_last_position()
cmd_QUERY_PROBE_help = "Return the status of the z-probe"
def cmd_QUERY_PROBE(self, params):
toolhead = self.printer.lookup_object('toolhead')
print_time = toolhead.get_last_move_time()
self.mcu_probe.query_endstop(print_time)
res = self.mcu_probe.query_endstop_wait()
self.gcode.respond_info(
"probe: %s" % (["open", "TRIGGERED"][not not res],))
# Endstop wrapper that enables running g-code scripts on setup
class ProbeEndstopWrapper:
def __init__(self, config, mcu_endstop):
self.mcu_endstop = mcu_endstop
self.gcode = config.get_printer().lookup_object('gcode')
self.activate_gcode = config.get('activate_gcode', "")
self.deactivate_gcode = config.get('deactivate_gcode', "")
# Wrappers
self.get_mcu = self.mcu_endstop.get_mcu
self.add_stepper = self.mcu_endstop.add_stepper
self.get_steppers = self.mcu_endstop.get_steppers
self.home_start = self.mcu_endstop.home_start
self.home_wait = self.mcu_endstop.home_wait
self.query_endstop = self.mcu_endstop.query_endstop
self.query_endstop_wait = self.mcu_endstop.query_endstop_wait
self.TimeoutError = self.mcu_endstop.TimeoutError
def home_prepare(self):
self.gcode.run_script(self.activate_gcode)
self.mcu_endstop.home_prepare()
def home_finalize(self):
self.gcode.run_script(self.deactivate_gcode)
self.mcu_endstop.home_finalize()
# Wrapper that records the last XY position of a virtual endstop probe
class ProbeVirtualEndstop:
def __init__(self, printer, mcu_endstop):
self.printer = printer
self.mcu_endstop = mcu_endstop
self.position = None
# Wrappers
self.get_mcu = self.mcu_endstop.get_mcu
self.add_stepper = self.mcu_endstop.add_stepper
self.get_steppers = self.mcu_endstop.get_steppers
self.home_start = self.mcu_endstop.home_start
self.home_wait = self.mcu_endstop.home_wait
self.query_endstop = self.mcu_endstop.query_endstop
self.query_endstop_wait = self.mcu_endstop.query_endstop_wait
self.home_prepare = self.mcu_endstop.home_prepare
self.TimeoutError = self.mcu_endstop.TimeoutError
def home_finalize(self):
self.position = self.printer.lookup_object('toolhead').get_position()
self.mcu_endstop.home_finalize()
# Helper code that can probe a series of points and report the
# position at each point.
class ProbePointsHelper:
def __init__(self, printer, probe_points, horizontal_move_z, speed,
manual_probe, callback):
self.printer = printer
self.probe_points = probe_points
self.horizontal_move_z = horizontal_move_z
self.speed = speed
self.manual_probe = manual_probe
self.callback = callback
self.toolhead = self.printer.lookup_object('toolhead')
self.results = []
self.busy = True
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command(
'NEXT', self.cmd_NEXT, desc=self.cmd_NEXT_help)
# Begin probing
self.move_next()
if not manual_probe:
while self.busy:
self.gcode.run_script("PROBE")
self.cmd_NEXT({})
def move_next(self):
x, y = self.probe_points[len(self.results)]
curpos = self.toolhead.get_position()
curpos[0] = x
curpos[1] = y
curpos[2] = self.horizontal_move_z
self.toolhead.move(curpos, self.speed)
self.gcode.reset_last_position()
cmd_NEXT_help = "Move to the next XY position to probe"
def cmd_NEXT(self, params):
# Record current position
self.toolhead.wait_moves()
self.results.append(self.callback.get_position())
# Move to next position
curpos = self.toolhead.get_position()
curpos[2] = self.horizontal_move_z
self.toolhead.move(curpos, self.speed)
if len(self.results) == len(self.probe_points):
self.toolhead.get_last_move_time()
self.finalize(True)
return
self.move_next()
def finalize(self, success):
self.busy = False
self.gcode.reset_last_position()
self.gcode.register_command('NEXT', None)
if success:
z_offset = 0.
if not self.manual_probe:
probe = self.printer.lookup_object('probe')
z_offset = probe.z_offset
self.callback.finalize(z_offset, self.results)
def load_config(config):
return PrinterProbe(config)

229
klippy/extras/replicape.py Normal file
View File

@@ -0,0 +1,229 @@
# Code to configure miscellaneous chips
#
# Copyright (C) 2017,2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging
import pins, mcu
REPLICAPE_MAX_CURRENT = 3.84
REPLICAPE_SHIFT_REGISTER_BUS = 1
REPLICAPE_SHIFT_REGISTER_DEVICE = 1
REPLICAPE_PCA9685_BUS = 2
REPLICAPE_PCA9685_ADDRESS = 0x70
REPLICAPE_PCA9685_CYCLE_TIME = .001
PIN_MIN_TIME = 0.100
class pca9685_pwm:
def __init__(self, replicape, channel, pin_params):
self._replicape = replicape
self._channel = channel
if pin_params['type'] not in ['digital_out', 'pwm']:
raise pins.error("Pin type not supported on replicape")
self._mcu = replicape.host_mcu
self._mcu.add_config_object(self)
self._bus = REPLICAPE_PCA9685_BUS
self._address = REPLICAPE_PCA9685_ADDRESS
self._cycle_time = REPLICAPE_PCA9685_CYCLE_TIME
self._max_duration = 2.
self._oid = None
self._invert = pin_params['invert']
self._start_value = self._shutdown_value = float(self._invert)
self._is_static = False
self._last_clock = 0
self._pwm_max = 0.
self._set_cmd = None
def get_mcu(self):
return self._mcu
def setup_max_duration(self, max_duration):
self._max_duration = max_duration
def setup_cycle_time(self, cycle_time, hardware_pwm=False):
if hardware_pwm:
raise pins.error("pca9685 does not support hardware_pwm parameter")
if cycle_time != self._cycle_time:
logging.info("Ignoring pca9685 cycle time of %.6f (using %.6f)",
cycle_time, self._cycle_time)
def setup_start_value(self, start_value, shutdown_value, is_static=False):
if is_static and start_value != shutdown_value:
raise pins.error("Static pin can not have shutdown value")
if self._invert:
start_value = 1. - start_value
shutdown_value = 1. - shutdown_value
self._start_value = max(0., min(1., start_value))
self._shutdown_value = max(0., min(1., shutdown_value))
self._is_static = is_static
self._replicape.note_pwm_start_value(
self._channel, self._start_value, self._shutdown_value)
def build_config(self):
self._pwm_max = self._mcu.get_constant_float("PCA9685_MAX")
cycle_ticks = self._mcu.seconds_to_clock(self._cycle_time)
if self._is_static:
self._mcu.add_config_cmd(
"set_pca9685_out bus=%d addr=%d channel=%d"
" cycle_ticks=%d value=%d" % (
self._bus, self._address, self._channel,
cycle_ticks, self._start_value * self._pwm_max))
return
self._oid = self._mcu.create_oid()
self._mcu.add_config_cmd(
"config_pca9685 oid=%d bus=%d addr=%d channel=%d cycle_ticks=%d"
" value=%d default_value=%d max_duration=%d" % (
self._oid, self._bus, self._address, self._channel, cycle_ticks,
self._start_value * self._pwm_max,
self._shutdown_value * self._pwm_max,
self._mcu.seconds_to_clock(self._max_duration)))
cmd_queue = self._mcu.alloc_command_queue()
self._set_cmd = self._mcu.lookup_command(
"schedule_pca9685_out oid=%c clock=%u value=%hu", cq=cmd_queue)
def set_pwm(self, print_time, value):
clock = self._mcu.print_time_to_clock(print_time)
if self._invert:
value = 1. - value
value = int(max(0., min(1., value)) * self._pwm_max + 0.5)
self._replicape.note_pwm_enable(print_time, self._channel, value)
self._set_cmd.send([self._oid, clock, value],
minclock=self._last_clock, reqclock=clock)
self._last_clock = clock
def set_digital(self, print_time, value):
if value:
self.set_pwm(print_time, 1.)
else:
self.set_pwm(print_time, 0.)
class ReplicapeDACEnable:
def __init__(self, replicape, channel, pin_params):
if pin_params['type'] != 'digital_out':
raise pins.error("Replicape virtual enable pin must be digital_out")
if pin_params['invert']:
raise pins.error("Replicape virtual enable pin can not be inverted")
self.mcu = replicape.host_mcu
self.value = replicape.stepper_dacs[channel]
self.pwm = pca9685_pwm(replicape, channel, pin_params)
def get_mcu(self):
return self.mcu
def setup_max_duration(self, max_duration):
self.pwm.setup_max_duration(max_duration)
def set_digital(self, print_time, value):
if value:
self.pwm.set_pwm(print_time, self.value)
else:
self.pwm.set_pwm(print_time, 0.)
ReplicapeStepConfig = {
'disable': None,
'1': (1<<7)|(1<<5), '2': (1<<7)|(1<<5)|(1<<6), 'spread2': (1<<5),
'4': (1<<7)|(1<<5)|(1<<4), '16': (1<<7)|(1<<5)|(1<<6)|(1<<4),
'spread4': (1<<5)|(1<<4), 'spread16': (1<<7), 'stealth4': (1<<7)|(1<<6),
'stealth16': 0
}
class Replicape:
def __init__(self, config):
printer = config.get_printer()
pins.get_printer_pins(printer).register_chip('replicape', self)
revisions = {'B3': 'B3'}
config.getchoice('revision', revisions)
self.host_mcu = mcu.get_printer_mcu(printer, config.get('host_mcu'))
# Setup enable pin
self.mcu_pwm_enable = pins.setup_pin(
printer, 'digital_out', config.get('enable_pin', '!P9_41'))
self.mcu_pwm_enable.setup_max_duration(0.)
self.mcu_pwm_start_value = self.mcu_pwm_shutdown_value = False
# Setup power pins
self.pins = {
"power_e": (pca9685_pwm, 5), "power_h": (pca9685_pwm, 3),
"power_hotbed": (pca9685_pwm, 4),
"power_fan0": (pca9685_pwm, 7), "power_fan1": (pca9685_pwm, 8),
"power_fan2": (pca9685_pwm, 9), "power_fan3": (pca9685_pwm, 10) }
# Setup stepper config
self.send_spi_cmd = None
self.last_stepper_time = 0.
self.stepper_dacs = {}
shift_registers = [1, 0, 0, 1, 1]
for port, name in enumerate('xyzeh'):
prefix = 'stepper_%s_' % (name,)
sc = config.getchoice(
prefix + 'microstep_mode', ReplicapeStepConfig, 'disable')
if sc is None:
continue
sc |= shift_registers[port]
if config.getboolean(prefix + 'chopper_off_time_high', False):
sc |= 1<<3
if config.getboolean(prefix + 'chopper_hysteresis_high', False):
sc |= 1<<2
if config.getboolean(prefix + 'chopper_blank_time_high', True):
sc |= 1<<1
shift_registers[port] = sc
channel = port + 11
cur = config.getfloat(
prefix + 'current', above=0., maxval=REPLICAPE_MAX_CURRENT)
self.stepper_dacs[channel] = cur / REPLICAPE_MAX_CURRENT
self.pins[prefix + 'enable'] = (ReplicapeDACEnable, channel)
self.enabled_channels = {ch: False for cl, ch in self.pins.values()}
if config.getboolean('servo0_enable', False):
shift_registers[1] |= 1
if config.getboolean('servo1_enable', False):
shift_registers[2] |= 1
self.sr_disabled = tuple(reversed(shift_registers))
if [i for i in [0, 1, 2] if 11+i in self.stepper_dacs]:
# Enable xyz steppers
shift_registers[0] &= ~1
if [i for i in [3, 4] if 11+i in self.stepper_dacs]:
# Enable eh steppers
shift_registers[3] &= ~1
if (config.getboolean('standstill_power_down', False)
and self.stepper_dacs):
shift_registers[4] &= ~1
self.sr_enabled = tuple(reversed(shift_registers))
self.host_mcu.add_config_object(self)
self.host_mcu.add_config_cmd("send_spi bus=%d dev=%d msg=%s" % (
REPLICAPE_SHIFT_REGISTER_BUS, REPLICAPE_SHIFT_REGISTER_DEVICE,
"".join(["%02x" % (x,) for x in self.sr_disabled])))
def build_config(self):
cmd_queue = self.host_mcu.alloc_command_queue()
self.send_spi_cmd = self.host_mcu.lookup_command(
"send_spi bus=%u dev=%u msg=%*s", cq=cmd_queue)
def note_pwm_start_value(self, channel, start_value, shutdown_value):
self.mcu_pwm_start_value |= not not start_value
self.mcu_pwm_shutdown_value |= not not shutdown_value
self.mcu_pwm_enable.setup_start_value(
self.mcu_pwm_start_value, self.mcu_pwm_shutdown_value)
self.enabled_channels[channel] = not not start_value
def note_pwm_enable(self, print_time, channel, value):
is_enable = not not value
if self.enabled_channels[channel] == is_enable:
# Nothing to do
return
self.enabled_channels[channel] = is_enable
# Check if need to set the pca9685 enable pin
on_channels = [1 for c, e in self.enabled_channels.items() if e]
if not on_channels:
self.mcu_pwm_enable.set_digital(print_time, 0)
elif is_enable and len(on_channels) == 1:
self.mcu_pwm_enable.set_digital(print_time, 1)
# Check if need to set the stepper enable lines
if channel not in self.stepper_dacs:
return
on_dacs = [1 for c in self.stepper_dacs.keys()
if self.enabled_channels[c]]
if not on_dacs:
sr = self.sr_disabled
elif is_enable and len(on_dacs) == 1:
sr = self.sr_enabled
else:
return
print_time = max(print_time, self.last_stepper_time + PIN_MIN_TIME)
clock = self.host_mcu.print_time_to_clock(print_time)
# XXX - the send_spi message should be scheduled
self.send_spi_cmd.send([REPLICAPE_SHIFT_REGISTER_BUS,
REPLICAPE_SHIFT_REGISTER_DEVICE, sr],
minclock=clock, reqclock=clock)
def setup_pin(self, pin_params):
pin = pin_params['pin']
if pin not in self.pins:
raise pins.error("Unknown replicape pin %s" % (pin,))
pclass, channel = self.pins[pin]
return pclass(self, channel, pin_params)
def load_config(config):
return Replicape(config)

59
klippy/extras/servo.py Normal file
View File

@@ -0,0 +1,59 @@
# Support for servos
#
# Copyright (C) 2017,2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import pins
SERVO_SIGNAL_PERIOD = 0.020
PIN_MIN_TIME = 0.100
class PrinterServo:
def __init__(self, config):
self.printer = config.get_printer()
self.mcu_servo = pins.setup_pin(self.printer, 'pwm', config.get('pin'))
self.mcu_servo.setup_max_duration(0.)
self.mcu_servo.setup_cycle_time(SERVO_SIGNAL_PERIOD)
self.min_width = config.getfloat(
'minimum_pulse_width', .001, above=0., below=SERVO_SIGNAL_PERIOD)
self.max_width = config.getfloat(
'maximum_pulse_width', .002
, above=self.min_width, below=SERVO_SIGNAL_PERIOD)
self.max_angle = config.getfloat('maximum_servo_angle', 180.)
self.angle_to_width = (self.max_width - self.min_width) / self.max_angle
self.width_to_value = 1. / SERVO_SIGNAL_PERIOD
self.last_value = self.last_value_time = 0.
self.gcode = self.printer.lookup_object('gcode')
self.gcode.register_command("SET_SERVO", self.cmd_SET_SERVO,
desc=self.cmd_SET_SERVO_help)
def set_pwm(self, print_time, value):
if value == self.last_value:
return
print_time = max(print_time, self.last_value_time + PIN_MIN_TIME)
self.mcu_servo.set_pwm(print_time, value)
self.last_value = value
self.last_value_time = print_time
def set_angle(self, print_time, angle):
angle = max(0., min(self.max_angle, angle))
width = self.min_width + angle * self.angle_to_width
self.set_pwm(print_time, width * self.width_to_value)
def set_pulse_width(self, print_time, width):
width = max(self.min_width, min(self.max_width, width))
self.set_pwm(print_time, width * self.width_to_value)
cmd_SET_SERVO_help = "Set servo angle"
def cmd_SET_SERVO(self, params):
servo_name = self.gcode.get_str('SERVO', params)
servo = self.printer.lookup_object('servo ' + servo_name, None)
if servo is not self:
if servo is None:
raise self.gcode.error("Servo not configured")
return servo.cmd_SET_SERVO(params)
print_time = self.printer.lookup_object('toolhead').get_last_move_time()
if 'WIDTH' in params:
self.set_pulse_width(print_time,
self.gcode.get_float('WIDTH', params))
else:
self.set_angle(print_time, self.gcode.get_float('ANGLE', params))
def load_config_prefix(config):
return PrinterServo(config)

Some files were not shown because too many files have changed in this diff Show More