From f03f8bfdda0ff8a06e6ae8b3a20b5bb4f4770d7c Mon Sep 17 00:00:00 2001 From: lavolpecheprogramma Date: Mon, 10 Feb 2020 20:00:15 +0100 Subject: [PATCH] initial --- .gitignore | 7 + COPYING | 681 +++++ Makefile | 106 + build/.gitignore | 4 + doc/csv/alarm_codes_en_US.csv | 11 + doc/csv/build_option_codes_en_US.csv | 23 + doc/csv/error_codes_en_US.csv | 37 + doc/csv/setting_codes_en_US.csv | 35 + doc/log/commit_log_v0.7.txt | 433 +++ doc/log/commit_log_v0.8c.txt | 831 ++++++ doc/log/commit_log_v0.9g.txt | 2409 +++++++++++++++++ doc/log/commit_log_v0.9i.txt | 871 ++++++ doc/log/commit_log_v0.9j.txt | 17 + doc/log/commit_log_v1.0b.txt | 140 + doc/log/commit_log_v1.0c.txt | 67 + doc/log/commit_log_v1.1.txt | 1187 ++++++++ doc/markdown/change_summary.md | 114 + doc/markdown/commands.md | 345 +++ doc/markdown/interface.md | 684 +++++ doc/markdown/jogging.md | 93 + doc/markdown/laser_mode.md | 89 + doc/markdown/settings.md | 259 ++ doc/script/fit_nonlinear_spindle.py | 373 +++ doc/script/simple_stream.py | 66 + doc/script/stream.py | 202 ++ grbl/config.h | 692 +++++ grbl/coolant_control.c | 126 + grbl/coolant_control.h | 47 + grbl/cpu_map.h | 260 ++ grbl/defaults.h | 571 ++++ grbl/eeprom.c | 151 ++ grbl/eeprom.h | 29 + grbl/examples/grblUpload/grblUpload.ino | 29 + grbl/examples/grblUpload/license.txt | 21 + .../grblWrite_BuildInfo.ino | 109 + grbl/examples/grblWrite_BuildInfo/license.txt | 21 + grbl/gcode.c | 1159 ++++++++ grbl/gcode.h | 248 ++ grbl/grbl.h | 140 + grbl/jog.c | 50 + grbl/jog.h | 32 + grbl/limits.c | 430 +++ grbl/limits.h | 41 + grbl/main.c | 109 + grbl/motion_control.c | 388 +++ grbl/motion_control.h | 66 + grbl/nuts_bolts.c | 190 ++ grbl/nuts_bolts.h | 87 + grbl/planner.c | 522 ++++ grbl/planner.h | 150 + grbl/print.c | 200 ++ grbl/print.h | 51 + grbl/probe.c | 66 + grbl/probe.h | 43 + grbl/protocol.c | 765 ++++++ grbl/protocol.h | 49 + grbl/report.c | 662 +++++ grbl/report.h | 131 + grbl/serial.c | 204 ++ grbl/serial.h | 62 + grbl/settings.c | 340 +++ grbl/settings.h | 153 ++ grbl/spindle_control.c | 290 ++ grbl/spindle_control.h | 73 + grbl/stepper.c | 1095 ++++++++ grbl/stepper.h | 59 + grbl/system.c | 410 +++ grbl/system.h | 212 ++ 68 files changed, 19617 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 Makefile create mode 100644 build/.gitignore create mode 100644 doc/csv/alarm_codes_en_US.csv create mode 100644 doc/csv/build_option_codes_en_US.csv create mode 100644 doc/csv/error_codes_en_US.csv create mode 100644 doc/csv/setting_codes_en_US.csv create mode 100644 doc/log/commit_log_v0.7.txt create mode 100644 doc/log/commit_log_v0.8c.txt create mode 100644 doc/log/commit_log_v0.9g.txt create mode 100644 doc/log/commit_log_v0.9i.txt create mode 100644 doc/log/commit_log_v0.9j.txt create mode 100644 doc/log/commit_log_v1.0b.txt create mode 100644 doc/log/commit_log_v1.0c.txt create mode 100644 doc/log/commit_log_v1.1.txt create mode 100644 doc/markdown/change_summary.md create mode 100644 doc/markdown/commands.md create mode 100644 doc/markdown/interface.md create mode 100644 doc/markdown/jogging.md create mode 100644 doc/markdown/laser_mode.md create mode 100644 doc/markdown/settings.md create mode 100644 doc/script/fit_nonlinear_spindle.py create mode 100755 doc/script/simple_stream.py create mode 100755 doc/script/stream.py create mode 100644 grbl/config.h create mode 100644 grbl/coolant_control.c create mode 100644 grbl/coolant_control.h create mode 100644 grbl/cpu_map.h create mode 100644 grbl/defaults.h create mode 100644 grbl/eeprom.c create mode 100644 grbl/eeprom.h create mode 100644 grbl/examples/grblUpload/grblUpload.ino create mode 100644 grbl/examples/grblUpload/license.txt create mode 100644 grbl/examples/grblWrite_BuildInfo/grblWrite_BuildInfo.ino create mode 100644 grbl/examples/grblWrite_BuildInfo/license.txt create mode 100644 grbl/gcode.c create mode 100644 grbl/gcode.h create mode 100644 grbl/grbl.h create mode 100644 grbl/jog.c create mode 100644 grbl/jog.h create mode 100644 grbl/limits.c create mode 100644 grbl/limits.h create mode 100644 grbl/main.c create mode 100644 grbl/motion_control.c create mode 100644 grbl/motion_control.h create mode 100644 grbl/nuts_bolts.c create mode 100644 grbl/nuts_bolts.h create mode 100644 grbl/planner.c create mode 100644 grbl/planner.h create mode 100644 grbl/print.c create mode 100644 grbl/print.h create mode 100644 grbl/probe.c create mode 100644 grbl/probe.h create mode 100644 grbl/protocol.c create mode 100644 grbl/protocol.h create mode 100644 grbl/report.c create mode 100644 grbl/report.h create mode 100644 grbl/serial.c create mode 100644 grbl/serial.h create mode 100644 grbl/settings.c create mode 100644 grbl/settings.h create mode 100644 grbl/spindle_control.c create mode 100644 grbl/spindle_control.h create mode 100644 grbl/stepper.c create mode 100644 grbl/stepper.h create mode 100644 grbl/system.c create mode 100644 grbl/system.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b61325d --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.hex +*.o +*.elf +*.DS_Store +*.d + +README.md diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..1cc1c47 --- /dev/null +++ b/COPYING @@ -0,0 +1,681 @@ +------------------------------------------------------------------------------ +COPYRIGHT NOTICE FOR GRBL: +------------------------------------------------------------------------------ + +Grbl - Embedded CNC g-code interpreter and motion-controller + +Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC +Copyright (c) 2009-2011 Simen Svale Skogsrud +Copyright (c) 2011 Jens Geisler + +Grbl is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Grbl is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Grbl. If not, see . + + +------------------------------------------------------------------------------ +COPYRIGHT NOTICE(S) FOR WORK CONTAINED IN THIS SOFTWARE: +------------------------------------------------------------------------------ + +Copyright (c) 2008, Atmel Corporation All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The name of ATMEL may not be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND +SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +------------------------------------------------------------------------------ +GNU GPLv3 TERMS AND CONDITIONS REPRODUCED HERE FOR CLARITY: +------------------------------------------------------------------------------ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9e20a43 --- /dev/null +++ b/Makefile @@ -0,0 +1,106 @@ +# Part of Grbl +# +# Copyright (c) 2009-2011 Simen Svale Skogsrud +# Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC +# +# Grbl is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Grbl is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Grbl. If not, see . + + +# This is a prototype Makefile. Modify it according to your needs. +# You should at least check the settings for +# DEVICE ....... The AVR device you compile for +# CLOCK ........ Target AVR clock rate in Hertz +# OBJECTS ...... The object files created from your source files. This list is +# usually the same as the list of source files with suffix ".o". +# PROGRAMMER ... Options to avrdude which define the hardware you use for +# uploading to the AVR and the interface where this hardware +# is connected. +# FUSES ........ Parameters for avrdude to flash the fuses appropriately. + +DEVICE ?= atmega328p +CLOCK = 16000000 +PROGRAMMER ?= -c avrisp2 -P usb +SOURCE = main.c motion_control.c gcode.c spindle_control.c coolant_control.c serial.c \ + protocol.c stepper.c eeprom.c settings.c planner.c nuts_bolts.c limits.c jog.c\ + print.c probe.c report.c system.c +BUILDDIR = build +SOURCEDIR = grbl +# FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m +FUSES = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m + +# Tune the lines below only if you know what you are doing: + +AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) -B 10 -F + +# Compile flags for avr-gcc v4.8.1. Does not produce -flto warnings. +# COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -I. -ffunction-sections + +# Compile flags for avr-gcc v4.9.2 compatible with the IDE. Or if you don't care about the warnings. +COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -I. -ffunction-sections -flto + + +OBJECTS = $(addprefix $(BUILDDIR)/,$(notdir $(SOURCE:.c=.o))) + +# symbolic targets: +all: grbl.hex + +$(BUILDDIR)/%.o: $(SOURCEDIR)/%.c + $(COMPILE) -MMD -MP -c $< -o $@ + +.S.o: + $(COMPILE) -x assembler-with-cpp -c $< -o $(BUILDDIR)/$@ +# "-x assembler-with-cpp" should not be necessary since this is the default +# file type for the .S (with capital S) extension. However, upper case +# characters are not always preserved on Windows. To ensure WinAVR +# compatibility define the file type manually. + +#.c.s: + $(COMPILE) -S $< -o $(BUILDDIR)/$@ + +flash: all + $(AVRDUDE) -U flash:w:grbl.hex:i + +fuse: + $(AVRDUDE) $(FUSES) + +# Xcode uses the Makefile targets "", "clean" and "install" +install: flash fuse + +# if you use a bootloader, change the command below appropriately: +load: all + bootloadHID grbl.hex + +clean: + rm -f grbl.hex $(BUILDDIR)/*.o $(BUILDDIR)/*.d $(BUILDDIR)/*.elf + +# file targets: +$(BUILDDIR)/main.elf: $(OBJECTS) + $(COMPILE) -o $(BUILDDIR)/main.elf $(OBJECTS) -lm -Wl,--gc-sections + +grbl.hex: $(BUILDDIR)/main.elf + rm -f grbl.hex + avr-objcopy -j .text -j .data -O ihex $(BUILDDIR)/main.elf grbl.hex + avr-size --format=berkeley $(BUILDDIR)/main.elf +# If you have an EEPROM section, you must also create a hex file for the +# EEPROM and add it to the "flash" target. + +# Targets for code debugging and analysis: +disasm: main.elf + avr-objdump -d $(BUILDDIR)/main.elf + +cpp: + $(COMPILE) -E $(SOURCEDIR)/main.c + +# include generated header dependencies +-include $(BUILDDIR)/$(OBJECTS:.o=.d) diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/doc/csv/alarm_codes_en_US.csv b/doc/csv/alarm_codes_en_US.csv new file mode 100644 index 0000000..685b61e --- /dev/null +++ b/doc/csv/alarm_codes_en_US.csv @@ -0,0 +1,11 @@ +"Alarm Code in v1.1+"," Alarm Message in v1.0-"," Alarm Description" +"1","Hard limit","Hard limit has been triggered. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." +"2","Soft limit","Soft limit alarm. G-code motion target exceeds machine travel. Machine position retained. Alarm may be safely unlocked." +"3","Abort during cycle","Reset while in motion. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." +"4","Probe fail","Probe fail. Probe is not in the expected initial state before starting probe cycle when G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered." +"5","Probe fail","Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4." +"6","Homing fail","Homing fail. The active homing cycle was reset." +"7","Homing fail","Homing fail. Safety door was opened during homing cycle." +"8","Homing fail","Homing fail. Pull off travel failed to clear limit switch. Try increasing pull-off setting or check wiring." +"9","Homing fail","Homing fail. Could not find limit switch within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." +"10","Homing fail","Homing fail. Second dual axis limit switch failed to trigger within configured search distance after first. Try increasing trigger fail distance or check wiring." diff --git a/doc/csv/build_option_codes_en_US.csv b/doc/csv/build_option_codes_en_US.csv new file mode 100644 index 0000000..54514bb --- /dev/null +++ b/doc/csv/build_option_codes_en_US.csv @@ -0,0 +1,23 @@ +OPT: Code, Build-Option Description,State +V,Variable spindle,Enabled +N,Line numbers,Enabled +M,Mist coolant M7,Enabled +C,CoreXY,Enabled +P,Parking motion,Enabled +Z,Homing force origin,Enabled +H,Homing single axis commands,Enabled +T,Two limit switches on axis,Enabled +A,Allow feed rate overrides in probe cycles,Enabled +D,Use spindle direction as enable pin,Enabled +0,Spindle enable off when speed is zero,Enabled +S,Software limit pin debouncing,Enabled +R,Parking override control,Enabled ++,Safety door input pin,Enabled +*,Restore all EEPROM command,Disabled +$,Restore EEPROM `$` settings command,Disabled +#,Restore EEPROM parameter data command,Disabled +I,Build info write user string command,Disabled +E,Force sync upon EEPROM write,Disabled +W,Force sync upon work coordinate offset change,Disabled +L,Homing initialization auto-lock,Disabled +2,Dual axis motors,Enabled \ No newline at end of file diff --git a/doc/csv/error_codes_en_US.csv b/doc/csv/error_codes_en_US.csv new file mode 100644 index 0000000..1375945 --- /dev/null +++ b/doc/csv/error_codes_en_US.csv @@ -0,0 +1,37 @@ +"Error Code in v1.1+","Error Message in v1.0-","Error Description" +"1","Expected command letter","G-code words consist of a letter and a value. Letter was not found." +"2","Bad number format","Missing the expected G-code word value or numeric value format is not valid." +"3","Invalid statement","Grbl '$' system command was not recognized or supported." +"4","Value < 0","Negative value received for an expected positive value." +"5","Setting disabled","Homing cycle failure. Homing is not enabled via settings." +"6","Value < 3 usec","Minimum step pulse time must be greater than 3usec." +"7","EEPROM read fail. Using defaults","An EEPROM read failed. Auto-restoring affected EEPROM to default values." +"8","Not idle","Grbl '$' command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job." +"9","G-code lock","G-code commands are locked out during alarm or jog state." +"10","Homing not enabled","Soft limits cannot be enabled without homing also enabled." +"11","Line overflow","Max characters per line exceeded. Received command line was not executed." +"12","Step rate > 30kHz","Grbl '$' setting value cause the step rate to exceed the maximum supported." +"13","Check Door","Safety door detected as opened and door state initiated." +"14","Line length exceeded","Build info or startup line exceeded EEPROM line length limit. Line not stored." +"15","Travel exceeded","Jog target exceeds machine travel. Jog command has been ignored." +"16","Invalid jog command","Jog command has no '=' or contains prohibited g-code." +"17","Setting disabled","Laser mode requires PWM output." +"20","Unsupported command","Unsupported or invalid g-code command found in block." +"21","Modal group violation","More than one g-code command from same modal group found in block." +"22","Undefined feed rate","Feed rate has not yet been set or is undefined." +"23","Invalid gcode ID:23","G-code command in block requires an integer value." +"24","Invalid gcode ID:24","More than one g-code command that requires axis words found in block." +"25","Invalid gcode ID:25","Repeated g-code word found in block." +"26","Invalid gcode ID:26","No axis words found in block for g-code command or current modal state which requires them." +"27","Invalid gcode ID:27","Line number value is invalid." +"28","Invalid gcode ID:28","G-code command is missing a required value word." +"29","Invalid gcode ID:29","G59.x work coordinate systems are not supported." +"30","Invalid gcode ID:30","G53 only allowed with G0 and G1 motion modes." +"31","Invalid gcode ID:31","Axis words found in block when no command or current modal state uses them." +"32","Invalid gcode ID:32","G2 and G3 arcs require at least one in-plane axis word." +"33","Invalid gcode ID:33","Motion command target is invalid." +"34","Invalid gcode ID:34","Arc radius value is invalid." +"35","Invalid gcode ID:35","G2 and G3 arcs require at least one in-plane offset word." +"36","Invalid gcode ID:36","Unused value words found in block." +"37","Invalid gcode ID:37","G43.1 dynamic tool length offset is not assigned to configured tool length axis." +"38","Invalid gcode ID:38","Tool number greater than max supported value." \ No newline at end of file diff --git a/doc/csv/setting_codes_en_US.csv b/doc/csv/setting_codes_en_US.csv new file mode 100644 index 0000000..fb97a3f --- /dev/null +++ b/doc/csv/setting_codes_en_US.csv @@ -0,0 +1,35 @@ +"$-Code"," Setting"," Units"," Setting Description" +"0","Step pulse time","microseconds","Sets time length per step. Minimum 3usec." +"1","Step idle delay","milliseconds","Sets a short hold delay when stopping to let dynamics settle before disabling steppers. Value 255 keeps motors enabled with no delay." +"2","Step pulse invert","mask","Inverts the step signal. Set axis bit to invert (00000ZYX)." +"3","Step direction invert","mask","Inverts the direction signal. Set axis bit to invert (00000ZYX)." +"4","Invert step enable pin","boolean","Inverts the stepper driver enable pin signal." +"5","Invert limit pins","boolean","Inverts the all of the limit input pins." +"6","Invert probe pin","boolean","Inverts the probe input pin signal." +"10","Status report options","mask","Alters data included in status reports." +"11","Junction deviation","millimeters","Sets how fast Grbl travels through consecutive motions. Lower value slows it down." +"12","Arc tolerance","millimeters","Sets the G2 and G3 arc tracing accuracy based on radial error. Beware: A very small value may effect performance." +"13","Report in inches","boolean","Enables inch units when returning any position and rate value that is not a settings value." +"20","Soft limits enable","boolean","Enables soft limits checks within machine travel and sets alarm when exceeded. Requires homing." +"21","Hard limits enable","boolean","Enables hard limits. Immediately halts motion and throws an alarm when switch is triggered." +"22","Homing cycle enable","boolean","Enables homing cycle. Requires limit switches on all axes." +"23","Homing direction invert","mask","Homing searches for a switch in the positive direction. Set axis bit (00000ZYX) to search in negative direction." +"24","Homing locate feed rate","mm/min","Feed rate to slowly engage limit switch to determine its location accurately." +"25","Homing search seek rate","mm/min","Seek rate to quickly find the limit switch before the slower locating phase." +"26","Homing switch debounce delay","milliseconds","Sets a short delay between phases of homing cycle to let a switch debounce." +"27","Homing switch pull-off distance","millimeters","Retract distance after triggering switch to disengage it. Homing will fail if switch isn't cleared." +"30","Maximum spindle speed","RPM","Maximum spindle speed. Sets PWM to 100% duty cycle." +"31","Minimum spindle speed","RPM","Minimum spindle speed. Sets PWM to 0.4% or lowest duty cycle." +"32","Laser-mode enable","boolean","Enables laser mode. Consecutive G1/2/3 commands will not halt when spindle speed is changed." +"100","X-axis travel resolution","step/mm","X-axis travel resolution in steps per millimeter." +"101","Y-axis travel resolution","step/mm","Y-axis travel resolution in steps per millimeter." +"102","Z-axis travel resolution","step/mm","Z-axis travel resolution in steps per millimeter." +"110","X-axis maximum rate","mm/min","X-axis maximum rate. Used as G0 rapid rate." +"111","Y-axis maximum rate","mm/min","Y-axis maximum rate. Used as G0 rapid rate." +"112","Z-axis maximum rate","mm/min","Z-axis maximum rate. Used as G0 rapid rate." +"120","X-axis acceleration","mm/sec^2","X-axis acceleration. Used for motion planning to not exceed motor torque and lose steps." +"121","Y-axis acceleration","mm/sec^2","Y-axis acceleration. Used for motion planning to not exceed motor torque and lose steps." +"122","Z-axis acceleration","mm/sec^2","Z-axis acceleration. Used for motion planning to not exceed motor torque and lose steps." +"130","X-axis maximum travel","millimeters","Maximum X-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances." +"131","Y-axis maximum travel","millimeters","Maximum Y-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances." +"132","Z-axis maximum travel","millimeters","Maximum Z-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances." diff --git a/doc/log/commit_log_v0.7.txt b/doc/log/commit_log_v0.7.txt new file mode 100644 index 0000000..5d536a3 --- /dev/null +++ b/doc/log/commit_log_v0.7.txt @@ -0,0 +1,433 @@ +---------------- +Date: 2012-01-17 +Author: Sonny Jeon +Subject: Update readme.textile + +---------------- +Date: 2012-01-17 +Author: Sonny Jeon +Subject: Merge pull request #47 from chamnit/v0_7 + +Merging chamnit/v0_7 to grbl/master + +---------------- +Date: 2012-01-17 +Author: Sonny Jeon +Subject: Merge chamnit/v0_7 with grbl/master + + +---------------- +Date: 2012-01-17 +Author: Sonny Jeon +Subject: Update readme.textile + +---------------- +Date: 2012-01-17 +Author: Sonny Jeon +Subject: Merge pull request #39 from chamnit/edge + +Merging chamnit/grbl edge v0.8a to grbl/grbl edge + +---------------- +Date: 2012-01-15 +Author: Sonny Jeon +Subject: Propagated premature step end bug fix from the edge branch. Updated printFloat() function. + +- Will not be uploading a hex build of this, unless asked. + + +---------------- +Date: 2012-01-15 +Author: Sonny Jeon +Subject: Fix bug with premature step end. Refactored _delay_ms() and square() for better portability. + +- Fixed a premature step end bug dating back to Simen's 0.7b edge +version is fixed, from which this code is forked from. Caused by Timer2 +constantly overflowing calling the Step Reset Interrupt every 128usec. +Now Timer2 is always disabled after a step end and should free up some +cycles for the main program. Could be more than one way to fix this +problem. I'm open to suggestions. + +- _delay_ms() refactored to accept only constants to comply with +current compilers. square() removed since not available with some +compilers. + + +---------------- +Date: 2012-01-10 +Author: Sonny Jeon +Subject: Extended position reporting with both home and work coordinates. Home position now retained after reset. Other minor changes/fixes. + +- Grbl now tracks both home and work (G92) coordinate systems and does +live updates when G92 is called. +- Rudimentary home and work position status reporting. Works but still +under major construction. +- Updated the main streaming script. Has a disabled periodic timer for +querying status reports, disabled only because the Python timer doesn't +consistently restart after the script exits. Add here only for user +testing. +- Fixed a bug to prevent an endless serial_write loop during status +reports. +- Refactored the planner variables to make it more clear what they are +and make it easier for clear them. + + +---------------- +Date: 2012-01-09 +Author: Sonny Jeon +Subject: Corrected a minor streaming script character counting bug. + +---------------- +Date: 2012-01-09 +Author: Sonny Jeon +Subject: Updated line in streaming script. + +---------------- +Date: 2012-01-06 +Author: Sonny Jeon +Subject: Position reporting, refactored system variables, serial print fixes, updated streaming scripts. + +- Added machine position reporting to status queries. This will be +further developed with part positioning/offsets and maintaining +location upon reset. + +- System variables refactored into a global struct for better +readability. + +- Removed old obsolete Ruby streaming scripts. These were no longer +compatible. Updated Python streaming scripts. + +- Fixed printFloat() and other printing functions. + +- Decreased planner buffer back to 18 blocks and increased TX serial +buffer to 64 bytes. Need the memory space for future developments. + +- Begun adding run-time modes to grbl, where block delete toggle, mm/in +reporting modes, jog modes, etc can be set during runtime. Will be +fleshed out and placed into EEPROM when everything is added. + + +---------------- +Date: 2011-12-10 +Author: Sonny Jeon +Subject: Various minor updates and variable definition corrections. Removed deprecated acceleration manager. + +- Removed deprecated acceleration manager (non-functional since v0.7b) +- Updated variable types and function headers. - Updated stepper +interrupt to ISR() from SIGNAL()+sei(). - General code cleanup. + + +---------------- +Date: 2011-12-08 +Author: Sonny Jeon +Subject: Initial v0.8 ALPHA commit. Features multi-tasking run-time command execution (feed hold, cycle start, reset, status query). Extensive re-structuring of code for future features. + +- ALPHA status. - Multitasking ability with run-time command executions +for real-time control and feedback. - Decelerating feed hold and resume +during operation. - System abort/reset, which immediately kills all +movement and re-initializes grbl. - Re-structured grbl to easily allow +for new features: Status reporting, jogging, backlash compensation. (To +be completed in the following releases.) - Resized TX/RX serial buffers +(32/128 bytes) - Increased planner buffer size to 20 blocks. - Updated +documentation. + + +---------------- +Date: 2011-11-19 +Author: Sonny Jeon +Subject: Updated README and reordered branch versions. + + +---------------- +Date: 2011-11-19 +Author: Sonny Jeon +Subject: Re-ordered stepper idle function to first disable interrupt. + +---------------- +Date: 2011-11-11 +Author: Sonny Jeon +Subject: Corrected clearing of target and position variable for the go home routine. Thanks Jens! + +---------------- +Date: 2011-10-11 +Author: Sonny Jeon +Subject: Delete a new work file shouldn't have been synced. + + +---------------- +Date: 2011-10-11 +Author: Sonny Jeon +Subject: Third time's a charm! No more deceleration issues! Updated grbl version and settings. General cleanup. + +- Fleshed out the original idea to completely remove the long slope at +the end of deceleration issue. This third time should absolutely +eliminate it. +- Changed the acceleration setting to kept as mm/min^2 internally, +since this was creating unneccessary additional computation in the +planner. Human readable value kept at mm/sec^2. +- Updated grbl version 0.7d and settings version to 4. NOTE: Please +check settings after update. These may have changed, but shouldn't. +- Before updating the new features (pause, e-stop, federate override, +etc), the edge branch will soon be merged with the master, barring any +immediate issues that people may have, and the edge branch will be the +testing ground for the new grbl version 0.8. + + +---------------- +Date: 2011-10-07 +Author: Sonny Jeon +Subject: Forgot something! Comments on what the last change does. + + +---------------- +Date: 2011-10-06 +Author: Sonny Jeon +Subject: Minor update to further eliminate the ole long slope deceleration issue. New update note! + +- Added another way to further ensure the long slope deceleration issue +is eliminated. If the stepper rate change is too great near zero, the +stepper rate is adjusted at half increments to the end of travel, +creating a smooth transition. - If the new STEPPER_IDLE_LOCK_TIME is +set as zero, this delay is not compiled at compile-time. - NOTE: The +next update is likely going to be major, involving a full re-write of +the stepper.c program to integrate a simple way to apply pauses, +jogging, e-stop, and feedrate overrides. The interface should be +flexible enough to be easily modified for use with either hardware +switches or software commands. Coming soon. + + +---------------- +Date: 2011-09-29 +Author: Sonny Jeon +Subject: Added complete stop delay at the end of all motion. Moved grbl preprocessor script into a new repository. + +Added a very short (25 ms) user-definable delay before the steppers are +disabled at the motors are disabled and grbl goes idle. This ensures +any residual inertia at the end of the last motion does not cause the +axes to drift and grbl to lose its position when manually entering +g-code or when performing a tool change and starting the next +operation. + + +---------------- +Date: 2011-09-25 +Author: Sonny Jeon +Subject: Updated some comments and fixed a bug in the new stepper logic. + +- The stepper logic was not initiating the decelerations for certain +cases. Just re-arranged the logic to fix it. + + +---------------- +Date: 2011-09-24 +Author: Sonny Jeon +Subject: Fixed long slope at deceleration issue. Moved things into config.h. New MINIMUM_PLANNER_SPEED parameter. + +- The long standing issue of a long slope at deceleration is likely +fixed. The stepper program was not tracking and timing the end of +acceleration and start of deceleration exactly and now is fixed to +start and stop on time. Also, to ensure a better acceleration curve fit +used by the planner, the stepper program delays the start of the +accelerations by a half trapezoid tick to employ the midpoint rule. - +Settings version 3 migration (not fully tested, but should work) - +Added a MINIMUM_PLANNER_SPEED user-defined parameter to planner to let +a user change this if problems arise for some reason. - Moved all +user-definable #define parameters into config.h with clear comments on +what they do and recommendations of how to change them. - Minor +housekeeping. + + +---------------- +Date: 2011-09-18 +Author: Sonny J +Subject: Fixed minor bugs in planner. Increased max dwell time. Long slope bug stop-gap solution note. + +- Fixed the planner TODO regarding minimum nominal speeds. Re-arranged +calculations to be both more efficient and guaranteed to be greater +than zero. - Missed a parenthesis location on the rate_delta +calculation. Should fix a nearly in-perceptible issue with incorrect +acceleration ramping in diagonal directions. - Increased maximum dwell +time from 6.5sec to an 18hour max. A crazy amount more, but that's how +the math works out. - Converted the internal feedrate values to mm/min +only, as it was switching between mm/min to mm/sec and back to mm/min. +Also added a feedrate > 0 check in gcode.c. - Identified the long slope +at the end of rapid de/ac-celerations noted by stephanix. Problem with +the numerical integration truncation error between the exact solution +of estimate_acceleration_distance and how grbl actually performs the +acceleration ramps discretely. Increasing the +ACCELERATION_TICKS_PER_SECOND in config.h helps fix this problem. +Investigating further. + + +---------------- +Date: 2011-09-15 +Author: Sonny J +Subject: More '%' modulo opertor removals and some housecleaning. + +- Serial functions contained quite a few modulo operations that would +be executed with high frequency when streaming. AVR processors are very +slow when operating these. In one test on the Arduino forums, it showed +about a 15x slow down compared to a simple if-then statement. - +Clarified some variable names and types and comments. + + +---------------- +Date: 2011-09-13 +Author: Sonny J +Subject: Further planner improvements and misc minor bug fixes. Memory savings and increased buffer size. + +- Update grbl version and settings version to automatically reset +eeprom. FYI, this will reset your grbl settings. - Saved +3*BLOCK_BUFFER_SIZE doubles in static memory by removing obsolete +variables: speed_x, speed_y, and speed_z. - Increased buffer size +conservatively to 18 from 16. (Probably can do 20). - Removed expensive! +modulo operator from block indexing function. Reduces significant +computational overhead. - Re-organized some sqrt() calls to be more +efficient during time critical planning cases, rather than non-time +critical. - Minor bug fix in planner max junction velocity logic. - +Simplified arc logic and removed need to multiply for CW or CCW +direction. + + +---------------- +Date: 2011-09-06 +Author: Sonny J +Subject: Optimized planner re-write. Significantly faster. Full arc support enabled by rotation matrix approach. + +- Significant improvements in the planner. Removed or reordered +repetitive and expensive calculations by order of importance: +recalculating unchanged blocks, trig functions [sin(), cos(), tan()], +sqrt(), divides, and multiplications. Blocks long enough for nominal +speed to be guaranteed to be reached ignored by planner. Done by +introducing two uint8_t flags per block. Reduced computational overhead +by an order of magnitude. - Arc motion generation completely +re-written and optimized. Now runs with acceleration planner. Removed +all but one trig function (atan2) from initialization. Streamlined +computations. Segment target locations generated by vector +transformation and small angle approximation. Arc path correction +implemented for accumulated error of approximation and single precision +calculation of Arduino. Bug fix in message passing. + + +---------------- +Date: 2011-09-04 +Author: Sonny J +Subject: Minor update for memory savings in ring buffer and fleshed out commenting. + +No changes in functionality. Path vectors moved from ring buffer to +local planner static variables to save 3*(BUFFER_SIZE - 1) doubles in +memory. Detailed comments. Really need to stop micro-updating. Should be +the last until a planner optimization (ala Jens Geisler) has been +completed. + + +---------------- +Date: 2011-09-04 +Author: Sonny J +Subject: More minor bug fixes in planner. + +Reverse planner was over-writing the initial/buffer tail entry speed, +which reset the forward planner and caused it to lose track of its +speed. Should now accelerate into short linear segments much nicer now. + + +---------------- +Date: 2011-09-03 +Author: Sonny J +Subject: Minor bug fixes in planner. + + +---------------- +Date: 2011-09-03 +Author: Sonny J +Subject: Add G02/03 arc conversion/pre-processor script and example streaming script + +Beta pre-processor script used to clean and streamline g-code for +streaming and converts G02/03 arcs into linear segments. Allows for full +acceleration support if the pre-processed g-code is then streamed to +grill, sans G02/03 arcs. Added a simple example streaming script for +Python users. + + +---------------- +Date: 2011-09-03 +Author: Sonny J +Subject: Significantly improved junction control and fixed computation bugs in planner + +- Junction jerk now re-defined as junction_deviation. The distance from +the junction to the edge of a circle tangent to both previous and +current path lines. The circle radii is used to compute the maximum +junction velocity by centripetal acceleration. More robust and +simplified way to compute jerk. - Fixed bugs related to entry and exit +factors. They were computed based on the current nominal speeds but not +when computing exit factors for neighboring blocks. Removed factors and +replaced with entry speeds only. Factors now only computed for stepper +trapezoid rate conversions. - Misc: Added min(), next_block_index, +prev_block_index functions for clarity. + + +---------------- +Date: 2011-08-15 +Author: Sonny J +Subject: Moved comment and block delete handling into protocol.c from gcode.c. Fixes bug when comment and block delete are not isolated. Blank lines ignored. + +Comments, block delete characters, and blank lines are no longer passed +to the gcode parser and should free up some memory by ignoring these +characters. Gcode parser now expects clean gcode only. There was a bug +if there were block deletes or comments not in the first character (i.e. +spindle on/off for proofing geode without turning it on, or a NXX +followed by a comment). This should fix it by bypassing the problem. +Left a commented line for easily turning on and off block deletes for a +later feature, if desired. + + +---------------- +Date: 2011-08-15 +Author: Sonny J +Subject: Revert ea5b8942db2616e93fc0478922010c3bab7c0481^..HEAD + + +---------------- +Date: 2011-08-15 +Author: Sonny J +Subject: Moved comment and block delete handling into protocol.c from gcode.c. Fixes bug when comment and block delete are not isolated. Blank lines ignored. + +Comments, block delete characters, and blank lines are no longer passed +to the gcode parser and should free up some memory by ignoring these +characters. Gcode parser now expects clean gcode only. There was a bug +if there were block deletes or comments not in the first character (i.e. +spindle on/off for proofing geode without turning it on, or a NXX +followed by a comment). This should fix it by bypassing the problem. +Left a commented line for easily turning on and off block deletes for a +later feature, if desired. + + +---------------- +Date: 2011-08-15 +Author: Sonny J +Subject: Revert 517a0f659a06182c89cafe27ee371edccad777a4^..HEAD + + +---------------- +Date: 2011-08-15 +Author: Sonny J +Subject: Revert "Moved comment and block delete handling to be done in protocol.c rather than gcode.c. Prevents these from being held in memory. Also, fixes bug when comments and block delete character are mixed with g-code." + +This reverts commit ea5b8942db2616e93fc0478922010c3bab7c0481. + + +---------------- +Date: 2011-08-15 +Author: Sonny J +Subject: Revert fdc90f1821f1f5edb7756fcddce75b4b4fbf6bbf^..HEAD + + +---------------- +Date: 2011-08-15 +Author: chamnit +Subject: Removed comment and block delete handling from gcode.c. Parser expects clean gcode. + +---------------- +Date: 2011-08-15 +Author: chamnit +Subject: Moved comment and block delete handling to be done in protocol.c rather than gcode.c. Prevents these from being held in memory. Also, fixes bug when comments and block delete character are mixed with g-code. diff --git a/doc/log/commit_log_v0.8c.txt b/doc/log/commit_log_v0.8c.txt new file mode 100644 index 0000000..f62cf89 --- /dev/null +++ b/doc/log/commit_log_v0.8c.txt @@ -0,0 +1,831 @@ +---------------- +Date: 2012-11-25 +Author: Sonny Jeon +Subject: G28/G30 post move bug fix. Altered file permissions. + + +---------------- +Date: 2012-11-25 +Author: Sonny Jeon +Subject: G28/G30 post move bug fix. + +- Fixed a bug when after moving to a pre-defined position G28/G30, the +next move would go someplace unexpected. The g-code parser position +vector wasn't getting updated. + + +---------------- +Date: 2012-11-20 +Author: Sonny Jeon +Subject: Merge error fix. + + +---------------- +Date: 2012-11-20 +Author: Sonny Jeon +Subject: Merge v0.8 edge to master + + +---------------- +Date: 2012-11-19 +Author: Sonny Jeon +Subject: Updated interface protocol. Fixed M2 bug. + +- Updated interface protocol to play nicer with interface programs. All +Grbl responses beginning with '$' signifies a setting. Bracketed '[]' +responses are feedback messages containing either state, parameter, or +general messages. Chevron '<>' response are from the real-time status +messages, i.e. position. + +- M2 Program end command was causing a system alarm. Fixed. Thanks +@blinkenlight ! + + +---------------- +Date: 2012-11-18 +Author: Sonny Jeon +Subject: Updated readme + + +---------------- +Date: 2012-11-18 +Author: Sonny Jeon +Subject: Homing search sequence now compile-time option. New defaults.h file. Tidying up. + +- The homing sequence is now a compile-time option, where a user can +choose which axes(s) move in sequence during the search phase. Up to 3 +sequences. Works with the locating phase and the pull-off maneuver. + +- New defaults.h file to store user generated default settings for +different machines. Mainly to be used as a central repo, but each set +may be select to be compiled in as a config.h define. + + +---------------- +Date: 2012-11-15 +Author: Sonny Jeon +Subject: Added Grbl state in status report. Removed switch support. + +- Added Grbl state (Idle, Running, Queued, Hold, etc) to the real-time +status reporting feature as feedback to the user of what Grbl is doing. +Updated the help message to reflect this change. + +- Removed switches (dry run, block delete, single block mode). To keep +Grbl simple and not muddled up from things that can easily be taken +care of by an external interface, these were removed. + +- Check g-code mode was retained, but the command was moved to '$C' +from '$S0'. + + +---------------- +Date: 2012-11-14 +Author: Sonny Jeon +Subject: Re-factored system states and alarm management. Serial baud support greater than 57600. + +- Refactored system states to be more clear and concise. Alarm locks +processes when position is unknown to indicate to user something has +gone wrong. + +- Changed mc_alarm to mc_reset, which now manages the system reset +function. Centralizes it. + +- Renamed '$X' kill homing lock to kill alarm lock. + +- Created an alarm error reporting method to clear up what is an alarm: +message vs a status error: message. For GUIs mainly. Alarm codes are +negative. Status codes are positive. + +- Serial baud support upto 115200. Previous baudrate calc was unstable +for 57600 and above. + +- Alarm state locks out all g-code blocks, including startup scripts, +but allows user to access settings and internal commands. For example, +to disable hard limits, if they are problematic. + +- Hard limits do not respond in an alarm state. + +- Fixed a problem with the hard limit interrupt during the homing +cycle. The interrupt register is still active during the homing cycle +and still signal the interrupt to trigger when re-enabled. Instead, +just disabled the register. + +- Homing rate adjusted. All axes move at homing seek rate, regardless +of how many axes move at the same time. This is unlike how the stepper +module does it as a point to point rate. + +- New config.h settings to disable the homing rate adjustment and the +force homing upon powerup. + +- Reduced the number of startup lines back down to 2 from 3. This +discourages users from placing motion block in there, which can be very +dangerous. + +- Startup blocks now run only after an alarm-free reset or after a +homing cycle. Does not run when $X kill is called. For satefy reasons + + +---------------- +Date: 2012-11-10 +Author: Sonny Jeon +Subject: Tweaks. Seek rate updates when set. CCW arc full circle fix. + +- Fixed a minor issue where the seek rates would not immediately be +used and only would after a reset. Should update live now. + +- A full circle IJ offset CCW arc would not do anything. Fixed bug via +a simple if-then statement. + +- Radius mode tweaks to check for negative value in sqrt() rather than +isnan() it. Error report updated to indicate what actually happened. + + +---------------- +Date: 2012-11-09 +Author: Sonny Jeon +Subject: Added note that D13 can't be used as input, pulled-high. + + +---------------- +Date: 2012-11-09 +Author: Sonny Jeon +Subject: Fixed homing cycle hanging after locating switches. + + +---------------- +Date: 2012-11-08 +Author: Sonny Jeon +Subject: Housekeeping. + +- Added some more notes to config.h. + +- Added the ability to override some of the #defines around Grbl in +config.h, like planner buffer size, line buffer size, serial +send/receive buffers. Mainly to centralize the configurations to be +able to port to different microcontrollers later. + + +---------------- +Date: 2012-11-08 +Author: Sonny Jeon +Subject: Sanguino compile patch + +@daapp : Sanguino compile serial USART path. Thanks! + + +---------------- +Date: 2012-11-07 +Author: Sonny Jeon +Subject: More tweaks. Removed dry run. Trimmed all messages to save flash space. + +- Removed the dry run switch. It was getting overly complicated for +what it needed to do. In practice, single block mode and feed rate +overrides (coming in next release) does a much better job with dry runs +than 'dry run'. + +- Trimmed all of Grbl's messages from help, status, feedback to +settings. Saved 0.6KB+ of flash space that could be used for v0.9 +features. + +- Removed some settings inits when set. Will depend on user to power +cycle to get some of these to reload. + +- Fixed a bug with settings version not re-writing old settings, when +it should. Thanks Alden! + + +---------------- +Date: 2012-11-06 +Author: Sonny Jeon +Subject: Merge pull request #132 from hin/header_dependencies + +Header dependencies + +---------------- +Date: 2012-11-05 +Author: Sonny Jeon +Subject: Tweaks and bug fixes. Increase to 3 startup blocks. Remove purge/added unlock command + +- Increased the number of startup blocks to 3 for no good reason other +than it doesn't increase the flash size. + +- Removed the purge buffer command and replaced with an disable homing +lock command. + +- Homing now blocks all g-code commands (not system commands) until the +homing cycle has been performed or the disable homing lock is sent. +Homing is required upon startup or if Grbl loses it position. This is +for safety reasons. + +- Cleaned up some of the Grbl states and re-organized it to be little +more cohesive. + +- Cleaned up the feedback and status messages to not use so much flash +space, as it's a premium now. + + - Check g-code and dry run switches how are mutually exclusive and +can't be enabled when the other is. And automatically resets Grbl when +disabled. + +- Some bug fixes and other minor tweaks. + + +---------------- +Date: 2012-11-05 +Author: Hans Insulander +Subject: Ignore dependency files + + +---------------- +Date: 2012-11-05 +Author: Hans Insulander +Subject: Generate header dependencies and use them in Makefile + + +---------------- +Date: 2012-11-05 +Author: Sonny Jeon +Subject: Tweaked dry run and check g-code switches. Now resets when toggled off. + +- To make managing the code easier and to help ensure a user starts +with a fresh reset, the functionality of check g-code and dry run has +been changed to automatically perform a soft reset when toggled off. +Position will not be lost, unless there is a cycle active. Feed hold +before toggling off it needed. + +This is mainly a safety issue. If a user dry runs a program and kills +it mid-program, and then restarts it thinking to run it as normal, the +g-code modes that we're set may not be what they expect, and very bad +things can happen. + +- NOTE: Grbl is at 83.5% of flash capacity. Not a lot of room left, but +I think we can squeeze in some more! + + +---------------- +Date: 2012-11-04 +Author: Sonny Jeon +Subject: Runtime command pinned out! Re-organized coolant pins. + +- Pinned out cycle start(A2), feed hold(A1), and reset(A0) runtime +commands. These pins are held high with the internal pull-up resistor +enabled. All you have to do is connect a normally-open switch to the +pin and ground. That's it. + +- Moved the coolant control pins to A3 (and the optional mist control +to A4). + +- Moved all of the MASK defines into the config.h file to centralize +them. + + +---------------- +Date: 2012-11-04 +Author: Sonny Jeon +Subject: Tweaks and minor bug fixes. Added purge buffer command. + +- Added a purge buffer (and lock) command. This is an advanced option +to clear any queued blocks in the buffer in the event of system +position being lost or homed. These queued blocks will likely not move +correctly if not purged. In typical use, the purging command releases +the homing axes lock in case a user need to move the axes off their +hard limit switches, but position is not guaranteed. Homing is advised +immediately after. + +- Created a system-wide sync current position function. Cleans up some +of the repetitive tasks in various places in the code that do the same +thing. + +- Removed the clear all switches command '$S'. Not really needed and +helped clean up a sync call. + +- Other minor tweaks. Readme updated slightly.. + + +---------------- +Date: 2012-11-03 +Author: Sonny Jeon +Subject: New startup script setting. New dry run, check gcode switches. New system state variable. Lots of reorganizing. + +(All v0.8 features installed. Still likely buggy, but now thourough +testing will need to start to squash them all. As soon as we're done, +this will be pushed to master and v0.9 development will be started. +Please report ANY issues to us so we can get this rolled out ASAP.) + +- User startup script! A user can now save one (up to 5 as compile-time +option) block of g-code in EEPROM memory. This will be run everytime +Grbl resets. Mainly to be used as a way to set your preferences, like +G21, G54, etc. + +- New dry run and check g-code switches. Dry run moves ALL motions at +rapids rate ignoring spindle, coolant, and dwell commands. For rapid +physical proofing of your code. The check g-code switch ignores all +motion and provides the user a way to check if there are any errors in +their program that Grbl may not like. + +- Program restart! (sort of). Program restart is typically an advanced +feature that allows users to restart a program mid-stream. The check +g-code switch can perform this feature by enabling the switch at the +start of the program, and disabling it at the desired point with some +minimal changes. + +- New system state variable. This state variable tracks all of the +different state processes that Grbl performs, i.e. cycle start, feed +hold, homing, etc. This is mainly for making managing of these task +easier and more clear. + +- Position lost state variable. Only when homing is enabled, Grbl will +refuse to move until homing is completed and position is known. This is +mainly for safety. Otherwise, it will let users fend for themselves. + +- Moved the default settings defines into config.h. The plan is to +eventually create a set of config.h's for particular as-built machines +to help users from doing it themselves. + +- Moved around misc defines into .h files. And lots of other little +things. + + +---------------- +Date: 2012-11-01 +Author: Sonny Jeon +Subject: Added block delete, opt stop, single block mode. New parser state and parameter feedback. Overhauled '$' command. + +NOTE: Another incremental update. Likely buggy, still a ways to go +before everything is installed, such as startup blocks. + +- Changed the '$' command to print help. '$$' now prints Grbl settings. +The help now instructs the user of runtime commands, switch toggling, +homing, etc. Jogging will be added to these in v0.9. + +- Added switches: block delete, opt stop, and single block mode. + +- Now can print the g-code parser state and persistent parameters +(coord sys) to view what Grbl has internally. + +- Made the gc struct in the g-code parser global to be able to print +the states. Also moved coordinate system tracking from sys to gc struct. + +- Changed up the welcome flag and updated version to v0.8c. + +- Removed spindle speed from gcode parser. Not used. + + +---------------- +Date: 2012-11-01 +Author: Sonny Jeon +Subject: New report module. 6 persistent work coordinates. New G-codes and settings. README and minor bug updates + +(NOTE: This push is likely buggy so proceed with caution. Just +uploading to let people know where we're going.) + +- New report.c module. Moved all feedback functions into this module to +centralize these processes. Includes realtime status reports, status +messages, feedback messages. + +- Official support 6 work coordinate systems (G54-G59), which are +persistently held in EEPROM memory. + +- New g-code support: G28.1, G30.1 stores current machine position as a +home position into EEPROM. G10 L20 Px stores current machine position +into work coordinates without needing to explicitly send XYZ words. + +- Homing performed with '$H' command. G28/G30 no longer start the +homing cycle. This is how it's supposed to be. + +- New settings: Stepper enable invert and n_arc correction installed. + +- Updated and changed up some limits and homing functionality. Pull-off +travel will now move after the homing cycle regardless of hard limits +enabled. Fixed direction of pull-off travel (went wrong way). + +- Started on designing an internal Grbl command protocol based on the +'$' settings letter. Commands with non numeric characters after '$' +will perform switch commands, homing cycle, jogging, printing +paramters, etc. Much more to do here. + +- Updated README to reflect all of the new features. + + +---------------- +Date: 2012-10-21 +Author: Sonny Jeon +Subject: Added misc message to indicate how to exit ALARM mode. + + +---------------- +Date: 2012-10-21 +Author: Sonny Jeon +Subject: New alarm method. Re(re)organized status messages. + +- Installed a new 'alarm' method to centralize motion kills across +alarm or reset events. Right now, this is controlled by system abort +and hard limits. But, in the future, a g-code parser error may call +this too as a safety feature. + +- Re(re)organized status messages to just print all errors, regardless +from where it was called. This centralizes them into one place. + +- Misc messages method installed for any user feedback that is not a +confirmation or error. Mainly so that there is a place to perform +warnings and such. + +- New stuff installed and still made the flash size smaller by saving +flash space from clearing out repeated '\r\n' pgmstrings. + +- Fixed a bug where hard limits message would print everytime a system +abort was sent. + + +---------------- +Date: 2012-10-21 +Author: Sonny Jeon +Subject: Re-organized status messages to be more coherent and centralized. + +- Reorganized all of the status message feedback from both the g-code +parser and settings modules to be centralized into two message modules: +status feedback from executing a line and warnings for misc feedback. + +- Pulled out the printPgmString() messages in settings.c and placed it +into the new module. (settings_dump() not moved). + +- Some other minor edits. Renaming defines, comment updates, etc. + + +---------------- +Date: 2012-10-18 +Author: Sonny Jeon +Subject: Hard limits code minor updates. + +- Fixed a bug that would not disable the steppers if a user issues a +system abort during a homing cycle. + +- Updated the hard limit interrupt to be more correct and to issue a +shutdown for the right situations when the switch has been triggered. + +- Added a status message to indicate to the user what happened and what +to do upon a hard limit trigger. + + +---------------- +Date: 2012-10-16 +Author: Sonny Jeon +Subject: Hard limits, homing direction, pull-off limits after homing, status reports in mm or inches, system alarm, and more. + +- Thank you statement added for Alden Hart of Synthetos. + +- Hard limits option added, which also works with homing by pulling off +the switches to help prevent unintended triggering. Hard limits use a +interrupt to sense a falling edge pin change and immediately go into +alarm mode, which stops everything and forces the user to issue a reset +(Ctrl-x) or reboot. + +- Auto cycle start now a configuration option. + +- Alarm mode: A new method to kill all Grbl processes in the event of +something catastrophic or potentially catastropic. Just works with hard +limits for now, but will be expanded to include g-code errors (most +likely) and other events. + +- Updated status reports to be configurable in inches or mm mode. Much +more to do here, but this is the first step. + +- New settings: auto cycle start, hard limit enable, homing direction +mask (which works the same as the stepper mask), homing pulloff +distance (or distance traveled from homed machine zero to prevent +accidental limit trip). + +- Minor memory liberation and calculation speed ups. + + +---------------- +Date: 2012-10-13 +Author: Sonny Jeon +Subject: Minor updates, improvements, and bug fixes. + +- Allowed status_message function to be called by others. This is to +centralize all feedback into protocol.c. + +- Fixed a bug where line number words 'N' were causing the parser to +error out. + +- Allowed homing routine feed rates to move slower than the +MINIMUM_STEP_RATE parameter in config.h. + +- Homing performs idle lock at the end of the routine. + +- Stepper idle lock time will now not disable the steppers when the +value is set at 255. This is accomodate users who prefer to keep their +axes enabled at all times. + +- Moved some defines around to where they need to be. + + +---------------- +Date: 2012-10-12 +Author: Sonny Jeon +Subject: Updated delay_us() function to accept long integers + + +---------------- +Date: 2012-10-11 +Author: Sonny Jeon +Subject: (2x) speed increase in printFloat() function. Decimal places setting added. + +- printFloat() function execution doubled in speed. This is a precursor +to status reporting, since GUIs may query real-time position rapidly. + +- Decimal places added to settings (for now). This may disappear in +future pushes, but here for testing purposes. + + +---------------- +Date: 2012-10-11 +Author: Sonny Jeon +Subject: Homing stepper enable bit fix. + + +---------------- +Date: 2012-10-10 +Author: Sonny Jeon +Subject: Homing direction pin bits fixed. Lite refactoring of settings. + + +---------------- +Date: 2012-10-09 +Author: Sonny Jeon +Subject: Improved homing cycle. New settings: homing enable/rates, debounce and step idle lock time. + +- Homing cycle will now cycle twice (spec more/less in config) to +improve repeatability and accuracy by decreasing overshoot. + +- New Grbl settings added: Enable/disable homing cycles, homing seek +and feed rates, switch debounce delay, and stepper idle lock time. + +- Please note that these settings may change upon the next push, since +there will be more added soon. Grbl *should* not re-write your old +settings, just re-write the new ones. So, make sure you keep these +written down somewhere in case they get lost from a code bug. + +- Refactored settings migration to be a little smaller and managable +going forward. + + +---------------- +Date: 2012-10-08 +Author: Sonny Jeon +Subject: Fixed an issue with leaving the limit switches during a homing cycle. + + +---------------- +Date: 2012-10-08 +Author: Sonny Jeon +Subject: Updated version number to v0.8b to reflect changes. + + +---------------- +Date: 2012-10-08 +Author: Sonny Jeon +Subject: Limit pin internal pull-resistors enabled. Re-wrote read_double() function. Correctly changed all 'double's to 'float's. + +- Limit pin internal pull-resistors now enabled. Normal high operation. +This will be the standard going forward. + +- Updated all of the 'double' variable types to 'float' to reflect what +happens when compiled for the Arduino. Also done for compatibility +reasons to @jgeisler0303 's Grbl simulator code. + +- G-code parser will now ignore 'E' exponent values, since they are +reserved g-code characters for some machines. Thanks @csdexter! + +- The read_double() function was re-written and optimized for use in +Grbl. The strtod() avr lib was removed. + + +---------------- +Date: 2012-09-30 +Author: Sonny Jeon +Subject: Updated limit/homing routine. Works, but needs more TLC. + +- Added acceleration to the homing routine. + +- Homing now accounts for different step rates when moving multiple +axes without exceeding acceleration limits. + +- Homing now updates all internal positioning variables to machine zero +after completion. + +- "Poor-man's" debounce delay added. + +- Updated the delay_us() function to perform faster and more accurate +microsecond delays. Previously, the single increments would add +noticeable time drift for larger delays. + +- Fix a bug in the stepper.c prescalar calculations that was changed in +the last commit. + +- Other minor fixes. + + +---------------- +Date: 2012-09-21 +Author: Sonny Jeon +Subject: Minor prescalar optimization. Changed up some defines. + + +---------------- +Date: 2012-09-21 +Author: Sonny Jeon +Subject: Added coolant control (M7*, M8, M9). Mist control can be enabled via config.h. + +- Added coolant control! Flood control (M8) functions on analog pin 0. +Mist control (M7) is compile-time optional and is on analog pin 1. (Use +only if you have multiple coolants on your system). Based on work by +@openpnp. + +- Fixed some variable assignments in spindle control. + + +---------------- +Date: 2012-09-21 +Author: Sonny Jeon +Subject: Merge pull request #120 from tmpvar/configurable-makefile + +Add support for overriding DEVICE and PROGRAMMER + +---------------- +Date: 2012-09-21 +Author: Elijah Insua +Subject: Add support for overriding DEVICE and PROGRAMMER + +By setting environment variables. + +example: PROGRAMMER=-c arduino -P /dev/tty.usbmodemfa131 make flash + + +---------------- +Date: 2012-09-19 +Author: Sonny Jeon +Subject: M30 minor bug fix. + +Order of operations was off. Now works as intended, + + +---------------- +Date: 2012-06-27 +Author: Sonny Jeon +Subject: No changes. Github commit bug. + + +---------------- +Date: 2012-06-26 +Author: Sonny Jeon +Subject: Added step pulse delay after direction set (Compile-time option only). Updated read me. + +Added a compile-time only experimental feature that creates a +user-specified time delay between a step pulse and a direction pin set +(in config.h). This is for users with hardware-specific issues +(opto-couplers) that need more than a few microseconds between events, +which can lead to slowly progressing step drift after many many +direction changes. We suggest to try the hack/fix posted in the Wiki +before using this, as this experimental feature may cause Grbl to take +a performance hit at high step rates and about complex curves. + + +---------------- +Date: 2012-03-10 +Author: Sonny Jeon +Subject: Minor fix related to spindle_stop() crashing abort in certain cases. + +- Updated spindle_stop() to fix abort bug and to be more in line with +v0.8. + + +---------------- +Date: 2012-03-05 +Author: Sonny Jeon +Subject: Minor updates. + +- Updated makefile to be more universally compatible by not requiring +grep or ruby. + +- Edited XON/XOFF flow control usage, noting that FTDI-based Arduinos +are known to work, but not Atmega8U2-based Arduino. Still officially +not supported, but added for advanced users. + +- Minor edits. + + +---------------- +Date: 2012-02-25 +Author: Sonny Jeon +Subject: Minor include related compile fix. Added experimental XON/XOFF flow control. Not officially supported! + +- A latency issue related to USB-to-serial converters on the Arduino +does not allow for XON/XOFF flow control to work correctly on standard +terminal programs. It seems that only specialized UI's or avoiding the +USB port all together solves this problem. However, XON/XOFF flow +control is added for advanced users only as a compile-time option. This +feature is officially *NOT* supported by grbl, but let us know of any +successes with it! + + +---------------- +Date: 2012-02-12 +Author: Sonny Jeon +Subject: Spindle DDR pins init minor fix. + + +---------------- +Date: 2012-02-11 +Author: Sonny Jeon +Subject: Fix to enable spindle DDR ports. + +---------------- +Date: 2012-02-11 +Author: Sonny Jeon +Subject: Minor compiler compatibility update for _delay_us(). + + +---------------- +Date: 2012-02-11 +Author: Sonny Jeon +Subject: G54 work coordinate support (w/ G10,G92.1). Re-factored g-code parser with error checking. Minor compiler compatibility changes. + +- G54 work coordinate system support. Up to 6 work coordinate systems +(G54-G59) available as a compile-time option. + +- G10 command added to set work coordinate offsets from machine +position. + +- G92/G92.1 position offsets and cancellation support. Properly follows +NIST standard rules with other systems. + +- G53 absolute override now works correctly with new coordinate systems. + +- Revamped g-code parser with robust error checking. Providing user +feedback with bad commands. Follows NIST standards. + +- Planner module slightly changed to only expected position movements +in terms of machine coordinates only. This was to simplify coordinate +system handling, which is done solely by the g-code parser. + +- Upon grbl system abort, machine position and work positions are +retained, while G92 offsets are reset per NIST standards. + +- Compiler compatibility update for _delay_us(). + +- Updated README. + + +---------------- +Date: 2012-01-31 +Author: Sonny Jeon +Subject: printFloat rounding fix. Affected settings. Recommend using new build. + +printFloat was printing incorrectly and adding a value of 5 to every +float instead of 0.0005 when rounding to 3 decimal places. The printed +settings values do not accurately portray the actual stored value. +Recommend using newly posted build. + + +---------------- +Date: 2012-01-28 +Author: Sonny Jeon +Subject: Program stop support (M0,M1*,M2,M30*), proper position retainment upon reset, misc minor updates. + +- Program stop support (M0,M1*,M2,M30*). *Optional stop to be done. +*Pallet shuttle not supported. + +- Work position is set equal to machine position upon reset, as +according to NIST RS274-NGC guidelines. G92 is disabled. + +- Renamed mc_set_current_position() to mc_set_coordinate_offset(). + +- Fixed bug in plan_synchronize(). Would exit right before last step is +finished and caused issues with program stops. Now fixed. + +- Spindle now stops upon a run-time abort command. + +- Updated readme and misc upkeeping. + + +---------------- +Date: 2012-01-27 +Author: Sonny Jeon +Subject: Streaming script argparse bugfix. + + +---------------- +Date: 2012-01-27 +Author: Sonny Jeon +Subject: Updated streaming scripts. Compiler compatibility for _delay_ms(). + +- Moved obsolete streaming scripts to folder for reference. + +- Added a more complex Python streaming script which uses the serial +buffer as an additional streaming buffer. + +- Removed all references to a _delay_ms(variable) to allow for better +porting across different compilers. + diff --git a/doc/log/commit_log_v0.9g.txt b/doc/log/commit_log_v0.9g.txt new file mode 100644 index 0000000..bb9f107 --- /dev/null +++ b/doc/log/commit_log_v0.9g.txt @@ -0,0 +1,2409 @@ +---------------- +Date: 2014-09-05 +Author: Sonny Jeon +Subject: Minor bug fix and CPU pin map update. + +- Sometime I HATE github. This push is just here to be able to describe +the last two pushes today that had a merging conflict and lost all of +the commit comments before. + +- Setting $10 would cause $11 to be the same value. Missed a break +statement in the switch-case. Oops! Now fixed. + +- CPU pin map for the future versions of Grbl introduced, but not yet +finalized. Still working on it and it’s subject to change. + +- Added a new high-speed machining test g-code routine written by Todd +Fleming. Mills a pocket at 15,000mm/min. Do not use when connected to +your machine! You’ve been warned! + + +---------------- +Date: 2014-09-05 +Author: Sonny Jeon +Subject: Updated README.md + + +---------------- +Date: 2014-09-05 +Author: Sonny Jeon +Subject: Merge branch 'master' of https://github.com/grbl/grbl + +Conflicts: + README.md + + +---------------- +Date: 2014-08-24 +Author: Sonny Jeon +Subject: Merge pull request #472 from BinaryConstruct/edge + +Add defaults for OX CNC + +---------------- +Date: 2014-08-24 +Author: BinaryConstruct +Subject: Add defaults for OX CNC + + +---------------- +Date: 2014-08-22 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-22 +Author: Sonny Jeon +Subject: Updated build date. + + +---------------- +Date: 2014-08-22 +Author: Sonny Jeon +Subject: WPos report bug fix when MPos disabled. + + +---------------- +Date: 2014-08-18 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-17 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-17 +Author: Sonny Jeon +Subject: Updated bitly link to master firmware + + +---------------- +Date: 2014-08-17 +Author: Sonny Jeon +Subject: Merge branch 'master' into edge + + +---------------- +Date: 2014-08-17 +Author: Sonny Jeon +Subject: Final minor updates for master release. + +- Updated ShapeOko2 defaults based on machine testing of the basic +model provided by Inventables. (or close to it.) Should be pretty +conservative but much faster than before. For example, X and Y axes are +set at (10x) faster at 5000mm/min. It can run much faster than this, +but this seems like a safe speed for everyone. + +- Updated README for master release. + +- Added some new settings methods for clearing the EEPROM when changing +versions. Needs some more work, but it should ok for master release. +Should work on it more for the next version. + + +---------------- +Date: 2014-08-13 +Author: Sonny Jeon +Subject: Added EEPROM force clear. + +- When updating from v0.8, the settings will wipe the startup lines and +build info locations so that it won’t use whatever is already there in +the EEPROM. Parameters (coord offsets) are retained. They should be ok +during an upgrade. + + +---------------- +Date: 2014-08-13 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-13 +Author: Sonny Jeon +Subject: G28/30 bug fix. Block '$$' during cycle. SO2 defaults. + +- A G28/30 bug would cause it to move to machine coordinate [0,0,0] if +no axis words were sent. It was a typo in the new g-code parser. Fixed +and slightly re-written to be more consistent with the program flow. + +- Updated the ShapeOko2 defaults based on testing on the real machine. +A little conservative, but it might change again after some more +testing. + +- Now blocks ‘$$’ command during a motion, because the printout takes +too long and can starve the segment buffer. + + +---------------- +Date: 2014-08-08 +Author: Sonny Jeon +Subject: XON/XOFF flow control variable typo. + + +---------------- +Date: 2014-08-07 +Author: Sonny Jeon +Subject: Moved Grbl Sim to its own repo. + + +---------------- +Date: 2014-08-07 +Author: Sonny Jeon +Subject: Updated licensing + + +---------------- +Date: 2014-08-05 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-05 +Author: Sonny Jeon +Subject: Fixed bug related to very very low feed rates. + +- A very very low feed rate command like `G1 X100 F0.01` would cause +some floating-point round-off error and freeze Grbl into an infinite +loop. To fix it, introduced a MINIMUM_FEED_RATE parameter in config.h +to ensure motions always complete. + +- MINIMUM_FEED_RATE is set at 1.0 mm/min by default. It’s recommended +that no rates are below this value, but 0.1mm/min may be ok in some +situations. + + +---------------- +Date: 2014-08-04 +Author: Sonny Jeon +Subject: Allow '$$' in check mode. + +- Now allows the ‘$$’ view Grbl settings while in check mode + +- Updated the version build date + + +---------------- +Date: 2014-08-04 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-04 +Author: Sonny Jeon +Subject: Fixed probe position sync error. + +- Restored probe position syncing. Had removed a pull-off motion after +a probe cycle completes, but ended up de-synchronizing the g-code +parser and probing cycle positions. Putting the pull-off motion back +fixed the problem. + + +---------------- +Date: 2014-08-03 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-03 +Author: Sonny Jeon +Subject: Probing cycle and view build info bug fixes. + +- Probing cycle would drop into a QUEUED state, if multiple G38.2 are +sent. It would not honor the auto cycle start flags. To fix, the auto +cycle start state is saved at the beginning of the probing cycle and +restored at the end, since the feed hold it uses to stop a triggered +probe will disable the auto start flag. For now it’s a patch, rather +than a permanent fix. + +- protocol_buffer_synchronize() also has a failure case. Auto cycle +start does not get executed when the system is waiting in here, so if +it’s in a QUEUED state already, it won’t resume. Patched here, but not +fully resolved. + +- Fixed a problem with the “view build info” command. The EEPROM write +would do weird things and corrupt the EEPROM. Not sure exactly what +caused it, but it’s likely a compiler problem with an improperly +defined EEPROM address. It didn’t have enough room to store a full +string. To fix, the build info EEPROM range was increased and the max +number of STARTUP_BLOCKS was reduced to 2 from 3. + +- Lastly, when a $I view build info is used for the first time, it +would normally show an EEPROM read error, since it wasn’t cleared or +wasn’t therein the first place. It will now not show that error. A +patch rather than a permanent fix again. + + +---------------- +Date: 2014-08-01 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-08-01 +Author: Sonny Jeon +Subject: Minor bug fixes. + +- Bug fix for step and direction invert masks not immediately being in +effect. Now regenerates the masks when a user changes this setting. + +- Bug fix for probing cycle. G-code standard mandates that there is an +error if the probe is already triggered when the cycle is commanded. +However, Grbl may have motions to pull off a previous probing cycle in +queue and can falsely lead to errors. To fix this, the triggered check +is performed within the probing cycle itself, right after the planner +buffer is synced. If there is an error, it will now alarm out as a +probe fail. + + +---------------- +Date: 2014-07-28 +Author: Sonny Jeon +Subject: Compile in Atmel Studio fix. + + +---------------- +Date: 2014-07-28 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-07-27 +Author: Sonny Jeon +Subject: Added build info feedback in help + +- `$I` prints the Grbl build info and version number. NOTE: `$I=xxx` +stores an additional 30 character string into EEPROM, which will be +printed with the build info the next time it’s run. This is for +identification purposes for users that have more than one system using +Grbl. + + +---------------- +Date: 2014-07-26 +Author: Sonny Jeon +Subject: Updates to allow Arduino IDE direct compiling. + +- Only minor changes were required to make the Arduino IDE compile all +of the Grbl’s source code (correctly using the C-compiler). Tested in +Windows and Mac and with the normal USB upload and with a programmer. + + +---------------- +Date: 2014-07-26 +Author: Sonny Jeon +Subject: Settings refactoring. Bug fixes. Misc new features. + +This is likely the last major change to the v0.9 code base before push +to master. Only two minor things remain on the agenda (CoreXY support, +force clear EEPROM, and an extremely low federate bug). + +- NEW! Grbl is now compile-able and may be flashed directly through the +Arduino IDE. Only minor changes were required for this compatibility. +See the Wiki to learn how to do it. + +- New status reporting mask to turn on and off what Grbl sends back. +This includes machine coordinates, work coordinates, serial RX buffer +usage, and planner buffer usage. Expandable to more information on user +request, but that’s it for now. + +- Settings have been completely renumbered to allow for future new +settings to be installed without having to constantly reshuffle and +renumber all of the settings every time. + +- All settings masks have been standardized to mean bit 0 = X, bit 1 = +Y, and bit 2 = Z, to reduce confusion on how they work. The invert +masks used by the internal Grbl system were updated to accommodate this +change as well. + +- New invert probe pin setting, which does what it sounds like. + +- Fixed a probing cycle bug, where it would freeze intermittently, and +removed some redundant code. + +- Homing may now be set to the origin wherever the limit switches are. +Traditionally machine coordinates should always be in negative space, +but when limit switches on are on the opposite side, the machine +coordinate would be set to -max_travel for the axis. Now you can always +make it [0,0,0] via a compile-time option in config.h. (Soft limits +routine was updated to account for this as well.) + + - Probe coordinate message immediately after a probing cycle may now +be turned off via a compile-time option in config.h. By default the +probing location is always reported. + +- Reduced the N_ARC_CORRECTION default value to reflect the changes in +how circles are generated by an arc tolerance, rather than a fixed arc +segment setting. + +- Increased the incoming line buffer limit from 70 to 80 characters. +Had some extra memory space to invest into this. + +- Fixed a bug where tool number T was not being tracked and reported +correctly. + +- Added a print free memory function for debugging purposes. Not used +otherwise. + +- Realtime rate report should now work during feed holds, but it hasn’t +been tested yet. + +- Updated the streaming scripts with MIT-license and added the simple +streaming to the main stream.py script to allow for settings to be sent. + +- Some minor code refactoring to improve flash efficiency. Reduced the +flash by several hundred KB, which was re-invested in some of these new +features. + + +---------------- +Date: 2014-07-17 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-07-12 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-07-12 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-07-12 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-07-12 +Author: Sonny Jeon +Subject: Updated README + + +---------------- +Date: 2014-07-11 +Author: Sonny Jeon +Subject: Updated README + + +---------------- +Date: 2014-07-11 +Author: Sonny Jeon +Subject: Merge pull request #441 from ashelly/edge-simfix + +Fixes for simulator in alternate configurations. + +---------------- +Date: 2014-07-10 +Author: ashelly +Subject: Restore changes made only for testing. + + +---------------- +Date: 2014-07-10 +Author: ashelly +Subject: Bug fixes for timers, added some wdt support for limit debounce. + +- Typo in timer def, +- Handle 8 bit timers correctly, +- Don't skip TOP count in CTC mode +- added SREG for atomic bit operations + + +---------------- +Date: 2014-07-09 +Author: Sonny Jeon +Subject: Merge branch 'dev' into edge + +Conflicts: + sim/simulator.c + sim/simulator.h + + +---------------- +Date: 2014-07-09 +Author: Sonny Jeon +Subject: Added test g-code programs. + + +---------------- +Date: 2014-07-06 +Author: Sonny Jeon +Subject: Version and build update. + +- Incremented from v0.9e to v0.9f due to the new g-codes, velocity +reporting option, decimal printing refactoring, grbl-sim updates, and +G0/G1 bug fix. + +- Settings version was also incremented since settings.decimal_places +is now gone. + + +---------------- +Date: 2014-07-06 +Author: Sonny Jeon +Subject: Isolate atomic bit flag for execution. + +- Denoted bit_true_atomic only for sys.execute bit settings. All other +bit_true type calls are for local variables only and don’t need atomic +access. Still looking into other ways of setting these flags without +requiring atomic access, but this is a patch for now. + + +---------------- +Date: 2014-07-06 +Author: Sonny Jeon +Subject: Merge pull request #436 from kfoltman/dev + +Fixed atomic access to flags in sys.execute. + +---------------- +Date: 2014-07-06 +Author: Sonny Jeon +Subject: Syntax fix for gcode.c + +- Whoops! Missed a bracket and it wasn’t compiling. Now fixed. + +- Updated the unsupported gcodes listed at the end of the gcode.c file. + + +---------------- +Date: 2014-07-06 +Author: Sonny Jeon +Subject: G43.1/G49 tool length offset installed. Minor bug fix. + +- Minor bug fix that caused G92.1 not to work. The mantissa of G92.1 +was not computed correctly due to floating point round-off errors and +the use of trunc(). Fixed it by changing the computation with round(). + +- Installed tool length offsets with G43.1 and G49! True tool length +offsets via G43 are not supported, because these require us to store +tool data that we don’t have space for. But we’ve come up with a good +solution for users that need this. Instead we are strictly using the +dynamic version G43.1 via linuxcnc.org. Visit their website for more +details on the command. + +- G43.1 operates by requiring an axis word and value to offset the +configured tool length axis, which can be configured for any axis +(default Z-axis) in config.h. For example, ```G43.1 Z0.5``` will offset +the work coordinates from Z0.0 to Z-0.5. + +- G49 will cancel the last tool length offset value and reset it to +zero. + +- Tweaked the ‘$#’ parameters report. `Probe` is now `PRB` and a new +value `TLO` states the tool length offset value. + + +---------------- +Date: 2014-07-05 +Author: Sonny Jeon +Subject: Merge branch 'ashelly-sim-update' into dev + + +---------------- +Date: 2014-07-05 +Author: Sonny Jeon +Subject: Merge grbl-sim updates for v0.9. + +- Removed some conflicting code in the main Grbl firmware source. + +- Temporary patch for coolant and spindle control with streaming +applied. + + +---------------- +Date: 2014-07-05 +Author: Sonny Jeon +Subject: New G43.1/G49 gcodes. Not working yet!! + +- Pushed this uncompleted code to merge a conflicting pull request. + +- New G43.1 and G49 g-codes to be installed. The beginnings of it are +in place. These g-codes are intended to be used in conjunction with +probing and allow GUIs to set tool length offsets without Grbl needing +to store a tool table. + +- G43.1 is defined as a dynamic tool length offset that is not stored +in memory. Rather, when commanded, these are applied to the work +coordinates until a reset or disabled by G49. This works much like G92. + + +---------------- +Date: 2014-07-05 +Author: ashelly +Subject: formatting + +---------------- +Date: 2014-07-05 +Author: ashelly +Subject: Update readme.md + +---------------- +Date: 2014-07-04 +Author: ashelly +Subject: Don't need kbhit.h + +---------------- +Date: 2014-07-04 +Author: Adam Shelly +Subject: minor tweaks for mingw. + + +---------------- +Date: 2014-07-04 +Author: Sonny Jeon +Subject: Realtime rate reporting. Updated decimal places. + +- Added a new optional compile-time feature for ‘realtime’ (within +50ms) feed rate reporting. When querying for a status report, a new +data value will state the current operating rate. It’s only beta at the +moment and has some kinks to work out. + +- Updated the code for printing floating point values to N decimal +places. Generalized the main floating point print code to accept a new +decimal places value and created a set of handler functions to print +certain floating point value types used in Grbl, like position, rates, +coordinate offsets, etc. All of these have different decimal +requirements and change when printed in mm or inches mode. + +- Number of decimal places for the different value types can be +re-defined in config.h, but there shouldn’t be a need for this, as +these are physically limited. + +- Removed the decimal places settings, as this was now obsoleted by the +new decimal places code. + +- The new decimal places code also saves almost 300kB in flash space, +as it’s more efficient. + + +---------------- +Date: 2014-07-04 +Author: ashelly +Subject: reduce diffs with dev branch + + +---------------- +Date: 2014-07-04 +Author: ashelly +Subject: Total rework of simulator for dev branch. Create separate thread for interrupt processes. Tick-accurate simulation of timers. Non-blocking character input for running in realtime mode. Decouple hardware sim from grbl code as much as possible. Expanded command line options. Provisions for cross-platform solution. + + +---------------- +Date: 2014-07-03 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-07-03 +Author: Sonny Jeon +Subject: G18 reporting bug fix. + +- G18 wasn’t getting reported back to the user correctly, even though +it has been set internally. Fixed the reporting code to reflect this +accurately. + + +---------------- +Date: 2014-07-03 +Author: Sonny Jeon +Subject: G-code parser G0/G1 bug fix. + +- Although stated as invalid in the NIST g-code standard, most g-code +parsers, including linuxcnc, allow G0 and G1 to be commanded without +axis words present. For example, something like ‘G1 F100.0’ to preset +the motion mode and feed rate without a motion commanded. Older CNC +controllers actually required this for feed rate settings. This update +should now allow this type of behavior. + + +---------------- +Date: 2014-07-02 +Author: Sonny Jeon +Subject: Minor bug fixes and updates. Line number tracking. + +- Line number tracking was getting truncated at 255, since it was using +wrong variable type. Fixed it with a trunc(). + +- Increased the max number line allowed by Grbl to 9999999 from the +g-code standard 99999. The latter seems to be an arbitrary number, so +we are allowing larger ones for at least one known use case scenario. + +- Created a new test directory to contain some testing g-code to proof +the firmware. Only got started with one test case so far. More will be +inserted as needed. + +- Some other commenting updates to clarify certain aspects of the code. + + +---------------- +Date: 2014-06-26 +Author: Krzysztof Foltman +Subject: Fixed atomic access to flags in sys.execute. + +This seems to fix the bug that caused Grbl to hang during some operations, +especially jogging. + + +---------------- +Date: 2014-05-31 +Author: Sonny Jeon +Subject: Arc error-checking update. + +- Updated offset-mode arc error-checking to EMC2’s version: The old +NIST definition required the radii to the current location and target +location to differ no more than 0.002mm. This proved to be problematic +and probably why LinuxCNC(EMC2) updated it to be 0.005mm AND 0.1% +radius OR 0.5mm. + + +---------------- +Date: 2014-05-31 +Author: Sonny Jeon +Subject: Various minor g-code parser fixes. + +- Updated the mantissa calculation that checks for non-integer values +and GXX.X commands that aren’t supported. There was a potential uint8 +overflow issue. + +- Fixed g-code parser bug related to not using the correct modal +struct. G10 P0 not selecting the current coordinate system when a +G55-59 is issued in the same line. + +- Fixed g-code parser bug related to not using the correct modal +struct. Target position locations were not computed correctly when +G90/91 distance modes were changed in the same line. It was using the +previous state, rather than the current block. + + +---------------- +Date: 2014-05-29 +Author: Sonny Jeon +Subject: Fixed spindle/coolant/dwell state check. + + +---------------- +Date: 2014-05-25 +Author: Sonny Jeon +Subject: Major g-code parser overhaul. 100%* compliant. Other related updates. + +- Completely overhauled the g-code parser. It’s now 100%* compliant. (* +may have some bugs). Being compliant, here are some of the major +differences. + +- SMALLER and JUST AS FAST! A number of optimizations were found that +sped things up and allowed for the more thorough error-checking to be +installed without a speed hit. Trimmed a lot of ‘fat’ in the parser and +still was able to make it significantly smaller than it was. + +- No default feed rate setting! Removed completely! This doesn’t exist +in the g-code standard. So, it now errors out whenever it’s undefined +for motions that require it (G1/2/3/38.2). + +- Any g-code parser error expunges the ENTIRE block. This means all +information is lost and not passed on to the running state. Before some +of the states would remain, which could have led to some problems. + +- If the g-code block passes all of the error-checks, the g-code state +is updated and all motions are executed according to the order of +execution. + +- Changes in spindle speed, when already running, will update the +output pin accordingly. This fixes a bug, where it wouldn’t update the +speed. + +- Update g-code parser error reporting. Errors now return detailed +information of what exact went wrong. The most common errors return a +short text description. For less common errors, the parser reports +‘Invalid gcode ID:20’, where 20 is a error ID. A list of error code IDs +and their descriptions will be documented for user reference elsewhere +to save flash space. + +- Other notable changes: + +- Added a print integer routine for uint8 variables. This saved +significant flash space by switching from a heavier universal print +integer routine. + +- Saved some flash space with our own short hypotenuse calculation + +- Some arc computation flash and memory optimizations. + + +---------------- +Date: 2014-05-18 +Author: Jens Geisler +Subject: Merge pull request #408 from chamnit/master + +MIT-Licensing change. + +---------------- +Date: 2014-05-18 +Author: Sonny Jeon +Subject: MIT-licensing change. + + +---------------- +Date: 2014-05-18 +Author: Sonny Jeon +Subject: MIT-licensing change + + +---------------- +Date: 2014-04-28 +Author: Sonny Jeon +Subject: Merge pull request #391 from paulkaplan/master + +Update Shapeoko 2 defaults + +---------------- +Date: 2014-04-14 +Author: Paul Kaplan +Subject: updated shapeoko2 defaults + + +---------------- +Date: 2014-03-14 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-03-13 +Author: Sonny Jeon +Subject: Comment corrections and function call update. + + +---------------- +Date: 2014-03-13 +Author: Sonny Jeon +Subject: Merge pull request #373 from EliteEng/dev + +Added Probing to Mega2560 and fixed Shapeoko2 compile error + +---------------- +Date: 2014-03-11 +Author: Rob Brown +Subject: Added Probing to Mega2560 and fixed Shapeoko2 compile error + + +---------------- +Date: 2014-03-07 +Author: henols +Subject: Probing command gets stuck in hold if several g38.2 are submitted +Ex. +G0 X0 Y0 Z0 +G38.2 Z-10 F100 +G10 L20 P0 Z0 +G0 Z2 +G38.2 Z-1 F50 +G10 L20 P0 Z0 +G0 Z2 +G0 X0 Y0 +G38.2 Z-1 F100 +G0 Z2 + + +---------------- +Date: 2014-03-10 +Author: Sonny Jeon +Subject: Merge pull request #372 from martinstingl/master + +Corrected units of default acceleration values + +---------------- +Date: 2014-03-10 +Author: Martin Stingl +Subject: Corrected units of default acceleration values + + +---------------- +Date: 2014-03-07 +Author: Sonny Jeon +Subject: Merge pull request #368 from henols/dev + +Probing command gets stuck in hold if several g38.2 are submitted + +---------------- +Date: 2014-03-07 +Author: henols +Subject: Probing command gets stuck in hold if several g38.2 are submitted +Ex. +G0 X0 Y0 Z0 +G38.2 Z-10 F100 +G10 L20 P0 Z0 +G0 Z2 +G38.2 Z-1 F50 +G10 L20 P0 Z0 +G0 Z2 +G0 X0 Y0 +G38.2 Z-1 F100 +G0 Z2 + + +---------------- +Date: 2014-02-28 +Author: Sonny Jeon +Subject: G38.2 probe feature rough draft installed. Working but needs testing. + +- G38.2 straight probe now supported. Rough draft. May be tweaked more +as testing ramps up. + +- G38.2 requires at least one axis word. Multiple axis words work too. +When commanded, the probe cycle will move at the last ‘F’ feed rate +specified in a straight line. + +- During a probe cycle: If the probe pin goes low (normal high), Grbl +will record that immediate position and engage a feed hold. Meaning +that the CNC machine will move a little past the probe switch point, so +keep federates low to stop sooner. Once stopped, Grbl will issue a move +to go back to the recorded probe trigger point. + +- During a probe cycle: If the probe switch does not engage by the time +the machine has traveled to its target coordinates, Grbl will issue an +ALARM and the user will be forced to reset Grbl. (Currently G38.3 probe +without error isn’t supported, but would be easy to implement later.) + +- After a successful probe, Grbl will send a feedback message +containing the recorded probe coordinates in the machine coordinate +system. This is as the g-code standard on probe parameters specifies. + +- The recorded probe parameters are retained in Grbl memory and can be +viewed with the ‘$#’ print parameters command. Upon a power-cycle, not +a soft-reset, Grbl will re-zero these values. + +- Moved ‘$#’ command to require IDLE or ALARM mode, because it accesses +EEPROM to fetch the coordinate system offsets. + +- Updated the Grbl version to v0.9d. + +- The probe cycle is subject to change upon testing or user-feedback. + + +---------------- +Date: 2014-02-27 +Author: Sonny Jeon +Subject: Probe cycle line numbers ifdef fixes to get it to compile. + +- Updated some of the ifdefs when disabling line numbers feature. +Getting messy with this compile-time option. This will likely get +cleaned up later. + +- This is just a push to get the new probing code to compile. Testing +and optimization of the code will soon follow and be pushed next. + + +---------------- +Date: 2014-02-27 +Author: Sonny Jeon +Subject: Merge pull request #362 from robgrz/dev + +Minimal probing cycle working. Supports both G38.2 for error and G38.3 ... + +---------------- +Date: 2014-02-26 +Author: Sonny Jeon +Subject: Added grbl planner Matlab simulator for test reference. Updated line number compile-time option. + +- Added a grbl planner simulation tool that was written in Matlab and +Python. It was used to visualize the inner workings of the planner as a +program is streamed to it. The simulation assumes that the planner +buffer is empty, then filled, and kept filled. This is mainly for users +to see how the planner works. + +- Updated some of the compile-time ifdefs when enabling line numbers. +The leaving the un-used line numbers in the function calls eats a +non-neglible amount of flash memory. So the new if-defs remove them. + + +---------------- +Date: 2014-02-25 +Author: Robert Grzesek +Subject: Minimal probing cycle working. Supports both G38.2 for error and G38.3 when no errors are desired. + + +---------------- +Date: 2014-02-19 +Author: Sonny Jeon +Subject: Minor updates to line number feature. + +- Changed line number integer types from unsigned to signed int32. +G-code mandates values cannot exceed 99999. Negative values can be used +to indicate certain modes. + +- Homing cycle line number changed to -1, as an indicator. + +- Fixed a reporting define for the spindle states that was broken by +the last merge. + + +---------------- +Date: 2014-02-19 +Author: Sonny Jeon +Subject: Merge pull request #356 from robgrz/dev + +Line number reporting as compile-time option. + +---------------- +Date: 2014-02-19 +Author: Sonny Jeon +Subject: Commenting updates. Minor bug fix with exit of soft limit event. + + +---------------- +Date: 2014-02-18 +Author: Robert Grzesek +Subject: Merge commit 'cd71a90ce8a770e0030ed6c9bac805b89724e275' into dev + +Conflicts: + limits.c + motion_control.c + report.c + + +---------------- +Date: 2014-02-15 +Author: Sonny Jeon +Subject: Homing and feed hold bug fixes. + +WARNING: Bugs may still exist. This branch is a work in progress and +will be pushed to the edge branch when at beta stability. Use at your +own risk. + +- Homing freezing issue fixed. Had to do with the cycle stop flag being +set incorrectly after the homing cycles and before the pull-off +maneuver. Now resets the stepper motors before this can happen. + +- Fixed an issue with a rare feed hold failure. Had to do with feed +hold ending exactly at the end of a block. The runtime protocol now +sets the QUEUED and IDLE states appropriately when this occurs. Still +need to clean this code up however, as it’s patched rather than written +well. + +- Updated version build via $I command. + +- Forgot to comment on a new feature for the last commit. Since steps +are integers and millimeters traveled are floats, the old step segment +generator ignored the step fraction differences in generating the +segment velocities. Didn’t see like it would be much of a big deal, but +there were instances that this would be a problem, especially for very +slow feed rates. The stepper algorithm now micro-adjusts the segment +velocities based on the step fractions not executed from the previous +segment. This ensures that Grbl generates the velocity profiles EXACTLY +and noticeably improves overall acceleration performance. + + +---------------- +Date: 2014-02-09 +Author: Sonny Jeon +Subject: Refactoring and lots of bug fixes. Updated homing cycle. + +WARNING: There are still some bugs to be worked out. Please use caution +if you test this firmware. + +- Feed holds work much better, but there are still some failure +conditions that need to be worked out. This is the being worked on +currently and a fix is planned to be pushed next. + +- Homing cycle refactoring: Slight adjustment of the homing cycle to +allow for limit pins to be shared by different axes, as long as the +shared limit pins are not homed on the same cycle. Also, removed the +LOCATE_CYCLE portion of the homing cycle configuration. It was +redundant. + +- Limit pin sharing: (See above). To clear up one or two limit pins for +other IO, limit pins can now be shared. For example, the Z-limit can be +shared with either X or Y limit pins, because it’s on a separate homing +cycle. Hard limit will still work exactly as before. + +- Spindle pin output fixed. The pins weren’t getting initialized +correctly. + +- Fixed a cycle issue where streaming was working almost like a single +block mode. This was caused by a problem with the spindle_run() and +coolant_run() commands and issuing an unintended planner buffer sync. + +- Refactored the cycle_start, feed_hold, and other runtime routines +into the runtime command module, where they should be handled here +only. These were redundant. + +- Moved some function calls around into more appropriate source code +modules. + +- Fixed the reporting of spindle state. + + +---------------- +Date: 2014-02-06 +Author: Robert Grzesek +Subject: Made line number reporting optional via config.h + + +---------------- +Date: 2014-02-06 +Author: Robert Grzesek +Subject: Initial line number reporting + + +---------------- +Date: 2014-02-02 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-01-28 +Author: Jens Geisler +Subject: Merge pull request #337 from michmerr/edge + +Make sure that cycle_start state is set before simulating steps. + +---------------- +Date: 2014-01-28 +Author: michmerr +Subject: Simplify setting of STATE_CYCLE and ISR interval. + +Set sys.state to STATE_CYCLE directly instead of calling back to +st_wakeup(). + +Convert get_step_time() to a constant and rename it to ISR_INTERVAL. + + +---------------- +Date: 2014-01-22 +Author: michmerr +Subject: Make sure that cycle_start state is set before simulating steps. + + +---------------- +Date: 2014-01-15 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-01-14 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-01-10 +Author: Sonny Jeon +Subject: Lots of re-organization and cleaning-up. Some bug fixes. + +- Added a new source and header file called system. These files contain +the system commands and variables, as well as all of the system headers +and standard libraries Grbl uses. Centralizing some of the code. + +- Re-organized the include headers throughout the source code. + +- ENABLE_M7 define was missing from config.h. Now there. + +- SPINDLE_MAX_RPM and SPINDLE_MIN_RPM now defined in config.h. No +uncommenting to prevent user issues. Minimum spindle RPM now provides +the lower, near 0V, scale adjustment, i.e. some spindles can go really +slow so why use up our 256 voltage bins for them? + +- Remove some persistent variables from coolant and spindle control. +They were redundant. + +- Removed a VARIABLE_SPINDLE define in cpu_map.h that shouldn’t have +been there. + +- Changed the DEFAULT_ARC_TOLERANCE to 0.002mm to improve arc tracing. +Before we had issues with performance, no longer. + +- Fixed a bug with the hard limits and the software debounce feature +enabled. The invert limit pin setting wasn’t honored. + +- Fixed a bug with the homing direction mask. Now is like it used to +be. At least for now. + +- Re-organized main.c to serve as only as the reset/initialization +routine. Makes things a little bit clearer in terms of execution +procedures. + +- Re-organized protocol.c as the overall master control unit for +execution procedures. Not quite there yet, but starting to make a +little more sense in how things are run. + +- Removed updating of old settings records. So many new settings have +been added that it’s not worth adding the code to migrate old user +settings. + +- Tweaked spindle_control.c a bit and made it more clear and consistent +with other parts of Grbl. + +- Tweaked the stepper disable bit code in stepper.c. Requires less +flash memory. + + +---------------- +Date: 2014-01-05 +Author: Sonny Jeon +Subject: Updates to some stepper algorithm commenting + + +---------------- +Date: 2014-01-05 +Author: Sonny Jeon +Subject: New build info feature. (per @Analogreality request) + +- New build info feature. Hidden command ‘$I’ will print the build info +for your Grbl firmware. Users may also write an identifying message +within it via ‘$I=‘ with up to 32 characters. (no more, or else it will +break). + +- Adjusted the max number of startup lines to 3. Majority of people +will only need one. + +- Fixed a compile error with spindle_control.c. A rogue #endif was +causing problems. + + +---------------- +Date: 2014-01-04 +Author: Sonny Jeon +Subject: Variable spindle output. Resolved conflicts in last push. + +Resolve conflicts. + + +---------------- +Date: 2014-01-04 +Author: Sonny Jeon +Subject: Cleaned up variable spindle output (PWM). Code and config comments. + +- Variable spindle speed output as a configuration option. Thanks +@EliteEng! When enabled, the Z-limit (D11) and spindle enable(D12) pins +switch to allow access to the hardware PWM output on pin D11. +Otherwise, everything should work as it does. + +- Removed option for inverting the spindle and coolant enable pins. +This is a safety hazard, especially for the spindle. When Grbl +initializes, all pins are momentarily low until it finishes booting. If +an invert is enabled, this means the spindles can be energized briefly +during this time. If users need signal inversion, it’s recommended to +just wire in an inversion circuit instead. + +- Cleared out references to spindle variable output in terms of step +signal. This isn’t complete and requires more deliberation before +installing. + +- Cleared up and cleaned up some code and config comments. + + +---------------- +Date: 2014-01-03 +Author: Sonny Jeon +Subject: Merge pull request #322 from EliteEng/dev + +Update to fix compile error + +---------------- +Date: 2014-01-03 +Author: Rob Brown +Subject: Update to fix compile error + +Update to fix compile error + + +---------------- +Date: 2014-01-02 +Author: Sonny Jeon +Subject: Merge pull request #318 from EliteEng/dev + +PWM Spindle Control and Invert Spindle & Coolant Pins + +---------------- +Date: 2014-01-03 +Author: Rob Brown +Subject: Update spindle_control.c + +Updated spindle_control.c due to compile error. + +---------------- +Date: 2014-01-02 +Author: Sonny Jeon +Subject: Fix for M7/8/9 modal group checks. Updated AMASS frequency cutoffs and code cleaned. + +- Updated Grbl version to 0.9c and build number. + +- G-code parser was missing modal group violation checks for M7/8/9 +commands. Added them. + +- Updated the Adaptive Multi-Axis Step Smoothing (AMASS) cutoff +frequencies so that the trade between the 16-bit Timer1 accuracy and +the level step smoothing are somewhat better balanced. (Smoothing isn’t +free, but a higher accuracy timer would provide high cutoff +frequencies.) + + +---------------- +Date: 2014-01-02 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-01-02 +Author: Rob Brown +Subject: PWM Spindle Control and Invert Spindle & Coolant Pins + +PWM Spindle Control and Invert Spindle & Coolant Pins + + +---------------- +Date: 2013-12-30 +Author: Sonny Jeon +Subject: Minor bug fixes: Homing travel calculations. Cycle resuming after spindle and dwell commands. + +- Homing travel calculations fixed. It was computing the min travel +rather than max. + +- Auto-start disable and pausing after spindle or dwell commands. +Related to plan_synchronize() function call. Now fixed, but still need +to work on the system state. + +- Pushed a fix to make this branch more Arduino IDE compatible. Removed +extern call in nuts_bolts.c + +- Updated the stepper configuration option of enabling or disabling the +new Adaptive Multi-Axis Step Smoothing Algorithm. Now works either way. + +- Updated some copyright info. + + +---------------- +Date: 2013-12-30 +Author: Sonny Jeon +Subject: Merge pull request #201 from Protoneer/master + +Made a few changes to make the code compatible with the Arduino IDE. Sorry about the tardiness! + +---------------- +Date: 2013-12-30 +Author: Sonny Jeon +Subject: Incomplete push but working. Lots more stuff. More to come. + +- NEW! An active multi-axis step smoothing algorithm that automatically +adjusts dependent on step frequency. This solves the long standing +issue to aliasing when moving with multiple axes. Similar in scheme to +Smoothieware, but more advanced in ensuring a more consistent CPU +overhead throughout all frequencies while maintaining step exactness. + +- Switched from Timer2 to Timer0 for the Step Port Reset Interrupt. +Mainly to free up hardware PWM pins. + +- Seperated the direction and step pin assignments, so we can now move +them to seperate ports. This means that we can more easily support 4+ +axes in the future. + +- Added a setting for inverting the limit pins, as so many users have +request. Better late than never. + +- Bug fix related to EEPROM calls when in cycle. The EEPROM would kill +the stepper motion. Now protocol mandates that the system be either in +IDLE or ALARM to access or change any settings. + +- Bug fix related to resuming the cycle after a spindle or dwell +command if auto start has been disabled. This fix is somewhat temporary +or more of a patch. Doesn’t work with a straight call-response +streaming protocol, but works fine with serial buffer pre-filling +streaming that most clients use. + +- Renamed the pin_map.h to cpu_map.h to more accurately describe what +the file is. + +- Pushed an auto start bug fix upon re-initialization. + +- Much more polishing to do! + + +---------------- +Date: 2013-12-29 +Author: Sonny Jeon +Subject: Incomplete dev code push, but working. Lots of updates/fixes/improvements. Much still to polish. + +- Ugh. Github just erased my list of improvements and changes due to a +conflict and forcing me to resolve it. Hope this goes through. + +- Major stepper algorithm change. Trashed the old v0.9 edge +branch-style stepper algorithm. It’s fine, but it was susceptible to +aliasing noise when moving very slow or very fast. It also had a bit of +CPU overhead. It was written to solve a standing issue with v0.8 +master, where it couldn’t generate a smooth acceleration abocve +10-15kHz. But, with new step segment buffer in v0.9c, it inadvertently +fixed the acceleration problem with v0.8 stepper algorithm. So, what +does it mean for you? Smoother stepper pulses and likely higher step +frequencies. + +- Stepper algorithm now uses Timer1 and Timer2, instead of Timer0 and +Timer2. Timers 0 and 2 can be swapped if there is an issue. + +- With the old v0.8 stepper algorithm, the STEP_DELAY_PULSE +configuration option is also back. + +- NEW! Hard limit software debouncing. Grbl now employs the AVR’s +watchdog timer as a way to monitor the hard limit pins and checking +their states after a delay. This is a simple software debouncing +technique and may help alleviate some of the false trigger some users +have been complaining about. BUT, this won’t fix electric noise issues! + +- Fixed an issue with the new homing cycle routine where it wasn’t +honoring the acceleration and axis speed limits depending on the homing +cycle mask. Now does. Also, updated the homing direction mask code to +be a little cleaner. + +- Moved the main part of the homing cycle control and execution to +motion_control.c, where it fits better. + +- Removed the STATE_INIT system state as it was redundant. Made the +system states into bitflags so multiple system states can be checked +via one if statement. + +- Reorganized the power-up routine to work with the new system states. + + +---------------- +Date: 2013-12-29 +Author: Sonny Jeon +Subject: Merge branch 'dev' of https://github.com/grbl/grbl into dev + +Conflicts: + limits.c + + +---------------- +Date: 2013-12-29 +Author: Sonny Jeon +Subject: Merge branch 'dev' of https://github.com/grbl/grbl into dev + +Conflicts: + limits.c + + +---------------- +Date: 2013-12-27 +Author: Sonny Jeon +Subject: Merge pull request #312 from scottrcarlson/dev + +Fixed homing_dir_mask functionality in the re-written homing_cycle. + +---------------- +Date: 2013-12-27 +Author: Scott R Carlson +Subject: Hard Limits configured for active high. + +Added the use of homing_dir_mask to homing_cycle + + +---------------- +Date: 2013-12-10 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2013-12-10 +Author: Sonny Jeon +Subject: Revamped homing cycle. Axis limits and max travel bug fixes. Build info. Refactored config.h. + +- Revamped and improved homing cycle. Now tied directly into the main +planner and stepper code, which enables much faster homing seek rates. +Also dropped the compiled flash size by almost 1KB, meaning 1KB more +for other features. + +- Refactored config.h. Removed obsolete defines and configuration +options. Moved lots of “advanced” options into the advanced area of the +file. + +- Updated defaults.h with the new homing cycle. Also updated the +Sherline 5400 defaults and added the ShapeOko2 defaults per user +submissions. + +- Fixed a bug where the individual axes limits on velocity and +acceleration were not working correctly. Caused by abs() returning a +int, rather than a float. Corrected with fabs(). Duh. + +- Added build version/date to the Grbl welcome message to help indicate +which version a user is operating on. + +- Max travel settings were not being defaulted into the settings EEPROM +correctly. Fixed. + +- To stop a single axis during a multi-axes homing move, the stepper +algorithm now has a simple axis lock mask which inhibits the desired +axes from moving. Meaning, if one of the limit switches engages before +the other, we stop that one axes and keep moving the other. + + +---------------- +Date: 2013-12-10 +Author: Sonny Jeon +Subject: Merge pull request #301 from shapeoko/master + +added shapeoko2 profile + +---------------- +Date: 2013-12-10 +Author: Edward +Subject: added shapeoko2 profile + +shapeoko 2 uses 2mm GT2 belting and 20tooth pulleys + + +---------------- +Date: 2013-12-07 +Author: Sonny Jeon +Subject: Deceleration to zero speed improvements. Update defaults. + +- A minor issue with deceleration ramps when close to zero velocity. +Should be virtually unnoticeable for most CNC systems, but fixed in +this push and accurate to physics. + +- Updated some of the junction deviation defaults. Because the new +stepper algorithm can easily maximize a CNC machine’s capabilities or +simply go much faster, this means the speed in which it enters +junctions has to be a little more constrained. Meaning that, we have to +slow a little bit down more so that we don’t exceed the acceleration +limits of the stepper motors. + + +---------------- +Date: 2013-12-07 +Author: Sonny Jeon +Subject: Pushed bug fixes. Updated readme. + +- G18 plane select fix from XZ-plane to ZX-plane per right hand rule. + +- Added volatile declaration for rx_buffer_tail in serial.c. No real +effect to operation as avr-gcc adds this upon compilation. Helps with +porting issues when using a different compiler. + + +---------------- +Date: 2013-12-07 +Author: Sonny Jeon +Subject: Pushed limits active high option. Updated defaults.h. Misc bug fixes. Cleaned up codebase. + +- Pushed limit switch active high option (i.e. NC switches). + +- Updated defaults.h to be in-line with the new settings. + +- Refactored feed hold handling and step segment buffer to be more +generalized in effort to make adding feedrate overrides easier in the +future. Also made it a little more clean. + +- Fixed G18 plane select issue. Now ZX-plane, rather than XZ-plane, per +right hand rule. + +- Cleaned some of the system settings by more accurately renaming some +of the variables and removing old obsolete ones. + +- Declared serial.c rx_buffer_tail to be volatile. No effect, since +avr-gcc automatically does this during compilation. Helps with porting +when using other compilers. + +- Updated version number to v0.9b. + +- Updates to README.md + + +---------------- +Date: 2013-12-04 +Author: Sonny Jeon +Subject: Reinstated feed holds into new stepper algorithm and planner. Rough draft, but working. + +- Reinstated the feed hold feature with the new stepper algorithm and +new optimized planner. It works, but will be re-factored a bit soon to +clean up the code. + +- At this point, feedrate overrides may need to be installed in the +v1.0 version of grbl, while this version will likely be pushed to the +edge branch soon and pushed to master after the bugs have been squashed. + +- Measured the overall performance of the new planner and stepper +algorithm on an oscilloscope. The new planner is about 4x faster than +before, where it is completing a plan in around 1ms. The stepper +algorithm itself is minutely faster, as it is a little lighter. The +trade-off in the increased planner performance comes from the new step +segment buffer. However, even in the worse case scenario, the step +segment buffer generates a new segment with a typical 0.2 ms, and the +worse case is 1ms upon a new block or replanning the active block. +Added altogether, it’s argubly still twice as efficient as the old one. + + +---------------- +Date: 2013-11-23 +Author: Sonny Jeon +Subject: Merge pull request #289 from Travis-Snoozy/master + +Add support for active-high limit switches + +---------------- +Date: 2013-11-22 +Author: Travis Snoozy +Subject: Add support for active-high limit switches + + +---------------- +Date: 2013-11-22 +Author: Sonny Jeon +Subject: Yet another major stepper algorithm and planner overhaul. + +- Overhauled the stepper algorithm and planner again. This time +concentrating on the decoupling of the stepper ISR completely. It is +now dumb, relying on the segment generator to provide the number of +steps to execute and how fast it needs to go. This freed up lots of +memory as well because it made a lot tracked variables obsolete. + +- The segment generator now computes the velocity profile of the +executing planner block on the fly in floating point math, instead of +allowing the stepper algorithm to govern accelerations in the previous +code. What this accomplishes is the ability and framework to (somewhat) +easily install a different physics model for generating a velocity +profile, i.e. s-curves. + +- Made some more planner enhancements and increased efficiency a bit. + +- The changes also did not increase the compiled size of Grbl, but +decreased it slightly as well. + +- Cleaned up a lot of the commenting. + +- Still much to do, but this push works and still is missing feedholds +(coming next.) + + +---------------- +Date: 2013-10-29 +Author: Sonny Jeon +Subject: Another merge fix. + + +---------------- +Date: 2013-10-29 +Author: Sonny Jeon +Subject: Merge fixes. + + +---------------- +Date: 2013-10-29 +Author: Sonny Jeon +Subject: Merge branch 'dev_2' into dev + +Conflicts: + README.md + gcode.c + motion_control.c + planner.c + planner.h + protocol.c + report.c + settings.c + settings.h + stepper.c + stepper.h + + +---------------- +Date: 2013-10-29 +Author: Sonny Jeon +Subject: Merge branch 'dev_2' into dev + +Conflicts: +README.md +gcode.c +motion_control.c +planner.c +planner.h +protocol.c +report.c +settings.c +settings.h +stepper.c +stepper.h + + +---------------- +Date: 2013-10-29 +Author: Sonny Jeon +Subject: Planner function call fix. More clean up. + + +---------------- +Date: 2013-10-29 +Author: Sonny Jeon +Subject: Updated comments. Changed stepper variable names to be more understandable. Added step locking note. + +- Updated config comments and stepper code comments for the new changes. + +- Changed stepper algorithm variable names to be more understandable in +what they actually do. + +- Added a stepper lock note in default.h per user request. + +- Started some code layout in handling feed holds and refactoring the +homing routine to use the main stepper algorithm instead of a seperate +version. + + +---------------- +Date: 2013-10-24 +Author: Sonny Jeon +Subject: Cleaned up stepper and planner code. + +- Added some compile-time error checking. Will add more in future +pushes to ensure settings are correct and within parameters that won't +break anything. + +- Pushed some master branch changes with MEGA pin settings. + +- Cleaned up planner code and comments to clarify some of the new +changes. Still much to do here. + +- Cleaned up the new stepper code. May need to abstract some of the +segment buffer more to fix the feed holds (and integrate homing into +the main stepper routine). With what's planned, this should make the +stepper algorithm easier to attach other types of processes to it, +where it is now tightly integrated with the planner buffer and nothing +else. + + +---------------- +Date: 2013-10-21 +Author: Sonny Jeon +Subject: Merge pull request #279 from EliteEng/master + +Changed Stepper Pins + +---------------- +Date: 2013-10-18 +Author: Rob Brown +Subject: Changed Stepper Pins + +Changed Stepper Pins so the Step Port Invert Mask matches the UNO + + +---------------- +Date: 2013-10-17 +Author: Sonny Jeon +Subject: Merge pull request #278 from EliteEng/master + +Update Pin Change Interrupts on Mega 2560 + +---------------- +Date: 2013-10-17 +Author: Rob Brown +Subject: Update Pin Change Interrupts so it works + +PCIE1 - Interrupt 8 on the Mega is attached to USART0 RX so when any +serial communication was transmitted it was triggering the Reset +Interrupt + + +---------------- +Date: 2013-10-14 +Author: Sonny Jeon +Subject: Fine tuning of new stepper algorithm with protected planner. Adaptive step prediction for segment buffer. + +- Cleaned up the new stepper algorithm code with more commenting and +better logic flow. + +- The new segment buffer now predicts the number of steps each segment +should have to execute over about 8 milliseconds each (based on the +ACCELERATION_TICKS_PER_SECOND setting). So, for when the whole segment +buffer is full, the stepper algorithm has roughly 40 milliseconds of +steps queued before it needs to refilled by the main program. + +- Readjusted the max supported step rate back to 30kHz from the lower +development 20kHz. Everything still works amazing great and the test +CNC machine still runs twice as fast with the new stepper algorithm and +planner. + +- Upped the standard serial baudrate to 115200 baud, as it is clear +that the bottleneck is the serial interface. Will now support this, as +well as the old 9600 baud, in new firmware builds. + + +---------------- +Date: 2013-10-12 +Author: Sonny Jeon +Subject: New stepper subsystem bug fixes. + +- New stepper algorithm with the new optimized planner seems to be +working nearly twice as fast as the previous algorithm. + +- For one, the planner computation overhead is probably a fraction of +what it used to be with the worst case being about half still. + +- Secondly, anytime the planner plans back to the first executing +block, it no longer overwrites the block conditions and allows it to +complete without lost steps. So no matter if the streams slows, the +protected planner should keep the steppers moving without risk of lost +steps (although this still needs to be tested thoroughly and may +audibly sound weird when this happens.) + +- It now seems that the bottleneck is the serial baudrate (which is +good!) + + +---------------- +Date: 2013-10-09 +Author: Sonny Jeon +Subject: Protected buffer works! Vast improvements to planner efficiency. Many things still broken with overhaul. + +Development push. Lots still broken. + +- Protected planner concept works! This is a critical precursor to +enabling feedrate overrides in allowing the planner buffer and the +stepper execution operate atomically. This is done through a +intermediary segment buffer. + +- Still lots of work to be done, as this was a complete overhaul of the +planner and stepper subsystems. The code can be cleaned up quite a bit, +re-enabling some of the broken features like feed holds, and finishing +up some of the concepts + +- Pushed some of the fixes from the master and edge branch to here, as +this will likely replace the edge branch when done. + + +---------------- +Date: 2013-08-25 +Author: Sonny Jeon +Subject: Merge pull request #263 from 0xPIT/master + +remove mcu argument for avr-size in makefile as it is not present in GNU... + +---------------- +Date: 2013-08-25 +Author: 0xPIT +Subject: remove mcu argument for avr-size in makefile as it is not present in GNU Binutils 2.22 + + +---------------- +Date: 2013-08-20 +Author: Sonny Jeon +Subject: Pin map definition cleanup. + + +---------------- +Date: 2013-08-19 +Author: Sonny Jeon +Subject: Processor-independent pin mapping feature. + +- Cleaned up and organized pin mapping concept by @elmom. + +- pin_map.h allows for user-supplied pin mapping and port vector +definitions in a centralized file. With more processor types, more +definitions could be added. + + +---------------- +Date: 2013-08-19 +Author: Sonny Jeon +Subject: Merge pull request #260 from elmom/master + +Thanks for the contribution! Looks good. Will update some of the semantics shortly, but the idea is solid. + +---------------- +Date: 2013-08-19 +Author: Sonny Jeon +Subject: Push old dev_2 draft to work on other things. + +- **NON-FUNCTIONAL** +- Contains an old draft of separating the stepper driver direct access +to the planner buffer. This is designed to keep the stepper and planner +modules independent and prevent overwriting or other complications. In +this way, feedrate override should be able to be installed as well. +- A number of planner optimizations are installed too. +- Not sure where the bugs are. Either in the new planner optimizations, +new stepper module updates, or in both. Or it just could be that the +Arduino AVR is choking with the new things it has to do. + + +---------------- +Date: 2013-08-19 +Author: Sonny Jeon +Subject: Merge pull request #229 from 0xPIT/patch-1 + +fix command line parameter for avr-size + +---------------- +Date: 2013-07-21 +Author: Elmo Mäntynen +Subject: Refactor config.h to allow defaults for chips/boards with different pin mappings + + +---------------- +Date: 2013-07-21 +Author: Elmo Mäntynen +Subject: Added pin mapping list to docs, useful for porting + + +---------------- +Date: 2013-07-21 +Author: Elmo Mäntynen +Subject: Make serial work with most chips by default + + +---------------- +Date: 2013-05-16 +Author: 0xPIT +Subject: fix command line parameter for avr-size + +---------------- +Date: 2013-04-05 +Author: Sonny Jeon +Subject: Updated readme + + +---------------- +Date: 2013-04-05 +Author: Sonny Jeon +Subject: Increased g-code parser line buffer. Added line overflow feedback. + +- Increased g-code parser line buffer from 50 to 70 characters. Should +fix most all issues with long arc statements, provided that they are 8 +digits(float) long only. + +- Added a line buffer overflow feedback error to let the user know when +it encounters this problem. Resets the line whenever this occurs. +(Thanks @BHSPitMonkey!) + + +---------------- +Date: 2013-04-05 +Author: Sonny Jeon +Subject: Updates to edge/dev. Line buffer increased/planner buffer decreased. Line overflow feedback. + +- Increased g-code parser line buffer to 70 characters (from 50) to +prevent some long arc commands from getting truncated. + +- Decreased planner buffer from 18 to 17 blocks to free up memory for +line buffer. + +- Added a line buffer overflow feedback error (Thanks @BHSPitMonkey!) + + +---------------- +Date: 2013-03-28 +Author: Sonny Jeon +Subject: Minor updates to code and commenting. + + +---------------- +Date: 2013-03-22 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2013-03-21 +Author: Sonny Jeon +Subject: Untested! Soft limits, max travel, homing changes, new settings. + +- WARNING: Completely untested. Will later when there is time. Settings +WILL be overwritten, as there are new settings. + +- Soft limits installed. Homing must be enabled for soft limits to work +correctly. Errors out much like a hard limit, locking out everything +and bringing up the alarm mode. Only difference is it forces a feed +hold before doing so. Position is not lost. + +- IMPORTANT: Homing had to be updated so that soft limits work better +with less CPU overhead. When homing completes, all axes are assumed to +exist in negative space. If your limit switch is other side, the homing +cycle with set this axis location to the max travel value, rather than +zero. + +- Update mc_line() to accept an array, rather than individual variables. + +- Added an mc_auto_cycle_start() function handle this feature. +Organization only. + +- + + +---------------- +Date: 2013-03-19 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2013-03-19 +Author: Sonny Jeon +Subject: G-code updates for G10 L2 and L20 + +- Updated g-codes G10 L2 and G10 L20 to the new descriptions on +linuxcnc.org + + +---------------- +Date: 2013-03-19 +Author: Sonny Jeon +Subject: G-code updates for G10 L2 and L20. + +- LinuxCNC's g-code definitions changed for G10. Updated to their +descriptions. + + +---------------- +Date: 2013-03-13 +Author: Bertus Kruger +Subject: Update planner.c + +Removed inline from all functions. + +If this is really needed is there another way that we can get +around using it? (The Arduino IDE does not recognize it)  + +---------------- +Date: 2013-03-13 +Author: Bertus Kruger +Subject: Update nuts_bolts.c + +Removed __floatunsisf and used normal casting on line 81. +This makes it compatible with the Arduino IDE. + +---------------- +Date: 2013-03-12 +Author: Sonny Jeon +Subject: Pushed minor changes. Thanks @Protoneer! + + +---------------- +Date: 2013-03-12 +Author: Sonny Jeon +Subject: Merge pull request #200 from Protoneer/master + +Fixed small bug. + +---------------- +Date: 2013-03-13 +Author: Bertus Kruger +Subject: Update gcode.c + +Removed the home_select variable. + +---------------- +Date: 2013-03-13 +Author: Bertus Kruger +Subject: Update eeprom.h + +Fixed the function signature. + +---------------- +Date: 2013-03-13 +Author: Bertus Kruger +Subject: Update eeprom.c + +Changed back + +---------------- +Date: 2013-03-12 +Author: Bertus Kruger +Subject: Update gcode.c + +home_select defined out of scope. Moved it outside the switch +so the rest of the switch can see it properly.  + +---------------- +Date: 2013-03-12 +Author: Bertus Kruger +Subject: Update eeprom.c + +Function eeprom_put_char's parameters did not align with the .h file. + +---------------- +Date: 2013-03-01 +Author: Sonny Jeon +Subject: Bug fix to-do note on soft limit checks. Not yet completed. + + +---------------- +Date: 2013-03-01 +Author: Sonny Jeon +Subject: Minor changes and added notes to soft limits routines. + +- Changed up mc_line to accept an array rather than individual x,y,z +coordinates. Makes some of the position data handling more effective, +especially for a 4th-axis later on. + +- Changed up some soft limits variable names. + + +---------------- +Date: 2013-02-26 +Author: Sonny Jeon +Subject: Merge pull request #193 from bungao/soft_limts + +integrating soft limits + +---------------- +Date: 2013-02-26 +Author: Jens Geisler +Subject: bugfix: uninitiallized curr_block->new_entry_speed_sqr lead to step loss +in some cases + +---------------- +Date: 2013-02-26 +Author: bungao +Subject: integrating soft limits + + +---------------- +Date: 2013-02-22 +Author: Sonny Jeon +Subject: Added some prelimary notes to new changes. + + +---------------- +Date: 2013-02-22 +Author: Sonny Jeon +Subject: Push additional updates from @jgeisler0303 + + +---------------- +Date: 2013-02-22 +Author: Jens Geisler +Subject: changed atomic access for updating the acceleration profile +the stepper interrupt is only halted when necessary and for the shortest +time possible (8% cycle time) + +---------------- +Date: 2013-02-20 +Author: Sonny Jeon +Subject: Merge pull request #188 from jgeisler0303/new_planner + +New planner commits merge into dev branch. + +---------------- +Date: 2013-02-20 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2013-02-20 +Author: Jens Geisler +Subject: added counter for planner steps + +---------------- +Date: 2013-02-20 +Author: Jens Geisler +Subject: implemented a mixture of Sonny's MATLAB and my previous grbl planner +ontop of the edge planner +examples run byte for byte identical old and new version + +---------------- +Date: 2013-01-18 +Author: Sonny Jeon +Subject: Merge pull request #169 from silasb/fix-execute-bit-on-files + +Removing executable bit on the files + +---------------- +Date: 2013-01-18 +Author: Sonny Jeon +Subject: Merge bug fixes from recent v0.8c push. Added readme for Grbl Sim. + + +---------------- +Date: 2013-01-18 +Author: Sonny Jeon +Subject: Merge pull request #167 from tmpvar/simulator-mac + +Fix sim makefile so it works on mac + +---------------- +Date: 2013-01-18 +Author: Elijah Insua +Subject: Fix sim makefile so it works on mac + +These changes include a path separator fix and the removal of --gc-sections which causes ld failures, and is not needed on a pc. + +This patch also changes how a compiler is selected. The makefile will now select the system compiler , which should work fine +under mingw and linux. + + +---------------- +Date: 2013-01-17 +Author: Silas Baronda +Subject: Removing executable bit on the files + + +---------------- +Date: 2013-01-17 +Author: Sonny Jeon +Subject: Merge pull request #112 from jgeisler0303/simulator + +Grbl Simulator. Oh yeah. + +---------------- +Date: 2013-01-17 +Author: Jens Geisler +Subject: relaunch ontop of latest grbl edge +code very messy but tested + +---------------- +Date: 2013-01-09 +Author: Sonny Jeon +Subject: Merge pull request #160 from daapp/edge + +Replace some constants with N_AXIS. + +---------------- +Date: 2013-01-10 +Author: Alexander Danilov +Subject: Replace some constants with N_AXIS. + + +---------------- +Date: 2013-01-06 +Author: Sonny Jeon +Subject: Fixed bug with homing and polling at the same time. Updated readme. + + +---------------- +Date: 2013-01-06 +Author: Sonny Jeon +Subject: Minor changes. + +- Changed some names up and removed a plan_reset() function that is +never used. + + +---------------- +Date: 2012-12-21 +Author: Sonny Jeon +Subject: Readme link to edge build 2012-12-21 + + +---------------- +Date: 2012-12-21 +Author: Sonny Jeon +Subject: Updated README. Max step rate back at 30kHz. Acceleration minor bug fix. + +- Returned the max step rate to 30kHz. The new arc algorithm works uses +so much less CPU overhead, because the segments are longer, that the +planner has no problem computing through them. + +- Fixed an issue with the acceleration independence scaling. Should now +work with accelerations above 400mm/sec^2 or so. + +- Updated README + + +---------------- +Date: 2012-12-19 +Author: Sonny Jeon +Subject: Arc mm_per_segment removed, now in terms of tolerance. Stepper ramp counter variable type corrected. + +- Arc mm_per_segment parameter was removed and replaced with an +arc_tolerance parameter, which scales all arc segments automatically to +radius, such that the line segment error doesn't exceed the tolerance. +Significantly improves arc performance through larger radius arc, +because the segments are much longer and the planner buffer has more to +work with. + +- Moved n_arc correction from the settings to config.h. Mathematically +this doesn't need to be a setting anymore, as the default config value +will work for all known CNC applications. The error does not accumulate +as much anymore, since the small angle approximation used by the arc +generation has been updated to a third-order approximation and how the +line segment length scale with radius and tolerance now. Left in +config.h for extraneous circumstances. + +- Corrected the st.ramp_count variable (acceleration tick counter) to a +8-bit vs. 32-bit variable. Should make the stepper algorithm just a +touch faster overall. + + +---------------- +Date: 2012-12-16 +Author: Sonny Jeon +Subject: Slow trailing steps fix. Added more defaults. + +- Fixed an issue (hopefully) with slow trailing steps after a +triangular velocity profile move. Sets the trapezoid tick cycle counter +to the correct value for an accurate reproduction of the deceleration +curve. Keeps it from arriving too early to the target position, which +causes the slow trailing steps. + +- Added Zen Toolworks 7x7 to default settings. + +- Updated readme with new edge build. + + +---------------- +Date: 2012-12-16 +Author: Sonny Jeon +Subject: Max velocity axes independence installed. Fixed intermittent slow trailing steps. Timer0 disable fix. + +- Maximum velocity for each axis is now configurable in settings. All +rapids/seek move at these maximums. All feed rates(including rapids) +may be limited and scaled down so that no axis does not exceed their +limits. + +- Moved around auto-cycle start. May change later, but mainly to ensure +the planner buffer is completely full before cycle starting a streaming +program. Otherwise it should auto-start when there is a break in the +serial stream. + +- Reverted old block->max_entry_speed_sqr calculations. Feedrate +overrides not close to ready at all. + +- Fixed intermittent slow trailing steps for some triangle velocity +profile moves. The acceleration tick counter updating was corrected to +be exact for that particular transition. Should be ok for normal +trapezoidal profiles. + +- Fixed the Timer0 disable after a step pulse falling edge. Thanks +@blinkenlight! + + +---------------- +Date: 2012-12-14 +Author: Sonny Jeon +Subject: Acceleration independence installed. Initial re-work of planner for feedrate overrides. + +NOTE: This push is a work-in-progress and there are known bugs that +need to be fixed, like homing acceleration being incompatible. Released +for testing. Settings will definitely be overwritten, as new settings +were needed. + +- Acceleration independence installed in planner. Each axis can now +have different accelerations and Grbl will maximize the accelerations +depending on the direction its moving. Very useful for users like on +the ShapeOko with vastly different Z-axis properties. + +- More planner optimizations and re-factoring. Slightly improved some +of the older calculations, but new acceleration calculations offset +these improvements. Overall no change in processing speed. + +- Removed planner nominal length checks. It was arguable whether or not +this improved planner efficiency, especially in the worst case scenario +of arcs. + +- Updated readme and changed to markdown format. + + +---------------- +Date: 2012-12-12 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2012-12-12 +Author: Sonny Jeon +Subject: Changed README to markdown + + +---------------- +Date: 2012-12-12 +Author: Sonny Jeon +Subject: Added download links to README. + + +---------------- +Date: 2012-12-12 +Author: Sonny Jeon +Subject: Moved compiled builds to different repo. + + +---------------- +Date: 2012-12-11 +Author: Sonny Jeon +Subject: Added builds folder. + +Because the Downloads section has been removed, added a builds folder +for users to download pre-compiled firmware without needing to compile +it themselves. + + +---------------- +Date: 2012-12-11 +Author: Sonny Jeon +Subject: Added builds folder. + +In light of the downloads section in Github being removed, added a +builds folder for all of the .hex files. Hopefully these won't be +removed either. + + +---------------- +Date: 2012-12-11 +Author: Sonny Jeon +Subject: Planner optimizations. + +- Improved planner execution speed by 5% or more. Re-factored most of +the calculations in terms of the square of velocity. This removed a lot +of sqrt() calculations for every planner_recalculate. + + +---------------- +Date: 2012-12-10 +Author: Sonny Jeon +Subject: (Another) Planner bug fix. + +- Oops again. Thought the new planner changes made things much better, +but there was a bug. Improvements we on the order of 20% execution time +reduction, rather than half. The increase to 30kHz Ranade timer +frequency also increased the overall overhead, so the total planner +change? Zero. But, it's still better. + + +---------------- +Date: 2012-12-10 +Author: Sonny Jeon +Subject: Planner bug fix. + +- Oops! Misplace an if-then statement. Should work as advertised now. +(Hopefully) + + +---------------- +Date: 2012-12-10 +Author: Sonny Jeon +Subject: Planner execution time halved and bug fixes. Increased step rate limit to 30kHz. + +- Planner execute speed has been more than halved from 4ms to 1.9ms +when computing a plan for a single line segment during arc generation. +This means that Grbl can now run through an arc (or complex curve) +twice as fast as before without starving the buffer. For 0.1mm arc +segments, this means about the theoretical feed rate limit is about +3000mm/min for arcs now. + +- Increased the Ranade timer frequency to 30kHz, as there doesn't seem +to be any problems with increasing the frequency. This means that the +maximum step frequency is now back at 30kHz. + +- Added Zen Toolworks 7x7 defaults. + + +---------------- +Date: 2012-12-08 +Author: Sonny Jeon +Subject: New stepper algorithm. Optimized planner. + +- Brand-new stepper algorithm. Based on the Pramod Ranade inverse time +algorithm, but modified to ensure step events are exact. Currently +limited to about 15kHz step rates, much more to be done to enable 30kHz +again. + +- Removed Timer1. Stepper algorithm now uses Timer0 and Timer2. + +- Much improved step generation during accelerations. Smoother. Allows +much higher accelerations (and speeds) than before on the same machine. + +- Cleaner algorithm that is more easily portable to other CPU types. + +- Streamlined planner calculations. Removed accelerate_until and +final_rate variables from block buffer since the new stepper algorithm +is that much more accurate. + +- Improved planner efficiency by about 15-20% during worst case +scenarios (arcs). + +- New config.h options to tune new stepper algorithm. + diff --git a/doc/log/commit_log_v0.9i.txt b/doc/log/commit_log_v0.9i.txt new file mode 100644 index 0000000..6627b0d --- /dev/null +++ b/doc/log/commit_log_v0.9i.txt @@ -0,0 +1,871 @@ +---------------- +Date: 2015-08-14 +Author: Sonny Jeon +Subject: Individual control pin invert compile-option. + +- Control pins may be individually inverted through a +CONTROL_INVERT_MASK macro. This mask is define in the cpu_map.h file. + + +---------------- +Date: 2015-07-17 +Author: Sonny Jeon +Subject: Version bump to v0.9j + +- Version bump requested by OEMs to easily determine whether the +firmware supports the new EEPROM reset feature. Other than that, no +significant changes. + + +---------------- +Date: 2015-06-25 +Author: Sonny Jeon +Subject: Restore parameters minor bug fix. + +- `$RST=#` was not wiping the G30 positions from EEPROM. Minor but now +fixed. + + +---------------- +Date: 2015-06-20 +Author: Sonny Jeon +Subject: New EEPROM restore functions. + +- Tweaked the previous EEPROM restore implementation and added new +functionality. + +- `$RST=$` restores the `$$` grbl settings back to firmware defaults, +which are set when compiled. + +- `$RST=#` restores the `$#` parameters in EEPROM. At times it’s useful +to clear these and start over, rather than manually writing each entry. + +-`$RST=*` wipe all of the data in EEPROM that Grbl uses and restores +them to defaults. This includes `$$` settings, `$#` parameters, `$N` +startup lines, and `$i` build info string. + +NOTE: This doesn’t write zeros throughout the EEPROM. It only writes +where Grbl looks for data. For a complete wipe, please use the Arduino +IDE’s EEPROM clear example. + +- Refactored the restore and wipe functions in settings.c to +accommodate the new commands. + + +---------------- +Date: 2015-06-18 +Author: Sonny Jeon +Subject: Updated README + + +---------------- +Date: 2015-06-18 +Author: Sonny Jeon +Subject: Added restore settings defaults command. + +- New restore setting defaults command. Only wipes ‘$$’ setting in +EEPROM and reloads them based on the defaults used when Grbl was +compiled. Used with a `$RST` command + +NOTE: `$RST` is intentionally not listed in the Grbl ‘$’ help message. + + +---------------- +Date: 2015-05-29 +Author: Sonny Jeon +Subject: Added G61 exact path support. + +- G61 exact path is the Grbl default path control mode, so it’s now +added as a supported g-code. + + +---------------- +Date: 2015-05-27 +Author: Sonny Jeon +Subject: Another git case-sensitive folder fix. + +- I’m now officially annoyed. + + +---------------- +Date: 2015-05-27 +Author: Sonny Jeon +Subject: Added X-Carve defaults. + +- Added X-Carve 500mm and 1000mm default files. + +- Tweaked all default files. Removed obsolete AUTO_START and updated +some JUNCTION_DEVIATION defaults after testing showed these needed to +be reduced slightly. + + +---------------- +Date: 2015-05-27 +Author: Sonny Jeon +Subject: Merge pull request #710 from buserror/fix-directory-case-sensitivity + +Rename Grbl to grbl + +---------------- +Date: 2015-05-27 +Author: Michel Pollet +Subject: Rename Grbl to grbl + +Otherwise compilation fails on linux, or other case sensitive systems + +Signed-off-by: Michel Pollet + + +---------------- +Date: 2015-05-26 +Author: Sonny Jeon +Subject: Updated README + + +---------------- +Date: 2015-05-26 +Author: Sonny Jeon +Subject: Merge pull request #706 from grbl/edge + +Merge edge branch. + +---------------- +Date: 2015-05-23 +Author: Sonny Jeon +Subject: CoreXY planner bug fix. + +- CoreXY motions were moving to the negative value of the intended +target. Now fixed. + + +---------------- +Date: 2015-05-23 +Author: Sonny Jeon +Subject: Moved cpu_map. + +- Moved cpu_map files to a cpu_map directory, like the defaults file +organization. + + +---------------- +Date: 2015-05-23 +Author: Sonny Jeon +Subject: Homing and limit updates. Minor bug fixes. + +- Updated new homing cycle to error out when a pull-off motion detects +the limit is still active. + +- Created a limits_get_state() function to centralize it. It reports +state as a bit-wise booleans according to axis numbering. + +- Updated the print uint8 functions. Generalized it to allow both base2 +and base10 printouts, while allowing base2 prints with N_AXIS digits +for limit state status reports. Doing this saved about 100bytes of +flash as well. + +- Applied CoreXY status reporting bug fix by @phd0. Thanks! + + +---------------- +Date: 2015-05-22 +Author: Sonny Jeon +Subject: Merge pull request #702 from ashelly/default-split + +Moving defaults to individual files in subdirectory + +---------------- +Date: 2015-05-22 +Author: ashelly +Subject: Moving defaults to individual files in subdirectory + + +---------------- +Date: 2015-05-22 +Author: Sonny Jeon +Subject: Merge pull request #700 from ashelly/header-split + +Header split + +---------------- +Date: 2015-05-22 +Author: ashelly +Subject: Fixing up comment blocks in headers + + +---------------- +Date: 2015-05-22 +Author: ashelly +Subject: Splitting Cpu map into separate files. + +Makes comparison, addition of new ones easier + + +---------------- +Date: 2015-05-17 +Author: Sonny Jeon +Subject: Critical M0/2/30 fix. Homing updates. + +- Critical fix for M0 program pause. Due to its recent change, it would +cause Grbl to suspend but wouldn’t notify the user of why Grbl was not +doing anything. The state would show IDLE and a cycle start would +resume it. Grbl now enters a HOLD state to better indicate the state +change. + +- Critical fix for M2 and M30 program end. As with M0, the state +previously would show IDLE while suspended. Grbl now does not suspend +upon program end and leaves job control to the GUI. Grbl simply reports +a `[Pgm End]` as a feedback message and resets certain g-code modes. + +- M2/30 g-code reseting fix. Previously Grbl would soft-reset after an +M2/30, but this was not complaint to the (linuxcnc) g-code standard. It +simply resets [G1,G17,G90,G94,G40,G54,M5,M9,M48] and keeps all other +modes the same. + +- M0/M2/M30 check-mode fix. It now does not suspend the machine during +check-mode. + +- Minor bug fix related to commands similar to G90.1, but not G90.1, +not reporting an unsupported command. + +- Homing cycle refactoring. To help reduce the chance of users +misunderstanding their limit switch wiring, Grbl only moves a short +distance for the locate cycles only. In addition, the homing cycle +pulls-off the limit switch by the pull-off distance to re-engage and +locate home. This should improve its accuracy. + +- HOMING_FORCE_ORIGIN now sets the origin to the pull-off location, +rather than where the limit switch was triggered. + +- Updated default junction deviation to 0.01mm. Recent tests showed +that this improves Grbl’s cornering behavior a bit. + +- Added the ShapeOko3 defaults. + +- Added new feedback message `[Pgm End]` for M2/30 notification. + +- Limit pin reporting is now a $10 status report option. Requested by +OEMs to help simplify support troubleshooting. + + +---------------- +Date: 2015-03-29 +Author: Sonny Jeon +Subject: Fix for limit pin reporting compile-option + +- The limit pin reporting wasn’t working correctly due to calling the +wrong similarly-named function. Verified to be working now. + + +---------------- +Date: 2015-03-29 +Author: Sonny Jeon +Subject: Commit history, logo license, full-arc fix. + +- Commit history added to repo, as an easier way for people to see view +the changes over time. + +- Grbl logo copyright license added. All rights reserved with regards +to the Grbl logo. + +- G2/3 full circles would sometime not execute. The problem was due to +numerical round-off of a trig calculation. Added a machine epsilon +define to help detect and correct for this problem. Tested and should +not effect general operation of arcs. + + +---------------- +Date: 2015-03-27 +Author: Sungeun Jeon +Subject: Compile-option for inverting spindle enable. + +- Installed a compile-option for inverting the spindle enable pin for +certain electronics boards users have reported needing this. + + +---------------- +Date: 2015-03-27 +Author: Sungeun Jeon +Subject: New compile options and inverse time bug fix. + +- Apparently inverse time motion were not working for quite some time. +Goes to show how many people actually use it. The calculation was bad +and is now fixed in this update. It should now work correctly. + +- `;` comment type is now supported. This is standard on LinuxCNC and +common on 3d printers. It was previously not supported due to not +existing in the NIST standard, which is out-dated. + +- New compile-option to ECHO the line received. This should help users +experiencing very weird problems and help diagnose if there is +something amiss in the communication to Grbl. + +- New compile-option to use the spindle direction pin D13 as a spindle +enable pin with PWM spindle speed on D11. This feature has been +requested often from the laser cutter community. Since spindle +direction isn’t really of much use, it seemed like good good trade. +Note that M4 spindle enable counter-clock-wise support is removed for +obvious reasons, while M3 and M5 still work. + + +---------------- +Date: 2015-03-27 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2015-03-26 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2015-03-16 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2015-03-15 +Author: Sungeun Jeon +Subject: Updated README + + +---------------- +Date: 2015-03-15 +Author: Sonny Jeon +Subject: Create README.md + +---------------- +Date: 2015-03-15 +Author: Sungeun Jeon +Subject: Merge branch 'edge' + + +---------------- +Date: 2015-03-15 +Author: Sungeun Jeon +Subject: Updated README. + +- Also altered the G38.X reporting to save some bytes. + + +---------------- +Date: 2015-03-14 +Author: Sungeun Jeon +Subject: Cleaned-up limit pin reporting and comments. + +- Cleaned up the limit pin state reporting option to display only the +state per axis, rather than the whole port. It’s organized by an XYZ +order, 0(low)-1(high), and generally looks like `Lim:001`. + +- Separated the control pin state reporting from limit state reporting +as a new compile option. This stayed the same in terms of showing the +entire port in binary, since it’s not anticipated that this will be +used much, if at all. + +- Updated some of the gcode source comments regarding supported g-codes. + + +---------------- +Date: 2015-03-07 +Author: Sonny Jeon +Subject: Another homing cycle fix. + +- The homing cycle should be working again. Reverted it back to how it +was about a month ago before I started to fiddle with it. Turns out +that my past self knew what he was doing. + + +---------------- +Date: 2015-03-04 +Author: Sonny Jeon +Subject: Arduino IDE compatibility and minor homing fixes + +- Added an include in the right spot, if a user tries to compile and +upload Grbl through the Arduino IDE with the old way. + +- Fixed a minor bug with homing max travel calculations. It was causing +simultaneous axes homing to move slow than it did before. + + +---------------- +Date: 2015-02-25 +Author: Sonny Jeon +Subject: G91.1 support. Fixed a config.h option. + +- G91.1 support added. This g-code sets the arc IJK distance mode to +incremental, which is the default already. This simply helps reduce +parsing errors with certain CAM programs that output this command. + +- Max step rate checks weren’t being compiled in if the option was +enabled. Fixed now. + +- Alarm codes were not displaying correctly when GUI reporting mode was +enabled. Due to unsigned int problem. Changed codes to positive values +since they aren’t shared with other codes. + + +---------------- +Date: 2015-02-23 +Author: Sonny Jeon +Subject: Fixed config.h to Grbl release defaults. + +- REPORT_GUI_MODE was accidentally enabled, when it shouldn’t have. + + +---------------- +Date: 2015-02-23 +Author: Sonny Jeon +Subject: New configuration options. + +- New configuration option at compile-time: + - Force alarm upon power-up or hard reset. When homing is enabled, +this is already the default behavior. This simply forces this all of +the time. + - GUI reporting mode. Removes most human-readable strings that GUIs +don’t need. This saves nearly 2KB in flash space that can be used for +other features. + - Hard limit force state check: In the hard limit pin change ISR, Grbl +by default sets the hard limit alarm upon any pin change to guarantee +the alarm is set. If this option is set, it’ll check the state within +the ISR, but can’t guarantee the pin will be read correctly if the +switch is bouncing. This option makes hard limit behavior a little less +annoying if you have a good buffered switch circuit that removes +bouncing and electronic noise. + +- Software debounce bug fix. It was reading the pin incorrectly for the +setting. + +- Re-factored some of the ‘$’ settings code. + + +---------------- +Date: 2015-02-15 +Author: Sonny Jeon +Subject: Improved homing limit search handling. + +- Instead of a single overall max travel for a search distance for the +homing limit switches. The homing cycle now applies the max travel of +each axis to the search target. Generally makes more sense this way and +saved more than a 100bytes of flash too. + + +---------------- +Date: 2015-02-15 +Author: Sonny Jeon +Subject: Homing alarm upon no switch. Licensing update. + +- Homing cycle failure reports alarm feedback when the homing cycle is +exited via a reset, interrupted by a safety door switch, or does not +find the limit switch. + +- Homing cycle bug fix when not finding the limit switch. It would just +idle before, but now will exit with an alarm. + +- Licensing update. Corrected licensing according to lawyer +recommendations. Removed references to other Grbl versions. + + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Merge pull request #593 from poelstra/fix_makefile_deps + +Fix generating header dependencies, merge with 'normal' compile, force r... + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Updated README with new logo sized for github. + + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Doc re-org. New Grbl Logos! + + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Merge pull request #591 from EliteEng/edge + +Safety Door Update for Mega2560 + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Merge pull request #592 from poelstra/fix_softlimit + +Fix EXEC_ALARM_* flags: soft limit would lead to hard limit error. + +---------------- +Date: 2015-02-13 +Author: Sonny Jeon +Subject: Merge pull request #594 from poelstra/fix_sim_build + +Fix function signature of print_uint32_base10(), necessary for compiling simulator. + +---------------- +Date: 2015-02-13 +Author: Martin Poelstra +Subject: Fix function signature of print_uint32_base10(), necessary for compiling simulator. + + +---------------- +Date: 2015-02-13 +Author: Martin Poelstra +Subject: Fix generating header dependencies, merge with 'normal' compile, force recompile when files are removed. + + +---------------- +Date: 2015-02-13 +Author: Martin Poelstra +Subject: Fix EXEC_ALARM_* flags: soft limit would lead to hard limit error. + + +---------------- +Date: 2015-02-13 +Author: Rob Brown +Subject: Safety Door Update for Mega2560 + + +---------------- +Date: 2015-02-11 +Author: Sonny Jeon +Subject: Overhauled state machine. New safety door feature. + +- Overhauled the state machine and cleaned up its overall operation. +This involved creating a new ‘suspend’ state for what all external +commands, except real-time commands, are ignored. All hold type states +enter this suspend state. + +- Removed ‘auto cycle start’ setting from Grbl. This was not used by +users in its intended way and is somewhat redundant, as GUI manage the +cycle start by streaming. It also muddled up how Grbl should interpret +how and when to execute a g-code block. Removing it made everything +much much simpler. + +- Fixed a program pause bug when used with other buffer_sync commands. + +- New safety door feature for OEMs. Immediately forces a feed hold and +then de-energizes the machine. Resuming is blocked until the door is +closed. When it is, it re-energizes the system and then resumes on the +normal toolpath. + +- Safety door input pin is optional and uses the feed hold pin on A1. +Enabled by config.h define. + +- Spindle and coolant re-energizing upon a safety door resume has a +programmable delay time to allow for complete spin up to rpm and +turning on the coolant before resuming motion. + +- Safety door-style feed holds can be used instead of regular feed hold +(doesn’t de-energize the machine) with a ‘@‘ character. If the safety +door input pin is not enabled, the system can be resumed at any time. + + +---------------- +Date: 2015-02-10 +Author: Sonny Jeon +Subject: Git fix for empty directory. Makefile updated. + +- ‘build’ directory was not being synced by git because it was empty. +Added a .gitignore file in the ‘build’ directory to force git to sync +it but keep it empty. + +- Updated the Makefile to not erase the .gitignore. + + +---------------- +Date: 2015-02-10 +Author: Sonny Jeon +Subject: File re-organization. New Makefile. + +- Re-organized source code files into a ‘grbl’ directory to lessen one +step in compiling Grbl through the Arduino IDE. + +- Added an ‘examples’ directory with an upload .INO sketch to further +simplify compiling and uploading Grbl via the Arduino IDE. + +- Updated the Makefile with regard to the source code no longer being +in the root directory. All files generated by compiling is placed in a +separate ‘build’ directory to keep things tidy. The makefile should +operate in the same way as it did before. + + +---------------- +Date: 2015-02-10 +Author: Sonny Jeon +Subject: Bug fix for certain motions. Re-org of includes. + +- Critical bug fix for diagonal motions that continue on the same +direction or return in the exact opposite direction. This issue could +cause Grbl to crash intermittently due to a numerical round-off error. +Grbl versions prior to v0.9g shouldn’t have this issue. + +- Reorganized all of the includes used by Grbl. Centralized it into a +single “grbl.h” include. This will help simplify the compiling and +uploading process through the Arduino IDE. + +- Added an example .INO file for users to simply open and run when +compiling and uploading through the IDE. More to come later. + + +---------------- +Date: 2015-02-06 +Author: Sonny Jeon +Subject: Limit/control pin state reporting option + +- As a setup feature, users can compile-in input pin status reporting. +Doesn’t do anything special, just prints the binary for the port. 0’s +and 1’s indicate low and high signals on the pins. It’s a bit cryptic +right now, but it’s just a start. + +- Added a max step rate check when writing step/mm and max rate +settings. Should help avoid people misdiagnosing problems associated +with going over the 30kHz step rate limit. Right now not enabled. Takes +up over 100k of flash. Need that room for other things right now. + + +---------------- +Date: 2015-02-04 +Author: Sonny Jeon +Subject: Rare planner bug fix and added simulator defaults. + +- Planner bug when moving along a diagonal back and forth on the same +path. Rare for the fact that most CAM programs don’t program this type +of motion, neither does jogging. Fixed in this update. + +- Added grbl_sim defaults for testing purposes. + + +---------------- +Date: 2015-01-17 +Author: Sonny Jeon +Subject: Fully configurable pins for NO or NC switches. + +- All pins, which include limits, control command, and probe pins, can +now all be configured to trigger as active-low or active-high and +whether the pin has its internal pull-up resistor enabled. This should +allow for just about all types of NO and NC switch configurations. + +- The probe pin invert setting hasn’t been added to the Grbl settings, +like the others, and will have to wait until v1.0. But for now, it’s +available as a compile-time option in config.h. + +- Fixed a variable spindle bug. + + +---------------- +Date: 2015-01-14 +Author: Sonny Jeon +Subject: Lot of refactoring for the future. CoreXY support. + +- Rudimentary CoreXY kinematics support. Didn’t test, but homing and +feed holds should work. See config.h. Please report successes and +issues as we find bugs. + +- G40 (disable cutter comp) is now “supported”. Meaning that Grbl will +no longer issue an error when typically sent in g-code program header. + +- Refactored coolant and spindle state setting into separate functions +for future features. + +- Configuration option for fixing homing behavior when there are two +limit switches on the same axis sharing an input pin. + +- Created a new “grbl.h” that will eventually be used as the main +include file for Grbl. Also will help simply uploading through the +Arduino IDE + +- Separated out the alarms execution flags from the realtime (used be +called runtime) execution flag variable. Now reports exactly what +caused the alarm. Expandable for new alarms later on. + +- Refactored the homing cycle to support CoreXY. + +- Applied @EliteEng updates to Mega2560 support. Some pins were +reconfigured. + +- Created a central step to position and vice versa function. Needed +for non-traditional cartesian machines. Should make it easier later. + +- Removed the new CPU map for the Uno. No longer going to used. There +will be only one configuration to keep things uniform. + + +---------------- +Date: 2014-11-05 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-10-29 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-10-28 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-10-28 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2014-10-01 +Author: Sonny Jeon +Subject: Updated variable spindle and new probing. Minor bug fixes. + +- Minor bug fix for variable spindle PWM output. Values smaller than +the minimum RPM for the spindle would overflow the PWM value. Thanks +Rob! + +- Created an optional minimum spindle PWM low-mark value as a +compile-time option. This is for special circumstances when the PWM has +to be at a certain level to be read by the spindle controller. + +- Refactored the new probing commands (G38.3, G38.4, G38.5) code to +work better with the rest of Grbl’s systems. + +- Refactored mc_probe() and mc_arc() to accept the mode of the command, +i.e. clockwise vs counter, toward vs away, etc. This is to make these +functions independent of gcode state variables. + +- Removed the pull off motion in the probing cycle. This is not an +official operation and was added for user simplicity, but wrongly did +so. So bye bye. + +- Created a configure probe invert mask function to handle the +different probe pin setting and probing cycle modes with a single mask. + + - Minor bug fix with reporting motion modes via $G. G38.2 wasn’t +showing up. It now does, along with the other new probing commands. + +- Refactored some of the new pin configurations for the future of Grbl. + +- + + +---------------- +Date: 2014-09-25 +Author: Sonny Jeon +Subject: Merge pull request #491 from tmpvar/G38.2+ + +G38.2+ + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: report probe_succeeded with probe status + + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: add probe_finalize to keep things DRY + +this allows the PRB report to be valid when in "no errors" mode and the probe fails + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: hop over probe pull-off sequence after probe miss + +and while "no errors" is enabled (G38.3, G38.5) + + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: add/install probe_errors_enabled in mc_probe_cycle + + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: bump mantissa to uint16_t to enable G38.5 + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: test only for & PROBE_ACTIVE + + +---------------- +Date: 2014-09-22 +Author: Elijah Insua +Subject: cleanup global var and push probe mode into probe_get_state + + +---------------- +Date: 2014-09-20 +Author: Sonny Jeon +Subject: Edit hard limit check at start of homing cycle + + +---------------- +Date: 2014-09-20 +Author: Sonny Jeon +Subject: Merge pull request #494 from ashelly/homing-alarm + +Alarm if limits engaged on homing start. + +---------------- +Date: 2014-09-20 +Author: Sonny Jeon +Subject: Merge pull request #493 from alpharesearch/edge + +If variable spindle is defined print S value via $G command. + +---------------- +Date: 2014-09-20 +Author: Sonny Jeon +Subject: Minor settings number overflow bug fix. + +- The `x` in `$x=val` would overflow when a value larger than 255 was +entered and passed to Grbl. This resulted with unintended parameters +being set by the overflow value. To fix, simply check for values larger +than 255 and error out. + + +---------------- +Date: 2014-09-17 +Author: ashelly +Subject: No false alarm if other bits in port are set. + +---------------- +Date: 2014-09-17 +Author: Markus Schulz +Subject: If variable spindle is defined print S value via $G command. + + +---------------- +Date: 2014-09-14 +Author: Elijah Insua +Subject: utilize MOTION_MODE_PROBE_NO_ERROR + + +---------------- +Date: 2014-09-14 +Author: Elijah Insua +Subject: install G38.{3,4,5} + + +---------------- +Date: 2014-09-14 +Author: Elijah Insua +Subject: add MOTION_MODE_PROBE_NO_ERROR + + +---------------- +Date: 2014-09-08 +Author: ashelly +Subject: Alarm if limits engaged on homing + diff --git a/doc/log/commit_log_v0.9j.txt b/doc/log/commit_log_v0.9j.txt new file mode 100644 index 0000000..3265c9d --- /dev/null +++ b/doc/log/commit_log_v0.9j.txt @@ -0,0 +1,17 @@ +---------------- +Date: 2015-08-14 +Author: Sonny Jeon +Subject: Individual control pin invert compile-option. + +- Control pins may be individually inverted through a +CONTROL_INVERT_MASK macro. This mask is define in the cpu_map.h file. + + +---------------- +Date: 2015-07-17 +Author: Sonny Jeon +Subject: Version bump to v0.9j + +- Version bump requested by OEMs to easily determine whether the +firmware supports the new EEPROM reset feature. Other than that, no +significant changes. diff --git a/doc/log/commit_log_v1.0b.txt b/doc/log/commit_log_v1.0b.txt new file mode 100644 index 0000000..8623d45 --- /dev/null +++ b/doc/log/commit_log_v1.0b.txt @@ -0,0 +1,140 @@ +---------------- +Date: 2015-09-30 +Author: Sonny Jeon +Subject: Bug fixes. + +- G38.x was not printing correctly in the $G g-code state reports. Now +fixed. + +- When investigating the above issue, it was noticed that G38.x +wouldn’t show at all, but instead a G0 would be printed. This was +unlike the v0.9j master build. It turned out volatile variables do not +like to be defined inside a C struct. These are undefined on how to be +handled. Once pulled out, all weird issues went away. + +- Also changed two ‘sizeof()’ statements in the mc_probe() and +probe_state_monitor() functions to be more robust later on. + +- Updated the commit logs to individual files for each minor release. +Forgot to update the generating script to account for this. + + +---------------- +Date: 2015-09-30 +Author: Sonny Jeon +Subject: Minor bug fixes. + +- G38.x was not printing correctly in the $G g-code state reports. Now +fixed. + +- Potential bug regarding volatile variables inside a struct. It has +never been a problem in v0.9, but ran into this during v1.0 +development. Just to be safe, the fixes are applied here. + +- Updated pre-built firmwares with these two bug fixes. + + +---------------- +Date: 2015-09-24 +Author: Sonny Jeon +Subject: Updated G28/G30 intermediate motion behavior. + +- G28 and G30’s behavior has been updated from the old NIST g-code +standard to LinuxCNC’s. Previously when an intermediate motion was +programmed, the NIST standard would move all axes to the final G28/30 +stored coordinates. LinuxCNC states it only moves the axes specified in +the command. + + For example, suppose G28’s stored position is (x,y,z) = (1,2,3) for +simplicity, and we want to do an automated z-axis tool retraction and +then park at the x,y location. `G28 G91 Z5` will first move the Z axis +5mm(or inches) up, then move Z to position 3 in machine coordinates. +Next, the command `G28 G91 X0 Y0` would skip the intermediate move +since distance is zero, but then move only the x and y axes to machine +coordinates 1 and 2, respectively. The z-axis wouldn’t move in this +case, since it wasn’t specified. + +This change is intended to make Grbl more LinuxCNC compatible while +making commands, like the shown tool retraction, much easier to +implement. + + +---------------- +Date: 2015-09-05 +Author: Sonny Jeon +Subject: Parking motion bug fix. + +- Parking motion would intermittently complete the queued tool path +upon resuming in certain scenarios. Now fixed. + + +---------------- +Date: 2015-08-29 +Author: Sonny Jeon +Subject: Optional line number reporting bug fix. + +- Fixed a bug where it would not compile when USE_LINE_NUMBERS was +enabled. + + +---------------- +Date: 2015-08-27 +Author: Sonny Jeon +Subject: Update README + + +---------------- +Date: 2015-08-27 +Author: Sonny Jeon +Subject: v1.0 Beta Release. + +- Tons of new stuff in this release, which is fairly stable and well +tested. However, much more is coming soon! + +- Real-time parking motion with safety door. When this compile option +is enabled, an opened safety door will cause Grbl to automatically feed +hold, retract, de-energize the spindle/coolant, and parks near Z max. +After the door is closed and resume is commanded, this reverses and the +program continues as if nothing happened. This is also highly +configurable. See config.h for details. + +- New spindle max and min rpm ‘$’ settings! This has been requested +often. Grbl will output 5V when commanded to turn on the spindle at its +max rpm, and 0.02V with min rpm. The voltage and the rpm range are +linear to each other. This should help users tweak their settings to +get close to true rpm’s. + +- If the new max rpm ‘$’ setting is set = 0 or less than min rpm, the +spindle speed PWM pin will act like a regular on/off spindle enable +pin. On pin D11. + +- BEWARE: Your old EEPROM settings will be wiped! The new spindle rpm +settings require a new settings version, so Grbl will automatically +wipe and restore the EEPROM with the new defaults. + +- Control pin can now be inverted individually with a +CONTROL_INVERT_MASK in the cpu_map header file. Not typical for users +to need this, but handy to have. + +- Fixed bug when Grbl receive too many characters in a line and +overflows. Previously it would respond with an error per overflow +character and another acknowledge upon an EOL character. This broke the +streaming protocol. Now fixed to only respond with an error after an +EOL character. + +- Fixed a bug with the safety door during an ALARM mode. You now can’t +home or unlock the axes until the safety door has been closed. This is +for safety reasons (obviously.) + +- Tweaked some the Mega2560 cpu_map settings . Increased segment buffer +size and fixed the spindle PWM settings to output at a higher PWM +frequency. + +- Generalized the delay function used by G4 delay for use by parking +motion. Allows non-blocking status reports and real-time control during +re-energizing of the spindle and coolant. + +- Added spindle rpm max and min defaults to default.h files. + +- Added a new print float for rpm values. + diff --git a/doc/log/commit_log_v1.0c.txt b/doc/log/commit_log_v1.0c.txt new file mode 100644 index 0000000..eee4324 --- /dev/null +++ b/doc/log/commit_log_v1.0c.txt @@ -0,0 +1,67 @@ +---------------- +Date: 2016-03-19 +Author: Sonny Jeon +Subject: No variable spindle and spindle speed fix. + +- Soft limit errors were stuck in a feed hold without notifying the +user why it was in a hold. When resumed, the soft limit error would +kick in. Issue should be fixed to behave as intended to automatically +hold and issue a soft limit alarm once the machine has come to a stop. + + +---------------- +Date: 2016-03-11 +Author: Sonny Jeon +Subject: Soft limit error bug fix. + +- Soft limit errors were stuck in a feed hold without notifying the +user why it was in a hold. When resumed, the soft limit error would +kick in. Issue should be fixed to behave as intended. To automatically +hold and issue a soft limit alarm once the machine has come to a stop. + + +---------------- +Date: 2016-03-04 +Author: Sonny Jeon +Subject: Applied master branch bug fixes. + +- Planner was under-estimating maximum speeds through straight +junctions in certain cases. The calculations have been updated to be +more accurate. + +- Strange sizeof() bug in the most recent releases. Manifested as an +alarm upon a power up even when homing was disabled. Fixed by declaring +sizeof() with struct types, rather than variable names, even though +they were validated to give the same value. + +- Spindle speed zero should disable the spindle. Now fixed. + +- New configuration option for inverting certain limit pins. Handy for +mixed NO and NC switch machines. See config.h for details. + + +---------------- +Date: 2015-11-09 +Author: Sonny Jeon +Subject: Pin state reporting of all pins. Flash optimization. + +- New pin state realtime reporting feature. Instead of `Lim:000` for +limit state reports, the new feature shows `Pin:000|0|0000`, or +something similar. The `|` delimited fields indicate xyz limits, probe, +and control pin states, where 0 is always not triggered, and 1 is +triggered. Invert masks ARE accounted for. + Each field may be enabled or disabled via the `$10` status report +setting. The probe and control pin flags are bits 5 and 6, respectively. + +- Remove the now deprecated `REPORT_CONTROL_PIN_STATE` option in +config.h + +- The old limit pin reports `Lim:000` may be re-enabled by commenting +out `REPORT_ALL_PIN_STATES` in config.h. + +- Incremented the version letter (v1.0c) to indicate the change in +reporting style. + +- Replaced all bit_true_atomic and bit_false_atomic macros with +function calls. This saved a couple hundred bytes of flash. + diff --git a/doc/log/commit_log_v1.1.txt b/doc/log/commit_log_v1.1.txt new file mode 100644 index 0000000..ac5473a --- /dev/null +++ b/doc/log/commit_log_v1.1.txt @@ -0,0 +1,1187 @@ +---------------- +Date: 2019-08-30 +Author: Sonny Jeon +Subject: Fixed typo bug effecting dual-axis build with Y. + + +---------------- +Date: 2019-08-25 +Author: Sonny Jeon +Subject: Update grbl.h + + +---------------- +Date: 2019-08-25 +Author: Sonny Jeon +Subject: Update system.c + + +---------------- +Date: 2019-07-30 +Author: Sonny Jeon +Subject: Dual motor support for self-squaring gantry homing. + +- New dual motor support feature for gantry CNC machines. An axis motor is efficiently mirrored to a dedicated set of step and direction pins (D12/D13 or A3/A4) with no detectable loss of performance. Primarily used to independently home both sides of a dual-motor gantry with a pair of limit switches (second shared with Z-axis limit pin). When the limit switches are setup correctly, Grbl will self-square the gantry (and stay square if $1=255 is programmed). Beware use at your own risk! Grbl is not responsible for any damage to any machines. + +- Dual axis motors is only supported on the X-axis or Y-axis. And deletes the spindle direction(D13) and optional coolant mist (A4) features to make room for the dual motor step and direction pins. + +- Dual axis homing will automatically abort homing if one limit switch triggers and travels more than 5% (default) of the non-dual axis max travel setting. For example, if the X-axis has dual motors and one X-axis triggers during homing, Grbl will abort 5% of the Y-axis max travel and the other X-axis limit fails to trigger. This will help keep any misconfigurations or failed limit switches from damaging the machine, but not completely eliminate this risk. Please take all precautions and test thouroughly before using this. + +- Dual axis motors supports two configurations: + +- Support for Arduino CNC shield clones. For these, step/dir on pins D12/D13, and spindle enable is moved to A3 (old coolant enable), while coolant enable is moved to A4 (SDA pin). Variable spindle/laser mode option is NOT supported for this shield. + +- Support for Protoneer CNC Shield v3.51. Step/dir on pins A3/A4, and coolant enable is moved to D13 (old spindle direction pin). Variable spindle/laser mode option IS supported for this shield. + +- Added Bob's CNC E3 and E4 CNC machine defaults. + + +---------------- +Date: 2018-11-12 +Author: Sonny Jeon +Subject: Update grbl.h + +---------------- +Date: 2018-11-12 +Author: Sonny Jeon +Subject: Update system.c + +Correct control pin state checking within pin change interrupt. Improper if-else statements could lead to missed signal. + +---------------- +Date: 2018-11-12 +Author: Sonny Jeon +Subject: Update gcode.c + +If statement bug fix related to jog motion modal group error checking. + +---------------- +Date: 2018-06-14 +Author: Sonny Jeon +Subject: Spindle/coolant rare bug fixes. Free more flash. + +[new] Altered the way default settings are stored and restored. Saved about 300 bytes(!) of flashed size. Should free up enough for certain configurations of CoreXY machines. + +[fix] When the optional M7 mist coolant IO was enabled, coolant overrides was not disabling correctly. + +[fix] Coolant override states was not restored correctly after a parking motion in certain situations. It would restore programmed state, rather than current overridden state. + +[fix] Now allow coolant overrides to operate during jogging motion. + +[fix] Invert control pin mask typo. + +[new] Added a new build info feedback mechanism for enabling the safety door input pin. + + +---------------- +Date: 2018-06-09 +Author: Jon +Subject: Fix apparent error in restore masking that causes the call to coolant_set_state to not re-enable the mist (M7) output if it was previously enabled. (#469) + + + +---------------- +Date: 2018-04-06 +Author: Sonny Jeon +Subject: Updated instructions in fit_nonlinear_spindle.py + +- repl.it has changed since the last time fit_nonlinear_spindle.py was tested. Updated instructions. + + +---------------- +Date: 2017-08-01 +Author: Sonny Jeon +Subject: Improved fix for rare lowering feed/rapid override bug. + +[fix] In the previous hot fix, there was still (rarer) potential for +very small floating point errors incorrectly handle an override +deceleration and crash Grbl. Re-factored the if-then statement in terms +of speed changes, rather than distance, to completely eliminate the +issue. + + +---------------- +Date: 2017-07-31 +Author: Sonny Jeon +Subject: Hot fix for rare lowering feed override bug. + +[fix] Squashed a very rare bug when lowering the feedrate (or rapid) override. When in the very strict set of circumstances with acceleration settings, override step size, and current speed, an internal calculation would cause Grbl to crash. The fix was an overlooked equality statement that should have been a less than or equal, not a less than. + + +---------------- +Date: 2017-07-17 +Author: Sonny Jeon +Subject: Clean up and new streaming script check-mode feature. + +[new] The stream.py streaming script now has a check-mode option, where it will place Grbl in $C check mode automatically and then stream the g-code program. It's a very fast way to check if the g-code program has any errors. + +[fix] The debug variable was not initialized if the debug option was enabled in config.h + +[fix] Updated error_codes CSV file to the same format as the others. + + +---------------- +Date: 2017-05-31 +Author: chamnit +Subject: New nonlinear spindle speed PWM output model and solution. Updated scripts. + +[new] A nonlinear spindle speed/PWM output option via a piecewise +linear fit model. Enabled through config.h and solved by a Python +script in /doc/script + +[new] fit_nonlinear_spindle.py. A solver script that can be run on +http://repl.it for free. No Python install necessary. All instructions +are available in the script file comments. + +[new] stream.py has been updated to include status reports feedback at +1 second interval. + +[fix] stream.py bug fix with verbose mode disabled. + + +---------------- +Date: 2017-03-24 +Author: Sonny Jeon +Subject: Added an error code for laser mode when VARIABLE_SPINDLE is disabled. + +- When trying to enable laser mode with $32=1 and VARIABLE_SPINDLE is +disabled, the error code shown was improperly stating it was a homing +failure. Added an new error code specifically for the laser mode being +disabled without VARIABLE_SPINDLE. + + +---------------- +Date: 2017-03-19 +Author: Sonny Jeon +Subject: Housekeeping. + +- Moved Grbl logo files to a separate repo. + +- Added PocketNC FR4 defaults. Needs some additional work though to be +compatible. + +- Updated README image links. + + +---------------- +Date: 2017-03-19 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2017-03-02 +Author: Sonny Jeon +Subject: Fixed $G report issue with M7 and M8 both enabled. + +[fix] When M7 and M8 are both enabled, $G report would show `M78`, +rather than `M7 M8`. This only effects systems that enable M7 mist +coolant in config.h. Not the default build. + + +---------------- +Date: 2017-02-27 +Author: Sonny Jeon +Subject: Fixed shared build info code. + +- The build info options of “two switches on an axis” and “homing init +lock” shared the same letter ‘L’. The former is now ’T’. + + +---------------- +Date: 2017-02-23 +Author: Sonny Jeon +Subject: Restrict coincident target updates to M3 constant laser only. + +- Restrict M3 forced updates when there is a motion block with a +coincident target. Force syncing of the spindle state can lead to some +pauses during a job that has coincident targets. That’s not +particularly desirable. This ensures M4 dynamic mode is not effected by +this force-sync. + + +---------------- +Date: 2017-02-23 +Author: Sonny Jeon +Subject: Fixed issue with M3 laser state changes and coincident targets. + +[fix] When in M3 constant laser power mode, a change from G0 to G1 +would not set the laser on, if G1 was passed with a coincident target. +Motion controller now checks for a coincident target situation and will +force a spindle sync when detected. + + +---------------- +Date: 2017-01-31 +Author: Sonny Jeon +Subject: Additional build info in the $I printout. + +- [new] Added total available planner buffer blocks (15 shown, but +there are 16. one is used by the ring buffer and to execute system +motions) and serial RX buffer bytes. This information is useful for +GUIs to setup and optimize their streaming protocols easily. + +[doc] Updated the interface document to reflect the change. + + +---------------- +Date: 2017-01-29 +Author: Sonny Jeon +Subject: Tidying up parking override control implementation + +[new] Added a default configuration for the parking override control +upon a reset or power-up. By default, parking is enabled, but this may +be disabled via a config.h option. + +[fix] Parking override control should be checking if the command word +is passed, rather than the value. + + +---------------- +Date: 2017-01-28 +Author: chamnit +Subject: v1.1f. Parking override control. Spindle enable pin option. + +[ver] v1.1f update due to tweaks to interface from new parking override +control. + +[new] Parking motion override control via new `M56 P0` and `M56 P1` +command, which disables and enables the parking motion, respectively. +Requires ENABLE_PARKING_OVERRIDE_CONTROL and PARKING_ENABLE enabled in +config.h. Primarily for OEMs. + +[new] `M56` appears in the $G report when enabled. + +[new] Five new build info identification letters. Some were missing and +a couple are new. Updated the CSV and documentation to reflect these +new items. + +[new] Spindle enable pin configuration option to alter its behavior +based on how certain lasers work. By default, Grbl treats the enable +pin separately and leaves it on when S is 0. The new option turns the +enable pin on and off with S>0 and S=0. This only is in effect when a +user enables the USE_SPINDLE_DIR_AS_ENABLE_PIN option. + +[fix] M4 is now allowed to work when USE_SPINDLE_DIR_AS_ENABLE_PIN is +enabled. Previously this was blocked and was problematic for laser +folks using M4. + +[fix] Properly declared system variables as extern. Not sure how that +went unnoticed or why it worked up until now but it has. + +[fix] EXTREMELY RARE. When AMASS is intentionally disabled and sent a +motion command that is _one step_ in length, Grbl would not actuate the +step due to numerical round-off. Applied a fix to prevent the round-off +issue. + +[fix] Added a compile-time check for AMASS settings to make sure that +the numerical round-off issue doesn’t effect it. This would only happen +if someone set AMASS max levels to zero. It does not effect AMASS with +its current defaults. + +[fix] Wrapped the mc_parking_motion() function in an ifdef for porting +purposes. + +[fix] Fixed an issue when in inverse time mode and G0’s would require a +F word. This was not correct. + +[fix] Added a note in the defaults.h file that MAX_TRAVEL values must +be positive. Some users were setting this negative and it was causing +issues. + + +---------------- +Date: 2017-01-14 +Author: Sonny Jeon +Subject: Tool number bug fix. Updated documentation. + +- [fix] Tool numbers were not being tracked and reported correctly. Now +shows tool number values in $G when programmed. + +- [fix] Added a max tool number value check to the g-code parser. + +- [doc] Added a new error code for invalid tool number. Updated CSV and +interface documents. + +- [doc] Added a implementation note for buffer state in status reports. +Don’t rely on this data for streaming. + + +---------------- +Date: 2017-01-03 +Author: Sonny Jeon +Subject: Spindle enable pin with variable spindle option fix. + +- [fix] When USE_SPINDLE_DIR_AS_ENABLE_PIN is enabled in config.h, the +enable pin was not being set when spindle speed is zero. This behavior +should now be fixed. + + +---------------- +Date: 2016-12-19 +Author: Sonny Jeon +Subject: Fixed homing fail alarm handling. Re-integrated software debouncing. + +- [bug] Fixed a homing fail issue, where the alarm was not being set +right, not cleared correctly. It would report the wrong code and enter +an infinite alarm loop. This was due to how alarm codes were altered a +while back. Now updated and fixed to show the right codes. + +- [feature] Re-installed optional software debouncing for hard limit +switches. By request. + + +---------------- +Date: 2016-12-18 +Author: Sonny Jeon +Subject: Addressed optional PWM min value issue. Updated docs. + +- [fix] Spindle PWM minimum value had some typos. Fixed the macros to +compile correctly. Only effects users that enable SPINDLE_MINIMUM_PWM. +The name changed to SPINDLE_PWM_MIN_VALUE for consistency sake. + +- Updated the laser documentation. + + +---------------- +Date: 2016-12-12 +Author: Sonny Jeon +Subject: Updating steam.py streaming script + +- Added push message capability to the stream.py streaming script. It +prints out as a `Debug:` string in the output. + + +---------------- +Date: 2016-12-11 +Author: Sonny Jeon +Subject: Updated documentation. + + +---------------- +Date: 2016-12-10 +Author: Sonny Jeon +Subject: Updated documentation. Cleaned up a bit. + +- [doc] Updated the markdown documents for the v1.1 release. + +- [doc] Removed references to classic GUI mode. + + +---------------- +Date: 2016-12-09 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2016-12-09 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2016-12-09 +Author: Sonny Jeon +Subject: Update README.md + +---------------- +Date: 2016-12-08 +Author: Sonny Jeon +Subject: Removed classic GUI interface. Fixed typo with line number support. + +- [config] Permanently removed classic GUI interface support. This +unintentionally created a problem where some users/GUI devs used this +compatibility mode and did not update to the new interface. So, there +were two interfaces in use, rather than just one like it was intended. +This removal should help everyone by forcing all GUIs to update and +updated GUI not having to support yet another interface. + +- Fixed typo with line number support in jog mode. + + +---------------- +Date: 2016-12-04 +Author: chamnit +Subject: Fixed unintended laser mode pausing. Updated documentation. Min SS OVR lowered to 10%. + +- [laser] Tested a working version and pushed the wrong one for the +last! 20161203 was pausing upon every spindle speed change. That’s not +right. Fixed so nearly all motions are passed through and does not stop. + +- Minimum spindle speed override lower from 50% to 10%. Lasers could +use the lower speeds. + +- Fixed a very minor bug related to G80 error checking. Allowed no +error with non-modal motions with axis words. Not correct and fixed. + +- Fixed a compile error when disabling VARIABLE_SPINDLE + +- [doc] Updated some obsolete documentation. + +- [doc] Started a “Laser Mode” document that summarizes how Grbl’s new +laser mode works. + + +---------------- +Date: 2016-12-03 +Author: Sonny Jeon +Subject: v1.1e: New laser features. G-code parser refactoring. CoreXY homing fix. + +- Increment to v1.1e due to new laser features. + +- After several discussions with some prominent laser people, a few +tweaks to the new laser mode has been installed. + +- LASER: M3 behaves in a constant power mode. + +- LASER: M4 behaves in a dynamic power mode, where the laser power is +automatically adjusted based on how fast Grbl is moving relative to the +programmed feed rate. This is the same as the CONSTANT_POWER_PER_RATE +config.h option in the last version. NOTE: When not in motion in M4, +Grbl automatically turns off the laser. Again, it only operates while +moving! + +- LASER: Only G1, G2, and G3 motion modes will turn on the laser. So, +this means that G0, G80 motion modes will always keep the laser +disabled. No matter if M3/M4 are active! + +- LASER: A spindle stop override is automatically invoked when a laser +is put in a feed hold. This behavior may be disabled by a config.h +option. + +- Lots of little tweaks to the g-code parser to help streamline it a +bit. It should no effect how it operates. Generally just added a parser +flag to track and execute certain scenarios a little more clearly. + +- Jog motions now allow line numbers to be passed to it and will be +displayed in the status reports. + +- Fixed a CoreXY homing bug. + +- Fixed an issue when $13 is changed, WCO isn’t sent immediately. + +- Altered how spindle PWM is set in the stepper ISR. Updated on a step +segment basis now. May need to change this back if there are any +oddities from doing this. + +- Updated some documentation. Clarified why M0 no longer showing up in +$G and why a `1.` floating point values are shown with no decimals, +like so `1`. + + +---------------- +Date: 2016-11-12 +Author: Sonny Jeon +Subject: PWM calculation correction. + +- The PWM calculation was a little bit off and has been corrected. + +- Edited the unused settings strings to be smaller and just show what +the settings are, rather than include units. May include this in the +master build, if it fits. + +- The minimum spindle PWM define in config.h needed to be update for +cpu map compatibilty. + + +---------------- +Date: 2016-11-04 +Author: Sonny Jeon +Subject: Fixed a g-code parser issue caused by last commit. + +- G-code parser refactoring in the last commit wasn’t tested. Found and +fixed issues with G28.1/30.1 and G38.x probe commands. They were not +being accepted due to a borked mantissa check. + + +---------------- +Date: 2016-11-04 +Author: Sonny Jeon +Subject: Improved constant laser power per rate mode. Re-factored for flash size. Minor bug fixes. + +- NOTE: This commit has largely been untested. + +- Constant laser power per rate mode has been improved. Altered its +implementation to be more responsive and accurate. + +- Based on LaserWeb dev feedback, only G1, G2, and G3 moves operate +with constant laser power mode. Meaning that G0, G38.x, and $J jogging +motions operate without it and will keep a constant power output. This +was specifically requested as a way to focus the laser by keeping the +laser on when not moving. Operationally, this shouldn’t alter how the +laser mode operates. + +- Re-factored parts of the g-code parser and g-code state reports to +save a few hundred bytes of flash. What was done makes the code a bit +more unreadable (bad), but the flash space was in dire need. So, I’m +willing to live with it for now. + +- Fixed a problem with $G g-code state reports. Showed `M0` program +pause during a run state. Now fixed to show nothing during a run state. +Also, `M30` program end was shown as `M2`. This was also corrected. + +- Improved spindle stop override responsiveness by removing the +enforced spindle restoring delay. It’s not needed for a feature that is +user controlled. + +- Fixed a bug with G2/3 arcs in inverse time mode. + +- Updated the interface.md document to make it more clear how WPos: or +MPos: can be calculated from WCO:. Some GUI devs have failed to catch +this in the documentation. + + +---------------- +Date: 2016-10-27 +Author: Sonny Jeon +Subject: Spindle speed overrides behavior tweak. New experimental laser dynamic power mode. + +- Spindle speed overrides now update immediately if they are changed +while in a HOLD state. Previously, they would update after exiting the +HOLD, which isn’t correct. + +- New experimental dynamic laser power mode that adjusts laser power +based on current machine speed. Enabled by uncommenting +LASER_CONSTANT_POWER_PER_RATE in config.h + + - It assumes the programmed rate is the intended power/rate for the +motion. + - Feed rate overrides (FRO) do not effect the power/rate. Meaning +that spindle PWM will automatically lower with lower FRO and increase +with higher FRO to keep it the same. + - Spindle speed overrides (SSO) will directly increase and decrease +the power/rate. So 150% SSO will increase the PWM output by 150% for +the same speed. + - The combination of FRO and SSO behaviors should allow for subtle +and highly flexible tuning of how the laser cutter is operating in +real-time and during the job. + +- Re-factored planner block rapid rate handling for the dynamic laser +power feature. Should have had no effect on how Grbl operates. + + +---------------- +Date: 2016-10-26 +Author: Sonny Jeon +Subject: Add high-frequency spindle output option. Minor parking motion re-factoring. + +- Some laser controllers were reported to need a very high PWM +frequency. Added a line to enable this in cpu_map.h, if needed. + +- Cleaned up some of the parking code. Mostly just editing the comments. + +- Moved the accessory state resetting after the initial parking +retract. Should ensure the accessory state is properly handled upon an +aborted parking restore. Not certain if this was a problem before +though. Just to be sure. + + +---------------- +Date: 2016-10-25 +Author: chamnit +Subject: Mandate all probe cycles ignore feed overrides. + +- For repeatability reasons, all G38.x probe cycles ignore feed rate +overrides and move at their programmed speed. + +- The mandate can be removed with a new config.h option. + +- Updated the documentation to reflect the change. + + +---------------- +Date: 2016-10-25 +Author: chamnit +Subject: Resolved parking accessory handling issue. + +- Yikes. Totally borked the last parking “fix”. Testing shows that all +accessories are now properly handled when retracting and restoring. It +was caused by not accounting for the planner re-factoring correctly in +the parking code. + + +---------------- +Date: 2016-10-24 +Author: Sonny Jeon +Subject: Minor re-factoring. Fix an issue with parking and spindle restore. + +- Altered the report counters to be count down, rather than count up. +Simplified some of the logic. + +- Fixed an issue with parking restore. The spindle state would disable +then reenable. + +- Clarified some of the config.h descriptions. + +- Moved the compile-time checks from config.h to grbl.h. They don’t +belong in the config.h file. + +- Refactored the initialization of the system variables in main.c. +System position and probe position were undefined when power cycled, +but were zero anyway. Added clear vector code to make it explicit. + + +---------------- +Date: 2016-10-23 +Author: Sonny Jeon +Subject: Spindle speed close to minimum fix. + +- When spindle speed is close to the minimum rpm, the PWM value would +be zero or lower than allowed. The computation error was caused by +setting the minimum PWM value to zero, when it should have been 1. + +- Added a compiler check for minimum PWM to be greater than zero. + +- Moved some of the spindle PWM macros to a more appropriate place in +the cpu_map.h. + + +---------------- +Date: 2016-10-22 +Author: Will Winder +Subject: Minor VARIABLE_SPINDLE feature toggle refactoring (#16) + +* Modify code CSV format. + +- Wrap value in quotes to avoid issue with embedded commas. This occurs + in one of the alarm codes. + +- Change header row format to allow same parsing code as data rows. + +* VARIABLE_SPINDLE feature flag experiment. + +- Use a macro for 'spindle_set_speed' and 'spindle_sync' to reduce the + number of required VARIABLE_SPINDLE checks. + + +---------------- +Date: 2016-10-18 +Author: Sonny Jeon +Subject: Improved option for v0.9 GUI compatibility. + +- Addressed an issue with backward compatibility with Grbl v0.9-style +GUIs. + +- It still may not work due to new data and states coming back from +Grbl v1.1. Regardless, DO NOT TRY TO USE THE COMPATIBILITY MODE UNTIL +THERE IS A REALLY GOOD REASON TO. + +- v0.9 GUI compatibility mode will be removed in future versions. +You’ve been warned. It’s highly recommended for GUIs to update to the +new v1.1 interface. + +- Compability mode will only fit on an Arduino Uno due to size +increases. + +- Removed the REPORT_GUI_MODE compile option since it’s part of the +v1.1 interface standard. + +- Updated the documentation to better describe the compatibility mode +build option. + + +---------------- +Date: 2016-10-17 +Author: Sonny Jeon +Subject: v1.1d: Tweaked interface a bit. Added realtime spindle speed and build option data. Minor bug fixes. + +- Increment to v1.1d due to interface tweaks. + +- Based on GUI dev feedback, the toggle overrides report was removed +and replace with showing “accessory state”. This shows a character if a +particular accessory is enabled, like the spindle or flood coolant. +These can be directly altered by the toggle overrides, so when they +execute, a GUI will be able to observe the state altering as feedback. + +- Altered the real-time feed rate to show real-time spindle speed as +well. It was an over-sight on my part. It’s needed because it’s hard to +know what the current spindle speed is when overrides are altering it. +Especially during something like a laser cutting job when its important +to know how spindle speed overrides are effecting things. + +- Real-time spindle speed is not shown if VARIABLE_SPINDLE is disabled. +The old real-time feed rate data field will show instead. + +- Compile-time option data is now included in another message +immediately following the build info version string, starting with +`[OPT:`. A character code follows the data type name with each +indicating a particular option enabled or disabled. This will help +immensely with debugging Grbl as well as help GUIs know exactly how +Grbl was compiled. + +- These interface changes are detailed in the updated documentation. + +- Reduced the default planner buffer size from 17 to 16. Needed to free +up some memory… + +- For increasing the serial TX buffer size from 90 to 104 bytes. The +addition of real-time spindle speeds and accessory enable data required +a bigger buffer. This is to ensure Grbl is performing at optimal levels. + +- Refactored parts of the spindle and coolant control code to make it +more consistent to each other and how it was called. It was a little +messy. The changes made it easier to track what each function call was +doing based on what was calling it. + +- Created a couple of new get_state functions for the spindle and +coolant. These are called by the accessory state report to look +directly at the pin state, rather than track how it was set. This +guarantees that the state is reported correctly. + +- Updated the g-code parser, parking motion, sleep mode, and spindle +stop calls to refactored spindle and coolant code. + +- Added a compile-time option to enable homing individual axes, rather +than having only the main homing cycle. The actual use case for this is +pretty rare. It’s not recommended you enable this, unless you have a +specific application for it. Otherwise, just alter the homing cycle +itself. + +- Refactored the printFloat() function to not show a decimal point if +there are no trailing values after it. For example, `1.` now shows `1`. + +- Fixed an issue regarding spindle speed overrides no being applied to +blocks without motions. + +- Removed the toggle_ovr_mask system variable and replaced with +spindle_stop_ovr system variable. Coolant toggles don’t need to be +tracked. + +- Updated README + + +---------------- +Date: 2016-10-17 +Author: Will Winder +Subject: Modify code CSV format. (#10) + +- Wrap value in quotes to avoid issue with embedded commas. This occurs + in one of the alarm codes. + +- Change header row format to allow same parsing code as data rows. + +---------------- +Date: 2016-10-12 +Author: chamnit +Subject: Merge branch 'dev' into edge + + +---------------- +Date: 2016-10-12 +Author: chamnit +Subject: Added settings documentation. Very minor bug fix to step direction handling. + +- Added v1.1 settings documentation to the markdown folder. + +- Fixed a very minor bug in the step direction handling upon wakeup. +The direction mask would temporarily go back to default mask for about +a millisecond when moving in the same non-default direction. It did not +effect Grbl behavior before, but fixed for consistency. + + +---------------- +Date: 2016-10-12 +Author: Sonny Jeon +Subject: Spindle speed bug fix. + +- Spindle speed updating wasn’t working in the g-code parser due to +some borked up logic on my part. Fixed it and should be operating as +intended for both normal and laser spindle modes. + +- Elaborated a little more on the new sleep mode in the documentation. + + +---------------- +Date: 2016-10-11 +Author: Sonny Jeon +Subject: v1.1c: New sleep mode. Laser mode and other bug fixes. + +- New $SLP sleep mode that will disable spindle, coolant, and stepper +enable pins. Allows users to disable their steppers without having to +alter their settings. A reset is required to exit and re-initializes in +alarm state. + +- Laser mode wasn’t updating the spindle PWM correctly (effected +spindle speed overrides) and not checking for modal states either. +Fixed both issues. + +- While in laser mode, parking motions are ignored, since the power off +delay with the retract motion would burn the material. It will just +turn off and not move. A restore immediately powers up and resumes. No +delays. + +- Changing rpm max and min settings did not update the spindle PWM +calculations. Now fixed. + +- Increased default planner buffer from 16 to 17 block. It seems to be +stable, but need to monitor this carefully. + +- Removed software debounce routine for limit pins. Obsolete. + +- Fixed a couple parking motion bugs. One related to restoring +incorrectly and the other the parking rate wasn’t compatible with the +planner structs. + +- Fixed a bug caused by refactoring the critical alarms in a recent +push. Soft limits weren’t invoking a critical alarm. + +- Updated the documentation with the new sleep feature and added some +more details to the change summary. + + +---------------- +Date: 2016-09-28 +Author: Sonny Jeon +Subject: New jog cancel real-time command. Parser typo fix from last push. + +- Added a new jog cancel real-time command. Rather than depending on a +feed hold to cancel a jogging motion, this realtime command can be used +instead. The main advantage is if a feed hold is used, you can +accidentally hold the machine right when Grbl returns to IDLE after +completing a jog. And the GUI doesn’t have to worry about tracking this +either. + +- Fixed a typo in the g-code parser edits from the last push. Was +causing the G10 set coordinate system command to not work correctly. + +- Updated the documentation with the jog cancel command. + + +---------------- +Date: 2016-09-27 +Author: Sonny Jeon +Subject: Refactored g-code parser. Saved 60bytes flash and some ram. Edited Readme. + +- Freed up another 60 bytes of flash and 12-24 bytes of stack RAM by +using the pre-allocated IJK arc offset vector that is guaranteed to be +not in use. Only G10 and G28/30 require fetching from EEPROM and +retaining extra data. Both commands use axis words, which rules out +G2/3 arcs using IJK offsets existing in same block. Not ideal, but +every byte helps. + +- Edited README. + + +---------------- +Date: 2016-09-27 +Author: Sonny Jeon +Subject: Update README and clarifications in jogging document. + + +---------------- +Date: 2016-09-26 +Author: Sonny Jeon +Subject: v1.1b: Tweaked Bf reports, jogging doc, saved another 160 bytes, minor bug fixes + +- Increment to v1.1b due to status report tweak. + +- Tweaked the buffer state status reports to show bytes and blocks +available, rather than in use. This does not require knowing the buffer +sizes beforehand. It’s implicit. + +- Also, since buffer states are not used by most devs (after +inquiries), it is no longer enabled by default and a status mask option +was added for this. + +- Fixed some typos and updated for the report tweak in the +documentation. + +- Wrote a joystick implementation concept in the jogging markdown +document. Outlines how to get a low-latency feel to a joystick (and +other input devices). + +- Removed XON/XOFF support. It’s not used by anyone because of its +inherent problems. Remains in older versions for reference. + +- Added a compile option on how to handle the probe position during a +check mode. + +- Fixed a jogging bug. If G93 is the modal state before a jogging +motion, the feed rate did not get calculated correctly. Fixed the issue. + +- Refactored some code to save another 160+ bytes. Included an improved +float vector comparison macro and reducing a few large and repetitive +function calls. + +- Fixed a probing bug (existing in v0.9 too) where the target positions +were not set correct and error handling was improper. + + +---------------- +Date: 2016-09-25 +Author: Sonny Jeon +Subject: Addressed much larger flash size with avr-gcc v4.9.2. Refactored reports to save 160KB. + +- The newest Arduino IDE 1.6.12 has recently updated to avr-gcc v4.9.2. +Unfortunately, it produces a compiled size almost 0.7KB to 1KB larger +than prior versions! This can easily cause the base build to exceed the +Arduino Duemilanove/Nano flash limit of 30.5KB. The Arduino Uno seems +to be ok still with its 31.5KB flash limit. + +- Makefile `-flto` compile flag added to cut down on the horrible flash +size when using the new avr-gcc. (Edit Makefile and remove comment on +COMPILE definition). This brings it in-line with what the IDE produces. + +- Functionalized repetitive tasks in report.c to try to reduce overall +flash size. Successfully cut down about 160bytes. + +- Removed printFloat_SettingValue() and printFloat_RPMValue() +functions. These aren’t required and can be replaced with a direct call +to printFloat() because they don’t require a unit conversion check. + + +---------------- +Date: 2016-09-24 +Author: Sonny Jeon +Subject: Serial RX count bug fix. Settings codes CSV. More documentation. + +- Reverted back the serial RX count function to how it was. The +variable type was unsigned and cause an integer underflow whenever the +calculation produced a negative number. The old way was the correct way. + +- Lots of minor edits to the code CSVs and markdown documents. + +- Expanded on explaining feedback messages and startup line execution +feedback. + +- Created a new settings codes CSV to help GUIs import the values and +meanings. + + +---------------- +Date: 2016-09-22 +Author: Sonny Jeon +Subject: Increment to v1.1a, minor compile bug fix, tweaked communication protocol, more docs. + +- Incremented to v1.1a, rather than keep 1.0e. This is because there +are existing v1.0 installations. Don’t want to confuse people further. + +- Certain version of the Arduino IDE did not like the `inline` in the +function header. Removed from spindle_control files to fix the problem. + +- Tweaked the communication protocol slightly. Added message type +indicators for all `[]`bracketed feedback messages. It’s been +problematic for GUI dev to try to determine the context of a message +and how it should be handled. These indictors should help tremendously +to remove context all together. + +- Also altered how `$N` startup lines are presented when executed. They +now start with an open chevron ‘>’ followed by the line and an ‘:ok’ to +indicate it executed. The ‘ok’ is on the same line intentionally so it +doesn’t mess up a streaming protocol counter. + +- Managed to save a 100+KB from refactoring parts of report.c. (Thanks +Vasilis!) Freed up room to alter the protocol a little. + +- Wrote a markdown document on interface messaging to make it clear how +it’s intended to work. See interface.md in /doc/markdown + +- Started to pull in some Wiki pages from the old grbl site and +beginning to update them for v1.1. + +- Created new commit log for v1.1. + + +---------------- +Date: 2016-09-22 +Author: Sonny Jeon +Subject: Merge pull request #1 from winder/dev + +Add locale to code CSVs. + +---------------- +Date: 2016-09-22 +Author: winder +Subject: Add locale to code CSVs. + + +---------------- +Date: 2016-09-21 +Author: chamnit +Subject: Grbl v1.0e huge beta release. Overrides and new reporting. + +- Feature: Realtime feed, rapid, and spindle speed overrides. These +alter the running machine state within tens of milliseconds! + - Feed override: 100%, +/-10%, +/-1% commands with values 1-200% of +programmed feed + - Rapid override: 100%, 50%, 25% rapid rate commands + - Spindle speed override: 100%, +/-10%, +/-1% commands with values +50-200% of programmed speed + - Override values have configurable limits and increments in +config.h. +- Feature: Realtime toggle overrides for spindle stop, flood coolant, +and optionally mist coolant + - Spindle stop: Enables and disables spindle during a feed hold. +Automatically restores last spindles state. + - Flood and mist coolant: Immediately toggles coolant state until +next toggle or g-code coolant command. +- Feature: Jogging mode! Incremental and absolute modes supported. + - Grbl accepts jogging-specific commands like $J=X100F50. An axis +word and feed rate are required. G20/21 and G90/G91 commands are +accepted. + - Jog motions can be canceled at any time by a feed hold `!` +command. The buffer is automatically flushed. (No resetting required). + - Jog motions do not alter the g-code parser state so GUIs don’t +have to track what they changed and correct it. +- Feature: Laser mode setting. Allows Grbl to execute continuous +motions with spindle speed and state changes. +- Feature: Significantly improved status reports. Overhauled to cram in +more meaningful data and still make it smaller on average. + - All available data is now sent by default, but does not appear if +it doesn’t change or is not active. + - Machine position(MPos) or work position(WPos) is reported but not +both at the same time. Instead, the work coordinate offsets (WCO)are +sent intermittently whenever it changes or refreshes after 10-30 status +reports. Position vectors are easily computed by WPos = MPos - WCO. + - All data has changed in some way. Details of changes are in the +markdown documents and wiki. +- Feature: 16 new realtime commands to control overrides. All in +extended-ASCII character space. + - While they are not easily typeable and requires a GUI, they can’t +be accidentally triggered by some latent character in the g-code +program and have tons of room for expansion. +- Feature: New substates for HOLD and SAFETY DOOR. A `:x` is appended +to the state, where `x` is an integer and indicates a substate. + - For example, each integer of a door state describes in what phase +the machine is in during parking. Substates are detailed in the +documentation. +- Feature: With the alarm codes, homing and probe alarms have been +expanded with more codes to provide more exact feedback on what caused +the alarm. +- Feature: New hard limit check upon power-up or reset. If detected, a +feedback message to check the limit switches sent immediately after the +welcome message. + - May be disabled in config.h. + +- OEM feature: Enable/disable `$RST=` individual commands based on +desired behavior in config.h. +- OEM feature: Configurable EEPROM wipe to prevent certain data from +being deleted during firmware upgrade to a new settings version or +`RST=*` command. +- OEM feature: Enable/disable the `$I=` build info write string with +external EEPROM write example sketch. + - This prevents a user from altering the build info string in +EEPROM. This requires the vendor to write the string to EEPROM via +external means. An Arduino example sketch is provided to accomplish +this. This would be useful for contain product data that is +retrievable. + +- Tweak: All feedback has been drastically trimmed to free up flash +space for the v1.0 release. + - The `$` help message is just one string, listing available +commands. + - The `$$` settings printout no longer includes descriptions. Only +the setting values. (Sorry it’s this or remove overrides!) + - Grbl `error:` and `ALARM:` responses now only contain codes. No +descriptions. All codes are explained in documentation. + - Grbl’s old feedback style may be restored via a config.h, but +keep in mind that it will likely not fit into the Arduino’s flash space. +- Tweak: Grbl now forces a buffer sync or stop motion whenever a g-code +command needs to update and write a value to EEPROM or changes the work +coordinate offset. + - This addresses two old issues in all prior Grbl versions. First, +an EEPROM write requires interrupts to be disabled, including stepper +and serial comm. Steps can be lost and data can be corrupted. Second, +the work position may not be correlated to the actual machine position, +since machine position is derived from the actual current execution +state, while work position is based on the g-code parser offset state. +They are usually not in sync and the parser state is several motions +behind. This forced sync ensures work and machine positions are always +correct. + - This behavior can be disabled through a config.h option, but it’s +not recommended to do so. +- Tweak: To make status reports standardized, users can no longer +change what is reported via status report mask, except for only +toggling machine or work positions. + - All other data fields are included in the report and can only be +disabled through the config.h file. It’s not recommended to alter this, +because GUIs will be expecting this data to be present and may not be +compatible. +- Tweak: Homing cycle and parking motion no longer report a negative +line number in a status report. These will now not report a line number +at all. +- Tweak: New `[Restoring spindle]` message when restoring from a +spindle stop override. Provides feedback what Grbl is doing while the +spindle is powering up and a 4.0 second delay is enforced. +- Tweak: Override values are reset to 100% upon M2/30. This behavior +can be disabled in config.h +- Tweak: The planner buffer size has been reduced from 18 to 16 to free +up RAM for tracking and controlling overrides. +- Tweak: TX buffer size has been increased from 64 to 90 bytes to +improve status reporting and overall performance. +- Tweak: Removed the MOTION CANCEL state. It was redundant and didn’t +affect Grbl’s overall operation by doing so. +- Tweak: Grbl’s serial buffer increased by +1 internally, such that 128 +bytes means 128, not 127 due to the ring buffer implementation. Long +overdue. +- Tweak: Altered sys.alarm variable to be set by alarm codes, rather +than bit flags. Simplified how it worked overall. +- Tweak: Planner buffer and serial RX buffer usage has been combined in +the status reports. +- Tweak: Pin state reporting has been refactored to report only the +pins “triggered” and nothing when not “triggered”. +- Tweak: Current machine rate or speed is now included in every report. +- Tweak: The work coordinate offset (WCO) and override states only need +to be refreshed intermittently or reported when they change. The +refresh rates may be altered for each in the config.h file with +different idle and busy rates to lessen Grbl’s load during a job. +- Tweak: For temporary compatibility to existing GUIs until they are +updated, an option to revert back to the old style status reports is +available in config.h, but not recommended for long term use. +- Tweak: Removed old limit pin state reporting option from config.h in +lieu of new status report that includes them. +- Tweak: Updated the defaults.h file to include laser mode, altered +status report mask, and fix an issue with a missing invert probe pin +default. + +- Refactor: Changed how planner line data is generated and passed to +the planner and onto the step generator. By making it a struct +variable, this saved significant flash space. +- Refactor: Major re-factoring of the planner to incorporate override +values and allow for re-calculations fast enough to immediately take +effect during operation. No small feat. +- Refactor: Re-factored the step segment generator for re-computing new +override states. +- Refactor: Re-factored spindle_control.c to accommodate the spindle +speed overrides and laser mode. +- Refactor: Re-factored parts of the codebase for a new jogging mode. +Still under development though and slated to be part of the official +v1.0 release. Hang tight. +- Refactor: Created functions for computing a unit vector and value +limiting based on axis maximums to free up more flash. +- Refactor: The spindle PWM is now set directly inside of the stepper +ISR as it loads new step segments. +- Refactor: Moved machine travel checks out of soft limits function +into its own since jogging uses this too. +- Refactor: Removed coolant_stop() and combined with +coolant_set_state(). +- Refactor: The serial RX ISR forks off extended ASCII values to +quickly assess the new override realtime commands. +- Refactor: Altered some names of the step control flags. +- Refactor: Improved efficiency of the serial RX get buffer count +function. +- Refactor: Saved significant flash by removing and combining print +functions. Namely the uint8 base10 and base2 functions. +- Refactor: Moved the probe state check in the main stepper ISR to +improve its efficiency. +- Refactor: Single character printPgmStrings() went converted to direct +serial_write() commands to save significant flash space. + +- Documentation: Detailed Markdown documents on error codes, alarm +codes, messages, new real-time commands, new status reports, and how +jogging works. More to come later and will be posted on the Wiki as +well. +- Documentation: CSV files for quick importing of Grbl error and alarm +codes. + +- Bug Fix: Applied v0.9 master fixes to CoreXY homing. +- Bug Fix: The print float function would cause Grbl to crash if a +value was 1e6 or greater. Increased the buffer by 3 bytes to help +prevent this in the future. +- Bug Fix: Build info and startup string EEPROM restoring was not +writing the checksum value. +- Bug Fix: Corrected an issue with safety door restoring the proper +spindle and coolant state. It worked before, but breaks with laser mode +that can continually change spindle state per planner block. +- Bug Fix: Move system position and probe position arrays out of the +system_t struct. Ran into some compiling errors that were hard to track +down as to why. Moving them out fixed it. + diff --git a/doc/markdown/change_summary.md b/doc/markdown/change_summary.md new file mode 100644 index 0000000..7825676 --- /dev/null +++ b/doc/markdown/change_summary.md @@ -0,0 +1,114 @@ +### _Grbl v1.1 - Change Summary_ + +-------- + +### _Specific details are available in the other markdown documents._ +-------- + +#### GUI Interface Tweaks from Grbl v0.9 + +Grbl v1.1's interface protocol has been tweaked in the attempt to make GUI development cleaner, clearer, and hopefully easier. All messages are designed to be deterministic without needing to know the context of the message. Each can be inferred to a much greater degree than before just by the message type, which are all listed below. + +- `ok` / `error:x` : Normal send command and execution response acknowledgement. Used for streaming. + +- `< >` : Enclosed chevrons contains status report data. + +- `Grbl X.Xx ['$' for help]` : Welcome message indicates initialization. + +- `ALARM:x` : Indicates an alarm has been thrown. Grbl is now in an alarm state. + +- `$x=val` and `$Nx=line` indicate a settings printout from a `$` and `$N` user query, respectively. + +- `[MSG:]` : Indicates a non-queried feedback message. + +- `[GC:]` : Indicates a queried `$G` g-code state message. + +- `[HLP:]` : Indicates the help message. + +- `[G54:]`, `[G55:]`, `[G56:]`, `[G57:]`, `[G58:]`, `[G59:]`, `[G28:]`, `[G30:]`, `[G92:]`, `[TLO:]`, and `[PRB:]` messages indicate the parameter data printout from a `$#` user query. + +- `[VER:]` : Indicates build info and string from a `$I` user query. + +- `[OPT:]` : Indicates compile-time option info from a `$I` user query. + +- `[echo:]` : Indicates an automated line echo from a pre-parsed string prior to g-code parsing. Enabled by config.h option. + +- `>G54G20:ok` : The open chevron indicates startup line execution. The `:ok` suffix shows it executed correctly without adding an unmatched `ok` response on a new line. + +In addition, all `$x=val` settings, `error:`, and `ALARM:` messages no longer contain human-readable strings, but rather codes that are defined in other documents. The `$` help message is also reduced to just showing the available commands. Doing this saves incredible amounts of flash space. Otherwise, the new overrides features would not have fit. + +Other minor changes and bug fixes that may effect GUI parsing include: + +- Floating point values printed with zero precision do not show a decimal, or look like an integer. This includes spindle speed RPM and feed rate in mm mode. +- `$G` reports fixed a long time bug with program modal state. It always showed `M0` program pause when running. Now during a normal program run, no program modal state is given until an `M0`, `M2`, or `M30` is active and then the appropriate state will be shown. + +On a final note, these interface tweaks came about out of necessity, because more data is being sent back from Grbl, it is capable of doing many more things, and flash space is at a premium. It's not intended to be altered again in the near future, if at all. This is likely the only and last major change to this. If you have any comments or suggestions before Grbl v1.1 goes to master, please do immediately so we can all vet the new alteration before its installed. + +---- + +#### Realtime Status Reports Changes from Grbl v0.9 + +- Intent of changes is to make parsing cleaner, reduce transmitting overhead without effecting overall Grbl performance, and add more feedback data, which includes three new override values and real-time velocity. + +- Data fields are separated by `|` pipe delimiters, rather than `,` commas that were used to separate data values. This should help with parsing. + +- The ability to mask and add/remove data fields from status reports via the `$10` status report mask setting has been disabled. Only selecting `MPos:` or `WPos:` coordinates is allowed. + - All available data is always sent to standardize the reports across all GUIs. + - For unique situations, data fields can be removed by config.h macros, but it is highly recommended to not alter these. + + +- `MPos:` OR `WPos:` are always included in a report, but not BOTH at the same time. + + - This reduces transmit overhead tremendously by removing upwards to 40 characters. + - `WCO:0.000,10.000,2.500` A current work coordinate offset is now sent to easily convert between position vectors, where `WPos = MPos - WCO` for each axis. + - `WCO:` is included immediately whenever a `WCO:` value changes or intermittently after every **X** status reports as a refresh. Refresh rates can dynamically vary from 10 to 30 (configurable) reports depending on what Grbl is doing. + - `WCO:` is simply the sum of the work coordinate system, G92, and G43.1 tool length offsets. + - Basically, a GUI just needs to retain the last `WCO:` and apply the equation to get the other position vector. + - `WCO:` messages may only be disabled via a config.h compile-option, if a GUI wants to handle the work position calculations on its own to free up more transmit bandwidth. + - Be aware of the following issue regarding `WPos:`. + - In Grbl v0.9 and prior, there is an old outstanding bug where the `WPos:` work position reported may not correlate to what is executing, because `WPos:` is based on the g-code parser state, which can be several motions behind. Grbl v1.1 now forces the planner buffer to empty, sync, and stops motion whenever there is a command that alters the work coordinate offsets `G10,G43.1,G92,G54-59`. This is the simplest way to ensure `WPos:` is always correct. Fortunately, it's exceedingly rare that any of these commands are used need continuous motions through them. + - A compile-time option is available to disable the planner sync and forced stop, but, if used, it's up to the GUI to handle this position correlation issue. + + +- The `Hold` and `Door` states includes useful sub-state info via a `:` colon delimiter and an integer value. See descriptions for details. + +- Limit and other input pin reports have significantly changed to reduce transmit overhead. + - The data type description is now just `Pn:`, rather than `Lim:000` or `Pin:000|0|0000` + - It does not appear if no inputs are detected as triggered. + - If an input is triggered, ```Pn:``` will be followed by a letter or set of letters of every triggered input pin. `XYZPDHRS` for the XYZ-axes limits, Probe, Door, Hold, soft-Reset, cycle Start pins, respectively. + - For example, a triggered Z-limit and probe pin would report `Pn:ZP`. + + +- Buffer data (planner and serial RX) reports have been tweaked and combined. + + - `Bf:15,128`. The first value is the available blocks in the planner buffer and the second is available bytes in the serial RX buffer. + - Note that this is different than before, where it reported blocks/bytes "in-use", rather than "available". This change does not require a GUI to know how many blocks/bytes Grbl has been compiled with, which can be substantially different on a Grbl-Mega build. + + +- Override reports are intermittent since they don't change often once set. + + - Overrides are included in every 10 or 20 status reports (configurable) depending on what Grbl is doing or, if an override value or toggle state changes, automatically in the next report. + - There are two override fields: + - `Ov:100,100,100` Organized as feed, rapid, and spindle speed overrides in percent. + +- Accessory states are shown alongside override reports when they are active. Like pin states, an accessory state report `A:SFM` contains a letter indicating an active accessory. Letters `S`, `C`, `F`, and `M` are defined as spindle CW, spindle CCW, flood coolant, and mist coolant, respectively. The pins are directly polled and shown here. + +- Line numbers, when enabled in config.h, are omitted when: + + - No line number is passed to Grbl in a block. + - Grbl is performing a system motion like homing, jogging, or parking. + - Grbl is executing g-code block that does not contain a motion, like `G20G54` or `G4P1` dwell. (NOTE: Looking to fixing this later.) + +------- + +#### New Commands + +- `$SLP` - Grbl v1.1 now has a sleep mode that can be invoked by this command. It requires Grbl to be in either an IDLE or ALARM state. Once invoked, Grbl will de-energize all connected systems, including the spindle, coolant, and stepper drivers. It'll enter a suspend state that can only be exited by a reset. When reset, Grbl will re-initiatize in an ALARM state because the steppers were disabled and position can not be guaranteed. + - NOTE: Grbl-Mega can invoke the sleep mode at any time, when the sleep timeout feature is enabled in config.h. It does so when Grbl has not received any external input after a timeout period. + +- `$J=line` New jogging commands. This command behaves much like a normal G1 command, but there are some key differences. Jog commands don't alter the g-code parser state, meaning a GUI doesn't have to manage it anymore. Jog commands may be queued and cancelled at any time, where they are automatically flushed from the planner buffer without requiring a reset. See the jogging documentation on how they work and how they may be used to implement a low-latency joystick or rotary dial. + +- Laser mode `$` setting - When enabled, laser mode will move through consecutive G1, G2, and G3 motion commands that have different spindle speed values without stopping. A spindle speed of zero will disable the laser without stopping as well. However, when spindle states change, like M3 or M5, stops are still enforced. + - NOTE: Parking motions are automatically disabled when laser mode is enabled to prevent burning. + +- `G56 P1` and `G56 P0` - When enabled in config.h with Grbl's parking motion, these commands enable and disable, respectively, the parking motion. Like all override control commands, these commands are modal and are part of the g-code stream. \ No newline at end of file diff --git a/doc/markdown/commands.md b/doc/markdown/commands.md new file mode 100644 index 0000000..5facba9 --- /dev/null +++ b/doc/markdown/commands.md @@ -0,0 +1,345 @@ +# Grbl v1.1 Commands + +In general, Grbl assumes all characters and streaming data sent to it is g-code and will parse and try to execute it as soon as it can. However, Grbl also has two separate system command types that are outside of the normal g-code streaming. One system command type is streamed to Grbl like g-code, but starts with a `$` character to tell Grbl it's not g-code. The other is composed of a special set of characters that will immediately command Grbl to do a task in real-time. It's not part of the g-code stream. Grbl's system commands do things like control machine state, report saved parameters or what Grbl is doing, save or print machine settings, run a homing cycle, or make the machine move faster or slower than programmed. This document describes these "internal" system Grbl commands, what they do, how they work, and how to use them. + +## Getting Started + +First, connect to Grbl using the serial terminal of your choice. + +Set the baud rate to **115200** as 8-N-1 (8-bits, no parity, and 1-stop bit.) + +Once connected + you should get the Grbl-prompt, which looks like this: + +``` +Grbl 1.1e ['$' for help] +``` + +Type $ and press enter to have Grbl print a help message. You should not see any local echo of the $ and enter. Grbl should respond with: + +``` +[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x] +``` + +The ‘$’-commands are Grbl system commands used to tweak the settings, view or change Grbl's states and running modes, and start a homing cycle. The last four **non**-'$' commands are realtime control commands that can be sent at anytime, no matter what Grbl is doing. These either immediately change Grbl's running behavior or immediately print a report of the important realtime data like current position (aka DRO). There are over a dozen more realtime control commands, but they are not user type-able. See realtime command section for details. + +*** + +## Grbl '$' Commands + +The `$` system commands provide additional controls for the user, such as printing feedback on the current G-code parser modal state or running the homing cycle. This section explains what these commands are and how to use them. + +#### `$$`and `$x=val` - View and write Grbl settings +See [Grbl v1.1 Configuration](https://github.com/gnea/grbl/wiki/Grbl-v1.1-Configuration#grbl-settings) for more details on how to view and write setting and learn what they are. + +#### `$#` - View gcode parameters + +G-code parameters store the coordinate offset values for G54-G59 work coordinates, G28/G30 pre-defined positions, G92 coordinate offset, tool length offsets, and probing (not officially, but we added here anyway). Most of these parameters are directly written to EEPROM anytime they are changed and are persistent. Meaning that they will remain the same, regardless of power-down, until they are explicitly changed. The non-persistent parameters, which will are not retained when reset or power-cycled, are G92, G43.1 tool length offsets, and the G38.2 probing data. + +G54-G59 work coordinates can be changed via the `G10 L2 Px` or `G10 L20 Px` command defined by the NIST gcode standard and the EMC2 (linuxcnc.org) standard. G28/G30 pre-defined positions can be changed via the `G28.1` and the `G30.1` commands, respectively. + +When `$#` is called, Grbl will respond with the stored offsets from machine coordinates for each system as follows. `TLO` denotes tool length offset (for the default z-axis), and `PRB` denotes the coordinates of the last probing cycle, where the suffix `:1` denotes if the last probe was successful and `:0` as not successful. + +``` +[G54:4.000,0.000,0.000] +[G55:4.000,6.000,7.000] +[G56:0.000,0.000,0.000] +[G57:0.000,0.000,0.000] +[G58:0.000,0.000,0.000] +[G59:0.000,0.000,0.000] +[G28:1.000,2.000,0.000] +[G30:4.000,6.000,0.000] +[G92:0.000,0.000,0.000] +[TLO:0.000] +[PRB:0.000,0.000,0.000:0] +``` + +#### `$G` - View gcode parser state + +This command prints all of the active gcode modes in Grbl's G-code parser. When sending this command to Grbl, it will reply with a message starting with an `[GC:` indicator like: + +``` +[GC:G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 S0.0 F500.0] +``` + +These active modes determine how the next G-code block or command will be interpreted by Grbl's G-code parser. For those new to G-code and CNC machining, modes sets the parser into a particular state so you don't have to constantly tell the parser how to parse it. These modes are organized into sets called "modal groups" that cannot be logically active at the same time. For example, the units modal group sets whether your G-code program is interpreted in inches or in millimeters. + +A short list of the modal groups, supported by Grbl, is shown below, but more complete and detailed descriptions can be found at LinuxCNC's [website](http://www.linuxcnc.org/docs/2.4/html/gcode_overview.html#sec:Modal-Groups). The G-code commands in **bold** indicate the default modes upon powering-up Grbl or resetting it. The commands in _italics_ indicate a special Grbl-only command. + +| Modal Group Meaning | Member Words | +|:----:|:----:| +| Motion Mode | **G0**, G1, G2, G3, G38.2, G38.3, G38.4, G38.5, G80 | +|Coordinate System Select | **G54**, G55, G56, G57, G58, G59| +|Plane Select | **G17**, G18, G19| +|Distance Mode | **G90**, G91| +|Arc IJK Distance Mode | **G91.1** | +|Feed Rate Mode | G93, **G94**| +|Units Mode | G20, **G21**| +|Cutter Radius Compensation | **G40** | +|Tool Length Offset |G43.1, **G49**| +|Program Mode | **M0**, M1, M2, M30| +|Spindle State |M3, M4, **M5**| +|Coolant State | M7, M8, **M9** | +|Override Control | _M56_ | + +Grbl supports a special _M56_ override control command, where this enables and disables Grbl's parking motion when a `P1` or a `P0` is passed with `M56`, respectively. This command is only available when both parking and this particular option is enabled. + +In addition to the G-code parser modes, Grbl will report the active `T` tool number, `S` spindle speed, and `F` feed rate, which all default to 0 upon a reset. For those that are curious, these don't quite fit into nice modal groups, but are just as important for determining the parser state. + +#### `$I` - View build info +This prints feedback to the user the Grbl version and source code build date. Optionally, `$I` can also store a short string to help identify which CNC machine you are communicating with, if you have more than machine using Grbl. To set this string, send Grbl `$I=xxx`, where `xxx` is your customization string that is less than 80 characters. The next time you query Grbl with a `$I` view build info, Grbl will print this string after the version and build date. + +NOTE: Some OEMs may block access to over-writing the build info string so they can store product information and codes there. + +#### $N - View startup blocks + +`$Nx` are the startup blocks that Grbl runs every time you power on Grbl or reset Grbl. In other words, a startup block is a line of G-code that you can have Grbl auto-magically run to set your G-code modal defaults, or anything else you need Grbl to do everytime you start up your machine. Grbl can store two blocks of G-code as a system default. + +So, when connected to Grbl, type `$N` and then enter. Grbl should respond with something short like: +``` +$N0= +$N1= +ok +``` +Not much to go on, but this just means that there is no G-code block stored in line `$N0` for Grbl to run upon startup. `$N1` is the next line to be run. + +#### $Nx=line - Save startup block + +**IMPORTANT: Be very careful when storing any motion (G0/1,G2/3,G28/30) commands in the startup blocks. These motion commands will run everytime you reset or power up Grbl, so if you have an emergency situation and have to e-stop and reset, a startup block move can and will likely make things worse quickly. Also, do not place any commands that save data to EEPROM, such as G10/G28.1/G30.1. This will cause Grbl to constantly re-write this data upon every startup and reset, which will eventually wear out your Arduino's EEPROM.** + +**Typical usage for a startup block is simply to set your preferred modal states, such as G20 inches mode, always default to a different work coordinate system, or, to provide a way for a user to run some user-written unique feature that they need for their crazy project.** + +To set a startup block, type `$N0=` followed by a valid G-code block and an enter. Grbl will run the block to check if it's valid and then reply with an `ok` or an `error:` to tell you if it's successful or something went wrong. If there is an error, Grbl will not save it. + +For example, say that you want to use your first startup block `$N0` to set your G-code parser modes like G54 work coordinate, G20 inches mode, G17 XY-plane. You would type `$N0=G20 G54 G17` with an enter and you should see an `ok` response. You can then check if it got stored by typing `$N` and you should now see a response like `$N0=G20G54G17`. + +Once you have a startup block stored in Grbl's EEPROM, everytime you startup or reset you will see your startup block printed back to you, starting with an open-chevron `>`, and a `:ok` response from Grbl to indicate if it ran okay. So for the previous example, you'll see: + +``` +Grbl 1.1d ['$' for help] +>G20G54G17:ok + +``` +If you have multiple G-code startup blocks, they will print back to you in order upon every startup. And if you'd like to clear one of the startup blocks, (e.g., block 0) type `$N0=` without anything following the equal sign. + +NOTE: There are two variations on when startup blocks with run. First, it will not run if Grbl initializes up in an ALARM state or exits an ALARM state via an `$X` unlock for safety reasons. Always address and cancel the ALARM and then finish by a reset, where the startup blocks will run at initialization. Second, if you have homing enabled, the startup blocks will execute immediately after a successful homing cycle, not at startup. + +#### `$C` - Check gcode mode +This toggles the Grbl's gcode parser to take all incoming blocks and process them completely, as it would in normal operation, but it does not move any of the axes, ignores dwells, and powers off the spindle and coolant. This is intended as a way to provide the user a way to check how their new G-code program fares with Grbl's parser and monitor for any errors (and checks for soft limit violations, if enabled). + +When toggled off, Grbl will perform an automatic soft-reset (^X). This is for two purposes. It simplifies the code management a bit. But, it also prevents users from starting a job when their G-code modes are not what they think they are. A system reset always gives the user a fresh, consistent start. + +#### `$X` - Kill alarm lock +Grbl's alarm mode is a state when something has gone critically wrong, such as a hard limit or an abort during a cycle, or if Grbl doesn't know its position. By default, if you have homing enabled and power-up the Arduino, Grbl enters the alarm state, because it does not know its position. The alarm mode will lock all G-code commands until the '$H' homing cycle has been performed. Or if a user needs to override the alarm lock to move their axes off their limit switches, for example, '$X' kill alarm lock will override the locks and allow G-code functions to work again. + +But, tread carefully!! This should only be used in emergency situations. The position has likely been lost, and Grbl may not be where you think it is. So, it's advised to use G91 incremental mode to make short moves. Then, perform a homing cycle or reset immediately afterwards. + +As noted earlier, startup lines do not execute after a `$X` command. Always reset when you have cleared the alarm and fixed the scenario that caused it. When Grbl resets to idle, the startup lines will then run as normal. + +#### `$H` - Run homing cycle +This command is the only way to perform the homing cycle in Grbl. Some other motion controllers designate a special G-code command to run a homing cycle, but this is incorrect according to the G-code standards. Homing is a completely separate command handled by the controller. + +TIP: After running a homing cycle, rather jogging manually all the time to a position in the middle of your workspace volume. You can set a G28 or G30 pre-defined position to be your post-homing position, closer to where you'll be machining. To set these, you'll first need to jog your machine to where you would want it to move to after homing. Type G28.1 (or G30.1) to have Grbl store that position. So then after '$H' homing, you could just enter 'G28' (or 'G30') and it'll move there auto-magically. In general, I would just move the XY axis to the center and leave the Z-axis up. This ensures that there isn't a chance the tool in the spindle will interfere and that it doesn't catch on anything. + +#### `$Jx=line` - Run jogging motion + +New to Grbl v1.1, this command will execute a special jogging motion. There are three main differences between a jogging motion and a motion commanded by a g-code line. + +- Like normal g-code commands, several jog motions may be queued into the planner buffer, but the jogging can be easily canceled by a jog-cancel or feed-hold real-time command. Grbl will immediately hold the current jog and then automatically purge the buffers of any remaining commands. +- Jog commands are completely independent of the g-code parser state. It will not change any modes like `G91` incremental distance mode. So, you no longer have to make sure that you change it back to `G90` absolute distance mode afterwards. This helps reduce the chance of starting with the wrong g-code modes enabled. +- If soft-limits are enabled, any jog command that exceeds a soft-limit will simply return an error. It will not throw an alarm as it would with a normal g-code command. This allows for a much more enjoyable and fluid GUI or joystick interaction. + +Executing a jog requires a specific command structure, as described below: + + - The first three characters must be '$J=' to indicate the jog. + - The jog command follows immediate after the '=' and works like a normal G1 command. + - Feed rate is only interpreted in G94 units per minute. A prior G93 state is ignored during jog. + - Required words: + - XYZ: One or more axis words with target value. + - F - Feed rate value. NOTE: Each jog requires this value and is not treated as modal. + - Optional words: Jog executes based on current G20/G21 and G90/G91 g-code parser state. If one of the following optional words is passed, that state is overridden for one command only. + - G20 or G21 - Inch and millimeter mode + - G90 or G91 - Absolute and incremental distances + - G53 - Move in machine coordinates + - All other g-codes, m-codes, and value words are not accepted in the jog command. + - Spaces and comments are allowed in the command. These are removed by the pre-parser. + + - Example: G21 and G90 are active modal states prior to jogging. These are sequential commands. + - `$J=X10.0 Y-1.5` will move to X=10.0mm and Y=-1.5mm in work coordinate frame (WPos). + - `$J=G91 G20 X0.5` will move +0.5 inches (12.7mm) to X=22.7mm (WPos). Note that G91 and G20 are only applied to this jog command. + - `$J=G53 Y5.0` will move the machine to Y=5.0mm in the machine coordinate frame (MPos). If the work coordinate offset for the y-axis is 2.0mm, then Y is 3.0mm in (WPos). + +Jog commands behave almost identically to normal g-code streaming. Every jog command will +return an 'ok' when the jogging motion has been parsed and is setup for execution. If a +command is not valid or exceeds a soft-limit, Grbl will return an 'error:'. Multiple jogging commands may be queued in sequence. + +NOTE: See additional jogging documentation for details on using this command to create a low-latency joystick or rotary dial interface. + + +#### `$RST=$`, `$RST=#`, and `$RST=*`- Restore Grbl settings and data to defaults +These commands are not listed in the main Grbl `$` help message, but are available to allow users to restore parts of or all of Grbl's EEPROM data. Note: Grbl will automatically reset after executing one of these commands to ensure the system is initialized correctly. + +- `$RST=$` : Erases and restores the `$$` Grbl settings back to defaults, which is defined by the default settings file used when compiling Grbl. Often OEMs will build their Grbl firmwares with their machine-specific recommended settings. This provides users and OEMs a quick way to get back to square-one, if something went awry or if a user wants to start over. +- `$RST=#` : Erases and zeros all G54-G59 work coordinate offsets and G28/30 positions stored in EEPROM. These are generally the values seen in the `$#` parameters printout. This provides an easy way to clear these without having to do it manually for each set with a `G20 L2/20` or `G28.1/30.1` command. +- `$RST=*` : This clears and restores all of the EEPROM data used by Grbl. This includes `$$` settings, `$#` parameters, `$N` startup lines, and `$I` build info string. Note that this doesn't wipe the entire EEPROM, only the data areas Grbl uses. To do a complete wipe, please use the Arduino IDE's EEPROM clear example project. + +NOTE: Some OEMs may restrict some or all of these commands to prevent certain data they use from being wiped. + +#### `$SLP` - Enable Sleep Mode + +This command will place Grbl into a de-powered sleep state, shutting down the spindle, coolant, and stepper enable pins and block any commands. It may only be exited by a soft-reset or power-cycle. Once re-initialized, Grbl will automatically enter an ALARM state, because it's not sure where it is due to the steppers being disabled. + +This feature is useful if you need to automatically de-power everything at the end of a job by adding this command at the end of your g-code program, BUT, it is highly recommended that you add commands to first move your machine to a safe parking location prior to this sleep command. It also should be emphasized that you should have a reliable CNC machine that will disable everything when its supposed to, like your spindle. Grbl is not responsible for any damage it may cause. It's never a good idea to leave your machine unattended. So, use this command with the utmost caution! + + +*** + +## Grbl v1.1 Realtime commands + +Realtime commands are single control characters that may be sent to Grbl to command and perform an action in real-time. This means that they can be sent at anytime, anywhere, and Grbl will immediately respond, regardless of what it is doing at the time. These commands include a reset, feed hold, resume, status report query, and overrides (in v1.1). + +A realtime command: + +- Will execute within tens of milliseconds. + +- Is a single character that may be sent to Grbl at any time. + +- Does not require a line feed or carriage return after them. + +- Is not considered a part of the streaming protocol. + +- Are intercepted when they are received and never placed in a buffer to be parsed by Grbl. + +- Will ignore multiple commands until it has executed the first received command. + +- May be tied to an input pin and may be operated with a button or switch. + +- Actions depends on state or what Grbl is doing. It may not do anything. + +- Descriptions explain how they work and what to expect. + +#### ASCII Realtime Command Descriptions +Four realtime commands are type-able by users on a keyboard and shown in the `$` Grbl help message. These realtime command characters control some of Grbl's basic functions. + +- `0x18` (ctrl-x) : Soft-Reset + + - Immediately halts and safely resets Grbl without a power-cycle. + - Accepts and executes this command at any time. + - If reset while in motion, Grbl will throw an alarm to indicate position may be lost from the motion halt. + - If reset while in not motion, position is retained and re-homing is not required. + - An input pin is available to connect a button or switch. + + +- `?` : Status Report Query + + - Immediately generates and sends back runtime data with a status report. + - Accepts and executes this command at any time, except during a homing cycle and when critical alarm (hard/soft limit error) is thrown. + + +- `~` : Cycle Start / Resume + + - Resumes a feed hold, a safety door/parking state when the door is closed, and the M0 program pause states. + - Command is otherwise ignored. + - If the parking compile-time option is enabled and the safety door state is ready to resume, Grbl will re-enable the spindle and coolant, move back into position, and then resume. + - An input pin is available to connect a button or switch. + + +- `!` : Feed Hold + + - Places Grbl into a suspend or HOLD state. If in motion, the machine will decelerate to a stop and then be suspended. + - Command executes when Grbl is in an IDLE, RUN, or JOG state. It is otherwise ignored. + - If jogging, a feed hold will cancel the jog motion and flush all remaining jog motions in the planner buffer. The state will return from JOG to IDLE or DOOR, if was detected as ajar during the active hold. + - By machine control definition, a feed hold does not disable the spindle or coolant. Only motion. + - An input pin is available to connect a button or switch. + + +#### Extended-ASCII Realtime Command Descriptions + +Grbl v1.1 installed more than a dozen new realtime commands to control feed, rapid, and spindle overrides. To help prevent users from inadvertently altering overrides with a keystroke and allow for more commands later on, all of the new control characters have been moved to the extended ASCII character set. These are not easily type-able on a keyboard, but, depending on the OS, they may be entered using specific keystroke and code. GUI developers will need to be able to send extended ASCII characters, values `128 (0x80)` to `255 (0xFF)`, to Grbl to take advantage of these new features. + +- `0x84` : Safety Door + + - Although typically connected to an input pin to detect the opening of a safety door, this command allows a GUI to enact the safety door behavior with this command. + - Immediately suspends into a DOOR state and disables the spindle and coolant. If in motion, the machine will decelerate to a stop and then be suspended. + - If executed during homing, Grbl will instead halt motion and throw a homing alarm. + - If already in a suspend state or HOLD, the DOOR state supersedes it. + - If the parking compile-time option is enabled, Grbl will park the spindle to a specified location. + - Command executes when Grbl is in an IDLE, HOLD, RUN, HOMING, or JOG state. It is otherwise ignored. + - If jogging, a safety door will cancel the jog and all queued motions in the planner buffer. When the safety door is closed and resumed, Grbl will return to an IDLE state. + - An input pin is available to connect a button or switch, if enabled with a compile-time option. + - Some builds of Grbl v0.9 used the `@` character for this command, but it was undocumented. Moved to extended-ASCII to prevent accidental commanding. + + +- `0x85` : Jog Cancel + + - Immediately cancels the current jog state by a feed hold and automatically flushing any remaining jog commands in the buffer. + - Command is ignored, if not in a JOG state or if jog cancel is already invoked and in-process. + - Grbl will return to the IDLE state or the DOOR state, if the safety door was detected as ajar during the cancel. + + +- Feed Overrides + + - Immediately alters the feed override value. An active feed motion is altered within tens of milliseconds. + - Does not alter rapid rates, which include G0, G28, and G30, or jog motions. + - Feed override value can not be 10% or greater than 200%. + - If feed override value does not change, the command is ignored. + - Feed override range and increments may be changed in config.h. + - The commands are: + - `0x90` : Set 100% of programmed rate. + - `0x91` : Increase 10% + - `0x92` : Decrease 10% + - `0x93` : Increase 1% + - `0x94` : Decrease 1% + + +- Rapid Overrides + + - Immediately alters the rapid override value. An active rapid motion is altered within tens of milliseconds. + - Only effects rapid motions, which include G0, G28, and G30. + - If rapid override value does not change, the command is ignored. + - Rapid override set values may be changed in config.h. + - The commands are: + - `0x95` : Set to 100% full rapid rate. + - `0x96` : Set to 50% of rapid rate. + - `0x97` : Set to 25% of rapid rate. + + +- Spindle Speed Overrides + + - Immediately alters the spindle speed override value. An active spindle speed is altered within tens of milliseconds. + - Override values may be changed at any time, regardless of if the spindle is enabled or disabled. + - Spindle override value can not be 10% or greater than 200% + - If spindle override value does not change, the command is ignored. + - Spindle override range and increments may be altered in config.h. + - The commands are: + - `0x99` : Set 100% of programmed spindle speed + - `0x9A` : Increase 10% + - `0x9B` : Decrease 10% + - `0x9C` : Increase 1% + - `0x9D` : Decrease 1% + + +- `0x9E` : Toggle Spindle Stop + + - Toggles spindle enable or disable state immediately, but only while in the HOLD state. + - The command is otherwise ignored, especially while in motion. This prevents accidental disabling during a job that can either destroy the part/machine or cause personal injury. Industrial machines handle the spindle stop override similarly. + - When motion restarts via cycle start, the last spindle state will be restored and wait 4.0 seconds (configurable) before resuming the tool path. This ensures the user doesn't forget to turn it back on. + - While disabled, spindle speed override values may still be altered and will be in effect once the spindle is re-enabled. + - If a safety door is opened, the DOOR state will supersede the spindle stop override, where it will manage the spindle re-energizing itself upon closing the door and resuming. The prior spindle stop override state is cleared and reset. + + +- `0xA0` : Toggle Flood Coolant + + - Toggles flood coolant state and output pin until the next toggle or g-code command alters it. + - May be commanded at any time while in IDLE, RUN, or HOLD states. It is otherwise ignored. + - This override directly changes the coolant modal state in the g-code parser. Grbl will continue to operate normally like it received and executed an `M8` or `M9` g-code command. + - When `$G` g-code parser state is queried, the toggle override change will be reflected by an `M8` enabled or disabled with an `M9` or not appearing when `M7` is present. + + +- `0xA1` : Toggle Mist Coolant + + - Enabled by `ENABLE_M7` compile-time option. Default is disabled. + - Toggles mist coolant state and output pin until the next toggle or g-code command alters it. + - May be commanded at any time while in IDLE, RUN, or HOLD states. It is otherwise ignored. + - This override directly changes the coolant modal state in the g-code parser. Grbl will continue to operate normally like it received and executed an `M7` or `M9` g-code command. + - When `$G` g-code parser state is queried, the toggle override change will be reflected by an `M7` enabled or disabled with an `M9` or not appearing when `M8` is present. \ No newline at end of file diff --git a/doc/markdown/interface.md b/doc/markdown/interface.md new file mode 100644 index 0000000..e02c32e --- /dev/null +++ b/doc/markdown/interface.md @@ -0,0 +1,684 @@ +# Grbl Interface Basics + +The interface for Grbl is fairly simple and straightforward. With Grbl v1.1, steps have been taken to try to make it even easier for new users to get started, and for GUI developers to write their own custom interfaces to Grbl. + +Grbl communicates through the serial interface on the Arduino. You just need to connect your Arduino to your computer with a USB cable. Use any standard serial terminal program to connect to Grbl, such as: the Arduino IDE serial monitor, Coolterm, puTTY, etc. Or use one of the many great Grbl GUIs out there in the Internet wild. + +The primary way to talk to Grbl is performed by sending it a string of characters, followed by a carriage return. Grbl will then process the string, set it up for execution, and then reply back with a **response message**, also terminated by a return, to tell you how it went. These command strings include sending Grbl: a G-code block to execute, commands to configure Grbl's system settings, to view how Grbl is doing, etc. + +To stream a g-code program to Grbl, the basic interface is to send Grbl a line of g-code, then wait for the proper **response message** starting with an `ok` or `error`. This signals Grbl has completed the parsing and executing the command. At times, Grbl may not respond immediately. This happens when Grbl is busy doing something else or waiting to place a commanded motion into the look-ahead planner buffer. Other times, usually at the start of a program, Grbl may quickly respond to several lines, but nothing happens. This occurs when Grbl places a series of commanded motions directly in the planner queue and will try to fill it up completely before starting. + +Along with **response messages**, Grbl has **push messages** to provide more feedback on what Grbl is doing and are also strings terminated by a return. These messages may be "pushed" from Grbl to the user in response to a query or to let the user know something important just happened. These can come at any time, but usually from something like a settings print out when asked to. **Push messages** are easily identified because they don't start with an `ok` or `error` like **response messages** do. They are typically placed in `[]` brackets, `<>` chevrons, start with a `$`, or a specific string of text. These are all defined and described later in this document. + +Finally, Grbl has **real-time commands** that are invoked by a set of special characters that may be sent at any time and are not part of the basic streaming send-response interface. These cause Grbl to immediately execute the command and typically don't generate a response. These include pausing the current motion, speed up/down everything, toggle the spindle during a job, reset Grbl, or query Grbl for a real-time status report. See the `Commands` document to see what they are and how they work. + +------- + +# Writing an Interface for Grbl + +The general interface for Grbl has been described above, but what's missing is how to run an entire G-code program on Grbl, when it doesn't seem to have an upload feature. This is where this section fits in. Early on, users fiercely requested for flash drive, external RAM, LCD support, joysticks, or network support so they can upload a g-code program and run it directly on Grbl. The general answer to that is, good ideas, but Grbl doesn't need them. Grbl already has nearly all of the tools and features to reliably communicate with a graphical user interface (GUI) or a seperate host interface that provides all those extra bells and whistles. Grbl's base philosophy is to minimize what Grbl should be doing, because, in the end, Grbl needs to be concentrating on producing clean, reliable motion. That's it. + + +## Streaming a G-Code Program to Grbl + +Here we will describe two different streaming methods for Grbl GUIs. One of the main problems with streaming to Grbl is the USB port itself. Arduinos and most all micro controllers use a USB-to-serial converter chip that, at times, behaves strangely and not typically how you'd expect, like USB packet buffering and delays that can wreak havoc to a streaming protocol. Another problem is how to deal with some of the latency and oddities of the PCs themselves, because none of them are truly real-time and always create micro-delays when executing other tasks. Regardless, we've come up with ways to ensure the G-code stream is reliable and simple. + +The following streaming protocols require tracking the **response messages** to determine when to send the next g-code line. All **push messages** are not counted toward the streaming protocol and should be handled separately. All real-time command characters can be sent at any time and are never placed in Grbl's RX serial buffer. They are intercepted as they come in and simply sets flags for Grbl to execute them. + +#### Streaming Protocol: Simple Send-Response _[Recommended]_ +The send-response streaming protocol is the most fool-proof and simplest method to stream a G-code program to Grbl. The host PC interface simply sends a line of G-code to Grbl and waits for an `ok` or `error:` **response message** before sending the next line of G-code. So, no matter if Grbl needs to wait for room in the look-ahead planner buffer to finish parsing and executing the last line of G-code or if the the host computer is busy doing something, this guarantees both to the host PC and Grbl, the programmed G-code has been sent and received properly. An example of this protocol is published in our `simple_stream.py` script in our repository. + +However, it's also the slowest of three outlined streaming protocols. Grbl essentially has two buffers between the execution of steps and the host PC interface. One of them is the serial receive buffer. This briefly stores up to 127 characters of data received from the host PC until Grbl has time to fetch and parse the line of G-code. The other buffer is the look-ahead planner buffer. This buffer stores up to 16 line motions that are acceleration-planned and optimized for step execution. Since the send-response protocol receives a line of G-code while the host PC waits for a response, Grbl's serial receive buffer is usually empty and under-utilized. If Grbl is actively running and executing steps, Grbl will immediately begin to execute and empty the look-ahead planner buffer, while it sends the response to the host PC, waits for the next line from the host PC, upon receiving it, parse and plan it, and add it to the end of the look-ahead buffer. + +Although this communication lag may take only a fraction of a second, there is a cumulative effect, because there is a lag with every G-code block sent to Grbl. In certain scenarios, like a G-code program containing lots of sequential, very short, line segments with high feed rates, the cumulative lag can be large enough to empty and starve the look-ahead planner buffer within this time. This could lead to start-stop motion when the streaming can't keep up with G-code program execution. Also, since Grbl can only plan and optimize what's in the look-ahead planner buffer, the performance through these types of motions will never be full-speed, because look-ahead buffer will always be partially full when using this streaming method. If your expected application doesn't contain a lot of these short line segments with high feed rates, this streaming protocol should be more than adequate for a vast majority of applications, is very robust, and is a quick way to get started. + +#### Streaming Protocol: Character-Counting _[**Recommended with Reservation**]_ + +To get the best of both worlds, the simplicity and reliability of the send-response method and assurance of maximum performance with software flow control, we came up with a simple character-counting protocol for streaming a G-code program to Grbl. It works like the send-response method, where the host PC sends a line of G-code for Grbl to execute and waits for a `response message`, but, rather than needing special XON/XOFF characters for flow control, this protocol simply uses Grbl's responses as a way to reliably track how much room there is in Grbl's serial receive buffer. An example of this protocol is outlined in the `stream.py` streaming script in our repo. This protocol is particular useful for very fast machines like laser cutters. + +The main difference between this protocol and the others is the host PC needs to maintain a standing count of how many characters it has sent to Grbl and then subtract the number of characters corresponding to the line executed with each Grbl response. Suppose there is a short G-code program that has 5 lines with 25, 40, 31, 58, and 20 characters (counting the line feed and carriage return characters too). We know Grbl has a 128 character serial receive buffer, and the host PC can send up to 128 characters without overflowing the buffer. If we let the host PC send as many complete lines as we can without over flowing Grbl's serial receive buffer, the first three lines of 25, 40, and 31 characters can be sent for a total of 96 characters. When Grbl sends a **response message**, we know the first line has been processed and is no longer in the serial read buffer. As it stands, the serial read buffer now has the 40 and 31 character lines in it for a total of 71 characters. The host PC needs to then determine if it's safe to send the next line without overflowing the buffer. With the next line at 58 characters and the serial buffer at 71 for a total of 129 characters, the host PC will need to wait until more room has cleared from the serial buffer. When the next Grbl **response message** comes in, the second line has been processed and only the third 31 character line remains in the serial buffer. At this point, it's safe to send the remaining last two 58 and 20 character lines of the g-code program for a total of 110. + +While seemingly complicated, this character-counting streaming protocol is extremely effective in practice. It always ensures Grbl's serial read buffer is filled, while never overflowing it. It maximizes Grbl's performance by keeping the look-ahead planner buffer full by better utilizing the bi-directional data flow of the serial port, and it's fairly simple to implement as our `stream.py` script illustrates. We have stress-tested this character-counting protocol to extremes and it has not yet failed. Seemingly, only the speed of the serial connection is the limit. + +_RESERVATION:_ + +- _If a g-code line is parsed and generates an error **response message**, a GUI should stop the stream immediately. However, since the character-counting method stuffs Grbl's RX buffer, Grbl will continue reading from the RX buffer and parse and execute the commands inside it. A GUI won't be able to control this. The interim solution is to check all of the g-code via the $C check mode, so all errors are vetted prior to streaming. This will get resolved in later versions of Grbl._ + + +## Interacting with Grbl's Systems + +Along with streaming a G-code program, there a few more things to consider when writing a GUI for Grbl, such as how to use status reporting, real-time control commands, dealing with EEPROM, and general message handling. + +#### Status Reporting +When a `?` character is sent to Grbl (no additional line feed or carriage return character required), it will immediately respond with something like `` to report its state and current position. The `?` is always picked-off and removed from the serial receive buffer whenever Grbl detects one. So, these can be sent at any time. Also, to make it a little easier for GUIs to pick up on status reports, they are always encased by `<>` chevrons. + +Developers can use this data to provide an on-screen position digital-read-out (DRO) for the user and/or to show the user a 3D position in a virtual workspace. We recommend querying Grbl for a `?` real-time status report at no more than 5Hz. 10Hz may be possible, but at some point, there are diminishing returns and you are taxing Grbl's CPU more by asking it to generate and send a lot of position data. + +Grbl's status report is fairly simply in organization. It always starts with a word describing the machine state like `IDLE` (descriptions of these are available elsewhere in the Wiki). The following data values are usually in the order listed below and separated by `|` pipe characters, but may not be in the exact order or printed at all. For a complete description of status report formatting, read the _Real-time Status Reports_ section below. + +#### Real-Time Control Commands +The real-time control commands, `~` cycle start/resume, `!` feed hold, `^X` soft-reset, and all of the override commands, all immediately signal Grbl to change its running state. Just like `?` status reports, these control characters are picked-off and removed from the serial buffer when they are detected and do not require an additional line-feed or carriage-return character to operate. + +One important note are the override command characters. These are defined in the extended-ASCII character space and are generally not type-able on a keyboard. A GUI must be able to send these 8-bit values to support overrides. + +#### EEPROM Issues +EEPROM access on the Arduino AVR CPUs turns off all of the interrupts while the CPU _writes_ to EEPROM. This poses a problem for certain features in Grbl, particularly if a user is streaming and running a g-code program, since it can pause the main step generator interrupt from executing on time. Most of the EEPROM access is restricted by Grbl when it's in certain states, but there are some things that developers need to know. + +* Settings should not be streamed with the character-counting streaming protocols. Only the simple send-response protocol works. This is because during the EEPROM write, the AVR CPU also shuts-down the serial RX interrupt, which means data can get corrupted or lost. This is safe with the send-response protocol, because it's not sending data after commanding Grbl to save data. + +For reference: +* Grbl's EEPROM write commands: `G10 L2`, `G10 L20`, `G28.1`, `G30.1`, `$x=`, `$I=`, `$Nx=`, `$RST=` +* Grbl's EEPROM read commands: `G54-G59`, `G28`, `G30`, `$$`, `$I`, `$N`, `$#` + +#### G-code Error Handling + +Grbl's g-code parser is fully standards-compilant with complete error-checking. When a G-code parser detects an error in a G-code block/line, the parser will dump everything in the block from memory and report an `error:` back to the user or GUI. This dump is absolutely the right thing to do, because a g-code line with an error can be interpreted in multiple ways. However, this dump can be problematic, because the bad G-code block may have contained some valuable positioning commands or feed rate settings that the following g-code depends on. + +It's highly recommended to do what all professional CNC controllers do when they detect an error in the G-code program, _**halt**_. Don't do anything further until the user has modified the G-code and fixed the error in their program. Otherwise, bad things could happen. + +As a service to GUIs, Grbl has a "check G-code" mode, enabled by the `$C` system command. GUIs can stream a G-code program to Grbl, where it will parse it, error-check it, and report `ok`'s and `errors:`'s without powering on anything or moving. So GUIs can pre-check the programs before streaming them for real. To disable the "check G-code" mode, send another `$C` system command and Grbl will automatically soft-reset to flush and re-initialize the G-code parser and the rest of the system. This perhaps should be run in the background when a user first loads a program, before a user sets up his machine. This flushing and re-initialization clears `G92`'s by G-code standard, which some users still incorrectly use to set their part zero. + +#### Jogging + +As of Grbl v1.1, a new jogging feature is available that accepts incremental, absolute, or absolute override motions, along with a jog cancel real-time command that will automatically feed hold and purge the planner buffer. The most important aspect of the new jogging motion is that it is completely independent from the g-code parser, so GUIs no longer have to ensure the g-code modal states are set back correctly after jogging is complete. See the jogging document for more details on how it works and how you can use it with an analog joystick or rotary dial. + +#### Synchronization + +For situations when a GUI needs to run a special set of commands for tool changes, auto-leveling, etc, there often needs to be a way to know when Grbl has completed a task and the planner buffer is empty. The absolute simplest way to do this is to insert a `G4 P0.01` dwell command, where P is in seconds and must be greater than 0.0. This acts as a quick force-synchronization and ensures the planner buffer is completely empty before the GUI sends the next task to execute. + +----- +# Message Summary + +In v1.1, Grbl's interface protocol has been tweaked in the attempt to make GUI development cleaner, clearer, and hopefully easier. All messages are designed to be deterministic without needing to know the context of the message. Each can be inferred to a much greater degree than before just by the message type, which are all listed below. + +- **Response Messages:** Normal send command and execution response acknowledgement. Used for streaming. + + - `ok` : Indicates the command line received was parsed and executed (or set to be executed). + - `error:x` : Indicated the command line received contained an error, with an error code `x`, and was purged. See error code section below for definitions. + +- **Push Messages:** + + - `< >` : Enclosed chevrons contains status report data. + - `Grbl X.Xx ['$' for help]` : Welcome message indicates initialization. + - `ALARM:x` : Indicates an alarm has been thrown. Grbl is now in an alarm state. + - `$x=val` and `$Nx=line` indicate a settings printout from a `$` and `$N` user query, respectively. + - `[MSG:]` : Indicates a non-queried feedback message. + - `[GC:]` : Indicates a queried `$G` g-code state message. + - `[HLP:]` : Indicates the help message. + - `[G54:]`, `[G55:]`, `[G56:]`, `[G57:]`, `[G58:]`, `[G59:]`, `[G28:]`, `[G30:]`, `[G92:]`, `[TLO:]`, and `[PRB:]` messages indicate the parameter data printout from a `$#` user query. + - `[VER:]` : Indicates build info and string from a `$I` user query. + - `[echo:]` : Indicates an automated line echo from a pre-parsed string prior to g-code parsing. Enabled by config.h option. + - `>G54G20:ok` : The open chevron indicates startup line execution. The `:ok` suffix shows it executed correctly without adding an unmatched `ok` response on a new line. + +In addition, all `$x=val` settings, `error:`, and `ALARM:` messages no longer contain human-readable strings, but rather codes that are defined in other documents. The `$` help message is also reduced to just showing the available commands. Doing this saves incredible amounts of flash space. Otherwise, the new overrides features would not have fit. + +Other minor changes and bug fixes that may effect GUI parsing include: + +- Floating point values printed with zero precision do not show a decimal, or look like an integer. This includes spindle speed RPM and feed rate in mm mode. +- `$G` reports fixed a long time bug with program modal state. It always showed `M0` program pause when running. Now during a normal program run, no program modal state is given until an `M0`, `M2`, or `M30` is active and then the appropriate state will be shown. + +On a final note, this interface tweak came about out of necessity, as more data is being sent back from Grbl and it is capable of doing many more things. It's not intended to be altered again in the near future, if at all. This is likely the only and last major change to this. If you have any comments or suggestions before Grbl v1.1 goes to master, please do immediately so we can all vet the new alteration before its installed. + + + + + +--------- + +# Grbl Response Messages + +Every G-code block sent to Grbl and Grbl `$` system command that is terminated with a return will be parsed and processed by Grbl. Grbl will then respond either if it recognized the command with an `ok` line or if there was a problem with an `error` line. + +* **`ok`**: All is good! Everything in the last line was understood by Grbl and was successfully processed and executed. + + - If an empty line with only a return is sent to Grbl, it considers it a valid line and will return an `ok` too, except it didn't do anything. + + +* **`error:X`**: Something went wrong! Grbl did not recognize the command and did not execute anything inside that message. The `X` is given as a numeric error code to tell you exactly what happened. The table below decribes every one of them. + + | ID | Error Code Description | +|:-------------:|----| +| **`1`** | G-code words consist of a letter and a value. Letter was not found. | +| **`2`** | Numeric value format is not valid or missing an expected value. | +| **`3`** | Grbl '$' system command was not recognized or supported. | +| **`4`** | Negative value received for an expected positive value. | +| **`5`** | Homing cycle is not enabled via settings. | +| **`6`** | Minimum step pulse time must be greater than 3usec | +| **`7`** | EEPROM read failed. Reset and restored to default values. | +| **`8`** | Grbl '$' command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job. | +| **`9`** | G-code locked out during alarm or jog state | +| **`10`** | Soft limits cannot be enabled without homing also enabled. | +| **`11`** | Max characters per line exceeded. Line was not processed and executed. | +| **`12`** | (Compile Option) Grbl '$' setting value exceeds the maximum step rate supported. | +| **`13`** | Safety door detected as opened and door state initiated. | +| **`14`** | (Grbl-Mega Only) Build info or startup line exceeded EEPROM line length limit. | +| **`15`** | Jog target exceeds machine travel. Command ignored. | +| **`16`** | Jog command with no '=' or contains prohibited g-code. | +| **`17`** | Laser mode disabled. Requires PWM output. | +| **`20`** | Unsupported or invalid g-code command found in block. | +| **`21`** | More than one g-code command from same modal group found in block.| +| **`22`** | Feed rate has not yet been set or is undefined. | +| **`23`** | G-code command in block requires an integer value. | +| **`24`** | Two G-code commands that both require the use of the `XYZ` axis words were detected in the block.| +| **`25`** | A G-code word was repeated in the block.| +| **`26`** | A G-code command implicitly or explicitly requires `XYZ` axis words in the block, but none were detected.| +| **`27`**| `N` line number value is not within the valid range of `1` - `9,999,999`. | +| **`28`** | A G-code command was sent, but is missing some required `P` or `L` value words in the line. | +| **`29`** | Grbl supports six work coordinate systems `G54-G59`. `G59.1`, `G59.2`, and `G59.3` are not supported.| +| **`30`**| The `G53` G-code command requires either a `G0` seek or `G1` feed motion mode to be active. A different motion was active.| +| **`31`** | There are unused axis words in the block and `G80` motion mode cancel is active.| +| **`32`** | A `G2` or `G3` arc was commanded but there are no `XYZ` axis words in the selected plane to trace the arc.| +| **`33`** | The motion command has an invalid target. `G2`, `G3`, and `G38.2` generates this error, if the arc is impossible to generate or if the probe target is the current position.| +| **`34`** | A `G2` or `G3` arc, traced with the radius definition, had a mathematical error when computing the arc geometry. Try either breaking up the arc into semi-circles or quadrants, or redefine them with the arc offset definition.| +| **`35`** | A `G2` or `G3` arc, traced with the offset definition, is missing the `IJK` offset word in the selected plane to trace the arc.| +| **`36`** | There are unused, leftover G-code words that aren't used by any command in the block.| +| **`37`** | The `G43.1` dynamic tool length offset command cannot apply an offset to an axis other than its configured axis. The Grbl default axis is the Z-axis.| +| **`38`** | Tool number greater than max supported value.| + + +---------------------- + +# Grbl Push Messages + +Along with the response message to indicate successfully executing a line command sent to Grbl, Grbl provides additional push messages for important feedback of its current state or if something went horribly wrong. These messages are "pushed" from Grbl and may appear at anytime. They are usually in response to a user query or some system event that Grbl needs to tell you about immediately. These push messages are organized into six general classes: + +- **_Welcome message_** - A unique message to indicate Grbl has initialized. + +- **_ALARM messages_** - Means an emergency mode has been enacted and shut down normal use. + +- **_'$' settings messages_** - Contains the type and data value for a Grbl setting. + +- **_Feedback messages_** - Contains general feedback and can provide useful data. + +- **_Startup line execution_** - Indicates a startup line as executed with the line itself and how it went. + +- **_Real-time status reports_** - Contains current run data like state, position, and speed. + + +------ + +#### Welcome Message + +**`Grbl X.Xx ['$' for help]`** + +The start up message always prints upon startup and after a reset. Whenever you see this message, this also means that Grbl has completed re-initializing all its systems, so everything starts out the same every time you use Grbl. + +* `X.Xx` indicates the major version number, followed by a minor version letter. The major version number indicates the general release, while the letter simply indicates a feature update or addition from the preceding minor version letter. +* Bug fix revisions are tracked by the build info version number, printed when an `$I` command is sent. These revisions don't update the version number and are given by date revised in year, month, and day, like so `20161014`. + +----- + +#### Alarm Message + +Alarm is an emergency state. Something has gone terribly wrong when these occur. Typically, they are caused by limit error when the machine has moved or wants to move outside the machine travel and crash into the ends. They also report problems if Grbl is lost and can't guarantee positioning or a probe command has failed. Once in alarm-mode, Grbl will lock out all g-code functionality and accept only a small set of commands. It may even stop everything and force you to acknowledge the problem until you issue Grbl a reset. While in alarm-mode, the user can override the alarm manually with a specific command, which then re-enables g-code so you can move the machine again. This ensures the user knows about the problem and has taken steps to fix or account for it. + +Similar to error messages, all alarm messages are sent as **`ALARM:X`**, where `X` is an alarm code to tell you exacly what caused the alarm. The table below describes the meaning of each alarm code. + +| ID | Alarm Code Description | +|:-------------:|----| +| **`1`** | Hard limit triggered. Machine position is likely lost due to sudden and immediate halt. Re-homing is highly recommended. | +| **`2`** | G-code motion target exceeds machine travel. Machine position safely retained. Alarm may be unlocked. | +| **`3`** | Reset while in motion. Grbl cannot guarantee position. Lost steps are likely. Re-homing is highly recommended. | +| **`4`** | Probe fail. The probe is not in the expected initial state before starting probe cycle, where G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered. | +| **`5`** | Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4. | +| **`6`** | Homing fail. Reset during active homing cycle. | +| **`7`** | Homing fail. Safety door was opened during active homing cycle. | +| **`8`** | Homing fail. Cycle failed to clear limit switch when pulling off. Try increasing pull-off setting or check wiring. | +| **`9`** | Homing fail. Could not find limit switch within search distance. Defined as `1.5 * max_travel` on search and `5 * pulloff` on locate phases. | + +------- + +#### Grbl `$` Settings Message + +When a push message starts with a `$`, this indicates Grbl is sending a setting and its configured value. There are only two types of settings messages: a single setting and value `$x=val` and a startup string setting `$Nx=line`. See [Configuring Grbl v1.x] document if you'd like to learn how to write these values for your machine. + +- `$x=val` will only appear when the user queries to print all of Grbl's settings via the `$$` print settings command. It does so sequentially and completes with an `ok`. + + - In prior versions of Grbl, the `$` settings included a short description of the setting immediately after the value. However, due to flash restrictions, most human-readable strings were removed to free up flash for the new override features in Grbl v1.1. In short, it was these strings or overrides, and overrides won. Keep in mind that once these values are set, they usually don't change, and GUIs will likely provide the assistance of translating these codes for users. + + - _**NOTE for GUI developers:**_ _As with the error and alarm codes, settings codes are available in an easy to parse CSV file in the `/doc/csv` folder. These are continually updated._ + + - The `$$` settings print out is shown below and the following describes each setting. + + ``` +$0=10 +$1=25 +$2=0 +$3=0 +$4=0 +$5=0 +$6=0 +$10=255 +$11=0.010 +$12=0.002 +$13=0 +$20=0 +$21=0 +$22=0 +$23=0 +$24=25.000 +$25=500.000 +$26=250 +$27=1.000 +$30=1000 +$31=0 +$32=0 +$100=250.000 +$101=250.000 +$102=250.000 +$110=500.000 +$111=500.000 +$112=500.000 +$120=10.000 +$121=10.000 +$122=10.000 +$130=200.000 +$131=200.000 +$132=200.000 +ok +``` + + | `$x` Code | Setting Description, Units | +|:-------------:|----| +| **`0`** | Step pulse time, microseconds | +| **`1`** | Step idle delay, milliseconds | +| **`2`** | Step pulse invert, mask | +| **`3`** | Step direction invert, mask | +| **`4`** | Invert step enable pin, boolean | +| **`5`** | Invert limit pins, boolean | +| **`6`** | Invert probe pin, boolean | +| **`10`** | Status report options, mask | +| **`11`** | Junction deviation, millimeters | +| **`12`** | Arc tolerance, millimeters | +| **`13`** | Report in inches, boolean | +| **`20`** | Soft limits enable, boolean | +| **`21`** | Hard limits enable, boolean | +| **`22`** | Homing cycle enable, boolean | +| **`23`** | Homing direction invert, mask | +| **`24`** | Homing locate feed rate, mm/min | +| **`25`** | Homing search seek rate, mm/min | +| **`26`** | Homing switch debounce delay, milliseconds | +| **`27`** | Homing switch pull-off distance, millimeters | +| **`30`** | Maximum spindle speed, RPM | +| **`31`** | Minimum spindle speed, RPM | +| **`32`** | Laser-mode enable, boolean | +| **`100`** | X-axis steps per millimeter | +| **`101`** | Y-axis steps per millimeter | +| **`102`** | Z-axis steps per millimeter | +| **`110`** | X-axis maximum rate, mm/min | +| **`111`** | Y-axis maximum rate, mm/min | +| **`112`** | Z-axis maximum rate, mm/min | +| **`120`** | X-axis acceleration, mm/sec^2 | +| **`121`** | Y-axis acceleration, mm/sec^2 | +| **`122`** | Z-axis acceleration, mm/sec^2 | +| **`130`** | X-axis maximum travel, millimeters | +| **`131`** | Y-axis maximum travel, millimeters | +| **`132`** | Z-axis maximum travel, millimeters | + + +- The other `$Nx=line` message is the print-out of a user-defined startup line, where `x` denotes the startup line order and ranges from `0` to `1` by default. The `line` denotes the startup line to be executed by Grbl upon reset or power-up, except during an ALARM. + + - When a user queries for the startup lines via a `$N` command, the following is sent by Grbl and completed by an `ok` response. The first line sets the initial startup work coordinate system to `G54`, while the second line is empty and does not execute. + ``` + $N0=G54 + $N1= + ok + ``` + + +------ + +#### Feedback Messages + +Feedback messages provide non-critical information on what Grbl is doing, what it needs, and/or provide some non-real-time data for the user when queried. Not too complicated. Feedback message are always enclosed in `[]` brackets, except for the startup line execution message which begins with an open chevron character `>`. + +- **Non-Queried Feedback Messages:** These feedback messages that may appear at any time and is not part of a query are listed and described below. They are usually sent as an additional helpful acknowledgement of some event or command executed. These always start with a `[MSG:` to denote their type. + + - `[MSG:Reset to continue]` - Critical event message. Reset is required before Grbl accepts any other commands. This prevents ongoing command streaming and risking a motion before the alarm is acknowledged. Only hard or soft limit errors send this message immediately after the ALARM:x code. + + - `[MSG:‘$H’|’$X’ to unlock]`- Alarm state is active at initialization. This message serves as a reminder note on how to cancel the alarm state. All g-code commands and some ‘$’ are blocked until the alarm state is cancelled via homing `$H` or unlocking `$X`. Only appears immediately after the `Grbl` welcome message when initialized with an alarm. Startup lines are not executed at initialization if this message is present and the alarm is active. + + - `[MSG:Caution: Unlocked]` - Appears as an alarm unlock `$X` acknowledgement. An 'ok' still appears immediately after to denote the `$X` was parsed and executed. This message reminds the user that Grbl is operating under an unlock state, where startup lines have still not be executed and should be cautious and mindful of what they do. Grbl may not have retained machine position due to an alarm suddenly halting the machine. A reset or re-homing Grbl is highly recommended as soon as possible, where any startup lines will be properly executed. + + - `[MSG:Enabled]` - Appears as a check-mode `$C` enabled acknowledgement. An 'ok' still appears immediately after to denote the `$C` was parsed and executed. + + - `[MSG:Disabled]` - Appears as a check-mode `$C` disabled acknowledgement. An 'ok' still appears immediately after to denote the `$C` was parsed and executed. Grbl is automatically reset afterwards to restore all default g-code parser states changed by the check-mode. + + - `[MSG:Check Door]` - This message appears whenever the safety door detected as open. This includes immediately upon a safety door switch detects a pin change or appearing after the welcome message, if the safety door is ajar when Grbl initializes after a power-up/reset. + + - If in motion and the safety door switch is triggered, Grbl will immediately send this message, start a feed hold, and place Grbl into a suspend with the DOOR state. + - If not in motion and not at startup, the same process occurs without the feed hold. + - If Grbl is in a DOOR state and already suspended, any detected door switch pin detected will generate this message, including a door close. + - If this message appears at startup, Grbl will suspended into immediately into the DOOR state. The startup lines are executed immediately after the DOOR state is exited by closing the door and sending Grbl a resume command. + + - `[MSG:Check Limits]` - If Grbl detects a limit switch as triggered after a power-up/reset and hard limits are enabled, this will appear as a courtesy message immediately after the Grbl welcome message. + + - `[MSG:Pgm End]` - M2/30 program end message to denote g-code modes have been restored to defaults according to the M2/30 g-code description. + + - `[MSG:Restoring defaults]` - Appears as an acknowledgement message when restoring EEPROM defaults via a `$RST=` command. An 'ok' still appears immediately after to denote the `$RST=` was parsed and executed. + + - `[MSG:Sleeping]` - Appears as an acknowledgement message when Grbl's sleep mode is invoked by issuing a `$SLP` command when in IDLE or ALARM states. Note that Grbl-Mega may invoke this at any time when the sleep timer option has been enabled and the timeout has been exceeded. Grbl may only be exited by a reset in the sleep state and will automatically enter an alarm state since the steppers were disabled. + - NOTE: Sleep will also invoke the parking motion, if it's enabled. However, if sleep is commanded during an ALARM, Grbl will not park and will simply de-energize everything and go to sleep. + +- **Queried Feedback Messages:** + + - `[GC:]` G-code Parser State Message + + ``` + [GC:G0 G54 G17 G21 G90 G94 M5 M9 T0 F0.0 S0] + ok + ``` + + - Initiated by the user via a `$G` command. Grbl replies as follows, where the `[GC:` denotes the message type and is followed by a separate `ok` to confirm the `$G` was executed. + + - The shown g-code are the current modal states of Grbl's g-code parser. This may not correlate to what is executing since there are usually several motions queued in the planner buffer. + + - NOTE: Program modal state has been fixed and will show `M0`, `M2`, or `M30` when they are active. During a run state, nothing will appear for program modal state. + + + + - `[HLP:]` : Initiated by the user via a `$` print help command. The help message is shown below with a separate `ok` to confirm the `$` was executed. + ``` + [HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $C $X $H ~ ! ? ctrl-x] + ok + ``` + - _**NOTE:** Grbl v1.1's new override real-time commands are not included in the help message. They use the extended-ASCII character set, which are not easily type-able, and require a GUI that supports them. This is for two reasons: Establish enough characters for all of the overrides with extra for later growth, and prevent accidental keystrokes or characters in a g-code file from enacting an override inadvertently._ + + + - The `$#` print parameter data query produces a large set of data which shown below and completed by an `ok` response message. + + - Each line of the printout is starts with the data type, a `:`, and followed by the data values. If there is more than one, the order is XYZ axes, separated by commas. + + ``` + [G54:0.000,0.000,0.000] + [G55:0.000,0.000,0.000] + [G56:0.000,0.000,0.000] + [G57:0.000,0.000,0.000] + [G58:0.000,0.000,0.000] + [G59:0.000,0.000,0.000] + [G28:0.000,0.000,0.000] + [G30:0.000,0.000,0.000] + [G92:0.000,0.000,0.000] + [TLO:0.000] + [PRB:0.000,0.000,0.000:0] + ok + ``` + + - The `PRB:` probe parameter message includes an additional `:` and suffix value is a boolean. It denotes whether the last probe cycle was successful or not. + + - `[VER:]` and `[OPT:]`: Indicates build info data from a `$I` user query. These build info messages are followed by an `ok` to confirm the `$I` was executed, like so: + + ``` + [VER:v1.1f.20170131:Some string] + [OPT:VL,16,128] + ok + ``` + + - The first line `[VER:]` contains the build version and date. + - A string may appear after the second `:` colon. It is a stored EEPROM string a user via a `$I=line` command or OEM can place there for personal use or tracking purposes. + - The `[OPT:]` line follows immediately after and contains character codes for compile-time options that were either enabled or disabled and two values separated by commas, which indicates the total usable planner blocks and serial RX buffer bytes, respectively. The codes are defined below and a CSV file is also provided for quick parsing. This is generally only used for quickly diagnosing firmware bugs or compatibility issues. + + | `OPT` Code | Setting Description, Units | +|:-------------:|----| +| **`V`** | Variable spindle enabled | +| **`N`** | Line numbers enabled | +| **`M`** | Mist coolant enabled | +| **`C`** | CoreXY enabled | +| **`P`** | Parking motion enabled | +| **`Z`** | Homing force origin enabled | +| **`H`** | Homing single axis enabled | +| **`T`** | Two limit switches on axis enabled | +| **`D`** | Spindle direction pin used as enable pin | +| **`0`** | Spindle enable off when speed is zero enabled | +| **`S`** | Software limit pin debouncing enabled | +| **`R`** | Parking override control enabled | +| **`A`** | Allow feed rate overrides in probe cycles | +| **`+`** | Safety door input pin enabled | +| **`*`** | Restore all EEPROM disabled | +| **`$`** | Restore EEPROM `$` settings disabled | +| **`#`** | Restore EEPROM parameter data disabled | +| **`I`** | Build info write user string disabled | +| **`E`** | Force sync upon EEPROM write disabled | +| **`W`** | Force sync upon work coordinate offset change disabled | +| **`L`** | Homing initialization auto-lock disabled | + + - `[echo:]` : Indicates an automated line echo from a command just prior to being parsed and executed. May be enabled only by a config.h option. Often used for debugging communication issues. A typical line echo message is shown below. A separate `ok` will eventually appear to confirm the line has been parsed and executed, but may not be immediate as with any line command containing motions. + ``` + [echo:G1X0.540Y10.4F100] + ``` + - NOTE: The echoed line will have been pre-parsed a bit by Grbl. No spaces or comments will appear and all letters will be capitalized. + +------ + +#### Startup Line Execution + + - `>G54G20:ok` : The open chevron indicates a startup line has just executed. The startup line `G54G20` immediately follows the `>` character and is followed by an `:ok` response to indicate it executed successfully. + + - A startup line will execute upon initialization only if a line is present and if Grbl is not in an alarm state. + + - The `:ok` on the same line is intentional. It prevents this `ok` response from being counted as part of a stream, because it is not tied to a sent command, but an internally-generated one. + + - There should always be an appended `:ok` because the startup line is checked for validity before it is stored in EEPROM. In the event that it's not, Grbl will print `>G54G20:error:X`, where `X` is the error code explaining why the startup line failed to execute. + + - In the rare chance that there is an EEPROM read error, the startup line execution will print `>:error:7` with no startup line and a error code `7` for a read fail. Grbl will also automatically wipe and try to restore the problematic EEPROM. + + +------ + +#### Real-time Status Reports + +- Contains real-time data of Grbl’s state, position, and other data required independently of the stream. + +- Categorized as a real-time message, where it is a separate message that should not be counted as part of the streaming protocol. It may appear at any given time. + +- A status report is initiated by sending Grbl a '?' character. + + - Like all real-time commands, the '?' character is intercepted and never enters the serial buffer. It's never a part of the stream and can be sent at any time. + + - Grbl will generate and transmit a report within ~5-20 milliseconds. + + - Every ’?’ command sent by a GUI is not guaranteed with a response. The following are the current scenarios when Grbl may not immediately or ignore a status report request. _NOTE: These may change in the future and will be documented here._ + + - If two or more '?' queries are sent before the first report is generated, the additional queries are ignored. + + - A soft-reset commanded clears the last status report query. + + - When Grbl throws a critical alarm from a limit violation. A soft-reset is required to resume operation. + + - During a homing cycle. + +- **Message Construction:** + + - A message is a single line of ascii text, completed by a carriage return and line feed. + + - `< >` Chevrons uniquely enclose reports to indicate message type. + + - `|` Pipe delimiters separate data fields inside the report. + + - The first data field is an exception to the following data field rules. See 'Machine State' description for details. + + - All remaining data fields consist of a data type followed by a `:` colon delimiter and data values. `type:value(s)` + + - Data values are given either as as one or more pre-defined character codes to indicate certain states/conditions or as numeric values, which are separated by a `,` comma delimiter when more than one is present. Numeric values are also in a pre-defined order and units of measure. + + - The first (Machine State) and second (Current Position) data fields are always included in every report. + + - Assume any following data field may or may not exist and can be in any order. The `$10` status report mask setting can alter what data is present and certain data fields can be reported intermittently (see descriptions for details.) + + - The `$13` report inches settings alters the units of some data values. `$13=0` false indicates mm-mode, while `$13=1` true indicates inch-mode reporting. Keep note of this setting and which report values can be altered. + +- **Data Field Descriptions:** + + - **Machine State:** + + - Valid states types: `Idle, Run, Hold, Jog, Alarm, Door, Check, Home, Sleep` + + - Sub-states may be included via `:` a colon delimiter and numeric code. + + - Current sub-states are: + + - `Hold:0` Hold complete. Ready to resume. + - `Hold:1` Hold in-progress. Reset will throw an alarm. + - `Door:0` Door closed. Ready to resume. + - `Door:1` Machine stopped. Door still ajar. Can't resume until closed. + - `Door:2` Door opened. Hold (or parking retract) in-progress. Reset will throw an alarm. + - `Door:3` Door closed and resuming. Restoring from park, if applicable. Reset will throw an alarm. + + - This data field is always present as the first field. + + - **Current Position:** + + - Depending on `$10` status report mask settings, position may be sent as either: + + - `MPos:0.000,-10.000,5.000` machine position or + - `WPos:-2.500,0.000,11.000` work position + + - **NOTE: Grbl v1.1 sends only one position vector because a GUI can easily compute the other position vector with the work coordinate offset `WCO:` data. See WCO description for details.** + + - Three position values are given in the order of X, Y, and Z. A fourth position value may exist in later versions for the A-axis. + + - `$13` report inches user setting effects these values and is given as either mm or inches. + + - This data field is always present as the second field. + + - **Work Coordinate Offset:** + + - `WCO:0.000,1.551,5.664` is the current work coordinate offset of the g-code parser, which is the sum of the current work coordinate system, G92 offsets, and G43.1 tool length offset. + + - Machine position and work position are related by this simple equation per axis: `WPos = MPos - WCO` + + - **GUI Developers:** Simply track and retain the last `WCO:` vector and use the above equation to compute the other position vector for your position readouts. If Grbl's status reports show either `WPos` or `MPos`, just follow the equations below. It's as easy as that! + - If `WPos:` is given, use `MPos = WPos + WCO`. + - If `MPos:` is given, use `WPos = MPos - WCO`. + + - Values are given in the order of the X,Y, and Z axes offsets. A fourth offset value may exist in later versions for the A-axis. + - `$13` report inches user setting effects these values and is given as either mm or inches. + + - `WCO:` values don't change often during a job once set and only requires intermittent refreshing. + + - This data field appears: + + - In every 10 or 30 (configurable 1-255) status reports, depending on if Grbl is in a motion state or not. + - Immediately in the next report, if an offset value has changed. + - In the first report after a reset/power-cycle. + + - This data field will not appear if: + + - It is disabled in the config.h file. No `$` mask setting available. + - The refresh counter is in-between intermittent reports. + + - **Buffer State:** + + - `Bf:15,128`. The first value is the number of available blocks in the planner buffer and the second is number of available bytes in the serial RX buffer. + + - The usage of this data is generally for debugging an interface, but is known to be used to control some GUI-specific tasks. While this is disabled by default, GUIs should expect this data field to appear, but they may ignore it, if desired. + + - IMPORTANT: Do not use this buffer data to control streaming. During a stream, the reported buffer will often be out-dated and may be incorrect by the time it has been received by the GUI. Instead, please use the streaming protocols outlined. They use Grbl's responses as a direct way to accurately determine the buffer state. + + - NOTE: The buffer state values changed from showing "in-use" blocks or bytes to "available". This change does not require the GUI knowing how many block/bytes Grbl has been compiled with. + + - This data field appears: + + - In every status report when enabled. It is disabled in the settings mask by default. + + - This data field will not appear if: + + - It is disabled by the `$` status report mask setting or disabled in the config.h file. + + - **Line Number:** + + - `Ln:99999` indicates line 99999 is currently being executed. This differs from the `$G` line `N` value since the parser is usually queued few blocks behind execution. + + - Compile-time option only because of memory requirements. However, if a GUI passes indicator line numbers onto Grbl, it's very useful to determine when Grbl is executing them. + + - This data field will not appear if: + + - It is disabled in the config.h file. No `$` mask setting available. + - The line number reporting not enabled in config.h. Different option to reporting data field. + - No line number or `N0` is passed with the g-code block. + - Grbl is homing, jogging, parking, or performing a system task/motion. + - There is no motion in the g-code block like a `G4P1` dwell. (May be fixed in later versions.) + + - **Current Feed and Speed:** + + - There are two versions of this data field that Grbl may respond with. + + - `F:500` contains real-time feed rate data as the value. This appears only when VARIABLE_SPINDLE is disabled in config.h, because spindle speed is not tracked in this mode. + - `FS:500,8000` contains real-time feed rate, followed by spindle speed, data as the values. Note the `FS:`, rather than `F:`, data type name indicates spindle speed data is included. + + - The current feed rate value is in mm/min or inches/min, depending on the `$` report inches user setting. + - The second value is the current spindle speed in RPM + + - These values will often not be the programmed feed rate or spindle speed, because several situations can alter or limit them. For example, overrides directly scale the programmed values to a different running value, while machine settings, acceleration profiles, and even the direction traveled can also limit rates to maximum values allowable. + + - As a operational note, reported rate is typically 30-50 msec behind actual position reported. + + - This data field will always appear, unless it was explicitly disabled in the config.h file. + + - **Input Pin State:** + + - `Pn:XYZPDHRS` indicates which input pins Grbl has detected as 'triggered'. + + - Pin state is evaluated every time a status report is generated. All input pin inversions are appropriately applied to determine 'triggered' states. + + - Each letter of `XYZPDHRS` denotes a particular 'triggered' input pin. + + - `X Y Z` XYZ limit pins, respectively + - `P` the probe pin. + - `D H R S` the door, hold, soft-reset, and cycle-start pins, respectively. + - Example: `Pn:PZ` indicates the probe and z-limit pins are 'triggered'. + - Note: `A` may be added in later versions for an A-axis limit pin. + + - Assume input pin letters are presented in no particular order. + + - One or more 'triggered' pin letter(s) will always be present with a `Pn:` data field. + + - This data field will not appear if: + + - It is disabled in the config.h file. No `$` mask setting available. + - No input pins are detected as triggered. + + - **Override Values:** + + - `Ov:100,100,100` indicates current override values in percent of programmed values for feed, rapids, and spindle speed, respectively. + + - Override maximum, minimum, and increment sizes are all configurable within config.h. Assume that a user or OEM will alter these based on customized use-cases. Recommend not hard-coding these values into a GUI, but rather just show the actual override values and generic increment buttons. + + - Override values don't change often during a job once set and only requires intermittent refreshing. This data field appears: + + - After 10 or 20 (configurable 1-255) status reports, depending on is in a motion state or not. + - If an override value has changed, this data field will appear immediately in the next report. However, if `WCO:` is present, this data field will be delayed one report. + - In the second report after a reset/power-cycle. + + - This data field will not appear if: + + - It is disabled in the config.h file. No `$` mask setting available. + - The override refresh counter is in-between intermittent reports. + - `WCO:` exists in current report during refresh. Automatically set to try again on next report. + + - **Accessory State:** + + - `A:SFM` indicates the current state of accessory machine components, such as the spindle and coolant. + + - Due to the new toggle overrides, these machine components may not be running according to the g-code program. This data is provided to ensure the user knows exactly what Grbl is doing at any given time. + + - Each letter after `A:` denotes a particular state. When it appears, the state is enabled. When it does not appear, the state is disabled. + + - `S` indicates spindle is enabled in the CW direction. This does not appear with `C`. + - `C` indicates spindle is enabled in the CCW direction. This does not appear with `S`. + - `F` indicates flood coolant is enabled. + - `M` indicates mist coolant is enabled. + + - Assume accessory state letters are presented in no particular order. + + - This data field appears: + + - When any accessory state is enabled. + - Only with the override values field in the same message. Any accessory state change will trigger the accessory state and override values fields to be shown on the next report. + + - This data field will not appear if: + + - No accessory state is active. + - It is disabled in the config.h file. No `$` mask setting available. + - If override refresh counter is in-between intermittent reports. + - `WCO:` exists in current report during refresh. Automatically set to try again on next report. diff --git a/doc/markdown/jogging.md b/doc/markdown/jogging.md new file mode 100644 index 0000000..c20aaee --- /dev/null +++ b/doc/markdown/jogging.md @@ -0,0 +1,93 @@ +# Grbl v1.1 Jogging + +This document outlines how to use Grbl v1.1's new jogging commands. These command differ because they can be cancelled and all queued motions are automatically purged with a simple jog-cancel or feed hold real-time command. Jogging command do not alter the g-code parser state in any way, so you no longer have to worry if you remembered to set the distance mode back to `G90` prior to starting a job. Also, jogging works well with an analog joysticks and rotary dials! See the implementation notes below. + +## How to Use +Executing a jog requires a specific command structure, as described below: + + - The first three characters must be '$J=' to indicate the jog. + - The jog command follows immediate after the '=' and works like a normal G1 command. + - Feed rate is only interpreted in G94 units per minute. A prior G93 state is ignored during jog. + - Required words: + - XYZ: One or more axis words with target value. + - F - Feed rate value. NOTE: Each jog requires this value and is not treated as modal. + - Optional words: Jog executes based on current G20/G21 and G90/G91 g-code parser state. If one of the following optional words is passed, that state is overridden for one command only. + - G20 or G21 - Inch and millimeter mode + - G90 or G91 - Absolute and incremental distances + - G53 - Move in machine coordinates + - N line numbers are valid. Will show in reports, if enabled, but is otherwise ignored. + - All other g-codes, m-codes, and value words (including S and T) are not accepted in the jog command. + - Spaces and comments are allowed in the command. These are removed by the pre-parser. + + - Example: G21 and G90 are active modal states prior to jogging. These are sequential commands. + - `$J=X10.0 Y-1.5` will move to X=10.0mm and Y=-1.5mm in work coordinate frame (WPos). + - `$J=G91 G20 X0.5` will move +0.5 inches (12.7mm) to X=22.7mm (WPos). Note that G91 and G20 are only applied to this jog command. + - `$J=G53 Y5.0` will move the machine to Y=5.0mm in the machine coordinate frame (MPos). If the work coordinate offset for the y-axis is 2.0mm, then Y is 3.0mm in (WPos). + +Jog commands behave almost identically to normal g-code streaming. Every jog command will +return an 'ok' when the jogging motion has been parsed and is setup for execution. If a +command is not valid, Grbl will return an 'error:'. Multiple jogging commands may be +queued in sequence. + +The main differences are: + +- During a jog, Grbl will report a 'Jog' state while executing the jog. +- A jog command will only be accepted when Grbl is in either the 'Idle' or 'Jog' states. +- Jogging motions may not be mixed with g-code commands while executing, which will return a lockout error, if attempted. +- All jogging motion(s) may be cancelled at anytime with a simple jog cancel realtime command or a feed hold or safety door event. Grbl will automatically flush Grbl's internal buffers of any queued jogging motions and return to the 'Idle' state. No soft-reset required. +- If soft-limits are enabled, jog commands that exceed the machine travel simply does not execute the command and return an error, rather than throwing an alarm in normal operation. +- IMPORTANT: Jogging does not alter the g-code parser state. Hence, no g-code modes need to be explicitly managed, unlike previous ways of implementing jogs with commands like 'G91G1X1F100'. Since G91, G1, and F feed rates are modal and if they are not changed back prior to resuming/starting a job, a job may not run how its was intended and result in a crash. + +------ + +## Joystick Implementation + +Jogging in Grbl v1.1 is generally intended to address some prior issues with old bootstrapped jogging methods. Unfortunately, the new Grbl jogging is not a complete solution. Flash and memory restrictions prevent the original envisioned implementation, but most of these can be mimicked by the following suggested methodology. + +With a combination of the new jog cancel and moving in `G91` incremental mode, the following implementation can create low latency feel for an analog joystick or similar control device. + +- Basic Implementation Overview: + - Create a loop to read the joystick signal and translate it to a desired jog motion vector. + - Send Grbl a very short `G91` incremental distance jog command with a feed rate based on the joystick throw. + - Wait for an 'ok' acknowledgement before restarting the loop. + - Continually read the joystick input and send Grbl short jog motions to keep Grbl's planner buffer full. + - If the joystick is returned to its neutral position, stop the jog loop and simply send Grbl a jog cancel real-time command. This will stop motion immediately somewhere along the programmed jog path with virtually zero-latency and automatically flush Grbl's planner queue. It's not advised to use a feed hold to cancel a jog, as it can lead to inadvertently suspending Grbl if its sent after returning to the IDLE state. + + +The overall idea is to minimize the total distance in the planner queue to provide a low-latency feel to joystick control. The main trick is ensuring there is just enough distance in the planner queue, such that the programmed feed rate is always met. How to compute this will be explain later. In practice, most machines will have a 0.5-1.0 second latency. When combined with the immediate jog cancel command, joystick interaction can be quite enjoyable and satisfying. + +However, please note, if a machine has a low acceleration and is being asked to move at a high programmed feed rate, joystick latency can get up to a handful of seconds. It may sound bad, but this is how long it'll take for a low acceleration machine, traveling at a high feed rate, to slow down to a stop. The argument can be made for a low acceleration machine that you really shouldn't be jogging at a high feed rate. It is difficult for a user to gauge where the machine will come to a stop. You risk overshooting your target destination, which can result in an expensive or dangerous crash. + +One of the advantages of this approach is that a GUI can deterministically track where Grbl will go by the jog commands it has already sent to Grbl. As long as a jog isn't cancelled, every jog command is guaranteed to execute. In the event a jog cancel is invoked, the GUI would just need to refresh their internal position from a status report after Grbl has cleared planner buffer and returned to the IDLE (or DOOR, if ajar) state from the JOG state. This stopped position will always be somewhere along the programmed jog path. If desired, jogging can then be quickly and easily restarted with a new tracked path. + +In combination with `G53` move in machine coordinates, a GUI can restrict jogging from moving into "keep-out" zones inside the machine space. This can be very useful for avoiding crashing into delicate probing hardware, workholding mechanisms, or other fixed features inside machine space that you want to avoid. + +#### How to compute incremental distances + +The quickest and easiest way to determine what the length of a jog motion needs to be to minimize latency are defined by the following equations. + +`s = v * dt` - Computes distance traveled for next jog command. + +where: + +- `s` - Incremental distance of jog command. +- `dt` - Estimated execution time of a single jog command in seconds. +- `v` - Current jog feed rate in **mm/sec**, not mm/min. Less than or equal to max jog rate. +- `N` - Number of Grbl planner blocks (`N=15`) +- `T = dt * N` - Computes total estimated latency in seconds. + +The time increment `dt` may be defined to whatever value you need. Obviously, you'd like the lowest value, since that translates to lower overall latency `T`. However, it is constrained by two factors. + +- `dt > 10ms` - The time it takes Grbl to parse and plan one jog command and receive the next one. Depending on a lot of factors, this can be around 1 to 5 ms. To be conservative, `10ms` is used. Keep in mind that on some systems, this value may still be greater than `10ms` due to round-trip communication latency. + +- `dt > v^2 / (2 * a * (N-1))` - The time increment needs to be large enough to ensure the jog feed rate will be acheived. Grbl always plans to a stop over the total distance queued in the planner buffer. This is primarily to ensure the machine will safely stop if a disconnection occurs. This equation simply ensures that `dt` is big enough to satisfy this constraint. + + - For simplicity, use the max jog feed rate for `v` in mm/sec and the smallest acceleration setting between the jog axes being moved in mm/sec^2. + + - For a lower latency, `dt` can be computed for each jog motion, where `v` is the current rate and `a` is the max acceleration along the jog vector. This is very useful if traveling a very slow speeds to locate a part zero. The `v` rate would be much lower in this scenario and the total latency would decrease quadratically. + +In practice, most CNC machines will operate with a jogging time increment of `0.025 sec` < `dt` < `0.06 sec`, which translates to about a `0.4` to `0.9` second total latency when traveling at the max jog rate. Good enough for most people. + +However, if jogging at a slower speed and a GUI adjusts the `dt` with it, you can get very close to the 0.1 second response time by human-interface guidelines for "feeling instantaneous". Not too shabby! + +With some ingenuity, this jogging methodology may be applied to different devices such as a rotary dial or touchscreen. An "inertial-feel", like swipe-scrolling on a smartphone or tablet, can be simulated by managing the jog rate decay and sending Grbl the associated jog commands. While this jogging implementation requires more initial work by a GUI, it is also inherently more flexible because you have complete deterministic control of how jogging behaves. \ No newline at end of file diff --git a/doc/markdown/laser_mode.md b/doc/markdown/laser_mode.md new file mode 100644 index 0000000..4e42ba3 --- /dev/null +++ b/doc/markdown/laser_mode.md @@ -0,0 +1,89 @@ +## Grbl v1.1 Laser Mode + +**_DISCLAIMER: Lasers are extremely dangerous devices. They can instantly cause fires and permanently damage your vision. Please read and understand all related documentation for your laser prior to using it. The Grbl project is not resposible for any damage or issues the firmware may cause, as defined by its GPL license._** + +---- + +Outlined in this document is how Grbl alters its running conditions for the new laser mode to provide both improved performance and attempting to enforce some basic user safety precautions. + +## Laser Mode Overview + +The main difference between default Grbl operation and the laser mode is how the spindle/laser output is controlled with motions involved. Every time a spindle state `M3 M4 M5` or spindle speed `Sxxx` is altered, Grbl would come to a stop, allow the spindle to change, and then continue. This is the normal operating procedure for a milling machine spindle. It needs time to change speeds. + +However, if a laser starts and stops like this for every spindle change, this leads to scorching and uneven cutting/engraving! Grbl's new laser mode prevents unnecessary stops whenever possible and adds a new dynamic laser power mode that automagically scales power based on current speed related to programmed rate. So, you can get super clean and crisp results, even on a low-acceleration machine! + +Enabling or disabling Grbl's laser mode is easy. Just alter the **$32** Grbl setting. +- **To Enable**: Send Grbl a `$32=1` command. +- **To Disable:** Send Grbl a `$32=0` command. + +**WARNING:** If you switch back from laser mode to a spindle for milling, you **MUST** disable laser mode by sending Grbl a `$32=0` command. Milling operations require the spindle to get up to the right rpm to cut correctly and to be **safe**, helping to prevent a tool from breaking and flinging metal shards everywhere. With laser mode disabled, Grbl will briefly pause upon any spindle speed or state change to give the spindle a chance to get up to speed before continuing. + + +## Laser Mode Operation + +When laser mode is enabled, Grbl controls laser power by varying the **0-5V** voltage from the spindle PWM D11 pin. **0V** should be treated as disabled, while **5V** is full power. Intermediate output voltages are also assumed to be linear with laser power, such that **2.5V** is approximate 50% laser power. (A compile time option exists to shift this linear model to start at a non-zero voltage.) + +By default, the spindle PWM frequency is **1kHz**, which is the recommended PWM frequency for most current Grbl-compatible lasers system. If a different frequency is required, this may be altered by editing the `cpu_map.h` file. + +The laser is enabled with the `M3` spindle CW and `M4` spindle CCW commands. These enable two different laser modes that are advantageous for different reasons each. + +- **`M3` Constant Laser Power Mode:** + + - Constant laser power mode simply keeps the laser power as programmed, regardless if the machine is moving, accelerating, or stopped. This provides better control of the laser state. With a good G-code program, this can lead to more consistent cuts in more difficult materials. + + - For a clean cut and prevent scorching with `M3` constant power mode, it's a good idea to add lead-in and lead-out motions around the line you want to cut to give some space for the machine to accelerate and decelerate. + + - NOTE: `M3` can be used to keep the laser on for focusing. + +- **`M4` Dynamic Laser Power Mode:** + - Dynamic laser power mode will automatically adjust laser power based on the current speed relative to the programmed rate. It essentially ensures the amount of laser energy along a cut is consistent even though the machine may be stopped or actively accelerating. This is very useful for clean, precise engraving and cutting on simple materials across a large range of G-code generation methods by CAM programs. It will generally run faster and may be all you need to use. + + - Grbl calculates laser power based on the assumption that laser power is linear with speed and the material. Often, this is not the case. Lasers can cut differently at varying power levels and some materials may not cut well at a particular speed and/power. In short, this means that dynamic power mode may not work for all situations. Always do a test piece prior to using this with a new material or machine. + + - When not in motion, `M4` dynamic mode turns off the laser. It only turns on when the machine moves. This generally makes the laser safer to operate, because, unlike `M3`, it will never burn a hole through your table, if you stop and forget to turn `M3` off in time. + +Describe below are the operational changes to Grbl when laser mode is enabled. Please read these carefully and understand them fully, because nothing is worse than a garage _**fire**_. + +- Grbl will move continuously through **consecutive** motion commands when programmed with a new `S` spindle speed (laser power). The spindle PWM pin will be updated instantaneously through each motion without stopping. + - Example: The following set of g-code commands will not pause between each of them when laser mode is enabled, but will pause when disabled. + + ``` + G1 X10 S100 F50 + G1 X0 S90 + G2 X0 I5 S80 + ``` + - Grbl will enforce a laser mode motion stop in a few circumstances. Primarily to ensure alterations stay in sync with the g-code program. + + - Any `M3`, `M4`, `M5` spindle state _change_. + - `M3` only and no motion programmed: A `S` spindle speed _change_. + - `M3` only and no motion programmed: A `G1 G2 G3` laser powered state _change_ to `G0 G80` laser disabled state. + - NOTE: `M4` does not stop for anything but a spindle state _change_. + +- The laser will only turn on when Grbl is in a `G1`, `G2`, or `G3` motion mode. + + - In other words, a `G0` rapid motion mode or `G38.x` probe cycle will never turn on and always disable the laser, but will still update the running modal state. When changed to a `G1 G2 G3` modal state, Grbl will immediately enable the laser based on the current running state. + + - Please remember that `G0` is the default motion mode upon power up and reset. You will need to alter it to `G1`, `G2`, or `G3` if you want to manually turn on your laser. This is strictly a safety measure. + + - Example: `G0 M3 S1000` will not turn on the laser, but will set the laser modal state to `M3` enabled and power of `S1000`. A following `G1` command will then immediately be set to `M3` and `S1000`. + + - To have the laser powered during a jog motion, first enable a valid motion mode and spindle state. The following jog motions will inherit and maintain the previous laser state. Please use with caution though. This ability is primarily to allow turning on the laser on a _very low_ power to use the laser dot to jog and visibly locate the start position of a job. + + +- An `S0` spindle speed of zero will turn off the laser. When programmed with a valid laser motion, Grbl will disable the laser instantaneously without stopping for the duration of that motion and future motions until set greater than zero.. + + - `M3` constant laser mode, this is a great way to turn off the laser power while continuously moving between a `G1` laser motion and a `G0` rapid motion without having to stop. Program a short `G1 S0` motion right before the `G0` motion and a `G1 Sxxx` motion is commanded right after to go back to cutting. + + +----- +###CAM Developer Implementation Notes + +TODO: Add some suggestions on how to write laser G-code for Grbl. + +- When using `M3` constant laser power mode, try to avoid force-sync conditions during a job whenever possible. Basically every spindle speed change must be accompanied by a valid motion. Any motion is fine, since Grbl will automatically enable and disable the laser based on the modal state. Avoid a `G0` and `G1` command with no axis words in this mode and in the middle of a job. + +- Ensure smooth motions throughout by turning the laser on and off without an `M3 M4 M5` spindle state command. There are two ways to do this: + + - _Program a zero spindle speed `S0`_: `S0` is valid G-code and turns off the spindle/laser without changing the spindle state. In laser mode, Grbl will smoothly move through consecutive motions and turn off the spindle. Conversely, you can turn on the laser with a spindle speed `S` greater than zero. Remember that `M3` constant power mode requires any spindle speed `S` change to be programmed with a motion to allow continuous motion, while `M4` dynamic power mode does not. + + - _Program an unpowered motion between powered motions_: If you are traversing between parts of a raster job that don't need to have the laser powered, program a `G0` rapid between them. `G0` enforces the laser to be disabled automatically. The last spindle speed programmed doesn't change, so if a valid powered motion, like a `G1` is executed after, it'll immediately re-power the laser with the last programmed spindle speed when executing that motion. diff --git a/doc/markdown/settings.md b/doc/markdown/settings.md new file mode 100644 index 0000000..4b54746 --- /dev/null +++ b/doc/markdown/settings.md @@ -0,0 +1,259 @@ +## Getting Started + +First, connect to Grbl using the serial terminal of your choice. + +Set the baud rate to **115200** as 8-N-1 (8-bits, no parity, and 1-stop bit.) + +Once connected + you should get the Grbl-prompt, which looks like this: + +``` +Grbl 1.1d ['$' for help] +``` + +Type $ and press enter to have Grbl print a help message. You should not see any local echo of the $ and enter. Grbl should respond with: + +``` +[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x] +``` + +The ‘$’-commands are Grbl system commands used to tweak the settings, view or change Grbl's states and running modes, and start a homing cycle. The last four **non**-'$' commands are realtime control commands that can be sent at anytime, no matter what Grbl is doing. These either immediately change Grbl's running behavior or immediately print a report of the important realtime data like current position (aka DRO). + +*** + +##Grbl Settings + +#### $$ - View Grbl settings +To view the settings, type `$$` and press enter after connecting to Grbl. Grbl should respond with a list of the current system settings, as shown in the example below. All of these settings are persistent and kept in EEPROM, so if you power down, these will be loaded back up the next time you power up your Arduino. + +The `x` of `$x=val` indicates a particular setting, while `val` is the setting value. In prior versions of Grbl, each setting had a description next to it in `()` parentheses, but Grbl v1.1+ no longer includes them unfortunately. This was done to free up precious flash memory to add the new features available in v1.1. However, most good GUIs will help out by attaching descriptions for you, so you know what you are looking at. + +``` +$0=10 +$1=25 +$2=0 +$3=0 +$4=0 +$5=0 +$6=0 +$10=1 +$11=0.010 +$12=0.002 +$13=0 +$20=0 +$21=0 +$22=1 +$23=0 +$24=25.000 +$25=500.000 +$26=250 +$27=1.000 +$30=1000. +$31=0. +$32=0 +$100=250.000 +$101=250.000 +$102=250.000 +$110=500.000 +$111=500.000 +$112=500.000 +$120=10.000 +$121=10.000 +$122=10.000 +$130=200.000 +$131=200.000 +$132=200.000 +``` + +#### $x=val - Save Grbl setting + +The `$x=val` command saves or alters a Grbl setting, which can be done manually by sending this command when connected to Grbl through a serial terminal program, but most Grbl GUIs will do this for you as a user-friendly feature. + +To manually change e.g. the microseconds step pulse option to 10us you would type this, followed by an enter: +``` +$0=10 +``` +If everything went well, Grbl will respond with an 'ok' and this setting is stored in EEPROM and will be retained forever or until you change them. You can check if Grbl has received and stored your setting correctly by typing `$$` to view the system settings again. + + +*** + +## Grbl's `$x=val` settings and what they mean + +**NOTE: From Grbl v0.9 to Grbl v1.1, only `$10` status reports changed and new `$30`/ `$31` spindle rpm max/min and `$32` laser mode settings were added. Everything else is the same.** + +#### $0 – Step pulse, microseconds + +Stepper drivers are rated for a certain minimum step pulse length. Check the data sheet or just try some numbers. You want the shortest pulses the stepper drivers can reliably recognize. If the pulses are too long, you might run into trouble when running the system at very high feed and pulse rates, because the step pulses can begin to overlap each other. We recommend something around 10 microseconds, which is the default value. + +#### $1 - Step idle delay, milliseconds + +Every time your steppers complete a motion and come to a stop, Grbl will delay disabling the steppers by this value. **OR**, you can always keep your axes enabled (powered so as to hold position) by setting this value to the maximum 255 milliseconds. Again, just to repeat, you can keep all axes always enabled by setting `$1=255`. + +The stepper idle lock time is the time length Grbl will keep the steppers locked before disabling. Depending on the system, you can set this to zero and disable it. On others, you may need 25-50 milliseconds to make sure your axes come to a complete stop before disabling. This is to help account for machine motors that do not like to be left on for long periods of time without doing something. Also, keep in mind that some stepper drivers don't remember which micro step they stopped on, so when you re-enable, you may witness some 'lost' steps due to this. In this case, just keep your steppers enabled via `$1=255`. + +#### $2 – Step port invert, mask + +This setting inverts the step pulse signal. By default, a step signal starts at normal-low and goes high upon a step pulse event. After a step pulse time set by `$0`, the pin resets to low, until the next step pulse event. When inverted, the step pulse behavior switches from normal-high, to low during the pulse, and back to high. Most users will not need to use this setting, but this can be useful for certain CNC-stepper drivers that have peculiar requirements. For example, an artificial delay between the direction pin and step pulse can be created by inverting the step pin. + +This invert mask setting is a value which stores the axes to invert as bit flags. You really don't need to completely understand how it works. You simply need to enter the settings value for the axes you want to invert. For example, if you want to invert the X and Z axes, you'd send `$2=5` to Grbl and the setting should now read `$2=5 (step port invert mask:00000101)`. + +| Setting Value | Mask |Invert X | Invert Y | Invert Z | +|:-------------:|:----:|:-------:|:--------:|:--------:| +| 0 | 00000000 |N | N | N | +| 1 | 00000001 |Y | N | N | +| 2 | 00000010 |N | Y | N | +| 3 | 00000011 |Y | Y | N | +| 4 | 00000100 |N | N | Y | +| 5 | 00000101 |Y | N | Y | +| 6 | 00000110 |N | Y | Y | +| 7 | 00000111 |Y | Y | Y | + +#### $3 – Direction port invert, mask + +This setting inverts the direction signal for each axis. By default, Grbl assumes that the axes move in a positive direction when the direction pin signal is low, and a negative direction when the pin is high. Often, axes don't move this way with some machines. This setting will invert the direction pin signal for those axes that move the opposite way. + +This invert mask setting works exactly like the step port invert mask and stores which axes to invert as bit flags. To configure this setting, you simply need to send the value for the axes you want to invert. Use the table above. For example, if want to invert the Y axis direction only, you'd send `$3=2` to Grbl and the setting should now read `$3=2 (dir port invert mask:00000010)` + +#### $4 - Step enable invert, boolean + +By default, the stepper enable pin is high to disable and low to enable. If your setup needs the opposite, just invert the stepper enable pin by typing `$4=1`. Disable with `$4=0`. (May need a power cycle to load the change.) + +#### $5 - Limit pins invert, boolean + +By default, the limit pins are held normally-high with the Arduino's internal pull-up resistor. When a limit pin is low, Grbl interprets this as triggered. For the opposite behavior, just invert the limit pins by typing `$5=1`. Disable with `$5=0`. You may need a power cycle to load the change. + +NOTE: If you invert your limit pins, you will need an external pull-down resistor wired in to all of the limit pins to prevent overloading the pins with current and frying them. + +#### $6 - Probe pin invert, boolean + +By default, the probe pin is held normally-high with the Arduino's internal pull-up resistor. When the probe pin is low, Grbl interprets this as triggered. For the opposite behavior, just invert the probe pin by typing `$6=1`. Disable with `$6=0`. You may need a power cycle to load the change. + +NOTE: If you invert your probe pin, you will need an external pull-down resistor wired in to the probe pin to prevent overloading it with current and frying it. + + +#### $10 - Status report, mask + +This setting determines what Grbl real-time data it reports back to the user when a '?' status report is sent. This data includes current run state, real-time position, real-time feed rate, pin states, current override values, buffer states, and the g-code line number currently executing (if enabled through compile-time options). + +By default, the new report implementation in Grbl v1.1+ will include just about everything in the standard status report. A lot of the data is hidden and will appear only if it changes. This increases efficiency dramatically over of the old report style and allows you to get faster updates and still get more data about your machine. The interface documentation outlines how it works and most of it applies only to GUI developers or the curious. + +To keep things simple and consistent, Grbl v1.1 has only two reporting options. These are primarily here just for users and developers to help set things up. + +- Position type may be specified to show either machine position (`MPos:`) or work position (`WPos:`), but no longer both at the same time. Enabling work position is useful in certain scenarios when Grbl is being directly interacted with through a serial terminal, but _machine position reporting should be used by default._ +- Usage data of Grbl's planner and serial RX buffers may be enabled. This shows the number of blocks or bytes available in the respective buffers. This is generally used to helps determine how Grbl is performing when testing out a streaming interface. _This should be disabled by default._ + +Use the table below enables and disable reporting options. Simply add the values listed of what you'd like to enable, then save it by sending Grbl your setting value. For example, the default report with machine position and no buffer data reports setting is `$10=1`. If work position and buffer data are desired, the setting will be `$10=2`. + +| Report Type | Value | Description | +|:-------------:|:----:|:----:| +| Position Type | 1 | Enabled `MPos:`. Disabled `WPos:`. | +| Buffer Data | 2 | Enabled `Buf:` field appears with planner and serial RX available buffer. + +#### $11 - Junction deviation, mm + +Junction deviation is used by the acceleration manager to determine how fast it can move through line segment junctions of a G-code program path. For example, if the G-code path has a sharp 10 degree turn coming up and the machine is moving at full speed, this setting helps determine how much the machine needs to slow down to safely go through the corner without losing steps. + +How we calculate it is a bit complicated, but, in general, higher values gives faster motion through corners, while increasing the risk of losing steps and positioning. Lower values makes the acceleration manager more careful and will lead to careful and slower cornering. So if you run into problems where your machine tries to take a corner too fast, *decrease* this value to make it slow down when entering corners. If you want your machine to move faster through junctions, *increase* this value to speed it up. For curious people, hit this [link](http://t.co/KQ5BvueY) to read about Grbl's cornering algorithm, which accounts for both velocity and junction angle with a very simple, efficient, and robust method. + +#### $12 – Arc tolerance, mm + +Grbl renders G2/G3 circles, arcs, and helices by subdividing them into teeny tiny lines, such that the arc tracing accuracy is never below this value. You will probably never need to adjust this setting, since `0.002mm` is well below the accuracy of most all CNC machines. But if you find that your circles are too crude or arc tracing is performing slowly, adjust this setting. Lower values give higher precision but may lead to performance issues by overloading Grbl with too many tiny lines. Alternately, higher values traces to a lower precision, but can speed up arc performance since Grbl has fewer lines to deal with. + +For the curious, arc tolerance is defined as the maximum perpendicular distance from a line segment with its end points lying on the arc, aka a chord. With some basic geometry, we solve for the length of the line segments to trace the arc that satisfies this setting. Modeling arcs in this way is great, because the arc line segments automatically adjust and scale with length to ensure optimum arc tracing performance, while never losing accuracy. + +#### $13 - Report inches, boolean + +Grbl has a real-time positioning reporting feature to provide a user feedback on where the machine is exactly at that time, as well as, parameters for coordinate offsets and probing. By default, it is set to report in mm, but by sending a `$13=1` command, you send this boolean flag to true and these reporting features will now report in inches. `$13=0` to set back to mm. + +#### $20 - Soft limits, boolean + +Soft limits is a safety feature to help prevent your machine from traveling too far and beyond the limits of travel, crashing or breaking something expensive. It works by knowing the maximum travel limits for each axis and where Grbl is in machine coordinates. Whenever a new G-code motion is sent to Grbl, it checks whether or not you accidentally have exceeded your machine space. If you do, Grbl will issue an immediate feed hold wherever it is, shutdown the spindle and coolant, and then set the system alarm indicating the problem. Machine position will be retained afterwards, since it's not due to an immediate forced stop like hard limits. + +NOTE: Soft limits requires homing to be enabled and accurate axis maximum travel settings, because Grbl needs to know where it is. `$20=1` to enable, and `$20=0` to disable. + +#### $21 - Hard limits, boolean + +Hard limit work basically the same as soft limits, but use physical switches instead. Basically you wire up some switches (mechanical, magnetic, or optical) near the end of travel of each axes, or where ever you feel that there might be trouble if your program moves too far to where it shouldn't. When the switch triggers, it will immediately halt all motion, shutdown the coolant and spindle (if connected), and go into alarm mode, which forces you to check your machine and reset everything. + +To use hard limits with Grbl, the limit pins are held high with an internal pull-up resistor, so all you have to do is wire in a normally-open switch with the pin and ground and enable hard limits with `$21=1`. (Disable with `$21=0`.) We strongly advise taking electric interference prevention measures. If you want a limit for both ends of travel of one axes, just wire in two switches in parallel with the pin and ground, so if either one of them trips, it triggers the hard limit. + +Keep in mind, that a hard limit event is considered to be critical event, where steppers immediately stop and will have likely have lost steps. Grbl doesn't have any feedback on position, so it can't guarantee it has any idea where it is. So, if a hard limit is triggered, Grbl will go into an infinite loop ALARM mode, giving you a chance to check your machine and forcing you to reset Grbl. Remember it's a purely a safety feature. + +#### $22 - Homing cycle, boolean + +Ahh, homing. For those just initiated into CNC, the homing cycle is used to accurately and precisely locate a known and consistent position on a machine every time you start up your Grbl between sessions. In other words, you know exactly where you are at any given time, every time. Say you start machining something or are about to start the next step in a job and the power goes out, you re-start Grbl and Grbl has no idea where it is. You're left with the task of figuring out where you are. If you have homing, you always have the machine zero reference point to locate from, so all you have to do is run the homing cycle and resume where you left off. + +To set up the homing cycle for Grbl, you need to have limit switches in a fixed position that won't get bumped or moved, or else your reference point gets messed up. Usually they are setup in the farthest point in +x, +y, +z of each axes. Wire your limit switches in with the limit pins and ground, just like with the hard limits, and enable homing. If you're curious, you can use your limit switches for both hard limits AND homing. They play nice with each other. + +By default, Grbl's homing cycle moves the Z-axis positive first to clear the workspace and then moves both the X and Y-axes at the same time in the positive direction. To set up how your homing cycle behaves, there are more Grbl settings down the page describing what they do (and compile-time options as well.) + +Also, one more thing to note, when homing is enabled. Grbl will lock out all G-code commands until you perform a homing cycle. Meaning no axes motions, unless the lock is disabled ($X) but more on that later. Most, if not all CNC controllers, do something similar, as it is mostly a safety feature to prevent users from making a positioning mistake, which is very easy to do and be saddened when a mistake ruins a part. If you find this annoying or find any weird bugs, please let us know and we'll try to work on it so everyone is happy. :) + +NOTE: Check out config.h for more homing options for advanced users. You can disable the homing lockout at startup, configure which axes move first during a homing cycle and in what order, and more. + + +#### $23 - Homing dir invert, mask + +By default, Grbl assumes your homing limit switches are in the positive direction, first moving the z-axis positive, then the x-y axes positive before trying to precisely locate machine zero by going back and forth slowly around the switch. If your machine has a limit switch in the negative direction, the homing direction mask can invert the axes' direction. It works just like the step port invert and direction port invert masks, where all you have to do is send the value in the table to indicate what axes you want to invert and search for in the opposite direction. + +#### $24 - Homing feed, mm/min + +The homing cycle first searches for the limit switches at a higher seek rate, and after it finds them, it moves at a slower feed rate to home into the precise location of machine zero. Homing feed rate is that slower feed rate. Set this to whatever rate value that provides repeatable and precise machine zero locating. + +#### $25 - Homing seek, mm/min + +Homing seek rate is the homing cycle search rate, or the rate at which it first tries to find the limit switches. Adjust to whatever rate gets to the limit switches in a short enough time without crashing into your limit switches if they come in too fast. + +#### $26 - Homing debounce, milliseconds + +Whenever a switch triggers, some of them can have electrical/mechanical noise that actually 'bounce' the signal high and low for a few milliseconds before settling in. To solve this, you need to debounce the signal, either by hardware with some kind of signal conditioner or by software with a short delay to let the signal finish bouncing. Grbl performs a short delay, only homing when locating machine zero. Set this delay value to whatever your switch needs to get repeatable homing. In most cases, 5-25 milliseconds is fine. + +#### $27 - Homing pull-off, mm + +To play nice with the hard limits feature, where homing can share the same limit switches, the homing cycle will move off all of the limit switches by this pull-off travel after it completes. In other words, it helps to prevent accidental triggering of the hard limit after a homing cycle. + +#### $30 - Max spindle speed, RPM + +This sets the spindle speed for the maximum 5V PWM pin output. Higher programmed spindle RPMs are accepted by Grbl but the PWM output will not exceed the max 5V. By default, Grbl linearly relates the max-min RPMs to 5V-0.02V PWM pin output in 255 increments. When the PWM pin reads 0V, this indicates spindle disabled. Note that there are additional configuration options are available in config.h to tweak how this operates. + +#### $31 - Min spindle speed, RPM + +This sets the spindle speed for the minimum 0.02V PWM pin output (0V is disabled). Lower RPM values are accepted by Grbl but the PWM output will not go below 0.02V, except when RPM is zero. If zero, the spindle is disabled and PWM output is 0V. + +#### $32 - Laser mode, boolean + +When enabled, Grbl will move continuously through consecutive `G1`, `G2`, or `G3` motion commands when programmed with a `S` spindle speed (laser power). The spindle PWM pin will be updated instantaneously through each motion without stopping. Please read the Grbl laser documentation and your laser device documentation prior to using this mode. Lasers are very dangerous. They can instantly damage your vision permanantly and cause fires. Grbl does not assume any responsibility for any issues the firmware may cause, as defined by its GPL license. + +When disabled, Grbl will operate as it always has, stopping motion with every `S` spindle speed command. This is the default operation of a milling machine to allow a pause to let the spindle change speeds. + +#### $100, $101 and $102 – [X,Y,Z] steps/mm + +Grbl needs to know how far each step will take the tool in reality. To calculate steps/mm for an axis of your machine you need to know: + +* The mm traveled per revolution of your stepper motor. This is dependent on your belt drive gears or lead screw pitch. +* The full steps per revolution of your steppers (typically 200) +* The microsteps per step of your controller (typically 1, 2, 4, 8, or 16). _Tip: Using high microstep values (e.g., 16) can reduce your stepper motor torque, so use the lowest that gives you the desired axis resolution and comfortable running properties._ + +The steps/mm can then be calculated like this: ```steps_per_mm = (steps_per_revolution*microsteps)/mm_per_rev``` + +Compute this value for every axis and write these settings to Grbl. + +#### $110, $111 and $112 – [X,Y,Z] Max rate, mm/min + +This sets the maximum rate each axis can move. Whenever Grbl plans a move, it checks whether or not the move causes any one of these individual axes to exceed their max rate. If so, it'll slow down the motion to ensure none of the axes exceed their max rate limits. This means that each axis has its own independent speed, which is extremely useful for limiting the typically slower Z-axis. + +The simplest way to determine these values is to test each axis one at a time by slowly increasing max rate settings and moving it. For example, to test the X-axis, send Grbl something like `G0 X50` with enough travel distance so that the axis accelerates to its max speed. You'll know you've hit the max rate threshold when your steppers stall. It'll make a bit of noise, but shouldn't hurt your motors. Enter a setting a 10-20% below this value, so you can account for wear, friction, and the mass of your workpiece/tool. Then, repeat for your other axes. + +NOTE: This max rate setting also sets the G0 seek rates. + +#### $120, $121, $122 – [X,Y,Z] Acceleration, mm/sec^2 + +This sets the axes acceleration parameters in mm/second/second. Simplistically, a lower value makes Grbl ease slower into motion, while a higher value yields tighter moves and reaches the desired feed rates much quicker. Much like the max rate setting, each axis has its own acceleration value and are independent of each other. This means that a multi-axis motion will only accelerate as quickly as the lowest contributing axis can. + +Again, like the max rate setting, the simplest way to determine the values for this setting is to individually test each axis with slowly increasing values until the motor stalls. Then finalize your acceleration setting with a value 10-20% below this absolute max value. This should account for wear, friction, and mass inertia. We highly recommend that you dry test some G-code programs with your new settings before committing to them. Sometimes the loading on your machine is different when moving in all axes together. + + +#### $130, $131, $132 – [X,Y,Z] Max travel, mm + +This sets the maximum travel from end to end for each axis in mm. This is only useful if you have soft limits (and homing) enabled, as this is only used by Grbl's soft limit feature to check if you have exceeded your machine limits with a motion command. diff --git a/doc/script/fit_nonlinear_spindle.py b/doc/script/fit_nonlinear_spindle.py new file mode 100644 index 0000000..57ca5f3 --- /dev/null +++ b/doc/script/fit_nonlinear_spindle.py @@ -0,0 +1,373 @@ +""" +--------------------- +The MIT License (MIT) + +Copyright (c) 2017-2018 Sungeun K. Jeon for Gnea Research LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +--------------------- +""" + + +""" +This Python script produces a continuous piece-wise line fit of actual spindle speed over +programmed speed/PWM, which must be measured and provided by the user. A plot of the data +and line fit will be auto-generated and saved in the working directory as 'line_fit.png'. + +REQUIREMENTS: + - Python 2.7 or 3.x with SciPy, NumPy, and Matplotlib Python Libraries + + - For the most people, the easiest way to run this script is on the free cloud service + https://repl.it/site/languages/python3. No account necessary. Unlimited runs. + + - Last checked on 4/5/2018. This site has been regularly evolving and becoming more + powerful. Things may not work exactly as shown. Please report any issues. + + - To use, go to the website and start the Python REPL. Copy and paste this script into + the main.py file in the browser editor. Click 'Run' and a solution should appear in + the text output in the REPL console window. You can edit the script directly in the + browser and re-run the script as many times as you need. A free account is only + necessary if you want to save files on their servers. + + - This script will also automatically generate a png image with the plot of the data + with the piece-wise linear fit over it, but this will not show up by default on this + website. To enable this, just click the 'Add File' icon and create a dummy file. + Name it anything, like dummy.py. Leave this file blank. Doing this places the REPL + in multiple file mode and will enable viewing the plot. Click the 'Run' icon. The + solution will be presented again in the console, and the data plot will appear in + the file list called 'line_fit.png'. Click the file to view the plot. + + - For offline Python installs, most Mac and Linux computers have Python pre-installed + with the required libraries. If not, a quick google search will show you how to + install them. For Windows, Python installations are bit more difficult. Anaconda and + Pyzo seem to work well. + +USAGE: + - First, make sure you are using the stock build of Grbl for the 328p processor. Most + importantly, the SPINDLE_PWM_MAX_VALUE and SPINDLE_PWM_MIN_VALUE should be unaltered + from defaults, otherwise change them back to 255.0 and 1.0 respectively for this test. + + - Next, program the max and min rpm Grbl settings to '$30=255' and '$31=1'. This sets + the internal PWM values equal to 'S' spindle speed for the standard Grbl build. + + - Check if your spindle does not turn on at very low voltages by setting 'S' spindle + speed to 'S1'. If it does not turn on or turns at a non-useful rpm, increase 'S' by + one until it does. Write down this 'S' value for later. You'll start the rpm data + collection from this point onward and will need to update the SPINDLE_PWM_MIN_VALUE + in cpu_map.h afterwards. + + - Collect actual spindle speed with a tachometer or similar means over a range of 'S' + and PWM values. Start by setting the spindle 'S' speed to the minimum useful 'S' from + the last step and measure and record actual spindle rpm. Next, increase 'S' spindle + speed over equally sized intervals and repeat the measurement. Increments of 20 rpm + should be more than enough, but decrease increment size, if highly nonlinear. Complete + the data collection the 'S' spindle speed equal to '$30' max rpm, or at the max useful + rpm, and record the actual rpm output. Make sure to collect rpm data all the way + throughout useful output rpm. The actual operating range within this model may be set + later within Grbl with the '$30' and '$31' settings. + + - In some cases, spindle PWM output can have discontinuities or not have a useful rpm + in certain ranges. For example, a known controller board has the spindle rpm drop + completely at voltages above ~4.5V. If you have discontinuities like this at the low + or high range of rpm, simply trim them from the data set. Don't include them. For + Grbl to compensate, you'll need to alter the SPINDLE_PWM_MIN_VALUE and/or + SPINDLE_PWM_MAX_VALUE in cpu_map.h to where your data set ends. This script will + indicate if you need to do that in the solution output. + + - Keep in mind that spindles without control electronics can slow down drastically when + cutting and under load. How much it slows down is dependent on a lot of factors, such + as feed rate, chip load, cutter diameter, flutes, cutter type, lubricant/coolant, + material being cut, etc. Even spindles with controllers can still slow down if the + load is higher than the max current the controller can provide. It's recommended to + frequently re-check and measure actual spindle speed during a job. You can always use + spindle speed overrides to tweak it temporarily to the desired speed. + + - Edit this script and enter the measured rpm values and their corresponding 'S' spindle + speed values in the data arrays below. Set the number of piecewise lines you would + like to use, from one to four lines. For most cases, four lines is perfectly fine. + In certain scenarios (laser engraving), this may significantly degrade performance and + should be reduced if possible. + + - Run the Python script. Visually assess the line fit from the plot. It will not likely + to what you want on the first go. Dial things in by altering the line fit junction + points 'PWM_pointX' in this script to move where the piecewise line junctions are + located along the plot x-axis. It may be desired to tweak the junction points so the + model solution is more accurate in the region that the spindle typically running. + Re-run the script and tweak the junction points until you are satified with the model. + + - Record the solution and enter the RPM_POINT and RPM_LINE values into config.h. Set the + number of piecewise lines used in this model in config.h. Also set the '$30' and '$31' + max and min rpm values to the solution values or in a range between them in Grbl '$' + settings. And finally, alter the SPINDLE_PWM_MIN_VALUE in cpu_map.h, if your spindle + needs to be above a certain voltage to produce a useful low rpm. + + - Once the solution is entered. Recompile and flash Grbl. This solution model is only + valid for this particular set of data. If the machine is altered, you will need to + perform this experiment again and regenerate a new model here. + +OUTPUT: + The solver produces a set of values that define the piecewise fit and can be used by + Grbl to quickly and efficiently compute spindle PWM output voltage for a desired RPM. + + The first two are the RPM_MAX ($30) and RPM_MIN ($31) Grbl settings. These must be + programmed into Grbl manually or setup in defaults.h for new systems. Altering these + values within Grbl after a piece-wise linear model is installed will not change alter + model. It will only alter the range of spindle speed rpm values Grbl output. + + For example, if the solver produces an RPM_MAX of 9000 and Grbl is programmed with + $30=8000, S9000 may be programmed, but Grbl will only produce the output voltage to run + at 8000 rpm. In other words, Grbl will only output voltages the range between + max(RPM_MIN,$31) and min(RPM_MAX,$30). + + The remaining values define the slopes and offsets of the line segments and the junction + points between line segments, like so for n_pieces=3: + + PWM_output = RPM_LINE_A1 * rpm - RPM_LINE_B1 [ RPM_MIN < rpm < RPM_POINT12 ] + PWM_output = RPM_LINE_A2 * rpm - RPM_LINE_B2 [ RPM_POINT12 < rpm < RPM_POINT23 ] + PWM_output = RPM_LINE_A3 * rpm - RPM_LINE_B3 [ RPM_POINT23 < rpm < RPM_MAX ] + + NOTE: The script solves in terms of PWM but the final equations and values are expressed + in terms of rpm in the form 'PWM = a*rpm - b'. + +""" + +from scipy import optimize +import numpy as np + +# ---------------------------------------------------------------------------------------- +# Configure spindle PWM line fit solver + +n_pieces = 4 # Number of line segments used for data fit. Only 1 to 4 line segments supported. + +# Programmed 'S' spindle speed values. Must start with minimum useful PWM or 'S' programmed +# value and end with the maximum useful PWM or 'S' programmed value. Order of the array must +# be synced with the RPM_measured array below. +# NOTE: ** DO NOT USE DATA FROM AN EXISTING PIECEWISE LINE FIT. USE DEFAULT GRBL MODEL ONLY. ** +PWM_set = np.array([2,18,36,55,73,91,109,127,146,164,182,200,218,237,254], dtype=float) + +# Actual RPM measured at the spindle. Must be in the ascending value and equal in length +# as the PWM_set array. Must include the min and max measured rpm output in the first and +# last array entries, respectively. +RPM_measured = np.array([213.,5420,7145,8282,9165,9765,10100,10500,10700,10900,11100,11250,11400,11550,11650], dtype=float) + +# Configure line fit points by 'S' programmed rpm or PWM value. Values must be between +# PWM_max and PWM_min. Typically, alter these values to space the points evenly between +# max and min PWM range. However, they may be tweaked to maximize accuracy in the places +# you normally operate for highly nonlinear curves. Plot to visually assess how well the +# solution fits the data. +PWM_point1 = 20.0 # (S) Point between segments 0 and 1. Used when n_pieces >= 2. +PWM_point2 = 80.0 # (S) Point between segments 1 and 2. Used when n_pieces >= 3. +PWM_point3 = 150.0 # (S) Point between segments 2 and 3. Used when n_pieces = 4. + +# ---------------------------------------------------------------------------------------- + +# Advanced settings + +# The optimizer requires an initial guess of the solution. Change value if solution fails. +slope_i = 100.0; # > 0.0 + +PWM_max = max(PWM_set) # Maximum PWM set in measured range +PWM_min = min(PWM_set) # Minimum PWM set in measured range +plot_figure = True # Set to False, if matplotlib is not available. + +# ---------------------------------------------------------------------------------------- +# DO NOT ALTER ANYTHING BELOW. + +def piecewise_linear_1(x,b,k1): + return np.piecewise(x, [(x>=PWM_min)&(x<=PWM_max)], [lambda x:k1*(x-PWM_min)+b]) + +def piecewise_linear_2(x,b,k1,k2): + c = [b, + b+k1*(PWM_point1-PWM_min)] + funcs = [lambda x:k1*(x-PWM_min)+c[0], + lambda x:k2*(x-PWM_point1)+c[1]] + conds = [(x=PWM_min), + (x<=PWM_max)&(x>=PWM_point1)] + return np.piecewise(x, conds, funcs) + +def piecewise_linear_3(x,b,k1,k2,k3): + c = [b, + b+k1*(PWM_point1-PWM_min), + b+k1*(PWM_point1-PWM_min)+k2*(PWM_point2-PWM_point1)] + funcs = [lambda x:k1*(x-PWM_min)+c[0], + lambda x:k2*(x-PWM_point1)+c[1], + lambda x:k3*(x-PWM_point2)+c[2]] + conds = [(x=PWM_min), + (x=PWM_point1), + (x<=PWM_max)&(x>=PWM_point2)] + return np.piecewise(x, conds, funcs) + +def piecewise_linear_4(x,b,k1,k2,k3,k4): + c = [b, + b+k1*(PWM_point1-PWM_min), + b+k1*(PWM_point1-PWM_min)+k2*(PWM_point2-PWM_point1), + b+k1*(PWM_point1-PWM_min)+k2*(PWM_point2-PWM_point1)+k3*(PWM_point3-PWM_point2)] + funcs = [lambda x:k1*(x-PWM_min)+c[0], + lambda x:k2*(x-PWM_point1)+c[1], + lambda x:k3*(x-PWM_point2)+c[2], + lambda x:k4*(x-PWM_point3)+c[3]] + conds = [(x=PWM_min), + (x=PWM_point1), + (x=PWM_point2), + (x<=PWM_max)&(x>=PWM_point3)] + return np.piecewise(x, conds, funcs) + +# ---------------------------------------------------------------------------------------- + +print("\nCONFIG:") +print(" N_pieces: %i" % n_pieces) +print(" PWM_min: %.1f" % PWM_min) +print(" PWM_max: %.1f" % PWM_max) +if n_pieces > 1: + print(" PWM_point1: %.1f" % PWM_point1) +if n_pieces > 2: + print(" PWM_point2: %.1f" % PWM_point2) +if n_pieces > 3: + print(" PWM_point3: %.1f" % PWM_point3) +print(" N_data: %i" % len(RPM_measured)) +print(" PWM_set: ", PWM_set) +print(" RPM_measured: ", RPM_measured) + +if n_pieces == 1: + piece_func = piecewise_linear_1 + p_initial = [RPM_measured[0],slope_i] + + p , e = optimize.curve_fit(piece_func, PWM_set, RPM_measured, p0=p_initial) + a = [p[1]] + b = [ p[0]-p[1]*PWM_min] + rpm = [ p[0], + p[0]+p[1]*(PWM_point1-PWM_min)] + +elif n_pieces == 2: + piece_func = piecewise_linear_2 + p_initial = [RPM_measured[0],slope_i,slope_i] + + p , e = optimize.curve_fit(piece_func, PWM_set, RPM_measured, p0=p_initial) + a = [p[1],p[2]] + b = [ p[0]-p[1]*PWM_min, + p[0]+p[1]*(PWM_point1-PWM_min)-p[2]*PWM_point1] + rpm = [ p[0], + p[0]+p[1]*(PWM_point1-PWM_min), + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_max-PWM_point1)] + +elif n_pieces == 3: + piece_func = piecewise_linear_3 + p_initial = [RPM_measured[0],slope_i,slope_i,slope_i] + + p , e = optimize.curve_fit(piece_func, PWM_set, RPM_measured, p0=p_initial) + a = [p[1],p[2],p[3]] + b = [ p[0]-p[1]*PWM_min, + p[0]+p[1]*(PWM_point1-PWM_min)-p[2]*PWM_point1, + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1)-p[3]*PWM_point2] + rpm = [ p[0], + p[0]+p[1]*(PWM_point1-PWM_min), + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1), + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1)+p[3]*(PWM_max-PWM_point2) ] + +elif n_pieces == 4: + piece_func = piecewise_linear_4 + p_initial = [RPM_measured[0],slope_i,slope_i,slope_i,slope_i] + + p , e = optimize.curve_fit(piece_func, PWM_set, RPM_measured, p0=p_initial) + a = [p[1],p[2],p[3],p[4]] + b = [ p[0]-p[1]*PWM_min, + p[0]+p[1]*(PWM_point1-PWM_min)-p[2]*PWM_point1, + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1)-p[3]*PWM_point2, + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1)+p[3]*(PWM_point3-PWM_point2)-p[4]*PWM_point3 ] + rpm = [ p[0], + p[0]+p[1]*(PWM_point1-PWM_min), + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1), + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1)+p[3]*(PWM_point3-PWM_point2), + p[0]+p[1]*(PWM_point1-PWM_min)+p[2]*(PWM_point2-PWM_point1)+p[3]*(PWM_point3-PWM_point2)+p[4]*(PWM_max-PWM_point3) ] + +else : + print("ERROR: Unsupported number of pieces. Check and alter n_pieces") + quit() + +print("\nSOLUTION:\n\n[Update these #define values and uncomment]\n[ENABLE_PIECEWISE_LINEAR_SPINDLE in config.h.]") +print("#define N_PIECES %.0f" % n_pieces) +print("#define RPM_MAX %.1f" % rpm[-1]) +print("#define RPM_MIN %.1f" % rpm[0]) + +if n_pieces > 1: + print("#define RPM_POINT12 %.1f" % rpm[1]) +if n_pieces > 2: + print("#define RPM_POINT23 %.1f" %rpm[2]) +if n_pieces > 3: + print("#define RPM_POINT34 %.1f" %rpm[3]) + +print("#define RPM_LINE_A1 %.6e" % (1./a[0])) +print("#define RPM_LINE_B1 %.6e" % (b[0]/a[0])) +if n_pieces > 1: + print("#define RPM_LINE_A2 %.6e" % (1./a[1])) + print("#define RPM_LINE_B2 %.6e" % (b[1]/a[1])) +if n_pieces > 2: + print("#define RPM_LINE_A3 %.6e" % (1./a[2])) + print("#define RPM_LINE_B3 %.6e" % (b[2]/a[2])) +if n_pieces > 3: + print("#define RPM_LINE_A4 %.6e" % (1./a[3])) + print("#define RPM_LINE_B4 %.6e" % (b[3]/a[3])) + +print("\n[To operate over full model range, manually write these]") +print("['$' settings or alter values in defaults.h. Grbl will]") +print("[operate between min($30,RPM_MAX) and max($31,RPM_MIN)]") +print("$30=%.1f (rpm max)" % rpm[-1]) +print("$31=%.1f (rpm min)" % rpm[0]) + +if (PWM_min > 1)|(PWM_max<255): + print("\n[Update the following #define values in cpu_map.h]") + if (PWM_min >1) : + print("#define SPINDLE_PWM_MIN_VALUE %.0f" % PWM_min) + if PWM_max <255: + print("#define SPINDLE_PWM_MAX_VALUE %.0f" % PWM_max) +else: + print("\n[No cpu_map.h changes required.]") +print("\n") + +test_val = (1./a[0])*rpm[0] - (b[0]/a[0]) +if test_val < 0.0 : + print("ERROR: Solution is negative at RPM_MIN. Adjust junction points or increase n_pieces.\n") + +if plot_figure: + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + + fig = plt.figure() + ax = fig.add_subplot(111) + xd = np.linspace(PWM_min, PWM_max, 10000) + ax.plot(PWM_set, RPM_measured, "o") + ax.plot(xd, piece_func(xd, *p),'g') + plt.xlabel("Programmed PWM") + plt.ylabel("Measured RPM") + + # Check solution by plotting in terms of rpm. +# x = np.linspace(rpm[0], rpm[1], 10000) +# ax.plot((1./a[0])*x-(b[0]/a[0]),x,'r:') +# if n_pieces > 1: +# x = np.linspace(rpm[1], rpm[2], 10000) +# ax.plot((1./a[1])*x-(b[1]/a[1]),x,'r:') +# if n_pieces > 2: +# x = np.linspace(rpm[2], rpm[3], 10000) +# ax.plot((1./a[2])*x-(b[2]/a[2]),x,'r:') +# if n_pieces > 3: +# x = np.linspace(rpm[3], rpm[-1], 10000) +# ax.plot((1./a[3])*x-(b[3]/a[3]),x,'r:') + + fig.savefig("line_fit.png") diff --git a/doc/script/simple_stream.py b/doc/script/simple_stream.py new file mode 100755 index 0000000..67c2a2c --- /dev/null +++ b/doc/script/simple_stream.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +"""\ +Simple g-code streaming script for grbl + +Provided as an illustration of the basic communication interface +for grbl. When grbl has finished parsing the g-code block, it will +return an 'ok' or 'error' response. When the planner buffer is full, +grbl will not send a response until the planner buffer clears space. + +G02/03 arcs are special exceptions, where they inject short line +segments directly into the planner. So there may not be a response +from grbl for the duration of the arc. + +--------------------- +The MIT License (MIT) + +Copyright (c) 2012 Sungeun K. Jeon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +--------------------- +""" + +import serial +import time + +# Open grbl serial port +s = serial.Serial('/dev/tty.usbmodem1811',115200) + +# Open g-code file +f = open('grbl.gcode','r'); + +# Wake up grbl +s.write("\r\n\r\n") +time.sleep(2) # Wait for grbl to initialize +s.flushInput() # Flush startup text in serial input + +# Stream g-code to grbl +for line in f: + l = line.strip() # Strip all EOL characters for consistency + print 'Sending: ' + l, + s.write(l + '\n') # Send g-code block to grbl + grbl_out = s.readline() # Wait for grbl response with carriage return + print ' : ' + grbl_out.strip() + +# Wait here until grbl is finished to close serial port and file. +raw_input(" Press to exit and disable grbl.") + +# Close file and serial port +f.close() +s.close() \ No newline at end of file diff --git a/doc/script/stream.py b/doc/script/stream.py new file mode 100755 index 0000000..4a637ab --- /dev/null +++ b/doc/script/stream.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +"""\ + +Stream g-code to grbl controller + +This script differs from the simple_stream.py script by +tracking the number of characters in grbl's serial read +buffer. This allows grbl to fetch the next line directly +from the serial buffer and does not have to wait for a +response from the computer. This effectively adds another +buffer layer to prevent buffer starvation. + +CHANGELOG: +- 20170531: Status report feedback at 1.0 second intervals. + Configurable baudrate and report intervals. Bug fixes. +- 20161212: Added push message feedback for simple streaming +- 20140714: Updated baud rate to 115200. Added a settings + write mode via simple streaming method. MIT-licensed. + +TODO: +- Add realtime control commands during streaming. + +--------------------- +The MIT License (MIT) + +Copyright (c) 2012-2017 Sungeun K. Jeon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +--------------------- +""" + +import serial +import re +import time +import sys +import argparse +import threading + +RX_BUFFER_SIZE = 128 +BAUD_RATE = 115200 +ENABLE_STATUS_REPORTS = True +REPORT_INTERVAL = 1.0 # seconds + +is_run = True # Controls query timer + +# Define command line argument interface +parser = argparse.ArgumentParser(description='Stream g-code file to grbl. (pySerial and argparse libraries required)') +parser.add_argument('gcode_file', type=argparse.FileType('r'), + help='g-code filename to be streamed') +parser.add_argument('device_file', + help='serial device path') +parser.add_argument('-q','--quiet',action='store_true', default=False, + help='suppress output text') +parser.add_argument('-s','--settings',action='store_true', default=False, + help='settings write mode') +parser.add_argument('-c','--check',action='store_true', default=False, + help='stream in check mode') +args = parser.parse_args() + +# Periodic timer to query for status reports +# TODO: Need to track down why this doesn't restart consistently before a release. +def send_status_query(): + s.write('?') + +def periodic_timer() : + while is_run: + send_status_query() + time.sleep(REPORT_INTERVAL) + + +# Initialize +s = serial.Serial(args.device_file,BAUD_RATE) +f = args.gcode_file +verbose = True +if args.quiet : verbose = False +settings_mode = False +if args.settings : settings_mode = True +check_mode = False +if args.check : check_mode = True + +# Wake up grbl +print "Initializing Grbl..." +s.write("\r\n\r\n") + +# Wait for grbl to initialize and flush startup text in serial input +time.sleep(2) +s.flushInput() + +if check_mode : + print "Enabling Grbl Check-Mode: SND: [$C]", + s.write("$C\n") + while 1: + grbl_out = s.readline().strip() # Wait for grbl response with carriage return + if grbl_out.find('error') >= 0 : + print "REC:",grbl_out + print " Failed to set Grbl check-mode. Aborting..." + quit() + elif grbl_out.find('ok') >= 0 : + if verbose: print 'REC:',grbl_out + break + +start_time = time.time(); + +# Start status report periodic timer +if ENABLE_STATUS_REPORTS : + timerThread = threading.Thread(target=periodic_timer) + timerThread.daemon = True + timerThread.start() + +# Stream g-code to grbl +l_count = 0 +error_count = 0 +if settings_mode: + # Send settings file via simple call-response streaming method. Settings must be streamed + # in this manner since the EEPROM accessing cycles shut-off the serial interrupt. + print "SETTINGS MODE: Streaming", args.gcode_file.name, " to ", args.device_file + for line in f: + l_count += 1 # Iterate line counter + # l_block = re.sub('\s|\(.*?\)','',line).upper() # Strip comments/spaces/new line and capitalize + l_block = line.strip() # Strip all EOL characters for consistency + if verbose: print "SND>"+str(l_count)+": \"" + l_block + "\"" + s.write(l_block + '\n') # Send g-code block to grbl + while 1: + grbl_out = s.readline().strip() # Wait for grbl response with carriage return + if grbl_out.find('ok') >= 0 : + if verbose: print " REC<"+str(l_count)+": \""+grbl_out+"\"" + break + elif grbl_out.find('error') >= 0 : + if verbose: print " REC<"+str(l_count)+": \""+grbl_out+"\"" + error_count += 1 + break + else: + print " MSG: \""+grbl_out+"\"" +else: + # Send g-code program via a more agressive streaming protocol that forces characters into + # Grbl's serial read buffer to ensure Grbl has immediate access to the next g-code command + # rather than wait for the call-response serial protocol to finish. This is done by careful + # counting of the number of characters sent by the streamer to Grbl and tracking Grbl's + # responses, such that we never overflow Grbl's serial read buffer. + g_count = 0 + c_line = [] + for line in f: + l_count += 1 # Iterate line counter + l_block = re.sub('\s|\(.*?\)','',line).upper() # Strip comments/spaces/new line and capitalize + # l_block = line.strip() + c_line.append(len(l_block)+1) # Track number of characters in grbl serial read buffer + grbl_out = '' + while sum(c_line) >= RX_BUFFER_SIZE-1 | s.inWaiting() : + out_temp = s.readline().strip() # Wait for grbl response + if out_temp.find('ok') < 0 and out_temp.find('error') < 0 : + print " MSG: \""+out_temp+"\"" # Debug response + else : + if out_temp.find('error') >= 0 : error_count += 1 + g_count += 1 # Iterate g-code counter + if verbose: print " REC<"+str(g_count)+": \""+out_temp+"\"" + del c_line[0] # Delete the block character count corresponding to the last 'ok' + s.write(l_block + '\n') # Send g-code block to grbl + if verbose: print "SND>"+str(l_count)+": \"" + l_block + "\"" + # Wait until all responses have been received. + while l_count > g_count : + out_temp = s.readline().strip() # Wait for grbl response + if out_temp.find('ok') < 0 and out_temp.find('error') < 0 : + print " MSG: \""+out_temp+"\"" # Debug response + else : + if out_temp.find('error') >= 0 : error_count += 1 + g_count += 1 # Iterate g-code counter + del c_line[0] # Delete the block character count corresponding to the last 'ok' + if verbose: print " REC<"+str(g_count)+": \""+out_temp + "\"" + +# Wait for user input after streaming is completed +print "\nG-code streaming finished!" +end_time = time.time(); +is_run = False; +print " Time elapsed: ",end_time-start_time,"\n" +if check_mode : + if error_count > 0 : + print "CHECK FAILED:",error_count,"errors found! See output for details.\n" + else : + print "CHECK PASSED: No errors found in g-code program.\n" +else : + print "WARNING: Wait until Grbl completes buffered g-code blocks before exiting." + raw_input(" Press to exit and disable Grbl.") + +# Close file and serial port +f.close() +s.close() diff --git a/grbl/config.h b/grbl/config.h new file mode 100644 index 0000000..f48d958 --- /dev/null +++ b/grbl/config.h @@ -0,0 +1,692 @@ +/* + config.h - compile time configuration + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +// This file contains compile-time configurations for Grbl's internal system. For the most part, +// users will not need to directly modify these, but they are here for specific needs, i.e. +// performance tuning or adjusting to non-typical machines. + +// IMPORTANT: Any changes here requires a full re-compiling of the source code to propagate them. + +#ifndef config_h +#define config_h +#include "grbl.h" // For Arduino IDE compatibility. + + +// Define CPU pin map and default settings. +// NOTE: OEMs can avoid the need to maintain/update the defaults.h and cpu_map.h files and use only +// one configuration file by placing their specific defaults and pin map at the bottom of this file. +// If doing so, simply comment out these two defines and see instructions below. +#define DEFAULTS_GENERIC +#define CPU_MAP_ATMEGA328P // Arduino Uno CPU + +// Serial baud rate +// #define BAUD_RATE 230400 +#define BAUD_RATE 115200 + +// Define realtime command special characters. These characters are 'picked-off' directly from the +// serial read data stream and are not passed to the grbl line execution parser. Select characters +// that do not and must not exist in the streamed g-code program. ASCII control characters may be +// used, if they are available per user setup. Also, extended ASCII codes (>127), which are never in +// g-code programs, maybe selected for interface programs. +// NOTE: If changed, manually update help message in report.c. + +#define CMD_RESET 0x18 // ctrl-x. +#define CMD_STATUS_REPORT '?' +#define CMD_CYCLE_START '~' +#define CMD_FEED_HOLD '!' + +// NOTE: All override realtime commands must be in the extended ASCII character set, starting +// at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands, +// such as status reports, feed hold, reset, and cycle start, are moved to the extended set +// space, serial.c's RX ISR will need to be modified to accomodate the change. +// #define CMD_RESET 0x80 +// #define CMD_STATUS_REPORT 0x81 +// #define CMD_CYCLE_START 0x82 +// #define CMD_FEED_HOLD 0x83 +#define CMD_SAFETY_DOOR 0x84 +#define CMD_JOG_CANCEL 0x85 +#define CMD_DEBUG_REPORT 0x86 // Only when DEBUG enabled, sends debug report in '{}' braces. +#define CMD_FEED_OVR_RESET 0x90 // Restores feed override value to 100%. +#define CMD_FEED_OVR_COARSE_PLUS 0x91 +#define CMD_FEED_OVR_COARSE_MINUS 0x92 +#define CMD_FEED_OVR_FINE_PLUS 0x93 +#define CMD_FEED_OVR_FINE_MINUS 0x94 +#define CMD_RAPID_OVR_RESET 0x95 // Restores rapid override value to 100%. +#define CMD_RAPID_OVR_MEDIUM 0x96 +#define CMD_RAPID_OVR_LOW 0x97 +// #define CMD_RAPID_OVR_EXTRA_LOW 0x98 // *NOT SUPPORTED* +#define CMD_SPINDLE_OVR_RESET 0x99 // Restores spindle override value to 100%. +#define CMD_SPINDLE_OVR_COARSE_PLUS 0x9A +#define CMD_SPINDLE_OVR_COARSE_MINUS 0x9B +#define CMD_SPINDLE_OVR_FINE_PLUS 0x9C +#define CMD_SPINDLE_OVR_FINE_MINUS 0x9D +#define CMD_SPINDLE_OVR_STOP 0x9E +#define CMD_COOLANT_FLOOD_OVR_TOGGLE 0xA0 +#define CMD_COOLANT_MIST_OVR_TOGGLE 0xA1 + +// If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces +// the user to perform the homing cycle (or override the locks) before doing anything else. This is +// mainly a safety feature to remind the user to home, since position is unknown to Grbl. +#define HOMING_INIT_LOCK // Comment to disable + +// Define the homing cycle patterns with bitmasks. The homing cycle first performs a search mode +// to quickly engage the limit switches, followed by a slower locate mode, and finished by a short +// pull-off motion to disengage the limit switches. The following HOMING_CYCLE_x defines are executed +// in order starting with suffix 0 and completes the homing routine for the specified-axes only. If +// an axis is omitted from the defines, it will not home, nor will the system update its position. +// Meaning that this allows for users with non-standard cartesian machines, such as a lathe (x then z, +// with no y), to configure the homing cycle behavior to their needs. +// NOTE: The homing cycle is designed to allow sharing of limit pins, if the axes are not in the same +// cycle, but this requires some pin settings changes in cpu_map.h file. For example, the default homing +// cycle can share the Z limit pin with either X or Y limit pins, since they are on different cycles. +// By sharing a pin, this frees up a precious IO pin for other purposes. In theory, all axes limit pins +// may be reduced to one pin, if all axes are homed with seperate cycles, or vice versa, all three axes +// on separate pin, but homed in one cycle. Also, it should be noted that the function of hard limits +// will not be affected by pin sharing. +// NOTE: Defaults are set for a traditional 3-axis CNC machine. Z-axis first to clear, followed by X & Y. +#define HOMING_CYCLE_0 (1< 3us, and, when added with the +// user-supplied step pulse time, the total time must not exceed 127us. Reported successful +// values for certain setups have ranged from 5 to 20us. +// #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled. + +// The number of linear motions in the planner buffer to be planned at any give time. The vast +// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra +// available RAM, like when re-compiling for a Mega2560. Or decrease if the Arduino begins to +// crash due to the lack of available RAM or if the CPU is having trouble keeping up with planning +// new incoming motions as they are executed. +// #define BLOCK_BUFFER_SIZE 16 // Uncomment to override default in planner.h. + +// Governs the size of the intermediary step segment buffer between the step execution algorithm +// and the planner blocks. Each segment is set of steps executed at a constant velocity over a +// fixed time defined by ACCELERATION_TICKS_PER_SECOND. They are computed such that the planner +// block velocity profile is traced exactly. The size of this buffer governs how much step +// execution lead time there is for other Grbl processes have to compute and do their thing +// before having to come back and refill this buffer, currently at ~50msec of step moves. +// #define SEGMENT_BUFFER_SIZE 6 // Uncomment to override default in stepper.h. + +// Line buffer size from the serial input stream to be executed. Also, governs the size of +// each of the startup blocks, as they are each stored as a string of this size. Make sure +// to account for the available EEPROM at the defined memory address in settings.h and for +// the number of desired startup blocks. +// NOTE: 80 characters is not a problem except for extreme cases, but the line buffer size +// can be too small and g-code blocks can get truncated. Officially, the g-code standards +// support up to 256 characters. In future versions, this default will be increased, when +// we know how much extra memory space we can re-invest into this. +// #define LINE_BUFFER_SIZE 80 // Uncomment to override default in protocol.h + +// Serial send and receive buffer size. The receive buffer is often used as another streaming +// buffer to store incoming blocks to be processed by Grbl when its ready. Most streaming +// interfaces will character count and track each block send to each block response. So, +// increase the receive buffer if a deeper receive buffer is needed for streaming and avaiable +// memory allows. The send buffer primarily handles messages in Grbl. Only increase if large +// messages are sent and Grbl begins to stall, waiting to send the rest of the message. +// NOTE: Grbl generates an average status report in about 0.5msec, but the serial TX stream at +// 115200 baud will take 5 msec to transmit a typical 55 character report. Worst case reports are +// around 90-100 characters. As long as the serial TX buffer doesn't get continually maxed, Grbl +// will continue operating efficiently. Size the TX buffer around the size of a worst-case report. +// #define RX_BUFFER_SIZE 128 // (1-254) Uncomment to override defaults in serial.h +// #define TX_BUFFER_SIZE 100 // (1-254) + +// A simple software debouncing feature for hard limit switches. When enabled, the interrupt +// monitoring the hard limit switch pins will enable the Arduino's watchdog timer to re-check +// the limit pin state after a delay of about 32msec. This can help with CNC machines with +// problematic false triggering of their hard limit switches, but it WILL NOT fix issues with +// electrical interference on the signal cables from external sources. It's recommended to first +// use shielded signal cables with their shielding connected to ground (old USB/computer cables +// work well and are cheap to find) and wire in a low-pass circuit into each limit pin. +// #define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable. + +// Configures the position after a probing cycle during Grbl's check mode. Disabled sets +// the position to the probe target, when enabled sets the position to the start position. +// #define SET_CHECK_MODE_PROBE_TO_START // Default disabled. Uncomment to enable. + +// Force Grbl to check the state of the hard limit switches when the processor detects a pin +// change inside the hard limit ISR routine. By default, Grbl will trigger the hard limits +// alarm upon any pin change, since bouncing switches can cause a state check like this to +// misread the pin. When hard limits are triggered, they should be 100% reliable, which is the +// reason that this option is disabled by default. Only if your system/electronics can guarantee +// that the switches don't bounce, we recommend enabling this option. This will help prevent +// triggering a hard limit when the machine disengages from the switch. +// NOTE: This option has no effect if SOFTWARE_DEBOUNCE is enabled. +// #define HARD_LIMIT_FORCE_STATE_CHECK // Default disabled. Uncomment to enable. + +// Adjusts homing cycle search and locate scalars. These are the multipliers used by Grbl's +// homing cycle to ensure the limit switches are engaged and cleared through each phase of +// the cycle. The search phase uses the axes max-travel setting times the SEARCH_SCALAR to +// determine distance to look for the limit switch. Once found, the locate phase begins and +// uses the homing pull-off distance setting times the LOCATE_SCALAR to pull-off and re-engage +// the limit switch. +// NOTE: Both of these values must be greater than 1.0 to ensure proper function. +// #define HOMING_AXIS_SEARCH_SCALAR 1.5 // Uncomment to override defaults in limits.c. +// #define HOMING_AXIS_LOCATE_SCALAR 10.0 // Uncomment to override defaults in limits.c. + +// Enable the '$RST=*', '$RST=$', and '$RST=#' eeprom restore commands. There are cases where +// these commands may be undesirable. Simply comment the desired macro to disable it. +// NOTE: See SETTINGS_RESTORE_ALL macro for customizing the `$RST=*` command. +#define ENABLE_RESTORE_EEPROM_WIPE_ALL // '$RST=*' Default enabled. Comment to disable. +#define ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // '$RST=$' Default enabled. Comment to disable. +#define ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // '$RST=#' Default enabled. Comment to disable. + +// Defines the EEPROM data restored upon a settings version change and `$RST=*` command. Whenever the +// the settings or other EEPROM data structure changes between Grbl versions, Grbl will automatically +// wipe and restore the EEPROM. This macro controls what data is wiped and restored. This is useful +// particularily for OEMs that need to retain certain data. For example, the BUILD_INFO string can be +// written into the Arduino EEPROM via a seperate .INO sketch to contain product data. Altering this +// macro to not restore the build info EEPROM will ensure this data is retained after firmware upgrades. +// NOTE: Uncomment to override defaults in settings.h +// #define SETTINGS_RESTORE_ALL (SETTINGS_RESTORE_DEFAULTS | SETTINGS_RESTORE_PARAMETERS | SETTINGS_RESTORE_STARTUP_LINES | SETTINGS_RESTORE_BUILD_INFO) + +// Enable the '$I=(string)' build info write command. If disabled, any existing build info data must +// be placed into EEPROM via external means with a valid checksum value. This macro option is useful +// to prevent this data from being over-written by a user, when used to store OEM product data. +// NOTE: If disabled and to ensure Grbl can never alter the build info line, you'll also need to enable +// the SETTING_RESTORE_ALL macro above and remove SETTINGS_RESTORE_BUILD_INFO from the mask. +// NOTE: See the included grblWrite_BuildInfo.ino example file to write this string seperately. +#define ENABLE_BUILD_INFO_WRITE_COMMAND // '$I=' Default enabled. Comment to disable. + +// AVR processors require all interrupts to be disabled during an EEPROM write. This includes both +// the stepper ISRs and serial comm ISRs. In the event of a long EEPROM write, this ISR pause can +// cause active stepping to lose position and serial receive data to be lost. This configuration +// option forces the planner buffer to completely empty whenever the EEPROM is written to prevent +// any chance of lost steps. +// However, this doesn't prevent issues with lost serial RX data during an EEPROM write, especially +// if a GUI is premptively filling up the serial RX buffer simultaneously. It's highly advised for +// GUIs to flag these gcodes (G10,G28.1,G30.1) to always wait for an 'ok' after a block containing +// one of these commands before sending more data to eliminate this issue. +// NOTE: Most EEPROM write commands are implicitly blocked during a job (all '$' commands). However, +// coordinate set g-code commands (G10,G28/30.1) are not, since they are part of an active streaming +// job. At this time, this option only forces a planner buffer sync with these g-code commands. +#define FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // Default enabled. Comment to disable. + +// In Grbl v0.9 and prior, there is an old outstanding bug where the `WPos:` work position reported +// may not correlate to what is executing, because `WPos:` is based on the g-code parser state, which +// can be several motions behind. This option forces the planner buffer to empty, sync, and stop +// motion whenever there is a command that alters the work coordinate offsets `G10,G43.1,G92,G54-59`. +// This is the simplest way to ensure `WPos:` is always correct. Fortunately, it's exceedingly rare +// that any of these commands are used need continuous motions through them. +#define FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // Default enabled. Comment to disable. + +// By default, Grbl disables feed rate overrides for all G38.x probe cycle commands. Although this +// may be different than some pro-class machine control, it's arguable that it should be this way. +// Most probe sensors produce different levels of error that is dependent on rate of speed. By +// keeping probing cycles to their programmed feed rates, the probe sensor should be a lot more +// repeatable. If needed, you can disable this behavior by uncommenting the define below. +// #define ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES // Default disabled. Uncomment to enable. + +// Enables and configures parking motion methods upon a safety door state. Primarily for OEMs +// that desire this feature for their integrated machines. At the moment, Grbl assumes that +// the parking motion only involves one axis, although the parking implementation was written +// to be easily refactored for any number of motions on different axes by altering the parking +// source code. At this time, Grbl only supports parking one axis (typically the Z-axis) that +// moves in the positive direction upon retracting and negative direction upon restoring position. +// The motion executes with a slow pull-out retraction motion, power-down, and a fast park. +// Restoring to the resume position follows these set motions in reverse: fast restore to +// pull-out position, power-up with a time-out, and plunge back to the original position at the +// slower pull-out rate. +// NOTE: Still a work-in-progress. Machine coordinates must be in all negative space and +// does not work with HOMING_FORCE_SET_ORIGIN enabled. Parking motion also moves only in +// positive direction. +// #define PARKING_ENABLE // Default disabled. Uncomment to enable + +// Configure options for the parking motion, if enabled. +#define PARKING_AXIS Z_AXIS // Define which axis that performs the parking motion +#define PARKING_TARGET -5.0 // Parking axis target. In mm, as machine coordinate [-max_travel,0]. +#define PARKING_RATE 500.0 // Parking fast rate after pull-out in mm/min. +#define PARKING_PULLOUT_RATE 100.0 // Pull-out/plunge slow feed rate in mm/min. +#define PARKING_PULLOUT_INCREMENT 5.0 // Spindle pull-out and plunge distance in mm. Incremental distance. + // Must be positive value or equal to zero. + +// Enables a special set of M-code commands that enables and disables the parking motion. +// These are controlled by `M56`, `M56 P1`, or `M56 Px` to enable and `M56 P0` to disable. +// The command is modal and will be set after a planner sync. Since it is g-code, it is +// executed in sync with g-code commands. It is not a real-time command. +// NOTE: PARKING_ENABLE is required. By default, M56 is active upon initialization. Use +// DEACTIVATE_PARKING_UPON_INIT to set M56 P0 as the power-up default. +// #define ENABLE_PARKING_OVERRIDE_CONTROL // Default disabled. Uncomment to enable +// #define DEACTIVATE_PARKING_UPON_INIT // Default disabled. Uncomment to enable. + +// This option will automatically disable the laser during a feed hold by invoking a spindle stop +// override immediately after coming to a stop. However, this also means that the laser still may +// be reenabled by disabling the spindle stop override, if needed. This is purely a safety feature +// to ensure the laser doesn't inadvertently remain powered while at a stop and cause a fire. +#define DISABLE_LASER_DURING_HOLD // Default enabled. Comment to disable. + +// This feature alters the spindle PWM/speed to a nonlinear output with a simple piecewise linear +// curve. Useful for spindles that don't produce the right RPM from Grbl's standard spindle PWM +// linear model. Requires a solution by the 'fit_nonlinear_spindle.py' script in the /doc/script +// folder of the repo. See file comments on how to gather spindle data and run the script to +// generate a solution. +// #define ENABLE_PIECEWISE_LINEAR_SPINDLE // Default disabled. Uncomment to enable. + +// N_PIECES, RPM_MAX, RPM_MIN, RPM_POINTxx, and RPM_LINE_XX constants are all set and given by +// the 'fit_nonlinear_spindle.py' script solution. Used only when ENABLE_PIECEWISE_LINEAR_SPINDLE +// is enabled. Make sure the constant values are exactly the same as the script solution. +// NOTE: When N_PIECES < 4, unused RPM_LINE and RPM_POINT defines are not required and omitted. +#define N_PIECES 4 // Integer (1-4). Number of piecewise lines used in script solution. +#define RPM_MAX 11686.4 // Max RPM of model. $30 > RPM_MAX will be limited to RPM_MAX. +#define RPM_MIN 202.5 // Min RPM of model. $31 < RPM_MIN will be limited to RPM_MIN. +#define RPM_POINT12 6145.4 // Used N_PIECES >=2. Junction point between lines 1 and 2. +#define RPM_POINT23 9627.8 // Used N_PIECES >=3. Junction point between lines 2 and 3. +#define RPM_POINT34 10813.9 // Used N_PIECES = 4. Junction point between lines 3 and 4. +#define RPM_LINE_A1 3.197101e-03 // Used N_PIECES >=1. A and B constants of line 1. +#define RPM_LINE_B1 -3.526076e-1 +#define RPM_LINE_A2 1.722950e-2 // Used N_PIECES >=2. A and B constants of line 2. +#define RPM_LINE_B2 8.588176e+01 +#define RPM_LINE_A3 5.901518e-02 // Used N_PIECES >=3. A and B constants of line 3. +#define RPM_LINE_B3 4.881851e+02 +#define RPM_LINE_A4 1.203413e-01 // Used N_PIECES = 4. A and B constants of line 4. +#define RPM_LINE_B4 1.151360e+03 + +/* --------------------------------------------------------------------------------------- + This optional dual axis feature is primarily for the homing cycle to locate two sides of + a dual-motor gantry independently, i.e. self-squaring. This requires an additional limit + switch for the cloned motor. To self square, both limit switches on the cloned axis must + be physically positioned to trigger when the gantry is square. Highly recommend keeping + the motors always enabled to ensure the gantry stays square with the $1=255 setting. + + For Grbl on the Arduino Uno, the cloned axis limit switch must to be shared with and + wired with z-axis limit pin due to the lack of available pins. The homing cycle must home + the z-axis and cloned axis in different cycles, which is already the default config. + + The dual axis feature works by cloning an axis step output onto another pair of step + and direction pins. The step pulse and direction of the cloned motor can be set + independently of the main axis motor. However to save precious flash and memory, this + dual axis feature must share the same settings (step/mm, max speed, acceleration) as the + parent motor. This is NOT a feature for an independent fourth axis. Only a motor clone. + + WARNING: Make sure to test the directions of your dual axis motors! They must be setup + to move the same direction BEFORE running your first homing cycle or any long motion! + Motors moving in opposite directions can cause serious damage to your machine! Use this + dual axis feature at your own risk. +*/ +// NOTE: This feature requires approximately 400 bytes of flash. Certain configurations can +// run out of flash to fit on an Arduino 328p/Uno. Only X and Y axes are supported. Variable +// spindle/laser mode IS supported, but only for one config option. Core XY, spindle direction +// pin, and M7 mist coolant are disabled/not supported. +// #define ENABLE_DUAL_AXIS // Default disabled. Uncomment to enable. + +// Select the one axis to mirror another motor. Only X and Y axis is supported at this time. +#define DUAL_AXIS_SELECT X_AXIS // Must be either X_AXIS or Y_AXIS + +// To prevent the homing cycle from racking the dual axis, when one limit triggers before the +// other due to switch failure or noise, the homing cycle will automatically abort if the second +// motor's limit switch does not trigger within the three distance parameters defined below. +// Axis length percent will automatically compute a fail distance as a percentage of the max +// travel of the other non-dual axis, i.e. if dual axis select is X_AXIS at 5.0%, then the fail +// distance will be computed as 5.0% of y-axis max travel. Fail distance max and min are the +// limits of how far or little a valid fail distance is. +#define DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT 5.0 // Float (percent) +#define DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX 25.0 // Float (mm) +#define DUAL_AXIS_HOMING_FAIL_DISTANCE_MIN 2.5 // Float (mm) + +// Dual axis pin configuration currently supports two shields. Uncomment the shield you want, +// and comment out the other one(s). +// NOTE: Protoneer CNC Shield v3.51 has A.STP and A.DIR wired to pins A4 and A3 respectively. +// The variable spindle (i.e. laser mode) build option works and may be enabled or disabled. +// Coolant pin A3 is moved to D13, replacing spindle direction. +#define DUAL_AXIS_CONFIG_PROTONEER_V3_51 // Uncomment to select. Comment other configs. + +// NOTE: Arduino CNC Shield Clone (Originally Protoneer v3.0) has A.STP and A.DIR wired to +// D12 and D13, respectively. With the limit pins and stepper enable pin on this same port, +// the spindle enable pin had to be moved and spindle direction pin deleted. The spindle +// enable pin now resides on A3, replacing coolant enable. Coolant enable is bumped over to +// pin A4. Spindle enable is used far more and this pin setup helps facilitate users to +// integrate this feature without arguably too much work. +// Variable spindle (i.e. laser mode) does NOT work with this shield as configured. While +// variable spindle technically can work with this shield, it requires too many changes for +// most user setups to accomodate. It would best be implemented by sharing all limit switches +// on pins D9/D10 (as [X1,Z]/[X2,Y] or [X,Y2]/[Y1,Z]), home each axis independently, and +// updating lots of code to ensure everything is running correctly. +// #define DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE // Uncomment to select. Comment other configs. + + +/* --------------------------------------------------------------------------------------- + OEM Single File Configuration Option + + Instructions: Paste the cpu_map and default setting definitions below without an enclosing + #ifdef. Comment out the CPU_MAP_xxx and DEFAULT_xxx defines at the top of this file, and + the compiler will ignore the contents of defaults.h and cpu_map.h and use the definitions + below. +*/ + +// Paste CPU_MAP definitions here. + +// Paste default settings definitions here. + + +#endif diff --git a/grbl/coolant_control.c b/grbl/coolant_control.c new file mode 100644 index 0000000..1eebfc0 --- /dev/null +++ b/grbl/coolant_control.c @@ -0,0 +1,126 @@ +/* + coolant_control.c - coolant control methods + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +void coolant_init() +{ + COOLANT_FLOOD_DDR |= (1 << COOLANT_FLOOD_BIT); // Configure as output pin + #ifdef ENABLE_M7 + COOLANT_MIST_DDR |= (1 << COOLANT_MIST_BIT); + #endif + coolant_stop(); +} + + +// Returns current coolant output state. Overrides may alter it from programmed state. +uint8_t coolant_get_state() +{ + uint8_t cl_state = COOLANT_STATE_DISABLE; + #ifdef INVERT_COOLANT_FLOOD_PIN + if (bit_isfalse(COOLANT_FLOOD_PORT,(1 << COOLANT_FLOOD_BIT))) { + #else + if (bit_istrue(COOLANT_FLOOD_PORT,(1 << COOLANT_FLOOD_BIT))) { + #endif + cl_state |= COOLANT_STATE_FLOOD; + } + #ifdef ENABLE_M7 + #ifdef INVERT_COOLANT_MIST_PIN + if (bit_isfalse(COOLANT_MIST_PORT,(1 << COOLANT_MIST_BIT))) { + #else + if (bit_istrue(COOLANT_MIST_PORT,(1 << COOLANT_MIST_BIT))) { + #endif + cl_state |= COOLANT_STATE_MIST; + } + #endif + return(cl_state); +} + + +// Directly called by coolant_init(), coolant_set_state(), and mc_reset(), which can be at +// an interrupt-level. No report flag set, but only called by routines that don't need it. +void coolant_stop() +{ + #ifdef INVERT_COOLANT_FLOOD_PIN + COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); + #else + COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT); + #endif + #ifdef ENABLE_M7 + #ifdef INVERT_COOLANT_MIST_PIN + COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); + #else + COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT); + #endif + #endif +} + + +// Main program only. Immediately sets flood coolant running state and also mist coolant, +// if enabled. Also sets a flag to report an update to a coolant state. +// Called by coolant toggle override, parking restore, parking retract, sleep mode, g-code +// parser program end, and g-code parser coolant_sync(). +void coolant_set_state(uint8_t mode) +{ + if (sys.abort) { return; } // Block during abort. + + if (mode & COOLANT_FLOOD_ENABLE) { + #ifdef INVERT_COOLANT_FLOOD_PIN + COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT); + #else + COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); + #endif + } else { + #ifdef INVERT_COOLANT_FLOOD_PIN + COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); + #else + COOLANT_FLOOD_PORT &= ~(1 << COOLANT_FLOOD_BIT); + #endif + } + + #ifdef ENABLE_M7 + if (mode & COOLANT_MIST_ENABLE) { + #ifdef INVERT_COOLANT_MIST_PIN + COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT); + #else + COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); + #endif + } else { + #ifdef INVERT_COOLANT_MIST_PIN + COOLANT_MIST_PORT |= (1 << COOLANT_MIST_BIT); + #else + COOLANT_MIST_PORT &= ~(1 << COOLANT_MIST_BIT); + #endif + } + #endif + + sys.report_ovr_counter = 0; // Set to report change immediately +} + + +// G-code parser entry-point for setting coolant state. Forces a planner buffer sync and bails +// if an abort or check-mode is active. +void coolant_sync(uint8_t mode) +{ + if (sys.state == STATE_CHECK_MODE) { return; } + protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program. + coolant_set_state(mode); +} diff --git a/grbl/coolant_control.h b/grbl/coolant_control.h new file mode 100644 index 0000000..49b85f0 --- /dev/null +++ b/grbl/coolant_control.h @@ -0,0 +1,47 @@ +/* + coolant_control.h - spindle control methods + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef coolant_control_h +#define coolant_control_h + +#define COOLANT_NO_SYNC false +#define COOLANT_FORCE_SYNC true + +#define COOLANT_STATE_DISABLE 0 // Must be zero +#define COOLANT_STATE_FLOOD PL_COND_FLAG_COOLANT_FLOOD +#define COOLANT_STATE_MIST PL_COND_FLAG_COOLANT_MIST + + +// Initializes coolant control pins. +void coolant_init(); + +// Returns current coolant output state. Overrides may alter it from programmed state. +uint8_t coolant_get_state(); + +// Immediately disables coolant pins. +void coolant_stop(); + +// Sets the coolant pins according to state specified. +void coolant_set_state(uint8_t mode); + +// G-code parser entry-point for setting coolant states. Checks for and executes additional conditions. +void coolant_sync(uint8_t mode); + +#endif diff --git a/grbl/cpu_map.h b/grbl/cpu_map.h new file mode 100644 index 0000000..9f43a3f --- /dev/null +++ b/grbl/cpu_map.h @@ -0,0 +1,260 @@ +/* + cpu_map.h - CPU and pin mapping configuration file + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +/* The cpu_map.h files serve as a central pin mapping selection file for different + processor types or alternative pin layouts. This version of Grbl officially supports + only the Arduino Mega328p. */ + + +#ifndef cpu_map_h +#define cpu_map_h + + +#ifdef CPU_MAP_ATMEGA328P // (Arduino Uno) Officially supported by Grbl. + + // Define serial port pins and interrupt vectors. + #define SERIAL_RX USART_RX_vect + #define SERIAL_UDRE USART_UDRE_vect + + // Define step pulse output pins. NOTE: All step bit pins must be on the same port. + #define STEP_DDR DDRD + #define STEP_PORT PORTD + #define X_STEP_BIT 2 // Uno Digital Pin 2 + #define Y_STEP_BIT 3 // Uno Digital Pin 3 + #define Z_STEP_BIT 4 // Uno Digital Pin 4 + #define STEP_MASK ((1< 62.5kHz + // #define SPINDLE_TCCRB_INIT_MASK (1< 7.8kHz (Used in v0.9) + // #define SPINDLE_TCCRB_INIT_MASK ((1< 1.96kHz + #define SPINDLE_TCCRB_INIT_MASK (1< 0.98kHz (J-tech laser) + + // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings. + #define SPINDLE_PWM_DDR DDRB + #define SPINDLE_PWM_PORT PORTB + #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 + + #else + + // Dual axis feature requires an independent step pulse pin to operate. The independent direction pin is not + // absolutely necessary but facilitates easy direction inverting with a Grbl $$ setting. These pins replace + // the spindle direction and optional coolant mist pins. + + #ifdef DUAL_AXIS_CONFIG_PROTONEER_V3_51 + // NOTE: Step pulse and direction pins may be on any port and output pin. + #define STEP_DDR_DUAL DDRC + #define STEP_PORT_DUAL PORTC + #define DUAL_STEP_BIT 4 // Uno Analog Pin 4 + #define STEP_MASK_DUAL ((1< 62.5kHz + // #define SPINDLE_TCCRB_INIT_MASK (1< 7.8kHz (Used in v0.9) + // #define SPINDLE_TCCRB_INIT_MASK ((1< 1.96kHz + #define SPINDLE_TCCRB_INIT_MASK (1< 0.98kHz (J-tech laser) + + // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings. + #define SPINDLE_PWM_DDR DDRB + #define SPINDLE_PWM_PORT PORTB + #define SPINDLE_PWM_BIT 3 // Uno Digital Pin 11 + #endif + + // NOTE: Variable spindle not supported with this shield. + #ifdef DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE + // NOTE: Step pulse and direction pins may be on any port and output pin. + #define STEP_DDR_DUAL DDRB + #define STEP_PORT_DUAL PORTB + #define DUAL_STEP_BIT 4 // Uno Digital Pin 12 + #define STEP_MASK_DUAL ((1<. +*/ + +/* The defaults.h file serves as a central default settings selector for different machine + types, from DIY CNC mills to CNC conversions of off-the-shelf machines. The settings + files listed here are supplied by users, so your results may vary. However, this should + give you a good starting point as you get to know your machine and tweak the settings for + your nefarious needs. + NOTE: Ensure one and only one of these DEFAULTS_XXX values is defined in config.h */ + +#ifndef defaults_h + +#ifdef DEFAULTS_GENERIC + // Grbl generic default settings. Should work across different machines. + #define DEFAULT_X_STEPS_PER_MM 250.0 + #define DEFAULT_Y_STEPS_PER_MM 250.0 + #define DEFAULT_Z_STEPS_PER_MM 250.0 + #define DEFAULT_X_MAX_RATE 500.0 // mm/min + #define DEFAULT_Y_MAX_RATE 500.0 // mm/min + #define DEFAULT_Z_MAX_RATE 500.0 // mm/min + #define DEFAULT_X_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 + #define DEFAULT_Y_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 + #define DEFAULT_Z_ACCELERATION (10.0*60*60) // 10*60*60 mm/min^2 = 10 mm/sec^2 + #define DEFAULT_X_MAX_TRAVEL 200.0 // mm NOTE: Must be a positive value. + #define DEFAULT_Y_MAX_TRAVEL 200.0 // mm NOTE: Must be a positive value. + #define DEFAULT_Z_MAX_TRAVEL 200.0 // mm NOTE: Must be a positive value. + #define DEFAULT_SPINDLE_RPM_MAX 1000.0 // rpm + #define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm + #define DEFAULT_STEP_PULSE_MICROSECONDS 10 + #define DEFAULT_STEPPING_INVERT_MASK 0 + #define DEFAULT_DIRECTION_INVERT_MASK 0 + #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled) + #define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled + #define DEFAULT_JUNCTION_DEVIATION 0.01 // mm + #define DEFAULT_ARC_TOLERANCE 0.002 // mm + #define DEFAULT_REPORT_INCHES 0 // false + #define DEFAULT_INVERT_ST_ENABLE 0 // false + #define DEFAULT_INVERT_LIMIT_PINS 0 // false + #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false + #define DEFAULT_HARD_LIMIT_ENABLE 0 // false + #define DEFAULT_INVERT_PROBE_PIN 0 // false + #define DEFAULT_LASER_MODE 0 // false + #define DEFAULT_HOMING_ENABLE 0 // false + #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir + #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min + #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min + #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k) + #define DEFAULT_HOMING_PULLOFF 1.0 // mm +#endif + +#ifdef DEFAULTS_SHERLINE_5400 + // Description: Sherline 5400 mill with three NEMA 23 Keling KL23H256-21-8B 185 oz-in stepper motors, + // driven by three Pololu A4988 stepper drivers with a 30V, 6A power supply at 1.5A per winding. + #define MICROSTEPS 2 + #define STEPS_PER_REV 200.0 + #define MM_PER_REV (0.050*MM_PER_INCH) // 0.050 inch/rev leadscrew + #define DEFAULT_X_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) + #define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) + #define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) + #define DEFAULT_X_MAX_RATE 635.0 // mm/min (25 ipm) + #define DEFAULT_Y_MAX_RATE 635.0 // mm/min + #define DEFAULT_Z_MAX_RATE 635.0 // mm/min + #define DEFAULT_X_ACCELERATION (50.0*60*60) // 50*60*60 mm/min^2 = 50 mm/sec^2 + #define DEFAULT_Y_ACCELERATION (50.0*60*60) // 50*60*60 mm/min^2 = 50 mm/sec^2 + #define DEFAULT_Z_ACCELERATION (50.0*60*60) // 50*60*60 mm/min^2 = 50 mm/sec^2 + #define DEFAULT_X_MAX_TRAVEL 225.0 // mm NOTE: Must be a positive value. + #define DEFAULT_Y_MAX_TRAVEL 125.0 // mm NOTE: Must be a positive value. + #define DEFAULT_Z_MAX_TRAVEL 170.0 // mm NOTE: Must be a positive value. + #define DEFAULT_SPINDLE_RPM_MAX 2800.0 // rpm + #define DEFAULT_SPINDLE_RPM_MIN 0.0 // rpm + #define DEFAULT_STEP_PULSE_MICROSECONDS 10 + #define DEFAULT_STEPPING_INVERT_MASK 0 + #define DEFAULT_DIRECTION_INVERT_MASK ((1< +#include + +/* These EEPROM bits have different names on different devices. */ +#ifndef EEPE + #define EEPE EEWE //!< EEPROM program/write enable. + #define EEMPE EEMWE //!< EEPROM master program/write enable. +#endif + +/* These two are unfortunately not defined in the device include files. */ +#define EEPM1 5 //!< EEPROM Programming Mode Bit 1. +#define EEPM0 4 //!< EEPROM Programming Mode Bit 0. + +/* Define to reduce code size. */ +#define EEPROM_IGNORE_SELFPROG //!< Remove SPM flag polling. + +/*! \brief Read byte from EEPROM. + * + * This function reads one byte from a given EEPROM address. + * + * \note The CPU is halted for 4 clock cycles during EEPROM read. + * + * \param addr EEPROM address to read from. + * \return The byte read from the EEPROM address. + */ +unsigned char eeprom_get_char( unsigned int addr ) +{ + do {} while( EECR & (1< 0; size--) { + checksum = (checksum << 1) || (checksum >> 7); + checksum += *source; + eeprom_put_char(destination++, *(source++)); + } + eeprom_put_char(destination, checksum); +} + +int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) { + unsigned char data, checksum = 0; + for(; size > 0; size--) { + data = eeprom_get_char(source++); + checksum = (checksum << 1) || (checksum >> 7); + checksum += data; + *(destination++) = data; + } + return(checksum == eeprom_get_char(source)); +} + +// end of file diff --git a/grbl/eeprom.h b/grbl/eeprom.h new file mode 100644 index 0000000..c9718a2 --- /dev/null +++ b/grbl/eeprom.h @@ -0,0 +1,29 @@ +/* + eeprom.h - EEPROM methods + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef eeprom_h +#define eeprom_h + +unsigned char eeprom_get_char(unsigned int addr); +void eeprom_put_char(unsigned int addr, unsigned char new_value); +void memcpy_to_eeprom_with_checksum(unsigned int destination, char *source, unsigned int size); +int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size); + +#endif diff --git a/grbl/examples/grblUpload/grblUpload.ino b/grbl/examples/grblUpload/grblUpload.ino new file mode 100644 index 0000000..581b6b3 --- /dev/null +++ b/grbl/examples/grblUpload/grblUpload.ino @@ -0,0 +1,29 @@ +/*********************************************************************** +This sketch compiles and uploads Grbl to your 328p-based Arduino! + +To use: +- First make sure you have imported Grbl source code into your Arduino + IDE. There are details on our Github website on how to do this. + +- Select your Arduino Board and Serial Port in the Tools drop-down menu. + NOTE: Grbl only officially supports 328p-based Arduinos, like the Uno. + Using other boards will likely not work! + +- Then just click 'Upload'. That's it! + +For advanced users: + If you'd like to see what else Grbl can do, there are some additional + options for customization and features you can enable or disable. + Navigate your file system to where the Arduino IDE has stored the Grbl + source code files, open the 'config.h' file in your favorite text + editor. Inside are dozens of feature descriptions and #defines. Simply + comment or uncomment the #defines or alter their assigned values, save + your changes, and then click 'Upload' here. + +Copyright (c) 2015 Sungeun K. Jeon +Released under the MIT-license. See license.txt for details. +***********************************************************************/ + +#include + +// Do not alter this file! diff --git a/grbl/examples/grblUpload/license.txt b/grbl/examples/grblUpload/license.txt new file mode 100644 index 0000000..1abcdb9 --- /dev/null +++ b/grbl/examples/grblUpload/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Sungeun K. Jeon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/grbl/examples/grblWrite_BuildInfo/grblWrite_BuildInfo.ino b/grbl/examples/grblWrite_BuildInfo/grblWrite_BuildInfo.ino new file mode 100644 index 0000000..2759d47 --- /dev/null +++ b/grbl/examples/grblWrite_BuildInfo/grblWrite_BuildInfo.ino @@ -0,0 +1,109 @@ +/*********************************************************************** +This sketch writes a `$I` build info string directly into Arduino EEPROM + +To use: +- Just alter the "build_info_line" string to whatever you'd like. Then + compile and upload this sketch to your Arduino. + +- If your Arduino is blinking slowly, your string has already been + written to your EEPROM and been verified by checksums! That's it! + +- If you Arduino LED is blinking fast, something went wrong and the + checksums don't match. You can optionally connect to the Arduino via + the serial monitor, and the sketch will show what its doing. + +NOTE: This sketch is provided as a tool template for OEMs who may need +to restrict users from altering their build info, so they can place +important product information here when enabling the restriction. + +NOTE: When uploading Grbl to the Arduino with this sketch on it, make +sure you see the slow blink before you start the upload process. This +ensures you aren't flashing Grbl when it's in mid-write of the EEPROM. + +Copyright (c) 2016 Sungeun K. Jeon for Gnea Research LLC +Released under the MIT-license. See license.txt for details. +***********************************************************************/ + +#include +#include + +#define SERIAL_BAUD_RATE 115200 +#define LINE_LENGTH 80U // Grbl line length +#define BYTE_LOCATION 942U // Grbl build info EEPROM address. + + +// ----- CHANGE THIS LINE ----- + +char build_info_line[LINE_LENGTH] = "Testing123."; + +// ----------------------------- + + +uint8_t status = false; +int ledPin = 13; // LED connected to digital pin 13 + +void setup() { + Serial.begin(SERIAL_BAUD_RATE); + delay(500); + + uint32_t address = BYTE_LOCATION; + uint32_t size = LINE_LENGTH; + char *write_pointer = (char*)build_info_line; + uint8_t write_checksum = 0; + for (; size>0; size--) { + write_checksum = (write_checksum << 1) || (write_checksum >> 7); + write_checksum += *write_pointer; + EEPROM.put(address++, *(write_pointer++)); + } + EEPROM.put(address,write_checksum); + + Serial.print(F("-> Writing line to EEPROM: '")); + Serial.print(build_info_line); + Serial.print(F("'\n\r-> Write checksum: ")); + Serial.println(write_checksum,DEC); + + size = LINE_LENGTH; + address = BYTE_LOCATION; + uint8_t data = 0; + char read_line[LINE_LENGTH]; + char *read_pointer = (char*)read_line; + uint8_t read_checksum = 0; + uint8_t stored_checksum = 0; + for(; size > 0; size--) { + data = EEPROM.read(address++); + read_checksum = (read_checksum << 1) || (read_checksum >> 7); + read_checksum += data; + *(read_pointer++) = data; + } + stored_checksum = EEPROM.read(address); + + Serial.print(F("<- Reading line from EEPROM: '")); + Serial.print(read_line); + Serial.print("'\n\r<- Read checksum: "); + Serial.println(read_checksum,DEC); + + if ((read_checksum == write_checksum) && (read_checksum == stored_checksum)) { + status = true; + Serial.print(F("SUCCESS! All checksums match!\r\n")); + } else { + if (write_checksum != stored_checksum) { + Serial.println(F("ERROR! Write and stored EEPROM checksums don't match!")); + } else { + Serial.println(F("ERROR! Read and stored checksums don't match!")); + } + } + pinMode(ledPin, OUTPUT); // sets the digital pin as output +} + +void loop() { + // Blink to let user know EEPROM write status. + // Slow blink is 'ok'. Fast blink is an 'error'. + digitalWrite(ledPin, HIGH); // sets the LED on + if (status) { delay(1500); } // Slow blink + else { delay(100); } // Rapid blink + digitalWrite(ledPin, LOW); // sets the LED off + if (status) { delay(1500); } + else { delay(100); } +} + + diff --git a/grbl/examples/grblWrite_BuildInfo/license.txt b/grbl/examples/grblWrite_BuildInfo/license.txt new file mode 100644 index 0000000..0da8f39 --- /dev/null +++ b/grbl/examples/grblWrite_BuildInfo/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Sungeun K. Jeon for Gnea Research LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/grbl/gcode.c b/grbl/gcode.c new file mode 100644 index 0000000..57e31e5 --- /dev/null +++ b/grbl/gcode.c @@ -0,0 +1,1159 @@ +/* + gcode.c - rs274/ngc parser. + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + +// NOTE: Max line number is defined by the g-code standard to be 99999. It seems to be an +// arbitrary value, and some GUIs may require more. So we increased it based on a max safe +// value when converting a float (7.2 digit precision)s to an integer. +#define MAX_LINE_NUMBER 10000000 +#define MAX_TOOL_NUMBER 255 // Limited by max unsigned 8-bit value + +#define AXIS_COMMAND_NONE 0 +#define AXIS_COMMAND_NON_MODAL 1 +#define AXIS_COMMAND_MOTION_MODE 2 +#define AXIS_COMMAND_TOOL_LENGTH_OFFSET 3 // *Undefined but required + +// Declare gc extern struct +parser_state_t gc_state; +parser_block_t gc_block; + +#define FAIL(status) return(status); + + +void gc_init() +{ + memset(&gc_state, 0, sizeof(parser_state_t)); + + // Load default G54 coordinate system. + if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) { + report_status_message(STATUS_SETTING_READ_FAIL); + } +} + + +// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard +// limit pull-off routines. +void gc_sync_position() +{ + system_convert_array_steps_to_mpos(gc_state.position,sys_position); +} + + +// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase +// characters and signed floating point values (no whitespace). Comments and block delete +// characters have been removed. In this function, all units and positions are converted and +// exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine +// coordinates, respectively. +uint8_t gc_execute_line(char *line) +{ + /* ------------------------------------------------------------------------------------- + STEP 1: Initialize parser block struct and copy current g-code state modes. The parser + updates these modes and commands as the block line is parser and will only be used and + executed after successful error-checking. The parser block struct also contains a block + values struct, word tracking variables, and a non-modal commands tracker for the new + block. This struct contains all of the necessary information to execute the block. */ + + memset(&gc_block, 0, sizeof(parser_block_t)); // Initialize the parser block struct. + memcpy(&gc_block.modal,&gc_state.modal,sizeof(gc_modal_t)); // Copy current modes + + uint8_t axis_command = AXIS_COMMAND_NONE; + uint8_t axis_0, axis_1, axis_linear; + uint8_t coord_select = 0; // Tracks G10 P coordinate selection for execution + + // Initialize bitflag tracking variables for axis indices compatible operations. + uint8_t axis_words = 0; // XYZ tracking + uint8_t ijk_words = 0; // IJK tracking + + // Initialize command and value words and parser flags variables. + uint16_t command_words = 0; // Tracks G and M command words. Also used for modal group violations. + uint16_t value_words = 0; // Tracks value words. + uint8_t gc_parser_flags = GC_PARSER_NONE; + + // Determine if the line is a jogging motion or a normal g-code block. + if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function. + // Set G1 and G94 enforced modes to ensure accurate error checks. + gc_parser_flags |= GC_PARSER_JOG_MOTION; + gc_block.modal.motion = MOTION_MODE_LINEAR; + gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; + #ifdef USE_LINE_NUMBERS + gc_block.values.n = JOG_LINE_NUMBER; // Initialize default line number reported during jog. + #endif + } + + /* ------------------------------------------------------------------------------------- + STEP 2: Import all g-code words in the block line. A g-code word is a letter followed by + a number, which can either be a 'G'/'M' command or sets/assigns a command value. Also, + perform initial error-checks for command word modal group violations, for any repeated + words, and for negative values set for the value words F, N, P, T, and S. */ + + uint8_t word_bit; // Bit-value for assigning tracking variables + uint8_t char_counter; + char letter; + float value; + uint8_t int_value = 0; + uint16_t mantissa = 0; + if (gc_parser_flags & GC_PARSER_JOG_MOTION) { char_counter = 3; } // Start parsing after `$J=` + else { char_counter = 0; } + + while (line[char_counter] != 0) { // Loop until no more g-code words in line. + + // Import the next g-code word, expecting a letter followed by a value. Otherwise, error out. + letter = line[char_counter]; + if((letter < 'A') || (letter > 'Z')) { FAIL(STATUS_EXPECTED_COMMAND_LETTER); } // [Expected word letter] + char_counter++; + if (!read_float(line, &char_counter, &value)) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // [Expected word value] + + // Convert values to smaller uint8 significand and mantissa values for parsing this word. + // NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more + // accurate than the NIST gcode requirement of x10 when used for commands, but not quite + // accurate enough for value words that require integers to within 0.0001. This should be + // a good enough comprimise and catch most all non-integer errors. To make it compliant, + // we would simply need to change the mantissa to int16, but this add compiled flash space. + // Maybe update this later. + int_value = trunc(value); + mantissa = round(100*(value - int_value)); // Compute mantissa for Gxx.x commands. + // NOTE: Rounding must be used to catch small floating point errors. + + // Check if the g-code word is supported or errors due to modal group violations or has + // been repeated in the g-code block. If ok, update the command or record its value. + switch(letter) { + + /* 'G' and 'M' Command Words: Parse commands and check for modal group violations. + NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */ + + case 'G': + // Determine 'G' command and its modal group + switch(int_value) { + case 10: case 28: case 30: case 92: + // Check for G10/28/30/92 being called with G0/1/2/3/38 on same block. + // * G43.1 is also an axis command but is not explicitly defined this way. + if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1 + if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] + axis_command = AXIS_COMMAND_NON_MODAL; + } + // No break. Continues to next line. + case 4: case 53: + word_bit = MODAL_GROUP_G0; + gc_block.non_modal_command = int_value; + if ((int_value == 28) || (int_value == 30) || (int_value == 92)) { + if (!((mantissa == 0) || (mantissa == 10))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } + gc_block.non_modal_command += mantissa; + mantissa = 0; // Set to zero to indicate valid non-integer G command. + } + break; + case 0: case 1: case 2: case 3: case 38: + // Check for G0/1/2/3/38 being called with G10/28/30/92 on same block. + // * G43.1 is also an axis command but is not explicitly defined this way. + if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] + axis_command = AXIS_COMMAND_MOTION_MODE; + // No break. Continues to next line. + case 80: + word_bit = MODAL_GROUP_G1; + gc_block.modal.motion = int_value; + if (int_value == 38){ + if (!((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))) { + FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command] + } + gc_block.modal.motion += (mantissa/10)+100; + mantissa = 0; // Set to zero to indicate valid non-integer G command. + } + break; + case 17: case 18: case 19: + word_bit = MODAL_GROUP_G2; + gc_block.modal.plane_select = int_value - 17; + break; + case 90: case 91: + if (mantissa == 0) { + word_bit = MODAL_GROUP_G3; + gc_block.modal.distance = int_value - 90; + } else { + word_bit = MODAL_GROUP_G4; + if ((mantissa != 10) || (int_value == 90)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G90.1 not supported] + mantissa = 0; // Set to zero to indicate valid non-integer G command. + // Otherwise, arc IJK incremental mode is default. G91.1 does nothing. + } + break; + case 93: case 94: + word_bit = MODAL_GROUP_G5; + gc_block.modal.feed_rate = 94 - int_value; + break; + case 20: case 21: + word_bit = MODAL_GROUP_G6; + gc_block.modal.units = 21 - int_value; + break; + case 40: + word_bit = MODAL_GROUP_G7; + // NOTE: Not required since cutter radius compensation is always disabled. Only here + // to support G40 commands that often appear in g-code program headers to setup defaults. + // gc_block.modal.cutter_comp = CUTTER_COMP_DISABLE; // G40 + break; + case 43: case 49: + word_bit = MODAL_GROUP_G8; + // NOTE: The NIST g-code standard vaguely states that when a tool length offset is changed, + // there cannot be any axis motion or coordinate offsets updated. Meaning G43, G43.1, and G49 + // all are explicit axis commands, regardless if they require axis words or not. + if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict] } + axis_command = AXIS_COMMAND_TOOL_LENGTH_OFFSET; + if (int_value == 49) { // G49 + gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_CANCEL; + } else if (mantissa == 10) { // G43.1 + gc_block.modal.tool_length = TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC; + } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported G43.x command] + mantissa = 0; // Set to zero to indicate valid non-integer G command. + break; + case 54: case 55: case 56: case 57: case 58: case 59: + // NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.) + word_bit = MODAL_GROUP_G12; + gc_block.modal.coord_select = int_value - 54; // Shift to array indexing. + break; + case 61: + word_bit = MODAL_GROUP_G13; + if (mantissa != 0) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G61.1 not supported] + // gc_block.modal.control = CONTROL_MODE_EXACT_PATH; // G61 + break; + default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G command] + } + if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [Unsupported or invalid Gxx.x command] + // Check for more than one command per modal group violations in the current block + // NOTE: Variable 'word_bit' is always assigned, if the command is valid. + if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); } + command_words |= bit(word_bit); + break; + + case 'M': + + // Determine 'M' command and its modal group + if (mantissa > 0) { FAIL(STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER); } // [No Mxx.x commands] + switch(int_value) { + case 0: case 1: case 2: case 30: + word_bit = MODAL_GROUP_M4; + switch(int_value) { + case 0: gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause + case 1: break; // Optional stop not supported. Ignore. + default: gc_block.modal.program_flow = int_value; // Program end and reset + } + break; + case 3: case 4: case 5: + word_bit = MODAL_GROUP_M7; + switch(int_value) { + case 3: gc_block.modal.spindle = SPINDLE_ENABLE_CW; break; + case 4: gc_block.modal.spindle = SPINDLE_ENABLE_CCW; break; + case 5: gc_block.modal.spindle = SPINDLE_DISABLE; break; + } + break; + #ifdef ENABLE_M7 + case 7: case 8: case 9: + #else + case 8: case 9: + #endif + word_bit = MODAL_GROUP_M8; + switch(int_value) { + #ifdef ENABLE_M7 + case 7: gc_block.modal.coolant |= COOLANT_MIST_ENABLE; break; + #endif + case 8: gc_block.modal.coolant |= COOLANT_FLOOD_ENABLE; break; + case 9: gc_block.modal.coolant = COOLANT_DISABLE; break; // M9 disables both M7 and M8. + } + break; + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + case 56: + word_bit = MODAL_GROUP_M9; + gc_block.modal.override = OVERRIDE_PARKING_MOTION; + break; + #endif + default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported M command] + } + + // Check for more than one command per modal group violations in the current block + // NOTE: Variable 'word_bit' is always assigned, if the command is valid. + if ( bit_istrue(command_words,bit(word_bit)) ) { FAIL(STATUS_GCODE_MODAL_GROUP_VIOLATION); } + command_words |= bit(word_bit); + break; + + // NOTE: All remaining letters assign values. + default: + + /* Non-Command Words: This initial parsing phase only checks for repeats of the remaining + legal g-code words and stores their value. Error-checking is performed later since some + words (I,J,K,L,P,R) have multiple connotations and/or depend on the issued commands. */ + switch(letter){ + // case 'A': // Not supported + // case 'B': // Not supported + // case 'C': // Not supported + // case 'D': // Not supported + case 'F': word_bit = WORD_F; gc_block.values.f = value; break; + // case 'H': // Not supported + case 'I': word_bit = WORD_I; gc_block.values.ijk[X_AXIS] = value; ijk_words |= (1< MAX_TOOL_NUMBER) { FAIL(STATUS_GCODE_MAX_VALUE_EXCEEDED); } + gc_block.values.t = int_value; + break; + case 'X': word_bit = WORD_X; gc_block.values.xyz[X_AXIS] = value; axis_words |= (1< MAX_LINE_NUMBER) { FAIL(STATUS_GCODE_INVALID_LINE_NUMBER); } // [Exceeds max line number] + } + // bit_false(value_words,bit(WORD_N)); // NOTE: Single-meaning value word. Set at end of error-checking. + + // Track for unused words at the end of error-checking. + // NOTE: Single-meaning value words are removed all at once at the end of error-checking, because + // they are always used when present. This was done to save a few bytes of flash. For clarity, the + // single-meaning value words may be removed as they are used. Also, axis words are treated in the + // same way. If there is an explicit/implicit axis command, XYZ words are always used and are + // are removed at the end of error-checking. + + // [1. Comments ]: MSG's NOT SUPPORTED. Comment handling performed by protocol. + + // [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate + // is not defined after switching to G94 from G93. + // NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word. + if (gc_parser_flags & GC_PARSER_JOG_MOTION) { + if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } + if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; } + } else { + if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93 + // NOTE: G38 can also operate in inverse time, but is undefined as an error. Missing F word check added here. + if (axis_command == AXIS_COMMAND_MOTION_MODE) { + if ((gc_block.modal.motion != MOTION_MODE_NONE) && (gc_block.modal.motion != MOTION_MODE_SEEK)) { + if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [F word missing] + } + } + // NOTE: It seems redundant to check for an F word to be passed after switching from G94 to G93. We would + // accomplish the exact same thing if the feed rate value is always reset to zero and undefined after each + // inverse time block, since the commands that use this value already perform undefined checks. This would + // also allow other commands, following this switch, to execute and not error out needlessly. This code is + // combined with the above feed rate mode and the below set feed rate error-checking. + + // [3. Set feed rate ]: F is negative (done.) + // - In inverse time mode: Always implicitly zero the feed rate value before and after block completion. + // NOTE: If in G93 mode or switched into it from G94, just keep F value as initialized zero or passed F word + // value in the block. If no F word is passed with a motion command that requires a feed rate, this will error + // out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires + // a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined. + } else { // = G94 + // - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value. + if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94 + if (bit_istrue(value_words,bit(WORD_F))) { + if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; } + } else { + gc_block.values.f = gc_state.feed_rate; // Push last state feed rate + } + } // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value. + } + } + // bit_false(value_words,bit(WORD_F)); // NOTE: Single-meaning value word. Set at end of error-checking. + + // [4. Set spindle speed ]: S is negative (done.) + if (bit_isfalse(value_words,bit(WORD_S))) { gc_block.values.s = gc_state.spindle_speed; } + // bit_false(value_words,bit(WORD_S)); // NOTE: Single-meaning value word. Set at end of error-checking. + + // [5. Select tool ]: NOT SUPPORTED. Only tracks value. T is negative (done.) Not an integer. Greater than max tool value. + // bit_false(value_words,bit(WORD_T)); // NOTE: Single-meaning value word. Set at end of error-checking. + + // [6. Change tool ]: N/A + // [7. Spindle control ]: N/A + // [8. Coolant control ]: N/A + // [9. Override control ]: Not supported except for a Grbl-only parking motion override control. + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if (bit_istrue(command_words,bit(MODAL_GROUP_M9))) { // Already set as enabled in parser. + if (bit_istrue(value_words,bit(WORD_P))) { + if (gc_block.values.p == 0.0) { gc_block.modal.override = OVERRIDE_DISABLED; } + bit_false(value_words,bit(WORD_P)); + } + } + #endif + + // [10. Dwell ]: P value missing. P is negative (done.) NOTE: See below. + if (gc_block.non_modal_command == NON_MODAL_DWELL) { + if (bit_isfalse(value_words,bit(WORD_P))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P word missing] + bit_false(value_words,bit(WORD_P)); + } + + // [11. Set active plane ]: N/A + switch (gc_block.modal.plane_select) { + case PLANE_SELECT_XY: + axis_0 = X_AXIS; + axis_1 = Y_AXIS; + axis_linear = Z_AXIS; + break; + case PLANE_SELECT_ZX: + axis_0 = Z_AXIS; + axis_1 = X_AXIS; + axis_linear = Y_AXIS; + break; + default: // case PLANE_SELECT_YZ: + axis_0 = Y_AXIS; + axis_1 = Z_AXIS; + axis_linear = X_AXIS; + } + + // [12. Set length units ]: N/A + // Pre-convert XYZ coordinate values to millimeters, if applicable. + uint8_t idx; + if (gc_block.modal.units == UNITS_MODE_INCHES) { + for (idx=0; idx N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys] + if (gc_state.modal.coord_select != gc_block.modal.coord_select) { + if (!(settings_read_coord_data(gc_block.modal.coord_select,block_coord_system))) { FAIL(STATUS_SETTING_READ_FAIL); } + } + } + + // [16. Set path control mode ]: N/A. Only G61. G61.1 and G64 NOT SUPPORTED. + // [17. Set distance mode ]: N/A. Only G91.1. G90.1 NOT SUPPORTED. + // [18. Set retract mode ]: NOT SUPPORTED. + + // [19. Remaining non-modal actions ]: Check go to predefined position, set G10, or set axis offsets. + // NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these + // commands all treat axis words differently. G10 as absolute offsets or computes current position as + // the axis value, G92 similarly to G10 L20, and G28/30 as an intermediate target position that observes + // all the current coordinate system and G92 offsets. + switch (gc_block.non_modal_command) { + case NON_MODAL_SET_COORDINATE_DATA: + // [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.) + // [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing. + // [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing. + if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS) }; // [No axis words] + if (bit_isfalse(value_words,((1< N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys] + if (gc_block.values.l != 20) { + if (gc_block.values.l == 2) { + if (bit_istrue(value_words,bit(WORD_R))) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G10 L2 R not supported] + } else { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [Unsupported L] + } + bit_false(value_words,(bit(WORD_L)|bit(WORD_P))); + + // Determine coordinate system to change and try to load from EEPROM. + if (coord_select > 0) { coord_select--; } // Adjust P1-P6 index to EEPROM coordinate data indexing. + else { coord_select = gc_block.modal.coord_select; } // Index P0 as the active coordinate system + + // NOTE: Store parameter data in IJK values. By rule, they are not in use with this command. + if (!settings_read_coord_data(coord_select,gc_block.values.ijk)) { FAIL(STATUS_SETTING_READ_FAIL); } // [EEPROM read fail] + + // Pre-calculate the coordinate data changes. + for (idx=0; idx WCS = MPos - G92 - TLO - WPos + gc_block.values.ijk[idx] = gc_state.position[idx]-gc_state.coord_offset[idx]-gc_block.values.xyz[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.ijk[idx] -= gc_state.tool_length_offset; } + } else { + // L2: Update coordinate system axis to programmed value. + gc_block.values.ijk[idx] = gc_block.values.xyz[idx]; + } + } // Else, keep current stored value. + } + break; + case NON_MODAL_SET_COORDINATE_OFFSET: + // [G92 Errors]: No axis words. + if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words] + + // Update axes defined only in block. Offsets current system to defined value. Does not update when + // active coordinate system is selected, but is still active unless G92.1 disables it. + for (idx=0; idx G92 = MPos - WCS - TLO - WPos + gc_block.values.xyz[idx] = gc_state.position[idx]-block_coord_system[idx]-gc_block.values.xyz[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) { gc_block.values.xyz[idx] -= gc_state.tool_length_offset; } + } else { + gc_block.values.xyz[idx] = gc_state.coord_offset[idx]; + } + } + break; + + default: + + // At this point, the rest of the explicit axis commands treat the axis values as the traditional + // target position with the coordinate system offsets, G92 offsets, absolute override, and distance + // modes applied. This includes the motion mode commands. We can now pre-compute the target position. + // NOTE: Tool offsets may be appended to these conversions when/if this feature is added. + if (axis_command != AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // TLO block any axis command. + if (axis_words) { + for (idx=0; idx C -----------------+--------------- T <- [x,y] + | <------ d/2 ---->| + + C - Current position + T - Target position + O - center of circle that pass through both C and T + d - distance from C to T + r - designated radius + h - distance from center of CT to O + + Expanding the equations: + + d -> sqrt(x^2 + y^2) + h -> sqrt(4 * r^2 - x^2 - y^2)/2 + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2 + + Which can be written: + + i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2 + + Which we for size and speed reasons optimize to: + + h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2) + i = (x - (y * h_x2_div_d))/2 + j = (y + (x * h_x2_div_d))/2 + */ + + // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller + // than d. If so, the sqrt of a negative number is complex and error out. + float h_x2_div_d = 4.0 * gc_block.values.r*gc_block.values.r - x*x - y*y; + + if (h_x2_div_d < 0) { FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); } // [Arc radius error] + + // Finish computing h_x2_div_d. + h_x2_div_d = -sqrt(h_x2_div_d)/hypot_f(x,y); // == -(h * 2 / d) + // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below) + if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; } + + /* The counter clockwise circle lies to the left of the target direction. When offset is positive, + the left hand circle will be generated - when it is negative the right hand circle is generated. + + T <-- Target position + + ^ + Clockwise circles with this center | Clockwise circles with this center will have + will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing! + \ | / + center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative + | + | + + C <-- Current position + */ + // Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!), + // even though it is advised against ever generating such circles in a single line of g-code. By + // inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of + // travel and thus we get the unadvisably long arcs as prescribed. + if (gc_block.values.r < 0) { + h_x2_div_d = -h_x2_div_d; + gc_block.values.r = -gc_block.values.r; // Finished with r. Set to positive for mc_arc + } + // Complete the operation by calculating the actual center of the arc + gc_block.values.ijk[axis_0] = 0.5*(x-(y*h_x2_div_d)); + gc_block.values.ijk[axis_1] = 0.5*(y+(x*h_x2_div_d)); + + } else { // Arc Center Format Offset Mode + if (!(ijk_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_OFFSETS_IN_PLANE); } // [No offsets in plane] + bit_false(value_words,(bit(WORD_I)|bit(WORD_J)|bit(WORD_K))); + + // Convert IJK values to proper units. + if (gc_block.modal.units == UNITS_MODE_INCHES) { + for (idx=0; idx 0.005) { + if (delta_r > 0.5) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.5mm + if (delta_r > (0.001*gc_block.values.r)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Arc definition error] > 0.005mm AND 0.1% radius + } + } + break; + case MOTION_MODE_PROBE_TOWARD_NO_ERROR: case MOTION_MODE_PROBE_AWAY_NO_ERROR: + gc_parser_flags |= GC_PARSER_PROBE_IS_NO_ERROR; // No break intentional. + case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_AWAY: + if ((gc_block.modal.motion == MOTION_MODE_PROBE_AWAY) || + (gc_block.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) { gc_parser_flags |= GC_PARSER_PROBE_IS_AWAY; } + // [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate + // is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning + // an error, it issues an alarm to prevent further motion to the probe. It's also done there to + // allow the planner buffer to empty and move off the probe trigger before another probing cycle. + if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words] + if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target] + break; + } + } + } + + // [21. Program flow ]: No error checks required. + + // [0. Non-specific error-checks]: Complete unused value words check, i.e. IJK used when in arc + // radius mode, or axis words that aren't used in the block. + if (gc_parser_flags & GC_PARSER_JOG_MOTION) { + // Jogging only uses the F feed rate and XYZ value words. N is valid, but S and T are invalid. + bit_false(value_words,(bit(WORD_N)|bit(WORD_F))); + } else { + bit_false(value_words,(bit(WORD_N)|bit(WORD_F)|bit(WORD_S)|bit(WORD_T))); // Remove single-meaning value words. + } + if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words. + if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words] + + /* ------------------------------------------------------------------------------------- + STEP 4: EXECUTE!! + Assumes that all error-checking has been completed and no failure modes exist. We just + need to update the state and execute the block according to the order-of-execution. + */ + + // Initialize planner data struct for motion blocks. + plan_line_data_t plan_data; + plan_line_data_t *pl_data = &plan_data; + memset(pl_data,0,sizeof(plan_line_data_t)); // Zero pl_data struct + + // Intercept jog commands and complete error checking for valid jog commands and execute. + // NOTE: G-code parser state is not updated, except the position to ensure sequential jog + // targets are computed correctly. The final parser position after a jog is updated in + // protocol_execute_realtime() when jogging completes or is canceled. + if (gc_parser_flags & GC_PARSER_JOG_MOTION) { + // Only distance and unit modal commands and G53 absolute override command are allowed. + // NOTE: Feed rate word and axis word checks have already been performed in STEP 3. + if (command_words & ~(bit(MODAL_GROUP_G3) | bit(MODAL_GROUP_G6) | bit(MODAL_GROUP_G0)) ) { FAIL(STATUS_INVALID_JOG_COMMAND) }; + if (!(gc_block.non_modal_command == NON_MODAL_ABSOLUTE_OVERRIDE || gc_block.non_modal_command == NON_MODAL_NO_ACTION)) { FAIL(STATUS_INVALID_JOG_COMMAND); } + + // Initialize planner data to current spindle and coolant modal state. + pl_data->spindle_speed = gc_state.spindle_speed; + plan_data.condition = (gc_state.modal.spindle | gc_state.modal.coolant); + + uint8_t status = jog_execute(&plan_data, &gc_block); + if (status == STATUS_OK) { memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); } + return(status); + } + + // If in laser mode, setup laser power based on current and past parser conditions. + if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { + if ( !((gc_block.modal.motion == MOTION_MODE_LINEAR) || (gc_block.modal.motion == MOTION_MODE_CW_ARC) + || (gc_block.modal.motion == MOTION_MODE_CCW_ARC)) ) { + gc_parser_flags |= GC_PARSER_LASER_DISABLE; + } + + // Any motion mode with axis words is allowed to be passed from a spindle speed update. + // NOTE: G1 and G0 without axis words sets axis_command to none. G28/30 are intentionally omitted. + // TODO: Check sync conditions for M3 enabled motions that don't enter the planner. (zero length). + if (axis_words && (axis_command == AXIS_COMMAND_MOTION_MODE)) { + gc_parser_flags |= GC_PARSER_LASER_ISMOTION; + } else { + // M3 constant power laser requires planner syncs to update the laser when changing between + // a G1/2/3 motion mode state and vice versa when there is no motion in the line. + if (gc_state.modal.spindle == SPINDLE_ENABLE_CW) { + if ((gc_state.modal.motion == MOTION_MODE_LINEAR) || (gc_state.modal.motion == MOTION_MODE_CW_ARC) + || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) { + if (bit_istrue(gc_parser_flags,GC_PARSER_LASER_DISABLE)) { + gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode. + } + } else { + // When changing to a G1 motion mode without axis words from a non-G1/2/3 motion mode. + if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_DISABLE)) { + gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; + } + } + } + } + } + + // [0. Non-specific/common error-checks and miscellaneous setup]: + // NOTE: If no line number is present, the value is zero. + gc_state.line_number = gc_block.values.n; + #ifdef USE_LINE_NUMBERS + pl_data->line_number = gc_state.line_number; // Record data for planner use. + #endif + + // [1. Comments feedback ]: NOT SUPPORTED + + // [2. Set feed rate mode ]: + gc_state.modal.feed_rate = gc_block.modal.feed_rate; + if (gc_state.modal.feed_rate) { pl_data->condition |= PL_COND_FLAG_INVERSE_TIME; } // Set condition flag for planner use. + + // [3. Set feed rate ]: + gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking. + pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use. + + // [4. Set spindle speed ]: + if ((gc_state.spindle_speed != gc_block.values.s) || bit_istrue(gc_parser_flags,GC_PARSER_LASER_FORCE_SYNC)) { + if (gc_state.modal.spindle != SPINDLE_DISABLE) { + #ifdef VARIABLE_SPINDLE + if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_ISMOTION)) { + if (bit_istrue(gc_parser_flags,GC_PARSER_LASER_DISABLE)) { + spindle_sync(gc_state.modal.spindle, 0.0); + } else { spindle_sync(gc_state.modal.spindle, gc_block.values.s); } + } + #else + spindle_sync(gc_state.modal.spindle, 0.0); + #endif + } + gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state. + } + // NOTE: Pass zero spindle speed for all restricted laser motions. + if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_DISABLE)) { + pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use. + } // else { pl_data->spindle_speed = 0.0; } // Initialized as zero already. + + // [5. Select tool ]: NOT SUPPORTED. Only tracks tool value. + gc_state.tool = gc_block.values.t; + + // [6. Change tool ]: NOT SUPPORTED + + // [7. Spindle control ]: + if (gc_state.modal.spindle != gc_block.modal.spindle) { + // Update spindle control and apply spindle speed when enabling it in this block. + // NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data, + // rather than gc_state, is used to manage laser state for non-laser motions. + spindle_sync(gc_block.modal.spindle, pl_data->spindle_speed); + gc_state.modal.spindle = gc_block.modal.spindle; + } + pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use. + + // [8. Coolant control ]: + if (gc_state.modal.coolant != gc_block.modal.coolant) { + // NOTE: Coolant M-codes are modal. Only one command per line is allowed. But, multiple states + // can exist at the same time, while coolant disable clears all states. + coolant_sync(gc_block.modal.coolant); + gc_state.modal.coolant = gc_block.modal.coolant; + } + pl_data->condition |= gc_state.modal.coolant; // Set condition flag for planner use. + + // [9. Override control ]: NOT SUPPORTED. Always enabled. Except for a Grbl-only parking control. + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if (gc_state.modal.override != gc_block.modal.override) { + gc_state.modal.override = gc_block.modal.override; + mc_override_ctrl_update(gc_state.modal.override); + } + #endif + + // [10. Dwell ]: + if (gc_block.non_modal_command == NON_MODAL_DWELL) { mc_dwell(gc_block.values.p); } + + // [11. Set active plane ]: + gc_state.modal.plane_select = gc_block.modal.plane_select; + + // [12. Set length units ]: + gc_state.modal.units = gc_block.modal.units; + + // [13. Cutter radius compensation ]: G41/42 NOT SUPPORTED + // gc_state.modal.cutter_comp = gc_block.modal.cutter_comp; // NOTE: Not needed since always disabled. + + // [14. Cutter length compensation ]: G43.1 and G49 supported. G43 NOT SUPPORTED. + // NOTE: If G43 were supported, its operation wouldn't be any different from G43.1 in terms + // of execution. The error-checking step would simply load the offset value into the correct + // axis of the block XYZ value array. + if (axis_command == AXIS_COMMAND_TOOL_LENGTH_OFFSET ) { // Indicates a change. + gc_state.modal.tool_length = gc_block.modal.tool_length; + if (gc_state.modal.tool_length == TOOL_LENGTH_OFFSET_CANCEL) { // G49 + gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] = 0.0; + } // else G43.1 + if ( gc_state.tool_length_offset != gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS] ) { + gc_state.tool_length_offset = gc_block.values.xyz[TOOL_LENGTH_OFFSET_AXIS]; + system_flag_wco_change(); + } + } + + // [15. Coordinate system selection ]: + if (gc_state.modal.coord_select != gc_block.modal.coord_select) { + gc_state.modal.coord_select = gc_block.modal.coord_select; + memcpy(gc_state.coord_system,block_coord_system,N_AXIS*sizeof(float)); + system_flag_wco_change(); + } + + // [16. Set path control mode ]: G61.1/G64 NOT SUPPORTED + // gc_state.modal.control = gc_block.modal.control; // NOTE: Always default. + + // [17. Set distance mode ]: + gc_state.modal.distance = gc_block.modal.distance; + + // [18. Set retract mode ]: NOT SUPPORTED + + // [19. Go to predefined position, Set G10, or Set axis offsets ]: + switch(gc_block.non_modal_command) { + case NON_MODAL_SET_COORDINATE_DATA: + settings_write_coord_data(coord_select,gc_block.values.ijk); + // Update system coordinate system if currently active. + if (gc_state.modal.coord_select == coord_select) { + memcpy(gc_state.coord_system,gc_block.values.ijk,N_AXIS*sizeof(float)); + system_flag_wco_change(); + } + break; + case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1: + // Move to intermediate position before going home. Obeys current coordinate system and offsets + // and absolute and incremental modes. + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + if (axis_command) { mc_line(gc_block.values.xyz, pl_data); } + mc_line(gc_block.values.ijk, pl_data); + memcpy(gc_state.position, gc_block.values.ijk, N_AXIS*sizeof(float)); + break; + case NON_MODAL_SET_HOME_0: + settings_write_coord_data(SETTING_INDEX_G28,gc_state.position); + break; + case NON_MODAL_SET_HOME_1: + settings_write_coord_data(SETTING_INDEX_G30,gc_state.position); + break; + case NON_MODAL_SET_COORDINATE_OFFSET: + memcpy(gc_state.coord_offset,gc_block.values.xyz,sizeof(gc_block.values.xyz)); + system_flag_wco_change(); + break; + case NON_MODAL_RESET_COORDINATE_OFFSET: + clear_vector(gc_state.coord_offset); // Disable G92 offsets by zeroing offset vector. + system_flag_wco_change(); + break; + } + + + // [20. Motion modes ]: + // NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes. + // Enter motion modes only if there are axis words or a motion mode command word in the block. + gc_state.modal.motion = gc_block.modal.motion; + if (gc_state.modal.motion != MOTION_MODE_NONE) { + if (axis_command == AXIS_COMMAND_MOTION_MODE) { + uint8_t gc_update_pos = GC_UPDATE_POS_TARGET; + if (gc_state.modal.motion == MOTION_MODE_LINEAR) { + mc_line(gc_block.values.xyz, pl_data); + } else if (gc_state.modal.motion == MOTION_MODE_SEEK) { + pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag. + mc_line(gc_block.values.xyz, pl_data); + } else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) { + mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r, + axis_0, axis_1, axis_linear, bit_istrue(gc_parser_flags,GC_PARSER_ARC_IS_CLOCKWISE)); + } else { + // NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So + // upon a successful probing cycle, the machine position and the returned value should be the same. + #ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES + pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE; + #endif + gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags); + } + + // As far as the parser is concerned, the position is now == target. In reality the + // motion control system might still be processing the action and the real tool position + // in any intermediate location. + if (gc_update_pos == GC_UPDATE_POS_TARGET) { + memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[] + } else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) { + gc_sync_position(); // gc_state.position[] = sys_position + } // == GC_UPDATE_POS_NONE + } + } + + // [21. Program flow ]: + // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may + // refill and can only be resumed by the cycle start run-time command. + gc_state.modal.program_flow = gc_block.modal.program_flow; + if (gc_state.modal.program_flow) { + protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on. + if (gc_state.modal.program_flow == PROGRAM_FLOW_PAUSED) { + if (sys.state != STATE_CHECK_MODE) { + system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause. + protocol_execute_realtime(); // Execute suspend. + } + } else { // == PROGRAM_FLOW_COMPLETED + // Upon program complete, only a subset of g-codes reset to certain defaults, according to + // LinuxCNC's program end descriptions and testing. Only modal groups [G-code 1,2,3,5,7,12] + // and [M-code 7,8,9] reset to [G1,G17,G90,G94,G40,G54,M5,M9,M48]. The remaining modal groups + // [G-code 4,6,8,10,13,14,15] and [M-code 4,5,6] and the modal words [F,S,T,H] do not reset. + gc_state.modal.motion = MOTION_MODE_LINEAR; + gc_state.modal.plane_select = PLANE_SELECT_XY; + gc_state.modal.distance = DISTANCE_MODE_ABSOLUTE; + gc_state.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; + // gc_state.modal.cutter_comp = CUTTER_COMP_DISABLE; // Not supported. + gc_state.modal.coord_select = 0; // G54 + gc_state.modal.spindle = SPINDLE_DISABLE; + gc_state.modal.coolant = COOLANT_DISABLE; + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + #ifdef DEACTIVATE_PARKING_UPON_INIT + gc_state.modal.override = OVERRIDE_DISABLED; + #else + gc_state.modal.override = OVERRIDE_PARKING_MOTION; + #endif + #endif + + #ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END + sys.f_override = DEFAULT_FEED_OVERRIDE; + sys.r_override = DEFAULT_RAPID_OVERRIDE; + sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; + #endif + + // Execute coordinate change and spindle/coolant stop. + if (sys.state != STATE_CHECK_MODE) { + if (!(settings_read_coord_data(gc_state.modal.coord_select,gc_state.coord_system))) { FAIL(STATUS_SETTING_READ_FAIL); } + system_flag_wco_change(); // Set to refresh immediately just in case something altered. + spindle_set_state(SPINDLE_DISABLE,0.0); + coolant_set_state(COOLANT_DISABLE); + } + report_feedback_message(MESSAGE_PROGRAM_END); + } + gc_state.modal.program_flow = PROGRAM_FLOW_RUNNING; // Reset program flow. + } + + // TODO: % to denote start of program. + + return(STATUS_OK); +} + + +/* + Not supported: + + - Canned cycles + - Tool radius compensation + - A,B,C-axes + - Evaluation of expressions + - Variables + - Override control (TBD) + - Tool changes + - Switches + + (*) Indicates optional parameter, enabled through config.h and re-compile + group 0 = {G92.2, G92.3} (Non modal: Cancel and re-enable G92 offsets) + group 1 = {G81 - G89} (Motion modes: Canned cycles) + group 4 = {M1} (Optional stop, ignored) + group 6 = {M6} (Tool change) + group 7 = {G41, G42} cutter radius compensation (G40 is supported) + group 8 = {G43} tool length offset (G43.1/G49 are supported) + group 8 = {M7*} enable mist coolant (* Compile-option) + group 9 = {M48, M49, M56*} enable/disable override switches (* Compile-option) + group 10 = {G98, G99} return mode canned cycles + group 13 = {G61.1, G64} path control mode (G61 is supported) +*/ diff --git a/grbl/gcode.h b/grbl/gcode.h new file mode 100644 index 0000000..6cdc61b --- /dev/null +++ b/grbl/gcode.h @@ -0,0 +1,248 @@ +/* + gcode.h - rs274/ngc parser. + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef gcode_h +#define gcode_h + + +// Define modal group internal numbers for checking multiple command violations and tracking the +// type of command that is called in the block. A modal group is a group of g-code commands that are +// mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute +// a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, +// and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc). +// NOTE: Modal group define values must be sequential and starting from zero. +#define MODAL_GROUP_G0 0 // [G4,G10,G28,G28.1,G30,G30.1,G53,G92,G92.1] Non-modal +#define MODAL_GROUP_G1 1 // [G0,G1,G2,G3,G38.2,G38.3,G38.4,G38.5,G80] Motion +#define MODAL_GROUP_G2 2 // [G17,G18,G19] Plane selection +#define MODAL_GROUP_G3 3 // [G90,G91] Distance mode +#define MODAL_GROUP_G4 4 // [G91.1] Arc IJK distance mode +#define MODAL_GROUP_G5 5 // [G93,G94] Feed rate mode +#define MODAL_GROUP_G6 6 // [G20,G21] Units +#define MODAL_GROUP_G7 7 // [G40] Cutter radius compensation mode. G41/42 NOT SUPPORTED. +#define MODAL_GROUP_G8 8 // [G43.1,G49] Tool length offset +#define MODAL_GROUP_G12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection +#define MODAL_GROUP_G13 10 // [G61] Control mode + +#define MODAL_GROUP_M4 11 // [M0,M1,M2,M30] Stopping +#define MODAL_GROUP_M7 12 // [M3,M4,M5] Spindle turning +#define MODAL_GROUP_M8 13 // [M7,M8,M9] Coolant control +#define MODAL_GROUP_M9 14 // [M56] Override control + +// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used +// internally by the parser to know which command to execute. +// NOTE: Some macro values are assigned specific values to make g-code state reporting and parsing +// compile a litte smaller. Necessary due to being completely out of flash on the 328p. Although not +// ideal, just be careful with values that state 'do not alter' and check both report.c and gcode.c +// to see how they are used, if you need to alter them. + +// Modal Group G0: Non-modal actions +#define NON_MODAL_NO_ACTION 0 // (Default: Must be zero) +#define NON_MODAL_DWELL 4 // G4 (Do not alter value) +#define NON_MODAL_SET_COORDINATE_DATA 10 // G10 (Do not alter value) +#define NON_MODAL_GO_HOME_0 28 // G28 (Do not alter value) +#define NON_MODAL_SET_HOME_0 38 // G28.1 (Do not alter value) +#define NON_MODAL_GO_HOME_1 30 // G30 (Do not alter value) +#define NON_MODAL_SET_HOME_1 40 // G30.1 (Do not alter value) +#define NON_MODAL_ABSOLUTE_OVERRIDE 53 // G53 (Do not alter value) +#define NON_MODAL_SET_COORDINATE_OFFSET 92 // G92 (Do not alter value) +#define NON_MODAL_RESET_COORDINATE_OFFSET 102 //G92.1 (Do not alter value) + +// Modal Group G1: Motion modes +#define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero) +#define MOTION_MODE_LINEAR 1 // G1 (Do not alter value) +#define MOTION_MODE_CW_ARC 2 // G2 (Do not alter value) +#define MOTION_MODE_CCW_ARC 3 // G3 (Do not alter value) +#define MOTION_MODE_PROBE_TOWARD 140 // G38.2 (Do not alter value) +#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 141 // G38.3 (Do not alter value) +#define MOTION_MODE_PROBE_AWAY 142 // G38.4 (Do not alter value) +#define MOTION_MODE_PROBE_AWAY_NO_ERROR 143 // G38.5 (Do not alter value) +#define MOTION_MODE_NONE 80 // G80 (Do not alter value) + +// Modal Group G2: Plane select +#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero) +#define PLANE_SELECT_ZX 1 // G18 (Do not alter value) +#define PLANE_SELECT_YZ 2 // G19 (Do not alter value) + +// Modal Group G3: Distance mode +#define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero) +#define DISTANCE_MODE_INCREMENTAL 1 // G91 (Do not alter value) + +// Modal Group G4: Arc IJK distance mode +#define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero) + +// Modal Group M4: Program flow +#define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero) +#define PROGRAM_FLOW_PAUSED 3 // M0 +#define PROGRAM_FLOW_OPTIONAL_STOP 1 // M1 NOTE: Not supported, but valid and ignored. +#define PROGRAM_FLOW_COMPLETED_M2 2 // M2 (Do not alter value) +#define PROGRAM_FLOW_COMPLETED_M30 30 // M30 (Do not alter value) + +// Modal Group G5: Feed rate mode +#define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero) +#define FEED_RATE_MODE_INVERSE_TIME 1 // G93 (Do not alter value) + +// Modal Group G6: Units mode +#define UNITS_MODE_MM 0 // G21 (Default: Must be zero) +#define UNITS_MODE_INCHES 1 // G20 (Do not alter value) + +// Modal Group G7: Cutter radius compensation mode +#define CUTTER_COMP_DISABLE 0 // G40 (Default: Must be zero) + +// Modal Group G13: Control mode +#define CONTROL_MODE_EXACT_PATH 0 // G61 (Default: Must be zero) + +// Modal Group M7: Spindle control +#define SPINDLE_DISABLE 0 // M5 (Default: Must be zero) +#define SPINDLE_ENABLE_CW PL_COND_FLAG_SPINDLE_CW // M3 (NOTE: Uses planner condition bit flag) +#define SPINDLE_ENABLE_CCW PL_COND_FLAG_SPINDLE_CCW // M4 (NOTE: Uses planner condition bit flag) + +// Modal Group M8: Coolant control +#define COOLANT_DISABLE 0 // M9 (Default: Must be zero) +#define COOLANT_FLOOD_ENABLE PL_COND_FLAG_COOLANT_FLOOD // M8 (NOTE: Uses planner condition bit flag) +#define COOLANT_MIST_ENABLE PL_COND_FLAG_COOLANT_MIST // M7 (NOTE: Uses planner condition bit flag) + +// Modal Group G8: Tool length offset +#define TOOL_LENGTH_OFFSET_CANCEL 0 // G49 (Default: Must be zero) +#define TOOL_LENGTH_OFFSET_ENABLE_DYNAMIC 1 // G43.1 + +// Modal Group M9: Override control +#ifdef DEACTIVATE_PARKING_UPON_INIT + #define OVERRIDE_DISABLED 0 // (Default: Must be zero) + #define OVERRIDE_PARKING_MOTION 1 // M56 +#else + #define OVERRIDE_PARKING_MOTION 0 // M56 (Default: Must be zero) + #define OVERRIDE_DISABLED 1 // Parking disabled. +#endif + +// Modal Group G12: Active work coordinate system +// N/A: Stores coordinate system value (54-59) to change to. + +// Define parameter word mapping. +#define WORD_F 0 +#define WORD_I 1 +#define WORD_J 2 +#define WORD_K 3 +#define WORD_L 4 +#define WORD_N 5 +#define WORD_P 6 +#define WORD_R 7 +#define WORD_S 8 +#define WORD_T 9 +#define WORD_X 10 +#define WORD_Y 11 +#define WORD_Z 12 + +// Define g-code parser position updating flags +#define GC_UPDATE_POS_TARGET 0 // Must be zero +#define GC_UPDATE_POS_SYSTEM 1 +#define GC_UPDATE_POS_NONE 2 + +// Define probe cycle exit states and assign proper position updating. +#define GC_PROBE_FOUND GC_UPDATE_POS_SYSTEM +#define GC_PROBE_ABORT GC_UPDATE_POS_NONE +#define GC_PROBE_FAIL_INIT GC_UPDATE_POS_NONE +#define GC_PROBE_FAIL_END GC_UPDATE_POS_TARGET +#ifdef SET_CHECK_MODE_PROBE_TO_START + #define GC_PROBE_CHECK_MODE GC_UPDATE_POS_NONE +#else + #define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET +#endif + +// Define gcode parser flags for handling special cases. +#define GC_PARSER_NONE 0 // Must be zero. +#define GC_PARSER_JOG_MOTION bit(0) +#define GC_PARSER_CHECK_MANTISSA bit(1) +#define GC_PARSER_ARC_IS_CLOCKWISE bit(2) +#define GC_PARSER_PROBE_IS_AWAY bit(3) +#define GC_PARSER_PROBE_IS_NO_ERROR bit(4) +#define GC_PARSER_LASER_FORCE_SYNC bit(5) +#define GC_PARSER_LASER_DISABLE bit(6) +#define GC_PARSER_LASER_ISMOTION bit(7) + + +// NOTE: When this struct is zeroed, the above defines set the defaults for the system. +typedef struct { + uint8_t motion; // {G0,G1,G2,G3,G38.2,G80} + uint8_t feed_rate; // {G93,G94} + uint8_t units; // {G20,G21} + uint8_t distance; // {G90,G91} + // uint8_t distance_arc; // {G91.1} NOTE: Don't track. Only default supported. + uint8_t plane_select; // {G17,G18,G19} + // uint8_t cutter_comp; // {G40} NOTE: Don't track. Only default supported. + uint8_t tool_length; // {G43.1,G49} + uint8_t coord_select; // {G54,G55,G56,G57,G58,G59} + // uint8_t control; // {G61} NOTE: Don't track. Only default supported. + uint8_t program_flow; // {M0,M1,M2,M30} + uint8_t coolant; // {M7,M8,M9} + uint8_t spindle; // {M3,M4,M5} + uint8_t override; // {M56} +} gc_modal_t; + +typedef struct { + float f; // Feed + float ijk[3]; // I,J,K Axis arc offsets + uint8_t l; // G10 or canned cycles parameters + int32_t n; // Line number + float p; // G10 or dwell parameters + // float q; // G82 peck drilling + float r; // Arc radius + float s; // Spindle speed + uint8_t t; // Tool selection + float xyz[3]; // X,Y,Z Translational axes +} gc_values_t; + + +typedef struct { + gc_modal_t modal; + + float spindle_speed; // RPM + float feed_rate; // Millimeters/min + uint8_t tool; // Tracks tool number. NOT USED. + int32_t line_number; // Last line number sent + + float position[N_AXIS]; // Where the interpreter considers the tool to be at this point in the code + + float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine + // position in mm. Loaded from EEPROM when called. + float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to + // machine zero in mm. Non-persistent. Cleared upon reset and boot. + float tool_length_offset; // Tracks tool length offset value when enabled. +} parser_state_t; +extern parser_state_t gc_state; + + +typedef struct { + uint8_t non_modal_command; + gc_modal_t modal; + gc_values_t values; +} parser_block_t; + + +// Initialize the parser +void gc_init(); + +// Execute one block of rs275/ngc/g-code +uint8_t gc_execute_line(char *line); + +// Set g-code parser position. Input in steps. +void gc_sync_position(); + +#endif diff --git a/grbl/grbl.h b/grbl/grbl.h new file mode 100644 index 0000000..dd8e781 --- /dev/null +++ b/grbl/grbl.h @@ -0,0 +1,140 @@ +/* + grbl.h - main Grbl include file + Part of Grbl + + Copyright (c) 2015-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef grbl_h +#define grbl_h + +// Grbl versioning system +#define GRBL_VERSION "1.1h" +#define GRBL_VERSION_BUILD "20190830" + +// Define standard libraries used by Grbl. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Define the Grbl system include files. NOTE: Do not alter organization. +#include "config.h" +#include "nuts_bolts.h" +#include "settings.h" +#include "system.h" +#include "defaults.h" +#include "cpu_map.h" +#include "planner.h" +#include "coolant_control.h" +#include "eeprom.h" +#include "gcode.h" +#include "limits.h" +#include "motion_control.h" +#include "planner.h" +#include "print.h" +#include "probe.h" +#include "protocol.h" +#include "report.h" +#include "serial.h" +#include "spindle_control.h" +#include "stepper.h" +#include "jog.h" + +// --------------------------------------------------------------------------------------- +// COMPILE-TIME ERROR CHECKING OF DEFINE VALUES: + +#ifndef HOMING_CYCLE_0 + #error "Required HOMING_CYCLE_0 not defined." +#endif + +#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(VARIABLE_SPINDLE) + #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with VARIABLE_SPINDLE enabled" +#endif + +#if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(CPU_MAP_ATMEGA328P) + #error "USE_SPINDLE_DIR_AS_ENABLE_PIN may only be used with a 328p processor" +#endif + +#if !defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && defined(SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED) + #error "SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED may only be used with USE_SPINDLE_DIR_AS_ENABLE_PIN enabled" +#endif + +#if defined(PARKING_ENABLE) + #if defined(HOMING_FORCE_SET_ORIGIN) + #error "HOMING_FORCE_SET_ORIGIN is not supported with PARKING_ENABLE at this time." + #endif +#endif + +#if defined(ENABLE_PARKING_OVERRIDE_CONTROL) + #if !defined(PARKING_ENABLE) + #error "ENABLE_PARKING_OVERRIDE_CONTROL must be enabled with PARKING_ENABLE." + #endif +#endif + +#if defined(SPINDLE_PWM_MIN_VALUE) + #if !(SPINDLE_PWM_MIN_VALUE > 0) + #error "SPINDLE_PWM_MIN_VALUE must be greater than zero." + #endif +#endif + +#if (REPORT_WCO_REFRESH_BUSY_COUNT < REPORT_WCO_REFRESH_IDLE_COUNT) + #error "WCO busy refresh is less than idle refresh." +#endif +#if (REPORT_OVR_REFRESH_BUSY_COUNT < REPORT_OVR_REFRESH_IDLE_COUNT) + #error "Override busy refresh is less than idle refresh." +#endif +#if (REPORT_WCO_REFRESH_IDLE_COUNT < 2) + #error "WCO refresh must be greater than one." +#endif +#if (REPORT_OVR_REFRESH_IDLE_COUNT < 1) + #error "Override refresh must be greater than zero." +#endif + +#if defined(ENABLE_DUAL_AXIS) + #if !((DUAL_AXIS_SELECT == X_AXIS) || (DUAL_AXIS_SELECT == Y_AXIS)) + #error "Dual axis currently supports X or Y axes only." + #endif + #if defined(DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE) && defined(VARIABLE_SPINDLE) + #error "VARIABLE_SPINDLE not supported with DUAL_AXIS_CNC_SHIELD_CLONE." + #endif + #if defined(DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE) && defined(DUAL_AXIS_CONFIG_PROTONEER_V3_51) + #error "More than one dual axis configuration found. Select one." + #endif + #if !defined(DUAL_AXIS_CONFIG_CNC_SHIELD_CLONE) && !defined(DUAL_AXIS_CONFIG_PROTONEER_V3_51) + #error "No supported dual axis configuration found. Select one." + #endif + #if defined(COREXY) + #error "CORE XY not supported with dual axis feature." + #endif + #if defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) + #error "USE_SPINDLE_DIR_AS_ENABLE_PIN not supported with dual axis feature." + #endif + #if defined(ENABLE_M7) + #error "ENABLE_M7 not supported with dual axis feature." + #endif +#endif + +// --------------------------------------------------------------------------------------- + +#endif diff --git a/grbl/jog.c b/grbl/jog.c new file mode 100644 index 0000000..553af77 --- /dev/null +++ b/grbl/jog.c @@ -0,0 +1,50 @@ +/* + jog.h - Jogging methods + Part of Grbl + + Copyright (c) 2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. +uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block) +{ + // Initialize planner data struct for jogging motions. + // NOTE: Spindle and coolant are allowed to fully function with overrides during a jog. + pl_data->feed_rate = gc_block->values.f; + pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE; + #ifdef USE_LINE_NUMBERS + pl_data->line_number = gc_block->values.n; + #endif + + if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { + if (system_check_travel_limits(gc_block->values.xyz)) { return(STATUS_TRAVEL_EXCEEDED); } + } + + // Valid jog command. Plan, set state, and execute. + mc_line(gc_block->values.xyz,pl_data); + if (sys.state == STATE_IDLE) { + if (plan_get_current_block() != NULL) { // Check if there is a block to execute. + sys.state = STATE_JOG; + st_prep_buffer(); + st_wake_up(); // NOTE: Manual start. No state machine required. + } + } + + return(STATUS_OK); +} diff --git a/grbl/jog.h b/grbl/jog.h new file mode 100644 index 0000000..c726246 --- /dev/null +++ b/grbl/jog.h @@ -0,0 +1,32 @@ +/* + jog.h - Jogging methods + Part of Grbl + + Copyright (c) 2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef jog_h +#define jog_h + +#include "gcode.h" + +// System motion line numbers must be zero. +#define JOG_LINE_NUMBER 0 + +// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog. +uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block); + +#endif diff --git a/grbl/limits.c b/grbl/limits.c new file mode 100644 index 0000000..1348c14 --- /dev/null +++ b/grbl/limits.c @@ -0,0 +1,430 @@ +/* + limits.c - code pertaining to limit-switches and performing the homing cycle + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +// Homing axis search distance multiplier. Computed by this value times the cycle travel. +#ifndef HOMING_AXIS_SEARCH_SCALAR + #define HOMING_AXIS_SEARCH_SCALAR 1.5 // Must be > 1 to ensure limit switch will be engaged. +#endif +#ifndef HOMING_AXIS_LOCATE_SCALAR + #define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared. +#endif + +#ifdef ENABLE_DUAL_AXIS + // Flags for dual axis async limit trigger check. + #define DUAL_AXIS_CHECK_DISABLE 0 // Must be zero + #define DUAL_AXIS_CHECK_ENABLE bit(0) + #define DUAL_AXIS_CHECK_TRIGGER_1 bit(1) + #define DUAL_AXIS_CHECK_TRIGGER_2 bit(2) +#endif + +void limits_init() +{ + LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins + + #ifdef DISABLE_LIMIT_PIN_PULL_UP + LIMIT_PORT &= ~(LIMIT_MASK); // Normal low operation. Requires external pull-down. + #else + LIMIT_PORT |= (LIMIT_MASK); // Enable internal pull-up resistors. Normal high operation. + #endif + + if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { + LIMIT_PCMSK |= LIMIT_MASK; // Enable specific pins of the Pin Change Interrupt + PCICR |= (1 << LIMIT_INT); // Enable Pin Change Interrupt + } else { + limits_disable(); + } + + #ifdef ENABLE_SOFTWARE_DEBOUNCE + MCUSR &= ~(1<condition = (PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE); + #ifdef USE_LINE_NUMBERS + pl_data->line_number = HOMING_CYCLE_LINE_NUMBER; + #endif + + // Initialize variables used for homing computations. + uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1); + uint8_t step_pin[N_AXIS]; + #ifdef ENABLE_DUAL_AXIS + uint8_t step_pin_dual; + uint8_t dual_axis_async_check; + int32_t dual_trigger_position; + #if (DUAL_AXIS_SELECT == X_AXIS) + float fail_distance = (-DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT/100.0)*settings.max_travel[Y_AXIS]; + #else + float fail_distance = (-DUAL_AXIS_HOMING_FAIL_AXIS_LENGTH_PERCENT/100.0)*settings.max_travel[X_AXIS]; + #endif + fail_distance = min(fail_distance, DUAL_AXIS_HOMING_FAIL_DISTANCE_MAX); + fail_distance = max(fail_distance, DUAL_AXIS_HOMING_FAIL_DISTANCE_MIN); + int32_t dual_fail_distance = trunc(fail_distance*settings.steps_per_mm[DUAL_AXIS_SELECT]); + // int32_t dual_fail_distance = trunc((DUAL_AXIS_HOMING_TRIGGER_FAIL_DISTANCE)*settings.steps_per_mm[DUAL_AXIS_SELECT]); + #endif + float target[N_AXIS]; + float max_travel = 0.0; + uint8_t idx; + for (idx=0; idxfeed_rate = homing_rate; // Set current homing rate. + plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion. + + sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags. + st_prep_buffer(); // Prep and fill segment buffer from newly planned block. + st_wake_up(); // Initiate motion + do { + if (approach) { + // Check limit state. Lock out cycle axes when they change. + limit_state = limits_get_state(); + for (idx=0; idx dual_fail_distance) { + system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH); + mc_reset(); + protocol_execute_realtime(); + return; + } + } + } else { + dual_axis_async_check |= DUAL_AXIS_CHECK_ENABLE; + dual_trigger_position = sys_position[DUAL_AXIS_SELECT]; + } + } + #endif + } + + st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us. + + // Exit routines: No time to run protocol_execute_realtime() in this loop. + if (sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) { + uint8_t rt_exec = sys_rt_exec_state; + // Homing failure condition: Reset issued during cycle. + if (rt_exec & EXEC_RESET) { system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_RESET); } + // Homing failure condition: Safety door was opened. + if (rt_exec & EXEC_SAFETY_DOOR) { system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_DOOR); } + // Homing failure condition: Limit switch still engaged after pull-off motion + if (!approach && (limits_get_state() & cycle_mask)) { system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_PULLOFF); } + // Homing failure condition: Limit switch not found during approach. + if (approach && (rt_exec & EXEC_CYCLE_STOP)) { system_set_exec_alarm(EXEC_ALARM_HOMING_FAIL_APPROACH); } + if (sys_rt_exec_alarm) { + mc_reset(); // Stop motors, if they are running. + protocol_execute_realtime(); + return; + } else { + // Pull-off motion complete. Disable CYCLE_STOP from executing. + system_clear_exec_state_flag(EXEC_CYCLE_STOP); + break; + } + } + + #ifdef ENABLE_DUAL_AXIS + } while ((STEP_MASK & axislock) || (sys.homing_axis_lock_dual)); + #else + } while (STEP_MASK & axislock); + #endif + + st_reset(); // Immediately force kill steppers and reset step segment buffer. + delay_ms(settings.homing_debounce_delay); // Delay to allow transient dynamics to dissipate. + + // Reverse direction and reset homing rate for locate cycle(s). + approach = !approach; + + // After first cycle, homing enters locating phase. Shorten search to pull-off distance. + if (approach) { + max_travel = settings.homing_pulloff*HOMING_AXIS_LOCATE_SCALAR; + homing_rate = settings.homing_feed_rate; + } else { + max_travel = settings.homing_pulloff; + homing_rate = settings.homing_seek_rate; + } + + } while (n_cycle-- > 0); + + // The active cycle axes should now be homed and machine limits have been located. By + // default, Grbl defines machine space as all negative, as do most CNCs. Since limit switches + // can be on either side of an axes, check and set axes machine zero appropriately. Also, + // set up pull-off maneuver from axes limit switches that have been homed. This provides + // some initial clearance off the switches and should also help prevent them from falsely + // triggering when hard limits are enabled or when more than one axes shares a limit pin. + int32_t set_axis_position; + // Set machine positions for homed limit switches. Don't update non-homed axes. + for (idx=0; idx. +*/ + +#ifndef limits_h +#define limits_h + + +// Initialize the limits module +void limits_init(); + +// Disables hard limits. +void limits_disable(); + +// Returns limit state as a bit-wise uint8 variable. +uint8_t limits_get_state(); + +// Perform one portion of the homing cycle based on the input settings. +void limits_go_home(uint8_t cycle_mask); + +// Check for soft limit violations +void limits_soft_check(float *target); + +#endif diff --git a/grbl/main.c b/grbl/main.c new file mode 100644 index 0000000..96f2aba --- /dev/null +++ b/grbl/main.c @@ -0,0 +1,109 @@ +/* + main.c - An embedded CNC Controller with rs274/ngc (g-code) support + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +// Declare system global variable structure +system_t sys; +int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. +int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. +volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. +volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. +volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. +volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. +volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. +#ifdef DEBUG + volatile uint8_t sys_rt_exec_debug; +#endif + + +int main(void) +{ + // Initialize system upon power-up. + serial_init(); // Setup serial baud rate and interrupts + settings_init(); // Load Grbl settings from EEPROM + stepper_init(); // Configure stepper pins and interrupt timers + system_init(); // Configure pinout pins and pin-change interrupt + + memset(sys_position,0,sizeof(sys_position)); // Clear machine position. + sei(); // Enable interrupts + + // Initialize system state. + #ifdef FORCE_INITIALIZATION_ALARM + // Force Grbl into an ALARM state upon a power-cycle or hard reset. + sys.state = STATE_ALARM; + #else + sys.state = STATE_IDLE; + #endif + + // Check for power-up and set system alarm if homing is enabled to force homing cycle + // by setting Grbl's alarm state. Alarm locks out all g-code commands, including the + // startup scripts, but allows access to settings and internal commands. Only a homing + // cycle '$H' or kill alarm locks '$X' will disable the alarm. + // NOTE: The startup script will run after successful completion of the homing cycle, but + // not after disabling the alarm locks. Prevents motion startup blocks from crashing into + // things uncontrollably. Very bad. + #ifdef HOMING_INIT_LOCK + if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; } + #endif + + // Grbl initialization loop upon power-up or a system abort. For the latter, all processes + // will return to this loop to be cleanly re-initialized. + for(;;) { + + // Reset system variables. + uint8_t prior_state = sys.state; + memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. + sys.state = prior_state; + sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100% + sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100% + sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100% + memset(sys_probe_position,0,sizeof(sys_probe_position)); // Clear probe position. + sys_probe_state = 0; + sys_rt_exec_state = 0; + sys_rt_exec_alarm = 0; + sys_rt_exec_motion_override = 0; + sys_rt_exec_accessory_override = 0; + + // Reset Grbl primary systems. + serial_reset_read_buffer(); // Clear serial read buffer + gc_init(); // Set g-code parser to default state + spindle_init(); + coolant_init(); + limits_init(); + probe_init(); + plan_reset(); // Clear block buffer and planner variables + st_reset(); // Clear stepper subsystem variables. + + // Sync cleared gcode and planner positions to current system position. + plan_sync_position(); + gc_sync_position(); + + // Print welcome message. Indicates an initialization has occured at power-up or with a reset. + report_init_message(); + + // Start Grbl main loop. Processes program inputs and executes them. + protocol_main_loop(); + + } + return 0; /* Never reached */ +} diff --git a/grbl/motion_control.c b/grbl/motion_control.c new file mode 100644 index 0000000..6e11e35 --- /dev/null +++ b/grbl/motion_control.c @@ -0,0 +1,388 @@ +/* + motion_control.c - high level interface for issuing motion commands + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second +// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in +// (1 minute)/feed_rate time. +// NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line +// segments, must pass through this routine before being passed to the planner. The seperation of +// mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being +// in the planner and to let backlash compensation or canned cycle integration simple and direct. +void mc_line(float *target, plan_line_data_t *pl_data) +{ + // If enabled, check for soft limit violations. Placed here all line motions are picked up + // from everywhere in Grbl. + if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { + // NOTE: Block jog state. Jogging is a special case and soft limits are handled independently. + if (sys.state != STATE_JOG) { limits_soft_check(target); } + } + + // If in check gcode mode, prevent motion by blocking planner. Soft limits still work. + if (sys.state == STATE_CHECK_MODE) { return; } + + // NOTE: Backlash compensation may be installed here. It will need direction info to track when + // to insert a backlash line motion(s) before the intended line motion and will require its own + // plan_check_full_buffer() and check for system abort loop. Also for position reporting + // backlash steps will need to be also tracked, which will need to be kept at a system level. + // There are likely some other things that will need to be tracked as well. However, we feel + // that backlash compensation should NOT be handled by Grbl itself, because there are a myriad + // of ways to implement it and can be effective or ineffective for different CNC machines. This + // would be better handled by the interface as a post-processor task, where the original g-code + // is translated and inserts backlash motions that best suits the machine. + // NOTE: Perhaps as a middle-ground, all that needs to be sent is a flag or special command that + // indicates to Grbl what is a backlash compensation motion, so that Grbl executes the move but + // doesn't update the machine position values. Since the position values used by the g-code + // parser and planner are separate from the system machine positions, this is doable. + + // If the buffer is full: good! That means we are well ahead of the robot. + // Remain in this loop until there is room in the buffer. + do { + protocol_execute_realtime(); // Check for any run-time commands + if (sys.abort) { return; } // Bail, if system abort. + if ( plan_check_full_buffer() ) { protocol_auto_cycle_start(); } // Auto-cycle start when buffer is full. + else { break; } + } while (1); + + // Plan and queue motion into planner buffer + if (plan_buffer_line(target, pl_data) == PLAN_EMPTY_BLOCK) { + if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { + // Correctly set spindle state, if there is a coincident position passed. Forces a buffer + // sync while in M3 laser mode only. + if (pl_data->condition & PL_COND_FLAG_SPINDLE_CW) { + spindle_sync(PL_COND_FLAG_SPINDLE_CW, pl_data->spindle_speed); + } + } + } +} + + +// Execute an arc in offset mode format. position == current xyz, target == target xyz, +// offset == offset from current xyz, axis_X defines circle plane in tool space, axis_linear is +// the direction of helical travel, radius == circle radius, isclockwise boolean. Used +// for vector transformation direction. +// The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance +// of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal +// distance from segment to the circle when the end points both lie on the circle. +void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius, + uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc) +{ + float center_axis0 = position[axis_0] + offset[axis_0]; + float center_axis1 = position[axis_1] + offset[axis_1]; + float r_axis0 = -offset[axis_0]; // Radius vector from center to current location + float r_axis1 = -offset[axis_1]; + float rt_axis0 = target[axis_0] - center_axis0; + float rt_axis1 = target[axis_1] - center_axis1; + + // CCW angle between position and target from circle center. Only one atan2() trig computation required. + float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1); + if (is_clockwise_arc) { // Correct atan2 output per direction + if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel -= 2*M_PI; } + } else { + if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON) { angular_travel += 2*M_PI; } + } + + // NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to + // (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit + // is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation. + // For the intended uses of Grbl, this value shouldn't exceed 2000 for the strictest of cases. + uint16_t segments = floor(fabs(0.5*angular_travel*radius)/ + sqrt(settings.arc_tolerance*(2*radius - settings.arc_tolerance)) ); + + if (segments) { + // Multiply inverse feed_rate to compensate for the fact that this movement is approximated + // by a number of discrete segments. The inverse feed_rate should be correct for the sum of + // all segments. + if (pl_data->condition & PL_COND_FLAG_INVERSE_TIME) { + pl_data->feed_rate *= segments; + bit_false(pl_data->condition,PL_COND_FLAG_INVERSE_TIME); // Force as feed absolute mode over arc segments. + } + + float theta_per_segment = angular_travel/segments; + float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments; + + /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, + and phi is the angle of rotation. Solution approach by Jens Geisler. + r_T = [cos(phi) -sin(phi); + sin(phi) cos(phi] * r ; + + For arc generation, the center of the circle is the axis of rotation and the radius vector is + defined from the circle center to the initial position. Each line segment is formed by successive + vector rotations. Single precision values can accumulate error greater than tool precision in rare + cases. So, exact arc path correction is implemented. This approach avoids the problem of too many very + expensive trig operations [sin(),cos(),tan()] which can take 100-200 usec each to compute. + + Small angle approximation may be used to reduce computation overhead further. A third-order approximation + (second order sin() has too much error) holds for most, if not, all CNC applications. Note that this + approximation will begin to accumulate a numerical drift error when theta_per_segment is greater than + ~0.25 rad(14 deg) AND the approximation is successively used without correction several dozen times. This + scenario is extremely unlikely, since segment lengths and theta_per_segment are automatically generated + and scaled by the arc tolerance setting. Only a very large arc tolerance setting, unrealistic for CNC + applications, would cause this numerical drift error. However, it is best to set N_ARC_CORRECTION from a + low of ~4 to a high of ~20 or so to avoid trig operations while keeping arc generation accurate. + + This approximation also allows mc_arc to immediately insert a line segment into the planner + without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied + a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. + This is important when there are successive arc motions. + */ + // Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec + float cos_T = 2.0 - theta_per_segment*theta_per_segment; + float sin_T = theta_per_segment*0.16666667*(cos_T + 4.0); + cos_T *= 0.5; + + float sin_Ti; + float cos_Ti; + float r_axisi; + uint16_t i; + uint8_t count = 0; + + for (i = 1; i. +*/ + +#ifndef motion_control_h +#define motion_control_h + + +// System motion commands must have a line number of zero. +#define HOMING_CYCLE_LINE_NUMBER 0 +#define PARKING_MOTION_LINE_NUMBER 0 + +#define HOMING_CYCLE_ALL 0 // Must be zero. +#define HOMING_CYCLE_X bit(X_AXIS) +#define HOMING_CYCLE_Y bit(Y_AXIS) +#define HOMING_CYCLE_Z bit(Z_AXIS) + + +// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second +// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in +// (1 minute)/feed_rate time. +void mc_line(float *target, plan_line_data_t *pl_data); + +// Execute an arc in offset mode format. position == current xyz, target == target xyz, +// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is +// the direction of helical travel, radius == circle radius, is_clockwise_arc boolean. Used +// for vector transformation direction. +void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *offset, float radius, + uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc); + +// Dwell for a specific number of seconds +void mc_dwell(float seconds); + +// Perform homing cycle to locate machine zero. Requires limit switches. +void mc_homing_cycle(uint8_t cycle_mask); + +// Perform tool length probe cycle. Requires probe switch. +uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags); + +// Handles updating the override control state. +void mc_override_ctrl_update(uint8_t override_state); + +// Plans and executes the single special motion case for parking. Independent of main planner buffer. +void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data); + +// Performs system reset. If in motion state, kills all motion and sets system alarm. +void mc_reset(); + +#endif diff --git a/grbl/nuts_bolts.c b/grbl/nuts_bolts.c new file mode 100644 index 0000000..9d89a8d --- /dev/null +++ b/grbl/nuts_bolts.c @@ -0,0 +1,190 @@ +/* + nuts_bolts.c - Shared functions + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) + + +// Extracts a floating point value from a string. The following code is based loosely on +// the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely +// available conversion method examples, but has been highly optimized for Grbl. For known +// CNC applications, the typical decimal value is expected to be in the range of E0 to E-4. +// Scientific notation is officially not supported by g-code, and the 'E' character may +// be a g-code word on some CNC systems. So, 'E' notation will not be recognized. +// NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod(). +uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr) +{ + char *ptr = line + *char_counter; + unsigned char c; + + // Grab first character and increment pointer. No spaces assumed in line. + c = *ptr++; + + // Capture initial positive/minus character + bool isnegative = false; + if (c == '-') { + isnegative = true; + c = *ptr++; + } else if (c == '+') { + c = *ptr++; + } + + // Extract number into fast integer. Track decimal in terms of exponent value. + uint32_t intval = 0; + int8_t exp = 0; + uint8_t ndigit = 0; + bool isdecimal = false; + while(1) { + c -= '0'; + if (c <= 9) { + ndigit++; + if (ndigit <= MAX_INT_DIGITS) { + if (isdecimal) { exp--; } + intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c + } else { + if (!(isdecimal)) { exp++; } // Drop overflow digits + } + } else if (c == (('.'-'0') & 0xff) && !(isdecimal)) { + isdecimal = true; + } else { + break; + } + c = *ptr++; + } + + // Return if no digits have been read. + if (!ndigit) { return(false); }; + + // Convert integer into floating point. + float fval; + fval = (float)intval; + + // Apply decimal. Should perform no more than two floating point multiplications for the + // expected range of E0 to E-4. + if (fval != 0) { + while (exp <= -2) { + fval *= 0.01; + exp += 2; + } + if (exp < 0) { + fval *= 0.1; + } else if (exp > 0) { + do { + fval *= 10.0; + } while (--exp > 0); + } + } + + // Assign floating point value with correct sign. + if (isnegative) { + *float_ptr = -fval; + } else { + *float_ptr = fval; + } + + *char_counter = ptr - line - 1; // Set char_counter to next statement + + return(true); +} + + +// Non-blocking delay function used for general operation and suspend features. +void delay_sec(float seconds, uint8_t mode) +{ + uint16_t i = ceil(1000/DWELL_TIME_STEP*seconds); + while (i-- > 0) { + if (sys.abort) { return; } + if (mode == DELAY_MODE_DWELL) { + protocol_execute_realtime(); + } else { // DELAY_MODE_SYS_SUSPEND + // Execute rt_system() only to avoid nesting suspend loops. + protocol_exec_rt_system(); + if (sys.suspend & SUSPEND_RESTART_RETRACT) { return; } // Bail, if safety door reopens. + } + _delay_ms(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment + } +} + + +// Delays variable defined milliseconds. Compiler compatibility fix for _delay_ms(), +// which only accepts constants in future compiler releases. +void delay_ms(uint16_t ms) +{ + while ( ms-- ) { _delay_ms(1); } +} + + +// Delays variable defined microseconds. Compiler compatibility fix for _delay_us(), +// which only accepts constants in future compiler releases. Written to perform more +// efficiently with larger delays, as the counter adds parasitic time in each iteration. +void delay_us(uint32_t us) +{ + while (us) { + if (us < 10) { + _delay_us(1); + us--; + } else if (us < 100) { + _delay_us(10); + us -= 10; + } else if (us < 1000) { + _delay_us(100); + us -= 100; + } else { + _delay_ms(1); + us -= 1000; + } + } +} + + +// Simple hypotenuse computation function. +float hypot_f(float x, float y) { return(sqrt(x*x + y*y)); } + + +float convert_delta_vector_to_unit_vector(float *vector) +{ + uint8_t idx; + float magnitude = 0.0; + for (idx=0; idx. +*/ + +#ifndef nuts_bolts_h +#define nuts_bolts_h + +#define false 0 +#define true 1 + +#define SOME_LARGE_VALUE 1.0E+38 + +// Axis array index values. Must start with 0 and be continuous. +#define N_AXIS 3 // Number of axes +#define X_AXIS 0 // Axis indexing value. +#define Y_AXIS 1 +#define Z_AXIS 2 +// #define A_AXIS 3 + +// CoreXY motor assignments. DO NOT ALTER. +// NOTE: If the A and B motor axis bindings are changed, this effects the CoreXY equations. +#ifdef COREXY + #define A_MOTOR X_AXIS // Must be X_AXIS + #define B_MOTOR Y_AXIS // Must be Y_AXIS +#endif + +// Conversions +#define MM_PER_INCH (25.40) +#define INCH_PER_MM (0.0393701) +#define TICKS_PER_MICROSECOND (F_CPU/1000000) + +#define DELAY_MODE_DWELL 0 +#define DELAY_MODE_SYS_SUSPEND 1 + +// Useful macros +#define clear_vector(a) memset(a, 0, sizeof(a)) +#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS) +// #define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS) +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define isequal_position_vector(a,b) !(memcmp(a, b, sizeof(float)*N_AXIS)) + +// Bit field and masking macros +#define bit(n) (1 << n) +#define bit_true(x,mask) (x) |= (mask) +#define bit_false(x,mask) (x) &= ~(mask) +#define bit_istrue(x,mask) ((x & mask) != 0) +#define bit_isfalse(x,mask) ((x & mask) == 0) + +// Read a floating point value from a string. Line points to the input buffer, char_counter +// is the indexer pointing to the current character of the line, while float_ptr is +// a pointer to the result variable. Returns true when it succeeds +uint8_t read_float(char *line, uint8_t *char_counter, float *float_ptr); + +// Non-blocking delay function used for general operation and suspend features. +void delay_sec(float seconds, uint8_t mode); + +// Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms(). +void delay_ms(uint16_t ms); + +// Delays variable-defined microseconds. Compiler compatibility fix for _delay_us(). +void delay_us(uint32_t us); + +// Computes hypotenuse, avoiding avr-gcc's bloated version and the extra error checking. +float hypot_f(float x, float y); + +float convert_delta_vector_to_unit_vector(float *vector); +float limit_value_by_axis_maximum(float *max_value, float *unit_vec); + +#endif diff --git a/grbl/planner.c b/grbl/planner.c new file mode 100644 index 0000000..49ff722 --- /dev/null +++ b/grbl/planner.c @@ -0,0 +1,522 @@ +/* + planner.c - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + Copyright (c) 2011 Jens Geisler + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +static plan_block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instructions +static uint8_t block_buffer_tail; // Index of the block to process now +static uint8_t block_buffer_head; // Index of the next block to be pushed +static uint8_t next_buffer_head; // Index of the next buffer head +static uint8_t block_buffer_planned; // Index of the optimally planned block + +// Define planner variables +typedef struct { + int32_t position[N_AXIS]; // The planner position of the tool in absolute steps. Kept separate + // from g-code position for movements requiring multiple line motions, + // i.e. arcs, canned cycles, and backlash compensation. + float previous_unit_vec[N_AXIS]; // Unit vector of previous path line segment + float previous_nominal_speed; // Nominal speed of previous path line segment +} planner_t; +static planner_t pl; + + +// Returns the index of the next block in the ring buffer. Also called by stepper segment buffer. +uint8_t plan_next_block_index(uint8_t block_index) +{ + block_index++; + if (block_index == BLOCK_BUFFER_SIZE) { block_index = 0; } + return(block_index); +} + + +// Returns the index of the previous block in the ring buffer +static uint8_t plan_prev_block_index(uint8_t block_index) +{ + if (block_index == 0) { block_index = BLOCK_BUFFER_SIZE; } + block_index--; + return(block_index); +} + + +/* PLANNER SPEED DEFINITION + +--------+ <- current->nominal_speed + / \ + current->entry_speed -> + \ + | + <- next->entry_speed (aka exit speed) + +-------------+ + time --> + + Recalculates the motion plan according to the following basic guidelines: + + 1. Go over every feasible block sequentially in reverse order and calculate the junction speeds + (i.e. current->entry_speed) such that: + a. No junction speed exceeds the pre-computed maximum junction speed limit or nominal speeds of + neighboring blocks. + b. A block entry speed cannot exceed one reverse-computed from its exit speed (next->entry_speed) + with a maximum allowable deceleration over the block travel distance. + c. The last (or newest appended) block is planned from a complete stop (an exit speed of zero). + 2. Go over every block in chronological (forward) order and dial down junction speed values if + a. The exit speed exceeds the one forward-computed from its entry speed with the maximum allowable + acceleration over the block travel distance. + + When these stages are complete, the planner will have maximized the velocity profiles throughout the all + of the planner blocks, where every block is operating at its maximum allowable acceleration limits. In + other words, for all of the blocks in the planner, the plan is optimal and no further speed improvements + are possible. If a new block is added to the buffer, the plan is recomputed according to the said + guidelines for a new optimal plan. + + To increase computational efficiency of these guidelines, a set of planner block pointers have been + created to indicate stop-compute points for when the planner guidelines cannot logically make any further + changes or improvements to the plan when in normal operation and new blocks are streamed and added to the + planner buffer. For example, if a subset of sequential blocks in the planner have been planned and are + bracketed by junction velocities at their maximums (or by the first planner block as well), no new block + added to the planner buffer will alter the velocity profiles within them. So we no longer have to compute + them. Or, if a set of sequential blocks from the first block in the planner (or a optimal stop-compute + point) are all accelerating, they are all optimal and can not be altered by a new block added to the + planner buffer, as this will only further increase the plan speed to chronological blocks until a maximum + junction velocity is reached. However, if the operational conditions of the plan changes from infrequently + used feed holds or feedrate overrides, the stop-compute pointers will be reset and the entire plan is + recomputed as stated in the general guidelines. + + Planner buffer index mapping: + - block_buffer_tail: Points to the beginning of the planner buffer. First to be executed or being executed. + - block_buffer_head: Points to the buffer block after the last block in the buffer. Used to indicate whether + the buffer is full or empty. As described for standard ring buffers, this block is always empty. + - next_buffer_head: Points to next planner buffer block after the buffer head block. When equal to the + buffer tail, this indicates the buffer is full. + - block_buffer_planned: Points to the first buffer block after the last optimally planned block for normal + streaming operating conditions. Use for planning optimizations by avoiding recomputing parts of the + planner buffer that don't change with the addition of a new block, as describe above. In addition, + this block can never be less than block_buffer_tail and will always be pushed forward and maintain + this requirement when encountered by the plan_discard_current_block() routine during a cycle. + + NOTE: Since the planner only computes on what's in the planner buffer, some motions with lots of short + line segments, like G2/3 arcs or complex curves, may seem to move slow. This is because there simply isn't + enough combined distance traveled in the entire buffer to accelerate up to the nominal speed and then + decelerate to a complete stop at the end of the buffer, as stated by the guidelines. If this happens and + becomes an annoyance, there are a few simple solutions: (1) Maximize the machine acceleration. The planner + will be able to compute higher velocity profiles within the same combined distance. (2) Maximize line + motion(s) distance per block to a desired tolerance. The more combined distance the planner has to use, + the faster it can go. (3) Maximize the planner buffer size. This also will increase the combined distance + for the planner to compute over. It also increases the number of computations the planner has to perform + to compute an optimal plan, so select carefully. The Arduino 328p memory is already maxed out, but future + ARM versions should have enough memory and speed for look-ahead blocks numbering up to a hundred or more. + +*/ +static void planner_recalculate() +{ + // Initialize block index to the last block in the planner buffer. + uint8_t block_index = plan_prev_block_index(block_buffer_head); + + // Bail. Can't do anything with one only one plan-able block. + if (block_index == block_buffer_planned) { return; } + + // Reverse Pass: Coarsely maximize all possible deceleration curves back-planning from the last + // block in buffer. Cease planning when the last optimal planned or tail pointer is reached. + // NOTE: Forward pass will later refine and correct the reverse pass to create an optimal plan. + float entry_speed_sqr; + plan_block_t *next; + plan_block_t *current = &block_buffer[block_index]; + + // Calculate maximum entry speed for last block in buffer, where the exit speed is always zero. + current->entry_speed_sqr = min( current->max_entry_speed_sqr, 2*current->acceleration*current->millimeters); + + block_index = plan_prev_block_index(block_index); + if (block_index == block_buffer_planned) { // Only two plannable blocks in buffer. Reverse pass complete. + // Check if the first block is the tail. If so, notify stepper to update its current parameters. + if (block_index == block_buffer_tail) { st_update_plan_block_parameters(); } + } else { // Three or more plan-able blocks + while (block_index != block_buffer_planned) { + next = current; + current = &block_buffer[block_index]; + block_index = plan_prev_block_index(block_index); + + // Check if next block is the tail block(=planned block). If so, update current stepper parameters. + if (block_index == block_buffer_tail) { st_update_plan_block_parameters(); } + + // Compute maximum entry speed decelerating over the current block from its exit speed. + if (current->entry_speed_sqr != current->max_entry_speed_sqr) { + entry_speed_sqr = next->entry_speed_sqr + 2*current->acceleration*current->millimeters; + if (entry_speed_sqr < current->max_entry_speed_sqr) { + current->entry_speed_sqr = entry_speed_sqr; + } else { + current->entry_speed_sqr = current->max_entry_speed_sqr; + } + } + } + } + + // Forward Pass: Forward plan the acceleration curve from the planned pointer onward. + // Also scans for optimal plan breakpoints and appropriately updates the planned pointer. + next = &block_buffer[block_buffer_planned]; // Begin at buffer planned pointer + block_index = plan_next_block_index(block_buffer_planned); + while (block_index != block_buffer_head) { + current = next; + next = &block_buffer[block_index]; + + // Any acceleration detected in the forward pass automatically moves the optimal planned + // pointer forward, since everything before this is all optimal. In other words, nothing + // can improve the plan from the buffer tail to the planned pointer by logic. + if (current->entry_speed_sqr < next->entry_speed_sqr) { + entry_speed_sqr = current->entry_speed_sqr + 2*current->acceleration*current->millimeters; + // If true, current block is full-acceleration and we can move the planned pointer forward. + if (entry_speed_sqr < next->entry_speed_sqr) { + next->entry_speed_sqr = entry_speed_sqr; // Always <= max_entry_speed_sqr. Backward pass sets this. + block_buffer_planned = block_index; // Set optimal plan pointer. + } + } + + // Any block set at its maximum entry speed also creates an optimal plan up to this + // point in the buffer. When the plan is bracketed by either the beginning of the + // buffer and a maximum entry speed or two maximum entry speeds, every block in between + // cannot logically be further improved. Hence, we don't have to recompute them anymore. + if (next->entry_speed_sqr == next->max_entry_speed_sqr) { block_buffer_planned = block_index; } + block_index = plan_next_block_index( block_index ); + } +} + + +void plan_reset() +{ + memset(&pl, 0, sizeof(planner_t)); // Clear planner struct + plan_reset_buffer(); +} + + +void plan_reset_buffer() +{ + block_buffer_tail = 0; + block_buffer_head = 0; // Empty = tail + next_buffer_head = 1; // plan_next_block_index(block_buffer_head) + block_buffer_planned = 0; // = block_buffer_tail; +} + + +void plan_discard_current_block() +{ + if (block_buffer_head != block_buffer_tail) { // Discard non-empty buffer. + uint8_t block_index = plan_next_block_index( block_buffer_tail ); + // Push block_buffer_planned pointer, if encountered. + if (block_buffer_tail == block_buffer_planned) { block_buffer_planned = block_index; } + block_buffer_tail = block_index; + } +} + + +// Returns address of planner buffer block used by system motions. Called by segment generator. +plan_block_t *plan_get_system_motion_block() +{ + return(&block_buffer[block_buffer_head]); +} + + +// Returns address of first planner block, if available. Called by various main program functions. +plan_block_t *plan_get_current_block() +{ + if (block_buffer_head == block_buffer_tail) { return(NULL); } // Buffer empty + return(&block_buffer[block_buffer_tail]); +} + + +float plan_get_exec_block_exit_speed_sqr() +{ + uint8_t block_index = plan_next_block_index(block_buffer_tail); + if (block_index == block_buffer_head) { return( 0.0 ); } + return( block_buffer[block_index].entry_speed_sqr ); +} + + +// Returns the availability status of the block ring buffer. True, if full. +uint8_t plan_check_full_buffer() +{ + if (block_buffer_tail == next_buffer_head) { return(true); } + return(false); +} + + +// Computes and returns block nominal speed based on running condition and override values. +// NOTE: All system motion commands, such as homing/parking, are not subject to overrides. +float plan_compute_profile_nominal_speed(plan_block_t *block) +{ + float nominal_speed = block->programmed_rate; + if (block->condition & PL_COND_FLAG_RAPID_MOTION) { nominal_speed *= (0.01*sys.r_override); } + else { + if (!(block->condition & PL_COND_FLAG_NO_FEED_OVERRIDE)) { nominal_speed *= (0.01*sys.f_override); } + if (nominal_speed > block->rapid_rate) { nominal_speed = block->rapid_rate; } + } + if (nominal_speed > MINIMUM_FEED_RATE) { return(nominal_speed); } + return(MINIMUM_FEED_RATE); +} + + +// Computes and updates the max entry speed (sqr) of the block, based on the minimum of the junction's +// previous and current nominal speeds and max junction speed. +static void plan_compute_profile_parameters(plan_block_t *block, float nominal_speed, float prev_nominal_speed) +{ + // Compute the junction maximum entry based on the minimum of the junction speed and neighboring nominal speeds. + if (nominal_speed > prev_nominal_speed) { block->max_entry_speed_sqr = prev_nominal_speed*prev_nominal_speed; } + else { block->max_entry_speed_sqr = nominal_speed*nominal_speed; } + if (block->max_entry_speed_sqr > block->max_junction_speed_sqr) { block->max_entry_speed_sqr = block->max_junction_speed_sqr; } +} + + +// Re-calculates buffered motions profile parameters upon a motion-based override change. +void plan_update_velocity_profile_parameters() +{ + uint8_t block_index = block_buffer_tail; + plan_block_t *block; + float nominal_speed; + float prev_nominal_speed = SOME_LARGE_VALUE; // Set high for first block nominal speed calculation. + while (block_index != block_buffer_head) { + block = &block_buffer[block_index]; + nominal_speed = plan_compute_profile_nominal_speed(block); + plan_compute_profile_parameters(block, nominal_speed, prev_nominal_speed); + prev_nominal_speed = nominal_speed; + block_index = plan_next_block_index(block_index); + } + pl.previous_nominal_speed = prev_nominal_speed; // Update prev nominal speed for next incoming block. +} + + +/* Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position + in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed + rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. + All position data passed to the planner must be in terms of machine position to keep the planner + independent of any coordinate system changes and offsets, which are handled by the g-code parser. + NOTE: Assumes buffer is available. Buffer checks are handled at a higher level by motion_control. + In other words, the buffer head is never equal to the buffer tail. Also the feed rate input value + is used in three ways: as a normal feed rate if invert_feed_rate is false, as inverse time if + invert_feed_rate is true, or as seek/rapids rate if the feed_rate value is negative (and + invert_feed_rate always false). + The system motion condition tells the planner to plan a motion in the always unused block buffer + head. It avoids changing the planner state and preserves the buffer to ensure subsequent gcode + motions are still planned correctly, while the stepper module only points to the block buffer head + to execute the special system motion. */ +uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data) +{ + // Prepare and initialize new block. Copy relevant pl_data for block execution. + plan_block_t *block = &block_buffer[block_buffer_head]; + memset(block,0,sizeof(plan_block_t)); // Zero all block values. + block->condition = pl_data->condition; + #ifdef VARIABLE_SPINDLE + block->spindle_speed = pl_data->spindle_speed; + #endif + #ifdef USE_LINE_NUMBERS + block->line_number = pl_data->line_number; + #endif + + // Compute and store initial move distance data. + int32_t target_steps[N_AXIS], position_steps[N_AXIS]; + float unit_vec[N_AXIS], delta_mm; + uint8_t idx; + + // Copy position data based on type of motion being planned. + if (block->condition & PL_COND_FLAG_SYSTEM_MOTION) { + #ifdef COREXY + position_steps[X_AXIS] = system_convert_corexy_to_x_axis_steps(sys_position); + position_steps[Y_AXIS] = system_convert_corexy_to_y_axis_steps(sys_position); + position_steps[Z_AXIS] = sys_position[Z_AXIS]; + #else + memcpy(position_steps, sys_position, sizeof(sys_position)); + #endif + } else { memcpy(position_steps, pl.position, sizeof(pl.position)); } + + #ifdef COREXY + target_steps[A_MOTOR] = lround(target[A_MOTOR]*settings.steps_per_mm[A_MOTOR]); + target_steps[B_MOTOR] = lround(target[B_MOTOR]*settings.steps_per_mm[B_MOTOR]); + block->steps[A_MOTOR] = labs((target_steps[X_AXIS]-position_steps[X_AXIS]) + (target_steps[Y_AXIS]-position_steps[Y_AXIS])); + block->steps[B_MOTOR] = labs((target_steps[X_AXIS]-position_steps[X_AXIS]) - (target_steps[Y_AXIS]-position_steps[Y_AXIS])); + #endif + + for (idx=0; idxsteps[idx] = labs(target_steps[idx]-position_steps[idx]); + } + block->step_event_count = max(block->step_event_count, block->steps[idx]); + if (idx == A_MOTOR) { + delta_mm = (target_steps[X_AXIS]-position_steps[X_AXIS] + target_steps[Y_AXIS]-position_steps[Y_AXIS])/settings.steps_per_mm[idx]; + } else if (idx == B_MOTOR) { + delta_mm = (target_steps[X_AXIS]-position_steps[X_AXIS] - target_steps[Y_AXIS]+position_steps[Y_AXIS])/settings.steps_per_mm[idx]; + } else { + delta_mm = (target_steps[idx] - position_steps[idx])/settings.steps_per_mm[idx]; + } + #else + target_steps[idx] = lround(target[idx]*settings.steps_per_mm[idx]); + block->steps[idx] = labs(target_steps[idx]-position_steps[idx]); + block->step_event_count = max(block->step_event_count, block->steps[idx]); + delta_mm = (target_steps[idx] - position_steps[idx])/settings.steps_per_mm[idx]; + #endif + unit_vec[idx] = delta_mm; // Store unit vector numerator + + // Set direction bits. Bit enabled always means direction is negative. + if (delta_mm < 0.0 ) { block->direction_bits |= get_direction_pin_mask(idx); } + } + + // Bail if this is a zero-length block. Highly unlikely to occur. + if (block->step_event_count == 0) { return(PLAN_EMPTY_BLOCK); } + + // Calculate the unit vector of the line move and the block maximum feed rate and acceleration scaled + // down such that no individual axes maximum values are exceeded with respect to the line direction. + // NOTE: This calculation assumes all axes are orthogonal (Cartesian) and works with ABC-axes, + // if they are also orthogonal/independent. Operates on the absolute value of the unit vector. + block->millimeters = convert_delta_vector_to_unit_vector(unit_vec); + block->acceleration = limit_value_by_axis_maximum(settings.acceleration, unit_vec); + block->rapid_rate = limit_value_by_axis_maximum(settings.max_rate, unit_vec); + + // Store programmed rate. + if (block->condition & PL_COND_FLAG_RAPID_MOTION) { block->programmed_rate = block->rapid_rate; } + else { + block->programmed_rate = pl_data->feed_rate; + if (block->condition & PL_COND_FLAG_INVERSE_TIME) { block->programmed_rate *= block->millimeters; } + } + + // TODO: Need to check this method handling zero junction speeds when starting from rest. + if ((block_buffer_head == block_buffer_tail) || (block->condition & PL_COND_FLAG_SYSTEM_MOTION)) { + + // Initialize block entry speed as zero. Assume it will be starting from rest. Planner will correct this later. + // If system motion, the system motion block always is assumed to start from rest and end at a complete stop. + block->entry_speed_sqr = 0.0; + block->max_junction_speed_sqr = 0.0; // Starting from rest. Enforce start from zero velocity. + + } else { + // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. + // Let a circle be tangent to both previous and current path line segments, where the junction + // deviation is defined as the distance from the junction to the closest edge of the circle, + // colinear with the circle center. The circular segment joining the two paths represents the + // path of centripetal acceleration. Solve for max velocity based on max acceleration about the + // radius of the circle, defined indirectly by junction deviation. This may be also viewed as + // path width or max_jerk in the previous Grbl version. This approach does not actually deviate + // from path, but used as a robust way to compute cornering speeds, as it takes into account the + // nonlinearities of both the junction angle and junction velocity. + // + // NOTE: If the junction deviation value is finite, Grbl executes the motions in an exact path + // mode (G61). If the junction deviation value is zero, Grbl will execute the motion in an exact + // stop mode (G61.1) manner. In the future, if continuous mode (G64) is desired, the math here + // is exactly the same. Instead of motioning all the way to junction point, the machine will + // just follow the arc circle defined here. The Arduino doesn't have the CPU cycles to perform + // a continuous mode path, but ARM-based microcontrollers most certainly do. + // + // NOTE: The max junction speed is a fixed value, since machine acceleration limits cannot be + // changed dynamically during operation nor can the line move geometry. This must be kept in + // memory in the event of a feedrate override changing the nominal speeds of blocks, which can + // change the overall maximum entry speed conditions of all blocks. + + float junction_unit_vec[N_AXIS]; + float junction_cos_theta = 0.0; + for (idx=0; idx 0.999999) { + // For a 0 degree acute junction, just set minimum junction speed. + block->max_junction_speed_sqr = MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED; + } else { + if (junction_cos_theta < -0.999999) { + // Junction is a straight line or 180 degrees. Junction speed is infinite. + block->max_junction_speed_sqr = SOME_LARGE_VALUE; + } else { + convert_delta_vector_to_unit_vector(junction_unit_vec); + float junction_acceleration = limit_value_by_axis_maximum(settings.acceleration, junction_unit_vec); + float sin_theta_d2 = sqrt(0.5*(1.0-junction_cos_theta)); // Trig half angle identity. Always positive. + block->max_junction_speed_sqr = max( MINIMUM_JUNCTION_SPEED*MINIMUM_JUNCTION_SPEED, + (junction_acceleration * settings.junction_deviation * sin_theta_d2)/(1.0-sin_theta_d2) ); + } + } + } + + // Block system motion from updating this data to ensure next g-code motion is computed correctly. + if (!(block->condition & PL_COND_FLAG_SYSTEM_MOTION)) { + float nominal_speed = plan_compute_profile_nominal_speed(block); + plan_compute_profile_parameters(block, nominal_speed, pl.previous_nominal_speed); + pl.previous_nominal_speed = nominal_speed; + + // Update previous path unit_vector and planner position. + memcpy(pl.previous_unit_vec, unit_vec, sizeof(unit_vec)); // pl.previous_unit_vec[] = unit_vec[] + memcpy(pl.position, target_steps, sizeof(target_steps)); // pl.position[] = target_steps[] + + // New block is all set. Update buffer head and next buffer head indices. + block_buffer_head = next_buffer_head; + next_buffer_head = plan_next_block_index(block_buffer_head); + + // Finish up by recalculating the plan with the new block. + planner_recalculate(); + } + return(PLAN_OK); +} + + +// Reset the planner position vectors. Called by the system abort/initialization routine. +void plan_sync_position() +{ + // TODO: For motor configurations not in the same coordinate frame as the machine position, + // this function needs to be updated to accomodate the difference. + uint8_t idx; + for (idx=0; idx= block_buffer_tail) { return((BLOCK_BUFFER_SIZE-1)-(block_buffer_head-block_buffer_tail)); } + return((block_buffer_tail-block_buffer_head-1)); +} + + +// Returns the number of active blocks are in the planner buffer. +// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h +uint8_t plan_get_block_buffer_count() +{ + if (block_buffer_head >= block_buffer_tail) { return(block_buffer_head-block_buffer_tail); } + return(BLOCK_BUFFER_SIZE - (block_buffer_tail-block_buffer_head)); +} + + +// Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail. +// Called after a steppers have come to a complete stop for a feed hold and the cycle is stopped. +void plan_cycle_reinitialize() +{ + // Re-plan from a complete stop. Reset planner entry speeds and buffer planned pointer. + st_update_plan_block_parameters(); + block_buffer_planned = block_buffer_tail; + planner_recalculate(); +} diff --git a/grbl/planner.h b/grbl/planner.h new file mode 100644 index 0000000..e3751e1 --- /dev/null +++ b/grbl/planner.h @@ -0,0 +1,150 @@ +/* + planner.h - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef planner_h +#define planner_h + + +// The number of linear motions that can be in the plan at any give time +#ifndef BLOCK_BUFFER_SIZE + #ifdef USE_LINE_NUMBERS + #define BLOCK_BUFFER_SIZE 15 + #else + #define BLOCK_BUFFER_SIZE 16 + #endif +#endif + +// Returned status message from planner. +#define PLAN_OK true +#define PLAN_EMPTY_BLOCK false + +// Define planner data condition flags. Used to denote running conditions of a block. +#define PL_COND_FLAG_RAPID_MOTION bit(0) +#define PL_COND_FLAG_SYSTEM_MOTION bit(1) // Single motion. Circumvents planner state. Used by home/park. +#define PL_COND_FLAG_NO_FEED_OVERRIDE bit(2) // Motion does not honor feed override. +#define PL_COND_FLAG_INVERSE_TIME bit(3) // Interprets feed rate value as inverse time when set. +#define PL_COND_FLAG_SPINDLE_CW bit(4) +#define PL_COND_FLAG_SPINDLE_CCW bit(5) +#define PL_COND_FLAG_COOLANT_FLOOD bit(6) +#define PL_COND_FLAG_COOLANT_MIST bit(7) +#define PL_COND_MOTION_MASK (PL_COND_FLAG_RAPID_MOTION|PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE) +#define PL_COND_SPINDLE_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW) +#define PL_COND_ACCESSORY_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW|PL_COND_FLAG_COOLANT_FLOOD|PL_COND_FLAG_COOLANT_MIST) + + +// This struct stores a linear movement of a g-code block motion with its critical "nominal" values +// are as specified in the source g-code. +typedef struct { + // Fields used by the bresenham algorithm for tracing the line + // NOTE: Used by stepper algorithm to execute the block correctly. Do not alter these values. + uint32_t steps[N_AXIS]; // Step count along each axis + uint32_t step_event_count; // The maximum step axis count and number of steps required to complete this block. + uint8_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) + + // Block condition data to ensure correct execution depending on states and overrides. + uint8_t condition; // Block bitflag variable defining block run conditions. Copied from pl_line_data. + #ifdef USE_LINE_NUMBERS + int32_t line_number; // Block line number for real-time reporting. Copied from pl_line_data. + #endif + + // Fields used by the motion planner to manage acceleration. Some of these values may be updated + // by the stepper module during execution of special motion cases for replanning purposes. + float entry_speed_sqr; // The current planned entry speed at block junction in (mm/min)^2 + float max_entry_speed_sqr; // Maximum allowable entry speed based on the minimum of junction limit and + // neighboring nominal speeds with overrides in (mm/min)^2 + float acceleration; // Axis-limit adjusted line acceleration in (mm/min^2). Does not change. + float millimeters; // The remaining distance for this block to be executed in (mm). + // NOTE: This value may be altered by stepper algorithm during execution. + + // Stored rate limiting data used by planner when changes occur. + float max_junction_speed_sqr; // Junction entry speed limit based on direction vectors in (mm/min)^2 + float rapid_rate; // Axis-limit adjusted maximum rate for this block direction in (mm/min) + float programmed_rate; // Programmed rate of this block (mm/min). + + #ifdef VARIABLE_SPINDLE + // Stored spindle speed data used by spindle overrides and resuming methods. + float spindle_speed; // Block spindle speed. Copied from pl_line_data. + #endif +} plan_block_t; + + +// Planner data prototype. Must be used when passing new motions to the planner. +typedef struct { + float feed_rate; // Desired feed rate for line motion. Value is ignored, if rapid motion. + float spindle_speed; // Desired spindle speed through line motion. + uint8_t condition; // Bitflag variable to indicate planner conditions. See defines above. + #ifdef USE_LINE_NUMBERS + int32_t line_number; // Desired line number to report when executing. + #endif +} plan_line_data_t; + + +// Initialize and reset the motion plan subsystem +void plan_reset(); // Reset all +void plan_reset_buffer(); // Reset buffer only. + +// Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position +// in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed +// rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. +uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data); + +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +void plan_discard_current_block(); + +// Gets the planner block for the special system motion cases. (Parking/Homing) +plan_block_t *plan_get_system_motion_block(); + +// Gets the current block. Returns NULL if buffer empty +plan_block_t *plan_get_current_block(); + +// Called periodically by step segment buffer. Mostly used internally by planner. +uint8_t plan_next_block_index(uint8_t block_index); + +// Called by step segment buffer when computing executing block velocity profile. +float plan_get_exec_block_exit_speed_sqr(); + +// Called by main program during planner calculations and step segment buffer during initialization. +float plan_compute_profile_nominal_speed(plan_block_t *block); + +// Re-calculates buffered motions profile parameters upon a motion-based override change. +void plan_update_velocity_profile_parameters(); + +// Reset the planner position vector (in steps) +void plan_sync_position(); + +// Reinitialize plan with a partially completed block +void plan_cycle_reinitialize(); + +// Returns the number of available blocks are in the planner buffer. +uint8_t plan_get_block_buffer_available(); + +// Returns the number of active blocks are in the planner buffer. +// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h +uint8_t plan_get_block_buffer_count(); + +// Returns the status of the block ring buffer. True, if buffer is full. +uint8_t plan_check_full_buffer(); + +void plan_get_planner_mpos(float *target); + + +#endif diff --git a/grbl/print.c b/grbl/print.c new file mode 100644 index 0000000..771e399 --- /dev/null +++ b/grbl/print.c @@ -0,0 +1,200 @@ +/* + print.c - Functions for formatting output strings + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +void printString(const char *s) +{ + while (*s) + serial_write(*s++); +} + + +// Print a string stored in PGM-memory +void printPgmString(const char *s) +{ + char c; + while ((c = pgm_read_byte_near(s++))) + serial_write(c); +} + + +// void printIntegerInBase(unsigned long n, unsigned long base) +// { +// unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. +// unsigned long i = 0; +// +// if (n == 0) { +// serial_write('0'); +// return; +// } +// +// while (n > 0) { +// buf[i++] = n % base; +// n /= base; +// } +// +// for (; i > 0; i--) +// serial_write(buf[i - 1] < 10 ? +// '0' + buf[i - 1] : +// 'A' + buf[i - 1] - 10); +// } + + +// Prints an uint8 variable in base 10. +void print_uint8_base10(uint8_t n) +{ + uint8_t digit_a = 0; + uint8_t digit_b = 0; + if (n >= 100) { // 100-255 + digit_a = '0' + n % 10; + n /= 10; + } + if (n >= 10) { // 10-99 + digit_b = '0' + n % 10; + n /= 10; + } + serial_write('0' + n); + if (digit_b) { serial_write(digit_b); } + if (digit_a) { serial_write(digit_a); } +} + + +// Prints an uint8 variable in base 2 with desired number of desired digits. +void print_uint8_base2_ndigit(uint8_t n, uint8_t digits) { + unsigned char buf[digits]; + uint8_t i = 0; + + for (; i < digits; i++) { + buf[i] = n % 2 ; + n /= 2; + } + + for (; i > 0; i--) + serial_write('0' + buf[i - 1]); +} + + +void print_uint32_base10(uint32_t n) +{ + if (n == 0) { + serial_write('0'); + return; + } + + unsigned char buf[10]; + uint8_t i = 0; + + while (n > 0) { + buf[i++] = n % 10; + n /= 10; + } + + for (; i > 0; i--) + serial_write('0' + buf[i-1]); +} + + +void printInteger(long n) +{ + if (n < 0) { + serial_write('-'); + print_uint32_base10(-n); + } else { + print_uint32_base10(n); + } +} + + +// Convert float to string by immediately converting to a long integer, which contains +// more digits than a float. Number of decimal places, which are tracked by a counter, +// may be set by the user. The integer is then efficiently converted to a string. +// NOTE: AVR '%' and '/' integer operations are very efficient. Bitshifting speed-up +// techniques are actually just slightly slower. Found this out the hard way. +void printFloat(float n, uint8_t decimal_places) +{ + if (n < 0) { + serial_write('-'); + n = -n; + } + + uint8_t decimals = decimal_places; + while (decimals >= 2) { // Quickly convert values expected to be E0 to E-4. + n *= 100; + decimals -= 2; + } + if (decimals) { n *= 10; } + n += 0.5; // Add rounding factor. Ensures carryover through entire value. + + // Generate digits backwards and store in string. + unsigned char buf[13]; + uint8_t i = 0; + uint32_t a = (long)n; + while(a > 0) { + buf[i++] = (a % 10) + '0'; // Get digit + a /= 10; + } + while (i < decimal_places) { + buf[i++] = '0'; // Fill in zeros to decimal point for (n < 1) + } + if (i == decimal_places) { // Fill in leading zero, if needed. + buf[i++] = '0'; + } + + // Print the generated string. + for (; i > 0; i--) { + if (i == decimal_places) { serial_write('.'); } // Insert decimal point in right place. + serial_write(buf[i-1]); + } +} + + +// Floating value printing handlers for special variables types used in Grbl and are defined +// in the config.h. +// - CoordValue: Handles all position or coordinate values in inches or mm reporting. +// - RateValue: Handles feed rate and current velocity in inches or mm reporting. +void printFloat_CoordValue(float n) { + if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { + printFloat(n*INCH_PER_MM,N_DECIMAL_COORDVALUE_INCH); + } else { + printFloat(n,N_DECIMAL_COORDVALUE_MM); + } +} + +void printFloat_RateValue(float n) { + if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { + printFloat(n*INCH_PER_MM,N_DECIMAL_RATEVALUE_INCH); + } else { + printFloat(n,N_DECIMAL_RATEVALUE_MM); + } +} + +// Debug tool to print free memory in bytes at the called point. +// NOTE: Keep commented unless using. Part of this function always gets compiled in. +// void printFreeMemory() +// { +// extern int __heap_start, *__brkval; +// uint16_t free; // Up to 64k values. +// free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); +// printInteger((int32_t)free); +// printString(" "); +// } diff --git a/grbl/print.h b/grbl/print.h new file mode 100644 index 0000000..31e0a57 --- /dev/null +++ b/grbl/print.h @@ -0,0 +1,51 @@ +/* + print.h - Functions for formatting output strings + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef print_h +#define print_h + + +void printString(const char *s); + +void printPgmString(const char *s); + +void printInteger(long n); + +void print_uint32_base10(uint32_t n); + +// Prints an uint8 variable in base 10. +void print_uint8_base10(uint8_t n); + +// Prints an uint8 variable in base 2 with desired number of desired digits. +void print_uint8_base2_ndigit(uint8_t n, uint8_t digits); + +void printFloat(float n, uint8_t decimal_places); + +// Floating value printing handlers for special variables types used in Grbl. +// - CoordValue: Handles all position or coordinate values in inches or mm reporting. +// - RateValue: Handles feed rate and current velocity in inches or mm reporting. +void printFloat_CoordValue(float n); +void printFloat_RateValue(float n); + +// Debug tool to print free memory in bytes at the called point. Not used otherwise. +void printFreeMemory(); + +#endif diff --git a/grbl/probe.c b/grbl/probe.c new file mode 100644 index 0000000..60c9073 --- /dev/null +++ b/grbl/probe.c @@ -0,0 +1,66 @@ +/* + probe.c - code pertaining to probing methods + Part of Grbl + + Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +// Inverts the probe pin state depending on user settings and probing cycle mode. +uint8_t probe_invert_mask; + + +// Probe pin initialization routine. +void probe_init() +{ + PROBE_DDR &= ~(PROBE_MASK); // Configure as input pins + #ifdef DISABLE_PROBE_PIN_PULL_UP + PROBE_PORT &= ~(PROBE_MASK); // Normal low operation. Requires external pull-down. + #else + PROBE_PORT |= PROBE_MASK; // Enable internal pull-up resistors. Normal high operation. + #endif + probe_configure_invert_mask(false); // Initialize invert mask. +} + + +// Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to +// appropriately set the pin logic according to setting for normal-high/normal-low operation +// and the probing cycle modes for toward-workpiece/away-from-workpiece. +void probe_configure_invert_mask(uint8_t is_probe_away) +{ + probe_invert_mask = 0; // Initialize as zero. + if (bit_isfalse(settings.flags,BITFLAG_INVERT_PROBE_PIN)) { probe_invert_mask ^= PROBE_MASK; } + if (is_probe_away) { probe_invert_mask ^= PROBE_MASK; } +} + + +// Returns the probe pin state. Triggered = true. Called by gcode parser and probe state monitor. +uint8_t probe_get_state() { return((PROBE_PIN & PROBE_MASK) ^ probe_invert_mask); } + + +// Monitors probe pin state and records the system position when detected. Called by the +// stepper ISR per ISR tick. +// NOTE: This function must be extremely efficient as to not bog down the stepper ISR. +void probe_state_monitor() +{ + if (probe_get_state()) { + sys_probe_state = PROBE_OFF; + memcpy(sys_probe_position, sys_position, sizeof(sys_position)); + bit_true(sys_rt_exec_state, EXEC_MOTION_CANCEL); + } +} diff --git a/grbl/probe.h b/grbl/probe.h new file mode 100644 index 0000000..03d5fd3 --- /dev/null +++ b/grbl/probe.h @@ -0,0 +1,43 @@ +/* + probe.h - code pertaining to probing methods + Part of Grbl + + Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef probe_h +#define probe_h + +// Values that define the probing state machine. +#define PROBE_OFF 0 // Probing disabled or not in use. (Must be zero.) +#define PROBE_ACTIVE 1 // Actively watching the input pin. + +// Probe pin initialization routine. +void probe_init(); + +// Called by probe_init() and the mc_probe() routines. Sets up the probe pin invert mask to +// appropriately set the pin logic according to setting for normal-high/normal-low operation +// and the probing cycle modes for toward-workpiece/away-from-workpiece. +void probe_configure_invert_mask(uint8_t is_probe_away); + +// Returns probe pin state. Triggered = true. Called by gcode parser and probe state monitor. +uint8_t probe_get_state(); + +// Monitors probe pin state and records the system position when detected. Called by the +// stepper ISR per ISR tick. +void probe_state_monitor(); + +#endif diff --git a/grbl/protocol.c b/grbl/protocol.c new file mode 100644 index 0000000..08ea48b --- /dev/null +++ b/grbl/protocol.c @@ -0,0 +1,765 @@ +/* + protocol.c - controls Grbl execution protocol and procedures + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + +// Define line flags. Includes comment type tracking and line overflow detection. +#define LINE_FLAG_OVERFLOW bit(0) +#define LINE_FLAG_COMMENT_PARENTHESES bit(1) +#define LINE_FLAG_COMMENT_SEMICOLON bit(2) + + +static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. + +static void protocol_exec_rt_suspend(); + + +/* + GRBL PRIMARY LOOP: +*/ +void protocol_main_loop() +{ + // Perform some machine checks to make sure everything is good to go. + #ifdef CHECK_LIMITS_AT_INIT + if (bit_istrue(settings.flags, BITFLAG_HARD_LIMIT_ENABLE)) { + if (limits_get_state()) { + sys.state = STATE_ALARM; // Ensure alarm state is active. + report_feedback_message(MESSAGE_CHECK_LIMITS); + } + } + #endif + // Check for and report alarm state after a reset, error, or an initial power up. + // NOTE: Sleep mode disables the stepper drivers and position can't be guaranteed. + // Re-initialize the sleep state as an ALARM mode to ensure user homes or acknowledges. + if (sys.state & (STATE_ALARM | STATE_SLEEP)) { + report_feedback_message(MESSAGE_ALARM_LOCK); + sys.state = STATE_ALARM; // Ensure alarm state is set. + } else { + // Check if the safety door is open. + sys.state = STATE_IDLE; + if (system_check_safety_door_ajar()) { + bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR); + protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state. + } + // All systems go! + system_execute_startup(line); // Execute startup script. + } + + // --------------------------------------------------------------------------------- + // Primary loop! Upon a system abort, this exits back to main() to reset the system. + // This is also where Grbl idles while waiting for something to do. + // --------------------------------------------------------------------------------- + + uint8_t line_flags = 0; + uint8_t char_counter = 0; + uint8_t c; + for (;;) { + + // Process one line of incoming serial data, as the data becomes available. Performs an + // initial filtering by removing spaces and comments and capitalizing all letters. + while((c = serial_read()) != SERIAL_NO_DATA) { + if ((c == '\n') || (c == '\r')) { // End of line reached + + protocol_execute_realtime(); // Runtime command check point. + if (sys.abort) { return; } // Bail to calling function upon system abort + + line[char_counter] = 0; // Set string termination character. + #ifdef REPORT_ECHO_LINE_RECEIVED + report_echo_line_received(line); + #endif + + // Direct and execute one line of formatted input, and report status of execution. + if (line_flags & LINE_FLAG_OVERFLOW) { + // Report line overflow error. + report_status_message(STATUS_OVERFLOW); + } else if (line[0] == 0) { + // Empty or comment line. For syncing purposes. + report_status_message(STATUS_OK); + } else if (line[0] == '$') { + // Grbl '$' system command + report_status_message(system_execute_line(line)); + } else if (sys.state & (STATE_ALARM | STATE_JOG)) { + // Everything else is gcode. Block if in alarm or jog mode. + report_status_message(STATUS_SYSTEM_GC_LOCK); + } else { + // Parse and execute g-code block. + report_status_message(gc_execute_line(line)); + } + + // Reset tracking data for next line. + line_flags = 0; + char_counter = 0; + + } else { + + if (line_flags) { + // Throw away all (except EOL) comment characters and overflow characters. + if (c == ')') { + // End of '()' comment. Resume line allowed. + if (line_flags & LINE_FLAG_COMMENT_PARENTHESES) { line_flags &= ~(LINE_FLAG_COMMENT_PARENTHESES); } + } + } else { + if (c <= ' ') { + // Throw away whitepace and control characters + } else if (c == '/') { + // Block delete NOT SUPPORTED. Ignore character. + // NOTE: If supported, would simply need to check the system if block delete is enabled. + } else if (c == '(') { + // Enable comments flag and ignore all characters until ')' or EOL. + // NOTE: This doesn't follow the NIST definition exactly, but is good enough for now. + // In the future, we could simply remove the items within the comments, but retain the + // comment control characters, so that the g-code parser can error-check it. + line_flags |= LINE_FLAG_COMMENT_PARENTHESES; + } else if (c == ';') { + // NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST. + line_flags |= LINE_FLAG_COMMENT_SEMICOLON; + // TODO: Install '%' feature + // } else if (c == '%') { + // Program start-end percent sign NOT SUPPORTED. + // NOTE: This maybe installed to tell Grbl when a program is running vs manual input, + // where, during a program, the system auto-cycle start will continue to execute + // everything until the next '%' sign. This will help fix resuming issues with certain + // functions that empty the planner buffer to execute its task on-time. + } else if (char_counter >= (LINE_BUFFER_SIZE-1)) { + // Detect line buffer overflow and set flag. + line_flags |= LINE_FLAG_OVERFLOW; + } else if (c >= 'a' && c <= 'z') { // Upcase lowercase + line[char_counter++] = c-'a'+'A'; + } else { + line[char_counter++] = c; + } + } + + } + } + + // If there are no more characters in the serial read buffer to be processed and executed, + // this indicates that g-code streaming has either filled the planner buffer or has + // completed. In either case, auto-cycle start, if enabled, any queued moves. + protocol_auto_cycle_start(); + + protocol_execute_realtime(); // Runtime command check point. + if (sys.abort) { return; } // Bail to main() program loop to reset system. + } + + return; /* Never reached */ +} + + +// Block until all buffered steps are executed or in a cycle state. Works with feed hold +// during a synchronize call, if it should happen. Also, waits for clean cycle end. +void protocol_buffer_synchronize() +{ + // If system is queued, ensure cycle resumes if the auto start flag is present. + protocol_auto_cycle_start(); + do { + protocol_execute_realtime(); // Check and execute run-time commands + if (sys.abort) { return; } // Check for system abort + } while (plan_get_current_block() || (sys.state == STATE_CYCLE)); +} + + +// Auto-cycle start triggers when there is a motion ready to execute and if the main program is not +// actively parsing commands. +// NOTE: This function is called from the main loop, buffer sync, and mc_line() only and executes +// when one of these conditions exist respectively: There are no more blocks sent (i.e. streaming +// is finished, single commands), a command that needs to wait for the motions in the buffer to +// execute calls a buffer sync, or the planner buffer is full and ready to go. +void protocol_auto_cycle_start() +{ + if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer. + system_set_exec_state_flag(EXEC_CYCLE_START); // If so, execute them! + } +} + + +// This function is the general interface to Grbl's real-time command execution system. It is called +// from various check points in the main program, primarily where there may be a while loop waiting +// for a buffer to clear space or any point where the execution time from the last check point may +// be more than a fraction of a second. This is a way to execute realtime commands asynchronously +// (aka multitasking) with grbl's g-code parsing and planning functions. This function also serves +// as an interface for the interrupts to set the system realtime flags, where only the main program +// handles them, removing the need to define more computationally-expensive volatile variables. This +// also provides a controlled way to execute certain tasks without having two or more instances of +// the same task, such as the planner recalculating the buffer upon a feedhold or overrides. +// NOTE: The sys_rt_exec_state variable flags are set by any process, step or serial interrupts, pinouts, +// limit switches, or the main program. +void protocol_execute_realtime() +{ + protocol_exec_rt_system(); + if (sys.suspend) { protocol_exec_rt_suspend(); } +} + + +// Executes run-time commands, when required. This function primarily operates as Grbl's state +// machine and controls the various real-time features Grbl has to offer. +// NOTE: Do not alter this unless you know exactly what you are doing! +void protocol_exec_rt_system() +{ + uint8_t rt_exec; // Temp variable to avoid calling volatile multiple times. + rt_exec = sys_rt_exec_alarm; // Copy volatile sys_rt_exec_alarm. + if (rt_exec) { // Enter only if any bit flag is true + // System alarm. Everything has shutdown by something that has gone severely wrong. Report + // the source of the error to the user. If critical, Grbl disables by entering an infinite + // loop until system reset/abort. + sys.state = STATE_ALARM; // Set system alarm state + report_alarm_message(rt_exec); + // Halt everything upon a critical event flag. Currently hard and soft limits flag this. + if ((rt_exec == EXEC_ALARM_HARD_LIMIT) || (rt_exec == EXEC_ALARM_SOFT_LIMIT)) { + report_feedback_message(MESSAGE_CRITICAL_EVENT); + system_clear_exec_state_flag(EXEC_RESET); // Disable any existing reset + do { + // Block everything, except reset and status reports, until user issues reset or power + // cycles. Hard limits typically occur while unattended or not paying attention. Gives + // the user and a GUI time to do what is needed before resetting, like killing the + // incoming stream. The same could be said about soft limits. While the position is not + // lost, continued streaming could cause a serious crash if by chance it gets executed. + } while (bit_isfalse(sys_rt_exec_state,EXEC_RESET)); + } + system_clear_exec_alarm(); // Clear alarm + } + + rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state. + if (rt_exec) { + + // Execute system abort. + if (rt_exec & EXEC_RESET) { + sys.abort = true; // Only place this is set true. + return; // Nothing else to do but exit. + } + + // Execute and serial print status + if (rt_exec & EXEC_STATUS_REPORT) { + report_realtime_status(); + system_clear_exec_state_flag(EXEC_STATUS_REPORT); + } + + // NOTE: Once hold is initiated, the system immediately enters a suspend state to block all + // main program processes until either reset or resumed. This ensures a hold completes safely. + if (rt_exec & (EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP)) { + + // State check for allowable states for hold methods. + if (!(sys.state & (STATE_ALARM | STATE_CHECK_MODE))) { + + // If in CYCLE or JOG states, immediately initiate a motion HOLD. + if (sys.state & (STATE_CYCLE | STATE_JOG)) { + if (!(sys.suspend & (SUSPEND_MOTION_CANCEL | SUSPEND_JOG_CANCEL))) { // Block, if already holding. + st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. + sys.step_control = STEP_CONTROL_EXECUTE_HOLD; // Initiate suspend state with active flag. + if (sys.state == STATE_JOG) { // Jog cancelled upon any hold event, except for sleeping. + if (!(rt_exec & EXEC_SLEEP)) { sys.suspend |= SUSPEND_JOG_CANCEL; } + } + } + } + // If IDLE, Grbl is not in motion. Simply indicate suspend state and hold is complete. + if (sys.state == STATE_IDLE) { sys.suspend = SUSPEND_HOLD_COMPLETE; } + + // Execute and flag a motion cancel with deceleration and return to idle. Used primarily by probing cycle + // to halt and cancel the remainder of the motion. + if (rt_exec & EXEC_MOTION_CANCEL) { + // MOTION_CANCEL only occurs during a CYCLE, but a HOLD and SAFETY_DOOR may been initiated beforehand + // to hold the CYCLE. Motion cancel is valid for a single planner block motion only, while jog cancel + // will handle and clear multiple planner block motions. + if (!(sys.state & STATE_JOG)) { sys.suspend |= SUSPEND_MOTION_CANCEL; } // NOTE: State is STATE_CYCLE. + } + + // Execute a feed hold with deceleration, if required. Then, suspend system. + if (rt_exec & EXEC_FEED_HOLD) { + // Block SAFETY_DOOR, JOG, and SLEEP states from changing to HOLD state. + if (!(sys.state & (STATE_SAFETY_DOOR | STATE_JOG | STATE_SLEEP))) { sys.state = STATE_HOLD; } + } + + // Execute a safety door stop with a feed hold and disable spindle/coolant. + // NOTE: Safety door differs from feed holds by stopping everything no matter state, disables powered + // devices (spindle/coolant), and blocks resuming until switch is re-engaged. + if (rt_exec & EXEC_SAFETY_DOOR) { + report_feedback_message(MESSAGE_SAFETY_DOOR_AJAR); + // If jogging, block safety door methods until jog cancel is complete. Just flag that it happened. + if (!(sys.suspend & SUSPEND_JOG_CANCEL)) { + // Check if the safety re-opened during a restore parking motion only. Ignore if + // already retracting, parked or in sleep state. + if (sys.state == STATE_SAFETY_DOOR) { + if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring + #ifdef PARKING_ENABLE + // Set hold and reset appropriate control flags to restart parking sequence. + if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { + st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. + sys.step_control = (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION); + sys.suspend &= ~(SUSPEND_HOLD_COMPLETE); + } // else NO_MOTION is active. + #endif + sys.suspend &= ~(SUSPEND_RETRACT_COMPLETE | SUSPEND_INITIATE_RESTORE | SUSPEND_RESTORE_COMPLETE); + sys.suspend |= SUSPEND_RESTART_RETRACT; + } + } + if (sys.state != STATE_SLEEP) { sys.state = STATE_SAFETY_DOOR; } + } + // NOTE: This flag doesn't change when the door closes, unlike sys.state. Ensures any parking motions + // are executed if the door switch closes and the state returns to HOLD. + sys.suspend |= SUSPEND_SAFETY_DOOR_AJAR; + } + + } + + if (rt_exec & EXEC_SLEEP) { + if (sys.state == STATE_ALARM) { sys.suspend |= (SUSPEND_RETRACT_COMPLETE|SUSPEND_HOLD_COMPLETE); } + sys.state = STATE_SLEEP; + } + + system_clear_exec_state_flag((EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP)); + } + + // Execute a cycle start by starting the stepper interrupt to begin executing the blocks in queue. + if (rt_exec & EXEC_CYCLE_START) { + // Block if called at same time as the hold commands: feed hold, motion cancel, and safety door. + // Ensures auto-cycle-start doesn't resume a hold without an explicit user-input. + if (!(rt_exec & (EXEC_FEED_HOLD | EXEC_MOTION_CANCEL | EXEC_SAFETY_DOOR))) { + // Resume door state when parking motion has retracted and door has been closed. + if ((sys.state == STATE_SAFETY_DOOR) && !(sys.suspend & SUSPEND_SAFETY_DOOR_AJAR)) { + if (sys.suspend & SUSPEND_RESTORE_COMPLETE) { + sys.state = STATE_IDLE; // Set to IDLE to immediately resume the cycle. + } else if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { + // Flag to re-energize powered components and restore original position, if disabled by SAFETY_DOOR. + // NOTE: For a safety door to resume, the switch must be closed, as indicated by HOLD state, and + // the retraction execution is complete, which implies the initial feed hold is not active. To + // restore normal operation, the restore procedures must be initiated by the following flag. Once, + // they are complete, it will call CYCLE_START automatically to resume and exit the suspend. + sys.suspend |= SUSPEND_INITIATE_RESTORE; + } + } + // Cycle start only when IDLE or when a hold is complete and ready to resume. + if ((sys.state == STATE_IDLE) || ((sys.state & STATE_HOLD) && (sys.suspend & SUSPEND_HOLD_COMPLETE))) { + if (sys.state == STATE_HOLD && sys.spindle_stop_ovr) { + sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after. + } else { + // Start cycle only if queued motions exist in planner buffer and the motion is not canceled. + sys.step_control = STEP_CONTROL_NORMAL_OP; // Restore step control to normal operation + if (plan_get_current_block() && bit_isfalse(sys.suspend,SUSPEND_MOTION_CANCEL)) { + sys.suspend = SUSPEND_DISABLE; // Break suspend state. + sys.state = STATE_CYCLE; + st_prep_buffer(); // Initialize step segment buffer before beginning cycle. + st_wake_up(); + } else { // Otherwise, do nothing. Set and resume IDLE state. + sys.suspend = SUSPEND_DISABLE; // Break suspend state. + sys.state = STATE_IDLE; + } + } + } + } + system_clear_exec_state_flag(EXEC_CYCLE_START); + } + + if (rt_exec & EXEC_CYCLE_STOP) { + // Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by + // realtime command execution in the main program, ensuring that the planner re-plans safely. + // NOTE: Bresenham algorithm variables are still maintained through both the planner and stepper + // cycle reinitializations. The stepper path should continue exactly as if nothing has happened. + // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes. + if ((sys.state & (STATE_HOLD|STATE_SAFETY_DOOR|STATE_SLEEP)) && !(sys.soft_limit) && !(sys.suspend & SUSPEND_JOG_CANCEL)) { + // Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user + // has issued a resume command or reset. + plan_cycle_reinitialize(); + if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { sys.suspend |= SUSPEND_HOLD_COMPLETE; } + bit_false(sys.step_control,(STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION)); + } else { + // Motion complete. Includes CYCLE/JOG/HOMING states and jog cancel/motion cancel/soft limit events. + // NOTE: Motion and jog cancel both immediately return to idle after the hold completes. + if (sys.suspend & SUSPEND_JOG_CANCEL) { // For jog cancel, flush buffers and sync positions. + sys.step_control = STEP_CONTROL_NORMAL_OP; + plan_reset(); + st_reset(); + gc_sync_position(); + plan_sync_position(); + } + if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog. + sys.suspend &= ~(SUSPEND_JOG_CANCEL); + sys.suspend |= SUSPEND_HOLD_COMPLETE; + sys.state = STATE_SAFETY_DOOR; + } else { + sys.suspend = SUSPEND_DISABLE; + sys.state = STATE_IDLE; + } + } + system_clear_exec_state_flag(EXEC_CYCLE_STOP); + } + } + + // Execute overrides. + rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override + if (rt_exec) { + system_clear_exec_motion_overrides(); // Clear all motion override flags. + + uint8_t new_f_override = sys.f_override; + if (rt_exec & EXEC_FEED_OVR_RESET) { new_f_override = DEFAULT_FEED_OVERRIDE; } + if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) { new_f_override += FEED_OVERRIDE_COARSE_INCREMENT; } + if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) { new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT; } + if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) { new_f_override += FEED_OVERRIDE_FINE_INCREMENT; } + if (rt_exec & EXEC_FEED_OVR_FINE_MINUS) { new_f_override -= FEED_OVERRIDE_FINE_INCREMENT; } + new_f_override = min(new_f_override,MAX_FEED_RATE_OVERRIDE); + new_f_override = max(new_f_override,MIN_FEED_RATE_OVERRIDE); + + uint8_t new_r_override = sys.r_override; + if (rt_exec & EXEC_RAPID_OVR_RESET) { new_r_override = DEFAULT_RAPID_OVERRIDE; } + if (rt_exec & EXEC_RAPID_OVR_MEDIUM) { new_r_override = RAPID_OVERRIDE_MEDIUM; } + if (rt_exec & EXEC_RAPID_OVR_LOW) { new_r_override = RAPID_OVERRIDE_LOW; } + + if ((new_f_override != sys.f_override) || (new_r_override != sys.r_override)) { + sys.f_override = new_f_override; + sys.r_override = new_r_override; + sys.report_ovr_counter = 0; // Set to report change immediately + plan_update_velocity_profile_parameters(); + plan_cycle_reinitialize(); + } + } + + rt_exec = sys_rt_exec_accessory_override; + if (rt_exec) { + system_clear_exec_accessory_overrides(); // Clear all accessory override flags. + + // NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization. + uint8_t last_s_override = sys.spindle_speed_ovr; + if (rt_exec & EXEC_SPINDLE_OVR_RESET) { last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE; } + if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) { last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT; } + if (rt_exec & EXEC_SPINDLE_OVR_COARSE_MINUS) { last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT; } + if (rt_exec & EXEC_SPINDLE_OVR_FINE_PLUS) { last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT; } + if (rt_exec & EXEC_SPINDLE_OVR_FINE_MINUS) { last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT; } + last_s_override = min(last_s_override,MAX_SPINDLE_SPEED_OVERRIDE); + last_s_override = max(last_s_override,MIN_SPINDLE_SPEED_OVERRIDE); + + if (last_s_override != sys.spindle_speed_ovr) { + sys.spindle_speed_ovr = last_s_override; + // NOTE: Spindle speed overrides during HOLD state are taken care of by suspend function. + if (sys.state == STATE_IDLE) { spindle_set_state(gc_state.modal.spindle, gc_state.spindle_speed); } + else { bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); } + sys.report_ovr_counter = 0; // Set to report change immediately + } + + if (rt_exec & EXEC_SPINDLE_OVR_STOP) { + // Spindle stop override allowed only while in HOLD state. + // NOTE: Report counters are set in spindle_set_state() when spindle stop is executed. + if (sys.state == STATE_HOLD) { + if (!(sys.spindle_stop_ovr)) { sys.spindle_stop_ovr = SPINDLE_STOP_OVR_INITIATE; } + else if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_ENABLED) { sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE; } + } + } + + // NOTE: Since coolant state always performs a planner sync whenever it changes, the current + // run state can be determined by checking the parser state. + // NOTE: Coolant overrides only operate during IDLE, CYCLE, HOLD, and JOG states. Ignored otherwise. + if (rt_exec & (EXEC_COOLANT_FLOOD_OVR_TOGGLE | EXEC_COOLANT_MIST_OVR_TOGGLE)) { + if ((sys.state == STATE_IDLE) || (sys.state & (STATE_CYCLE | STATE_HOLD | STATE_JOG))) { + uint8_t coolant_state = gc_state.modal.coolant; + #ifdef ENABLE_M7 + if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) { + if (coolant_state & COOLANT_MIST_ENABLE) { bit_false(coolant_state,COOLANT_MIST_ENABLE); } + else { coolant_state |= COOLANT_MIST_ENABLE; } + } + if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) { + if (coolant_state & COOLANT_FLOOD_ENABLE) { bit_false(coolant_state,COOLANT_FLOOD_ENABLE); } + else { coolant_state |= COOLANT_FLOOD_ENABLE; } + } + #else + if (coolant_state & COOLANT_FLOOD_ENABLE) { bit_false(coolant_state,COOLANT_FLOOD_ENABLE); } + else { coolant_state |= COOLANT_FLOOD_ENABLE; } + #endif + coolant_set_state(coolant_state); // Report counter set in coolant_set_state(). + gc_state.modal.coolant = coolant_state; + } + } + } + + #ifdef DEBUG + if (sys_rt_exec_debug) { + report_realtime_debug(); + sys_rt_exec_debug = 0; + } + #endif + + // Reload step segment buffer + if (sys.state & (STATE_CYCLE | STATE_HOLD | STATE_SAFETY_DOOR | STATE_HOMING | STATE_SLEEP| STATE_JOG)) { + st_prep_buffer(); + } + +} + + +// Handles Grbl system suspend procedures, such as feed hold, safety door, and parking motion. +// The system will enter this loop, create local variables for suspend tasks, and return to +// whatever function that invoked the suspend, such that Grbl resumes normal operation. +// This function is written in a way to promote custom parking motions. Simply use this as a +// template +static void protocol_exec_rt_suspend() +{ + #ifdef PARKING_ENABLE + // Declare and initialize parking local variables + float restore_target[N_AXIS]; + float parking_target[N_AXIS]; + float retract_waypoint = PARKING_PULLOUT_INCREMENT; + plan_line_data_t plan_data; + plan_line_data_t *pl_data = &plan_data; + memset(pl_data,0,sizeof(plan_line_data_t)); + pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE); + #ifdef USE_LINE_NUMBERS + pl_data->line_number = PARKING_MOTION_LINE_NUMBER; + #endif + #endif + + plan_block_t *block = plan_get_current_block(); + uint8_t restore_condition; + #ifdef VARIABLE_SPINDLE + float restore_spindle_speed; + if (block == NULL) { + restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); + restore_spindle_speed = gc_state.spindle_speed; + } else { + restore_condition = (block->condition & PL_COND_SPINDLE_MASK) | coolant_get_state(); + restore_spindle_speed = block->spindle_speed; + } + #ifdef DISABLE_LASER_DURING_HOLD + if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { + system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); + } + #endif + #else + if (block == NULL) { restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); } + else { restore_condition = (block->condition & PL_COND_SPINDLE_MASK) | coolant_get_state(); } + #endif + + while (sys.suspend) { + + if (sys.abort) { return; } + + // Block until initial hold is complete and the machine has stopped motion. + if (sys.suspend & SUSPEND_HOLD_COMPLETE) { + + // Parking manager. Handles de/re-energizing, switch state checks, and parking motions for + // the safety door and sleep states. + if (sys.state & (STATE_SAFETY_DOOR | STATE_SLEEP)) { + + // Handles retraction motions and de-energizing. + if (bit_isfalse(sys.suspend,SUSPEND_RETRACT_COMPLETE)) { + + // Ensure any prior spindle stop override is disabled at start of safety door routine. + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; + + #ifndef PARKING_ENABLE + + spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize + + #else + + // Get current position and store restore location and spindle retract waypoint. + system_convert_array_steps_to_mpos(parking_target,sys_position); + if (bit_isfalse(sys.suspend,SUSPEND_RESTART_RETRACT)) { + memcpy(restore_target,parking_target,sizeof(parking_target)); + retract_waypoint += restore_target[PARKING_AXIS]; + retract_waypoint = min(retract_waypoint,PARKING_TARGET); + } + + // Execute slow pull-out parking retract motion. Parking requires homing enabled, the + // current location not exceeding the parking target location, and laser mode disabled. + // NOTE: State is will remain DOOR, until the de-energizing and retract is complete. + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if ((bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) && + (parking_target[PARKING_AXIS] < PARKING_TARGET) && + bit_isfalse(settings.flags,BITFLAG_LASER_MODE) && + (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { + #else + if ((bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) && + (parking_target[PARKING_AXIS] < PARKING_TARGET) && + bit_isfalse(settings.flags,BITFLAG_LASER_MODE)) { + #endif + // Retract spindle by pullout distance. Ensure retraction motion moves away from + // the workpiece and waypoint motion doesn't exceed the parking target location. + if (parking_target[PARKING_AXIS] < retract_waypoint) { + parking_target[PARKING_AXIS] = retract_waypoint; + pl_data->feed_rate = PARKING_PULLOUT_RATE; + pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Retain accessory state + pl_data->spindle_speed = restore_spindle_speed; + mc_parking_motion(parking_target, pl_data); + } + + // NOTE: Clear accessory state after retract and after an aborted restore motion. + pl_data->condition = (PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE); + pl_data->spindle_speed = 0.0; + spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize + + // Execute fast parking retract motion to parking target location. + if (parking_target[PARKING_AXIS] < PARKING_TARGET) { + parking_target[PARKING_AXIS] = PARKING_TARGET; + pl_data->feed_rate = PARKING_RATE; + mc_parking_motion(parking_target, pl_data); + } + + } else { + + // Parking motion not possible. Just disable the spindle and coolant. + // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately. + spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize + + } + + #endif + + sys.suspend &= ~(SUSPEND_RESTART_RETRACT); + sys.suspend |= SUSPEND_RETRACT_COMPLETE; + + } else { + + + if (sys.state == STATE_SLEEP) { + report_feedback_message(MESSAGE_SLEEP_MODE); + // Spindle and coolant should already be stopped, but do it again just to be sure. + spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize + coolant_set_state(COOLANT_DISABLE); // De-energize + st_go_idle(); // Disable steppers + while (!(sys.abort)) { protocol_exec_rt_system(); } // Do nothing until reset. + return; // Abort received. Return to re-initialize. + } + + // Allows resuming from parking/safety door. Actively checks if safety door is closed and ready to resume. + if (sys.state == STATE_SAFETY_DOOR) { + if (!(system_check_safety_door_ajar())) { + sys.suspend &= ~(SUSPEND_SAFETY_DOOR_AJAR); // Reset door ajar flag to denote ready to resume. + } + } + + // Handles parking restore and safety door resume. + if (sys.suspend & SUSPEND_INITIATE_RESTORE) { + + #ifdef PARKING_ENABLE + // Execute fast restore motion to the pull-out position. Parking requires homing enabled. + // NOTE: State is will remain DOOR, until the de-energizing and retract is complete. + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if (((settings.flags & (BITFLAG_HOMING_ENABLE|BITFLAG_LASER_MODE)) == BITFLAG_HOMING_ENABLE) && + (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { + #else + if ((settings.flags & (BITFLAG_HOMING_ENABLE|BITFLAG_LASER_MODE)) == BITFLAG_HOMING_ENABLE) { + #endif + // Check to ensure the motion doesn't move below pull-out position. + if (parking_target[PARKING_AXIS] <= PARKING_TARGET) { + parking_target[PARKING_AXIS] = retract_waypoint; + pl_data->feed_rate = PARKING_RATE; + mc_parking_motion(parking_target, pl_data); + } + } + #endif + + // Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle. + if (gc_state.modal.spindle != SPINDLE_DISABLE) { + // Block if safety door re-opened during prior restore actions. + if (bit_isfalse(sys.suspend,SUSPEND_RESTART_RETRACT)) { + if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { + // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + } else { + spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); + } + } + } + if (gc_state.modal.coolant != COOLANT_DISABLE) { + // Block if safety door re-opened during prior restore actions. + if (bit_isfalse(sys.suspend,SUSPEND_RESTART_RETRACT)) { + // NOTE: Laser mode will honor this delay. An exhaust system is often controlled by this pin. + coolant_set_state((restore_condition & (PL_COND_FLAG_COOLANT_FLOOD | PL_COND_FLAG_COOLANT_MIST))); + delay_sec(SAFETY_DOOR_COOLANT_DELAY, DELAY_MODE_SYS_SUSPEND); + } + } + + #ifdef PARKING_ENABLE + // Execute slow plunge motion from pull-out position to resume position. + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if (((settings.flags & (BITFLAG_HOMING_ENABLE|BITFLAG_LASER_MODE)) == BITFLAG_HOMING_ENABLE) && + (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) { + #else + if ((settings.flags & (BITFLAG_HOMING_ENABLE|BITFLAG_LASER_MODE)) == BITFLAG_HOMING_ENABLE) { + #endif + // Block if safety door re-opened during prior restore actions. + if (bit_isfalse(sys.suspend,SUSPEND_RESTART_RETRACT)) { + // Regardless if the retract parking motion was a valid/safe motion or not, the + // restore parking motion should logically be valid, either by returning to the + // original position through valid machine space or by not moving at all. + pl_data->feed_rate = PARKING_PULLOUT_RATE; + pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Restore accessory state + pl_data->spindle_speed = restore_spindle_speed; + mc_parking_motion(restore_target, pl_data); + } + } + #endif + + if (bit_isfalse(sys.suspend,SUSPEND_RESTART_RETRACT)) { + sys.suspend |= SUSPEND_RESTORE_COMPLETE; + system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. + } + } + + } + + + } else { + + // Feed hold manager. Controls spindle stop override states. + // NOTE: Hold ensured as completed by condition check at the beginning of suspend routine. + if (sys.spindle_stop_ovr) { + // Handles beginning of spindle stop + if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { + if (gc_state.modal.spindle != SPINDLE_DISABLE) { + spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. + } else { + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state + } + // Handles restoring of spindle state + } else if (sys.spindle_stop_ovr & (SPINDLE_STOP_OVR_RESTORE | SPINDLE_STOP_OVR_RESTORE_CYCLE)) { + if (gc_state.modal.spindle != SPINDLE_DISABLE) { + report_feedback_message(MESSAGE_SPINDLE_RESTORE); + if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { + // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + } else { + spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + } + } + if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { + system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. + } + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state + } + } else { + // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. + // NOTE: STEP_CONTROL_UPDATE_SPINDLE_PWM is automatically reset upon resume in step generator. + if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM)) { + spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); + } + } + + } + } + + protocol_exec_rt_system(); + + } +} diff --git a/grbl/protocol.h b/grbl/protocol.h new file mode 100644 index 0000000..7bc6e92 --- /dev/null +++ b/grbl/protocol.h @@ -0,0 +1,49 @@ +/* + protocol.h - controls Grbl execution protocol and procedures + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef protocol_h +#define protocol_h + +// Line buffer size from the serial input stream to be executed. +// NOTE: Not a problem except for extreme cases, but the line buffer size can be too small +// and g-code blocks can get truncated. Officially, the g-code standards support up to 256 +// characters. In future versions, this will be increased, when we know how much extra +// memory space we can invest into here or we re-write the g-code parser not to have this +// buffer. +#ifndef LINE_BUFFER_SIZE + #define LINE_BUFFER_SIZE 80 +#endif + +// Starts Grbl main loop. It handles all incoming characters from the serial port and executes +// them as they complete. It is also responsible for finishing the initialization procedures. +void protocol_main_loop(); + +// Checks and executes a realtime command at various stop points in main program +void protocol_execute_realtime(); +void protocol_exec_rt_system(); + +// Executes the auto cycle feature, if enabled. +void protocol_auto_cycle_start(); + +// Block until all buffered steps are executed +void protocol_buffer_synchronize(); + +#endif diff --git a/grbl/report.c b/grbl/report.c new file mode 100644 index 0000000..000836f --- /dev/null +++ b/grbl/report.c @@ -0,0 +1,662 @@ +/* + report.c - reporting and messaging methods + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +/* + This file functions as the primary feedback interface for Grbl. Any outgoing data, such + as the protocol status messages, feedback messages, and status reports, are stored here. + For the most part, these functions primarily are called from protocol.c methods. If a + different style feedback is desired (i.e. JSON), then a user can change these following + methods to accomodate their needs. +*/ + +#include "grbl.h" + + +// Internal report utilities to reduce flash with repetitive tasks turned into functions. +void report_util_setting_prefix(uint8_t n) { serial_write('$'); print_uint8_base10(n); serial_write('='); } +static void report_util_line_feed() { printPgmString(PSTR("\r\n")); } +static void report_util_feedback_line_feed() { serial_write(']'); report_util_line_feed(); } +static void report_util_gcode_modes_G() { printPgmString(PSTR(" G")); } +static void report_util_gcode_modes_M() { printPgmString(PSTR(" M")); } +// static void report_util_comment_line_feed() { serial_write(')'); report_util_line_feed(); } +static void report_util_axis_values(float *axis_value) { + uint8_t idx; + for (idx=0; idx= AXIS_SETTINGS_INCREMENT) { + n -= AXIS_SETTINGS_INCREMENT; + idx++; + } + serial_write(n+'x'); + switch (idx) { + case 0: printPgmString(PSTR(":stp/mm")); break; + case 1: printPgmString(PSTR(":mm/min")); break; + case 2: printPgmString(PSTR(":mm/s^2")); break; + case 3: printPgmString(PSTR(":mm max")); break; + } + break; + } + report_util_comment_line_feed(); +} +*/ + +static void report_util_uint8_setting(uint8_t n, int val) { + report_util_setting_prefix(n); + print_uint8_base10(val); + report_util_line_feed(); // report_util_setting_string(n); +} +static void report_util_float_setting(uint8_t n, float val, uint8_t n_decimal) { + report_util_setting_prefix(n); + printFloat(val,n_decimal); + report_util_line_feed(); // report_util_setting_string(n); +} + + +// Handles the primary confirmation protocol response for streaming interfaces and human-feedback. +// For every incoming line, this method responds with an 'ok' for a successful command or an +// 'error:' to indicate some error event with the line or some critical system error during +// operation. Errors events can originate from the g-code parser, settings module, or asynchronously +// from a critical error, such as a triggered hard limit. Interface should always monitor for these +// responses. +void report_status_message(uint8_t status_code) +{ + switch(status_code) { + case STATUS_OK: // STATUS_OK + printPgmString(PSTR("ok\r\n")); break; + default: + printPgmString(PSTR("error:")); + print_uint8_base10(status_code); + report_util_line_feed(); + } +} + +// Prints alarm messages. +void report_alarm_message(uint8_t alarm_code) +{ + printPgmString(PSTR("ALARM:")); + print_uint8_base10(alarm_code); + report_util_line_feed(); + delay_ms(500); // Force delay to ensure message clears serial write buffer. +} + +// Prints feedback messages. This serves as a centralized method to provide additional +// user feedback for things that are not of the status/alarm message protocol. These are +// messages such as setup warnings, switch toggling, and how to exit alarms. +// NOTE: For interfaces, messages are always placed within brackets. And if silent mode +// is installed, the message number codes are less than zero. +void report_feedback_message(uint8_t message_code) +{ + printPgmString(PSTR("[MSG:")); + switch(message_code) { + case MESSAGE_CRITICAL_EVENT: + printPgmString(PSTR("Reset to continue")); break; + case MESSAGE_ALARM_LOCK: + printPgmString(PSTR("'$H'|'$X' to unlock")); break; + case MESSAGE_ALARM_UNLOCK: + printPgmString(PSTR("Caution: Unlocked")); break; + case MESSAGE_ENABLED: + printPgmString(PSTR("Enabled")); break; + case MESSAGE_DISABLED: + printPgmString(PSTR("Disabled")); break; + case MESSAGE_SAFETY_DOOR_AJAR: + printPgmString(PSTR("Check Door")); break; + case MESSAGE_CHECK_LIMITS: + printPgmString(PSTR("Check Limits")); break; + case MESSAGE_PROGRAM_END: + printPgmString(PSTR("Pgm End")); break; + case MESSAGE_RESTORE_DEFAULTS: + printPgmString(PSTR("Restoring defaults")); break; + case MESSAGE_SPINDLE_RESTORE: + printPgmString(PSTR("Restoring spindle")); break; + case MESSAGE_SLEEP_MODE: + printPgmString(PSTR("Sleeping")); break; + } + report_util_feedback_line_feed(); +} + + +// Welcome message +void report_init_message() +{ + printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n")); +} + +// Grbl help message +void report_grbl_help() { + printPgmString(PSTR("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n")); +} + + +// Grbl global settings print out. +// NOTE: The numbering scheme here must correlate to storing in settings.c +void report_grbl_settings() { + // Print Grbl settings. + report_util_uint8_setting(0,settings.pulse_microseconds); + report_util_uint8_setting(1,settings.stepper_idle_lock_time); + report_util_uint8_setting(2,settings.step_invert_mask); + report_util_uint8_setting(3,settings.dir_invert_mask); + report_util_uint8_setting(4,bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); + report_util_uint8_setting(5,bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)); + report_util_uint8_setting(6,bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN)); + report_util_uint8_setting(10,settings.status_report_mask); + report_util_float_setting(11,settings.junction_deviation,N_DECIMAL_SETTINGVALUE); + report_util_float_setting(12,settings.arc_tolerance,N_DECIMAL_SETTINGVALUE); + report_util_uint8_setting(13,bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); + report_util_uint8_setting(20,bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); + report_util_uint8_setting(21,bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); + report_util_uint8_setting(22,bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); + report_util_uint8_setting(23,settings.homing_dir_mask); + report_util_float_setting(24,settings.homing_feed_rate,N_DECIMAL_SETTINGVALUE); + report_util_float_setting(25,settings.homing_seek_rate,N_DECIMAL_SETTINGVALUE); + report_util_uint8_setting(26,settings.homing_debounce_delay); + report_util_float_setting(27,settings.homing_pulloff,N_DECIMAL_SETTINGVALUE); + report_util_float_setting(30,settings.rpm_max,N_DECIMAL_RPMVALUE); + report_util_float_setting(31,settings.rpm_min,N_DECIMAL_RPMVALUE); + #ifdef VARIABLE_SPINDLE + report_util_uint8_setting(32,bit_istrue(settings.flags,BITFLAG_LASER_MODE)); + #else + report_util_uint8_setting(32,0); + #endif + // Print axis settings + uint8_t idx, set_idx; + uint8_t val = AXIS_SETTINGS_START_VAL; + for (set_idx=0; set_idx= MOTION_MODE_PROBE_TOWARD) { + printPgmString(PSTR("38.")); + print_uint8_base10(gc_state.modal.motion - (MOTION_MODE_PROBE_TOWARD-2)); + } else { + print_uint8_base10(gc_state.modal.motion); + } + + report_util_gcode_modes_G(); + print_uint8_base10(gc_state.modal.coord_select+54); + + report_util_gcode_modes_G(); + print_uint8_base10(gc_state.modal.plane_select+17); + + report_util_gcode_modes_G(); + print_uint8_base10(21-gc_state.modal.units); + + report_util_gcode_modes_G(); + print_uint8_base10(gc_state.modal.distance+90); + + report_util_gcode_modes_G(); + print_uint8_base10(94-gc_state.modal.feed_rate); + + if (gc_state.modal.program_flow) { + report_util_gcode_modes_M(); + switch (gc_state.modal.program_flow) { + case PROGRAM_FLOW_PAUSED : serial_write('0'); break; + // case PROGRAM_FLOW_OPTIONAL_STOP : serial_write('1'); break; // M1 is ignored and not supported. + case PROGRAM_FLOW_COMPLETED_M2 : + case PROGRAM_FLOW_COMPLETED_M30 : + print_uint8_base10(gc_state.modal.program_flow); + break; + } + } + + report_util_gcode_modes_M(); + switch (gc_state.modal.spindle) { + case SPINDLE_ENABLE_CW : serial_write('3'); break; + case SPINDLE_ENABLE_CCW : serial_write('4'); break; + case SPINDLE_DISABLE : serial_write('5'); break; + } + + #ifdef ENABLE_M7 + if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time. + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) { report_util_gcode_modes_M(); serial_write('7'); } + if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_FLOOD) { report_util_gcode_modes_M(); serial_write('8'); } + } else { report_util_gcode_modes_M(); serial_write('9'); } + #else + report_util_gcode_modes_M(); + if (gc_state.modal.coolant) { serial_write('8'); } + else { serial_write('9'); } + #endif + + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) { + report_util_gcode_modes_M(); + print_uint8_base10(56); + } + #endif + + printPgmString(PSTR(" T")); + print_uint8_base10(gc_state.tool); + + printPgmString(PSTR(" F")); + printFloat_RateValue(gc_state.feed_rate); + + #ifdef VARIABLE_SPINDLE + printPgmString(PSTR(" S")); + printFloat(gc_state.spindle_speed,N_DECIMAL_RPMVALUE); + #endif + + report_util_feedback_line_feed(); +} + +// Prints specified startup line +void report_startup_line(uint8_t n, char *line) +{ + printPgmString(PSTR("$N")); + print_uint8_base10(n); + serial_write('='); + printString(line); + report_util_line_feed(); +} + +void report_execute_startup_message(char *line, uint8_t status_code) +{ + serial_write('>'); + printString(line); + serial_write(':'); + report_status_message(status_code); +} + +// Prints build info line +void report_build_info(char *line) +{ + printPgmString(PSTR("[VER:" GRBL_VERSION "." GRBL_VERSION_BUILD ":")); + printString(line); + report_util_feedback_line_feed(); + printPgmString(PSTR("[OPT:")); // Generate compile-time build option list + #ifdef VARIABLE_SPINDLE + serial_write('V'); + #endif + #ifdef USE_LINE_NUMBERS + serial_write('N'); + #endif + #ifdef ENABLE_M7 + serial_write('M'); + #endif + #ifdef COREXY + serial_write('C'); + #endif + #ifdef PARKING_ENABLE + serial_write('P'); + #endif + #ifdef HOMING_FORCE_SET_ORIGIN + serial_write('Z'); + #endif + #ifdef HOMING_SINGLE_AXIS_COMMANDS + serial_write('H'); + #endif + #ifdef LIMITS_TWO_SWITCHES_ON_AXES + serial_write('T'); + #endif + #ifdef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES + serial_write('A'); + #endif + #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN + serial_write('D'); + #endif + #ifdef SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED + serial_write('0'); + #endif + #ifdef ENABLE_SOFTWARE_DEBOUNCE + serial_write('S'); + #endif + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + serial_write('R'); + #endif + #ifndef HOMING_INIT_LOCK + serial_write('L'); + #endif + #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN + serial_write('+'); + #endif + #ifndef ENABLE_RESTORE_EEPROM_WIPE_ALL // NOTE: Shown when disabled. + serial_write('*'); + #endif + #ifndef ENABLE_RESTORE_EEPROM_DEFAULT_SETTINGS // NOTE: Shown when disabled. + serial_write('$'); + #endif + #ifndef ENABLE_RESTORE_EEPROM_CLEAR_PARAMETERS // NOTE: Shown when disabled. + serial_write('#'); + #endif + #ifndef ENABLE_BUILD_INFO_WRITE_COMMAND // NOTE: Shown when disabled. + serial_write('I'); + #endif + #ifndef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE // NOTE: Shown when disabled. + serial_write('E'); + #endif + #ifndef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE // NOTE: Shown when disabled. + serial_write('W'); + #endif + #ifdef ENABLE_DUAL_AXIS + serial_write('2'); + #endif + // NOTE: Compiled values, like override increments/max/min values, may be added at some point later. + serial_write(','); + print_uint8_base10(BLOCK_BUFFER_SIZE-1); + serial_write(','); + print_uint8_base10(RX_BUFFER_SIZE); + + report_util_feedback_line_feed(); +} + + +// Prints the character string line Grbl has received from the user, which has been pre-parsed, +// and has been sent into protocol_execute_line() routine to be executed by Grbl. +void report_echo_line_received(char *line) +{ + printPgmString(PSTR("[echo: ")); printString(line); + report_util_feedback_line_feed(); +} + + + // Prints real-time data. This function grabs a real-time snapshot of the stepper subprogram + // and the actual location of the CNC machine. Users may change the following function to their + // specific needs, but the desired real-time data report must be as short as possible. This is + // requires as it minimizes the computational overhead and allows grbl to keep running smoothly, + // especially during g-code programs with fast, short line segments and high frequency reports (5-20Hz). +void report_realtime_status() +{ + uint8_t idx; + int32_t current_position[N_AXIS]; // Copy current state of the system position variable + memcpy(current_position,sys_position,sizeof(sys_position)); + float print_position[N_AXIS]; + system_convert_array_steps_to_mpos(print_position,current_position); + + // Report current machine state and sub-states + serial_write('<'); + switch (sys.state) { + case STATE_IDLE: printPgmString(PSTR("Idle")); break; + case STATE_CYCLE: printPgmString(PSTR("Run")); break; + case STATE_HOLD: + if (!(sys.suspend & SUSPEND_JOG_CANCEL)) { + printPgmString(PSTR("Hold:")); + if (sys.suspend & SUSPEND_HOLD_COMPLETE) { serial_write('0'); } // Ready to resume + else { serial_write('1'); } // Actively holding + break; + } // Continues to print jog state during jog cancel. + case STATE_JOG: printPgmString(PSTR("Jog")); break; + case STATE_HOMING: printPgmString(PSTR("Home")); break; + case STATE_ALARM: printPgmString(PSTR("Alarm")); break; + case STATE_CHECK_MODE: printPgmString(PSTR("Check")); break; + case STATE_SAFETY_DOOR: + printPgmString(PSTR("Door:")); + if (sys.suspend & SUSPEND_INITIATE_RESTORE) { + serial_write('3'); // Restoring + } else { + if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { + if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { + serial_write('1'); // Door ajar + } else { + serial_write('0'); + } // Door closed and ready to resume + } else { + serial_write('2'); // Retracting + } + } + break; + case STATE_SLEEP: printPgmString(PSTR("Sleep")); break; + } + + float wco[N_AXIS]; + if (bit_isfalse(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE) || + (sys.report_wco_counter == 0) ) { + for (idx=0; idx< N_AXIS; idx++) { + // Apply work coordinate offsets and tool length offset to current position. + wco[idx] = gc_state.coord_system[idx]+gc_state.coord_offset[idx]; + if (idx == TOOL_LENGTH_OFFSET_AXIS) { wco[idx] += gc_state.tool_length_offset; } + if (bit_isfalse(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE)) { + print_position[idx] -= wco[idx]; + } + } + } + + // Report machine position + if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_POSITION_TYPE)) { + printPgmString(PSTR("|MPos:")); + } else { + printPgmString(PSTR("|WPos:")); + } + report_util_axis_values(print_position); + + // Returns planner and serial read buffer states. + #ifdef REPORT_FIELD_BUFFER_STATE + if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_BUFFER_STATE)) { + printPgmString(PSTR("|Bf:")); + print_uint8_base10(plan_get_block_buffer_available()); + serial_write(','); + print_uint8_base10(serial_get_rx_buffer_available()); + } + #endif + + #ifdef USE_LINE_NUMBERS + #ifdef REPORT_FIELD_LINE_NUMBERS + // Report current line number + plan_block_t * cur_block = plan_get_current_block(); + if (cur_block != NULL) { + uint32_t ln = cur_block->line_number; + if (ln > 0) { + printPgmString(PSTR("|Ln:")); + printInteger(ln); + } + } + #endif + #endif + + // Report realtime feed speed + #ifdef REPORT_FIELD_CURRENT_FEED_SPEED + #ifdef VARIABLE_SPINDLE + printPgmString(PSTR("|FS:")); + printFloat_RateValue(st_get_realtime_rate()); + serial_write(','); + printFloat(sys.spindle_speed,N_DECIMAL_RPMVALUE); + #else + printPgmString(PSTR("|F:")); + printFloat_RateValue(st_get_realtime_rate()); + #endif + #endif + + #ifdef REPORT_FIELD_PIN_STATE + uint8_t lim_pin_state = limits_get_state(); + uint8_t ctrl_pin_state = system_control_get_state(); + uint8_t prb_pin_state = probe_get_state(); + if (lim_pin_state | ctrl_pin_state | prb_pin_state) { + printPgmString(PSTR("|Pn:")); + if (prb_pin_state) { serial_write('P'); } + if (lim_pin_state) { + #ifdef ENABLE_DUAL_AXIS + #if (DUAL_AXIS_SELECT == X_AXIS) + if (bit_istrue(lim_pin_state,(bit(X_AXIS)|bit(N_AXIS)))) { serial_write('X'); } + if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); } + #endif + #if (DUAL_AXIS_SELECT == Y_AXIS) + if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); } + if (bit_istrue(lim_pin_state,(bit(Y_AXIS)|bit(N_AXIS)))) { serial_write('Y'); } + #endif + if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); } + #else + if (bit_istrue(lim_pin_state,bit(X_AXIS))) { serial_write('X'); } + if (bit_istrue(lim_pin_state,bit(Y_AXIS))) { serial_write('Y'); } + if (bit_istrue(lim_pin_state,bit(Z_AXIS))) { serial_write('Z'); } + #endif + } + if (ctrl_pin_state) { + #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN + if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_SAFETY_DOOR)) { serial_write('D'); } + #endif + if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_RESET)) { serial_write('R'); } + if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_FEED_HOLD)) { serial_write('H'); } + if (bit_istrue(ctrl_pin_state,CONTROL_PIN_INDEX_CYCLE_START)) { serial_write('S'); } + } + } + #endif + + #ifdef REPORT_FIELD_WORK_COORD_OFFSET + if (sys.report_wco_counter > 0) { sys.report_wco_counter--; } + else { + if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) { + sys.report_wco_counter = (REPORT_WCO_REFRESH_BUSY_COUNT-1); // Reset counter for slow refresh + } else { sys.report_wco_counter = (REPORT_WCO_REFRESH_IDLE_COUNT-1); } + if (sys.report_ovr_counter == 0) { sys.report_ovr_counter = 1; } // Set override on next report. + printPgmString(PSTR("|WCO:")); + report_util_axis_values(wco); + } + #endif + + #ifdef REPORT_FIELD_OVERRIDES + if (sys.report_ovr_counter > 0) { sys.report_ovr_counter--; } + else { + if (sys.state & (STATE_HOMING | STATE_CYCLE | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)) { + sys.report_ovr_counter = (REPORT_OVR_REFRESH_BUSY_COUNT-1); // Reset counter for slow refresh + } else { sys.report_ovr_counter = (REPORT_OVR_REFRESH_IDLE_COUNT-1); } + printPgmString(PSTR("|Ov:")); + print_uint8_base10(sys.f_override); + serial_write(','); + print_uint8_base10(sys.r_override); + serial_write(','); + print_uint8_base10(sys.spindle_speed_ovr); + + uint8_t sp_state = spindle_get_state(); + uint8_t cl_state = coolant_get_state(); + if (sp_state || cl_state) { + printPgmString(PSTR("|A:")); + if (sp_state) { // != SPINDLE_STATE_DISABLE + #ifdef VARIABLE_SPINDLE + #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN + serial_write('S'); // CW + #else + if (sp_state == SPINDLE_STATE_CW) { serial_write('S'); } // CW + else { serial_write('C'); } // CCW + #endif + #else + if (sp_state & SPINDLE_STATE_CW) { serial_write('S'); } // CW + else { serial_write('C'); } // CCW + #endif + } + if (cl_state & COOLANT_STATE_FLOOD) { serial_write('F'); } + #ifdef ENABLE_M7 + if (cl_state & COOLANT_STATE_MIST) { serial_write('M'); } + #endif + } + } + #endif + + serial_write('>'); + report_util_line_feed(); +} + + +#ifdef DEBUG + void report_realtime_debug() + { + + } +#endif diff --git a/grbl/report.h b/grbl/report.h new file mode 100644 index 0000000..f148002 --- /dev/null +++ b/grbl/report.h @@ -0,0 +1,131 @@ +/* + report.h - reporting and messaging methods + Part of Grbl + + Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ +#ifndef report_h +#define report_h + +// Define Grbl status codes. Valid values (0-255) +#define STATUS_OK 0 +#define STATUS_EXPECTED_COMMAND_LETTER 1 +#define STATUS_BAD_NUMBER_FORMAT 2 +#define STATUS_INVALID_STATEMENT 3 +#define STATUS_NEGATIVE_VALUE 4 +#define STATUS_SETTING_DISABLED 5 +#define STATUS_SETTING_STEP_PULSE_MIN 6 +#define STATUS_SETTING_READ_FAIL 7 +#define STATUS_IDLE_ERROR 8 +#define STATUS_SYSTEM_GC_LOCK 9 +#define STATUS_SOFT_LIMIT_ERROR 10 +#define STATUS_OVERFLOW 11 +#define STATUS_MAX_STEP_RATE_EXCEEDED 12 +#define STATUS_CHECK_DOOR 13 +#define STATUS_LINE_LENGTH_EXCEEDED 14 +#define STATUS_TRAVEL_EXCEEDED 15 +#define STATUS_INVALID_JOG_COMMAND 16 +#define STATUS_SETTING_DISABLED_LASER 17 + +#define STATUS_GCODE_UNSUPPORTED_COMMAND 20 +#define STATUS_GCODE_MODAL_GROUP_VIOLATION 21 +#define STATUS_GCODE_UNDEFINED_FEED_RATE 22 +#define STATUS_GCODE_COMMAND_VALUE_NOT_INTEGER 23 +#define STATUS_GCODE_AXIS_COMMAND_CONFLICT 24 +#define STATUS_GCODE_WORD_REPEATED 25 +#define STATUS_GCODE_NO_AXIS_WORDS 26 +#define STATUS_GCODE_INVALID_LINE_NUMBER 27 +#define STATUS_GCODE_VALUE_WORD_MISSING 28 +#define STATUS_GCODE_UNSUPPORTED_COORD_SYS 29 +#define STATUS_GCODE_G53_INVALID_MOTION_MODE 30 +#define STATUS_GCODE_AXIS_WORDS_EXIST 31 +#define STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE 32 +#define STATUS_GCODE_INVALID_TARGET 33 +#define STATUS_GCODE_ARC_RADIUS_ERROR 34 +#define STATUS_GCODE_NO_OFFSETS_IN_PLANE 35 +#define STATUS_GCODE_UNUSED_WORDS 36 +#define STATUS_GCODE_G43_DYNAMIC_AXIS_ERROR 37 +#define STATUS_GCODE_MAX_VALUE_EXCEEDED 38 + +// Define Grbl alarm codes. Valid values (1-255). 0 is reserved. +#define ALARM_HARD_LIMIT_ERROR EXEC_ALARM_HARD_LIMIT +#define ALARM_SOFT_LIMIT_ERROR EXEC_ALARM_SOFT_LIMIT +#define ALARM_ABORT_CYCLE EXEC_ALARM_ABORT_CYCLE +#define ALARM_PROBE_FAIL_INITIAL EXEC_ALARM_PROBE_FAIL_INITIAL +#define ALARM_PROBE_FAIL_CONTACT EXEC_ALARM_PROBE_FAIL_CONTACT +#define ALARM_HOMING_FAIL_RESET EXEC_ALARM_HOMING_FAIL_RESET +#define ALARM_HOMING_FAIL_DOOR EXEC_ALARM_HOMING_FAIL_DOOR +#define ALARM_HOMING_FAIL_PULLOFF EXEC_ALARM_HOMING_FAIL_PULLOFF +#define ALARM_HOMING_FAIL_APPROACH EXEC_ALARM_HOMING_FAIL_APPROACH + +// Define Grbl feedback message codes. Valid values (0-255). +#define MESSAGE_CRITICAL_EVENT 1 +#define MESSAGE_ALARM_LOCK 2 +#define MESSAGE_ALARM_UNLOCK 3 +#define MESSAGE_ENABLED 4 +#define MESSAGE_DISABLED 5 +#define MESSAGE_SAFETY_DOOR_AJAR 6 +#define MESSAGE_CHECK_LIMITS 7 +#define MESSAGE_PROGRAM_END 8 +#define MESSAGE_RESTORE_DEFAULTS 9 +#define MESSAGE_SPINDLE_RESTORE 10 +#define MESSAGE_SLEEP_MODE 11 + +// Prints system status messages. +void report_status_message(uint8_t status_code); + +// Prints system alarm messages. +void report_alarm_message(uint8_t alarm_code); + +// Prints miscellaneous feedback messages. +void report_feedback_message(uint8_t message_code); + +// Prints welcome message +void report_init_message(); + +// Prints Grbl help and current global settings +void report_grbl_help(); + +// Prints Grbl global settings +void report_grbl_settings(); + +// Prints an echo of the pre-parsed line received right before execution. +void report_echo_line_received(char *line); + +// Prints realtime status report +void report_realtime_status(); + +// Prints recorded probe position +void report_probe_parameters(); + +// Prints Grbl NGC parameters (coordinate offsets, probe) +void report_ngc_parameters(); + +// Prints current g-code parser mode state +void report_gcode_modes(); + +// Prints startup line when requested and executed. +void report_startup_line(uint8_t n, char *line); +void report_execute_startup_message(char *line, uint8_t status_code); + +// Prints build info and user info +void report_build_info(char *line); + +#ifdef DEBUG + void report_realtime_debug(); +#endif + +#endif diff --git a/grbl/serial.c b/grbl/serial.c new file mode 100644 index 0000000..cf5f35e --- /dev/null +++ b/grbl/serial.c @@ -0,0 +1,204 @@ +/* + serial.c - Low level functions for sending and recieving bytes via the serial port + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + +#define RX_RING_BUFFER (RX_BUFFER_SIZE+1) +#define TX_RING_BUFFER (TX_BUFFER_SIZE+1) + +uint8_t serial_rx_buffer[RX_RING_BUFFER]; +uint8_t serial_rx_buffer_head = 0; +volatile uint8_t serial_rx_buffer_tail = 0; + +uint8_t serial_tx_buffer[TX_RING_BUFFER]; +uint8_t serial_tx_buffer_head = 0; +volatile uint8_t serial_tx_buffer_tail = 0; + + +// Returns the number of bytes available in the RX serial buffer. +uint8_t serial_get_rx_buffer_available() +{ + uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile + if (serial_rx_buffer_head >= rtail) { return(RX_BUFFER_SIZE - (serial_rx_buffer_head-rtail)); } + return((rtail-serial_rx_buffer_head-1)); +} + + +// Returns the number of bytes used in the RX serial buffer. +// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h. +uint8_t serial_get_rx_buffer_count() +{ + uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile + if (serial_rx_buffer_head >= rtail) { return(serial_rx_buffer_head-rtail); } + return (RX_BUFFER_SIZE - (rtail-serial_rx_buffer_head)); +} + + +// Returns the number of bytes used in the TX serial buffer. +// NOTE: Not used except for debugging and ensuring no TX bottlenecks. +uint8_t serial_get_tx_buffer_count() +{ + uint8_t ttail = serial_tx_buffer_tail; // Copy to limit multiple calls to volatile + if (serial_tx_buffer_head >= ttail) { return(serial_tx_buffer_head-ttail); } + return (TX_RING_BUFFER - (ttail-serial_tx_buffer_head)); +} + + +void serial_init() +{ + // Set baud rate + #if BAUD_RATE < 57600 + uint16_t UBRR0_value = ((F_CPU / (8L * BAUD_RATE)) - 1)/2 ; + UCSR0A &= ~(1 << U2X0); // baud doubler off - Only needed on Uno XXX + #else + uint16_t UBRR0_value = ((F_CPU / (4L * BAUD_RATE)) - 1)/2; + UCSR0A |= (1 << U2X0); // baud doubler on for high baud rates, i.e. 115200 + #endif + UBRR0H = UBRR0_value >> 8; + UBRR0L = UBRR0_value; + + // enable rx, tx, and interrupt on complete reception of a byte + UCSR0B |= (1< 0x7F) { // Real-time control characters are extended ACSII only. + switch(data) { + case CMD_SAFETY_DOOR: system_set_exec_state_flag(EXEC_SAFETY_DOOR); break; // Set as true + case CMD_JOG_CANCEL: + if (sys.state & STATE_JOG) { // Block all other states from invoking motion cancel. + system_set_exec_state_flag(EXEC_MOTION_CANCEL); + } + break; + #ifdef DEBUG + case CMD_DEBUG_REPORT: {uint8_t sreg = SREG; cli(); bit_true(sys_rt_exec_debug,EXEC_DEBUG_REPORT); SREG = sreg;} break; + #endif + case CMD_FEED_OVR_RESET: system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET); break; + case CMD_FEED_OVR_COARSE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS); break; + case CMD_FEED_OVR_COARSE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS); break; + case CMD_FEED_OVR_FINE_PLUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS); break; + case CMD_FEED_OVR_FINE_MINUS: system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS); break; + case CMD_RAPID_OVR_RESET: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET); break; + case CMD_RAPID_OVR_MEDIUM: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM); break; + case CMD_RAPID_OVR_LOW: system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW); break; + case CMD_SPINDLE_OVR_RESET: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET); break; + case CMD_SPINDLE_OVR_COARSE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS); break; + case CMD_SPINDLE_OVR_COARSE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS); break; + case CMD_SPINDLE_OVR_FINE_PLUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS); break; + case CMD_SPINDLE_OVR_FINE_MINUS: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS); break; + case CMD_SPINDLE_OVR_STOP: system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); break; + case CMD_COOLANT_FLOOD_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break; + #ifdef ENABLE_M7 + case CMD_COOLANT_MIST_OVR_TOGGLE: system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE); break; + #endif + } + // Throw away any unfound extended-ASCII character by not passing it to the serial buffer. + } else { // Write character to buffer + next_head = serial_rx_buffer_head + 1; + if (next_head == RX_RING_BUFFER) { next_head = 0; } + + // Write data to buffer unless it is full. + if (next_head != serial_rx_buffer_tail) { + serial_rx_buffer[serial_rx_buffer_head] = data; + serial_rx_buffer_head = next_head; + } + } + } +} + + +void serial_reset_read_buffer() +{ + serial_rx_buffer_tail = serial_rx_buffer_head; +} diff --git a/grbl/serial.h b/grbl/serial.h new file mode 100644 index 0000000..5a3f776 --- /dev/null +++ b/grbl/serial.h @@ -0,0 +1,62 @@ +/* + serial.c - Low level functions for sending and recieving bytes via the serial port + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef serial_h +#define serial_h + + +#ifndef RX_BUFFER_SIZE + #define RX_BUFFER_SIZE 128 +#endif +#ifndef TX_BUFFER_SIZE + #ifdef USE_LINE_NUMBERS + #define TX_BUFFER_SIZE 112 + #else + #define TX_BUFFER_SIZE 104 + #endif +#endif + +#define SERIAL_NO_DATA 0xff + + +void serial_init(); + +// Writes one byte to the TX serial buffer. Called by main program. +void serial_write(uint8_t data); + +// Fetches the first byte in the serial read buffer. Called by main program. +uint8_t serial_read(); + +// Reset and empty data in read buffer. Used by e-stop and reset. +void serial_reset_read_buffer(); + +// Returns the number of bytes available in the RX serial buffer. +uint8_t serial_get_rx_buffer_available(); + +// Returns the number of bytes used in the RX serial buffer. +// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h. +uint8_t serial_get_rx_buffer_count(); + +// Returns the number of bytes used in the TX serial buffer. +// NOTE: Not used except for debugging and ensuring no TX bottlenecks. +uint8_t serial_get_tx_buffer_count(); + +#endif diff --git a/grbl/settings.c b/grbl/settings.c new file mode 100644 index 0000000..a9c830e --- /dev/null +++ b/grbl/settings.c @@ -0,0 +1,340 @@ +/* + settings.c - eeprom configuration handling + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + +settings_t settings; + +const __flash settings_t defaults = {\ + .pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS, + .stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME, + .step_invert_mask = DEFAULT_STEPPING_INVERT_MASK, + .dir_invert_mask = DEFAULT_DIRECTION_INVERT_MASK, + .status_report_mask = DEFAULT_STATUS_REPORT_MASK, + .junction_deviation = DEFAULT_JUNCTION_DEVIATION, + .arc_tolerance = DEFAULT_ARC_TOLERANCE, + .rpm_max = DEFAULT_SPINDLE_RPM_MAX, + .rpm_min = DEFAULT_SPINDLE_RPM_MIN, + .homing_dir_mask = DEFAULT_HOMING_DIR_MASK, + .homing_feed_rate = DEFAULT_HOMING_FEED_RATE, + .homing_seek_rate = DEFAULT_HOMING_SEEK_RATE, + .homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY, + .homing_pulloff = DEFAULT_HOMING_PULLOFF, + .flags = (DEFAULT_REPORT_INCHES << BIT_REPORT_INCHES) | \ + (DEFAULT_LASER_MODE << BIT_LASER_MODE) | \ + (DEFAULT_INVERT_ST_ENABLE << BIT_INVERT_ST_ENABLE) | \ + (DEFAULT_HARD_LIMIT_ENABLE << BIT_HARD_LIMIT_ENABLE) | \ + (DEFAULT_HOMING_ENABLE << BIT_HOMING_ENABLE) | \ + (DEFAULT_SOFT_LIMIT_ENABLE << BIT_SOFT_LIMIT_ENABLE) | \ + (DEFAULT_INVERT_LIMIT_PINS << BIT_INVERT_LIMIT_PINS) | \ + (DEFAULT_INVERT_PROBE_PIN << BIT_INVERT_PROBE_PIN), + .steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM, + .steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM, + .steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM, + .max_rate[X_AXIS] = DEFAULT_X_MAX_RATE, + .max_rate[Y_AXIS] = DEFAULT_Y_MAX_RATE, + .max_rate[Z_AXIS] = DEFAULT_Z_MAX_RATE, + .acceleration[X_AXIS] = DEFAULT_X_ACCELERATION, + .acceleration[Y_AXIS] = DEFAULT_Y_ACCELERATION, + .acceleration[Z_AXIS] = DEFAULT_Z_ACCELERATION, + .max_travel[X_AXIS] = (-DEFAULT_X_MAX_TRAVEL), + .max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL), + .max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL)}; + + +// Method to store startup lines into EEPROM +void settings_store_startup_line(uint8_t n, char *line) +{ + #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE + protocol_buffer_synchronize(); // A startup line may contain a motion and be executing. + #endif + uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK; + memcpy_to_eeprom_with_checksum(addr,(char*)line, LINE_BUFFER_SIZE); +} + + +// Method to store build info into EEPROM +// NOTE: This function can only be called in IDLE state. +void settings_store_build_info(char *line) +{ + // Build info can only be stored when state is IDLE. + memcpy_to_eeprom_with_checksum(EEPROM_ADDR_BUILD_INFO,(char*)line, LINE_BUFFER_SIZE); +} + + +// Method to store coord data parameters into EEPROM +void settings_write_coord_data(uint8_t coord_select, float *coord_data) +{ + #ifdef FORCE_BUFFER_SYNC_DURING_EEPROM_WRITE + protocol_buffer_synchronize(); + #endif + uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; + memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS); +} + + +// Method to store Grbl global settings struct and version number into EEPROM +// NOTE: This function can only be called in IDLE state. +void write_global_settings() +{ + eeprom_put_char(0, SETTINGS_VERSION); + memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t)); +} + + +// Method to restore EEPROM-saved Grbl global settings back to defaults. +void settings_restore(uint8_t restore_flag) { + if (restore_flag & SETTINGS_RESTORE_DEFAULTS) { + settings = defaults; + write_global_settings(); + } + + if (restore_flag & SETTINGS_RESTORE_PARAMETERS) { + uint8_t idx; + float coord_data[N_AXIS]; + memset(&coord_data, 0, sizeof(coord_data)); + for (idx=0; idx <= SETTING_INDEX_NCOORD; idx++) { settings_write_coord_data(idx, coord_data); } + } + + if (restore_flag & SETTINGS_RESTORE_STARTUP_LINES) { + #if N_STARTUP_LINE > 0 + eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK, 0); + eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+1, 0); // Checksum + #endif + #if N_STARTUP_LINE > 1 + eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+1), 0); + eeprom_put_char(EEPROM_ADDR_STARTUP_BLOCK+(LINE_BUFFER_SIZE+2), 0); // Checksum + #endif + } + + if (restore_flag & SETTINGS_RESTORE_BUILD_INFO) { + eeprom_put_char(EEPROM_ADDR_BUILD_INFO , 0); + eeprom_put_char(EEPROM_ADDR_BUILD_INFO+1 , 0); // Checksum + } +} + + +// Reads startup line from EEPROM. Updated pointed line string data. +uint8_t settings_read_startup_line(uint8_t n, char *line) +{ + uint32_t addr = n*(LINE_BUFFER_SIZE+1)+EEPROM_ADDR_STARTUP_BLOCK; + if (!(memcpy_from_eeprom_with_checksum((char*)line, addr, LINE_BUFFER_SIZE))) { + // Reset line with default value + line[0] = 0; // Empty line + settings_store_startup_line(n, line); + return(false); + } + return(true); +} + + +// Reads startup line from EEPROM. Updated pointed line string data. +uint8_t settings_read_build_info(char *line) +{ + if (!(memcpy_from_eeprom_with_checksum((char*)line, EEPROM_ADDR_BUILD_INFO, LINE_BUFFER_SIZE))) { + // Reset line with default value + line[0] = 0; // Empty line + settings_store_build_info(line); + return(false); + } + return(true); +} + + +// Read selected coordinate data from EEPROM. Updates pointed coord_data value. +uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data) +{ + uint32_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; + if (!(memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) { + // Reset with default zero vector + clear_vector_float(coord_data); + settings_write_coord_data(coord_select,coord_data); + return(false); + } + return(true); +} + + +// Reads Grbl global settings struct from EEPROM. +uint8_t read_global_settings() { + // Check version-byte of eeprom + uint8_t version = eeprom_get_char(0); + if (version == SETTINGS_VERSION) { + // Read settings-record and check checksum + if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) { + return(false); + } + } else { + return(false); + } + return(true); +} + + +// A helper method to set settings from command line +uint8_t settings_store_global_setting(uint8_t parameter, float value) { + if (value < 0.0) { return(STATUS_NEGATIVE_VALUE); } + if (parameter >= AXIS_SETTINGS_START_VAL) { + // Store axis configuration. Axis numbering sequence set by AXIS_SETTING defines. + // NOTE: Ensure the setting index corresponds to the report.c settings printout. + parameter -= AXIS_SETTINGS_START_VAL; + uint8_t set_idx = 0; + while (set_idx < AXIS_N_SETTINGS) { + if (parameter < N_AXIS) { + // Valid axis setting found. + switch (set_idx) { + case 0: + #ifdef MAX_STEP_RATE_HZ + if (value*settings.max_rate[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); } + #endif + settings.steps_per_mm[parameter] = value; + break; + case 1: + #ifdef MAX_STEP_RATE_HZ + if (value*settings.steps_per_mm[parameter] > (MAX_STEP_RATE_HZ*60.0)) { return(STATUS_MAX_STEP_RATE_EXCEEDED); } + #endif + settings.max_rate[parameter] = value; + break; + case 2: settings.acceleration[parameter] = value*60*60; break; // Convert to mm/min^2 for grbl internal use. + case 3: settings.max_travel[parameter] = -value; break; // Store as negative for grbl internal use. + } + break; // Exit while-loop after setting has been configured and proceed to the EEPROM write call. + } else { + set_idx++; + // If axis index greater than N_AXIS or setting index greater than number of axis settings, error out. + if ((parameter < AXIS_SETTINGS_INCREMENT) || (set_idx == AXIS_N_SETTINGS)) { return(STATUS_INVALID_STATEMENT); } + parameter -= AXIS_SETTINGS_INCREMENT; + } + } + } else { + // Store non-axis Grbl settings + uint8_t int_value = trunc(value); + switch(parameter) { + case 0: + if (int_value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } + settings.pulse_microseconds = int_value; break; + case 1: settings.stepper_idle_lock_time = int_value; break; + case 2: + settings.step_invert_mask = int_value; + st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks. + break; + case 3: + settings.dir_invert_mask = int_value; + st_generate_step_dir_invert_masks(); // Regenerate step and direction port invert masks. + break; + case 4: // Reset to ensure change. Immediate re-init may cause problems. + if (int_value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } + else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } + break; + case 5: // Reset to ensure change. Immediate re-init may cause problems. + if (int_value) { settings.flags |= BITFLAG_INVERT_LIMIT_PINS; } + else { settings.flags &= ~BITFLAG_INVERT_LIMIT_PINS; } + break; + case 6: // Reset to ensure change. Immediate re-init may cause problems. + if (int_value) { settings.flags |= BITFLAG_INVERT_PROBE_PIN; } + else { settings.flags &= ~BITFLAG_INVERT_PROBE_PIN; } + probe_configure_invert_mask(false); + break; + case 10: settings.status_report_mask = int_value; break; + case 11: settings.junction_deviation = value; break; + case 12: settings.arc_tolerance = value; break; + case 13: + if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; } + else { settings.flags &= ~BITFLAG_REPORT_INCHES; } + system_flag_wco_change(); // Make sure WCO is immediately updated. + break; + case 20: + if (int_value) { + if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); } + settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; + } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; } + break; + case 21: + if (int_value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } + else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } + limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later. + break; + case 22: + if (int_value) { settings.flags |= BITFLAG_HOMING_ENABLE; } + else { + settings.flags &= ~BITFLAG_HOMING_ENABLE; + settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; // Force disable soft-limits. + } + break; + case 23: settings.homing_dir_mask = int_value; break; + case 24: settings.homing_feed_rate = value; break; + case 25: settings.homing_seek_rate = value; break; + case 26: settings.homing_debounce_delay = int_value; break; + case 27: settings.homing_pulloff = value; break; + case 30: settings.rpm_max = value; spindle_init(); break; // Re-initialize spindle rpm calibration + case 31: settings.rpm_min = value; spindle_init(); break; // Re-initialize spindle rpm calibration + case 32: + #ifdef VARIABLE_SPINDLE + if (int_value) { settings.flags |= BITFLAG_LASER_MODE; } + else { settings.flags &= ~BITFLAG_LASER_MODE; } + #else + return(STATUS_SETTING_DISABLED_LASER); + #endif + break; + default: + return(STATUS_INVALID_STATEMENT); + } + } + write_global_settings(); + return(STATUS_OK); +} + + +// Initialize the config subsystem +void settings_init() { + if(!read_global_settings()) { + report_status_message(STATUS_SETTING_READ_FAIL); + settings_restore(SETTINGS_RESTORE_ALL); // Force restore all EEPROM data. + report_grbl_settings(); + } +} + + +// Returns step pin mask according to Grbl internal axis indexing. +uint8_t get_step_pin_mask(uint8_t axis_idx) +{ + if ( axis_idx == X_AXIS ) { return((1<. +*/ + +#ifndef settings_h +#define settings_h + +#include "grbl.h" + + +// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl +// when firmware is upgraded. Always stored in byte 0 of eeprom +#define SETTINGS_VERSION 10 // NOTE: Check settings_reset() when moving to next version. + +// Define bit flag masks for the boolean settings in settings.flag. +#define BIT_REPORT_INCHES 0 +#define BIT_LASER_MODE 1 +#define BIT_INVERT_ST_ENABLE 2 +#define BIT_HARD_LIMIT_ENABLE 3 +#define BIT_HOMING_ENABLE 4 +#define BIT_SOFT_LIMIT_ENABLE 5 +#define BIT_INVERT_LIMIT_PINS 6 +#define BIT_INVERT_PROBE_PIN 7 + +#define BITFLAG_REPORT_INCHES bit(BIT_REPORT_INCHES) +#define BITFLAG_LASER_MODE bit(BIT_LASER_MODE) +#define BITFLAG_INVERT_ST_ENABLE bit(BIT_INVERT_ST_ENABLE) +#define BITFLAG_HARD_LIMIT_ENABLE bit(BIT_HARD_LIMIT_ENABLE) +#define BITFLAG_HOMING_ENABLE bit(BIT_HOMING_ENABLE) +#define BITFLAG_SOFT_LIMIT_ENABLE bit(BIT_SOFT_LIMIT_ENABLE) +#define BITFLAG_INVERT_LIMIT_PINS bit(BIT_INVERT_LIMIT_PINS) +#define BITFLAG_INVERT_PROBE_PIN bit(BIT_INVERT_PROBE_PIN) + +// Define status reporting boolean enable bit flags in settings.status_report_mask +#define BITFLAG_RT_STATUS_POSITION_TYPE bit(0) +#define BITFLAG_RT_STATUS_BUFFER_STATE bit(1) + +// Define settings restore bitflags. +#define SETTINGS_RESTORE_DEFAULTS bit(0) +#define SETTINGS_RESTORE_PARAMETERS bit(1) +#define SETTINGS_RESTORE_STARTUP_LINES bit(2) +#define SETTINGS_RESTORE_BUILD_INFO bit(3) +#ifndef SETTINGS_RESTORE_ALL + #define SETTINGS_RESTORE_ALL 0xFF // All bitflags +#endif + +// Define EEPROM memory address location values for Grbl settings and parameters +// NOTE: The Atmega328p has 1KB EEPROM. The upper half is reserved for parameters and +// the startup script. The lower half contains the global settings and space for future +// developments. +#define EEPROM_ADDR_GLOBAL 1U +#define EEPROM_ADDR_PARAMETERS 512U +#define EEPROM_ADDR_STARTUP_BLOCK 768U +#define EEPROM_ADDR_BUILD_INFO 942U + +// Define EEPROM address indexing for coordinate parameters +#define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1) +#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+1 // Total number of system stored (from index 0) +// NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59) +#define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1 +#define SETTING_INDEX_G30 N_COORDINATE_SYSTEM+1 // Home position 2 +// #define SETTING_INDEX_G92 N_COORDINATE_SYSTEM+2 // Coordinate offset (G92.2,G92.3 not supported) + +// Define Grbl axis settings numbering scheme. Starts at START_VAL, every INCREMENT, over N_SETTINGS. +#define AXIS_N_SETTINGS 4 +#define AXIS_SETTINGS_START_VAL 100 // NOTE: Reserving settings values >= 100 for axis settings. Up to 255. +#define AXIS_SETTINGS_INCREMENT 10 // Must be greater than the number of axis settings + +// Global persistent settings (Stored from byte EEPROM_ADDR_GLOBAL onwards) +typedef struct { + // Axis settings + float steps_per_mm[N_AXIS]; + float max_rate[N_AXIS]; + float acceleration[N_AXIS]; + float max_travel[N_AXIS]; + + // Remaining Grbl settings + uint8_t pulse_microseconds; + uint8_t step_invert_mask; + uint8_t dir_invert_mask; + uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. + uint8_t status_report_mask; // Mask to indicate desired report data. + float junction_deviation; + float arc_tolerance; + + float rpm_max; + float rpm_min; + + uint8_t flags; // Contains default boolean settings + + uint8_t homing_dir_mask; + float homing_feed_rate; + float homing_seek_rate; + uint16_t homing_debounce_delay; + float homing_pulloff; +} settings_t; +extern settings_t settings; + +// Initialize the configuration subsystem (load settings from EEPROM) +void settings_init(); + +// Helper function to clear and restore EEPROM defaults +void settings_restore(uint8_t restore_flag); + +// A helper method to set new settings from command line +uint8_t settings_store_global_setting(uint8_t parameter, float value); + +// Stores the protocol line variable as a startup line in EEPROM +void settings_store_startup_line(uint8_t n, char *line); + +// Reads an EEPROM startup line to the protocol line variable +uint8_t settings_read_startup_line(uint8_t n, char *line); + +// Stores build info user-defined string +void settings_store_build_info(char *line); + +// Reads build info user-defined string +uint8_t settings_read_build_info(char *line); + +// Writes selected coordinate data to EEPROM +void settings_write_coord_data(uint8_t coord_select, float *coord_data); + +// Reads selected coordinate data from EEPROM +uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data); + +// Returns the step pin mask according to Grbl's internal axis numbering +uint8_t get_step_pin_mask(uint8_t i); + +// Returns the direction pin mask according to Grbl's internal axis numbering +uint8_t get_direction_pin_mask(uint8_t i); + +// Returns the limit pin mask according to Grbl's internal axis numbering +uint8_t get_limit_pin_mask(uint8_t i); + + +#endif diff --git a/grbl/spindle_control.c b/grbl/spindle_control.c new file mode 100644 index 0000000..550b752 --- /dev/null +++ b/grbl/spindle_control.c @@ -0,0 +1,290 @@ +/* + spindle_control.c - spindle control methods + Part of Grbl + + Copyright (c) 2012-2017 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +#ifdef VARIABLE_SPINDLE + static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions. +#endif + + +void spindle_init() +{ + #ifdef VARIABLE_SPINDLE + // Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are + // combined unless configured otherwise. + SPINDLE_PWM_DDR |= (1<= settings.rpm_max) || (rpm >= RPM_MAX)) { + rpm = RPM_MAX; + pwm_value = SPINDLE_PWM_MAX_VALUE; + } else if (rpm <= RPM_MIN) { + if (rpm == 0.0) { // S0 disables spindle + pwm_value = SPINDLE_PWM_OFF_VALUE; + } else { + rpm = RPM_MIN; + pwm_value = SPINDLE_PWM_MIN_VALUE; + } + } else { + // Compute intermediate PWM value with linear spindle speed model via piecewise linear fit model. + #if (N_PIECES > 3) + if (rpm > RPM_POINT34) { + pwm_value = floor(RPM_LINE_A4*rpm - RPM_LINE_B4); + } else + #endif + #if (N_PIECES > 2) + if (rpm > RPM_POINT23) { + pwm_value = floor(RPM_LINE_A3*rpm - RPM_LINE_B3); + } else + #endif + #if (N_PIECES > 1) + if (rpm > RPM_POINT12) { + pwm_value = floor(RPM_LINE_A2*rpm - RPM_LINE_B2); + } else + #endif + { + pwm_value = floor(RPM_LINE_A1*rpm - RPM_LINE_B1); + } + } + sys.spindle_speed = rpm; + return(pwm_value); + } + + #else + + // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. + uint8_t spindle_compute_pwm_value(float rpm) // 328p PWM register is 8-bit. + { + uint8_t pwm_value; + rpm *= (0.010*sys.spindle_speed_ovr); // Scale by spindle speed override value. + // Calculate PWM register value based on rpm max/min settings and programmed rpm. + if ((settings.rpm_min >= settings.rpm_max) || (rpm >= settings.rpm_max)) { + // No PWM range possible. Set simple on/off spindle control pin state. + sys.spindle_speed = settings.rpm_max; + pwm_value = SPINDLE_PWM_MAX_VALUE; + } else if (rpm <= settings.rpm_min) { + if (rpm == 0.0) { // S0 disables spindle + sys.spindle_speed = 0.0; + pwm_value = SPINDLE_PWM_OFF_VALUE; + } else { // Set minimum PWM output + sys.spindle_speed = settings.rpm_min; + pwm_value = SPINDLE_PWM_MIN_VALUE; + } + } else { + // Compute intermediate PWM value with linear spindle speed model. + // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight. + sys.spindle_speed = rpm; + pwm_value = floor((rpm-settings.rpm_min)*pwm_gradient) + SPINDLE_PWM_MIN_VALUE; + } + return(pwm_value); + } + + #endif +#endif + + +// Immediately sets spindle running state with direction and spindle rpm via PWM, if enabled. +// Called by g-code parser spindle_sync(), parking retract and restore, g-code program end, +// sleep, and spindle stop override. +#ifdef VARIABLE_SPINDLE + void spindle_set_state(uint8_t state, float rpm) +#else + void _spindle_set_state(uint8_t state) +#endif +{ + if (sys.abort) { return; } // Block during abort. + + if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm. + + #ifdef VARIABLE_SPINDLE + sys.spindle_speed = 0.0; + #endif + spindle_stop(); + + } else { + + #if !defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && !defined(ENABLE_DUAL_AXIS) + if (state == SPINDLE_ENABLE_CW) { + SPINDLE_DIRECTION_PORT &= ~(1<. +*/ + +#ifndef spindle_control_h +#define spindle_control_h + +#define SPINDLE_NO_SYNC false +#define SPINDLE_FORCE_SYNC true + +#define SPINDLE_STATE_DISABLE 0 // Must be zero. +#define SPINDLE_STATE_CW bit(0) +#define SPINDLE_STATE_CCW bit(1) + + +// Initializes spindle pins and hardware PWM, if enabled. +void spindle_init(); + +// Returns current spindle output state. Overrides may alter it from programmed states. +uint8_t spindle_get_state(); + +// Called by g-code parser when setting spindle state and requires a buffer sync. +// Immediately sets spindle running state with direction and spindle rpm via PWM, if enabled. +// Called by spindle_sync() after sync and parking motion/spindle stop override during restore. +#ifdef VARIABLE_SPINDLE + + // Called by g-code parser when setting spindle state and requires a buffer sync. + void spindle_sync(uint8_t state, float rpm); + + // Sets spindle running state with direction, enable, and spindle PWM. + void spindle_set_state(uint8_t state, float rpm); + + // Sets spindle PWM quickly for stepper ISR. Also called by spindle_set_state(). + // NOTE: 328p PWM register is 8-bit. + void spindle_set_speed(uint8_t pwm_value); + + // Computes 328p-specific PWM register value for the given RPM for quick updating. + uint8_t spindle_compute_pwm_value(float rpm); + +#else + + // Called by g-code parser when setting spindle state and requires a buffer sync. + #define spindle_sync(state, rpm) _spindle_sync(state) + void _spindle_sync(uint8_t state); + + // Sets spindle running state with direction and enable. + #define spindle_set_state(state, rpm) _spindle_set_state(state) + void _spindle_set_state(uint8_t state); + +#endif + +// Stop and start spindle routines. Called by all spindle routines and stepper ISR. +void spindle_stop(); + + +#endif diff --git a/grbl/stepper.c b/grbl/stepper.c new file mode 100644 index 0000000..8e0b151 --- /dev/null +++ b/grbl/stepper.c @@ -0,0 +1,1095 @@ +/* + stepper.c - stepper motor driver: executes motion plans using stepper motors + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +// Some useful constants. +#define DT_SEGMENT (1.0/(ACCELERATION_TICKS_PER_SECOND*60.0)) // min/segment +#define REQ_MM_INCREMENT_SCALAR 1.25 +#define RAMP_ACCEL 0 +#define RAMP_CRUISE 1 +#define RAMP_DECEL 2 +#define RAMP_DECEL_OVERRIDE 3 + +#define PREP_FLAG_RECALCULATE bit(0) +#define PREP_FLAG_HOLD_PARTIAL_BLOCK bit(1) +#define PREP_FLAG_PARKING bit(2) +#define PREP_FLAG_DECEL_OVERRIDE bit(3) + +// Define Adaptive Multi-Axis Step-Smoothing(AMASS) levels and cutoff frequencies. The highest level +// frequency bin starts at 0Hz and ends at its cutoff frequency. The next lower level frequency bin +// starts at the next higher cutoff frequency, and so on. The cutoff frequencies for each level must +// be considered carefully against how much it over-drives the stepper ISR, the accuracy of the 16-bit +// timer, and the CPU overhead. Level 0 (no AMASS, normal operation) frequency bin starts at the +// Level 1 cutoff frequency and up to as fast as the CPU allows (over 30kHz in limited testing). +// NOTE: AMASS cutoff frequency multiplied by ISR overdrive factor must not exceed maximum step frequency. +// NOTE: Current settings are set to overdrive the ISR to no more than 16kHz, balancing CPU overhead +// and timer accuracy. Do not alter these settings unless you know what you are doing. +#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + #define MAX_AMASS_LEVEL 3 + // AMASS_LEVEL0: Normal operation. No AMASS. No upper cutoff frequency. Starts at LEVEL1 cutoff frequency. + #define AMASS_LEVEL1 (F_CPU/8000) // Over-drives ISR (x2). Defined as F_CPU/(Cutoff frequency in Hz) + #define AMASS_LEVEL2 (F_CPU/4000) // Over-drives ISR (x4) + #define AMASS_LEVEL3 (F_CPU/2000) // Over-drives ISR (x8) + + #if MAX_AMASS_LEVEL <= 0 + error "AMASS must have 1 or more levels to operate correctly." + #endif +#endif + + +// Stores the planner block Bresenham algorithm execution data for the segments in the segment +// buffer. Normally, this buffer is partially in-use, but, for the worst case scenario, it will +// never exceed the number of accessible stepper buffer segments (SEGMENT_BUFFER_SIZE-1). +// NOTE: This data is copied from the prepped planner blocks so that the planner blocks may be +// discarded when entirely consumed and completed by the segment buffer. Also, AMASS alters this +// data for its own use. +typedef struct { + uint32_t steps[N_AXIS]; + uint32_t step_event_count; + uint8_t direction_bits; + #ifdef ENABLE_DUAL_AXIS + uint8_t direction_bits_dual; + #endif + #ifdef VARIABLE_SPINDLE + uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate + #endif +} st_block_t; +static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1]; + +// Primary stepper segment ring buffer. Contains small, short line segments for the stepper +// algorithm to execute, which are "checked-out" incrementally from the first block in the +// planner buffer. Once "checked-out", the steps in the segments buffer cannot be modified by +// the planner, where the remaining planner block steps still can. +typedef struct { + uint16_t n_step; // Number of step events to be executed for this segment + uint16_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate. + uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment. + #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment + #else + uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing. + #endif + #ifdef VARIABLE_SPINDLE + uint8_t spindle_pwm; + #endif +} segment_t; +static segment_t segment_buffer[SEGMENT_BUFFER_SIZE]; + +// Stepper ISR data struct. Contains the running data for the main stepper ISR. +typedef struct { + // Used by the bresenham line algorithm + uint32_t counter_x, // Counter variables for the bresenham line tracer + counter_y, + counter_z; + #ifdef STEP_PULSE_DELAY + uint8_t step_bits; // Stores out_bits output to complete the step pulse delay + #endif + + uint8_t execute_step; // Flags step execution for each interrupt. + uint8_t step_pulse_time; // Step pulse reset time after step rise + uint8_t step_outbits; // The next stepping-bits to be output + uint8_t dir_outbits; + #ifdef ENABLE_DUAL_AXIS + uint8_t step_outbits_dual; + uint8_t dir_outbits_dual; + #endif + #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + uint32_t steps[N_AXIS]; + #endif + + uint16_t step_count; // Steps remaining in line segment motion + uint8_t exec_block_index; // Tracks the current st_block index. Change indicates new block. + st_block_t *exec_block; // Pointer to the block data for the segment being executed + segment_t *exec_segment; // Pointer to the segment being executed +} stepper_t; +static stepper_t st; + +// Step segment ring buffer indices +static volatile uint8_t segment_buffer_tail; +static uint8_t segment_buffer_head; +static uint8_t segment_next_head; + +// Step and direction port invert masks. +static uint8_t step_port_invert_mask; +static uint8_t dir_port_invert_mask; +#ifdef ENABLE_DUAL_AXIS + static uint8_t step_port_invert_mask_dual; + static uint8_t dir_port_invert_mask_dual; +#endif + +// Used to avoid ISR nesting of the "Stepper Driver Interrupt". Should never occur though. +static volatile uint8_t busy; + +// Pointers for the step segment being prepped from the planner buffer. Accessed only by the +// main program. Pointers may be planning segments or planner blocks ahead of what being executed. +static plan_block_t *pl_block; // Pointer to the planner block being prepped +static st_block_t *st_prep_block; // Pointer to the stepper block data being prepped + +// Segment preparation data struct. Contains all the necessary information to compute new segments +// based on the current executing planner block. +typedef struct { + uint8_t st_block_index; // Index of stepper common data block being prepped + uint8_t recalculate_flag; + + float dt_remainder; + float steps_remaining; + float step_per_mm; + float req_mm_increment; + + #ifdef PARKING_ENABLE + uint8_t last_st_block_index; + float last_steps_remaining; + float last_step_per_mm; + float last_dt_remainder; + #endif + + uint8_t ramp_type; // Current segment ramp state + float mm_complete; // End of velocity profile from end of current planner block in (mm). + // NOTE: This value must coincide with a step(no mantissa) when converted. + float current_speed; // Current speed at the end of the segment buffer (mm/min) + float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min) + float exit_speed; // Exit speed of executing block (mm/min) + float accelerate_until; // Acceleration ramp end measured from end of block (mm) + float decelerate_after; // Deceleration ramp start measured from end of block (mm) + + #ifdef VARIABLE_SPINDLE + float inv_rate; // Used by PWM laser mode to speed up segment calculations. + uint8_t current_spindle_pwm; + #endif +} st_prep_t; +static st_prep_t prep; + + +/* BLOCK VELOCITY PROFILE DEFINITION + __________________________ + /| |\ _________________ ^ + / | | \ /| |\ | + / | | \ / | | \ s + / | | | | | \ p + / | | | | | \ e + +-----+------------------------+---+--+---------------+----+ e + | BLOCK 1 ^ BLOCK 2 | d + | + time -----> EXAMPLE: Block 2 entry speed is at max junction velocity + + The planner block buffer is planned assuming constant acceleration velocity profiles and are + continuously joined at block junctions as shown above. However, the planner only actively computes + the block entry speeds for an optimal velocity plan, but does not compute the block internal + velocity profiles. These velocity profiles are computed ad-hoc as they are executed by the + stepper algorithm and consists of only 7 possible types of profiles: cruise-only, cruise- + deceleration, acceleration-cruise, acceleration-only, deceleration-only, full-trapezoid, and + triangle(no cruise). + + maximum_speed (< nominal_speed) -> + + +--------+ <- maximum_speed (= nominal_speed) /|\ + / \ / | \ + current_speed -> + \ / | + <- exit_speed + | + <- exit_speed / | | + +-------------+ current_speed -> +----+--+ + time --> ^ ^ ^ ^ + | | | | + decelerate_after(in mm) decelerate_after(in mm) + ^ ^ ^ ^ + | | | | + accelerate_until(in mm) accelerate_until(in mm) + + The step segment buffer computes the executing block velocity profile and tracks the critical + parameters for the stepper algorithm to accurately trace the profile. These critical parameters + are shown and defined in the above illustration. +*/ + + +// Stepper state initialization. Cycle should only start if the st.cycle_start flag is +// enabled. Startup init and limits call this function but shouldn't start the cycle. +void st_wake_up() +{ + // Enable stepper drivers. + if (bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)) { STEPPERS_DISABLE_PORT |= (1<> 3); + // Set delay between direction pin write and step command. + OCR0A = -(((settings.pulse_microseconds)*TICKS_PER_MICROSECOND) >> 3); + #else // Normal operation + // Set step pulse time. Ad hoc computation from oscilloscope. Uses two's complement. + st.step_pulse_time = -(((settings.pulse_microseconds-2)*TICKS_PER_MICROSECOND) >> 3); + #endif + + // Enable Stepper Driver Interrupt + TIMSK1 |= (1<prescaler<cycles_per_tick; + st.step_count = st.exec_segment->n_step; // NOTE: Can sometimes be zero when moving slow. + // If the new segment starts a new planner block, initialize stepper variables and counters. + // NOTE: When the segment data index changes, this indicates a new planner block. + if ( st.exec_block_index != st.exec_segment->st_block_index ) { + st.exec_block_index = st.exec_segment->st_block_index; + st.exec_block = &st_block_buffer[st.exec_block_index]; + + // Initialize Bresenham line and distance counters + st.counter_x = st.counter_y = st.counter_z = (st.exec_block->step_event_count >> 1); + } + st.dir_outbits = st.exec_block->direction_bits ^ dir_port_invert_mask; + #ifdef ENABLE_DUAL_AXIS + st.dir_outbits_dual = st.exec_block->direction_bits_dual ^ dir_port_invert_mask_dual; + #endif + + #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + // With AMASS enabled, adjust Bresenham axis increment counters according to AMASS level. + st.steps[X_AXIS] = st.exec_block->steps[X_AXIS] >> st.exec_segment->amass_level; + st.steps[Y_AXIS] = st.exec_block->steps[Y_AXIS] >> st.exec_segment->amass_level; + st.steps[Z_AXIS] = st.exec_block->steps[Z_AXIS] >> st.exec_segment->amass_level; + #endif + + #ifdef VARIABLE_SPINDLE + // Set real-time spindle output as segment is loaded, just prior to the first step. + spindle_set_speed(st.exec_segment->spindle_pwm); + #endif + + } else { + // Segment buffer empty. Shutdown. + st_go_idle(); + #ifdef VARIABLE_SPINDLE + // Ensure pwm is set properly upon completion of rate-controlled motion. + if (st.exec_block->is_pwm_rate_adjusted) { spindle_set_speed(SPINDLE_PWM_OFF_VALUE); } + #endif + system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end + return; // Nothing to do but exit. + } + } + + + // Check probing state. + if (sys_probe_state == PROBE_ACTIVE) { probe_state_monitor(); } + + // Reset step out bits. + st.step_outbits = 0; + #ifdef ENABLE_DUAL_AXIS + st.step_outbits_dual = 0; + #endif + + // Execute step displacement profile by Bresenham line algorithm + #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + st.counter_x += st.steps[X_AXIS]; + #else + st.counter_x += st.exec_block->steps[X_AXIS]; + #endif + if (st.counter_x > st.exec_block->step_event_count) { + st.step_outbits |= (1<step_event_count; + if (st.exec_block->direction_bits & (1<steps[Y_AXIS]; + #endif + if (st.counter_y > st.exec_block->step_event_count) { + st.step_outbits |= (1<step_event_count; + if (st.exec_block->direction_bits & (1<steps[Z_AXIS]; + #endif + if (st.counter_z > st.exec_block->step_event_count) { + st.step_outbits |= (1<step_event_count; + if (st.exec_block->direction_bits & (1<entry_speed_sqr = prep.current_speed*prep.current_speed; // Update entry speed. + pl_block = NULL; // Flag st_prep_segment() to load and check active velocity profile. + } +} + + +// Increments the step segment buffer block data ring buffer. +static uint8_t st_next_block_index(uint8_t block_index) +{ + block_index++; + if ( block_index == (SEGMENT_BUFFER_SIZE-1) ) { return(0); } + return(block_index); +} + + +#ifdef PARKING_ENABLE + // Changes the run state of the step segment buffer to execute the special parking motion. + void st_parking_setup_buffer() + { + // Store step execution data of partially completed block, if necessary. + if (prep.recalculate_flag & PREP_FLAG_HOLD_PARTIAL_BLOCK) { + prep.last_st_block_index = prep.st_block_index; + prep.last_steps_remaining = prep.steps_remaining; + prep.last_dt_remainder = prep.dt_remainder; + prep.last_step_per_mm = prep.step_per_mm; + } + // Set flags to execute a parking motion + prep.recalculate_flag |= PREP_FLAG_PARKING; + prep.recalculate_flag &= ~(PREP_FLAG_RECALCULATE); + pl_block = NULL; // Always reset parking motion to reload new block. + } + + + // Restores the step segment buffer to the normal run state after a parking motion. + void st_parking_restore_buffer() + { + // Restore step execution data and flags of partially completed block, if necessary. + if (prep.recalculate_flag & PREP_FLAG_HOLD_PARTIAL_BLOCK) { + st_prep_block = &st_block_buffer[prep.last_st_block_index]; + prep.st_block_index = prep.last_st_block_index; + prep.steps_remaining = prep.last_steps_remaining; + prep.dt_remainder = prep.last_dt_remainder; + prep.step_per_mm = prep.last_step_per_mm; + prep.recalculate_flag = (PREP_FLAG_HOLD_PARTIAL_BLOCK | PREP_FLAG_RECALCULATE); + prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR/prep.step_per_mm; // Recompute this value. + } else { + prep.recalculate_flag = false; + } + pl_block = NULL; // Set to reload next block. + } +#endif + + +/* Prepares step segment buffer. Continuously called from main program. + + The segment buffer is an intermediary buffer interface between the execution of steps + by the stepper algorithm and the velocity profiles generated by the planner. The stepper + algorithm only executes steps within the segment buffer and is filled by the main program + when steps are "checked-out" from the first block in the planner buffer. This keeps the + step execution and planning optimization processes atomic and protected from each other. + The number of steps "checked-out" from the planner buffer and the number of segments in + the segment buffer is sized and computed such that no operation in the main program takes + longer than the time it takes the stepper algorithm to empty it before refilling it. + Currently, the segment buffer conservatively holds roughly up to 40-50 msec of steps. + NOTE: Computation units are in steps, millimeters, and minutes. +*/ +void st_prep_buffer() +{ + // Block step prep buffer, while in a suspend state and there is no suspend motion to execute. + if (bit_istrue(sys.step_control,STEP_CONTROL_END_MOTION)) { return; } + + while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer. + + // Determine if we need to load a new planner block or if the block needs to be recomputed. + if (pl_block == NULL) { + + // Query planner for a queued block + if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { pl_block = plan_get_system_motion_block(); } + else { pl_block = plan_get_current_block(); } + if (pl_block == NULL) { return; } // No planner blocks. Exit. + + // Check if we need to only recompute the velocity profile or load a new block. + if (prep.recalculate_flag & PREP_FLAG_RECALCULATE) { + + #ifdef PARKING_ENABLE + if (prep.recalculate_flag & PREP_FLAG_PARKING) { prep.recalculate_flag &= ~(PREP_FLAG_RECALCULATE); } + else { prep.recalculate_flag = false; } + #else + prep.recalculate_flag = false; + #endif + + } else { + + // Load the Bresenham stepping data for the block. + prep.st_block_index = st_next_block_index(prep.st_block_index); + + // Prepare and copy Bresenham algorithm segment data from the new planner block, so that + // when the segment buffer completes the planner block, it may be discarded when the + // segment buffer finishes the prepped block, but the stepper ISR is still executing it. + st_prep_block = &st_block_buffer[prep.st_block_index]; + st_prep_block->direction_bits = pl_block->direction_bits; + #ifdef ENABLE_DUAL_AXIS + #if (DUAL_AXIS_SELECT == X_AXIS) + if (st_prep_block->direction_bits & (1<direction_bits & (1<direction_bits_dual = (1<direction_bits_dual = 0; } + #endif + uint8_t idx; + #ifndef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + for (idx=0; idxsteps[idx] = (pl_block->steps[idx] << 1); } + st_prep_block->step_event_count = (pl_block->step_event_count << 1); + #else + // With AMASS enabled, simply bit-shift multiply all Bresenham data by the max AMASS + // level, such that we never divide beyond the original data anywhere in the algorithm. + // If the original data is divided, we can lose a step from integer roundoff. + for (idx=0; idxsteps[idx] = pl_block->steps[idx] << MAX_AMASS_LEVEL; } + st_prep_block->step_event_count = pl_block->step_event_count << MAX_AMASS_LEVEL; + #endif + + // Initialize segment buffer data for generating the segments. + prep.steps_remaining = (float)pl_block->step_event_count; + prep.step_per_mm = prep.steps_remaining/pl_block->millimeters; + prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR/prep.step_per_mm; + prep.dt_remainder = 0.0; // Reset for new segment block + + if ((sys.step_control & STEP_CONTROL_EXECUTE_HOLD) || (prep.recalculate_flag & PREP_FLAG_DECEL_OVERRIDE)) { + // New block loaded mid-hold. Override planner block entry speed to enforce deceleration. + prep.current_speed = prep.exit_speed; + pl_block->entry_speed_sqr = prep.exit_speed*prep.exit_speed; + prep.recalculate_flag &= ~(PREP_FLAG_DECEL_OVERRIDE); + } else { + prep.current_speed = sqrt(pl_block->entry_speed_sqr); + } + + #ifdef VARIABLE_SPINDLE + // Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the + // spindle off. + st_prep_block->is_pwm_rate_adjusted = false; + if (settings.flags & BITFLAG_LASER_MODE) { + if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) { + // Pre-compute inverse programmed rate to speed up PWM updating per step segment. + prep.inv_rate = 1.0/pl_block->programmed_rate; + st_prep_block->is_pwm_rate_adjusted = true; + } + } + #endif + } + + /* --------------------------------------------------------------------------------- + Compute the velocity profile of a new planner block based on its entry and exit + speeds, or recompute the profile of a partially-completed planner block if the + planner has updated it. For a commanded forced-deceleration, such as from a feed + hold, override the planner velocities and decelerate to the target exit speed. + */ + prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block. + float inv_2_accel = 0.5/pl_block->acceleration; + if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity] + // Compute velocity profile parameters for a feed hold in-progress. This profile overrides + // the planner block profile, enforcing a deceleration to zero speed. + prep.ramp_type = RAMP_DECEL; + // Compute decelerate distance relative to end of block. + float decel_dist = pl_block->millimeters - inv_2_accel*pl_block->entry_speed_sqr; + if (decel_dist < 0.0) { + // Deceleration through entire planner block. End of feed hold is not in this block. + prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters); + } else { + prep.mm_complete = decel_dist; // End of feed hold. + prep.exit_speed = 0.0; + } + } else { // [Normal Operation] + // Compute or recompute velocity profile parameters of the prepped planner block. + prep.ramp_type = RAMP_ACCEL; // Initialize as acceleration ramp. + prep.accelerate_until = pl_block->millimeters; + + float exit_speed_sqr; + float nominal_speed; + if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { + prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion. + } else { + exit_speed_sqr = plan_get_exec_block_exit_speed_sqr(); + prep.exit_speed = sqrt(exit_speed_sqr); + } + + nominal_speed = plan_compute_profile_nominal_speed(pl_block); + float nominal_speed_sqr = nominal_speed*nominal_speed; + float intersect_distance = + 0.5*(pl_block->millimeters+inv_2_accel*(pl_block->entry_speed_sqr-exit_speed_sqr)); + + if (pl_block->entry_speed_sqr > nominal_speed_sqr) { // Only occurs during override reductions. + prep.accelerate_until = pl_block->millimeters - inv_2_accel*(pl_block->entry_speed_sqr-nominal_speed_sqr); + if (prep.accelerate_until <= 0.0) { // Deceleration-only. + prep.ramp_type = RAMP_DECEL; + // prep.decelerate_after = pl_block->millimeters; + // prep.maximum_speed = prep.current_speed; + + // Compute override block exit speed since it doesn't match the planner exit speed. + prep.exit_speed = sqrt(pl_block->entry_speed_sqr - 2*pl_block->acceleration*pl_block->millimeters); + prep.recalculate_flag |= PREP_FLAG_DECEL_OVERRIDE; // Flag to load next block as deceleration override. + + // TODO: Determine correct handling of parameters in deceleration-only. + // Can be tricky since entry speed will be current speed, as in feed holds. + // Also, look into near-zero speed handling issues with this. + + } else { + // Decelerate to cruise or cruise-decelerate types. Guaranteed to intersect updated plan. + prep.decelerate_after = inv_2_accel*(nominal_speed_sqr-exit_speed_sqr); // Should always be >= 0.0 due to planner reinit. + prep.maximum_speed = nominal_speed; + prep.ramp_type = RAMP_DECEL_OVERRIDE; + } + } else if (intersect_distance > 0.0) { + if (intersect_distance < pl_block->millimeters) { // Either trapezoid or triangle types + // NOTE: For acceleration-cruise and cruise-only types, following calculation will be 0.0. + prep.decelerate_after = inv_2_accel*(nominal_speed_sqr-exit_speed_sqr); + if (prep.decelerate_after < intersect_distance) { // Trapezoid type + prep.maximum_speed = nominal_speed; + if (pl_block->entry_speed_sqr == nominal_speed_sqr) { + // Cruise-deceleration or cruise-only type. + prep.ramp_type = RAMP_CRUISE; + } else { + // Full-trapezoid or acceleration-cruise types + prep.accelerate_until -= inv_2_accel*(nominal_speed_sqr-pl_block->entry_speed_sqr); + } + } else { // Triangle type + prep.accelerate_until = intersect_distance; + prep.decelerate_after = intersect_distance; + prep.maximum_speed = sqrt(2.0*pl_block->acceleration*intersect_distance+exit_speed_sqr); + } + } else { // Deceleration-only type + prep.ramp_type = RAMP_DECEL; + // prep.decelerate_after = pl_block->millimeters; + // prep.maximum_speed = prep.current_speed; + } + } else { // Acceleration-only type + prep.accelerate_until = 0.0; + // prep.decelerate_after = 0.0; + prep.maximum_speed = prep.exit_speed; + } + } + + #ifdef VARIABLE_SPINDLE + bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); // Force update whenever updating block. + #endif + } + + // Initialize new segment + segment_t *prep_segment = &segment_buffer[segment_buffer_head]; + + // Set new segment to point to the current segment data block. + prep_segment->st_block_index = prep.st_block_index; + + /*------------------------------------------------------------------------------------ + Compute the average velocity of this new segment by determining the total distance + traveled over the segment time DT_SEGMENT. The following code first attempts to create + a full segment based on the current ramp conditions. If the segment time is incomplete + when terminating at a ramp state change, the code will continue to loop through the + progressing ramp states to fill the remaining segment execution time. However, if + an incomplete segment terminates at the end of the velocity profile, the segment is + considered completed despite having a truncated execution time less than DT_SEGMENT. + The velocity profile is always assumed to progress through the ramp sequence: + acceleration ramp, cruising state, and deceleration ramp. Each ramp's travel distance + may range from zero to the length of the block. Velocity profiles can end either at + the end of planner block (typical) or mid-block at the end of a forced deceleration, + such as from a feed hold. + */ + float dt_max = DT_SEGMENT; // Maximum segment time + float dt = 0.0; // Initialize segment time + float time_var = dt_max; // Time worker variable + float mm_var; // mm-Distance worker variable + float speed_var; // Speed worker variable + float mm_remaining = pl_block->millimeters; // New segment distance from end of block. + float minimum_mm = mm_remaining-prep.req_mm_increment; // Guarantee at least one step. + if (minimum_mm < 0.0) { minimum_mm = 0.0; } + + do { + switch (prep.ramp_type) { + case RAMP_DECEL_OVERRIDE: + speed_var = pl_block->acceleration*time_var; + if (prep.current_speed-prep.maximum_speed <= speed_var) { + // Cruise or cruise-deceleration types only for deceleration override. + mm_remaining = prep.accelerate_until; + time_var = 2.0*(pl_block->millimeters-mm_remaining)/(prep.current_speed+prep.maximum_speed); + prep.ramp_type = RAMP_CRUISE; + prep.current_speed = prep.maximum_speed; + } else { // Mid-deceleration override ramp. + mm_remaining -= time_var*(prep.current_speed - 0.5*speed_var); + prep.current_speed -= speed_var; + } + break; + case RAMP_ACCEL: + // NOTE: Acceleration ramp only computes during first do-while loop. + speed_var = pl_block->acceleration*time_var; + mm_remaining -= time_var*(prep.current_speed + 0.5*speed_var); + if (mm_remaining < prep.accelerate_until) { // End of acceleration ramp. + // Acceleration-cruise, acceleration-deceleration ramp junction, or end of block. + mm_remaining = prep.accelerate_until; // NOTE: 0.0 at EOB + time_var = 2.0*(pl_block->millimeters-mm_remaining)/(prep.current_speed+prep.maximum_speed); + if (mm_remaining == prep.decelerate_after) { prep.ramp_type = RAMP_DECEL; } + else { prep.ramp_type = RAMP_CRUISE; } + prep.current_speed = prep.maximum_speed; + } else { // Acceleration only. + prep.current_speed += speed_var; + } + break; + case RAMP_CRUISE: + // NOTE: mm_var used to retain the last mm_remaining for incomplete segment time_var calculations. + // NOTE: If maximum_speed*time_var value is too low, round-off can cause mm_var to not change. To + // prevent this, simply enforce a minimum speed threshold in the planner. + mm_var = mm_remaining - prep.maximum_speed*time_var; + if (mm_var < prep.decelerate_after) { // End of cruise. + // Cruise-deceleration junction or end of block. + time_var = (mm_remaining - prep.decelerate_after)/prep.maximum_speed; + mm_remaining = prep.decelerate_after; // NOTE: 0.0 at EOB + prep.ramp_type = RAMP_DECEL; + } else { // Cruising only. + mm_remaining = mm_var; + } + break; + default: // case RAMP_DECEL: + // NOTE: mm_var used as a misc worker variable to prevent errors when near zero speed. + speed_var = pl_block->acceleration*time_var; // Used as delta speed (mm/min) + if (prep.current_speed > speed_var) { // Check if at or below zero speed. + // Compute distance from end of segment to end of block. + mm_var = mm_remaining - time_var*(prep.current_speed - 0.5*speed_var); // (mm) + if (mm_var > prep.mm_complete) { // Typical case. In deceleration ramp. + mm_remaining = mm_var; + prep.current_speed -= speed_var; + break; // Segment complete. Exit switch-case statement. Continue do-while loop. + } + } + // Otherwise, at end of block or end of forced-deceleration. + time_var = 2.0*(mm_remaining-prep.mm_complete)/(prep.current_speed+prep.exit_speed); + mm_remaining = prep.mm_complete; + prep.current_speed = prep.exit_speed; + } + dt += time_var; // Add computed ramp time to total segment time. + if (dt < dt_max) { time_var = dt_max - dt; } // **Incomplete** At ramp junction. + else { + if (mm_remaining > minimum_mm) { // Check for very slow segments with zero steps. + // Increase segment time to ensure at least one step in segment. Override and loop + // through distance calculations until minimum_mm or mm_complete. + dt_max += DT_SEGMENT; + time_var = dt_max - dt; + } else { + break; // **Complete** Exit loop. Segment execution time maxed. + } + } + } while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete. + + #ifdef VARIABLE_SPINDLE + /* ----------------------------------------------------------------------------------- + Compute spindle speed PWM output for step segment + */ + + if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) { + if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) { + float rpm = pl_block->spindle_speed; + // NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate. + if (st_prep_block->is_pwm_rate_adjusted) { rpm *= (prep.current_speed * prep.inv_rate); } + // If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE) + // but this would be instantaneous only and during a motion. May not matter at all. + prep.current_spindle_pwm = spindle_compute_pwm_value(rpm); + } else { + sys.spindle_speed = 0.0; + prep.current_spindle_pwm = SPINDLE_PWM_OFF_VALUE; + } + bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM); + } + prep_segment->spindle_pwm = prep.current_spindle_pwm; // Reload segment PWM value + + #endif + + /* ----------------------------------------------------------------------------------- + Compute segment step rate, steps to execute, and apply necessary rate corrections. + NOTE: Steps are computed by direct scalar conversion of the millimeter distance + remaining in the block, rather than incrementally tallying the steps executed per + segment. This helps in removing floating point round-off issues of several additions. + However, since floats have only 7.2 significant digits, long moves with extremely + high step counts can exceed the precision of floats, which can lead to lost steps. + Fortunately, this scenario is highly unlikely and unrealistic in CNC machines + supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm). + */ + float step_dist_remaining = prep.step_per_mm*mm_remaining; // Convert mm_remaining to steps + float n_steps_remaining = ceil(step_dist_remaining); // Round-up current steps remaining + float last_n_steps_remaining = ceil(prep.steps_remaining); // Round-up last steps remaining + prep_segment->n_step = last_n_steps_remaining-n_steps_remaining; // Compute number of steps to execute. + + // Bail if we are at the end of a feed hold and don't have a step to execute. + if (prep_segment->n_step == 0) { + if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { + // Less than one step to decelerate to zero speed, but already very close. AMASS + // requires full steps to execute. So, just bail. + bit_true(sys.step_control,STEP_CONTROL_END_MOTION); + #ifdef PARKING_ENABLE + if (!(prep.recalculate_flag & PREP_FLAG_PARKING)) { prep.recalculate_flag |= PREP_FLAG_HOLD_PARTIAL_BLOCK; } + #endif + return; // Segment not generated, but current step data still retained. + } + } + + // Compute segment step rate. Since steps are integers and mm distances traveled are not, + // the end of every segment can have a partial step of varying magnitudes that are not + // executed, because the stepper ISR requires whole steps due to the AMASS algorithm. To + // compensate, we track the time to execute the previous segment's partial step and simply + // apply it with the partial step distance to the current segment, so that it minutely + // adjusts the whole segment rate to keep step output exact. These rate adjustments are + // typically very small and do not adversely effect performance, but ensures that Grbl + // outputs the exact acceleration and velocity profiles as computed by the planner. + dt += prep.dt_remainder; // Apply previous segment partial step execute time + float inv_rate = dt/(last_n_steps_remaining - step_dist_remaining); // Compute adjusted step rate inverse + + // Compute CPU cycles per step for the prepped segment. + uint32_t cycles = ceil( (TICKS_PER_MICROSECOND*1000000*60)*inv_rate ); // (cycles/step) + + #ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING + // Compute step timing and multi-axis smoothing level. + // NOTE: AMASS overdrives the timer with each level, so only one prescalar is required. + if (cycles < AMASS_LEVEL1) { prep_segment->amass_level = 0; } + else { + if (cycles < AMASS_LEVEL2) { prep_segment->amass_level = 1; } + else if (cycles < AMASS_LEVEL3) { prep_segment->amass_level = 2; } + else { prep_segment->amass_level = 3; } + cycles >>= prep_segment->amass_level; + prep_segment->n_step <<= prep_segment->amass_level; + } + if (cycles < (1UL << 16)) { prep_segment->cycles_per_tick = cycles; } // < 65536 (4.1ms @ 16MHz) + else { prep_segment->cycles_per_tick = 0xffff; } // Just set the slowest speed possible. + #else + // Compute step timing and timer prescalar for normal step generation. + if (cycles < (1UL << 16)) { // < 65536 (4.1ms @ 16MHz) + prep_segment->prescaler = 1; // prescaler: 0 + prep_segment->cycles_per_tick = cycles; + } else if (cycles < (1UL << 19)) { // < 524288 (32.8ms@16MHz) + prep_segment->prescaler = 2; // prescaler: 8 + prep_segment->cycles_per_tick = cycles >> 3; + } else { + prep_segment->prescaler = 3; // prescaler: 64 + if (cycles < (1UL << 22)) { // < 4194304 (262ms@16MHz) + prep_segment->cycles_per_tick = cycles >> 6; + } else { // Just set the slowest speed possible. (Around 4 step/sec.) + prep_segment->cycles_per_tick = 0xffff; + } + } + #endif + + // Segment complete! Increment segment buffer indices, so stepper ISR can immediately execute it. + segment_buffer_head = segment_next_head; + if ( ++segment_next_head == SEGMENT_BUFFER_SIZE ) { segment_next_head = 0; } + + // Update the appropriate planner and segment data. + pl_block->millimeters = mm_remaining; + prep.steps_remaining = n_steps_remaining; + prep.dt_remainder = (n_steps_remaining - step_dist_remaining)*inv_rate; + + // Check for exit conditions and flag to load next planner block. + if (mm_remaining == prep.mm_complete) { + // End of planner block or forced-termination. No more distance to be executed. + if (mm_remaining > 0.0) { // At end of forced-termination. + // Reset prep parameters for resuming and then bail. Allow the stepper ISR to complete + // the segment queue, where realtime protocol will set new state upon receiving the + // cycle stop flag from the ISR. Prep_segment is blocked until then. + bit_true(sys.step_control,STEP_CONTROL_END_MOTION); + #ifdef PARKING_ENABLE + if (!(prep.recalculate_flag & PREP_FLAG_PARKING)) { prep.recalculate_flag |= PREP_FLAG_HOLD_PARTIAL_BLOCK; } + #endif + return; // Bail! + } else { // End of planner block + // The planner block is complete. All steps are set to be executed in the segment buffer. + if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) { + bit_true(sys.step_control,STEP_CONTROL_END_MOTION); + return; + } + pl_block = NULL; // Set pointer to indicate check and load next planner block. + plan_discard_current_block(); + } + } + + } +} + + +// Called by realtime status reporting to fetch the current speed being executed. This value +// however is not exactly the current speed, but the speed computed in the last step segment +// in the segment buffer. It will always be behind by up to the number of segment blocks (-1) +// divided by the ACCELERATION TICKS PER SECOND in seconds. +float st_get_realtime_rate() +{ + if (sys.state & (STATE_CYCLE | STATE_HOMING | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)){ + return prep.current_speed; + } + return 0.0f; +} diff --git a/grbl/stepper.h b/grbl/stepper.h new file mode 100644 index 0000000..41871a6 --- /dev/null +++ b/grbl/stepper.h @@ -0,0 +1,59 @@ +/* + stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors + Part of Grbl + + Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef stepper_h +#define stepper_h + +#ifndef SEGMENT_BUFFER_SIZE + #define SEGMENT_BUFFER_SIZE 6 +#endif + +// Initialize and setup the stepper motor subsystem +void stepper_init(); + +// Enable steppers, but cycle does not start unless called by motion control or realtime command. +void st_wake_up(); + +// Immediately disables steppers +void st_go_idle(); + +// Generate the step and direction port invert masks. +void st_generate_step_dir_invert_masks(); + +// Reset the stepper subsystem variables +void st_reset(); + +// Changes the run state of the step segment buffer to execute the special parking motion. +void st_parking_setup_buffer(); + +// Restores the step segment buffer to the normal run state after a parking motion. +void st_parking_restore_buffer(); + +// Reloads step segment buffer. Called continuously by realtime execution system. +void st_prep_buffer(); + +// Called by planner_recalculate() when the executing block is updated by the new plan. +void st_update_plan_block_parameters(); + +// Called by realtime status reporting if realtime rate reporting is enabled in config.h. +float st_get_realtime_rate(); + +#endif diff --git a/grbl/system.c b/grbl/system.c new file mode 100644 index 0000000..55e6c40 --- /dev/null +++ b/grbl/system.c @@ -0,0 +1,410 @@ +/* + system.c - Handles system level commands and real-time processes + Part of Grbl + + Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include "grbl.h" + + +void system_init() +{ + CONTROL_DDR &= ~(CONTROL_MASK); // Configure as input pins + #ifdef DISABLE_CONTROL_PIN_PULL_UP + CONTROL_PORT &= ~(CONTROL_MASK); // Normal low operation. Requires external pull-down. + #else + CONTROL_PORT |= CONTROL_MASK; // Enable internal pull-up resistors. Normal high operation. + #endif + CONTROL_PCMSK |= CONTROL_MASK; // Enable specific pins of the Pin Change Interrupt + PCICR |= (1 << CONTROL_INT); // Enable Pin Change Interrupt +} + + +// Returns control pin state as a uint8 bitfield. Each bit indicates the input pin state, where +// triggered is 1 and not triggered is 0. Invert mask is applied. Bitfield organization is +// defined by the CONTROL_PIN_INDEX in the header file. +uint8_t system_control_get_state() +{ + uint8_t control_state = 0; + uint8_t pin = (CONTROL_PIN & CONTROL_MASK) ^ CONTROL_MASK; + #ifdef INVERT_CONTROL_PIN_MASK + pin ^= INVERT_CONTROL_PIN_MASK; + #endif + if (pin) { + #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN + if (bit_istrue(pin,(1< 255)) { return(STATUS_INVALID_STATEMENT); } + return(settings_store_global_setting((uint8_t)parameter, value)); + } + } + } + return(STATUS_OK); // If '$' command makes it to here, then everything's ok. +} + + + +void system_flag_wco_change() +{ + #ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE + protocol_buffer_synchronize(); + #endif + sys.report_wco_counter = 0; +} + + +// Returns machine position of axis 'idx'. Must be sent a 'step' array. +// NOTE: If motor steps and machine position are not in the same coordinate frame, this function +// serves as a central place to compute the transformation. +float system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx) +{ + float pos; + #ifdef COREXY + if (idx==X_AXIS) { + pos = (float)system_convert_corexy_to_x_axis_steps(steps) / settings.steps_per_mm[idx]; + } else if (idx==Y_AXIS) { + pos = (float)system_convert_corexy_to_y_axis_steps(steps) / settings.steps_per_mm[idx]; + } else { + pos = steps[idx]/settings.steps_per_mm[idx]; + } + #else + pos = steps[idx]/settings.steps_per_mm[idx]; + #endif + return(pos); +} + + +void system_convert_array_steps_to_mpos(float *position, int32_t *steps) +{ + uint8_t idx; + for (idx=0; idx -settings.max_travel[idx]) { return(true); } + } else { + if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return(true); } + } + #else + // NOTE: max_travel is stored as negative + if (target[idx] > 0 || target[idx] < settings.max_travel[idx]) { return(true); } + #endif + } + return(false); +} + + +// Special handlers for setting and clearing Grbl's real-time execution flags. +void system_set_exec_state_flag(uint8_t mask) { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_state |= (mask); + SREG = sreg; +} + +void system_clear_exec_state_flag(uint8_t mask) { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_state &= ~(mask); + SREG = sreg; +} + +void system_set_exec_alarm(uint8_t code) { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_alarm = code; + SREG = sreg; +} + +void system_clear_exec_alarm() { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_alarm = 0; + SREG = sreg; +} + +void system_set_exec_motion_override_flag(uint8_t mask) { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_motion_override |= (mask); + SREG = sreg; +} + +void system_set_exec_accessory_override_flag(uint8_t mask) { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_accessory_override |= (mask); + SREG = sreg; +} + +void system_clear_exec_motion_overrides() { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_motion_override = 0; + SREG = sreg; +} + +void system_clear_exec_accessory_overrides() { + uint8_t sreg = SREG; + cli(); + sys_rt_exec_accessory_override = 0; + SREG = sreg; +} diff --git a/grbl/system.h b/grbl/system.h new file mode 100644 index 0000000..cfc9273 --- /dev/null +++ b/grbl/system.h @@ -0,0 +1,212 @@ +/* + system.h - Header for system level commands and real-time processes + Part of Grbl + + Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef system_h +#define system_h + +#include "grbl.h" + +// Define system executor bit map. Used internally by realtime protocol as realtime command flags, +// which notifies the main program to execute the specified realtime command asynchronously. +// NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default +// flags are always false, so the realtime protocol only needs to check for a non-zero value to +// know when there is a realtime command to execute. +#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001 +#define EXEC_CYCLE_START bit(1) // bitmask 00000010 +#define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 +#define EXEC_FEED_HOLD bit(3) // bitmask 00001000 +#define EXEC_RESET bit(4) // bitmask 00010000 +#define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000 +#define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000 +#define EXEC_SLEEP bit(7) // bitmask 10000000 + +// Alarm executor codes. Valid values (1-255). Zero is reserved. +#define EXEC_ALARM_HARD_LIMIT 1 +#define EXEC_ALARM_SOFT_LIMIT 2 +#define EXEC_ALARM_ABORT_CYCLE 3 +#define EXEC_ALARM_PROBE_FAIL_INITIAL 4 +#define EXEC_ALARM_PROBE_FAIL_CONTACT 5 +#define EXEC_ALARM_HOMING_FAIL_RESET 6 +#define EXEC_ALARM_HOMING_FAIL_DOOR 7 +#define EXEC_ALARM_HOMING_FAIL_PULLOFF 8 +#define EXEC_ALARM_HOMING_FAIL_APPROACH 9 +#define EXEC_ALARM_HOMING_FAIL_DUAL_APPROACH 10 + +// Override bit maps. Realtime bitflags to control feed, rapid, spindle, and coolant overrides. +// Spindle/coolant and feed/rapids are separated into two controlling flag variables. +#define EXEC_FEED_OVR_RESET bit(0) +#define EXEC_FEED_OVR_COARSE_PLUS bit(1) +#define EXEC_FEED_OVR_COARSE_MINUS bit(2) +#define EXEC_FEED_OVR_FINE_PLUS bit(3) +#define EXEC_FEED_OVR_FINE_MINUS bit(4) +#define EXEC_RAPID_OVR_RESET bit(5) +#define EXEC_RAPID_OVR_MEDIUM bit(6) +#define EXEC_RAPID_OVR_LOW bit(7) +// #define EXEC_RAPID_OVR_EXTRA_LOW bit(*) // *NOT SUPPORTED* + +#define EXEC_SPINDLE_OVR_RESET bit(0) +#define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1) +#define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2) +#define EXEC_SPINDLE_OVR_FINE_PLUS bit(3) +#define EXEC_SPINDLE_OVR_FINE_MINUS bit(4) +#define EXEC_SPINDLE_OVR_STOP bit(5) +#define EXEC_COOLANT_FLOOD_OVR_TOGGLE bit(6) +#define EXEC_COOLANT_MIST_OVR_TOGGLE bit(7) + +// Define system state bit map. The state variable primarily tracks the individual functions +// of Grbl to manage each without overlapping. It is also used as a messaging flag for +// critical events. +#define STATE_IDLE 0 // Must be zero. No flags. +#define STATE_ALARM bit(0) // In alarm state. Locks out all g-code processes. Allows settings access. +#define STATE_CHECK_MODE bit(1) // G-code check mode. Locks out planner and motion only. +#define STATE_HOMING bit(2) // Performing homing cycle +#define STATE_CYCLE bit(3) // Cycle is running or motions are being executed. +#define STATE_HOLD bit(4) // Active feed hold +#define STATE_JOG bit(5) // Jogging mode. +#define STATE_SAFETY_DOOR bit(6) // Safety door is ajar. Feed holds and de-energizes system. +#define STATE_SLEEP bit(7) // Sleep state. + +// Define system suspend flags. Used in various ways to manage suspend states and procedures. +#define SUSPEND_DISABLE 0 // Must be zero. +#define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete. +#define SUSPEND_RESTART_RETRACT bit(1) // Flag to indicate a retract from a restore parking motion. +#define SUSPEND_RETRACT_COMPLETE bit(2) // (Safety door only) Indicates retraction and de-energizing is complete. +#define SUSPEND_INITIATE_RESTORE bit(3) // (Safety door only) Flag to initiate resume procedures from a cycle start. +#define SUSPEND_RESTORE_COMPLETE bit(4) // (Safety door only) Indicates ready to resume normal operation. +#define SUSPEND_SAFETY_DOOR_AJAR bit(5) // Tracks safety door state for resuming. +#define SUSPEND_MOTION_CANCEL bit(6) // Indicates a canceled resume motion. Currently used by probing routine. +#define SUSPEND_JOG_CANCEL bit(7) // Indicates a jog cancel in process and to reset buffers when complete. + +// Define step segment generator state flags. +#define STEP_CONTROL_NORMAL_OP 0 // Must be zero. +#define STEP_CONTROL_END_MOTION bit(0) +#define STEP_CONTROL_EXECUTE_HOLD bit(1) +#define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2) +#define STEP_CONTROL_UPDATE_SPINDLE_PWM bit(3) + +// Define control pin index for Grbl internal use. Pin maps may change, but these values don't. +#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN + #define N_CONTROL_PIN 4 + #define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0) + #define CONTROL_PIN_INDEX_RESET bit(1) + #define CONTROL_PIN_INDEX_FEED_HOLD bit(2) + #define CONTROL_PIN_INDEX_CYCLE_START bit(3) +#else + #define N_CONTROL_PIN 3 + #define CONTROL_PIN_INDEX_RESET bit(0) + #define CONTROL_PIN_INDEX_FEED_HOLD bit(1) + #define CONTROL_PIN_INDEX_CYCLE_START bit(2) +#endif + +// Define spindle stop override control states. +#define SPINDLE_STOP_OVR_DISABLED 0 // Must be zero. +#define SPINDLE_STOP_OVR_ENABLED bit(0) +#define SPINDLE_STOP_OVR_INITIATE bit(1) +#define SPINDLE_STOP_OVR_RESTORE bit(2) +#define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3) + + +// Define global system variables +typedef struct { + uint8_t state; // Tracks the current system state of Grbl. + uint8_t abort; // System abort flag. Forces exit back to main loop for reset. + uint8_t suspend; // System suspend bitflag variable that manages holds, cancels, and safety door. + uint8_t soft_limit; // Tracks soft limit errors for the state machine. (boolean) + uint8_t step_control; // Governs the step segment generator depending on system state. + uint8_t probe_succeeded; // Tracks if last probing cycle was successful. + uint8_t homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR. + #ifdef ENABLE_DUAL_AXIS + uint8_t homing_axis_lock_dual; + #endif + uint8_t f_override; // Feed rate override value in percent + uint8_t r_override; // Rapids override value in percent + uint8_t spindle_speed_ovr; // Spindle speed value in percent + uint8_t spindle_stop_ovr; // Tracks spindle stop override states + uint8_t report_ovr_counter; // Tracks when to add override data to status reports. + uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports. + #ifdef ENABLE_PARKING_OVERRIDE_CONTROL + uint8_t override_ctrl; // Tracks override control states. + #endif + #ifdef VARIABLE_SPINDLE + float spindle_speed; + #endif +} system_t; +extern system_t sys; + +// NOTE: These position variables may need to be declared as volatiles, if problems arise. +extern int32_t sys_position[N_AXIS]; // Real-time machine (aka home) position vector in steps. +extern int32_t sys_probe_position[N_AXIS]; // Last probe position in machine coordinates and steps. + +extern volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR. +extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks. +extern volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms. +extern volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides. +extern volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. + +#ifdef DEBUG + #define EXEC_DEBUG_REPORT bit(0) + extern volatile uint8_t sys_rt_exec_debug; +#endif + +// Initialize the serial protocol +void system_init(); + +// Returns bitfield of control pin states, organized by CONTROL_PIN_INDEX. (1=triggered, 0=not triggered). +uint8_t system_control_get_state(); + +// Returns if safety door is open or closed, based on pin state. +uint8_t system_check_safety_door_ajar(); + +// Executes an internal system command, defined as a string starting with a '$' +uint8_t system_execute_line(char *line); + +// Execute the startup script lines stored in EEPROM upon initialization +void system_execute_startup(char *line); + + +void system_flag_wco_change(); + +// Returns machine position of axis 'idx'. Must be sent a 'step' array. +float system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx); + +// Updates a machine 'position' array based on the 'step' array sent. +void system_convert_array_steps_to_mpos(float *position, int32_t *steps); + +// CoreXY calculation only. Returns x or y-axis "steps" based on CoreXY motor steps. +#ifdef COREXY + int32_t system_convert_corexy_to_x_axis_steps(int32_t *steps); + int32_t system_convert_corexy_to_y_axis_steps(int32_t *steps); +#endif + +// Checks and reports if target array exceeds machine travel limits. +uint8_t system_check_travel_limits(float *target); + +// Special handlers for setting and clearing Grbl's real-time execution flags. +void system_set_exec_state_flag(uint8_t mask); +void system_clear_exec_state_flag(uint8_t mask); +void system_set_exec_alarm(uint8_t code); +void system_clear_exec_alarm(); +void system_set_exec_motion_override_flag(uint8_t mask); +void system_set_exec_accessory_override_flag(uint8_t mask); +void system_clear_exec_motion_overrides(); +void system_clear_exec_accessory_overrides(); + + +#endif